📄 menubar.c
字号:
while (NOT_NULL(p = (unsigned char*) STRCHR(path, '/'))) { p[0] = '\0'; if (path[0] == '\0') return NULL; if (!STRCMP(path, DOT)) { /* nothing to do */ } else if (!STRCMP(path, DOTS)) { if (NOT_NULL(*menu)) *menu = (*menu)->parent; } else { path = rxvt_menu_find_base(r, menu, path); if (path[0] != '\0') /* not found */ { p[0] = '/'; /* fix-up name again */ return path; } } path = (p + 1); } } if (!STRCMP(path, DOTS)) { path += STRLEN(DOTS); if (NOT_NULL(*menu)) *menu = (*menu)->parent; return path; } /* find this menu */ if (IS_NULL(*menu)) { for (m = r->h->MenuBar.tail; NOT_NULL(m); m = m->prev) { if (!STRCMP(path, m->name)) break; } } else { /* find this menu */ for (item = (*menu)->tail; NOT_NULL(item); item = item->prev) { if ( item->entry.itemType == MenuSubMenu && !STRCMP(path, (item->entry.submenu.menu)->name) ) { m = (item->entry.submenu.menu); break; } } } if (NOT_NULL(m)) { *menu = m; path += STRLEN(path); } return path;}/* * delete this entire menu *//* INTPROTO */menu_t*rxvt_menu_delete(rxvt_t *r, menu_t *menu){ menu_t *parent = NULL, *prev, *next; menuitem_t *item; rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "rxvt_menu_delete()\n")); assert( menu != r->h->ActiveMenu ); /* Shouldn't delete current menu */ /* delete the entire menu */ if (IS_NULL(menu)) return NULL; parent = menu->parent; /* unlink MENU */ prev = menu->prev; next = menu->next; if (NOT_NULL(prev)) prev->next = next; if (NOT_NULL(next)) next->prev = prev; if (IS_NULL(parent)) { /* * If we got here, then this menu is either a popup menu, or a pulldown * submenu of the main menubar. */ const int width = 2 * HSPACE_PIXEL + PTEXTWIDTH( r, menu->name, menu->len); /* * Reset start / end of menus in the menubar if we deleted the first / * last pulldown menu. */ if (r->h->MenuBar.tail == menu) r->h->MenuBar.tail = prev; if (r->h->MenuBar.head == menu) r->h->MenuBar.head = next; /* * Move all subsequent entries of the menubar to the left. Popups don't * have next or prev set, so no worries doing this */ for (next = menu->next; NOT_NULL(next); next = next->next) next->x -= width; } else { for (item = parent->tail; NOT_NULL(item); item = item->prev) { if (item->entry.itemType == MenuSubMenu && item->entry.submenu.menu == menu) { /* Unlink from the parent menu */ SET_NULL(item->entry.submenu.menu); rxvt_menuitem_free(r, menu->parent, item); break; } } } item = menu->tail; while (NOT_NULL(item)) { menuitem_t *p = item->prev; rxvt_menuitem_free(r, menu, item); item = p; } rxvt_free(menu->name); rxvt_free(menu); return parent;}/* INTPROTO */menu_t*rxvt_menu_add(rxvt_t *r, menu_t *parent, unsigned char *path){ menu_t *menu; rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "rxvt_menu_add(): Adding menu %s to parent %s\n", path, NOT_NULL(parent) ? (char *)parent->name : "(nil)")); if (NOT_NULL(STRCHR(path, '/'))) { unsigned char *p; if (path[0] == '/') { /* shouldn't happen */ path++; SET_NULL(parent); } while (NOT_NULL(p = (unsigned char*) STRCHR(path, '/'))) { p[0] = '\0'; if (path[0] == '\0') return NULL; parent = rxvt_menu_add(r, parent, path); path = (p + 1); } } if (!STRCMP(path, DOTS)) return (NOT_NULL(parent) ? parent->parent : parent); if (!STRCMP(path, DOT) || path[0] == '\0') return parent; /* allocate a new menu */ menu = (menu_t *) rxvt_malloc(sizeof(menu_t)); menu->lwidth = menu->rwidth = 0; menu->parent = parent; menu->len = STRLEN(path); /* possible integer overflow? */ assert (menu->len > 0 && menu->len+1 > 0); menu->name = rxvt_malloc((menu->len + 1)); STRCPY(menu->name, path); /* initialize head/tail */ SET_NULL(menu->head); SET_NULL(menu->tail); SET_NULL(menu->prev); SET_NULL(menu->next); UNSET_WIN(menu->win); menu->x = menu->y = menu->height = 0; SET_NULL(menu->item); if (IS_NULL(parent)) { /* Add menus named PopupButton%d to popupMenu[%d] */ if( !STRNCASECMP("popupbutton", (char*) path, (sizeof("popupbutton")-1)) && path[sizeof("popupbutton")-1] >= '1' && path[sizeof("popupbutton")-1] <= '3' && path[sizeof("popupbutton")] == '\0' ) { int i = path[sizeof("popupbutton")-1] - '1'; /* Free the menu */ if( r->h->popupMenu[i] ) rxvt_menu_delete( r, r->h->popupMenu[i] ); r->h->popupMenu[i] = menu; } else { /* * Add this menu as a the last pulldown menu in the menubar. */ menu->prev = r->h->MenuBar.tail; if (NOT_NULL(r->h->MenuBar.tail)) r->h->MenuBar.tail->next = menu; r->h->MenuBar.tail = menu; /* fix head */ if (IS_NULL(r->h->MenuBar.head)) r->h->MenuBar.head = menu; if (menu->prev) menu->x = menu->prev->x + 2 * HSPACE_PIXEL + PTEXTWIDTH( r, menu->prev->name, menu->prev->len); } } else { menuitem_t *item; item = rxvt_menuitem_add(r, parent, path, (unsigned char*) "", (unsigned char*) ""); if (IS_NULL(item)) { if (NOT_NULL(menu->name)) rxvt_free( menu->name ); rxvt_free(menu); return parent; }#ifdef DEBUG assert(item->entry.itemType == MenuLabel);#endif item->entry.itemType = MenuSubMenu; item->entry.submenu.menu = menu; } return menu;}/* INTPROTO */voidrxvt_drawbox_menubar(rxvt_t *r, int x, int len, int state){ unsigned long top, bot; rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "rxvt_drawbox_menubar()\n")); /* XXXMENU */ len += HSPACE_PIXEL + SHADOW; if (x >= TWIN_WIDTH(r)) return; else if (x + len >= TWIN_WIDTH(r)) len = (TWIN_WIDTH(r) - x);#ifdef MENUBAR_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 */ } rxvt_draw_shadow(r->Xdisplay, r->menuBar.win, r->menuBar.gc, top, bot, x, 0, len, rxvt_menubar_height(r));}/* INTPROTO */voidrxvt_menubar_draw_triangle(rxvt_t *r, int x, int y, int state){ unsigned long top, bot; int w; rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "rxvt_menubar_draw_triangle()\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 */ } w = TRIANGLE_WIDTH; x -= SHADOW + (3 * w / 2); y += SHADOW*2 + (HEIGHT_TEXT - TRIANGLE_WIDTH)/2; rxvt_draw_triangle (r->Xdisplay, r->h->ActiveMenu->win, r->menuBar.gc, top, bot, x, y, w, 'r');}/* INTPROTO */voidrxvt_drawbox_menuitem(rxvt_t *r, int y, int state){ unsigned long top, bot; rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "rxvt_drawbox_menuitem()\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 */ } rxvt_draw_shadow (r->Xdisplay, r->h->ActiveMenu->win, r->menuBar.gc, top, bot, SHADOW + 0, SHADOW + y, MENUWIDTH( r->h->ActiveMenu ) - 2 * (SHADOW), HEIGHT_TEXT + 2 * SHADOW); XFlush(r->Xdisplay);}#ifdef DEBUG/* INTPROTO */voidrxvt_print_menu_ancestors(menu_t *menu){ rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "rxvt_print_menu_ancestors()\n")); if (IS_NULL(menu)) { rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "Top Level menu\n")); return; } rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "menu %s ", menu->name)); if (NOT_NULL(menu->parent)) { menuitem_t *item; for (item = menu->parent->head; NOT_NULL(item); item = item->next) { if (item->entry.itemType == MenuSubMenu && item->entry.submenu.menu == menu) { break; } } if (IS_NULL(item)) { rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "is an orphan!\n")); return; } } rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "\n")); rxvt_print_menu_ancestors(menu->parent);}/* INTPROTO */voidrxvt_print_menu_descendants(menu_t *menu){ rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "rxvt_print_menu_descendants()\n")); menuitem_t *item; menu_t *parent; int i, level = 0; parent = menu; do { level++; parent = parent->parent; } while (NOT_NULL(parent)); for (i = 0; i < level; i++) rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, ">")); rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "%s\n", menu->name)); for (item = menu->head; NOT_NULL(item); item = item->next) { if (item->entry.itemType == MenuSubMenu) { if (IS_NULL(item->entry.submenu.menu)) rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "> %s == NULL\n", item->name)); else rxvt_print_menu_descendants(item->entry.submenu.menu); } else { for (i = 0; i < level; i++) rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "+")); if (item->entry.itemType == MenuLabel) rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "label: ")); rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "%s\n", item->name)); } } for (i = 0; i < level; i++) rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "<")); rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "\n"));}#endif /* DEBUG *//* * Build a menu with all the titles of current tabs. *//* INTPROTO */voidrxvt_build_tablist(rxvt_t *r, menu_t *menu){ int i; unsigned char action[16], title[MAX_DISPLAY_TAB_TXT + 4]; assert( menu); rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "rxvt_build_tablist()\n")); /* * Empty menus should get renamed to "Switch to tab". */ if( !menu->head && STRCMP( menu->name, "Switch to tab")) { rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "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); rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "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; rxvt_dbgmsg ((DBG_DEBUG, DBG_MENUBAR, "rxvt_menu_show()\n")); if (IS_NULL(ActiveMenu)) 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 (IS_NULL(ActiveMenu->parent)) { register int h; /* find the height */ for (h = 0, item = ActiveMenu->head; NOT_NULL(item); 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 :)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -