📄 menubar.c
字号:
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 + -