📄 menubar.c
字号:
break; } } } item = menu->tail; while (item != NULL) { menuitem_t *p = item->prev; rxvt_menuitem_free(r, menu, item); item = p; } if (menu->name != NULL) free(menu->name); free(menu); return parent;}/* INTPROTO */menu_t *rxvt_menu_add(rxvt_t *r, menu_t *parent, char *path){ menu_t *menu; bar_t *CurrentBar = r->h->CurrentBar;#ifdef DEBUG_STRICT assert(CurrentBar != NULL);#endif if (STRCHR(path, '/') != NULL) { char *p; if (path[0] == '/') { /* shouldn't happen */ path++; parent = NULL; } while ((p = 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->width = 0; menu->parent = parent; menu->len = STRLEN(path); 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->w = menu->h = 0; menu->item = NULL;/* add to tail of list */ if (parent == NULL) { menu->prev = CurrentBar->tail; if (CurrentBar->tail != NULL) CurrentBar->tail->next = menu; CurrentBar->tail = menu; if (CurrentBar->head == NULL) CurrentBar->head = menu; /* fix head */ if (menu->prev) menu->x = (menu->prev->x + menu->prev->len + HSPACE); } else { menuitem_t *item; item = rxvt_menuitem_add(parent, path, "", ""); if (item == NULL) { free(menu); return parent; }#ifdef DEBUG_STRICT assert(item->entry.type == MenuLabel);#endif item->entry.type = MenuSubMenu; item->entry.submenu.menu = menu; } return menu;}/* INTPROTO */voidrxvt_drawbox_menubar(rxvt_t *r, int x, int len, int state){ GC top, bot; x = Width2Pixel(x); len = Width2Pixel(len + HSPACE); if (x >= r->TermWin.width) return; else if (x + len >= r->TermWin.width) len = (TermWin_TotalWidth() - x);#ifdef MENUBAR_SHADOW_IN state = -state;#endif switch (state) { case +1: top = r->h->topShadowGC; bot = r->h->botShadowGC; break; /* SHADOW_OUT */ case -1: top = r->h->botShadowGC; bot = r->h->topShadowGC; break; /* SHADOW_IN */ default: top = bot = r->h->scrollbarGC; break; /* neutral */ } rxvt_Draw_Shadow(r->Xdisplay, r->menuBar.win, top, bot, x, 0, len, menuBar_TotalHeight());}/* INTPROTO */voidrxvt_drawtriangle(rxvt_t *r, int x, int y, int state){ GC top, bot; int w;#ifdef MENU_SHADOW_IN state = -state;#endif switch (state) { case +1: top = r->h->topShadowGC; bot = r->h->botShadowGC; break; /* SHADOW_OUT */ case -1: top = r->h->botShadowGC; bot = r->h->topShadowGC; break; /* SHADOW_IN */ default: top = bot = r->h->scrollbarGC; break; /* neutral */ } w = Height2Pixel(1) - 2 * SHADOW; x -= SHADOW + (3 * w / 2); y += SHADOW * 3; rxvt_Draw_Triangle(r->Xdisplay, r->h->ActiveMenu->win, top, bot, x, y, w, 'r');}/* INTPROTO */voidrxvt_drawbox_menuitem(rxvt_t *r, int y, int state){ GC top, bot;#ifdef MENU_SHADOW_IN state = -state;#endif switch (state) { case +1: top = r->h->topShadowGC; bot = r->h->botShadowGC; break; /* SHADOW_OUT */ case -1: top = r->h->botShadowGC; bot = r->h->topShadowGC; break; /* SHADOW_IN */ default: top = bot = r->h->scrollbarGC; break; /* neutral */ } rxvt_Draw_Shadow(r->Xdisplay, r->h->ActiveMenu->win, top, bot, SHADOW + 0, SHADOW + y, r->h->ActiveMenu->w - 2 * (SHADOW), HEIGHT_TEXT + 2 * SHADOW); XFlush(r->Xdisplay);}#ifdef DEBUG_MENU_LAYOUT/* INTPROTO */voidrxvt_print_menu_ancestors(menu_t *menu){ 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){ 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/* pop up/down the current menu and redraw the menuBar button *//* INTPROTO */voidrxvt_menu_show(rxvt_t *r){ int x, y, xright; menu_t *ActiveMenu = r->h->ActiveMenu; menuitem_t *item; if (ActiveMenu == NULL) return; x = ActiveMenu->x; if (ActiveMenu->parent == NULL) { register int h; rxvt_drawbox_menubar(r, x, ActiveMenu->len, -1); x = Width2Pixel(x); ActiveMenu->y = 1; ActiveMenu->w = Menu_PixelWidth(ActiveMenu); if ((x + ActiveMenu->w) >= r->TermWin.width) x = (TermWin_TotalWidth() - ActiveMenu->w); /* 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->h = h + 2 * SHADOW; } if (ActiveMenu->win == None) { ActiveMenu->win = XCreateSimpleWindow(r->Xdisplay, r->TermWin.vt, x, ActiveMenu->y, ActiveMenu->w, ActiveMenu->h, 0, r->PixColors[Color_fg], r->PixColors[Color_scroll]); XMapWindow(r->Xdisplay, ActiveMenu->win); } rxvt_Draw_Shadow(r->Xdisplay, ActiveMenu->win, r->h->topShadowGC, r->h->botShadowGC, 0, 0, ActiveMenu->w, ActiveMenu->h);/* determine the correct right-alignment */ for (xright = 0, item = ActiveMenu->head; item != NULL; item = item->next) if (item->len2 > xright) xright = item->len2; for (y = 0, item = ActiveMenu->head; item != NULL; item = item->next) { const int xoff = (SHADOW + Width2Pixel(HSPACE) / 2); register int h; GC gc = r->h->menubarGC; if (isSeparator(item->name)) { rxvt_Draw_Shadow(r->Xdisplay, ActiveMenu->win, r->h->topShadowGC, r->h->botShadowGC, SHADOW, y + SHADOW + 1, ActiveMenu->w - 2 * SHADOW, 0); h = HEIGHT_SEPARATOR; } else { char *name = item->name; int len = item->len; if (item->entry.type == MenuLabel) { gc = r->h->botShadowGC; } else if (item->entry.type == MenuSubMenu) { int x1, y1; menuitem_t *it; menu_t *menu = item->entry.submenu.menu; rxvt_drawtriangle(r, ActiveMenu->w, y, +1); name = menu->name; len = menu->len; y1 = ActiveMenu->y + y; menu->w = Menu_PixelWidth(menu); /* place sub-menu at midpoint of parent menu */ x1 = ActiveMenu->w / 2; if (x1 > menu->w) /* right-flush menu if too small */ x1 += (x1 - menu->w); x1 += x; /* 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->h = h + 2 * SHADOW; /* ensure menu is in window limits */ if ((x1 + menu->w) >= r->TermWin.width) x1 = (TermWin_TotalWidth() - menu->w); if ((y1 + menu->h) >= r->TermWin.height) y1 = (TermWin_TotalHeight() - menu->h); menu->x = (x1 < 0 ? 0 : x1); menu->y = (y1 < 0 ? 0 : y1); } else if (item->name2 && !STRCMP(name, item->name2)) name = NULL; if (len && name) {#ifdef USE_XIM if (r->TermWin.fontset) XmbDrawString(r->Xdisplay, ActiveMenu->win, r->TermWin.fontset, gc, xoff, 2 * SHADOW + y + r->TermWin.font->ascent + 1, name, len); else#endif XDrawString(r->Xdisplay, ActiveMenu->win, gc, xoff, 2 * SHADOW + y + r->TermWin.font->ascent + 1, name, len); } len = item->len2; name = item->name2; if (len && name) {#ifdef USE_XIM if (r->TermWin.fontset) XmbDrawString(r->Xdisplay, ActiveMenu->win, r->TermWin.fontset, gc, ActiveMenu->w - (xoff + Width2Pixel(xright)), 2 * SHADOW + y + r->TermWin.font->ascent + 1, name, len); else#endif XDrawString(r->Xdisplay, ActiveMenu->win, gc, ActiveMenu->w - (xoff + Width2Pixel(xright)), 2 * SHADOW + y + r->TermWin.font->ascent + 1, name, len); } h = HEIGHT_TEXT + 2 * SHADOW; } y += h; }}/* INTPROTO */voidrxvt_menu_display(rxvt_t *r, void (*update)(rxvt_t *)){ menu_t *ActiveMenu = r->h->ActiveMenu; if (ActiveMenu == NULL) return; if (ActiveMenu->win != None) XDestroyWindow(r->Xdisplay, ActiveMenu->win); ActiveMenu->win = None; ActiveMenu->item = NULL; if (ActiveMenu->parent == NULL) rxvt_drawbox_menubar(r, ActiveMenu->x, ActiveMenu->len, +1); r->h->ActiveMenu = ActiveMenu->parent; update(r);}/* INTPROTO */voidrxvt_menu_hide_all(rxvt_t *r){ rxvt_menu_display(r, rxvt_menu_hide_all);}/* INTPROTO */voidrxvt_menu_hide(rxvt_t *r){ rxvt_menu_display(r, rxvt_menu_show);}/* INTPROTO */voidrxvt_menu_clear(rxvt_t *r, menu_t *menu){ 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->width = 0; }}/* INTPROTO */voidrxvt_menubar_clear(rxvt_t *r){ bar_t *CurrentBar = r->h->CurrentBar; if (CurrentBar != NULL) { menu_t *menu = CurrentBar->tail; while (menu != NULL) { menu_t *prev = menu->prev; rxvt_menu_delete(r, menu); menu = prev; } CurrentBar->head = CurrentBar->tail = NULL; if (CurrentBar->title) { free(CurrentBar->title); CurrentBar->title = NULL; } rxvt_menuarrow_free(r, 0); /* remove all arrow functions */ } r->h->ActiveMenu = NULL;}#if (MENUBAR_MAX > 1)/* find if menu already exists *//* INTPROTO */bar_t *rxvt_menubar_find(rxvt_t *r, const char *name){ bar_t *bar = r->h->CurrentBar;#ifdef DEBUG_MENUBAR_STACKING fprintf(stderr, "looking for [menu:%s] ...", name ? name : "(nil)");#endif if (bar == NULL || name == NULL) return NULL; if (STRLEN(name) && STRCMP(name, "*")) { do { if (!STRCMP(bar->name, name)) {#ifdef DEBUG_MENUBAR_STACKING fprintf(stderr, " found!\n");#endif return bar; } bar = bar->next; } while (bar != r->h->CurrentBar); bar = NULL; }#ifdef DEBUG_MENUBAR_STACKING fprintf(stderr, "%s found!\n", (bar ? "" : " NOT"));#endif return bar;}/* INTPROTO */intrxvt_menubar_push(rxvt_t *r, const char *name){ int ret = 1; bar_t *bar; if (r->h->CurrentBar == NULL) { /* allocate first one */ bar = (bar_t *) rxvt_malloc(sizeof(bar_t)); MEMSET(bar, 0, sizeof(bar_t)); /* circular linked-list */ bar->next = bar->prev = bar; bar->head = bar->tail = NULL; bar->title = NULL; r->h->CurrentBar = bar; r->h->Nbars++; rxvt_menubar_clear(r); } else { /* find if menu already exists */ bar = rxvt_menubar_find(r, name); if (bar != NULL) { /* found it, use it */ r->h->CurrentBar = bar; } else { /* create if needed, or reuse the existing empty menubar */ if (r->h->CurrentBar->head != NULL) { /* need to malloc another one */ if (r->h->Nbars < MENUBAR_MAX) bar = (bar_t *) rxvt_malloc(sizeof(bar_t)); else bar = NULL; /* malloc failed or too many menubars, reuse another */ if (bar == NULL) { bar = r->h->CurrentBar->next; ret = -1; } else { bar->head = bar->tail = NULL; bar->title = NULL; bar->next = r->h->CurrentBar->next; r->h->CurrentBar->next = bar; bar->prev = r->h->CurrentBar;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -