📄 rxvtlib_menubar.c
字号:
}/* give menubar this name */ STRNCPY (o->CurrentBar->name, name, MAXNAME); o->CurrentBar->name[MAXNAME - 1] = '\0'; return ret;}#endif#ifdef MENUBAR/* switch to a menu called NAME and remove it *//* INTPROTO */void rxvtlib_menubar_remove (rxvtlib *o, const char *name){ bar_t *bar; if ((bar = rxvtlib_menubar_find (o, name)) == NULL) return; o->CurrentBar = bar; do { rxvtlib_menubar_clear (o); /* * pop a menubar, clean it up first */ if (o->CurrentBar != NULL) { bar_t *prev = o->CurrentBar->prev; bar_t *next = o->CurrentBar->next; if (prev == next && prev == o->CurrentBar) { /* only 1 left */ prev = NULL; o->Nbars = 0; /* safety */ } else { next->prev = prev; prev->next = next; o->Nbars--; } FREE (o->CurrentBar); o->CurrentBar = prev; } } while (o->CurrentBar && !strcmp (name, "*"));}#endif#ifdef MENUBAR/* INTPROTO */void action_decode (FILE * fp, action_t * act){ unsigned char *str; short len; if (act == NULL || (len = act->len) == 0 || (str = act->str) == NULL) return; if (act->type == MenuTerminalAction) { fprintf (fp, "^@"); /* can strip trailing ^G from XTerm sequence */ if (str[0] == 033 && str[1] == ']' && str[len - 1] == 007) len--; } else if (str[0] == 033) { switch (str[1]) { case '[': case ']': break; case 'x': /* can strip trailing '\r' from M-x sequence */ if (str[len - 1] == '\r') len--; /* FALLTHROUGH */ default: fprintf (fp, "M-"); /* meta prefix */ str++; len--; break; } }/* * control character form is preferred, since backslash-escaping * can be really ugly looking when the backslashes themselves also * have to be escaped to avoid Shell (or whatever scripting * language) interpretation */ while (len > 0) { unsigned char ch = *str++; switch (ch) { case 033: fprintf (fp, "\\E"); break; /* escape */ case '\r': fprintf (fp, "\\r"); break; /* carriage-return */ case '\\': fprintf (fp, "\\\\"); break; /* backslash */ case '^': fprintf (fp, "\\^"); break; /* caret */ case 127: fprintf (fp, "^?"); default: if (ch <= 31) fprintf (fp, "^%c", ('@' + ch)); else if (ch > 127) fprintf (fp, "\\%o", ch); else fprintf (fp, "%c", ch); break; } len--; } fprintf (fp, "\n");}#endif#ifdef MENUBAR/* INTPROTO */void rxvtlib_menu_dump (rxvtlib *o, FILE * fp, menu_t * menu){ menuitem_t *item;/* create a new menu and clear it */ fprintf (fp, (menu->parent ? "./%s/*\n" : "/%s/*\n"), menu->name); for (item = menu->head; item != NULL; item = item->next) { switch (item->entry.type) { case MenuSubMenu: if (item->entry.submenu.menu == NULL) fprintf (fp, "> %s == NULL\n", item->name); else rxvtlib_menu_dump (o, fp, item->entry.submenu.menu); break; case MenuLabel: fprintf (fp, "{%s}\n", (strlen (item->name) ? item->name : "-")); break; case MenuTerminalAction: case MenuAction: fprintf (fp, "{%s}", item->name); if (item->name2 != NULL && strlen (item->name2)) fprintf (fp, "{%s}", item->name2); fprintf (fp, "\t"); action_decode (fp, &(item->entry.action)); break; } } fprintf (fp, (menu->parent ? "../\n" : "/\n\n"));}#endif#ifdef MENUBAR/* INTPROTO */void rxvtlib_menubar_dump (rxvtlib *o, FILE * fp){ bar_t *bar = o->CurrentBar; time_t t; if (bar == NULL || fp == NULL) return; time (&t); fprintf (fp, "# " APL_SUBCLASS " (%s) Pid: %u\n# Date: %s\n\n", o->rs[Rs_name], (unsigned int)getpid (), ctime (&t));/* dump in reverse order */ bar = o->CurrentBar->prev; do { menu_t *menu; int i; fprintf (fp, "[menu:%s]\n", bar->name); if (bar->title != NULL) fprintf (fp, "[title:%s]\n", bar->title); for (i = 0; i < NARROWS; i++) { switch (bar->arrows[i].type) { case MenuTerminalAction: case MenuAction: fprintf (fp, "<%c>", o->Arrows[i].name); action_decode (fp, &(bar->arrows[i])); break; } } fprintf (fp, "\n"); for (menu = bar->head; menu != NULL; menu = menu->next) rxvtlib_menu_dump (o, fp, menu); fprintf (fp, "\n[done:%s]\n\n", bar->name); bar = bar->prev; } while (bar != o->CurrentBar->prev);}#endif#endif /* (MENUBAR_MAX > 1) *//* * 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 */void rxvtlib_menubar_read (rxvtlib *o, const char *filename){#ifdef MENUBAR/* read in a menu from a file */ FILE *fp; char buffer[256]; char *p, *file, *tag = NULL; file = (char *)rxvtlib_File_find (o, filename, ".menu"); if (file == NULL) return; fp = fopen (file, "rb"); FREE (file); if (fp == NULL) return;#if (MENUBAR_MAX > 1)/* semi-colon delimited */ if ((tag = strchr (filename, ';')) != NULL) { tag++; if (*tag == '\0') tag = NULL; }#endif /* (MENUBAR_MAX > 1) */#ifdef DEBUG_MENU fprintf (stderr, "[read:%s]\n", p); if (tag) fprintf (stderr, "looking for [menu:%s]\n", tag);#endif while ((p = fgets (buffer, sizeof (buffer), fp)) != NULL) { int n; if ((n = Str_match (p, "[menu")) != 0) { if (tag) { /* looking for [menu:tag] */ if (p[n] == ':' && p[n + 1] != ']') { n++; n += Str_match (p + n, tag); if (p[n] == ']') {#ifdef DEBUG_MENU fprintf (stderr, "[menu:%s]\n", tag);#endif break; } } } else if (p[n] == ':' || p[n] == ']') break; } }/* found [menu], [menu:???] tag */ while (p != NULL) { int n;#ifdef DEBUG_MENU fprintf (stderr, "read line = %s\n", p);#endif /* looking for [done:tag] or [done:] */ if ((n = Str_match (p, "[done")) != 0) { if (p[n] == ']') { o->menu_readonly = 1; break; } else if (p[n] == ':') { n++; if (p[n] == ']') { o->menu_readonly = 1; break; } else if (tag) { n += Str_match (p + n, tag); if (p[n] == ']') {#ifdef DEBUG_MENU fprintf (stderr, "[done:%s]\n", tag);#endif o->menu_readonly = 1; 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 */ (void)Str_trim (p); if (*p && *p != '#') { o->menu_readonly = 0; /* if case we read another file */ rxvtlib_menubar_dispatch (o, p); } /* get another line */ p = fgets (buffer, sizeof (buffer), fp); } fclose (fp);#endif}/* * user interface for building/deleting and otherwise managing menus *//* EXTPROTO */void rxvtlib_menubar_dispatch (rxvtlib *o, char *str){#ifdef MENUBAR int n, cmd; char *path, *name, *name2; if (menubar_visible () && o->ActiveMenu != NULL) rxvtlib_menubar_expose (o); else o->ActiveMenu = NULL; cmd = *str; switch (cmd) { case '.': case '/': /* absolute & relative path */ case MENUITEM_BEG: /* menuitem */ /* add `+' prefix for these cases */ cmd = '+'; break; case '+': case '-': str++; /* skip cmd character */ break; case '<':#if (MENUBAR_MAX > 1) if (o->CurrentBar == NULL) break;#endif /* (MENUBAR_MAX > 1) */ if (str[1] && str[2] == '>') /* arrow commands */ rxvtlib_menuarrow_add (o, str); break; case '[': /* extended command */ while (str[0] == '[') { char *next = (++str); /* skip leading '[' */ if (str[0] == ':') { /* [:command:] */ do { next++; if ((next = strchr (next, ':')) == NULL) return; /* parse error */ } while (next[1] != ']'); /* remove and skip ':]' */ *next = '\0'; next += 2; } else { if ((next = strchr (next, ']')) == NULL) return; /* parse error */ /* remove and skip ']' */ *next = '\0'; next++; } if (str[0] == ':') { int saved; /* try and dispatch it, regardless of read/write status */ saved = o->menu_readonly; o->menu_readonly = 0; rxvtlib_menubar_dispatch (o, str + 1); o->menu_readonly = saved; } /* these ones don't require menu stacking */ else if (!strcmp (str, "clear")) { rxvtlib_menubar_clear (o); } else if (!strcmp (str, "done") || Str_match (str, "done:")) { o->menu_readonly = 1; } else if (!strcmp (str, "show")) { rxvtlib_map_menuBar (o, 1); o->menu_readonly = 1; } else if (!strcmp (str, "hide")) { rxvtlib_map_menuBar (o, 0); o->menu_readonly = 1; } else if ((n = Str_match (str, "read:")) != 0) { /* read in a menu from a file */ str += n; rxvtlib_menubar_read (o, str); } else if ((n = Str_match (str, "title:")) != 0) { str += n; if (o->CurrentBar != NULL && !o->menu_readonly) { if (*str) { name = REALLOC (o->CurrentBar->title, strlen (str) + 1); if (name != NULL) { STRCPY (name, str); o->CurrentBar->title = name; } rxvtlib_menubar_expose (o); } else { FREE (o->CurrentBar->title); o->CurrentBar->title = NULL; } } } else if ((n = Str_match (str, "pixmap:")) != 0) { str += n; rxvtlib_xterm_seq (o, XTerm_Pixmap, str); }#if (MENUBAR_MAX > 1) else if ((n = Str_match (str, "rm")) != 0) { str += n; switch (str[0]) { case ':': str++; rxvtlib_menubar_remove (o, str); break; case '\0': rxvtlib_menubar_remove (o, str); break; case '*': rxvtlib_menubar_remove (o, str); break; } o->menu_readonly = 1; } else if ((n = Str_match (str, "menu")) != 0) { str += n; switch (str[0]) { case ':': str++; /* add/access menuBar */ if (*str != '\0' && *str != '*') rxvtlib_menubar_push (o, str); break; default: if (o->CurrentBar == NULL) { rxvtlib_menubar_push (o, "default"); } } if (o->CurrentBar != NULL) o->menu_readonly = 0; /* allow menu build commands */ } else if (!strcmp (str, "dump")) { /* dump current menubars to a file */ FILE *fp; /* enough space to hold the results */ char buffer[32]; sprintf (buffer, "/tmp/" APL_SUBCLASS "-%u", (unsigned int)getpid ()); if ((fp = fopen (buffer, "wb")) != NULL) { rxvtlib_xterm_seq (o, XTerm_title, buffer); rxvtlib_menubar_dump (o, fp); fclose (fp); } } else if (!strcmp (str, "next")) { if (o->CurrentBar) { o->CurrentBar = o->CurrentBar->next; o->menu_readonly = 1; } } else if (!strcmp (str, "prev")) { if (o->CurrentBar) { o->CurrentBar = o->CurrentBar->prev; o->menu_readonly = 1; } } else if (!strcmp (str, "swap")) { /* swap the top 2 menus */ if (o->CurrentBar) { bar_t *prev = o->CurrentBar->prev; bar_t *next = o->CurrentBar->next; prev->next = next; next->prev = prev; o->CurrentBar->next = prev; o->CurrentBar->prev = prev->prev; prev->prev->next = o->CurrentBar; prev->prev = o->CurrentBar; o->CurrentBar = prev; o->menu_readonly = 1; } }#endif /* (MENUBAR_MAX > 1) */ str = next; o->BuildMenu = o->ActiveMenu = NULL; rxvtlib_menubar_expose (o);#ifdef DEBUG_MENUBAR_STACKING fprintf (stderr, "menus are read%s\n", o->menu_readonly ? "only" : "/write");#endif } return; break; }#if (MENUBAR_MAX > 1) if (o->CurrentBar == NULL) return; if (o->menu_readonly) {#ifdef DEBUG_MENUBAR_STACKING fprintf (stderr, "menus are read%s\n", o->menu_readonly ? "only" : "/write");#endif return; }#endif /* (MENUBAR_MAX > 1) */ switch (cmd) { case '+': case '-': path = name = str; name2 = NULL; /* parse STR, allow spaces inside (name) */ if (path[0] != '\0') { name = strchr (path, MENUITEM_BEG); str = strchr (path, MENUITEM_END); if (name != NULL || str != NULL) { if (name == NULL || str == NULL || str <= (name + 1) || (name > path && name[-1] != '/')) { print_error ("menu error <%s>\n", path); break; } if (str[1] == MENUITEM_BEG) { name2 = (str + 2); str = strchr (name2, MENUITEM_END); if (str == NULL) { print_error ("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 (*str)) str++; /* skip space */ }#ifdef DEBUG_MENU fprintf (stderr,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -