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

📄 tabbar.c

📁 multi-tabed terminal based on rxvt
💻 C
📖 第 1 页 / 共 5 页
字号:
/*--------------------------------*-C-*---------------------------------* * File:    tabbar.c *----------------------------------------------------------------------* * * All portions of code are copyright by their respective author/s. * Copyright (c) 2002        Alexis <materm@tuxfamily.org> * Copyright (c) 2004        Terry Griffin <griffint@pobox.com> * Copyright (c) 2004        Sergey Popov <p_sergey@jungo.com> * Copyright (c) 2004-2006   Jingmin Zhou <jimmyzhou@users.sourceforge.net> * Copyright (c) 2005        Mark Olesen <Mark.Olesen@gmx.net> * Copyright (c) 2005-2006   Gautam Iyer <gi1242@users.sourceforge.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *----------------------------------------------------------------------*/#include "../config.h"#include "rxvt.h"#ifdef HAVE_WORDEXP_H# include <wordexp.h>#endif#ifdef HAVE_LIBXPM#include "close_term.xpm"#include "term.xpm"#include "right.xpm"#include "left.xpm"#include "close_term_d.xpm"#include "term_d.xpm"#include "right_d.xpm"#include "left_d.xpm"#else#include "close_term.xbm"#include "term.xbm"#include "right.xbm"#include "left.xbm"#endif /* HAVE_LIBXPM */#ifdef XFT_SUPPORT# define    FHEIGHT pheight# define    FWIDTH  pwidth#else# define    FHEIGHT fheight# define    FWIDTH  fwidth#endif/* border between the tabs */#define TAB_BORDER	((int) 1)/* margin around the text of the tab */#define TXT_MARGIN	((int) 3)/* * Parameters to draw top tabbar *//* space between top window border and tab top */#define TAB_TOPOFF	((int) 0)/* Extra height of the active tab. */#define ATAB_EXTRA	((int) (ATAB_EXTRA_PERCENT * r->TermWin.FHEIGHT / 100))/* space between top window border and tab bottom */#define TAB_BOTOFF	((int) (r->TermWin.FHEIGHT + 2*TXT_MARGIN) + ATAB_EXTRA)/* Radius of tab corners */#define TAB_RADIUS	(TAB_RADIUS_PERCENT * TXT_XOFF / 100 )/* X offset of text in tab */#define TXT_XOFF	((int) (r->TermWin.FWIDTH - TAB_BORDER))/* height of text in tab */#define TXT_YOFF	((int) (r->TermWin.FHEIGHT + TXT_MARGIN + TAB_BORDER))/* width of No. idx tab */#define TAB_WIDTH(idx)	((int) (TAB_BORDER + r->vts[idx]->tab_width))/* size of button */#define BTN_WIDTH	((int) 18)#define BTN_HEIGHT	((int) 18)/* space between top window border and button top */#define BTN_TOPOFF	(max (0, ((TAB_BOTOFF - BTN_HEIGHT)/2)))/* space between buttons */#define BTN_SPACE	((int) 5)/* width of tabbar that can be used to draw tabs */#define TAB_SPACE	(TWIN_WIDTH(r)- \    (ISSET_OPTION(r, Opt2_hideButtons) ? 0 : 1) * \    (4 * (BTN_WIDTH+BTN_SPACE) + TAB_BORDER))#define CHOOSE_GC_FG(R, PIXCOL)	\    XSetForeground ((R)->Xdisplay, (R)->tabBar.gc, (PIXCOL))/*******************************************************************************			Begin internal routine prototypes.		      *******************************************************************************//*******************************************************************************			End internal routine prototypes.		      *******************************************************************************/enum {XPM_TERM,XPM_CLOSE,XPM_LEFT,XPM_RIGHT,NB_XPM};#ifdef HAVE_LIBXPMstatic char** xpm_name[] ={    term_xpm,close_term_xpm,    left_xpm,right_xpm};static char** xpm_d_name[] ={    term_d_xpm,close_term_d_xpm,    left_d_xpm,right_d_xpm};#elsestatic unsigned char *xbm_name[] ={    term_bits,close_term_bits,    left_bits,right_bits};#endif    static Pixmap img[NB_XPM];#ifdef HAVE_LIBXPMstatic Pixmap img_e[NB_XPM]; /* enable image */static Pixmap img_emask[NB_XPM]; /* shape mask image */static Pixmap img_d[NB_XPM]; /* disable image */static Pixmap img_dmask[NB_XPM]; /* shape mask image */#endif    extern char **cmd_argv;/* * Width between two tabs: * From the left of the first tab to the right of the second tab *//* INTPROTO */static intwidth_between (rxvt_t* r, int start, int end){    register int    i, w=0;        for (i = start; i <= end; i++)	w += TAB_WIDTH(i);        return w;}/* * Find most left tab within specified distance. Note that the * distance does not include the width of tab[start]. It means * distance = (beginning of tab[start] - 0) *//* INTPROTO */static intfind_left_tab (rxvt_t* r, int start, int distance){    register int    i, left;    /* Sanatization */    if (0 == start)	return 0;    /* BUG: tab overlap with button */    if (distance < 0)	return start;    left = distance;    for (i = start - 1; i >= 0; i --)    {	if (left < TAB_WIDTH(i))	    break;	left -= (TAB_WIDTH(i));    }    return (i + 1);}/* * Find most right tab within specified distance. Note that the * distance does not include the width of tab[start]. It means * distance = (beginning of first button - end of tab[start]) *//* INTPROTO */static intfind_right_tab (rxvt_t* r, int start, int distance){    register int    i, left;    /* Sanatization */    if (LTAB(r) == start)	return start;    /* BUG: tab overlap with button */    if (distance < 0)	return start;    left = distance;    for (i = start + 1; i <= LTAB(r); i ++)    {	if (left < TAB_WIDTH(i))	    break;	left -= (TAB_WIDTH(i));    }    return (i - 1);}/* EXTPROTO *//* * If refresh is true, then the respective parts of the tabbar are redrawn. * NOTE: This function redraws parts of the tabbar soley based on wether the tab * position / width has changed. It does not check to see if the tab titles / * etc has changed. */voidrxvt_tabbar_set_visible_tabs (rxvt_t* r, Bool refresh){    assert( LTAB(r) >= 0 );    /*     * For Firefox style tabs, we should recompute all tabwidths.     */#ifdef XFT_SUPPORT    if( ISSET_OPTION(r, Opt_xft) && r->TermWin.xftpfont )    {	int	i;	short	tabWidth = rxvt_tab_width( r, NULL);	/* Firefox style tabs							   don't need the tab							   title */	int	numVisible = (TAB_SPACE - TAB_BORDER)				/ (TAB_BORDER + tabWidth);	int	oldTabWidth = PVTS(r,0)->tab_width,		oldFVtab    = FVTAB(r),		oldLVtab    = LVTAB(r);	/*	 * Reset the widths of all tabs (visible or not).	 */	for (i = 0; i <= LTAB(r); i ++) PVTS(r, i)->tab_width = tabWidth;	/*	 * Set visible tabs. First make sure the active tab is visible	 */	if( numVisible == 1 )	    FVTAB(r) = LVTAB(r) = ATAB(r);	else	{	    if( ATAB(r) < FVTAB(r) )		/* Make ATAB second last tab that's visible */		FVTAB(r) = max( ATAB(r) - numVisible + 2, 0);	    else if ( ATAB(r) >= FVTAB(r) + numVisible )		/* Make ATAB the second tab that's visible */		FVTAB(r) = max( ATAB(r) - 1, 0);	    /*	     * Active tab is now visible. Try and make as many other tabs	     * visible.	     */	    if( FVTAB(r) + numVisible - 1 > LTAB(r) )	    {		LVTAB(r) = LTAB(r);		FVTAB(r) = max( LVTAB(r) - numVisible + 1, 0);	    }	    else		LVTAB(r) = FVTAB(r) + numVisible - 1;	}	if( refresh && IS_WIN(r->tabBar.win))	{	    /* Clear out the parts of the tabbar that have changed. Expose	     * events will be sent to the tabbar. */	    if( tabWidth != oldTabWidth || FVTAB(r) != oldFVtab )		/* Refresh all tabs */		XClearArea( r->Xdisplay, r->tabBar.win,			0, 0, TAB_SPACE, 0, True);	    else if( oldLVtab != LVTAB(r) )	    {		int x = TAB_BORDER +		    (TAB_BORDER + tabWidth) * min( oldLVtab, LVTAB(r));		XClearArea( r->Xdisplay, r->tabBar.win,			x, 0, TAB_SPACE - x + 1, 0, True);	    }	}    }    else#endif    {	/* set first visible tab to active tab */	FVTAB(r) = ATAB(r);	/* always try visualize the right tabs */	LVTAB(r) = find_right_tab (r, FVTAB(r),	    TAB_SPACE - TAB_WIDTH(FVTAB(r)));	if (LVTAB(r) == LTAB(r) && 0 != FVTAB(r))	{	    /* now try to visualize the left tabs */	    register int size = TAB_SPACE -		width_between (r, FVTAB(r), LVTAB(r));	    FVTAB(r) = find_left_tab (r, FVTAB(r), size);	}	if( refresh && IS_WIN(r->tabBar.win))	    XClearArea( r->Xdisplay, r->tabBar.win, 0, 0, TAB_SPACE, 0, True);    }}/* *  x, y      : starting position of string, no need to adjust y *  str       : string to draw *  len       : byte length of the string, not number of characters! *  multichar : whether the string is multichar string *  active    : active or inactive tab * *  Returns the pixel width of the string drawn. *//* INTPROTO */static intdraw_string (rxvt_t* r, Region clipRegion,	int x, int y, char* str, int len,	__attribute__((unused)) int multichar, int active){#ifdef XFT_SUPPORT    XGlyphInfo	ginfo;#endif#ifdef MULTICHAR_SET    if (multichar)    {	/*	 * Draw the multichar string	 */# ifdef XFT_SUPPORT	if (ISSET_OPTION(r, Opt_xft) && (NULL != r->tabBar.xftwin))	{#  ifdef HAVE_ICONV_H	    if (		    ENC_NOENC != r->encoding_method		    && (iconv_t) -1 != r->TermWin.xfticonv	       )	    {		char		buf[1024];		int		plen = 1023;		char*		pstr = buf;		int		olen = len;		char*		ostr = str;		/* convert to UTF-8 */		iconv (r->TermWin.xfticonv, (char**) &ostr,		    (size_t*) &olen, &pstr, (size_t*) &plen);		*pstr = (char) 0;   /* set end of string */		rxvt_draw_string_xft (r, r->tabBar.win, r->tabBar.gc,			clipRegion, RS_None, 			active ? USE_BOLD_PFONT : USE_PFONT,			r->tabBar.xftwin,			active ? &(r->tabBar.xftfg) : &(r->tabBar.xftifg),			x, y, buf, len, XftDrawStringUtf8);		if( r->TermWin.xftpfont )		{		    XftTextExtentsUtf8( r->Xdisplay, r->TermWin.xftpfont,			    (unsigned char*) buf, pstr - buf, &ginfo);		    return ginfo.width;		}		else return Width2Pixel( pstr - buf );	    }	    else#  endif	    {		rxvt_dbgmsg ((DBG_VERBOSE, DBG_TABBAR, "XFT non-iconv tab title\n"));		rxvt_draw_string_xft (r, r->tabBar.win, r->tabBar.gc,			clipRegion, RS_None,			active ? USE_BOLD_PFONT : USE_PFONT,			r->tabBar.xftwin,			active ? &(r->tabBar.xftfg) : &(r->tabBar.xftifg),			x, y, str, len, XftDrawString8);		if( r->TermWin.xftpfont )		{		    XftTextExtents8( r->Xdisplay, r->TermWin.xftpfont,			    (unsigned char*) str, len, &ginfo);		    return ginfo.width;		}		else return Width2Pixel( len );	    }	}	else# endif	/* XFT_SUPPORT */	{	    if (ENC_NOENC != r->encoding_method)	    {		XSetFont (r->Xdisplay, r->tabBar.gc, r->TermWin.mfont->fid);		r->h->multichar_decode ( (unsigned char*) str, len);		rxvt_draw_string_x11 (r, r->tabBar.win, r->tabBar.gc,			clipRegion, x, y, str, len/2, XDrawString16);	    }	    else	    {		XSetFont (r->Xdisplay, r->tabBar.gc, r->TermWin.font->fid);		rxvt_draw_string_x11 (r, r->tabBar.win, r->tabBar.gc,			clipRegion, x, y, str, len, XDrawString);	    }	    return Width2Pixel( len );	}    } /* if (multichar) */    else#endif /* MULTICHAR_SET */    {	/*	 * Draw the non-multichar string	 */# ifdef XFT_SUPPORT	if (ISSET_OPTION(r, Opt_xft) && (NULL != r->tabBar.xftwin))	{	    rxvt_draw_string_xft (r, r->tabBar.win, r->tabBar.gc,		    clipRegion, RS_None,		    active ? USE_BOLD_PFONT : USE_PFONT,		    r->tabBar.xftwin,		    active ? &(r->tabBar.xftfg) : &(r->tabBar.xftifg),		    x, y, str, len, XftDrawString8);	    if( r->TermWin.xftpfont )	    {		XftTextExtents8( r->Xdisplay, r->TermWin.xftpfont,			(unsigned char*) str, len, &ginfo);		return ginfo.width;	    }	    else return Width2Pixel( len );	}	else# endif	/* XFT_SUPPORT */	{	    XSetFont (r->Xdisplay, r->tabBar.gc, r->TermWin.font->fid);	    rxvt_draw_string_x11 (r, r->tabBar.win, r->tabBar.gc,		    clipRegion, x, y, str, len, XDrawString);	    return Width2Pixel( len );	}    }}/* * Draw tab title string * * If region is non-empty, we assume that the caller has set the GC's clipping * to region, and we honor it. *//* INTPROTO */static voiddraw_title (rxvt_t* r, int x, int y, int tnum, Region region){    Region	clipRegion;    char	str[MAX_DISPLAY_TAB_TXT + 1];#ifdef MULTICHAR_SET    char	buf[MAX_TAB_TXT + 1];    const char*	sptr;    const char*	ptr;    int		multichar;    int		len;#endif    UNSET_REGION( clipRegion );    /*     * Adjust y offset, and make sure output is restricted to the current tab     * title.     */#ifdef XFT_SUPPORT    if (ISSET_OPTION(r, Opt_xft) && (NULL != r->tabBar.xftwin))    {	if( r->TermWin.xftpfont )	{	    /*	     * If we use pfont to draw tab titles, the we dont' know how many	     * characters will fit on the title. So we should clip the output	     * correctly.	     */	    XRectangle rect;	    rect.x = x;	    rect.y = y - r->TermWin.pheight;	    rect.width = PVTS(r, tnum)->tab_width - 2*TXT_XOFF;	    rect.height = r->TermWin.pheight;	    clipRegion = XCreateRegion();	    XUnionRectWithRegion( &rect, clipRegion, clipRegion);	    if (IS_REGION(region))		XIntersectRegion( clipRegion, region, clipRegion);	    XftDrawSetClip( r->tabBar.xftwin, clipRegion);	    y -= r->TermWin.xftpfont->descent;	}	else y -= r->TermWin.xftfont->descent;    }    else#endif /* XFT_SUPPORT */	y -= r->TermWin.font->descent;    /*     * Get the title into str. Under Xft, we use the format specified by

⌨️ 快捷键说明

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