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

📄 menubar.c

📁 multi-tabed terminal based on rxvt
💻 C
📖 第 1 页 / 共 5 页
字号:
		unsigned char	       *next = (++str);	/* skip leading '[' */		if (str[0] == ':')	/* [:command:] */		{		    do		      {			next++;			if (IS_NULL(next = (unsigned char*) STRCHR(next, ':')))			    return; /* parse error */		      }		    while (next[1] != ']');		    /* remove and skip ':]' */		    *next = '\0';		    next += 2;		}		else		{		    if (IS_NULL(next = (unsigned char*) STRCHR(next, ']')))			return;	/* parse error */		    /* remove and skip ']' */		    *next = '\0';		    next++;		}		if (str[0] == ':')		    rxvt_menubar_dispatcher(r, str + 1);		else if (!STRCMP(str, "clear"))		    rxvt_menubar_clear(r);		else if (			    !STRCMP((char*) str, "done")			    || rxvt_str_match( (char*) str, "done:")			)		{		    /* We shouldn't ever get here */		    assert(0);		}		/*		 * 2006-02-02 gi1242: Using this command in config files will		 * override the users --showmenu option. Since there are other		 * escape sequences and shortcuts to do the same, we don't need		 * this here.		 */#if 0		else if (!STRCMP(str, "show"))		{		    if (rxvt_menubar_show(r))			rxvt_resize_on_subwin (r, SHOW_MENUBAR);		}		else if (!STRCMP(str, "hide"))		{		    if (rxvt_menubar_hide(r))			rxvt_resize_on_subwin (r, HIDE_MENUBAR);		}#endif		else if ((n = rxvt_str_match( (char*) str, "read:")) != 0)		{		    /* read in a menu from a file */		    str += n;		    rxvt_menubar_load_file(r, str);		}		else if ((n = rxvt_str_match( (char*) str, "title:")) != 0)		{		    str += n;		    if (*str)		    {			name = rxvt_realloc(r->h->MenuBar.title,			    STRLEN(str) + 1);			if (NOT_NULL(name))			{			    STRCPY(name, str);			    r->h->MenuBar.title = name;			}		    }		    else		    {			rxvt_free(r->h->MenuBar.title);			SET_NULL(r->h->MenuBar.title);		    }		}		else if ((n = rxvt_str_match( (char*) str, "pixmap:")) != 0)		{		    str += n;		    rxvt_xterm_seq(r, ATAB(r), XTerm_Pixmap,			    (char*) str, CHAR_ST);		}		str = next;		/*		 * 2006-02-04 gi1242: Don't clear the menu currently bieng		 * built. This will enable [read:...] commands to add to the		 * current menu, instead of the menubar.		 */#if 0		SET_NULL(r->h->BuildMenu);		SET_NULL(r->h->ActiveMenu);		rxvt_menubar_expose(r);#endif	    }	    return;	    break;    }    switch (cmd)    {	case '+':	case '-':	    path = name = str;	    SET_NULL(name2);	    /* parse STR, allow spaces inside (name)  */	    if (path[0] != '\0')	    {		name = (unsigned char*) STRCHR(path, MENUITEM_BEG);		str = (unsigned char*) STRCHR(path, MENUITEM_END);		if (NOT_NULL(name) || NOT_NULL(str))		{		    if (IS_NULL(name) || IS_NULL(str) || str <= (name + 1) ||			(name > path && name[-1] != '/')		       )		    {			rxvt_msg (DBG_ERROR, DBG_MENUBAR, "menu error <%s>\n", path);			break;		    }		    if (str[1] == MENUITEM_BEG)		    {			name2 = (str + 2);			str = (unsigned char*) STRCHR(name2, MENUITEM_END);			if (IS_NULL(str))			{			    rxvt_msg (DBG_ERROR, DBG_MENUBAR, "menu error <%s>\n", path);			    break;			}			name2[-2] = '\0';   /* remove prev MENUITEM_END */		    }		    if (name > path && name[-1] == '/')			name[-1] = '\0';		    *name++ = '\0'; /* delimit */		    *str++ = '\0';  /* delimit */		    while (isspace((int) *str))			str++;	/* skip space */		}		rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "`%c' path = <%s>, name = <%s>, name2 = <%s>, action = <%s>\n", cmd, (path ? (char*) path : "(nil)"), (name ? (char*) name : "(nil)"), (name2 ? (char*) name2 : "(nil)"), (str ? (char*) str : "(nil)")));	    }	    /* process the different commands */	    switch (cmd)	    {		case '+':	/* add/replace existing menu or menuitem */		    if (path[0] != '\0')		    {			int	     len;			rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "Current menu %s\n", NOT_NULL(r->h->BuildMenu) ? (char *)r->h->BuildMenu->name : "(nil)"));			path = rxvt_menu_find_base(r, &(r->h->BuildMenu), path);			len = STRLEN(path);			/* don't allow menus called `*' */			if (path[0] == '*')			{			    rxvt_menu_clear(r, r->h->BuildMenu);			    break;			}			else if (len >= 2 && !STRCMP((path + len - 2), "/*"))			{			    path[len - 2] = '\0';			}			if (path[0] != '\0')			    r->h->BuildMenu =				rxvt_menu_add(r, r->h->BuildMenu, path);		    }		    if (NOT_NULL(name) && name[0] != '\0')			rxvt_menuitem_add(r, r->h->BuildMenu,			      (STRCMP(name, SEPARATOR_NAME) ?				    name : (unsigned char *) ""),			      name2, str);		    break;		case '-':	/* delete menu entry */		    if ( !STRCMP(path, "/*") &&			(IS_NULL(name) || name[0] == '\0')		       )		    {			rxvt_menubar_clear(r);			SET_NULL(r->h->BuildMenu);			break;		    }		    else if (path[0] != '\0')		    {			int	     len;			menu_t	     *menu = r->h->BuildMenu;			path = rxvt_menu_find_base(r, &menu, path);			len = STRLEN(path);			/* submenu called `*' clears all menu items */			if (path[0] == '*')			{			    rxvt_menu_clear(r, menu);			    break;  /* done */			}			else if (len >= 2 && !STRCMP(&path[len - 2], "/*"))			{			    /* done */			    break;			}			else if (path[0] != '\0')			{			    SET_NULL(r->h->BuildMenu);			    break;			}			else			    r->h->BuildMenu = menu;		    }		    if (NOT_NULL(r->h->BuildMenu))		    {			if (IS_NULL(name) || name[0] == '\0')			    r->h->BuildMenu =				rxvt_menu_delete(r, r->h->BuildMenu);			else			{			    const unsigned char	 *n1;			    menuitem_t	 	 *item;			    menu_t	 	 *BuildMenu = r->h->BuildMenu;			    n1 = STRCMP(name, SEPARATOR_NAME)				    ? name : (unsigned char*) "";			    item = rxvt_menuitem_find(BuildMenu, n1);			    if (NOT_NULL(item) &&				item->entry.itemType != MenuSubMenu			       )			    {				rxvt_menuitem_free(r, BuildMenu, item);				/* fix up the width */				BuildMenu->lwidth = BuildMenu->rwidth = 0;				for (item = BuildMenu->head; NOT_NULL(item);					item = item->next)				{				    unsigned short l;				    				    l = PTEXTWIDTH( r, item->name, item->len);				    MAX_IT(BuildMenu->lwidth, l);				    l = PTEXTWIDTH( r, item->name2, item->len2);				    MAX_IT(BuildMenu->rwidth, l);				}			    }			}		    }		    break;	    }	    break;    }}/*** general dispatch routine,** it would be nice to have `sticky' menus*//* EXTPROTO */voidrxvt_menubar_control(rxvt_t *r, XButtonEvent *ev){    rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "rxvt_menubar_control()\n"));    switch (ev->type)    {	case ButtonPress:	    if (ev->button == Button1)		rxvt_menubar_select(r, ev);	    break;	case ButtonRelease:	    if (ev->button == Button1 && r->h->ActiveMenu)		rxvt_menu_select(r, ev);	    break;	case MotionNotify:	    while (XCheckTypedWindowEvent(r->Xdisplay, r->TermWin.parent,			      MotionNotify, (XEvent *) ev)) ;	    if (r->h->ActiveMenu)		while (rxvt_menu_select(r, ev)) ;	    else		ev->y = -1;	    if (ev->y < 0)	    {		Window	      unused_root, unused_child;		int	     unused_root_x, unused_root_y;		unsigned int	unused_mask;		XQueryPointer(r->Xdisplay, r->menuBar.win,		      &unused_root, &unused_child,		      &unused_root_x, &unused_root_y,		      &(ev->x), &(ev->y), &unused_mask);		rxvt_menubar_select(r, ev);	    }	    break;    }}/* * read in menubar commands from FILENAME * ignore all input before the tag line [menu] or [menu:???] * * Note that since File_find () is used, FILENAME can be semi-colon * delimited such that the second part can refer to a tag * so that a large `database' of menus can be collected together * * FILENAME = "file" * FILENAME = "file;" *    read `file' starting with first [menu] or [menu:???] line * * FILENAME = "file;tag" *    read `file' starting with [menu:tag] *//* EXTPROTO */voidrxvt_menubar_load_file(rxvt_t *r, const unsigned char *filename){/* read in a menu from a file */    FILE	   *fp;    unsigned char   buffer[256];    unsigned char  *p, *file, *tag = NULL;    rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "rxvt_menubar_load_file()\n"));    file = (unsigned char*) rxvt_File_find( (char*) filename,	    ".menu", r->h->rs[Rs_path]);    if (IS_NULL(file))    {	rxvt_msg (DBG_ERROR, DBG_MENUBAR,  "Could not open file %s\n",		filename);	return;    }    fp = fopen( (char*) file, "rb");    rxvt_free(file);    if (IS_NULL(fp))	return;    /* semi-colon delimited */    if (NOT_NULL(tag = (unsigned char*) STRCHR(filename, ';')))    {	tag++;	if (*tag == '\0')	    SET_NULL(tag);    }    rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "[read:%s]\n", filename));    if (tag)	rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "looking for [menu:%s]\n", tag));    while (NOT_NULL(p = (unsigned char*) fgets( (char*) buffer, sizeof(buffer), fp)))    {	int	     n;	if ((n = rxvt_str_match( (char*) p, "[menu")) != 0)	{	    if (tag)	    {		/* looking for [menu:tag] */		if (p[n] == ':' && p[n + 1] != ']')		{		    n++;		    n += rxvt_str_match( (char*) p + n, (char*) tag);		    if (p[n] == ']')		    {			rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "[menu:%s]\n", tag));			break;		    }		}	    }	    else if (p[n] == ':' || p[n] == ']')		break;	}    }    /* found [menu], [menu:???] tag */    while (NOT_NULL(p))    {	int	     n;	rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "read line = %s\n", p));	/* looking for [done:tag] or [done:] */	if ((n = rxvt_str_match( (char*) p, "[done")) != 0)	{	    if (p[n] == ']')	    {		break;	    }	    else if (p[n] == ':')	    {		n++;		if (p[n] == ']')		{		    break;		}		else if (tag)		{		    n += rxvt_str_match( (char*) p + n, (char*) tag);		    if (p[n] == ']')		    {			rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "[done:%s]\n", tag));			break;		    }		}		else		{		    /* what? ... skip this line */		    p[0] = COMMENT_CHAR;		}	    }	}	/*	 * remove leading/trailing space and strip-off leading/trailing quotes	 * skip blank or comment lines	 */	rxvt_str_trim( (char*) p);	if (*p && *p != '#') rxvt_menubar_dispatcher(r, p);	/* get another line */	p = (unsigned char*) fgets( (char*) buffer, sizeof(buffer), fp);    }    fclose(fp);}/* EXTPROTO */unsigned shortrxvt_menubar_height(rxvt_t *r){    rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "rxvt_menubar_height()\n"));    /* If menubar is not created or not mapped, return 0 */    return  (NOT_WIN(r->menuBar.win) || !r->menuBar.state) ?	    0 : rxvt_menubar_rheight(r);}/* EXTPROTO */unsigned shortrxvt_menubar_rheight(rxvt_t *r){    rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "rxvt_menubar_rheight()\n"));# ifdef XFT_SUPPORT    if (ISSET_OPTION(r, Opt_xft))	return (r->TermWin.pheight + 2*SHADOW + 2*MENUBAR_MARGIN);    else# endif	return (r->TermWin.fheight + 2*SHADOW + 2*MENUBAR_MARGIN);}/* EXTPROTO */intrxvt_is_menubar_win(rxvt_t *r, Window w){    rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "rxvt_is_menubar_win()\n"));    return (w == r->menuBar.win);}/* EXTPROTO */voidrxvt_menubar_resize(rxvt_t *r){    menu_t  *menu;    int	    i;    rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "rxvt_menubar_resize()\n"));    if (IS_WIN(r->menuBar.win) && r->menuBar.state)	XMoveResizeWindow(r->Xdisplay, r->menuBar.win,	    0, 0, TWIN_WIDTH(r), rxvt_menubar_rheight(r));    /*     * All submenus now need to be traversed and resized.     */    for (menu = r->h->MenuBar.head; NOT_NULL(menu); menu = menu->next)    {	resizeSubMenus( r, menu );	/* X coordinate of menu names in menubar need to be updated */	if( menu->prev )	    menu->x = menu->prev->x + 2 * HSPACE_PIXEL		+ PTEXTWIDTH( r, menu->prev->name, menu->prev->len);    }    /*     * Resize the popup menus if any.     */    for( i=0; i < 3; i++)	if( r->h->popupMenu[i] ) resizeSubMenus( r, r->h->popupMenu[i]);}/* * Update menu->width for all submenus. *//* INTPROTO */voidresizeSubMenus( rxvt_t *r, menu_t *menu){    menuitem_t *item;    menu->lwidth = menu->rwidth = 0;    for( item = menu->head; NOT_NULL(item); item = item->next)    {	unsigned short width;		width = PTEXTWIDTH( r, item->name, item->len);	if( menu->lwidth < width ) menu->lwidth = width;	width = PTEXTWIDTH( r, item->name2, item->len2);	if( menu->rwidth < width ) menu->rwidth = width;	if( item->entry.itemType == MenuSubMenu && item->entry.submenu.menu)	    resizeSubMenus( r, item->entry.submenu.menu );    }}#endif	/* HAVE_MENUBAR *//*----------------------- end-of-file (C source) -----------------------*/

⌨️ 快捷键说明

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