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

📄 menubar.c

📁 Mrxvt是一个小巧
💻 C
📖 第 1 页 / 共 5 页
字号:
	 * Empty menus should get renamed to "Switch to tab".	 */	if( !menu->head && STRCMP( menu->name, "Switch to tab"))	{		DBG_MSG( 1, (stderr, "Renaming menu to Switch to tab\n"));		menu->name = rxvt_realloc( menu->name, 14);		STRCPY( menu->name, "Switch to tab");	}	rxvt_menu_clear( r, menu);	for( i=0; i <= LTAB(r); i++)	{		sprintf( (char*) title, "%2d. %.*s", i+1, MAX_DISPLAY_TAB_TXT-1,				PVTS(r, i)->tab_title);		/* sprintf( action, "]\e]%d;%d\a", Xterm_switchtab, i+1); */		sprintf( (char*) action, "GotoTab %d", i + 1);		rxvt_menuitem_add( r, menu, title, NULL, action);		DBG_MSG( 1, (stderr, "Added menuentry for %s\n",					PVTS(r, i)->tab_title));	}}/* pop up/down the current menu and redraw the menuBar button *//* EXTPROTO */voidrxvt_menu_show(rxvt_t *r){	int			 y, xright;	menu_t		 *ActiveMenu = r->h->ActiveMenu;	menuitem_t	 *item;	unsigned short amenu_width;	DBG_MSG( 2, (stderr, "rxvt_menu_show()\n"));	if (ActiveMenu == NULL)		return;	/*	 * Popup tablist for menus named tablist, or empty popupbutton menus.	 */	if(		 !STRCASECMP( (char*) ActiveMenu->name, "Switch to tab")		 || (			  !STRNCASECMP( (char*) ActiveMenu->name, "popupbutton", 11 )			  && ActiveMenu->head == NULL			)	  )		rxvt_build_tablist( r, ActiveMenu );	if (ActiveMenu->parent == NULL)	{		register int	h;		/* find the height */		for (h = 0, item = ActiveMenu->head; item != NULL; item = item->next)			h += isSeparator(item->name) ? HEIGHT_SEPARATOR					 : HEIGHT_TEXT + 2 * SHADOW;		ActiveMenu->height = h + 2 * SHADOW;		if( !( r->h->showingMenu & POPUP_MENU ))		{			rxvt_drawbox_menubar(r, ActiveMenu->x,					PTEXTWIDTH( r, ActiveMenu->name, ActiveMenu->len), -1);			ActiveMenu->y = rxvt_menubar_height( r );		}	}	amenu_width = MENUWIDTH( ActiveMenu );	/*	 * Move popup menus, or submenus back on screen if they are not completely	 * on screen.	 *	 * XXX 2006-02-02 gi1242: It would be a LOT nicer if we could move all	 * parents of the menu too. We should only do this for popup menus. This is	 * what fvwm does :)	 *	 * BUG: If a moved menu obscures a grandparent menu, then that menu is not	 * redrawn when the child is removed.	 */	if( (r->h->showingMenu & POPUP_MENU) || ActiveMenu->parent != NULL)	{		int		 unused_x, unused_y;		unsigned rootWidth, rootHeight, unused_depth, unused_border_width;		Window	 unused_win;		XGetGeometry( r->Xdisplay, XROOT, &unused_win, &unused_x, &unused_y,				&rootWidth, &rootHeight,				&unused_border_width, &unused_depth);		if( r->szHint.x + ActiveMenu->x + amenu_width >= rootWidth				&& amenu_width < rootWidth)			ActiveMenu->x = rootWidth - amenu_width - r->szHint.x;		if( r->szHint.y + ActiveMenu->y + ActiveMenu->height >= rootHeight				&& ActiveMenu->height < rootHeight)			ActiveMenu->y = rootHeight - ActiveMenu->height - r->szHint.y;	}	/*	 * Create the menu window.	 */	if (ActiveMenu->win == None)	{#if 0		ActiveMenu->win = XCreateSimpleWindow(r->Xdisplay,							r->TermWin.parent,							x, ActiveMenu->y,							ActiveMenu->width, ActiveMenu->height,							0,							r->PixColors[Color_fg],							r->PixColors[Color_scroll]);#endif		/*		 * 2006-02-05 gi1242: We should make menu windows childs of the root		 * window. That way they can go outside the terminal window's		 * boundaries.		 */		XSetWindowAttributes attrs;		attrs.override_redirect = True;		attrs.save_under = True;		attrs.cursor = r->h->bar_pointer;		attrs.background_pixel = r->PixColors[ Color_scroll ];		attrs.border_pixel = r->PixColors[Color_fg];		ActiveMenu->win = XCreateWindow( r->Xdisplay, XROOT,				r->szHint.x + ActiveMenu->x, r->szHint.y + ActiveMenu->y,				amenu_width, ActiveMenu->height, 0,				CopyFromParent, CopyFromParent, CopyFromParent,				CWOverrideRedirect | CWSaveUnder | CWCursor					| CWBackPixel | CWBorderPixel, &attrs);		XMapWindow(r->Xdisplay, ActiveMenu->win);	}#ifdef XFT_SUPPORT	else if( r->Options & Opt_xft )		XClearWindow( r->Xdisplay, ActiveMenu->win );#endif	rxvt_draw_shadow (r->Xdisplay, ActiveMenu->win, r->menuBar.gc,		r->menuBar.topshadow, r->menuBar.botshadow,		0, 0, amenu_width, ActiveMenu->height);	/* determine the correct right-alignment */	for (xright = 0, item = ActiveMenu->head; item != NULL; item = item->next)		if( item->name2 && item->len )		{			int width = PTEXTWIDTH( r, item->name2, item->len2);			if( xright < width ) xright = width;		}	for (y = 0, item = ActiveMenu->head; item != NULL; item = item->next)	{		const int		xoff = (SHADOW + HSPACE_PIXEL/2);		register int	h;		if (isSeparator(item->name))		{			rxvt_draw_shadow (r->Xdisplay, ActiveMenu->win,				r->menuBar.gc,				r->menuBar.topshadow, r->menuBar.botshadow,				SHADOW, y + SHADOW + 1,				amenu_width - 2 * SHADOW, 0);			h = HEIGHT_SEPARATOR;		}		else		{			unsigned char		*name	= item->name;			unsigned short		len		= item->len;			if (item->entry.itemType == MenuSubMenu)			{				int			 x1, y1;				menuitem_t	 *it;				menu_t		 *menu = item->entry.submenu.menu;				rxvt_menubar_draw_triangle(r, amenu_width, y, +1);				name = menu->name;				len = menu->len;				if( name && !STRCMP( menu->name, "Switch to tab"))					rxvt_build_tablist( r, menu);				y1 = ActiveMenu->y + y;#if 0				/* place sub-menu at midpoint of parent menu */				x1 = ActiveMenu->width / 2;				if (x1 > menu->width)	/* right-flush menu if too small */					x1 += (x1 - menu->width);				x1 += x;#endif				/*				 * 2006-01-28 gi1242: Oh my god. This is so ugly. Place				 * sub-menus near the triangle. That'll look a *little* better.				 */				x1 = ActiveMenu->x + amenu_width - TRIANGLE_WIDTH - xoff;				/* find the height of this submenu */				for (h = 0, it = menu->head; it != NULL; it = it->next)					h += isSeparator(it->name) ? HEIGHT_SEPARATOR								   : HEIGHT_TEXT + 2 * SHADOW;				menu->height = h + 2 * SHADOW;				/*				 * XXX 2006-02-02 gi1242: Should we really move the menu back				 * over the terminal window? It's a better idea to do what fvwm				 * does.				 */#if 0				/* ensure menu is in window limits */				if ((x1 + menu->width) >= TWIN_WIDTH(r))					x1 = (TWIN_WIDTH(r) - menu->width);				if ((y1 + menu->height) >= TWIN_HEIGHT(r))					y1 = (TWIN_HEIGHT(r) - menu->height);#endif				menu->x = (x1 < 0 ? 0 : x1);				menu->y = (y1 < 0 ? 0 : y1);			}			else if (item->name2 && !STRCMP(name, item->name2))				name = NULL;			if (item->entry.itemType == MenuLabel)			{				CHOOSE_GC_FG (r, r->menuBar.botshadow);			}			else			{				CHOOSE_GC_FG (r, r->menuBar.fg);			}			if (len && name)			{# ifdef XFT_SUPPORT				/*				 * TODO: Add multichar support.				 */				if( r->Options & Opt_xft )				{					XftFont *font = r->TermWin.xftpfont ?						r->TermWin.xftpfont : r->TermWin.xftfont;					XftDrawChange( r->menuBar.xftDraw, ActiveMenu->win);					XftDrawString8( r->menuBar.xftDraw, &r->menuBar.xftFore,							font, xoff, 2 * SHADOW + y + font->ascent + 1,							name, len);				}				else#endif#ifdef USE_XIM				if (r->TermWin.fontset)				{					XmbDrawString(r->Xdisplay,						  ActiveMenu->win, r->TermWin.fontset,						  r->menuBar.gc, xoff,						  2 * SHADOW + y + r->TermWin.font->ascent + 1,						  (char*) name, len);				}				else#endif				XDrawString(r->Xdisplay, ActiveMenu->win,					r->menuBar.gc, xoff,					2 * SHADOW + y + r->TermWin.font->ascent + 1,					(char*) name, len);			}			len = item->len2;			name = item->name2;			if (len && name)			{# ifdef XFT_SUPPORT				/*				 * XXX Add multichar support.				 */				if( r->Options & Opt_xft )				{					XftFont *font = r->TermWin.xftpfont ?						r->TermWin.xftpfont : r->TermWin.xftfont;					XftDrawChange( r->menuBar.xftDraw, ActiveMenu->win);					XftDrawString8( r->menuBar.xftDraw, &r->menuBar.xftFore,							font,							amenu_width - (xoff + xright),							2 * SHADOW + y + font->ascent + 1,							name, len);				}				else#endif#ifdef USE_XIM				if (r->TermWin.fontset)					XmbDrawString(r->Xdisplay,						ActiveMenu->win, r->TermWin.fontset,						r->menuBar.gc,						amenu_width - (xoff + xright),						2 * SHADOW + y + r->TermWin.font->ascent + 1,						(char*) name, len);				else#endif				XDrawString(r->Xdisplay, ActiveMenu->win,					r->menuBar.gc,					amenu_width - (xoff + xright),					2 * SHADOW + y + r->TermWin.font->ascent + 1,					(char*) name, len);			}			h = HEIGHT_TEXT + 2 * SHADOW;		}		y += h;	}#ifdef XFT_SUPPORT	if( r->Options & Opt_xft )		/*		 * 2006-01-29 gi1242: For some reason if we leave xftDraw		 * with drawable ActiveMenu->win, we get a RenderBadPicture		 * error (I'm not sure on what function call). Thus we reset		 * it.		 */		XftDrawChange( r->menuBar.xftDraw, r->menuBar.win);#endif}/* * Destroy the ActiveMenu window if any, and redisplay (using update) the * parent. Setting updated to recursively call this function will hide all menus * (as in rxvt_menu_hide_all) *//* INTPROTO */voidrxvt_menu_display(rxvt_t *r, void (*update)(rxvt_t *)){	menu_t		 *ActiveMenu = r->h->ActiveMenu;	DBG_MSG( 2, (stderr, "rxvt_menu_display()\n"));	if (ActiveMenu == NULL) return;	if (ActiveMenu->win != None)	{		XDestroyWindow(r->Xdisplay, ActiveMenu->win);		ActiveMenu->win = None;	}	ActiveMenu->item = NULL;	if (ActiveMenu->parent == NULL &&			!(r->h->showingMenu & POPUP_MENU) )		/*		 * 2006-01-30 gi1242: Just clearing the shadow will be enough. But with		 * transparency, drawbox_menubar(0) is not enough.		 */#if 0		rxvt_drawbox_menubar(r, ActiveMenu->x, ActiveMenu->len, 0);#endif		rxvt_menubar_draw_labels(r);	r->h->ActiveMenu = ActiveMenu->parent;	update(r);}/* INTPROTO */voidrxvt_menu_hide_all(rxvt_t *r){	DBG_MSG( 2, (stderr, "rxvt_menu_hide_all()\n"));	rxvt_menu_display(r, rxvt_menu_hide_all);	/* r->h->showingMenu &= ~PULLDOWN_MENU; */}/* * Hide current menu window, and redisplay the parent. *//* INTPROTO */voidrxvt_menu_hide(rxvt_t *r){	DBG_MSG( 2, (stderr, "rxvt_menu_hide()\n"));	/*	 * rxvt_menu_display just destroys the current menu window, and reshow's the	 * parent (if rxvt_menu_show is passed as update function).	 */	rxvt_menu_display(r, rxvt_menu_show);}/* INTPROTO */voidrxvt_menu_clear(rxvt_t *r, menu_t *menu){	DBG_MSG( 2, (stderr, "rxvt_menu_clear()\n"));	if (menu != NULL)	{		menuitem_t	 *item = menu->tail;		while (item != NULL)		{			rxvt_menuitem_free(r, menu, item);			/* it didn't get freed ... why? */			if (item == menu->tail) return;			item = menu->tail;		}		menu->lwidth = menu->rwidth = 0;	}}/* INTPROTO */voidrxvt_menubar_clear(rxvt_t *r){	menu_t		 *menu = r->h->MenuBar.tail;	DBG_MSG( 2, (stderr, "rxvt_menubar_clear()\n"));	while (menu != NULL)	{		menu_t		 *prev = menu->prev;		rxvt_menu_delete(r, menu);		menu = prev;	}	r->h->MenuBar.head = r->h->MenuBar.tail = NULL;	if (r->h->MenuBar.title)	{		free(r->h->MenuBar.title);		r->h->MenuBar.title = NULL;	}	rxvt_menuarrow_free(r, 0);	/* remove all arrow functions */}/* INTPROTO */voidrxvt_draw_arrows(rxvt_t *r, int name, int state){	unsigned long	top, bot;	int			 i;	DBG_MSG( 2, (stderr, "rxvt_draw_arrows()\n"));#ifdef MENU_SHADOW_IN	state = -state;#endif	switch (state)	{		case +1:			top = r->menuBar.topshadow;			bot = r->menuBar.botshadow;			break;			/* SHADOW_OUT */		case -1:			top = r->menuBar.botshadow;			bot = r->menuBar.topshadow;			break;			/* SHADOW_IN */		default:			top = bot = r->menuBar.bg;			break;			/* neutral */	}	if (!r->h->Arrows_x)		return;	for (i = 0; i < NARROWS; i++)	{		const int   w = MENUBAR_ARROW_WIDTH;		const int   y = (rxvt_menubar_height(r) - w) / 2;		int			x = r->h->Arrows_x + (5 * MENUBAR_ARROW_WIDTH * i) / 4;		if (!name || name == Arrows[i].name)			rxvt_draw_triangle (r->Xdisplay, r->menuBar.win,				r->menuBar.gc, top, bot,				x, y, w, Arrows[i].name);	}	XFlush(r->Xdisplay);}/* EXTPROTO */intrxvt_menu_select(rxvt_t *r, XButtonEvent *ev){	menuitem_t	 	*thisitem, *item = NULL;	int			 	this_y, y;	menu_t		 	*ActiveMenu = r->h->ActiveMenu;	unsigned short	amenu_width = MENUWIDTH( ActiveMenu );	Window		 	unused_root, unused_child;	int			 	unused_root_x, unused_root_y;	unsigned int	unused_mask;	DBG_MSG( 2, (stderr, "rxvt_menu_select() (%d)\n",				ev->type));	if (ActiveMenu == NULL) return 0;	XQueryPointer(r->Xdisplay, ActiveMenu->win,		  &unused_root, &unused_child,		  &unused_root_x, &unused_root_y,		  &(ev->x), &(ev->y), &unused_mask);	if (ActiveMenu->parent != NULL && (ev->x < 0 || ev->y < 0))	{		rxvt_menu_hide(r);		return 1;	}	/* determine the menu item corresponding to the Y index */	y = SHADOW;	if (ev->x >= 0 && ev->x <= (amenu_width - SHADOW))	{		for (item = ActiveMenu->head; item != NULL; item = item->next)		{			int			 h = HEIGHT_TEXT + 2 * SHADOW;			if (isSeparator(item->name)) h = HEIGHT_SEPARATOR;			else if (ev->y >= y && ev->y < (y + h))				break;			y += h;		}	}	if (item == NULL && ev->type == ButtonRelease)	{		rxvt_menu_hide_all(r);		return 0;	}	thisitem = item;	this_y = y - SHADOW;	/* erase the last item */	if (ActiveMenu->item != NULL || ev->type == ButtonRelease)	{		if (ActiveMenu->item && ActiveMenu->item != thisitem)		{			/*			 * Erase shadow of old menuitem. We can not get here during a button			 * release.			 */			for (y = 0, item = ActiveMenu->head;					item != NULL;					item = item->next)			{				int			 h;				if (isSeparator(item->name))					h = HEIGHT_SEPARATOR;				else if (item == ActiveMenu->item)				{					/* erase old menuitem shadow */					rxvt_drawbox_menuitem(r, y, 0);	/* No Shadow */					if (item->entry.itemType == MenuSubMenu)						rxvt_menubar_draw_triangle(r, amenu_width, y, +1);					break;				}				else					h = HEIGHT_TEXT + 2 * SHADOW;				y += h;			}		}		else		{			switch (ev->type)

⌨️ 快捷键说明

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