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

📄 menubar.c

📁 multi-tabed terminal based on rxvt
💻 C
📖 第 1 页 / 共 5 页
字号:
/*--------------------------------*-C-*---------------------------------* * File:    menubar.c *----------------------------------------------------------------------* * * All portions of code are copyright by their respective author/s. * Copyright (c) 1997,1998   mj olesen <olesen@me.QueensU.CA> * Copyright (c) 2004        Jingmin Zhou <jimmyzhou@users.sourceforge.net> * Copyright (c) 2005-6      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"#define NEWARGLIM 500#ifdef HAVE_MENUBAR#define CHOOSE_GC_FG(R, PIXCOL)	\    XSetForeground ((R)->Xdisplay, (R)->menuBar.gc, (PIXCOL))#define TRIANGLE_WIDTH	(HEIGHT_TEXT * 3 / 5 - 2 * SHADOW)/*--------------------------------------------------------------------* *         BEGIN `INTERNAL' ROUTINE PROTOTYPES                        * *--------------------------------------------------------------------*/menuitem_t*   rxvt_menuitem_find          (const menu_t*, const unsigned char*);void          rxvt_menuitem_free          (rxvt_t*, menu_t*, menuitem_t*);/* int           rxvt_action_type            (action_t*, unsigned char*); *//* int           rxvt_action_dispatch        (rxvt_t*, action_t*); */int           rxvt_menuarrow_find         (char);void          rxvt_menuarrow_free         (rxvt_t*, unsigned char);void          rxvt_menuarrow_add          (rxvt_t*, unsigned char*);menuitem_t*   rxvt_menuitem_add           (rxvt_t*, menu_t*, const unsigned char*, const unsigned char*, const unsigned char*);unsigned char* rxvt_menu_find_base         (rxvt_t*, menu_t**, unsigned char*);menu_t*       rxvt_menu_delete            (rxvt_t*, menu_t*);menu_t*       rxvt_menu_add               (rxvt_t*, menu_t*, unsigned char*);void          rxvt_drawbox_menubar        (rxvt_t*, int, int, int);void          rxvt_menubar_draw_triangle  (rxvt_t*, int, int, int);void          rxvt_drawbox_menuitem       (rxvt_t*, int, int);void	      rxvt_build_tablist	  (rxvt_t*, menu_t *);void          rxvt_menu_display           (rxvt_t*, void (*update)(rxvt_t*));void          rxvt_menu_hide_all          (rxvt_t*);void          rxvt_menu_hide              (rxvt_t*);void          rxvt_menu_clear             (rxvt_t*, menu_t*);void          rxvt_menubar_clear          (rxvt_t*);void          rxvt_draw_arrows            (rxvt_t*, int, int);void          rxvt_menubar_select         (rxvt_t*, XButtonEvent*);void	      rxvt_menubar_draw_labels	  (rxvt_t*);void	      resizeSubMenus		  (rxvt_t*, menu_t*);#ifdef DEBUGvoid          rxvt_print_menu_ancestors   (menu_t*);void          rxvt_print_menu_descendants (menu_t*);#endif/*--------------------------------------------------------------------* *         END   `INTERNAL' ROUTINE PROTOTYPES                        * *--------------------------------------------------------------------*/static const struct {    const char	  name;	/* (l)eft, (u)p, (d)own, (r)ight */    const unsigned char str[5];	/* str[0] = STRLEN (str+1) */} Arrows[NARROWS] = {    { 'l', "\003\033[D" },    { 'u', "\003\033[A" },    { 'd', "\003\033[B" },    { 'r', "\003\033[C" }};#ifdef XFT_SUPPORT#define PTEXTWIDTH( R, s, len)				    \    ( (ISSET_OPTION(R, Opt_xft) && r->TermWin.xftpfont ) ?  \	( xftPfontTextWidth( (R), (s), (len)) )	:	    \	Width2Pixel(len))intxftPfontTextWidth( rxvt_t *r, const unsigned char *s, int len){    if( s && len )    {	XGlyphInfo ginfo;	XftTextExtents8( r->Xdisplay, r->TermWin.xftpfont, s, len, &ginfo);	return ginfo.width;    }    else	return 0;}# else# define PTEXTWIDTH( r, s, len) (Width2Pixel((len)))#endif#define MENUWIDTH( menu )			    \    ( MENU_ITEM_WIDTH( (menu)->lwidth, (menu)->rwidth ) )#define MENU_ITEM_WIDTH( item_lwidth, item_rwidth )		    \    ((item_lwidth) + (item_rwidth) + 2*SHADOW + 3*HSPACE_PIXEL)/* * find an item called NAME in MENU *//* INTPROTO */menuitem_t*rxvt_menuitem_find(const menu_t *menu, const unsigned char *name){    menuitem_t	 *item;#ifdef DEBUG    assert(NOT_NULL(name));    assert(NOT_NULL(menu));#endif    rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "rxvt_menuitem_find(%s) ... ", name));    /* find the last item in the menu, this is good for separators */    for (item = menu->tail; NOT_NULL(item); item = item->prev)    {	rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "%d", item->entry.itemType));	if (item->entry.itemType == MenuSubMenu)	{	    if (!STRCMP(name, (item->entry.submenu.menu)->name))		break;	}	else if ((isSeparator(name) && isSeparator(item->name))	       || !STRCMP(name, item->name))	    break;	rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, ","));    }    rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "Returning %p\n", item));    return item;}/* * unlink ITEM from its MENU and free its memory *//* INTPROTO */voidrxvt_menuitem_free(rxvt_t *r, menu_t *menu, menuitem_t *item){    /* disconnect */    menuitem_t	 *prev, *next;#ifdef DEBUG    assert(NOT_NULL(menu));#endif    rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "rxvt_menuitem_free()\n"));    prev = item->prev;    next = item->next;    if (NOT_NULL(prev)) prev->next = next;    if (NOT_NULL(next)) next->prev = prev;    /* new head, tail */    if (menu->tail == item) menu->tail = prev;    if (menu->head == item) menu->head = next;    switch (item->entry.itemType)    {	case MenuSubMenu:	    rxvt_menu_delete(r, item->entry.submenu.menu);	    SET_NULL(item->entry.submenu.menu);	    break;	case MenuItem:	    rxvt_free(item->entry.action.str);	    SET_NULL(item->entry.action.str);	    break;    }    if (NOT_NULL(item->name)) rxvt_free(item->name);    if (NOT_NULL(item->name2)) rxvt_free(item->name2);    rxvt_free(item);}/* return the arrow index corresponding to NAME *//* INTPROTO */intrxvt_menuarrow_find(char name){    int		 i;    rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "rxvt_menuarrow_find()\n"));    for (i = 0; i < NARROWS; i++)    if (name == Arrows[i].name)	return i;    return -1;}/* free the memory associated with arrow NAME of the current menubar *//* INTPROTO */voidrxvt_menuarrow_free(rxvt_t *r, unsigned char name){    int		 i;    rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "rxvt_menuarrow_free()\n"));    if (name)    {	i = rxvt_menuarrow_find(name);	if (i >= 0)	{	    action_t	   *act = &(r->h->MenuBar.arrows[i]);	    if (act->len)	    {		assert (NOT_NULL(act->str));		rxvt_free(act->str);		SET_NULL(act->str);		act->len = 0;	    }	    act->type = MenuLabel;	}    }    else    {	/* Free all arrows */	/*	 * 2006-02-22 gi1242 XXX: If Arrows[i].name is NULL this will lead to an	 * infinite loop. WTF.	 */	for (i = 0; i < NARROWS; i++)	    rxvt_menuarrow_free(r, Arrows[i].name);    }}/* INTPROTO */voidrxvt_menuarrow_add(rxvt_t *r, unsigned char *string){    int		 	i;    unsigned short	xtra_len;    unsigned char	*p;    struct    {	unsigned char	*str;	unsigned short	len;    }	    beg = { NULL, 0 },	    end = { NULL, 0 },	    *cur,	    parse[NARROWS];    rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "rxvt_menuarrow_add()\n"));    MEMSET(parse, 0, sizeof(parse));    for (p = string; NOT_NULL(p) && *p; string = p)    {    p = (string + 3);    switch (string[1])    {	case 'b':	    cur = &beg;	    break;	case 'e':	    cur = &end;	    break;	default:	    i = rxvt_menuarrow_find(string[1]);	    if (i >= 0)	    cur = &(parse[i]);	    else	    continue;	/* not found */	    break;    }    string = p;    cur->str = string;    cur->len = 0;    if (cur == &end)    {	p = (unsigned char*) STRCHR(string, '\0');    }    else    {	unsigned char	*next = string;	while (1)	{	    p = (unsigned char*) STRCHR(next, '<');	    if (NOT_NULL(p))	    {		if (p[1] && p[2] == '>')		break;		/* parsed */	    }	    else	    {		if (IS_NULL(beg.str))	/* no end needed */		p = (unsigned char*) STRCHR(next, '\0');		break;	    }	    next = (p + 1);	}    }    if (IS_NULL(p))	return;    cur->len = (p - string);    }#ifdef DEBUG    cur = &beg;    rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "<b>(len %d) = %.*s\n", cur->len, (cur->str ? (char*) cur->str : "")));    for (i = 0; i < NARROWS; i++)    {	cur = &(parse[i]);	rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "<%c>(len %d) = %.*s\n", Arrows[i].name, cur->len, (cur->str ? (char*) cur->str : "")));    }    cur = &end;    rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "<e>(len %d) = %.*s\n", cur->len, (cur->str ? (char*) cur->str : "")));#endif    xtra_len = (beg.len + end.len);    for (i = 0; i < NARROWS; i++)    {	if (xtra_len || parse[i].len)	    rxvt_menuarrow_free(r, Arrows[i].name);    }    for (i = 0; i < NARROWS; i++)    {	char  		str[NEWARGLIM];	unsigned short	len;	if (!parse[i].len)	    continue;	/* possible integer overflow? */	assert (parse[i].len <= 0xffff - xtra_len - 1);	/* str = rxvt_malloc(parse[i].len + xtra_len + 1); */	len = 0;	if (beg.len)	{	    STRNCPY(str + len, beg.str, beg.len);	    len += beg.len;	}	STRNCPY(str + len, parse[i].str, parse[i].len);	len += parse[i].len;	if (end.len)	{	    STRNCPY(str + len, end.str, end.len);	    len += end.len;	}	str[len] = '\0';#ifdef DEBUG	rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "<%c>(len %d) = %s\n", Arrows[i].name, len, str));#endif	rxvt_set_action( &(r->h->MenuBar.arrows[i]), str);    }}/* INTPROTO */menuitem_t   *rxvt_menuitem_add(rxvt_t *r, menu_t *menu,	const unsigned char *name, const unsigned char *name2,	const unsigned char *action){    menuitem_t	 *item;    unsigned int    len;    rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "rxvt_menuitem_add()\n"));#ifdef DEBUG    assert(NOT_NULL(name));    assert(NOT_NULL(action));#endif    if (IS_NULL(menu)) return NULL;    if (isSeparator(name))    {	/* add separator, no action */	name	= (unsigned char *) "";	action	= (unsigned char *) "";    }    else    {	/*	 * add/replace existing menu item	 */	item = rxvt_menuitem_find(menu, name);	if (NOT_NULL(item))	{	    if (NOT_NULL(item->name2) && NOT_NULL(name2))	    {		rxvt_free(item->name2);		item->len2 = 0;		SET_NULL(item->name2);	    }	    switch (item->entry.itemType)	    {		case MenuSubMenu:		    rxvt_menu_delete(r, item->entry.submenu.menu);		    SET_NULL(item->entry.submenu.menu);		    break;		    		case MenuItem:		    rxvt_free(item->entry.action.str);		    SET_NULL(item->entry.action.str);		break;	    }	    goto Item_Found;	}    }    /* allocate a new itemect */    item = (menuitem_t *) rxvt_malloc( sizeof( menuitem_t) );    SET_NULL(item->entry.action.str); /* If not null will be freed by				     rxvt_action_set */    item->len2 = 0;    SET_NULL(item->name2);    len = STRLEN(name);    /* possible integer overflow? */    assert (len >= 0 && len + 1 >= 0);    item->name = rxvt_malloc(len + 1);    STRCPY(item->name, name);    if (name[0] == '.' && name[1] != '.')	len = 0;	/* hidden menu name */    item->len = len;    /* add to tail of list */    item->prev = menu->tail;    SET_NULL(item->next);    if (NOT_NULL(menu->tail))	(menu->tail)->next = item;    menu->tail = item;    /* fix head */    if (IS_NULL(menu->head))	menu->head = item;    /*     * add action     */Item_Found:    if (NOT_NULL(name2) && IS_NULL(item->name2))    {	len = STRLEN(name2);	if (len == 0)	    SET_NULL(item->name2);	else	{	    /* possible integer overflow? */	    assert (len > 0 && len + 1 > 0);	    item->name2 = rxvt_malloc(len + 1);	    STRCPY(item->name2, name2);	}	item->len2 = len;    }    item->entry.itemType = MenuLabel;    len = STRLEN(action);    if (len == 0 && NOT_NULL(item->name2))    {	action = item->name2;	len = item->len2;    }    if (len)    {	char	str[NEWARGLIM];	/* possible integer overflow? */	assert (len > 0 && len + 1 > 0);	/* str = rxvt_malloc(len + 1); */	STRCPY(str, action);	SET_NULL(item->entry.action.str);	if( rxvt_set_action( &(item->entry.action), str) )	    item->entry.itemType = MenuItem;    }    /* new item and a possible increase in width */    len = PTEXTWIDTH( r, item->name, item->len );   /* Left text width */    if( menu->lwidth < len ) menu->lwidth = len;    len = PTEXTWIDTH( r, item->name2, item->len2);  /* Right text width */    if( menu->rwidth < len ) menu->rwidth = len;    return item;}/* * search for the base starting menu for NAME. * return a pointer to the portion of NAME that remains *//* INTPROTO */unsigned char*rxvt_menu_find_base(rxvt_t *r, menu_t **menu, unsigned char *path){    menu_t	 *m = NULL;    menuitem_t	 *item;    rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "rxvt_menu_find_base()\n"));#ifdef DEBUG    assert(NOT_NULL(menu));#endif    if (path[0] == '\0')    return path;    if (NOT_NULL(STRCHR(path, '/')))    {	unsigned char	       *p = path;	while (NOT_NULL(p = (unsigned char*) STRCHR(p, '/')))	{	    p++;	    if (*p == '/')	    path = p;	}	if (path[0] == '/')	{	    path++;	    SET_NULL(*menu);	}

⌨️ 快捷键说明

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