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

📄 menubar.c

📁 Mrxvt是一个小巧
💻 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 DEBUG_VERBOSE#define DEBUG_LEVEL 1#else #define DEBUG_LEVEL 0#endif#if DEBUG_LEVEL#define DBG_MSG(d,x) if(d <= DEBUG_LEVEL) fprintf x#else#define DBG_MSG(d,x)#endif#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 DEBUG_MENU_LAYOUTvoid          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)								\	(( ((r)->Options & 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(name != NULL);	assert(menu != NULL);#endif	DBG_MSG( 2, (stderr, "rxvt_menuitem_find(%s) ... ", name));	/* find the last item in the menu, this is good for separators */	for (item = menu->tail; item != NULL; item = item->prev)	{		DBG_MSG(4, ( stderr, "%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;		DBG_MSG( 4, ( stderr, ","));	}	DBG_MSG( 2, (stderr, "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(menu != NULL);#endif	DBG_MSG( 2, (stderr, "rxvt_menuitem_free()\n"));	prev = item->prev;	next = item->next;	if (prev != NULL) prev->next = next;	if (next != NULL) 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);			item->entry.submenu.menu = NULL;			break;		case MenuItem:			free(item->entry.action.str);			item->entry.action.str = NULL;			break;	}	if (item->name != NULL) free(item->name);	if (item->name2 != NULL) free(item->name2);	free(item);}#if 0 /* {{{ Obsolete: macro action dispatch / set are much better. *//* * sort command vs. terminal actions and * remove the first character of STR if it's '\0' * * return value < 0 means caller can safely free str. >=0 0 means was assigned * to action, and should only be freed when action is destroyed. *//* INTPROTO */intrxvt_action_type(action_t *action, unsigned char *str){	unsigned short	len;	DBG_MSG( 2, (stderr, "rxvt_action_type(action, %s)\n", str));	switch( *str)	{			/*			 * Old behaviour: Use ^@^@ for leading null strings, and ^@ for			 * terminal strings.			 */#if 0		case '>':	/* Write string to child process */#if defined (DEBUG_MENU) || defined (DEBUG_MENUARROWS)			len = STRLEN(str+1);			fprintf(stderr, "(len %d) = %s\n", len, str);#else			len = rxvt_str_escaped( ((char*) str) + 1); /* Skip leading '>' */#endif			if (!len) return -1;			/* sort command vs. terminal actions */			action->type = MenuItem;			if (str[1] == '\0')			{				/* the functional equivalent: memmove (str, str+2, len); */				unsigned char  *dst = (str);				unsigned char  *src = (str + 2);				unsigned char  *end = (str + len);				while (src <= end)					*dst++ = *src++;				len--;			/* decrement length */				if (str[0] != '\0')					action->type = MenuTerminalAction;			}			else				/* Skip leading '>' */				memmove( str, str + 1, len);			action->str = str;			action->len = len;			break;#endif		case '>':	/* Write string to child process */		case ']':	/* Write string to rxvt */			action->type = ((*str == '>') ? MenuAction : MenuTerminalAction);			len = rxvt_str_escaped( ((char*) str) + 1); /* Skip leading ] or > */			memmove( str, str + 1, len);			action->str = str;			action->len = len;			break;		case '\0':	/* Empty action */			return -1;		default:#if 0			/*			 * Looks like there is no need to implement a new set of functions			 * to be called from the menu. Escape sequences work wonderfully.			 */			for( i=0; i < NUM_HKFUNCS; i++)			{				if( !STRCMP( hk_handlers[i].res+7, str))				{					fprintf( stderr, "Matched handler %d, %s\n", i, str);					action->type = MenuCallFuncAction;					action->handler = hk_handlers[i].handler;					return -1;				}			}			fprintf( stderr, "Unknown function %s\n", str);#endif			rxvt_print_error( "Badly formed menu action %s", str);			return -1;	}	return 0;}/* INTPROTO */intrxvt_action_dispatch(rxvt_t *r, action_t *action){	DBG_MSG( 2, (stderr, "rxvt_action_dispatch()\n"));	switch (action->type)	{		case MenuTerminalAction:			rxvt_cmd_write(r, ATAB(r), action->str, action->len);			break;		case MenuAction:			rxvt_tt_write(r, ATAB(r), action->str, action->len);			break;#if 0	/* Better to implement with escape sequences */		case MenuCallFuncAction:			fprintf( stderr, "Calls not implemnted yet\n");			break;#endif		default:			return -1;			break;	}	return 0;}#endif /* }}} *//* return the arrow index corresponding to NAME *//* INTPROTO */intrxvt_menuarrow_find(char name){	int			 i;	DBG_MSG( 2, (stderr, "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;	DBG_MSG( 2, (stderr, "rxvt_menuarrow_free()\n"));	if (name)	{		i = rxvt_menuarrow_find(name);		if (i >= 0)		{			action_t	   *act = &(r->h->MenuBar.arrows[i]);			free(act->str);			act->str = NULL;			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];	DBG_MSG( 2, (stderr, "rxvt_menuarrow_add()\n"));	MEMSET(parse, 0, sizeof(parse));/* fprintf(stderr, "add arrows = `%s'\n", string); */	for (p = string; p != NULL && *p; string = p)	{	p = (string + 3);	/* fprintf(stderr, "parsing at %s\n", string); */	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 (p != NULL)			{				if (p[1] && p[2] == '>')				break;				/* parsed */			}			else			{				if (beg.str == NULL)	/* no end needed */				p = (unsigned char*) STRCHR(next, '\0');				break;			}			next = (p + 1);		}	}	if (p == NULL)		return;	cur->len = (p - string);	}#ifdef DEBUG_MENUARROWS	cur = &beg;	fprintf(stderr, "<b>(len %d) = %.*s\n",		cur->len, cur->len, (cur->str ? cur->str : ""));	for (i = 0; i < NARROWS; i++)	{		cur = &(parse[i]);		fprintf(stderr, "<%c>(len %d) = %.*s\n",			Arrows[i].name,			cur->len, cur->len, (cur->str ? cur->str : ""));	}	cur = &end;	fprintf(stderr, "<e>(len %d) = %.*s\n",		cur->len, cur->len, (cur->str ? 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 >= 0 && xtra_len >= 0);		assert (parse[i].len + xtra_len + 1 > 0);		/* 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_MENUARROWS		fprintf(stderr, "<%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;	DBG_MSG( 2, (stderr, "rxvt_menuitem_add()\n"));#ifdef DEBUG	assert(name != NULL);	assert(action != NULL);#endif	if (menu == NULL) 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 (item != NULL)		{			if (item->name2 != NULL && name2 != NULL)			{				free(item->name2);				item->len2 = 0;				item->name2 = NULL;			}			switch (item->entry.itemType)			{				case MenuSubMenu:					rxvt_menu_delete(r, item->entry.submenu.menu);					item->entry.submenu.menu = NULL;					break;									case MenuItem:					free(item->entry.action.str);					item->entry.action.str = NULL;				break;			}			goto Item_Found;		}	}	/* allocate a new itemect */	item = (menuitem_t *) rxvt_malloc( sizeof( menuitem_t) );

⌨️ 快捷键说明

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