"Just mail it to the fvwm mailing list, is the best way I guess." Hm.
Enclosed is a patch to fvwm-2.0.45 that will allow a set of menus to be
established, and then modified afterwards, by adding functions
"AddAboveInMenu", "ReplaceInMenu", and "DeleteFromMenu" to complement the
existing "AddToMenu" function.
This is useful at my lab, because we are trying to modularize our standard
user config; we want to be able to allow the users to change whatever
they like of their environment, while the admin staff is still able to
change the defaults and be sure that no one is inadvertently left out.
This is pretty easy in the case of shells and so forth, since each
variable can be overwritten individually. Fvwm2 accommodates changes to
the Styles pretty well even without this patch---but as for menus, users
can only add to the end, and if they want to make minor changes to one of
the other items, well, they have to inline the whole menu, or worse, the
whole config.
I'd appreciate any feedback from fvwm's maintainers (or anyone who knows
what they're talking about, for that matter). Thanks,
-------------------------------------------------------------------------
Konrad Schroder
http://www.hitl.washington.edu/people/perseant/
System Administrator perseant_at_hitl.washington.edu
Human Interface Technology Lab Voice: (206) 616-1478
Box 352142, University of Washington, 98195, USA FAX: (206) 543-5380
*** fvwm/builtins.c.dist Wed Jan 22 05:37:28 1997
--- fvwm/builtins.c Fri Sep 05 14:09:14 1997
***************
*** 468,471 ****
--- 468,570 ----
#endif
char *last_menu = NULL;
+ char *last_menu_arg = NULL;
+ int last_menu_flag = MA_NORMAL;
+
+
+ void delete_item_from_menu(XEvent *eventp, Window w, FvwmWindow *tmp_win,
+ unsigned long context, char *action, int *Module)
+ {
+ MenuRoot *mr;
+
+ char *token, *rest,*item;
+ char *flag, *arg;
+
+ #ifdef USEDECOR
+ last_decor = NULL;
+ #endif
+ if(last_menu != NULL)
+ free(last_menu);
+ last_menu = NULL;
+
+ rest = GetNextToken(action,&token);
+ mr = FindPopup(token);
+ rest = GetNextToken(rest,&item);
+
+ if(mr)
+ {
+ DeleteFromMenu(mr,item);
+ MakeMenu(mr);
+ }
+ free(item);
+ }
+
+ /* This is the same as below, but controls placement too */
+ void add_item_above_in_menu(XEvent *eventp, Window w, FvwmWindow *tmp_win,
+ unsigned long context, char *action, int *Module)
+ {
+ MenuRoot *mr;
+
+ char *token, *rest,*item;
+ char *flag, *arg;
+
+ #ifdef USEDECOR
+ last_decor = NULL;
+ #endif
+
+ rest = GetNextToken(action,&token);
+ mr = FindPopup(token);
+ if(mr == NULL)
+ mr = NewMenuRoot(token, 0);
+ if(last_menu != NULL)
+ free(last_menu);
+ last_menu = token;
+
+ rest = GetNextToken(rest,&arg); /* the reference item */
+
+ rest = GetNextToken(rest,&item); /* now the new item */
+
+ last_menu_arg = arg;
+ last_menu_flag = MA_ABOVE;
+
+ AddToMenu(mr, item, rest, MA_ABOVE, arg);
+ free(item);
+
+ MakeMenu(mr);
+ return;
+ }
+
+ void replace_item_in_menu(XEvent *eventp,Window w,FvwmWindow *tmp_win,
+ unsigned long context,
+ char *action, int *Module)
+ {
+ MenuRoot *mr;
+
+ char *token, *rest,*item;
+ char *flag, *arg;
+
+ #ifdef USEDECOR
+ last_decor = NULL;
+ #endif
+ last_menu = NULL;
+ last_menu_arg = NULL;
+ last_menu_flag = MA_NORMAL;
+
+ rest = GetNextToken(action,&token);
+ mr = FindPopup(token);
+ if(mr == NULL)
+ mr = NewMenuRoot(token, 0);
+ if(last_menu != NULL)
+ free(last_menu);
+
+ rest = GetNextToken(rest,&arg); /* the reference item */
+ rest = GetNextToken(rest,&item); /* now the new item */
+
+ AddToMenu(mr, item, rest, MA_REPLACE, arg);
+ free(item);
+
+ MakeMenu(mr);
+ return;
+ }
+
void add_item_to_menu(XEvent *eventp,Window w,FvwmWindow *tmp_win,
unsigned long context,
***************
*** 475,478 ****
--- 574,579 ----
char *token, *rest,*item;
+ char *flag, *arg;
+ int i_flag = MA_NORMAL, i;
#ifdef USEDECOR
***************
*** 487,493 ****
free(last_menu);
last_menu = token;
rest = GetNextToken(rest,&item);
! AddToMenu(mr, item,rest);
free(item);
--- 588,597 ----
free(last_menu);
last_menu = token;
+ last_menu_arg = NULL;
+ last_menu_flag = MA_NORMAL;
+
rest = GetNextToken(rest,&item);
! AddToMenu(mr, item, rest, MA_NORMAL, NULL);
free(item);
***************
*** 517,521 ****
rest = GetNextToken(action,&item);
! AddToMenu(mr, item,rest);
free(item);
--- 621,625 ----
rest = GetNextToken(action,&item);
! AddToMenu(mr, item, rest, last_menu_flag, last_menu_arg);
free(item);
***************
*** 549,553 ****
rest = GetNextToken(action,&item);
! AddToMenu(mr, item,rest);
free(item);
--- 653,657 ----
rest = GetNextToken(action,&item);
! AddToMenu(mr, item, rest, last_menu_flag, last_menu_arg);
free(item);
***************
*** 591,595 ****
rest = GetNextToken(rest,&item);
! AddToMenu(mr, item,rest);
free(item);
--- 695,699 ----
rest = GetNextToken(rest,&item);
! AddToMenu(mr, item, rest, MA_NORMAL, NULL);
free(item);
*** fvwm/functions.c.dist Fri Sep 05 13:16:50 1997
--- fvwm/functions.c Fri Sep 05 14:15:08 1997
***************
*** 36,39 ****
--- 36,40 ----
struct functions func_config[] =
{
+ {"AddAboveInMenu",add_item_above_in_menu, F_ADDMENU_ABOVE, FUNC_NO_WINDOW},
#ifdef MULTISTYLE
{"AddButtonStyle",AddButtonStyle, F_ADD_BUTTON_STYLE, FUNC_NO_WINDOW},
***************
*** 68,71 ****
--- 69,73 ----
#endif
{"DestroyFunc", destroy_menu, F_DESTROY_MENU, FUNC_NO_WINDOW},
+ {"DestroyMenuItem", delete_item_from_menu, F_DELMITEM, FUNC_NO_WINDOW},
{"DestroyMenu", destroy_menu, F_DESTROY_MENU, FUNC_NO_WINDOW},
{"DestroyModuleConfig", DestroyModConfig, F_DESTROY_MOD, FUNC_NO_WINDOW},
***************
*** 112,115 ****
--- 114,118 ----
{"Refresh", refresh_function, F_REFRESH, FUNC_NO_WINDOW},
{"RefreshWindow",refresh_win_function, F_REFRESH, FUNC_NEEDS_WINDOW},
+ {"ReplaceInMenu",replace_item_in_menu, F_REPLACEMENU, FUNC_NO_WINDOW},
{"Resize", resize_window, F_RESIZE, FUNC_NEEDS_WINDOW},
{"Restart", restart_function, F_RESTART, FUNC_NO_WINDOW},
*** fvwm/menus.c.dist Thu Sep 04 12:08:52 1997
--- fvwm/menus.c Fri Sep 05 13:02:24 1997
***************
*** 876,880 ****
--- 876,893 ----
+ MenuItem *DestroyMenuItem(MenuItem *mi)
+ {
+ MenuItem *tmp2 = mi->next;
+ if (mi->item != NULL) free(mi->item);
+ if (mi->item2 != NULL) free(mi->item2);
+ if (mi->action != NULL) free(mi->action);
+ if(mi->picture)
+ DestroyPicture(dpy,mi->picture);
+ if(mi->lpicture)
+ DestroyPicture(dpy,mi->lpicture);
+ free(mi);
+ return tmp2;
+ }
void DestroyMenu(MenuRoot *mr)
***************
*** 908,921 ****
while(mi != NULL)
{
! tmp2 = mi->next;
! if (mi->item != NULL) free(mi->item);
! if (mi->item2 != NULL) free(mi->item2);
! if (mi->action != NULL) free(mi->action);
! if(mi->picture)
! DestroyPicture(dpy,mi->picture);
! if(mi->lpicture)
! DestroyPicture(dpy,mi->lpicture);
! free(mi);
! mi = tmp2;
}
free(mr);
--- 921,925 ----
while(mi != NULL)
{
! mi = DestroyMenuItem(mi);
}
free(mr);
***************
*** 1167,1171 ****
--- 1171,1252 ----
+ /*
+ * GetReferenceMenuItem - get a reference menu item to delete, or add after.
+ */
+ MenuItem *GetReferenceMenuItem(MenuRoot *menu, char *ref)
+ {
+ MenuItem *mi_ref;
+
+ if(ref==NULL || ref[0]=='\0')
+ mi_ref = menu->first;
+ else
+ {
+ if(menu->first == NULL)
+ mi_ref = NULL;
+ else
+ {
+ for(mi_ref=menu->first; mi_ref; mi_ref = mi_ref->next)
+ {
+ if(mi_ref->item && strcasecmp(mi_ref->item,ref)==0)
+ break;
+ }
+ if(mi_ref==NULL)
+ {
+ /* try again with item2 */
+ for(mi_ref=menu->first; mi_ref; mi_ref = mi_ref->next)
+ {
+ if(mi_ref->item2 && strcasecmp(mi_ref->item2,ref)==0)
+ break;
+ }
+ }
+ if(mi_ref==NULL)
+ {
+ /* now we're desperate...try partial matches */
+ for(mi_ref=menu->first; mi_ref; mi_ref = mi_ref->next)
+ {
+ if((mi_ref->item
+ && strncasecmp(mi_ref->item,ref,strlen(ref))==0)
+ || (mi_ref->item2
+ && strncasecmp(mi_ref->item2,ref,strlen(ref))==0))
+ break;
+ }
+ }
+ }
+ }
+ return mi_ref;
+ }
+
+ /*
+ * DeleteFromMenu - delete an item from a menu
+ */
+
+ void DeleteFromMenu(MenuRoot *menu, char *item)
+ {
+ MenuItem *delenda, *t;
+
+ delenda = GetReferenceMenuItem(menu,item);
+ if(delenda)
+ {
+ /* detach */
+ if(delenda->prev)
+ delenda->prev->next = delenda->next;
+ else
+ menu->first = delenda->next;
+ if(delenda->next)
+ delenda->next->prev = delenda->prev;
+ else
+ menu->last = delenda->prev;
+
+ /* destroy */
+ DestroyMenuItem(delenda);
+
+ /* clean up numbering */
+ menu->items=0;
+ for(t=menu->first; t; t=t->next)
+ t->item_num = menu->items++;
+ }
+ }
+
/***********************************************************************
*
***************
*** 1181,1184 ****
--- 1262,1267 ----
* action - the string to possibly execute
* func - the numeric function
+ * (ks) how - additional flags to control placement
+ * (ks) ref - menu item relative to which placement is done
*
* ckh - need to add boolean to say whether or not to expand for pixmaps,
***************
*** 1186,1193 ****
*
***********************************************************************/
! void AddToMenu(MenuRoot *menu, char *item, char *action)
{
! MenuItem *tmp;
char *start,*end;
if(item == NULL)
--- 1269,1277 ----
*
***********************************************************************/
! void AddToMenu(MenuRoot *menu, char *item, char *action, int how, char *ref)
{
! MenuItem *tmp, *mi_ref, *t;
char *start,*end;
+ int i;
if(item == NULL)
***************
*** 1195,1209 ****
tmp = (MenuItem *)safemalloc(sizeof(MenuItem));
! if (menu->first == NULL)
! {
! menu->first = tmp;
! tmp->prev = NULL;
! }
! else
! {
! menu->last->next = tmp;
! tmp->prev = menu->last;
! }
! menu->last = tmp;
tmp->picture=NULL;
tmp->lpicture=NULL;
--- 1279,1337 ----
tmp = (MenuItem *)safemalloc(sizeof(MenuItem));
!
! /* If we need a reference, get one here. NULL means none was available */
! if(how!=MA_NORMAL)
! {
! mi_ref = GetReferenceMenuItem(menu,ref);
! }
!
! switch(how)
! {
! /* all of these cases fall through to the standard case, if */
! /* no reference menu item could be found */
! case MA_REPLACE:
! if(mi_ref)
! {
! tmp->prev = mi_ref->prev;
! tmp->next = mi_ref->next;
! if(tmp->prev)
! tmp->prev->next = tmp;
! else
! menu->first = tmp;
! if(tmp->next)
! tmp->next->prev = tmp;
! else
! menu->last = tmp;
! DestroyMenuItem(mi_ref);
! break;
! }
! case MA_ABOVE:
! if(mi_ref)
! {
! tmp->next = mi_ref;
! tmp->prev = mi_ref->prev;
! mi_ref->prev = tmp;
! if(tmp->prev)
! tmp->prev->next = tmp;
! else
! menu->first = tmp;
! break;
! }
! case MA_NORMAL:
! default:
! if (menu->first == NULL)
! {
! menu->first = tmp;
! tmp->prev = NULL;
! }
! else
! {
! menu->last->next = tmp;
! tmp->prev = menu->last;
! }
! menu->last = tmp;
! break;
! }
!
tmp->picture=NULL;
tmp->lpicture=NULL;
***************
*** 1258,1265 ****
tmp->action = stripcpy(action);
- tmp->next = NULL;
tmp->state = 0;
tmp->func_type = find_func_type(tmp->action);
! tmp->item_num = menu->items++;
}
--- 1386,1401 ----
tmp->action = stripcpy(action);
tmp->state = 0;
tmp->func_type = find_func_type(tmp->action);
! if(how == MA_NORMAL)
! {
! tmp->next = NULL;
! tmp->item_num = menu->items++;
! }
! else
! for(menu->items=0, tmp=menu->first; tmp; tmp=tmp->next)
! {
! tmp->item_num = menu->items++;
! }
}
*** fvwm/menus.h.dist Thu Sep 04 12:45:19 1997
--- fvwm/menus.h Thu Sep 04 12:47:09 1997
***************
*** 54,57 ****
--- 54,62 ----
#include "../libs/fvwmlib.h"
+ #define MA_NORMAL 0
+ #define MA_ABOVE 1
+ #define MA_BENEATH 2
+ #define MA_REPLACE 3
+
typedef struct MenuItem
{
*** fvwm/misc.h.dist Thu Sep 04 13:41:18 1997
--- fvwm/misc.h Fri Sep 05 14:17:11 1997
***************
*** 224,228 ****
extern void UngrabEm(void);
extern MenuRoot *NewMenuRoot(char *name, int function_or_popup);
! extern void AddToMenu(MenuRoot *, char *, char *);
extern void MakeMenu(MenuRoot *);
extern void CaptureAllWindows(void);
--- 224,228 ----
extern void UngrabEm(void);
extern MenuRoot *NewMenuRoot(char *name, int function_or_popup);
! extern void AddToMenu(MenuRoot *, char *, char *, int, char *);
extern void MakeMenu(MenuRoot *);
extern void CaptureAllWindows(void);
***************
*** 468,472 ****
--- 468,481 ----
void GetMenuXPMFile(char *name, MenuItem *it);
void GetMenuBitmapFile(char *name, MenuItem *it);
+ void delete_item_from_menu(XEvent *eventp,Window w,FvwmWindow *tmp_win,
+ unsigned long context,
+ char *action, int *Module);
+ void add_item_above_in_menu(XEvent *eventp,Window w,FvwmWindow *tmp_win,
+ unsigned long context,
+ char *action, int *Module);
void add_item_to_menu(XEvent *eventp,Window w,FvwmWindow *tmp_win,
+ unsigned long context,
+ char *action, int *Module);
+ void replace_item_in_menu(XEvent *eventp,Window w,FvwmWindow *tmp_win,
unsigned long context,
char *action, int *Module);
*** fvwm/parse.h.dist Fri Sep 05 13:16:33 1997
--- fvwm/parse.h Fri Sep 05 14:06:30 1997
***************
*** 74,77 ****
--- 74,82 ----
#define F_TITLESTYLE 56
#define F_EXEC_SETUP 57
+
+ #define F_ADDMENU_ABOVE 58
+ #define F_DELMITEM 59
+ #define F_REPLACEMENU 60
+
/* Functions which require a target window */
#define F_RESIZE 100
*** fvwm/windows.c.dist Thu Sep 04 13:33:13 1997
--- fvwm/windows.c Thu Sep 04 13:34:04 1997
***************
*** 135,139 ****
}
mr=NewMenuRoot(tlabel,0);
! AddToMenu(mr, tlabel, "TITLE");
next_desk = 0;
--- 135,139 ----
}
mr=NewMenuRoot(tlabel,0);
! AddToMenu(mr, tlabel, "TITLE", MA_NORMAL, NULL);
next_desk = 0;
***************
*** 227,231 ****
else
sprintf(tlabel,"WindowListFunc %ld",t->w);
! AddToMenu(mr, t_hot, tlabel);
#ifdef MINI_ICONS
/* Add the title pixmap */
--- 227,231 ----
else
sprintf(tlabel,"WindowListFunc %ld",t->w);
! AddToMenu(mr, t_hot, tlabel, MA_NORMAL, NULL);
#ifdef MINI_ICONS
/* Add the title pixmap */
--
Visit the official FVWM web page at <URL:http://www.hpc.uh.edu/fvwm/>.
To unsubscribe from the list, send "unsubscribe fvwm" in the body of a
message to majordomo_at_hpc.uh.edu.
To report problems, send mail to fvwm-owner_at_hpc.uh.edu.
Received on Fri Sep 05 1997 - 20:00:55 BST