📄 rxvtlib_menubar.c
字号:
#include "rxvtlib.h"/*--------------------------------*-C-*---------------------------------* * File: menubar.c *----------------------------------------------------------------------* * $Id: menubar.c,v 1.27 1999/01/23 14:26:36 mason Exp $ * * Copyright (C) 1997,1998 mj olesen <olesen@me.QueensU.CA> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *----------------------------------------------------------------------* * refer.html (or refer.txt) contains up-to-date documentation. The * summary that appears at the end of this file was taken from there. *----------------------------------------------------------------------*/#ifdef MENUBAR /* okay to alter menu? *//* (l)eft, (u)p, (d)own, (r)ight *//* str[0] = strlen (str+1) */ /* currently active menu */#endif/*}}} */#ifdef MENUBAR/* * find an item called NAME in MENU *//* INTPROTO */menuitem_t *menuitem_find (const menu_t * menu, const char *name){ menuitem_t *item; assert (name != NULL); assert (menu != NULL);/* find the last item in the menu, this is good for separators */ for (item = menu->tail; item != NULL; item = item->prev) { if (item->entry.type == MenuSubMenu) { if (!strcmp (name, (item->entry.submenu.menu)->name)) break; } else if ((isSeparator (name) && isSeparator (item->name)) || !strcmp (name, item->name)) break; } return item;}#endif#ifdef MENUBAR/* * unlink ITEM from its MENU and free its memory *//* INTPROTO */void rxvtlib_menuitem_free (rxvtlib *o, menu_t * menu, menuitem_t * item){/* disconnect */ menuitem_t *prev, *next; assert (menu != NULL); prev = item->prev; next = item->next; if (prev != NULL) prev->next = next; if (next != NULL) next->prev = prev;/* new head, tail */ if (menu->tail == item) menu->tail = prev; if (menu->head == item) menu->head = next; switch (item->entry.type) { case MenuAction: case MenuTerminalAction: FREE (item->entry.action.str); break; case MenuSubMenu: (void)rxvtlib_menu_delete (o, item->entry.submenu.menu); break; } if (item->name != NULL) FREE (item->name); if (item->name2 != NULL) FREE (item->name2); FREE (item);}#endif#ifdef MENUBAR/* * sort command vs. terminal actions and * remove the first character of STR if it's '\0' *//* INTPROTO */int action_type (action_t * action, unsigned char *str){ unsigned int len;#if defined (DEBUG_MENU) || defined (DEBUG_MENUARROWS) len = strlen (str); fprintf (stderr, "(len %d) = %s\n", len, str);#else len = Str_escaped ((char *)str);#endif if (!len) return -1;/* sort command vs. terminal actions */ action->type = MenuAction; if (str[0] == '\0') { /* the functional equivalent: memmove (str, str+1, len); */ unsigned char *dst = (str); unsigned char *src = (str + 1); unsigned char *end = (str + len); while (src <= end) *dst++ = *src++; len--; /* decrement length */ if (str[0] != '\0') action->type = MenuTerminalAction; } action->str = str; action->len = len; return 0;}#endif#ifdef MENUBAR/* INTPROTO */int rxvtlib_action_dispatch (rxvtlib *o, action_t * action){ switch (action->type) { case MenuTerminalAction: rxvtlib_cmd_write (o, action->str, action->len); break; case MenuAction: rxvtlib_tt_write (o, action->str, action->len); break; default: return -1; break; } return 0;}#endif#ifdef MENUBAR/* return the arrow index corresponding to NAME *//* INTPROTO */int rxvtlib_menuarrow_find (rxvtlib *o, char name){ int i; for (i = 0; i < NARROWS; i++) if (name == o->Arrows[i].name) return i; return -1;}#endif#ifdef MENUBAR/* free the memory associated with arrow NAME of the current menubar *//* INTPROTO */void rxvtlib_menuarrow_free (rxvtlib *o, char name){ int i; if (name) { i = rxvtlib_menuarrow_find (o, name); if (i >= 0) { action_t *act = &(o->CurrentBar->arrows[i]); switch (act->type) { case MenuAction: case MenuTerminalAction: FREE (act->str); act->str = NULL; act->len = 0; break; } act->type = MenuLabel; } } else { for (i = 0; i < NARROWS; i++) rxvtlib_menuarrow_free (o, o->Arrows[i].name); }}#endif#ifdef MENUBAR/* INTPROTO */void rxvtlib_menuarrow_add (rxvtlib *o, char *string){ int i; unsigned xtra_len; char *p; struct { char *str; int len; } beg = { NULL, 0} , end = { NULL, 0} , *cur, parse[NARROWS]; MEMSET (parse, 0, sizeof (parse));/* fprintf(stderr, "add arrows = `%s'\n", string); */ for (p = string; p != NULL && *p; string = p) { p = (string + 3); /* fprintf(stderr, "parsing at %s\n", string); */ switch (string[1]) { case 'b': cur = &beg; break; case 'e': cur = &end; break; default: i = rxvtlib_menuarrow_find (o, string[1]); if (i >= 0) cur = &(parse[i]); else continue; /* not found */ break; } string = p; cur->str = string; cur->len = 0; if (cur == &end) { p = strchr (string, '\0'); } else { char *next = string; while (1) { p = strchr (next, '<'); if (p != NULL) { if (p[1] && p[2] == '>') break; /* parsed */ } else { if (beg.str == NULL) /* no end needed */ p = strchr (next, '\0'); break; } next = (p + 1); } } if (p == NULL) return; cur->len = (p - string); }#ifdef DEBUG_MENUARROWS cur = &beg; fprintf (stderr, "<b>(len %d) = %.*s\n", cur->len, cur->len, (cur->str ? cur->str : "")); for (i = 0; i < NARROWS; i++) { cur = &(parse[i]); fprintf (stderr, "<%c>(len %d) = %.*s\n", o->Arrows[i].name, cur->len, cur->len, (cur->str ? cur->str : "")); } cur = &end; fprintf (stderr, "<e>(len %d) = %.*s\n", cur->len, cur->len, (cur->str ? cur->str : ""));#endif xtra_len = (beg.len + end.len); for (i = 0; i < NARROWS; i++) { if (xtra_len || parse[i].len) rxvtlib_menuarrow_free (o, o->Arrows[i].name); } for (i = 0; i < NARROWS; i++) { unsigned char *str; unsigned int len; if (!parse[i].len) continue; str = MALLOC (parse[i].len + xtra_len + 1); if (str == NULL) continue; len = 0; if (beg.len) { STRNCPY (str + len, beg.str, beg.len); len += beg.len; } STRNCPY (str + len, parse[i].str, parse[i].len); len += parse[i].len; if (end.len) { STRNCPY (str + len, end.str, end.len); len += end.len; } str[len] = '\0';#ifdef DEBUG_MENUARROWS fprintf (stderr, "<%c>(len %d) = %s\n", o->Arrows[i].name, len, str);#endif if (action_type (&(o->CurrentBar->arrows[i]), str) < 0) FREE (str); }}#endif#ifdef MENUBAR/* INTPROTO */menuitem_t *rxvtlib_menuitem_add (rxvtlib *o, menu_t * menu, const char *name, const char *name2, const char *action){ menuitem_t *item; unsigned int len; assert (name != NULL); assert (action != NULL); if (menu == NULL) return NULL; if (isSeparator (name)) { /* add separator, no action */ name = ""; action = ""; } else { /* * add/replace existing menu item */ item = menuitem_find (menu, name); if (item != NULL) { if (item->name2 != NULL && name2 != NULL) { FREE (item->name2); item->len2 = 0; item->name2 = NULL; } switch (item->entry.type) { case MenuAction: case MenuTerminalAction: FREE (item->entry.action.str); item->entry.action.str = NULL; break; } goto Item_Found; } }/* allocate a new itemect */ if ((item = (menuitem_t *) MALLOC (sizeof (menuitem_t))) == NULL) return NULL; item->len2 = 0; item->name2 = NULL; len = strlen (name); item->name = MALLOC (len + 1); if (item->name != NULL) { STRCPY (item->name, name); if (name[0] == '.' && name[1] != '.') len = 0; /* hidden menu name */ } else { FREE (item); return NULL; } 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 = MALLOC (len + 1)) == NULL) { len = 0; item->name2 = NULL; } else { STRCPY (item->name2, name2); } item->len2 = len; } item->entry.type = MenuLabel; len = strlen (action); if (len == 0 && item->name2 != NULL) { action = item->name2; len = item->len2; } if (len) { unsigned char *str = MALLOC (len + 1); if (str == NULL) { rxvtlib_menuitem_free (o, menu, item); return NULL; } STRCPY (str, action); if (action_type (&(item->entry.action), str) < 0) FREE (str); }/* new item and a possible increase in width */ if (menu->width < (item->len + item->len2)) menu->width = (item->len + item->len2); return item;}#endif#ifdef MENUBAR/* * search for the base starting menu for NAME. * return a pointer to the portion of NAME that remains *//* INTPROTO */char *rxvtlib_menu_find_base (rxvtlib *o, menu_t ** menu, char *path){ menu_t *m = NULL; menuitem_t *item; assert (menu != NULL); assert (o->CurrentBar != NULL); if (path[0] == '\0') return path; if (strchr (path, '/') != NULL) { register char *p = path; while ((p = strchr (p, '/')) != NULL) { p++; if (*p == '/') path = p; } if (path[0] == '/') { path++; *menu = NULL; } while ((p = 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 = rxvtlib_menu_find_base (o, 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 = o->CurrentBar->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.type == MenuSubMenu && !strcmp (path, (item->entry.submenu.menu)->name)) { m = (item->entry.submenu.menu); break; } } } if (m != NULL) { *menu = m; path += strlen (path); } return path;}#endif#ifdef MENUBAR/* * delete this entire menu *//* INTPROTO */menu_t *rxvtlib_menu_delete (rxvtlib *o, menu_t * menu){ menu_t *parent = NULL, *prev, *next; menuitem_t *item; assert (o->CurrentBar != NULL);/* 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;/* fix the index */ if (parent == NULL) { const int len = (menu->len + HSPACE); if (o->CurrentBar->tail == menu) o->CurrentBar->tail = prev; if (o->CurrentBar->head == menu) o->CurrentBar->head = next; for (next = menu->next; next != NULL; next = next->next) next->x -= len; } else { for (item = parent->tail; item != NULL; item = item->prev) { if (item->entry.type == MenuSubMenu && item->entry.submenu.menu == menu) { item->entry.submenu.menu = NULL; rxvtlib_menuitem_free (o, menu->parent, item); break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -