⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tabbar.c

📁 multi-tabed terminal based on rxvt
💻 C
📖 第 1 页 / 共 5 页
字号:
	register int	curimg = NB_XPM - i;	switch (curimg)	{	    case XPM_TERM:		img[XPM_TERM] = (LTAB(r) == MAX_PAGES - 1) ? 		    img_d[XPM_TERM] : img_e[XPM_TERM];		break;	    case XPM_CLOSE:		img[XPM_CLOSE] = (ISSET_OPTION(r, Opt2_protectSecondary) &&				PRIMARY != AVTS(r)->current_screen) ?			img_d[XPM_CLOSE] : img_e[XPM_CLOSE];		break;	    case XPM_LEFT:		img[XPM_LEFT] = (FVTAB(r) == 0) ? 		    img_d[XPM_LEFT] : img_e[XPM_LEFT];		break;	    case XPM_RIGHT:		img[XPM_RIGHT] = (LVTAB(r) == LTAB(r)) ? 		    img_d[XPM_RIGHT] : img_e[XPM_RIGHT];		break;	}#endif	if (IS_PIXMAP(img[NB_XPM-i]))	{	    XCopyArea  (r->Xdisplay, img[NB_XPM-i], r->tabBar.win,		r->tabBar.gc, 0, 0,		BTN_WIDTH, BTN_HEIGHT,		TWIN_WIDTH(r)-(i*(BTN_WIDTH+BTN_SPACE)), topoff);	}    }    CHOOSE_GC_FG (r, r->tabBar.frame);    for (i = NB_XPM; i >= 1; i--)    {	/*	XDrawRectangle (r->Xdisplay, r->tabBar.win,	    r->tabBar.gc,	    TWIN_WIDTH(r)-(i*(BTN_WIDTH+BTN_SPACE)), topoff,	    BTN_WIDTH, BTN_HEIGHT);	*/	int	sx = TWIN_WIDTH(r) - (i*(BTN_WIDTH+BTN_SPACE));	/* draw top line */	XDrawLine (r->Xdisplay, r->tabBar.win, r->tabBar.gc,	    sx, topoff, sx + BTN_WIDTH, topoff);	/* draw left line */	XDrawLine (r->Xdisplay, r->tabBar.win, r->tabBar.gc,	    sx, topoff, sx, topoff + BTN_HEIGHT);    }    CHOOSE_GC_FG (r, r->tabBar.delimit);    for (i = NB_XPM; i >= 1; i--)    {	int	sx = TWIN_WIDTH(r) - (i*(BTN_WIDTH+BTN_SPACE));	/* draw bottom line */	XDrawLine (r->Xdisplay, r->tabBar.win, r->tabBar.gc,	    sx, topoff+BTN_HEIGHT, sx+BTN_WIDTH, topoff+BTN_HEIGHT);	/* draw right line */	XDrawLine (r->Xdisplay, r->tabBar.win, r->tabBar.gc,	    sx+BTN_WIDTH, topoff, sx+BTN_WIDTH, topoff+BTN_HEIGHT);    }}/* * Initialize global data structure of all tabs *//* INTPROTO */static voidinit_tabbar (rxvt_t* r){    r->tabBar.state = 0;    /* not mapped yet */    LTAB(r) = -1;   /* the last tab */    r->tabBar.atab = 0;	/* the active tab */    FVTAB(r) = 0;   /* first visiable tab */    LVTAB(r) = 0;   /* last visiable tab */    r->tabBar.ptab = 0;	    /* previous active tab */    /* Make sure that font has been initialized */#ifdef XFT_SUPPORT    if (ISSET_OPTION (r, Opt_xft))	assert (NULL != r->TermWin.xftfont);    else#endif    assert (NULL != r->TermWin.font);    assert (r->TermWin.FHEIGHT > 0);    /* resource string are static, needn't to free */    r->tabBar.rsfg =    r->tabBar.rsbg =    r->tabBar.rsifg =    r->tabBar.rsibg = 0;}/* INTPROTO */voidrxvt_kill_page (rxvt_t* r, short page){    kill (PVTS(r, page)->cmd_pid, SIGHUP);}/* * Reduce r->num_fds so that select() is more efficient *//* EXTPROTO */voidrxvt_adjust_fd_number( rxvt_t* r ){    int	    num_fds = STDERR_FILENO;    int	    i;    for( i=0; i <= LTAB(r); i++ )	MAX_IT( num_fds, PVTS(r, i)->cmd_fd );    rxvt_dbgmsg ((DBG_DEBUG, DBG_TABBAR, "LTAB=%d, stderr_fd=%d, num_fds=%d. ", LTAB(r), STDERR_FILENO, num_fds));    MAX_IT( num_fds, r->Xfd );#ifdef USE_FIFO    MAX_IT( num_fds, r->fifo_fd );#endif/*USE_FIFO*/#ifdef HAVE_X11_SM_SMLIB_H    MAX_IT( num_fds, r->TermWin.ice_fd );#endif#if 0    MAX_IT( num_fds, r->num_fds-1 );#endif#ifdef OS_IRIX    /* Alex Coventry says we need 4 & 7 too */    MAX_IT( num_fds, 7 );#endif    r->num_fds = num_fds + 1;	/* counts from 0 */    rxvt_dbgmsg ((DBG_VERBOSE, DBG_TABBAR, "Adjust num_fds to %d\n", r->num_fds));}/* * Append a new tab after the last tab. If command is not NULL, run that * command in the tab. If command begins with '!', then run the shell first. *//* EXTPROTO */voidrxvt_append_page( rxvt_t* r, int profile,	const char TAINTED *title, const char *command ){    int	    num_cmd_args = 0; /* Number of args we got from parsing command */    char**  argv;    rxvt_dbgmsg ((DBG_DEBUG, DBG_TABBAR, "rxvt_append_page( r, %d, %s, %s )\n", profile, title ? title : "(nil)", command ? command : "(nil)" ));    /* Sanitization */    assert( LTAB(r) < MAX_PAGES );    if (LTAB(r) == MAX_PAGES-1)    {	rxvt_msg (DBG_ERROR, DBG_TABBAR,  "Too many tabs" );	return ;    }    if( profile < 0 || profile >= MAX_PROFILES )    {	rxvt_msg (DBG_WARN, DBG_TABBAR,  "Warning: Profile %d out of range", profile );	profile = 0;    }    /* indicate that we add a new tab */    LTAB(r)++;    rxvt_dbgmsg ((DBG_VERBOSE, DBG_TABBAR, "last page is %d\n", LTAB(r)));    /*     * Use command specified with -e only if we're opening the first tab, or the     * --cmdAllTabs option is specified, and we're not given a command to     *  execute (e.g. via the NewTab cmd macro).     */    if(	 cmd_argv	    /* Argument specified via -e option */	 && command == NULL /* No command specified (e.g. via NewTab macro) */	 && (	       LTAB(r)== 0			    /* First tab */	       || ISSET_OPTION(r, Opt2_cmdAllTabs)  /* -at option */	    )      )	argv = cmd_argv;    else    {	/* load tab command if necessary*/	if( command == NULL )	    command = getProfileOption( r, profile, Rs_command );	if( command != NULL && *command != '!' )	{	    const char *cmd = command;	    /* If "command" starts with '!', we should run it in the shell. */	    if( cmd[0] == '\\' && cmd[1] == '!' )		cmd++;	    argv = rxvt_string_to_argv( cmd, &num_cmd_args );	}	else	    argv = NULL;    }    rxvt_dbgmsg ((DBG_DEBUG, DBG_TABBAR, "Forking command=%s, argv[0]=%s\n", command ? command : "(nil)", ( argv && argv[0] ) ? argv[0] : "(nil)" ));    /*     * Set the tab title.     */    if( title == NULL || *title == '\0' )    {	title = getProfileOption( r, profile, Rs_tabtitle );	if( title == NULL || *title == '\0' )	{	    if( command && *command != '\0' )		title = command;	    else if( argv && argv[0] && *argv[0] != '\0' )		title = argv[0];	}    }    rxvt_create_termwin( r, LTAB(r), profile, title );    /*     * Run the child process.     *     * 2006-02-17 gi1242: Bug -- If the child produces some output and exits     * quickly, then some of that output is sometimes lost.     */    if( getProfileOption( r, profile, Rs_cwd ) != NULL )    {	const char  *cwdOption	= getProfileOption( r, profile, Rs_cwd );	char	    cwd[PATH_MAX] = "",		    child_cwd[PATH_MAX] = "";	int	    len = 0;	getcwd (cwd, PATH_MAX);	if( !STRCMP( cwdOption, "." ) )	{	    if( ATAB(r) != LTAB(r) )	    {		/*		 * Copy working directory of the current tab into child_cwd.		 */		char	proc_cwd[32];		/* 16 is enough */		sprintf( proc_cwd, "/proc/%d/cwd", AVTS(r)->cmd_pid );		if( (len = readlink( proc_cwd, child_cwd, PATH_MAX-1) ) > 0 )		    /* readlink does not null terminate */		    child_cwd[len] = 0;	    }	}		else	{#ifdef HAVE_WORDEXP_H	    wordexp_t p;	    int wordexp_result = wordexp(cwdOption, &p, 0);	    char *filename;	    if( wordexp_result == 0 )	    {		if( p.we_wordc > 1)		    rxvt_msg( DBG_ERROR, DBG_TABBAR,			    "Too many words when expanding %s\n", cwdOption );		else		{		    filename = *p.we_wordv;		    len  = STRLEN( filename );		    MIN_IT( len, PATH_MAX - 1 );		    STRNCPY( child_cwd, filename, len );		    child_cwd[len] = 0;		}		wordfree( &p );	    }	    else	    {		rxvt_dbgmsg(( DBG_VERBOSE, DBG_TABBAR,			    "wordexp error code '%i', expanding '%s'\n",			    wordexp_result, filename ));	    }#endif /* HAVE_WORDEXP_H */	}	if( len > 0 && chdir( child_cwd ) == 0 )	{	    /* Now in working directory of ATAB */	    rxvt_dbgmsg ((DBG_DEBUG, DBG_TABBAR,			"Running child in directory: %s\n", child_cwd ));	    /* Run command in this new directory. */	    LVTS(r)->cmd_fd =		rxvt_run_command( r, LTAB(r), (const char**) argv );	    /* Restore old working directory. */	    chdir( cwd );	}	else	{	    /* Exec command in original directory. */	    rxvt_dbgmsg(( DBG_DEBUG, DBG_TABBAR,			"Running child in original directory\n"));	    LVTS(r)->cmd_fd =		rxvt_run_command( r, LTAB(r), (const char**) argv );	}    }    else	LVTS(r)->cmd_fd = rxvt_run_command (r, LTAB(r), (const char**) argv);    /*     * In case we allocated memory for argv using rxvt_string_to_argv (because a     * command was specified), then free it.     */    if( num_cmd_args > 0)    {	char **s;	for( s = argv; *s != NULL; s++) rxvt_free(*s);	rxvt_free( argv );    }    /*     * If run command failed, rollback     */    assert( -1 != LVTS(r)->cmd_fd );    if (-1 == LVTS(r)->cmd_fd)    {	rxvt_destroy_termwin (r, LTAB(r));	LTAB(r) --;	return;    }    rxvt_dbgmsg ((DBG_DEBUG, DBG_TABBAR,"page %d's cmd_fd is %d\n", LTAB(r), LVTS(r)->cmd_fd));    /* adjust number of file descriptors to listen */    rxvt_adjust_fd_number (r);    /*     * Initialize the screen data structures     */    rxvt_scr_reset (r, LTAB(r));    rxvt_scr_refresh (r, LTAB(r), FAST_REFRESH);    /*     * Now we actually execute the command after executing shell, but we need     * careful check first.     */    if( command != NULL && *command == '!' )    {	command++;  /* Skip leading '!' */	rxvt_tt_write( r, LTAB(r), (const unsigned char*) command,		STRLEN(command) );	rxvt_tt_write( r, LTAB(r), (const unsigned char*) "\n", 1 );    }    /*     * Now update active page information     */    PTAB(r) = ATAB(r); /* set last previous tab */    ATAB(r) = LTAB(r); /* set the active tab */    /* update mapped flag */    AVTS(r)->mapped = 1;    /* first tab is special since ptab = atab now */    if (PTAB(r) != ATAB(r))	PVTS(r, r->tabBar.ptab)->mapped = 0;    /* Adjust visible tabs */    rxvt_tabbar_set_visible_tabs (r, True); /* Send expose events to tabbar */    refresh_tabbar_tab( r, PTAB(r));	    /* PTAB will need to be drawn as					       inactive */    /*     * Auto show tabbar if we have exactly two tabs.     */    if(	 !r->tabBar.state && LTAB(r) == 1	 && ISSET_OPTION(r, Opt2_autohideTabbar)	 && rxvt_tabbar_show( r )      )	rxvt_resize_on_subwin( r, SHOW_TABBAR);    /* synchronize terminal title with tab title */    if (ISSET_OPTION(r, Opt2_syncTabTitle))	sync_tab_title( r, ATAB(r) );    /* synchronize icon name to tab title */    if (ISSET_OPTION(r, Opt2_syncTabIcon))	rxvt_set_icon_name (r,		(const unsigned char*) PVTS(r, ATAB(r))->tab_title);}/* * Called by the handler of SIGCHLD; destroy the terminal and its tab *//* EXTPROTO */voidrxvt_remove_page (rxvt_t* r, short page){    register int    i;    rxvt_dbgmsg ((DBG_VERBOSE, DBG_TABBAR,"remove_page(%d)\n", page));    /* clean utmp/wtmp entry */#ifdef UTMP_SUPPORT    rxvt_privileges (RESTORE);    rxvt_cleanutent (r, page);     rxvt_privileges (IGNORE);#endif    /* free virtual terminal related resources */    assert (PVTS(r, page)->ttydev);    rxvt_free (PVTS(r, page)->ttydev);    assert (PVTS(r, page)->cmd_fd >= 0);    close (PVTS(r, page)->cmd_fd);    if (PVTS(r, page)->v_buffer)    {	rxvt_free (PVTS(r, page)->v_buffer);	PVTS(r, page)->v_buffer = NULL;    }    /* free screen structure */    rxvt_scr_release (r, page);    /* destroy the virtual terminal window */    rxvt_destroy_termwin (r, page);    /* update total number of tabs */    LTAB(r)--;    /* quit the last the terminal, exit the application */    if( LTAB(r) < 0 )	rxvt_clean_exit (r);    /* update TermWin and tab_widths */    for (i = page; i <= LTAB(r); i++)    {	PVTS(r, i) = PVTS(r, i+1);	refresh_tabbar_tab( r, i);    }    /* update selection */    if (page == r->selection.vt)	rxvt_process_selectionclear (r, page);    else if (r->selection.vt > page)	r->selection.vt --;    /*     * Now we try to set correct atab, ptab, fvtab, and lvtab     * Must be careful here!!!     */    /* update previous active tab */    if (PTAB(r) > page) PTAB(r)--;    /* in case PTAB is invalid */    if (PTAB(r) > LTAB(r)) PTAB(r) = LTAB(r);    /* update active tab */    if( ATAB(r) == page )    {	/* Fall back to previous active */	ATAB(r) = PTAB(r);	/* Make the previous active tab the previous / next tab if possible. */	if( PTAB(r) > 0 ) PTAB(r)--;	else if (PTAB(r) < LTAB(r) ) PTAB(r)++;    }    else if( ATAB(r) > page) ATAB(r)--;    /* always set mapped flag */    AVTS(r)->mapped = 1;    /* Adjust the number of FD's we select() for.  */    rxvt_adjust_fd_number(r);    /* adjust visible tabs */    rxvt_tabbar_set_visible_tabs (r, True);    refresh_tabbar_tab( r, ATAB(r));	/* Active tab has changed */    /* redraw the tabs and buttons */    if (r->tabBar.state)    {	if( LTAB(r) == 0 && ISSET_OPTION(r, Opt2_autohideTabbar) 		&& rxvt_tabbar_hide( r ))	    /*	     * Only one tab left. Auto hide tabbar.	     */	    rxvt_resize_on_subwin (r, HIDE_TABBAR);    }    /* Switch fg/bg colors */    rxvt_set_vt_colors( r, ATAB(r) );    XMapRaised( r->Xdisplay, AVTS(r)->vt );    /*     * We don't need to touch the screen here. XMapRaised will generate a     * MapNotify and Expose events, which will refresh the screen as needed.     * Touching the screen unnecessarily causes a flicker (and is *horrible*     * under slow connections).     */    /* rxvt_scr_touch (r, ATAB(r), True); */    /* synchronize terminal title with tab title */    if (ISSET_OPTION(r, Opt2_syncTabTitle))	sync_tab_title( r, ATAB(r) );    /* synchronize icon name to tab title */    if (ISSET_OPTION(r, Opt2_syncTabIcon))	rxvt_set_icon_name(r,		(const unsigned char*) PVTS(r, ATAB(r))->tab_title);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -