⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 menubar.c

📁 rxvt经典的linux下的终端.小巧实用
💻 C
📖 第 1 页 / 共 4 页
字号:
/*--------------------------------*-C-*---------------------------------* * File:	menubar.c *----------------------------------------------------------------------* * $Id: menubar.c,v 1.56 2002/10/07 14:38:27 gcw 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. *----------------------------------------------------------------------*/#include "../config.h"		/* NECESSARY */#include "rxvt.h"		/* NECESSARY */#ifdef MENUBAR#include "version.h"#include "menubar.h"#include "menubar.intpro"	/* PROTOS for internal routines */#define Menu_PixelWidth(menu)					\    (2 * SHADOW + Width2Pixel ((menu)->width + 3 * HSPACE))static const struct {    const char      name;	/* (l)eft, (u)p, (d)own, (r)ight */    const unsigned char str[5];	/* str[0] = STRLEN (str+1) */} Arrows[NARROWS] = {    { 'l', "\003\033[D" },    { 'u', "\003\033[A" },    { 'd', "\003\033[B" },    { 'r', "\003\033[C" }};/*}}} *//* * find an item called NAME in MENU *//* INTPROTO */menuitem_t     *rxvt_menuitem_find(const menu_t *menu, const char *name){    menuitem_t     *item;#ifdef DEBUG_STRICT    assert(name != NULL);    assert(menu != NULL);#endif/* 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;}/* * unlink ITEM from its MENU and free its memory *//* INTPROTO */voidrxvt_menuitem_free(rxvt_t *r, menu_t *menu, menuitem_t *item){/* disconnect */    menuitem_t     *prev, *next;#ifdef DEBUG_STRICT    assert(menu != NULL);#endif    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:	rxvt_menu_delete(r, item->entry.submenu.menu);	break;    }    if (item->name != NULL)	free(item->name);    if (item->name2 != NULL)	free(item->name2);    free(item);}/* * sort command vs. terminal actions and * remove the first character of STR if it's '\0' *//* INTPROTO */intrxvt_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 = rxvt_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;}/* INTPROTO */intrxvt_action_dispatch(rxvt_t *r, action_t *action){    switch (action->type) {    case MenuTerminalAction:	rxvt_cmd_write(r, action->str, action->len);	break;    case MenuAction:	rxvt_tt_write(r, action->str, action->len);	break;    default:	return -1;	break;    }    return 0;}/* return the arrow index corresponding to NAME *//* INTPROTO */intrxvt_menuarrow_find(char name){    int             i;    for (i = 0; i < NARROWS; i++)	if (name == Arrows[i].name)	    return i;    return -1;}/* free the memory associated with arrow NAME of the current menubar *//* INTPROTO */voidrxvt_menuarrow_free(rxvt_t *r, char name){    int             i;    if (name) {	i = rxvt_menuarrow_find(name);	if (i >= 0) {	    action_t       *act = &(r->h->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++)	    rxvt_menuarrow_free(r, Arrows[i].name);    }}/* INTPROTO */voidrxvt_menuarrow_add(rxvt_t *r, 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 = rxvt_menuarrow_find(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",		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)	    rxvt_menuarrow_free(r, Arrows[i].name);    }    for (i = 0; i < NARROWS; i++) {	unsigned char  *str;	unsigned int    len;	if (!parse[i].len)	    continue;	str = rxvt_malloc(parse[i].len + xtra_len + 1);	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", Arrows[i].name, len, str);#endif	if (rxvt_action_type(&(r->h->CurrentBar->arrows[i]), str) < 0)	    free(str);    }}/* INTPROTO */menuitem_t     *rxvt_menuitem_add(menu_t *menu, const char *name, const char *name2, const char *action){    menuitem_t     *item;    unsigned int    len;#ifdef DEBUG_STRICT    assert(name != NULL);    assert(action != NULL);#endif    if (menu == NULL)	return NULL;    if (isSeparator(name)) {	/* add separator, no action */	name = "";	action = "";    } else {	/*	 * add/replace existing menu item	 */	item = rxvt_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 */    item = (menuitem_t *) rxvt_malloc(sizeof(menuitem_t));    item->len2 = 0;    item->name2 = NULL;    len = STRLEN(name);    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 {	    item->name2 = rxvt_malloc(len + 1);	    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 = rxvt_malloc(len + 1);	STRCPY(str, action);	if (rxvt_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;}/* * search for the base starting menu for NAME. * return a pointer to the portion of NAME that remains *//* INTPROTO */char           *rxvt_menu_find_base(rxvt_t *r, menu_t **menu, char *path){    menu_t         *m = NULL;    menuitem_t     *item;#ifdef DEBUG_STRICT    assert(menu != NULL);    assert(r->h->CurrentBar != NULL);#endif    if (path[0] == '\0')	return path;    if (STRCHR(path, '/') != NULL) {	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 = 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->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;}/* * 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;    bar_t          *CurrentBar = r->h->CurrentBar;#ifdef DEBUG_STRICT    assert(CurrentBar != NULL);#endif/* 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 (CurrentBar->tail == menu)	    CurrentBar->tail = prev;	if (CurrentBar->head == menu)	    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;		rxvt_menuitem_free(r, menu->parent, item);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -