📄 menubar.c
字号:
str++; /* skip space */ }#ifdef DEBUG_MENU fprintf(stderr, "`%c' path = <%s>, name = <%s>, name2 = <%s>, action = <%s>\n", cmd, (path ? path : "(nil)"), (name ? name : "(nil)"), (name2 ? name2 : "(nil)"), (str ? str : "(nil)") );#endif } /* process the different commands */ switch (cmd) { case '+': /* add/replace existing menu or menuitem */ if (path[0] != '\0') { int len; 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 (name != NULL && name[0] != '\0') rxvt_menuitem_add(r->h->BuildMenu, (STRCMP(name, SEPARATOR_NAME) ? name : ""), name2, str); break; case '-': /* delete menu entry */ if (!STRCMP(path, "/*") && (name == NULL || name[0] == '\0')) { rxvt_menubar_clear(r); r->h->BuildMenu = NULL; rxvt_menubar_expose(r); 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') { r->h->BuildMenu = NULL; break; } else r->h->BuildMenu = menu; } if (r->h->BuildMenu != NULL) { if (name == NULL || name[0] == '\0') r->h->BuildMenu = rxvt_menu_delete(r, r->h->BuildMenu); else { const char *n1; menuitem_t *item; menu_t *BuildMenu = r->h->BuildMenu; n1 = STRCMP(name, SEPARATOR_NAME) ? name : ""; item = rxvt_menuitem_find(BuildMenu, n1); if (item != NULL && item->entry.type != MenuSubMenu) { rxvt_menuitem_free(r, BuildMenu, item); /* fix up the width */ BuildMenu->width = 0; for (item = BuildMenu->head; item != NULL; item = item->next) { short l = item->len + item->len2; MAX_IT(BuildMenu->width, l); } } } rxvt_menubar_expose(r); } break; } break; }}/* INTPROTO */voidrxvt_draw_Arrows(rxvt_t *r, int name, int state){ GC top, bot; int i;#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 */ } if (!r->h->Arrows_x) return; for (i = 0; i < NARROWS; i++) { const int w = Width2Pixel(1); const int y = (menuBar_TotalHeight() - w) / 2; int x = r->h->Arrows_x + (5 * Width2Pixel(i)) / 4; if (!name || name == Arrows[i].name) rxvt_Draw_Triangle(r->Xdisplay, r->menuBar.win, top, bot, x, y, w, Arrows[i].name); } XFlush(r->Xdisplay);}/* EXTPROTO */voidrxvt_menubar_expose(rxvt_t *r){ menu_t *menu; int x; if (!menubar_visible(r) || r->menuBar.win == 0) return; if (r->h->menubarGC == None) { /* Create the graphics context */ XGCValues gcvalue; gcvalue.font = r->TermWin.font->fid; gcvalue.foreground = (XDEPTH <= 2 ? r->PixColors[Color_fg] : r->PixColors[Color_Black]); r->h->menubarGC = XCreateGC(r->Xdisplay, r->menuBar.win, GCForeground | GCFont, &gcvalue); }/* make sure the font is correct */ XSetFont(r->Xdisplay, r->h->menubarGC, r->TermWin.font->fid); XSetFont(r->Xdisplay, r->h->botShadowGC, r->TermWin.font->fid); XClearWindow(r->Xdisplay, r->menuBar.win); rxvt_menu_hide_all(r); x = 0; if (r->h->CurrentBar != NULL) { for (menu = r->h->CurrentBar->head; menu != NULL; menu = menu->next) { int len = menu->len; x = (menu->x + menu->len + HSPACE);#ifdef DEBUG_MENU_LAYOUT rxvt_print_menu_descendants(menu);#endif if (x >= r->TermWin.ncol) len = (r->TermWin.ncol - (menu->x + HSPACE)); rxvt_drawbox_menubar(r, menu->x, len, +1);#ifdef USE_XIM if (r->TermWin.fontset) XmbDrawString(r->Xdisplay, r->menuBar.win, r->TermWin.fontset, r->h->menubarGC, (Width2Pixel(menu->x) + Width2Pixel(HSPACE) / 2), menuBar_height() - SHADOW, menu->name, len); else#endif XDrawString(r->Xdisplay, r->menuBar.win, r->h->menubarGC, (Width2Pixel(menu->x) + Width2Pixel(HSPACE) / 2), menuBar_height() - SHADOW, menu->name, len); if (x >= r->TermWin.ncol) break; } } rxvt_drawbox_menubar(r, x, r->TermWin.ncol, (r->h->CurrentBar ? +1 : -1));/* add the menuBar title, if it exists and there's plenty of room */ r->h->Arrows_x = 0; if (x < r->TermWin.ncol) { const char *str; int ncol; unsigned int len; char title[256]; ncol = (int)r->TermWin.ncol; if (x < (ncol - (NARROWS + 1))) { ncol -= (NARROWS + 1); r->h->Arrows_x = Width2Pixel(ncol); } rxvt_draw_Arrows(r, 0, +1); str = (r->h->CurrentBar && r->h->CurrentBar->title) ? r->h->CurrentBar->title : "%n-%v"; for (len = 0; str[0] && len < sizeof(title) - 1; str++) { const char *s = NULL; switch (str[0]) { case '%': str++; switch (str[0]) { case 'n': s = r->h->rs[Rs_name]; break; /* resource name */ case 'v': s = VERSION; break; /* version number */ case '%': s = "%"; break; /* literal '%' */ } if (s != NULL) while (*s && len < sizeof(title) - 1) title[len++] = *s++; break; default: title[len++] = str[0]; break; } } title[len] = '\0'; ncol -= (x + len + HSPACE); if (len > 0 && ncol >= 0) {#ifdef USE_XIM if (r->TermWin.fontset) XmbDrawString(r->Xdisplay, r->menuBar.win, r->TermWin.fontset, r->h->menubarGC, Width2Pixel(x) + Width2Pixel(ncol + HSPACE) / 2, menuBar_height() - SHADOW, title, len); else#endif XDrawString(r->Xdisplay, r->menuBar.win, r->h->menubarGC, Width2Pixel(x) + Width2Pixel(ncol + HSPACE) / 2, menuBar_height() - SHADOW, title, len); } }}/* INTPROTO */intrxvt_menubar_mapping(rxvt_t *r, int map){ int change = 0; if (map && !menubar_visible(r)) { r->menuBar.state = 1; if (r->menuBar.win == 0) return 0; XMapWindow(r->Xdisplay, r->menuBar.win); change = 1; } else if (!map && menubar_visible(r)) { rxvt_menubar_expose(r); r->menuBar.state = 0; XUnmapWindow(r->Xdisplay, r->menuBar.win); change = 1; } else rxvt_menubar_expose(r); return change;}/* INTPROTO */intrxvt_menu_select(rxvt_t *r, XButtonEvent *ev){ menuitem_t *thisitem, *item = NULL; int this_y, y; menu_t *ActiveMenu = r->h->ActiveMenu; Window unused_root, unused_child; int unused_root_x, unused_root_y; unsigned int unused_mask; if (ActiveMenu == NULL) return 0; XQueryPointer(r->Xdisplay, ActiveMenu->win, &unused_root, &unused_child, &unused_root_x, &unused_root_y, &(ev->x), &(ev->y), &unused_mask); if (ActiveMenu->parent != NULL && (ev->x < 0 || ev->y < 0)) { rxvt_menu_hide(r); return 1; }/* determine the menu item corresponding to the Y index */ y = SHADOW; if (ev->x >= 0 && ev->x <= (ActiveMenu->w - SHADOW)) { for (item = ActiveMenu->head; item != NULL; item = item->next) { int h = HEIGHT_TEXT + 2 * SHADOW; if (isSeparator(item->name)) h = HEIGHT_SEPARATOR; else if (ev->y >= y && ev->y < (y + h)) break; y += h; } } if (item == NULL && ev->type == ButtonRelease) { rxvt_menu_hide_all(r); return 0; } thisitem = item; this_y = y - SHADOW;/* erase the last item */ if (ActiveMenu->item != NULL) { if (ActiveMenu->item != thisitem) { for (y = 0, item = ActiveMenu->head; item != NULL; item = item->next) { int h; if (isSeparator(item->name)) h = HEIGHT_SEPARATOR; else if (item == ActiveMenu->item) { /* erase old menuitem */ rxvt_drawbox_menuitem(r, y, 0); /* No Shadow */ if (item->entry.type == MenuSubMenu) rxvt_drawtriangle(r, ActiveMenu->w, y, +1); break; } else h = HEIGHT_TEXT + 2 * SHADOW; y += h; } } else { switch (ev->type) { case ButtonRelease: switch (item->entry.type) { case MenuLabel: case MenuSubMenu: rxvt_menu_hide_all(r); break; case MenuAction: case MenuTerminalAction: rxvt_drawbox_menuitem(r, this_y, -1); {#ifdef HAVE_NANOSLEEP struct timespec rqt; rqt.tv_sec = 0; rqt.tv_nsec = MENU_DELAY_USEC * 1000; nanosleep(&rqt, NULL);#else /* use select for timing */ struct timeval tv; tv.tv_sec = 0; tv.tv_usec = MENU_DELAY_USEC; select(0, NULL, NULL, NULL, &tv);#endif } /* remove menu before sending keys to the application */ rxvt_menu_hide_all(r);#ifndef DEBUG_MENU rxvt_action_dispatch(r, &(item->entry.action));#else /* DEBUG_MENU */ fprintf(stderr, "%s: %s\n", item->name, item->entry.action.str);#endif /* DEBUG_MENU */ break; } break; default: if (item->entry.type == MenuSubMenu) goto DoMenu; break; } return 0; } } DoMenu: ActiveMenu->item = thisitem; y = this_y; if (thisitem != NULL) { item = ActiveMenu->item; if (item->entry.type != MenuLabel) rxvt_drawbox_menuitem(r, y, +1); if (item->entry.type == MenuSubMenu) { int x; rxvt_drawtriangle(r, ActiveMenu->w, y, -1); x = ev->x + (ActiveMenu->parent ? ActiveMenu->x : Width2Pixel(ActiveMenu->x)); if (x >= item->entry.submenu.menu->x) { r->h->ActiveMenu = item->entry.submenu.menu; rxvt_menu_show(r); return 1; } } } return 0;}/* INTPROTO */voidrxvt_menubar_select(rxvt_t *r, XButtonEvent *ev){ menu_t *menu = NULL;/* determine the pulldown menu corresponding to the X index */ if (ev->y >= 0 && ev->y <= menuBar_height() && r->h->CurrentBar != NULL) { for (menu = r->h->CurrentBar->head; menu != NULL; menu = menu->next) { int x = Width2Pixel(menu->x); int w = Width2Pixel(menu->len + HSPACE); if ((ev->x >= x && ev->x < x + w)) break; } } switch (ev->type) { case ButtonRelease: rxvt_menu_hide_all(r); break; case ButtonPress: if (menu == NULL && r->h->Arrows_x && ev->x >= r->h->Arrows_x) { int i; for (i = 0; i < NARROWS; i++) { if (ev->x >= (r->h->Arrows_x + (Width2Pixel(4 * i + i)) / 4) && ev->x < (r->h->Arrows_x + (Width2Pixel(4 * i + i + 4)) / 4)) { rxvt_draw_Arrows(r, Arrows[i].name, -1); {#ifdef HAVE_NANOSLEEP struct timespec rqt; rqt.tv_sec = 0; rqt.tv_nsec = MENU_DELAY_USEC * 1000; nanosleep(&rqt, NULL);#else /* use select for timing */ struct timeval tv; tv.tv_sec = 0; tv.tv_usec = MENU_DELAY_USEC; select(0, NULL, NULL, NULL, &tv);#endif } rxvt_draw_Arrows(r, Arrows[i].name, +1);#ifdef DEBUG_MENUARROWS fprintf(stderr, "'%c': ", Arrows[i].name); if (r->h->CurrentBar == NULL || (r->h->CurrentBar->arrows[i].type != MenuAction && r->h->CurrentBar->arrows[i].type != MenuTerminalAction)) { if (Arrows[i].str != NULL && Arrows[i].str[0]) fprintf(stderr, "(default) \\033%s\n", &(Arrows[i].str[2])); } else { fprintf(stderr, "%s\n", r->h->CurrentBar->arrows[i].str); }#else /* DEBUG_MENUARROWS */ if (r->h->CurrentBar == NULL || rxvt_action_dispatch(r, &(r->h->CurrentBar->arrows[i])) ) { if (Arrows[i].str != NULL && Arrows[i].str[0] != 0) rxvt_tt_write(r, (Arrows[i].str + 1), Arrows[i].str[0]); }#endif /* DEBUG_MENUARROWS */ return; } } } /* FALLTHROUGH */ default: /* * press menubar or move to a new entry */ if (menu != NULL && menu != r->h->ActiveMenu) { rxvt_menu_hide_all(r); /* pop down old menu */ r->h->ActiveMenu = menu; rxvt_menu_show(r); /* pop up new menu */ } break; }}/* * general dispatch routine, * it would be nice to have `sticky' menus *//* EXTPROTO */voidrxvt_menubar_control(rxvt_t *r, XButtonEvent *ev){ switch (ev->type) { case ButtonPress: if (ev->button == Button1) rxvt_menubar_select(r, ev); break; case ButtonRelease: if (ev->button == Button1) rxvt_menu_select(r, ev); break; case MotionNotify: while (XCheckTypedWindowEvent(r->Xdisplay, r->TermWin.parent[0], 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; }}/* EXTPROTO */voidrxvt_map_menuBar(rxvt_t *r, int map){ if (rxvt_menubar_mapping(r, map)) rxvt_resize_all_windows(r, 0, 0, 0);}#endif/*----------------------- end-of-file (C source) -----------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -