cleaning the house today
[wmaker-crm.git] / WPrefs.app / Menu.c
blobfd0e204eedfd0fb76d9d5a188eb1f17b8b7c69d2
1 /* Menu.c- menu definition
2 *
3 * WPrefs - Window Maker Preferences Program
4 *
5 * Copyright (c) 2000-2002 Alfredo K. Kojima
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20 * USA.
24 #include "WPrefs.h"
25 #include <assert.h>
26 #include <ctype.h>
28 #include <X11/keysym.h>
29 #include <X11/cursorfont.h>
32 #include "editmenu.h"
35 typedef enum {
36 NoInfo,
37 ExecInfo,
38 CommandInfo,
39 ExternalInfo,
40 PipeInfo,
41 DirectoryInfo,
42 WSMenuInfo,
43 WWindowListInfo,
44 LastInfo
45 } InfoType;
47 #define MAX_SECTION_SIZE 4
49 typedef struct _Panel {
50 WMBox *box;
51 char *sectionName;
53 char *description;
55 CallbackRec callbacks;
56 WMWidget *parent;
59 WMFont *boldFont;
60 WMFont *normalFont;
61 WMColor *white;
62 WMColor *gray;
63 WMColor *black;
65 WMPixmap *markerPix[LastInfo];
67 WMPopUpButton *typeP;
69 WMWidget *itemPad[3];
70 int currentPad;
72 WEditMenu *menu;
73 char *menuPath;
75 WMFrame *optionsF;
77 WMFrame *commandF;
78 WMTextField *commandT; /* command to run */
79 WMButton *xtermC; /* inside xterm? */
81 WMFrame *pathF;
82 WMTextField *pathT;
84 WMFrame *pipeF;
85 WMTextField *pipeT;
86 WMButton *pipeCacheB;
88 WMFrame *dpathF;
89 WMTextField *dpathT;
91 WMFrame *dcommandF;
92 WMTextField *dcommandT;
94 WMButton *dstripB;
96 WMFrame *shortF;
97 WMTextField *shortT;
98 WMButton *sgrabB;
99 WMButton *sclearB;
101 WMList *icommandL;
103 WMFrame *paramF;
104 WMTextField *paramT;
106 WMButton *quickB;
108 Bool dontAsk; /* whether to comfirm submenu remove */
109 Bool dontSave;
111 Bool capturing;
114 /* about the currently selected item */
115 WEditMenuItem *currentItem;
116 InfoType currentType;
117 WMWidget *sections[LastInfo][MAX_SECTION_SIZE];
118 } _Panel;
121 typedef struct {
122 InfoType type;
123 union {
124 struct {
125 int command;
126 char *parameter;
127 char *shortcut;
128 } command;
129 struct {
130 char *command;
131 char *shortcut;
132 } exec;
133 struct {
134 char *path;
135 } external;
136 struct {
137 char *command;
138 unsigned cached:1;
139 } pipe;
140 struct {
141 char *directory;
142 char *command;
143 unsigned stripExt:1;
144 } directory;
145 } param;
146 } ItemData;
150 static char *commandNames[] = {
151 "ARRANGE_ICONS",
152 "HIDE_OTHERS",
153 "SHOW_ALL",
154 "EXIT",
155 "SHUTDOWN",
156 "RESTART",
157 "RESTART",
158 "SAVE_SESSION",
159 "CLEAR_SESSION",
160 "REFRESH",
161 "INFO_PANEL",
162 "LEGAL_PANEL"
167 #define NEW(type) memset(wmalloc(sizeof(type)), 0, sizeof(type))
170 #define ICON_FILE "menus"
174 static void showData(_Panel *panel);
177 static void updateMenuItem(_Panel *panel, WEditMenuItem *item,
178 WMWidget *changedWidget);
180 static void menuItemSelected(struct WEditMenuDelegate *delegate,
181 WEditMenu *menu, WEditMenuItem *item);
183 static void menuItemDeselected(struct WEditMenuDelegate *delegate,
184 WEditMenu *menu, WEditMenuItem *item);
186 static void menuItemCloned(struct WEditMenuDelegate *delegate, WEditMenu *menu,
187 WEditMenuItem *origItem, WEditMenuItem *newItem);
189 static void menuItemEdited(struct WEditMenuDelegate *delegate, WEditMenu *menu,
190 WEditMenuItem *item);
192 static Bool shouldRemoveItem(struct WEditMenuDelegate *delegate,
193 WEditMenu *menu, WEditMenuItem *item);
196 static void freeItemData(ItemData *data);
200 static WEditMenuDelegate menuDelegate = {
201 NULL,
202 menuItemCloned,
203 menuItemEdited,
204 menuItemSelected,
205 menuItemDeselected,
206 shouldRemoveItem
210 static void
211 dataChanged(void *self, WMNotification *notif)
213 _Panel *panel = (_Panel*)self;
214 WEditMenuItem *item = panel->currentItem;
215 WMWidget *w = (WMWidget*)WMGetNotificationObject(notif);
217 updateMenuItem(panel, item, w);
221 static void
222 buttonClicked(WMWidget *w, void *data)
224 _Panel *panel = (_Panel*)data;
225 WEditMenuItem *item = panel->currentItem;
227 updateMenuItem(panel, item, w);
231 static void
232 icommandLClicked(WMWidget *w, void *data)
234 _Panel *panel = (_Panel*)data;
235 int cmd;
237 cmd = WMGetListSelectedItemRow(w);
238 if (cmd == 3 || cmd == 4) {
239 WMMapWidget(panel->quickB);
240 } else {
241 WMUnmapWidget(panel->quickB);
243 if (cmd == 6) {
244 WMMapWidget(panel->paramF);
245 } else {
246 WMUnmapWidget(panel->paramF);
258 static char*
259 captureShortcut(Display *dpy, _Panel *panel)
261 XEvent ev;
262 KeySym ksym;
263 char buffer[64];
264 char *key = NULL;
266 while (panel->capturing) {
267 XAllowEvents(dpy, AsyncKeyboard, CurrentTime);
268 WMNextEvent(dpy, &ev);
269 if (ev.type==KeyPress && ev.xkey.keycode!=0) {
270 ksym = XKeycodeToKeysym(dpy, ev.xkey.keycode, 0);
271 if (!IsModifierKey(ksym)) {
272 key=XKeysymToString(ksym);
273 panel->capturing = 0;
274 break;
277 WMHandleEvent(&ev);
280 if (!key)
281 return NULL;
283 buffer[0] = 0;
285 if (ev.xkey.state & ControlMask) {
286 strcat(buffer, "Control+");
288 if (ev.xkey.state & ShiftMask) {
289 strcat(buffer, "Shift+");
291 if (ev.xkey.state & Mod1Mask) {
292 strcat(buffer, "Mod1+");
294 if (ev.xkey.state & Mod2Mask) {
295 strcat(buffer, "Mod2+");
297 if (ev.xkey.state & Mod3Mask) {
298 strcat(buffer, "Mod3+");
300 if (ev.xkey.state & Mod4Mask) {
301 strcat(buffer, "Mod4+");
303 if (ev.xkey.state & Mod5Mask) {
304 strcat(buffer, "Mod5+");
306 strcat(buffer, key);
308 return wstrdup(buffer);
313 static void
314 sgrabClicked(WMWidget *w, void *data)
316 _Panel *panel = (_Panel*)data;
317 Display *dpy = WMScreenDisplay(WMWidgetScreen(panel->parent));
318 char *shortcut;
321 if (w == panel->sclearB) {
322 WMSetTextFieldText(panel->shortT, "");
323 updateMenuItem(panel, panel->currentItem, panel->shortT);
324 return;
327 if (!panel->capturing) {
328 panel->capturing = 1;
329 WMSetButtonText(w, _("Cancel"));
330 XGrabKeyboard(dpy, WMWidgetXID(panel->parent), True, GrabModeAsync,
331 GrabModeAsync, CurrentTime);
332 shortcut = captureShortcut(dpy, panel);
333 if (shortcut) {
334 WMSetTextFieldText(panel->shortT, shortcut);
335 updateMenuItem(panel, panel->currentItem, panel->shortT);
336 wfree(shortcut);
339 panel->capturing = 0;
340 WMSetButtonText(w, _("Capture"));
341 XUngrabKeyboard(dpy, CurrentTime);
345 static void
346 changedItemPad(WMWidget *w, void *data)
348 _Panel *panel = (_Panel*)data;
349 int padn = WMGetPopUpButtonSelectedItem(w);
351 WMUnmapWidget(panel->itemPad[panel->currentPad]);
352 WMMapWidget(panel->itemPad[padn]);
354 panel->currentPad = padn;
358 static WEditMenu*
359 putNewSubmenu(WEditMenu *menu, char *title)
361 WEditMenu *tmp;
362 WEditMenuItem *item;
364 item = WAddMenuItemWithTitle(menu, title);
366 tmp = WCreateEditMenu(WMWidgetScreen(menu), title);
367 WSetEditMenuAcceptsDrop(tmp, True);
368 WSetEditMenuDelegate(tmp, &menuDelegate);
369 WSetEditMenuSubmenu(menu, item, tmp);
371 return tmp;
375 static ItemData*
376 putNewItem(_Panel *panel, WEditMenu *menu, int type, char *title)
378 WEditMenuItem *item;
379 ItemData *data;
381 item = WAddMenuItemWithTitle(menu, title);
383 data = NEW(ItemData);
384 data->type = type;
385 WSetEditMenuItemData(item, data, (WMCallback*)freeItemData);
386 WSetEditMenuItemImage(item, panel->markerPix[type]);
388 return data;
392 static WEditMenu*
393 makeFactoryMenu(WMWidget *parent, int width)
395 WEditMenu *pad;
397 pad = WCreateEditMenuPad(parent);
398 WMResizeWidget(pad, width, 10);
399 WSetEditMenuMinSize(pad, wmksize(width, 0));
400 WSetEditMenuMaxSize(pad, wmksize(width, 0));
401 WSetEditMenuSelectable(pad, False);
402 WSetEditMenuEditable(pad, False);
403 WSetEditMenuIsFactory(pad, True);
404 WSetEditMenuDelegate(pad, &menuDelegate);
406 return pad;
410 static void
411 createPanel(_Panel *p)
413 _Panel *panel = (_Panel*)p;
414 WMScreen *scr = WMWidgetScreen(panel->parent);
415 WMColor *black = WMBlackColor(scr);
416 WMColor *white = WMWhiteColor(scr);
417 WMColor *gray = WMGrayColor(scr);
418 WMFont *bold = WMBoldSystemFontOfSize(scr, 12);
419 WMFont *font = WMSystemFontOfSize(scr, 12);
420 WMLabel *label;
421 int width;
424 menuDelegate.data = panel;
427 panel->boldFont = bold;
428 panel->normalFont = font;
430 panel->black = black;
431 panel->white = white;
432 panel->gray = gray;
435 Pixmap pix;
436 Display *dpy = WMScreenDisplay(scr);
437 GC gc;
438 WMPixmap *pixm;
440 pixm = WMCreatePixmap(scr, 7, 7, WMScreenDepth(scr), True);
442 pix = WMGetPixmapXID(pixm);
444 XDrawLine(dpy, pix, WMColorGC(black), 0, 3, 6, 3);
445 XDrawLine(dpy, pix, WMColorGC(black), 3, 0, 3, 6);
447 XDrawLine(dpy, pix, WMColorGC(black), 1, 0, 3, 3);
448 XDrawLine(dpy, pix, WMColorGC(black), 1, 6, 3, 3);
449 XDrawLine(dpy, pix, WMColorGC(black), 0, 0, 0, 6);
452 pix = WMGetPixmapMaskXID(pixm);
454 gc = XCreateGC(dpy, pix, 0, NULL);
456 XSetForeground(dpy, gc, 0);
457 XFillRectangle(dpy, pix, gc, 0, 0, 7, 7);
459 XSetForeground(dpy, gc, 1);
460 XDrawLine(dpy, pix, gc, 0, 3, 6, 3);
461 XDrawLine(dpy, pix, gc, 3, 0, 3, 6);
463 panel->markerPix[ExternalInfo] = pixm;
464 panel->markerPix[PipeInfo] = pixm;
465 panel->markerPix[DirectoryInfo] = pixm;
466 panel->markerPix[WSMenuInfo] = pixm;
467 panel->markerPix[WWindowListInfo] = pixm;
469 XFreeGC(dpy, gc);
472 panel->box = WMCreateBox(panel->parent);
473 WMSetViewExpandsToParent(WMWidgetView(panel->box), 2, 2, 2, 2);
475 panel->typeP = WMCreatePopUpButton(panel->box);
476 WMResizeWidget(panel->typeP, 150, 20);
477 WMMoveWidget(panel->typeP, 10, 10);
479 WMAddPopUpButtonItem(panel->typeP, _("New Items"));
480 WMAddPopUpButtonItem(panel->typeP, _("Sample Commands"));
481 WMAddPopUpButtonItem(panel->typeP, _("Sample Submenus"));
483 WMSetPopUpButtonAction(panel->typeP, changedItemPad, panel);
485 WMSetPopUpButtonSelectedItem(panel->typeP, 0);
488 WEditMenu *pad;
489 WEditMenu *smenu;
490 ItemData *data;
492 pad = makeFactoryMenu(panel->box, 150);
493 WMMoveWidget(pad, 10, 40);
495 data = putNewItem(panel, pad, ExecInfo, _("Run Program"));
496 data = putNewItem(panel, pad, CommandInfo, _("Internal Command"));
497 smenu = putNewSubmenu(pad, _("Submenu"));
498 data = putNewItem(panel, pad, ExternalInfo, _("External Submenu"));
499 data = putNewItem(panel, pad, PipeInfo, _("Generated Submenu"));
500 data = putNewItem(panel, pad, DirectoryInfo, _("Directory Contents"));
501 data = putNewItem(panel, pad, WSMenuInfo, _("Workspace Menu"));
502 data = putNewItem(panel, pad, WWindowListInfo, _("Window List Menu"));
504 panel->itemPad[0] = pad;
508 WEditMenu *pad;
509 ItemData *data;
510 WMScrollView *sview;
512 sview = WMCreateScrollView(panel->box);
513 WMResizeWidget(sview, 150, 180);
514 WMMoveWidget(sview, 10, 40);
515 WMSetScrollViewHasVerticalScroller(sview, True);
517 pad = makeFactoryMenu(panel->box, 130);
519 WMSetScrollViewContentView(sview, WMWidgetView(pad));
521 data = putNewItem(panel, pad, ExecInfo, _("XTerm"));
522 data->param.exec.command = "xterm -sb -sl 2000 -bg black -fg white";
524 data = putNewItem(panel, pad, ExecInfo, _("rxvt"));
525 data->param.exec.command = "rxvt";
527 data = putNewItem(panel, pad, ExecInfo, _("ETerm"));
528 data->param.exec.command = "eterm";
530 data = putNewItem(panel, pad, ExecInfo, _("Run..."));
531 data->param.exec.command = _("%a(Run,Type command to run)");
533 data = putNewItem(panel, pad, ExecInfo, _("Netscape"));
534 data->param.exec.command = "netscape";
536 data = putNewItem(panel, pad, ExecInfo, _("gimp"));
537 data->param.exec.command = "gimp";
539 data = putNewItem(panel, pad, ExecInfo, _("epic"));
540 data->param.exec.command = "xterm -e epic";
542 data = putNewItem(panel, pad, ExecInfo, _("ee"));
543 data->param.exec.command = "ee";
545 data = putNewItem(panel, pad, ExecInfo, _("xv"));
546 data->param.exec.command = "xv";
548 data = putNewItem(panel, pad, ExecInfo, _("Acrobat Reader"));
549 data->param.exec.command = "acroread || /usr/local/Acrobat4/bin/acroread";
551 data = putNewItem(panel, pad, ExecInfo, _("ghostview"));
552 data->param.exec.command = "gv";
554 data = putNewItem(panel, pad, CommandInfo, _("Exit Window Maker"));
555 data->param.command.command = 3;
557 WMMapWidget(pad);
559 panel->itemPad[1] = sview;
564 WEditMenu *pad, *smenu;
565 ItemData *data;
566 WMScrollView *sview;
568 sview = WMCreateScrollView(panel->box);
569 WMResizeWidget(sview, 150, 180);
570 WMMoveWidget(sview, 10, 40);
571 WMSetScrollViewHasVerticalScroller(sview, True);
573 pad = makeFactoryMenu(panel->box, 130);
575 WMSetScrollViewContentView(sview, WMWidgetView(pad));
577 data = putNewItem(panel, pad, ExternalInfo, _("Debian Menu"));
578 data->param.pipe.command = "/etc/X11/WindowMaker/menu.hook";
580 data = putNewItem(panel, pad, PipeInfo, _("RedHat Menu"));
581 data->param.pipe.command = "wmconfig --output wmaker";
583 data = putNewItem(panel, pad, PipeInfo, _("Menu Conectiva"));
584 data->param.pipe.command = "wmconfig --output wmaker";
586 data = putNewItem(panel, pad, DirectoryInfo, _("Themes"));
587 data->param.directory.command = "setstyle";
588 data->param.directory.directory = "/usr/share/WindowMaker/Themes /usr/local/share/WindowMaker/Themes $HOME/GNUstep/Library/WindowMaker/Themes";
589 data->param.directory.stripExt = 1;
591 data = putNewItem(panel, pad, DirectoryInfo, _("Bg Images (scale)"));
592 data->param.directory.command = "wmsetbg -u -s";
593 data->param.directory.directory = "/opt/kde2/share/wallpapers /usr/share/WindowMaker/Backgrounds $HOME/GNUstep/Library/WindowMaker/Backgrounds";
594 data->param.directory.stripExt = 1;
596 data = putNewItem(panel, pad, DirectoryInfo, _("Bg Images (tile)"));
597 data->param.directory.command = "wmsetbg -u -t";
598 data->param.directory.directory = "/opt/kde2/share/wallpapers /usr/share/WindowMaker/Backgrounds $HOME/GNUstep/Library/WindowMaker/Backgrounds";
599 data->param.directory.stripExt = 1;
601 smenu = putNewSubmenu(pad, _("Assorted XTerms"));
603 data = putNewItem(panel, smenu, ExecInfo, _("XTerm Yellow on Blue"));
604 data->param.exec.command = "xterm -sb -sl 2000 -bg midnightblue -fg yellow";
606 data = putNewItem(panel, smenu, ExecInfo, _("XTerm White on Black"));
607 data->param.exec.command = "xterm -sb -sl 2000 -bg black -fg white";
609 data = putNewItem(panel, smenu, ExecInfo, _("XTerm Black on White"));
610 data->param.exec.command = "xterm -sb -sl 2000 -bg white -fg black";
612 data = putNewItem(panel, smenu, ExecInfo, _("XTerm Black on Beige"));
613 data->param.exec.command = "xterm -sb -sl 2000 -bg '#bbbb99' -fg black";
615 data = putNewItem(panel, smenu, ExecInfo, _("XTerm White on Green"));
616 data->param.exec.command = "xterm -sb -sl 2000 -bg '#228822' -fg white";
618 data = putNewItem(panel, smenu, ExecInfo, _("XTerm White on Olive"));
619 data->param.exec.command = "xterm -sb -sl 2000 -bg '#335533' -fg white";
621 data = putNewItem(panel, smenu, ExecInfo, _("XTerm Blue on Blue"));
622 data->param.exec.command = "xterm -sb -sl 2000 -bg '#112244' -fg '#88aabb'";
624 data = putNewItem(panel, smenu, ExecInfo, _("XTerm BIG FONTS"));
625 data->param.exec.command = "xterm -sb -sl 2000 -bg black -fg white -fn 10x20";
627 WMMapWidget(pad);
629 panel->itemPad[2] = sview;
633 width = FRAME_WIDTH - 20 - 150 - 10 - 2;
635 panel->optionsF = WMCreateFrame(panel->box);
636 WMResizeWidget(panel->optionsF, width, FRAME_HEIGHT - 15);
637 WMMoveWidget(panel->optionsF, 10 + 150 + 10, 5);
639 width -= 20;
641 /* command */
643 panel->commandF = WMCreateFrame(panel->optionsF);
644 WMResizeWidget(panel->commandF, width, 50);
645 WMMoveWidget(panel->commandF, 10, 20);
646 WMSetFrameTitle(panel->commandF, _("Program to Run"));
648 panel->commandT = WMCreateTextField(panel->commandF);
649 WMResizeWidget(panel->commandT, width - 20, 20);
650 WMMoveWidget(panel->commandT, 10, 20);
652 WMAddNotificationObserver(dataChanged, panel,
653 WMTextDidChangeNotification,
654 panel->commandT);
656 #if 0
657 panel->xtermC = WMCreateSwitchButton(panel->commandF);
658 WMResizeWidget(panel->xtermC, width - 20, 20);
659 WMMoveWidget(panel->xtermC, 10, 50);
660 WMSetButtonText(panel->xtermC, _("Run the program inside a Xterm"));
661 #endif
662 WMMapSubwidgets(panel->commandF);
665 /* path */
667 panel->pathF = WMCreateFrame(panel->optionsF);
668 WMResizeWidget(panel->pathF, width, 150);
669 WMMoveWidget(panel->pathF, 10, 40);
670 WMSetFrameTitle(panel->pathF, _("Path for Menu"));
672 panel->pathT = WMCreateTextField(panel->pathF);
673 WMResizeWidget(panel->pathT, width - 20, 20);
674 WMMoveWidget(panel->pathT, 10, 20);
676 WMAddNotificationObserver(dataChanged, panel,
677 WMTextDidChangeNotification,
678 panel->pathT);
680 label = WMCreateLabel(panel->pathF);
681 WMResizeWidget(label, width - 20, 80);
682 WMMoveWidget(label, 10, 50);
683 WMSetLabelText(label, _("Enter the path for a file containing a menu\n"
684 "or a list of directories with the programs you\n"
685 "want to have listed in the menu. Ex:\n"
686 "~/GNUstep/Library/WindowMaker/menu\n"
687 "or\n"
688 "/usr/X11R6/bin ~/xbin"));
690 WMMapSubwidgets(panel->pathF);
693 /* pipe */
695 panel->pipeF = WMCreateFrame(panel->optionsF);
696 WMResizeWidget(panel->pipeF, width, 150);
697 WMMoveWidget(panel->pipeF, 10, 30);
698 WMSetFrameTitle(panel->pipeF, _("Command"));
700 panel->pipeT = WMCreateTextField(panel->pipeF);
701 WMResizeWidget(panel->pipeT, width - 20, 20);
702 WMMoveWidget(panel->pipeT, 10, 20);
704 WMAddNotificationObserver(dataChanged, panel,
705 WMTextDidChangeNotification,
706 panel->pipeT);
709 label = WMCreateLabel(panel->pipeF);
710 WMResizeWidget(label, width - 20, 40);
711 WMMoveWidget(label, 10, 50);
712 WMSetLabelText(label, _("Enter a command that outputs a menu\n"
713 "definition to stdout when invoked."));
716 panel->pipeCacheB = WMCreateSwitchButton(panel->pipeF);
717 WMResizeWidget(panel->pipeCacheB, width - 20, 40);
718 WMMoveWidget(panel->pipeCacheB, 10, 110);
719 WMSetButtonText(panel->pipeCacheB,
720 _("Cache menu contents after opening for\n"
721 "the first time"));
723 WMMapSubwidgets(panel->pipeF);
726 /* directory menu */
728 panel->dcommandF = WMCreateFrame(panel->optionsF);
729 WMResizeWidget(panel->dcommandF, width, 90);
730 WMMoveWidget(panel->dcommandF, 10, 25);
731 WMSetFrameTitle(panel->dcommandF, _("Command to Open Files"));
733 panel->dcommandT = WMCreateTextField(panel->dcommandF);
734 WMResizeWidget(panel->dcommandT, width - 20, 20);
735 WMMoveWidget(panel->dcommandT, 10, 20);
737 WMAddNotificationObserver(dataChanged, panel,
738 WMTextDidChangeNotification,
739 panel->dcommandT);
742 label = WMCreateLabel(panel->dcommandF);
743 WMResizeWidget(label, width - 20, 45);
744 WMMoveWidget(label, 10, 40);
745 WMSetLabelText(label, _("Enter the command you want to use to open the\n"
746 "files in the directories listed below."));
748 WMMapSubwidgets(panel->dcommandF);
751 panel->dpathF = WMCreateFrame(panel->optionsF);
752 WMResizeWidget(panel->dpathF, width, 80);
753 WMMoveWidget(panel->dpathF, 10, 125);
754 WMSetFrameTitle(panel->dpathF, _("Directories with Files"));
756 panel->dpathT = WMCreateTextField(panel->dpathF);
757 WMResizeWidget(panel->dpathT, width - 20, 20);
758 WMMoveWidget(panel->dpathT, 10, 20);
760 WMAddNotificationObserver(dataChanged, panel,
761 WMTextDidChangeNotification,
762 panel->dpathT);
764 panel->dstripB = WMCreateSwitchButton(panel->dpathF);
765 WMResizeWidget(panel->dstripB, width - 20, 20);
766 WMMoveWidget(panel->dstripB, 10, 50);
767 WMSetButtonText(panel->dstripB, _("Strip extensions from file names"));
769 WMSetButtonAction(panel->dstripB, buttonClicked, panel);
771 WMMapSubwidgets(panel->dpathF);
774 /* shortcut */
776 panel->shortF = WMCreateFrame(panel->optionsF);
777 WMResizeWidget(panel->shortF, width, 50);
778 WMMoveWidget(panel->shortF, 10, 160);
779 WMSetFrameTitle(panel->shortF, _("Keyboard Shortcut"));
781 panel->shortT = WMCreateTextField(panel->shortF);
782 WMResizeWidget(panel->shortT, width - 20 - 170, 20);
783 WMMoveWidget(panel->shortT, 10, 20);
785 WMAddNotificationObserver(dataChanged, panel,
786 WMTextDidChangeNotification,
787 panel->shortT);
789 panel->sgrabB = WMCreateCommandButton(panel->shortF);
790 WMResizeWidget(panel->sgrabB, 80, 24);
791 WMMoveWidget(panel->sgrabB, width - 90, 18);
792 WMSetButtonText(panel->sgrabB, _("Capture"));
793 WMSetButtonAction(panel->sgrabB, sgrabClicked, panel);
795 panel->sclearB = WMCreateCommandButton(panel->shortF);
796 WMResizeWidget(panel->sclearB, 80, 24);
797 WMMoveWidget(panel->sclearB, width - 175, 18);
798 WMSetButtonText(panel->sclearB, _("Clear"));
799 WMSetButtonAction(panel->sclearB, sgrabClicked, panel);
801 WMMapSubwidgets(panel->shortF);
803 /* internal command */
805 panel->icommandL = WMCreateList(panel->optionsF);
806 WMResizeWidget(panel->icommandL, width, 80);
807 WMMoveWidget(panel->icommandL, 10, 20);
809 WMSetListAction(panel->icommandL, icommandLClicked, panel);
811 WMAddNotificationObserver(dataChanged, panel,
812 WMListSelectionDidChangeNotification,
813 panel->icommandL);
815 WMInsertListItem(panel->icommandL, 0, _("Arrange Icons"));
816 WMInsertListItem(panel->icommandL, 1, _("Hide All Windows Except For The Focused One"));
817 WMInsertListItem(panel->icommandL, 2, _("Show All Windows"));
819 WMInsertListItem(panel->icommandL, 3, _("Exit Window Maker"));
820 WMInsertListItem(panel->icommandL, 4, _("Exit X Session"));
821 WMInsertListItem(panel->icommandL, 5, _("Restart Window Maker"));
822 WMInsertListItem(panel->icommandL, 6, _("Start Another Window Manager : ("));
824 WMInsertListItem(panel->icommandL, 7, _("Save Current Session"));
825 WMInsertListItem(panel->icommandL, 8, _("Clear Saved Session"));
826 WMInsertListItem(panel->icommandL, 9, _("Refresh Screen"));
827 WMInsertListItem(panel->icommandL, 10, _("Open Info Panel"));
828 WMInsertListItem(panel->icommandL, 11, _("Open Copyright Panel"));
831 panel->paramF = WMCreateFrame(panel->optionsF);
832 WMResizeWidget(panel->paramF, width, 50);
833 WMMoveWidget(panel->paramF, 10, 105);
834 WMSetFrameTitle(panel->paramF, _("Window Manager to Start"));
836 panel->paramT = WMCreateTextField(panel->paramF);
837 WMResizeWidget(panel->paramT, width - 20, 20);
838 WMMoveWidget(panel->paramT, 10, 20);
840 WMAddNotificationObserver(dataChanged, panel,
841 WMTextDidChangeNotification,
842 panel->paramT);
844 WMMapSubwidgets(panel->paramF);
847 panel->quickB = WMCreateSwitchButton(panel->optionsF);
848 WMResizeWidget(panel->quickB, width, 20);
849 WMMoveWidget(panel->quickB, 10, 120);
850 WMSetButtonText(panel->quickB, _("Do not confirm action."));
851 WMSetButtonAction(panel->quickB, buttonClicked, panel);
856 label = WMCreateLabel(panel->optionsF);
857 WMResizeWidget(label, width - 10, FRAME_HEIGHT - 50);
858 WMMoveWidget(label, 10, 20);
859 WMSetLabelText(label,
860 _("Instructions:\n\n"
861 " - drag items from the left to the menu to add new items\n"
862 " - drag items out of the menu to remove items\n"
863 " - drag items in menu to change their position\n"
864 " - drag items with Control pressed to copy them\n"
865 " - double click in a menu item to change the label\n"
866 " - click on a menu item to change related information"));
867 WMMapWidget(label);
869 WMRealizeWidget(panel->box);
870 WMMapSubwidgets(panel->box);
871 WMMapWidget(panel->box);
875 int i;
876 for (i = 0; i < 3; i++)
877 WMUnmapWidget(panel->itemPad[i]);
879 changedItemPad(panel->typeP, panel);
881 panel->sections[NoInfo][0] = label;
883 panel->sections[ExecInfo][0] = panel->commandF;
884 panel->sections[ExecInfo][1] = panel->shortF;
886 panel->sections[CommandInfo][0] = panel->icommandL;
887 panel->sections[CommandInfo][1] = panel->shortF;
889 panel->sections[ExternalInfo][0] = panel->pathF;
891 panel->sections[PipeInfo][0] = panel->pipeF;
893 panel->sections[DirectoryInfo][0] = panel->dpathF;
894 panel->sections[DirectoryInfo][1] = panel->dcommandF;
896 panel->currentType = NoInfo;
898 showData(panel);
901 WMPoint pos;
903 pos = WMGetViewScreenPosition(WMWidgetView(panel->box));
905 if (pos.x < 200) {
906 pos.x += FRAME_WIDTH + 20;
907 } else {
908 pos.x = 10;
911 pos.y = WMAX(pos.y - 100, 0);
913 if (panel->menu)
914 WEditMenuShowAt(panel->menu, pos.x, pos.y);
921 static void
922 freeItemData(ItemData *data)
924 #define CFREE(d) if (d) wfree(d)
926 /* TODO */
927 switch (data->type) {
928 case CommandInfo:
929 CFREE(data->param.command.parameter);
930 CFREE(data->param.command.shortcut);
931 break;
933 case ExecInfo:
934 CFREE(data->param.exec.command);
935 CFREE(data->param.exec.shortcut);
936 break;
938 case PipeInfo:
939 CFREE(data->param.pipe.command);
940 break;
942 case ExternalInfo:
943 CFREE(data->param.external.path);
944 break;
946 case DirectoryInfo:
947 CFREE(data->param.directory.command);
948 CFREE(data->param.directory.directory);
949 break;
951 default:
952 break;
955 wfree(data);
956 #undef CFREE
960 static ItemData*
961 parseCommand(WMPropList *item)
963 ItemData *data = NEW(ItemData);
964 WMPropList *p;
965 char *command = NULL;
966 char *parameter = NULL;
967 char *shortcut = NULL;
968 int i = 1;
971 p = WMGetFromPLArray(item, i++);
972 command = WMGetFromPLString(p);
973 if (strcmp(command, "SHORTCUT") == 0) {
974 p = WMGetFromPLArray(item, i++);
975 shortcut = WMGetFromPLString(p);
976 p = WMGetFromPLArray(item, i++);
977 command = WMGetFromPLString(p);
979 p = WMGetFromPLArray(item, i++);
980 if (p)
981 parameter = WMGetFromPLString(p);
983 if (strcmp(command, "EXEC") == 0 || strcmp(command, "SHEXEC") == 0) {
985 data->type = ExecInfo;
987 data->param.exec.command = wstrdup(parameter);
988 if (shortcut)
989 data->param.exec.shortcut = wstrdup(shortcut);
991 } else if (strcmp(command, "OPEN_MENU") == 0) {
992 char *p;
994 * dir menu, menu file
995 * dir WITH
996 * |pipe
998 p = parameter;
999 while (isspace(*p) && *p) p++;
1000 if (*p == '|') {
1001 if (*(p+1) == '|') {
1002 p++;
1003 data->param.pipe.cached = 0;
1004 } else {
1005 data->param.pipe.cached = 1;
1007 data->type = PipeInfo;
1008 data->param.pipe.command = wtrimspace(p+1);
1009 } else {
1010 char *s;
1012 p = wstrdup(p);
1014 s = strstr(p, "WITH");
1015 if (s) {
1016 char **tokens;
1017 char **ctokens;
1018 int tokn;
1019 int i, j;
1021 data->type = DirectoryInfo;
1023 *s = '\0';
1024 s += 5;
1025 while (*s && isspace(*s)) s++;
1026 data->param.directory.command = wstrdup(s);
1028 wtokensplit(p, &tokens, &tokn);
1029 wfree(p);
1031 ctokens = wmalloc(sizeof(char*)*tokn);
1033 for (i = 0, j = 0; i < tokn; i++) {
1034 if (strcmp(tokens[i], "-noext") == 0) {
1035 wfree(tokens[i]);
1036 data->param.directory.stripExt = 1;
1037 } else {
1038 ctokens[j++] = tokens[i];
1041 data->param.directory.directory = wtokenjoin(ctokens, j);
1042 wfree(ctokens);
1044 wtokenfree(tokens, tokn);
1045 } else {
1046 data->type = ExternalInfo;
1047 data->param.external.path = p;
1050 } else if (strcmp(command, "WORKSPACE_MENU") == 0) {
1051 data->type = WSMenuInfo;
1052 } else if (strcmp(command, "WINDOWS_MENU") == 0) {
1053 data->type = WWindowListInfo;
1054 } else {
1055 int cmd;
1057 if (strcmp(command, "ARRANGE_ICONS") == 0) {
1058 cmd = 0;
1059 } else if (strcmp(command, "HIDE_OTHERS") == 0) {
1060 cmd = 1;
1061 } else if (strcmp(command, "SHOW_ALL") == 0) {
1062 cmd = 2;
1063 } else if (strcmp(command, "EXIT") == 0) {
1064 cmd = 3;
1065 } else if (strcmp(command, "SHUTDOWN") == 0) {
1066 cmd = 4;
1067 } else if (strcmp(command, "RESTART") == 0) {
1068 if (parameter) {
1069 cmd = 6;
1070 } else {
1071 cmd = 5;
1073 } else if (strcmp(command, "SAVE_SESSION") == 0) {
1074 cmd = 7;
1075 } else if (strcmp(command, "CLEAR_SESSION") == 0) {
1076 cmd = 8;
1077 } else if (strcmp(command, "REFRESH") == 0) {
1078 cmd = 9;
1079 } else if (strcmp(command, "INFO_PANEL") == 0) {
1080 cmd = 10;
1081 } else if (strcmp(command, "LEGAL_PANEL") == 0) {
1082 cmd = 11;
1083 } else {
1084 wwarning(_("unknown command '%s' in menu"), command);
1085 goto error;
1088 data->type = CommandInfo;
1090 data->param.command.command = cmd;
1091 if (shortcut)
1092 data->param.command.shortcut = wstrdup(shortcut);
1093 if (parameter)
1094 data->param.command.parameter = wstrdup(parameter);
1097 return data;
1099 error:
1100 wfree(data);
1102 return NULL;
1108 static void
1109 updateFrameTitle(_Panel *panel, char *title, InfoType type)
1111 if (type != NoInfo) {
1112 char *tmp;
1114 switch (type) {
1115 case ExecInfo:
1116 tmp = wstrconcat(title, _(": Execute Program"));
1117 break;
1119 case CommandInfo:
1120 tmp = wstrconcat(title, _(": Perform Internal Command"));
1121 break;
1123 case ExternalInfo:
1124 tmp = wstrconcat(title, _(": Open a Submenu"));
1125 break;
1127 case PipeInfo:
1128 tmp = wstrconcat(title, _(": Program Generated Submenu"));
1129 break;
1131 case DirectoryInfo:
1132 tmp = wstrconcat(title, _(": Directory Contents Menu"));
1133 break;
1135 case WSMenuInfo:
1136 tmp = wstrconcat(title, _(": Open Workspaces Submenu"));
1137 break;
1139 case WWindowListInfo:
1140 tmp = wstrconcat(title, _(": Open Window List Submenu"));
1141 break;
1143 default:
1144 tmp = NULL;
1145 break;
1147 WMSetFrameTitle(panel->optionsF, tmp);
1148 wfree(tmp);
1149 } else {
1150 WMSetFrameTitle(panel->optionsF, NULL);
1156 static void
1157 changeInfoType(_Panel *panel, char *title, InfoType type)
1159 WMWidget **w;
1161 if (panel->currentType != type) {
1163 w = panel->sections[panel->currentType];
1165 while (*w) {
1166 WMUnmapWidget(*w);
1167 w++;
1169 WMUnmapWidget(panel->paramF);
1170 WMUnmapWidget(panel->quickB);
1173 w = panel->sections[type];
1175 while (*w) {
1176 WMMapWidget(*w);
1177 w++;
1181 updateFrameTitle(panel, title, type);
1183 panel->currentType = type;
1189 static void
1190 updateMenuItem(_Panel *panel, WEditMenuItem *item, WMWidget *changedWidget)
1192 ItemData *data = WGetEditMenuItemData(item);
1194 assert(data != NULL);
1196 #define REPLACE(v, d) if (v) wfree(v); v = d
1198 switch (data->type) {
1199 case ExecInfo:
1200 if (changedWidget == panel->commandT) {
1201 REPLACE(data->param.exec.command,
1202 WMGetTextFieldText(panel->commandT));
1204 if (changedWidget == panel->shortT) {
1205 REPLACE(data->param.exec.shortcut,
1206 WMGetTextFieldText(panel->shortT));
1208 break;
1210 case CommandInfo:
1211 if (changedWidget == panel->icommandL) {
1212 data->param.command.command =
1213 WMGetListSelectedItemRow(panel->icommandL);
1215 switch (data->param.command.command) {
1216 case 3:
1217 case 4:
1218 if (changedWidget == panel->quickB) {
1219 REPLACE(data->param.command.parameter,
1220 WMGetButtonSelected(panel->quickB)
1221 ? wstrdup("QUICK") : NULL);
1223 break;
1225 case 6:
1226 if (changedWidget == panel->paramT) {
1227 REPLACE(data->param.command.parameter,
1228 WMGetTextFieldText(panel->paramT));
1230 break;
1232 if (changedWidget == panel->shortT) {
1233 REPLACE(data->param.command.shortcut,
1234 WMGetTextFieldText(panel->shortT));
1238 break;
1240 case PipeInfo:
1241 if (changedWidget == panel->pipeT) {
1242 REPLACE(data->param.pipe.command,
1243 WMGetTextFieldText(panel->pipeT));
1245 if (changedWidget == panel->pipeCacheB) {
1246 data->param.pipe.cached =
1247 WMGetButtonSelected(panel->pipeCacheB);
1249 break;
1251 case ExternalInfo:
1252 if (changedWidget == panel->pathT) {
1253 REPLACE(data->param.external.path,
1254 WMGetTextFieldText(panel->pathT));
1256 break;
1258 case DirectoryInfo:
1259 if (changedWidget == panel->dpathT) {
1260 REPLACE(data->param.directory.directory,
1261 WMGetTextFieldText(panel->dpathT));
1263 if (changedWidget == panel->dcommandT) {
1264 REPLACE(data->param.directory.command,
1265 WMGetTextFieldText(panel->dcommandT));
1267 if (changedWidget == panel->dstripB) {
1268 data->param.directory.stripExt =
1269 WMGetButtonSelected(panel->dstripB);
1271 break;
1273 default:
1274 assert(0);
1275 break;
1278 #undef REPLACE
1283 static void
1284 menuItemCloned(WEditMenuDelegate *delegate, WEditMenu *menu,
1285 WEditMenuItem *origItem, WEditMenuItem *newItem)
1287 ItemData *data = WGetEditMenuItemData(origItem);
1288 ItemData *newData;
1290 if (!data)
1291 return;
1293 #define DUP(s) (s) ? wstrdup(s) : NULL
1295 newData = NEW(ItemData);
1297 newData->type = data->type;
1299 switch (data->type) {
1300 case ExecInfo:
1301 newData->param.exec.command = DUP(data->param.exec.command);
1302 newData->param.exec.shortcut = DUP(data->param.exec.shortcut);
1303 break;
1305 case CommandInfo:
1306 newData->param.command.command = data->param.command.command;
1307 newData->param.command.parameter = DUP(data->param.command.parameter);
1308 newData->param.command.shortcut = DUP(data->param.command.shortcut);
1309 break;
1311 case PipeInfo:
1312 newData->param.pipe.command = DUP(data->param.pipe.command);
1313 newData->param.pipe.cached = data->param.pipe.cached;
1314 break;
1316 case ExternalInfo:
1317 newData->param.external.path = DUP(data->param.external.path);
1318 break;
1320 case DirectoryInfo:
1321 newData->param.directory.directory = DUP(data->param.directory.directory);
1322 newData->param.directory.command = DUP(data->param.directory.command);
1323 newData->param.directory.stripExt = data->param.directory.stripExt;
1324 break;
1326 default:
1327 break;
1330 #undef DUP
1332 WSetEditMenuItemData(newItem, newData, (WMCallback*)freeItemData);
1336 static void
1337 menuItemEdited(struct WEditMenuDelegate *delegate, WEditMenu *menu,
1338 WEditMenuItem *item)
1340 _Panel *panel = (_Panel*)delegate->data;
1341 WEditMenu *submenu;
1343 updateFrameTitle(panel, WGetEditMenuItemTitle(item), panel->currentType);
1345 submenu = WGetEditMenuSubmenu(menu, item);
1346 if (submenu) {
1347 WSetEditMenuTitle(submenu, WGetEditMenuItemTitle(item));
1352 static Bool
1353 shouldRemoveItem(struct WEditMenuDelegate *delegate, WEditMenu *menu,
1354 WEditMenuItem *item)
1356 _Panel *panel = (_Panel*)delegate->data;
1358 if (panel->dontAsk)
1359 return True;
1361 if (WGetEditMenuSubmenu(menu, item)) {
1362 int res;
1364 res = WMRunAlertPanel(WMWidgetScreen(menu), NULL,
1365 _("Remove Submenu"),
1366 _("Removing this item will destroy all items inside\n"
1367 "the submenu. Do you really want to do that?"),
1368 _("Yes"), _("No"),
1369 _("Yes, don't ask again."));
1370 switch (res) {
1371 case WAPRDefault:
1372 return True;
1373 case WAPRAlternate:
1374 return False;
1375 case WAPROther:
1376 panel->dontAsk = True;
1377 return True;
1380 return True;
1384 static void
1385 menuItemDeselected(WEditMenuDelegate *delegate, WEditMenu *menu,
1386 WEditMenuItem *item)
1388 _Panel *panel = (_Panel*)delegate->data;
1390 changeInfoType(panel, NULL, NoInfo);
1394 static void
1395 menuItemSelected(WEditMenuDelegate *delegate, WEditMenu *menu,
1396 WEditMenuItem *item)
1398 ItemData *data = WGetEditMenuItemData(item);
1399 _Panel *panel = (_Panel*)delegate->data;
1401 panel->currentItem = item;
1403 if (data) {
1404 changeInfoType(panel, WGetEditMenuItemTitle(item), data->type);
1406 switch (data->type) {
1407 case NoInfo:
1408 break;
1410 case ExecInfo:
1411 WMSetTextFieldText(panel->commandT, data->param.exec.command);
1412 WMSetTextFieldText(panel->shortT, data->param.exec.shortcut);
1413 break;
1415 case CommandInfo:
1416 WMSelectListItem(panel->icommandL,
1417 data->param.command.command);
1418 WMSetListPosition(panel->icommandL,
1419 data->param.command.command - 2);
1420 WMSetTextFieldText(panel->shortT, data->param.command.shortcut);
1422 switch (data->param.command.command) {
1423 case 3:
1424 case 4:
1425 WMSetButtonSelected(panel->quickB,
1426 data->param.command.parameter!=NULL);
1427 break;
1428 case 6:
1429 WMSetTextFieldText(panel->paramT,
1430 data->param.command.parameter);
1431 break;
1434 icommandLClicked(panel->icommandL, panel);
1435 break;
1437 case PipeInfo:
1438 WMSetTextFieldText(panel->pipeT, data->param.pipe.command);
1439 WMSetButtonSelected(panel->pipeCacheB, data->param.pipe.cached);
1440 break;
1442 case ExternalInfo:
1443 WMSetTextFieldText(panel->pathT, data->param.external.path);
1444 break;
1446 case DirectoryInfo:
1447 WMSetTextFieldText(panel->dpathT, data->param.directory.directory);
1448 WMSetTextFieldText(panel->dcommandT, data->param.directory.command);
1449 WMSetButtonSelected(panel->dstripB, data->param.directory.stripExt);
1450 break;
1452 case WSMenuInfo:
1453 break;
1455 default:
1456 break;
1463 static WEditMenu*
1464 buildSubmenu(_Panel *panel, WMPropList *pl)
1466 WMScreen *scr = WMWidgetScreen(panel->parent);
1467 WEditMenu *menu;
1468 WEditMenuItem *item;
1469 char *title;
1470 WMPropList *tp, *bp;
1471 int i;
1473 tp = WMGetFromPLArray(pl, 0);
1474 title = WMGetFromPLString(tp);
1476 menu = WCreateEditMenu(scr, title);
1478 for (i = 1; i < WMGetPropListItemCount(pl); i++) {
1479 WMPropList *pi;
1481 pi = WMGetFromPLArray(pl, i);
1483 tp = WMGetFromPLArray(pi, 0);
1484 bp = WMGetFromPLArray(pi, 1);
1486 title = WMGetFromPLString(tp);
1488 if (!bp || WMIsPLArray(bp)) { /* it's a submenu */
1489 WEditMenu *submenu;
1491 submenu = buildSubmenu(panel, pi);
1493 item = WAddMenuItemWithTitle(menu, title);
1495 WSetEditMenuSubmenu(menu, item, submenu);
1496 } else {
1497 ItemData *data;
1499 item = WAddMenuItemWithTitle(menu, title);
1501 data = parseCommand(pi);
1503 if (panel->markerPix[data->type])
1504 WSetEditMenuItemImage(item, panel->markerPix[data->type]);
1505 WSetEditMenuItemData(item, data, (WMCallback*)freeItemData);
1509 WSetEditMenuAcceptsDrop(menu, True);
1510 WSetEditMenuDelegate(menu, &menuDelegate);
1512 WMRealizeWidget(menu);
1514 return menu;
1519 static void
1520 buildMenuFromPL(_Panel *panel, WMPropList *pl)
1522 panel->menu = buildSubmenu(panel, pl);
1527 static WMPropList*
1528 getDefaultMenu(_Panel *panel)
1530 WMPropList *menu, *pmenu;
1531 char *menuPath, *gspath;
1533 gspath = wusergnusteppath();
1535 menuPath = wmalloc(strlen(gspath)+128);
1536 /* if there is a localized plmenu for the tongue put it's filename here */
1537 sprintf(menuPath, _("%s/Library/WindowMaker/plmenu"), gspath);
1539 menu = WMReadPropListFromFile(menuPath);
1540 if (!menu) {
1541 wwarning("%s:could not read property list menu", menuPath);
1543 if (strcmp("%s/Library/WindowMaker/plmenu",
1544 _("%s/Library/WindowMaker/plmenu"))!=0) {
1546 sprintf(menuPath, "%s/Library/WindowMaker/plmenu", gspath);
1547 menu = WMReadPropListFromFile(menuPath);
1548 wwarning("%s:could not read property list menu", menuPath);
1550 if (!menu) {
1551 char buffer[512];
1553 sprintf(buffer, _("Could not open default menu from '%s'"),
1554 menuPath);
1555 WMRunAlertPanel(WMWidgetScreen(panel->parent), panel->parent,
1556 _("Error"), buffer, _("OK"), NULL, NULL);
1560 wfree(menuPath);
1562 if (menu) {
1563 pmenu = menu;
1564 } else {
1565 pmenu = NULL;
1568 return pmenu;
1572 static void
1573 showData(_Panel *panel)
1575 char *gspath;
1576 char *menuPath;
1577 WMPropList *pmenu;
1579 gspath = wusergnusteppath();
1581 menuPath = wmalloc(strlen(gspath)+32);
1582 strcpy(menuPath, gspath);
1583 strcat(menuPath, "/Defaults/WMRootMenu");
1585 pmenu = WMReadPropListFromFile(menuPath);
1587 if (!pmenu || !WMIsPLArray(pmenu)) {
1588 int res;
1590 res = WMRunAlertPanel(WMWidgetScreen(panel->parent), panel->parent,
1591 _("Warning"),
1592 _("The menu file format currently in use is not supported\n"
1593 "by this tool. Do you want to discard the current menu\n"
1594 "to use this tool?"),
1595 _("Yes, Discard and Update"),
1596 _("No, Keep Current Menu"), NULL);
1598 if (res == WAPRDefault) {
1599 pmenu = getDefaultMenu(panel);
1601 if (!pmenu) {
1602 pmenu = WMCreatePLArray(WMCreatePLString("Applications"),
1603 NULL);
1605 } else {
1606 panel->dontSave = True;
1607 return;
1611 panel->menuPath = menuPath;
1613 buildMenuFromPL(panel, pmenu);
1615 WMReleasePropList(pmenu);
1619 static Bool
1620 notblank(char *s)
1622 if (s) {
1623 while (*s++) {
1624 if (!isspace(*s))
1625 return True;
1628 return False;
1632 static WMPropList*
1633 processData(char *title, ItemData *data)
1635 WMPropList *item;
1636 char *s1;
1637 static WMPropList *pscut = NULL;
1638 static WMPropList *pomenu = NULL;
1639 int i;
1641 if (!pscut) {
1642 pscut = WMCreatePLString("SHORTCUT");
1643 pomenu = WMCreatePLString("OPEN_MENU");
1646 item = WMCreatePLArray(WMCreatePLString(title), NULL);
1649 switch (data->type) {
1650 case ExecInfo:
1651 if (data->param.exec.command == NULL)
1652 return NULL;
1653 #if 1
1654 if (strpbrk(data->param.exec.command, "&$*|><?`=;")) {
1655 s1 = "SHEXEC";
1656 } else {
1657 s1 = "EXEC";
1659 #else
1660 s1 = "SHEXEC";
1661 #endif
1663 if (notblank(data->param.exec.shortcut)) {
1664 WMAddToPLArray(item, pscut);
1665 WMAddToPLArray(item,
1666 WMCreatePLString(data->param.exec.shortcut));
1669 WMAddToPLArray(item, WMCreatePLString(s1));
1670 WMAddToPLArray(item, WMCreatePLString(data->param.exec.command));
1671 break;
1673 case CommandInfo:
1674 if (notblank(data->param.command.shortcut)) {
1675 WMAddToPLArray(item, pscut);
1676 WMAddToPLArray(item,
1677 WMCreatePLString(data->param.command.shortcut));
1680 i = data->param.command.command;
1682 WMAddToPLArray(item, WMCreatePLString(commandNames[i]));
1684 switch (i) {
1685 case 3:
1686 case 4:
1687 if (data->param.command.parameter) {
1688 WMAddToPLArray(item,
1689 WMCreatePLString(data->param.command.parameter));
1691 break;
1693 case 6: /* restart */
1694 if (data->param.command.parameter) {
1695 WMAddToPLArray(item,
1696 WMCreatePLString(data->param.command.parameter));
1698 break;
1701 break;
1703 case PipeInfo:
1704 if (!data->param.pipe.command)
1705 return NULL;
1706 WMAddToPLArray(item, pomenu);
1707 if (data->param.pipe.cached)
1708 s1 = wstrconcat("| ", data->param.pipe.command);
1709 else
1710 s1 = wstrconcat("|| ", data->param.pipe.command);
1711 WMAddToPLArray(item, WMCreatePLString(s1));
1712 wfree(s1);
1713 break;
1715 case ExternalInfo:
1716 if (!data->param.external.path)
1717 return NULL;
1718 WMAddToPLArray(item, pomenu);
1719 WMAddToPLArray(item, WMCreatePLString(data->param.external.path));
1720 break;
1722 case DirectoryInfo:
1723 if (!data->param.directory.directory
1724 || !data->param.directory.command)
1725 return NULL;
1727 int l;
1728 char *tmp;
1730 l = strlen(data->param.directory.directory);
1731 l += strlen(data->param.directory.command);
1732 l += 32;
1734 WMAddToPLArray(item, pomenu);
1736 tmp = wmalloc(l);
1737 sprintf(tmp, "%s%s WITH %s",
1738 data->param.directory.stripExt ? "-noext " : "",
1739 data->param.directory.directory,
1740 data->param.directory.command);
1742 WMAddToPLArray(item, WMCreatePLString(tmp));
1743 wfree(tmp);
1745 break;
1747 case WSMenuInfo:
1748 WMAddToPLArray(item, WMCreatePLString("WORKSPACE_MENU"));
1749 break;
1751 case WWindowListInfo:
1752 WMAddToPLArray(item, WMCreatePLString("WINDOWS_MENU"));
1753 break;
1755 default:
1756 assert(0);
1757 break;
1760 return item;
1764 static WMPropList*
1765 processSubmenu(WEditMenu *menu)
1767 WEditMenuItem *item;
1768 WMPropList *pmenu;
1769 WMPropList *pl;
1770 char *s;
1771 int i;
1774 s = WGetEditMenuTitle(menu);
1775 pl = WMCreatePLString(s);
1777 pmenu = WMCreatePLArray(pl, NULL);
1779 i = 0;
1780 while ((item = WGetEditMenuItem(menu, i++))) {
1781 WEditMenu *submenu;
1783 s = WGetEditMenuItemTitle(item);
1785 submenu = WGetEditMenuSubmenu(menu, item);
1786 if (submenu) {
1787 pl = processSubmenu(submenu);
1788 } else {
1789 pl = processData(s, WGetEditMenuItemData(item));
1792 if (!pl)
1793 continue;
1795 WMAddToPLArray(pmenu, pl);
1798 return pmenu;
1803 static WMPropList*
1804 buildPLFromMenu(_Panel *panel)
1806 WMPropList *menu;
1808 menu = processSubmenu(panel->menu);
1810 return menu;
1816 static void
1817 storeData(_Panel *panel)
1819 WMPropList *menu;
1821 if (panel->dontSave)
1822 return;
1824 menu = buildPLFromMenu(panel);
1826 WMWritePropListToFile(menu, panel->menuPath, True);
1828 WMReleasePropList(menu);
1833 static void
1834 showMenus(_Panel *panel)
1836 if (panel->menu)
1837 WEditMenuUnhide(panel->menu);
1841 static void
1842 hideMenus(_Panel *panel)
1844 if (panel->menu)
1845 WEditMenuHide(panel->menu);
1851 Panel*
1852 InitMenu(WMScreen *scr, WMWidget *parent)
1854 _Panel *panel;
1856 panel = wmalloc(sizeof(_Panel));
1857 memset(panel, 0, sizeof(_Panel));
1859 panel->sectionName = _("Applications Menu Definition");
1861 panel->description = _("Edit the menu for launching applications.");
1863 panel->parent = parent;
1865 panel->callbacks.createWidgets = createPanel;
1866 panel->callbacks.updateDomain = storeData;
1867 panel->callbacks.showPanel = showMenus;
1868 panel->callbacks.hidePanel = hideMenus;
1871 AddSection(panel, ICON_FILE);
1873 return panel;