📄 menubar.c
字号:
item->entry.action.str = NULL; /* If not null will be freed by rxvt_action_set */ item->len2 = 0; item->name2 = NULL; len = STRLEN(name); /* possible integer overflow? */ assert (len >= 0 && len + 1 >= 0); item->name = rxvt_malloc(len + 1); STRCPY(item->name, name); if (name[0] == '.' && name[1] != '.') len = 0; /* hidden menu name */ item->len = len; /* add to tail of list */ item->prev = menu->tail; item->next = NULL; if (menu->tail != NULL) (menu->tail)->next = item; menu->tail = item; /* fix head */ if (menu->head == NULL) menu->head = item; /* * add action */Item_Found: if (name2 != NULL && item->name2 == NULL) { len = STRLEN(name2); if (len == 0) item->name2 = NULL; else { /* possible integer overflow? */ assert (len > 0 && len + 1 > 0); item->name2 = rxvt_malloc(len + 1); STRCPY(item->name2, name2); } item->len2 = len; } item->entry.itemType = MenuLabel; len = STRLEN(action); if (len == 0 && item->name2 != NULL) { action = item->name2; len = item->len2; } if (len) { char str[NEWARGLIM]; /* possible integer overflow? */ assert (len > 0 && len + 1 > 0); /* str = rxvt_malloc(len + 1); */ STRCPY(str, action); item->entry.action.str = NULL; if( rxvt_set_action( &(item->entry.action), str) ) item->entry.itemType = MenuItem; } /* new item and a possible increase in width */ len = PTEXTWIDTH( r, item->name, item->len ); /* Left text width */ if( menu->lwidth < len ) menu->lwidth = len; len = PTEXTWIDTH( r, item->name2, item->len2); /* Right text width */ if( menu->rwidth < len ) menu->rwidth = len; return item;}/* * search for the base starting menu for NAME. * return a pointer to the portion of NAME that remains *//* INTPROTO */unsigned char*rxvt_menu_find_base(rxvt_t *r, menu_t **menu, unsigned char *path){ menu_t *m = NULL; menuitem_t *item; DBG_MSG( 2, (stderr, "rxvt_menu_find_base()\n"));#ifdef DEBUG assert(menu != NULL);#endif if (path[0] == '\0') return path; if (STRCHR(path, '/') != NULL) { unsigned char *p = path; while ((p = (unsigned char*) STRCHR(p, '/')) != NULL) { p++; if (*p == '/') path = p; } if (path[0] == '/') { path++; *menu = NULL; } while ((p = (unsigned char*) STRCHR(path, '/')) != NULL) { p[0] = '\0'; if (path[0] == '\0') return NULL; if (!STRCMP(path, DOT)) { /* nothing to do */ } else if (!STRCMP(path, DOTS)) { if (*menu != NULL) *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 (*menu != NULL) *menu = (*menu)->parent; return path; } /* find this menu */ if (*menu == NULL) { for (m = r->h->MenuBar.tail; m != NULL; m = m->prev) { if (!STRCMP(path, m->name)) break; } } else { /* find this menu */ for (item = (*menu)->tail; item != NULL; item = item->prev) { if ( item->entry.itemType == MenuSubMenu && !STRCMP(path, (item->entry.submenu.menu)->name) ) { m = (item->entry.submenu.menu); break; } } } if (m != NULL) { *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; DBG_MSG( 2, (stderr, "rxvt_menu_delete()\n")); assert( menu != r->h->ActiveMenu ); /* Shouldn't delete current menu */ /* delete the entire menu */ if (menu == NULL) return NULL; parent = menu->parent; /* unlink MENU */ prev = menu->prev; next = menu->next; if (prev != NULL) prev->next = next; if (next != NULL) next->prev = prev; if (parent == NULL) { /* * 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; next != NULL; next = next->next) next->x -= width; } else { for (item = parent->tail; item != NULL; item = item->prev) { if (item->entry.itemType == MenuSubMenu && item->entry.submenu.menu == menu) { /* Unlink from the parent menu */ item->entry.submenu.menu = NULL; rxvt_menuitem_free(r, menu->parent, item); break; } } } item = menu->tail; while (item != NULL) { menuitem_t *p = item->prev; rxvt_menuitem_free(r, menu, item); item = p; } free(menu->name); free(menu); return parent;}/* INTPROTO */menu_t*rxvt_menu_add(rxvt_t *r, menu_t *parent, unsigned char *path){ menu_t *menu; DBG_MSG( 2, (stderr, "rxvt_menu_add(): Adding menu %s to parent %s\n", path, parent ? parent->name : "(nil)")); if (STRCHR(path, '/') != NULL) { unsigned char *p; if (path[0] == '/') { /* shouldn't happen */ path++; parent = NULL; } while ((p = (unsigned char*) STRCHR(path, '/')) != NULL) { p[0] = '\0'; if (path[0] == '\0') return NULL; parent = rxvt_menu_add(r, parent, path); path = (p + 1); } } if (!STRCMP(path, DOTS)) return (parent != NULL ? 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 */ menu->head = menu->tail = NULL; menu->prev = menu->next = NULL; menu->win = None; menu->x = menu->y = menu->height = 0; menu->item = NULL; if (parent == NULL) { /* Add menus named PopupButton%d to popupMenu[%d] */ if( !STRNCASECMP( "popupbutton", (char *) path, 11 ) && path[11] >= '1' && path[11] <= '3' && path[12] == '\0' ) { int i = path[11] - '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 (r->h->MenuBar.tail != NULL) r->h->MenuBar.tail->next = menu; r->h->MenuBar.tail = menu; /* fix head */ if (r->h->MenuBar.head == NULL) 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 (item == NULL) { if( menu->name != NULL) free( menu->name ); 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; DBG_MSG( 2, (stderr, "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; DBG_MSG( 2, (stderr, "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; DBG_MSG( 2, (stderr, "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_MENU_LAYOUT/* INTPROTO */voidrxvt_print_menu_ancestors(menu_t *menu){ DBG_MSG( 2, (stderr, "rxvt_print_menu_ancestors()\n")); if (menu == NULL) { fprintf(stderr, "Top Level menu\n"); return; } fprintf(stderr, "menu %s ", menu->name); if (menu->parent != NULL) { menuitem_t *item; for (item = menu->parent->head; item != NULL; item = item->next) { if ( item->entry.type == MenuSubMenu && item->entry.submenu.menu == menu ) { break; } } if (item == NULL) { fprintf(stderr, "is an orphan!\n"); return; } } fprintf(stderr, "\n"); rxvt_print_menu_ancestors(menu->parent);}/* INTPROTO */voidrxvt_print_menu_descendants(menu_t *menu){ DBG_MSG( 2, (stderr, "rxvt_print_menu_descendants()\n")); menuitem_t *item; menu_t *parent; int i, level = 0; parent = menu; do { level++; parent = parent->parent; } while (parent != NULL); for (i = 0; i < level; i++) fprintf(stderr, ">"); fprintf(stderr, "%s\n", menu->name); for (item = menu->head; item != NULL; item = item->next) { if (item->entry.type == MenuSubMenu) { if (item->entry.submenu.menu == NULL) fprintf(stderr, "> %s == NULL\n", item->name); else rxvt_print_menu_descendants(item->entry.submenu.menu); } else { for (i = 0; i < level; i++) fprintf(stderr, "+"); if (item->entry.type == MenuLabel) fprintf(stderr, "label: "); fprintf(stderr, "%s\n", item->name); } } for (i = 0; i < level; i++) fprintf(stderr, "<"); fprintf(stderr, "\n");}#endif/* * 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); DBG_MSG( 2, (stderr, "rxvt_build_tablist()\n")); /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -