Paint app icons when updated
[wmaker-crm.git] / WPrefs.app / Menu.c
blobc179e68902138e47c3fee9a59f921923516a7a71
1 /* Menu.c- menu definition
3 * WPrefs - Window Maker Preferences Program
5 * Copyright (c) 2000-2003 Alfredo K. Kojima
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 along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include "WPrefs.h"
23 #include <assert.h>
24 #include <ctype.h>
26 #include <X11/keysym.h>
27 #include <X11/cursorfont.h>
29 #include "editmenu.h"
31 typedef enum {
32 NoInfo,
33 ExecInfo,
34 CommandInfo,
35 ExternalInfo,
36 PipeInfo,
37 DirectoryInfo,
38 WSMenuInfo,
39 WWindowListInfo,
40 LastInfo
41 } InfoType;
43 #define MAX_SECTION_SIZE 4
45 typedef struct _Panel {
46 WMBox *box;
47 char *sectionName;
49 char *description;
51 CallbackRec callbacks;
52 WMWidget *parent;
54 WMFont *boldFont;
55 WMFont *normalFont;
56 WMColor *white;
57 WMColor *gray;
58 WMColor *black;
60 WMPixmap *markerPix[LastInfo];
62 WMPopUpButton *typeP;
64 WMWidget *itemPad[3];
65 int currentPad;
67 WEditMenu *menu;
68 char *menuPath;
70 WMFrame *optionsF;
72 WMFrame *commandF;
73 WMTextField *commandT; /* command to run */
74 WMButton *browseB;
75 WMButton *xtermC; /* inside xterm? */
77 WMFrame *pathF;
78 WMTextField *pathT;
80 WMFrame *pipeF;
81 WMTextField *pipeT;
82 WMButton *pipeCacheB;
84 WMFrame *dpathF;
85 WMTextField *dpathT;
87 WMFrame *dcommandF;
88 WMTextField *dcommandT;
90 WMButton *dstripB;
92 WMFrame *shortF;
93 WMTextField *shortT;
94 WMButton *sgrabB;
95 WMButton *sclearB;
97 WMList *icommandL;
99 WMFrame *paramF;
100 WMTextField *paramT;
102 WMButton *quickB;
104 Bool dontAsk; /* whether to comfirm submenu remove */
105 Bool dontSave;
107 Bool capturing;
109 /* about the currently selected item */
110 WEditMenuItem *currentItem;
111 InfoType currentType;
112 WMWidget *sections[LastInfo][MAX_SECTION_SIZE];
113 } _Panel;
115 typedef struct {
116 InfoType type;
117 union {
118 struct {
119 int command;
120 char *parameter;
121 char *shortcut;
122 } command;
123 struct {
124 char *command;
125 char *shortcut;
126 } exec;
127 struct {
128 char *path;
129 } external;
130 struct {
131 char *command;
132 unsigned cached:1;
133 } pipe;
134 struct {
135 char *directory;
136 char *command;
137 unsigned stripExt:1;
138 } directory;
139 } param;
140 } ItemData;
142 static char *commandNames[] = {
143 "ARRANGE_ICONS",
144 "HIDE_OTHERS",
145 "SHOW_ALL",
146 "EXIT",
147 "SHUTDOWN",
148 "RESTART",
149 "RESTART",
150 "SAVE_SESSION",
151 "CLEAR_SESSION",
152 "REFRESH",
153 "INFO_PANEL",
154 "LEGAL_PANEL"
157 #define NEW(type) memset(wmalloc(sizeof(type)), 0, sizeof(type))
159 #define ICON_FILE "menus"
161 static void showData(_Panel * panel);
163 static void updateMenuItem(_Panel * panel, WEditMenuItem * item, WMWidget * changedWidget);
165 static void menuItemSelected(struct WEditMenuDelegate *delegate, WEditMenu * menu, WEditMenuItem * item);
167 static void menuItemDeselected(struct WEditMenuDelegate *delegate, WEditMenu * menu, WEditMenuItem * item);
169 static void menuItemCloned(struct WEditMenuDelegate *delegate, WEditMenu * menu,
170 WEditMenuItem * origItem, WEditMenuItem * newItem);
172 static void menuItemEdited(struct WEditMenuDelegate *delegate, WEditMenu * menu, WEditMenuItem * item);
174 static Bool shouldRemoveItem(struct WEditMenuDelegate *delegate, WEditMenu * menu, WEditMenuItem * item);
176 static void freeItemData(ItemData * data);
178 static WEditMenuDelegate menuDelegate = {
179 NULL,
180 menuItemCloned,
181 menuItemEdited,
182 menuItemSelected,
183 menuItemDeselected,
184 shouldRemoveItem
187 static void dataChanged(void *self, WMNotification * notif)
189 _Panel *panel = (_Panel *) self;
190 WEditMenuItem *item = panel->currentItem;
191 WMWidget *w = (WMWidget *) WMGetNotificationObject(notif);
193 updateMenuItem(panel, item, w);
196 static void buttonClicked(WMWidget * w, void *data)
198 _Panel *panel = (_Panel *) data;
199 WEditMenuItem *item = panel->currentItem;
201 updateMenuItem(panel, item, w);
204 static void icommandLClicked(WMWidget * w, void *data)
206 _Panel *panel = (_Panel *) data;
207 int cmd;
209 cmd = WMGetListSelectedItemRow(w);
210 if (cmd == 3 || cmd == 4) {
211 WMMapWidget(panel->quickB);
212 } else {
213 WMUnmapWidget(panel->quickB);
215 if (cmd == 6) {
216 WMMapWidget(panel->paramF);
217 } else {
218 WMUnmapWidget(panel->paramF);
222 static void browseForFile(WMWidget * self, void *clientData)
224 _Panel *panel = (_Panel *) clientData;
225 WMFilePanel *filePanel;
226 char *text, *oldprog, *newprog;
228 filePanel = WMGetOpenPanel(WMWidgetScreen(self));
229 text = WMGetTextFieldText(panel->commandT);
231 oldprog = wtrimspace(text);
232 wfree(text);
234 if (oldprog[0] == 0 || oldprog[0] != '/') {
235 wfree(oldprog);
236 oldprog = wstrdup("/");
237 } else {
238 char *ptr = oldprog;
239 while (*ptr && !isspace(*ptr))
240 ptr++;
241 *ptr = 0;
244 WMSetFilePanelCanChooseDirectories(filePanel, False);
246 if (WMRunModalFilePanelForDirectory(filePanel, panel->parent, oldprog, _("Select Program"), NULL) == True) {
247 newprog = WMGetFilePanelFileName(filePanel);
248 WMSetTextFieldText(panel->commandT, newprog);
249 updateMenuItem(panel, panel->currentItem, panel->commandT);
250 wfree(newprog);
253 wfree(oldprog);
256 static char *captureShortcut(Display * dpy, _Panel * panel)
258 XEvent ev;
259 KeySym ksym;
260 char buffer[64];
261 char *key = NULL;
263 while (panel->capturing) {
264 XAllowEvents(dpy, AsyncKeyboard, CurrentTime);
265 WMNextEvent(dpy, &ev);
266 if (ev.type == KeyPress && ev.xkey.keycode != 0) {
267 ksym = XKeycodeToKeysym(dpy, ev.xkey.keycode, 0);
268 if (!IsModifierKey(ksym)) {
269 key = XKeysymToString(ksym);
270 panel->capturing = 0;
271 break;
274 WMHandleEvent(&ev);
277 if (!key)
278 return NULL;
280 buffer[0] = 0;
282 if (ev.xkey.state & ControlMask) {
283 strcat(buffer, "Control+");
285 if (ev.xkey.state & ShiftMask) {
286 strcat(buffer, "Shift+");
288 if (ev.xkey.state & Mod1Mask) {
289 strcat(buffer, "Mod1+");
291 if (ev.xkey.state & Mod2Mask) {
292 strcat(buffer, "Mod2+");
294 if (ev.xkey.state & Mod3Mask) {
295 strcat(buffer, "Mod3+");
297 if (ev.xkey.state & Mod4Mask) {
298 strcat(buffer, "Mod4+");
300 if (ev.xkey.state & Mod5Mask) {
301 strcat(buffer, "Mod5+");
303 strcat(buffer, key);
305 return wstrdup(buffer);
308 static void sgrabClicked(WMWidget * w, void *data)
310 _Panel *panel = (_Panel *) data;
311 Display *dpy = WMScreenDisplay(WMWidgetScreen(panel->parent));
312 char *shortcut;
314 if (w == panel->sclearB) {
315 WMSetTextFieldText(panel->shortT, "");
316 updateMenuItem(panel, panel->currentItem, panel->shortT);
317 return;
320 if (!panel->capturing) {
321 panel->capturing = 1;
322 WMSetButtonText(w, _("Cancel"));
323 XGrabKeyboard(dpy, WMWidgetXID(panel->parent), True, GrabModeAsync, GrabModeAsync, CurrentTime);
324 shortcut = captureShortcut(dpy, panel);
325 if (shortcut) {
326 WMSetTextFieldText(panel->shortT, shortcut);
327 updateMenuItem(panel, panel->currentItem, panel->shortT);
328 wfree(shortcut);
331 panel->capturing = 0;
332 WMSetButtonText(w, _("Capture"));
333 XUngrabKeyboard(dpy, CurrentTime);
336 static void changedItemPad(WMWidget * w, void *data)
338 _Panel *panel = (_Panel *) data;
339 int padn = WMGetPopUpButtonSelectedItem(w);
341 WMUnmapWidget(panel->itemPad[panel->currentPad]);
342 WMMapWidget(panel->itemPad[padn]);
344 panel->currentPad = padn;
347 static WEditMenu *putNewSubmenu(WEditMenu * menu, char *title)
349 WEditMenu *tmp;
350 WEditMenuItem *item;
352 item = WAddMenuItemWithTitle(menu, title);
354 tmp = WCreateEditMenu(WMWidgetScreen(menu), title);
355 WSetEditMenuAcceptsDrop(tmp, True);
356 WSetEditMenuDelegate(tmp, &menuDelegate);
357 WSetEditMenuSubmenu(menu, item, tmp);
359 return tmp;
362 static ItemData *putNewItem(_Panel * panel, WEditMenu * menu, int type, char *title)
364 WEditMenuItem *item;
365 ItemData *data;
367 item = WAddMenuItemWithTitle(menu, title);
369 data = NEW(ItemData);
370 data->type = type;
371 WSetEditMenuItemData(item, data, (WMCallback *) freeItemData);
372 WSetEditMenuItemImage(item, panel->markerPix[type]);
374 return data;
377 static WEditMenu *makeFactoryMenu(WMWidget * parent, int width)
379 WEditMenu *pad;
381 pad = WCreateEditMenuPad(parent);
382 WMResizeWidget(pad, width, 10);
383 WSetEditMenuMinSize(pad, wmksize(width, 0));
384 WSetEditMenuMaxSize(pad, wmksize(width, 0));
385 WSetEditMenuSelectable(pad, False);
386 WSetEditMenuEditable(pad, False);
387 WSetEditMenuIsFactory(pad, True);
388 WSetEditMenuDelegate(pad, &menuDelegate);
390 return pad;
393 static void createPanel(_Panel * p)
395 _Panel *panel = (_Panel *) p;
396 WMScreen *scr = WMWidgetScreen(panel->parent);
397 WMColor *black = WMBlackColor(scr);
398 WMColor *white = WMWhiteColor(scr);
399 WMColor *gray = WMGrayColor(scr);
400 WMFont *bold = WMBoldSystemFontOfSize(scr, 12);
401 WMFont *font = WMSystemFontOfSize(scr, 12);
402 WMLabel *label;
403 int width;
405 menuDelegate.data = panel;
407 panel->boldFont = bold;
408 panel->normalFont = font;
410 panel->black = black;
411 panel->white = white;
412 panel->gray = gray;
415 Pixmap pix;
416 Display *dpy = WMScreenDisplay(scr);
417 GC gc;
418 WMPixmap *pixm;
420 pixm = WMCreatePixmap(scr, 7, 7, WMScreenDepth(scr), True);
422 pix = WMGetPixmapXID(pixm);
424 XDrawLine(dpy, pix, WMColorGC(black), 0, 3, 6, 3);
425 XDrawLine(dpy, pix, WMColorGC(black), 3, 0, 3, 6);
427 XDrawLine(dpy, pix, WMColorGC(black), 1, 0, 3, 3);
428 XDrawLine(dpy, pix, WMColorGC(black), 1, 6, 3, 3);
429 XDrawLine(dpy, pix, WMColorGC(black), 0, 0, 0, 6);
432 pix = WMGetPixmapMaskXID(pixm);
434 gc = XCreateGC(dpy, pix, 0, NULL);
436 XSetForeground(dpy, gc, 0);
437 XFillRectangle(dpy, pix, gc, 0, 0, 7, 7);
439 XSetForeground(dpy, gc, 1);
440 XDrawLine(dpy, pix, gc, 0, 3, 6, 3);
441 XDrawLine(dpy, pix, gc, 3, 0, 3, 6);
443 panel->markerPix[ExternalInfo] = pixm;
444 panel->markerPix[PipeInfo] = pixm;
445 panel->markerPix[DirectoryInfo] = pixm;
446 panel->markerPix[WSMenuInfo] = pixm;
447 panel->markerPix[WWindowListInfo] = pixm;
449 XFreeGC(dpy, gc);
452 panel->box = WMCreateBox(panel->parent);
453 WMSetViewExpandsToParent(WMWidgetView(panel->box), 2, 2, 2, 2);
455 panel->typeP = WMCreatePopUpButton(panel->box);
456 WMResizeWidget(panel->typeP, 150, 20);
457 WMMoveWidget(panel->typeP, 10, 10);
459 WMAddPopUpButtonItem(panel->typeP, _("New Items"));
460 WMAddPopUpButtonItem(panel->typeP, _("Sample Commands"));
461 WMAddPopUpButtonItem(panel->typeP, _("Sample Submenus"));
463 WMSetPopUpButtonAction(panel->typeP, changedItemPad, panel);
465 WMSetPopUpButtonSelectedItem(panel->typeP, 0);
468 WEditMenu *pad;
469 WEditMenu *smenu;
470 ItemData *data;
472 pad = makeFactoryMenu(panel->box, 150);
473 WMMoveWidget(pad, 10, 40);
475 data = putNewItem(panel, pad, ExecInfo, _("Run Program"));
476 data = putNewItem(panel, pad, CommandInfo, _("Internal Command"));
477 smenu = putNewSubmenu(pad, _("Submenu"));
478 data = putNewItem(panel, pad, ExternalInfo, _("External Submenu"));
479 data = putNewItem(panel, pad, PipeInfo, _("Generated Submenu"));
480 data = putNewItem(panel, pad, DirectoryInfo, _("Directory Contents"));
481 data = putNewItem(panel, pad, WSMenuInfo, _("Workspace Menu"));
482 data = putNewItem(panel, pad, WWindowListInfo, _("Window List Menu"));
484 panel->itemPad[0] = pad;
488 WEditMenu *pad;
489 ItemData *data;
490 WMScrollView *sview;
492 sview = WMCreateScrollView(panel->box);
493 WMResizeWidget(sview, 150, 180);
494 WMMoveWidget(sview, 10, 40);
495 WMSetScrollViewHasVerticalScroller(sview, True);
497 pad = makeFactoryMenu(panel->box, 130);
499 WMSetScrollViewContentView(sview, WMWidgetView(pad));
501 data = putNewItem(panel, pad, ExecInfo, _("XTerm"));
502 data->param.exec.command = "xterm -sb -sl 2000 -bg black -fg white";
504 data = putNewItem(panel, pad, ExecInfo, _("rxvt"));
505 data->param.exec.command = "rxvt";
507 data = putNewItem(panel, pad, ExecInfo, _("ETerm"));
508 data->param.exec.command = "eterm";
510 data = putNewItem(panel, pad, ExecInfo, _("Run..."));
511 data->param.exec.command = _("%A(Run,Type command to run)");
513 data = putNewItem(panel, pad, ExecInfo, _("Firefox"));
514 data->param.exec.command = "firefox";
516 data = putNewItem(panel, pad, ExecInfo, _("gimp"));
517 data->param.exec.command = "gimp";
519 data = putNewItem(panel, pad, ExecInfo, _("epic"));
520 data->param.exec.command = "xterm -e epic";
522 data = putNewItem(panel, pad, ExecInfo, _("ee"));
523 data->param.exec.command = "ee";
525 data = putNewItem(panel, pad, ExecInfo, _("xv"));
526 data->param.exec.command = "xv";
528 data = putNewItem(panel, pad, ExecInfo, _("Evince"));
529 data->param.exec.command = "evince";
531 data = putNewItem(panel, pad, ExecInfo, _("ghostview"));
532 data->param.exec.command = "gv";
534 data = putNewItem(panel, pad, CommandInfo, _("Exit Window Maker"));
535 data->param.command.command = 3;
537 WMMapWidget(pad);
539 panel->itemPad[1] = sview;
543 WEditMenu *pad, *smenu;
544 ItemData *data;
545 WMScrollView *sview;
547 sview = WMCreateScrollView(panel->box);
548 WMResizeWidget(sview, 150, 180);
549 WMMoveWidget(sview, 10, 40);
550 WMSetScrollViewHasVerticalScroller(sview, True);
552 pad = makeFactoryMenu(panel->box, 130);
554 WMSetScrollViewContentView(sview, WMWidgetView(pad));
556 data = putNewItem(panel, pad, ExternalInfo, _("Debian Menu"));
557 data->param.pipe.command = "/etc/X11/WindowMaker/menu.hook";
559 data = putNewItem(panel, pad, PipeInfo, _("RedHat Menu"));
560 data->param.pipe.command = "wmconfig --output wmaker";
562 data = putNewItem(panel, pad, PipeInfo, _("Menu Conectiva"));
563 data->param.pipe.command = "wmconfig --output wmaker";
565 data = putNewItem(panel, pad, DirectoryInfo, _("Themes"));
566 data->param.directory.command = "setstyle";
567 data->param.directory.directory =
568 "/usr/share/WindowMaker/Themes /usr/local/share/WindowMaker/Themes $HOME/GNUstep/Library/WindowMaker/Themes";
569 data->param.directory.stripExt = 1;
571 data = putNewItem(panel, pad, DirectoryInfo, _("Bg Images (scale)"));
572 data->param.directory.command = "wmsetbg -u -s";
573 data->param.directory.directory =
574 "/opt/kde2/share/wallpapers /usr/share/WindowMaker/Backgrounds $HOME/GNUstep/Library/WindowMaker/Backgrounds";
575 data->param.directory.stripExt = 1;
577 data = putNewItem(panel, pad, DirectoryInfo, _("Bg Images (tile)"));
578 data->param.directory.command = "wmsetbg -u -t";
579 data->param.directory.directory =
580 "/opt/kde2/share/wallpapers /usr/share/WindowMaker/Backgrounds $HOME/GNUstep/Library/WindowMaker/Backgrounds";
581 data->param.directory.stripExt = 1;
583 smenu = putNewSubmenu(pad, _("Assorted XTerms"));
585 data = putNewItem(panel, smenu, ExecInfo, _("XTerm Yellow on Blue"));
586 data->param.exec.command = "xterm -sb -sl 2000 -bg midnightblue -fg yellow";
588 data = putNewItem(panel, smenu, ExecInfo, _("XTerm White on Black"));
589 data->param.exec.command = "xterm -sb -sl 2000 -bg black -fg white";
591 data = putNewItem(panel, smenu, ExecInfo, _("XTerm Black on White"));
592 data->param.exec.command = "xterm -sb -sl 2000 -bg white -fg black";
594 data = putNewItem(panel, smenu, ExecInfo, _("XTerm Black on Beige"));
595 data->param.exec.command = "xterm -sb -sl 2000 -bg '#bbbb99' -fg black";
597 data = putNewItem(panel, smenu, ExecInfo, _("XTerm White on Green"));
598 data->param.exec.command = "xterm -sb -sl 2000 -bg '#228822' -fg white";
600 data = putNewItem(panel, smenu, ExecInfo, _("XTerm White on Olive"));
601 data->param.exec.command = "xterm -sb -sl 2000 -bg '#335533' -fg white";
603 data = putNewItem(panel, smenu, ExecInfo, _("XTerm Blue on Blue"));
604 data->param.exec.command = "xterm -sb -sl 2000 -bg '#112244' -fg '#88aabb'";
606 data = putNewItem(panel, smenu, ExecInfo, _("XTerm BIG FONTS"));
607 data->param.exec.command = "xterm -sb -sl 2000 -bg black -fg white -fn 10x20";
609 WMMapWidget(pad);
611 panel->itemPad[2] = sview;
614 width = FRAME_WIDTH - 20 - 150 - 10 - 2;
616 panel->optionsF = WMCreateFrame(panel->box);
617 WMResizeWidget(panel->optionsF, width, FRAME_HEIGHT - 15);
618 WMMoveWidget(panel->optionsF, 10 + 150 + 10, 5);
620 width -= 20;
622 /* command */
624 panel->commandF = WMCreateFrame(panel->optionsF);
625 WMResizeWidget(panel->commandF, width, 50);
626 WMMoveWidget(panel->commandF, 10, 20);
627 WMSetFrameTitle(panel->commandF, _("Program to Run"));
628 WMSetFrameTitlePosition(panel->commandF, WTPAtTop);
630 panel->commandT = WMCreateTextField(panel->commandF);
631 WMResizeWidget(panel->commandT, width - 95, 20);
632 WMMoveWidget(panel->commandT, 10, 20);
634 panel->browseB = WMCreateCommandButton(panel->commandF);
635 WMResizeWidget(panel->browseB, 70, 24);
636 WMMoveWidget(panel->browseB, width - 80, 18);
637 WMSetButtonText(panel->browseB, _("Browse"));
638 WMSetButtonAction(panel->browseB, browseForFile, panel);
640 WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->commandT);
642 #if 0
643 panel->xtermC = WMCreateSwitchButton(panel->commandF);
644 WMResizeWidget(panel->xtermC, width - 20, 20);
645 WMMoveWidget(panel->xtermC, 10, 50);
646 WMSetButtonText(panel->xtermC, _("Run the program inside a Xterm"));
647 #endif
648 WMMapSubwidgets(panel->commandF);
650 /* path */
652 panel->pathF = WMCreateFrame(panel->optionsF);
653 WMResizeWidget(panel->pathF, width, 150);
654 WMMoveWidget(panel->pathF, 10, 40);
655 WMSetFrameTitle(panel->pathF, _("Path for Menu"));
657 panel->pathT = WMCreateTextField(panel->pathF);
658 WMResizeWidget(panel->pathT, width - 20, 20);
659 WMMoveWidget(panel->pathT, 10, 20);
661 WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->pathT);
663 label = WMCreateLabel(panel->pathF);
664 WMResizeWidget(label, width - 20, 80);
665 WMMoveWidget(label, 10, 50);
666 WMSetLabelText(label, _("Enter the path for a file containing a menu\n"
667 "or a list of directories with the programs you\n"
668 "want to have listed in the menu. Ex:\n"
669 "~/GNUstep/Library/WindowMaker/menu\n" "or\n" "/usr/X11R6/bin ~/xbin"));
671 WMMapSubwidgets(panel->pathF);
673 /* pipe */
675 panel->pipeF = WMCreateFrame(panel->optionsF);
676 WMResizeWidget(panel->pipeF, width, 155);
677 WMMoveWidget(panel->pipeF, 10, 30);
678 WMSetFrameTitle(panel->pipeF, _("Command"));
680 panel->pipeT = WMCreateTextField(panel->pipeF);
681 WMResizeWidget(panel->pipeT, width - 20, 20);
682 WMMoveWidget(panel->pipeT, 10, 20);
684 WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->pipeT);
686 label = WMCreateLabel(panel->pipeF);
687 WMResizeWidget(label, width - 20, 40);
688 WMMoveWidget(label, 10, 50);
689 WMSetLabelText(label, _("Enter a command that outputs a menu\n" "definition to stdout when invoked."));
691 panel->pipeCacheB = WMCreateSwitchButton(panel->pipeF);
692 WMResizeWidget(panel->pipeCacheB, width - 20, 40);
693 WMMoveWidget(panel->pipeCacheB, 10, 110);
694 WMSetButtonText(panel->pipeCacheB, _("Cache menu contents after opening for\n" "the first time"));
696 WMMapSubwidgets(panel->pipeF);
698 /* directory menu */
700 panel->dcommandF = WMCreateFrame(panel->optionsF);
701 WMResizeWidget(panel->dcommandF, width, 90);
702 WMMoveWidget(panel->dcommandF, 10, 25);
703 WMSetFrameTitle(panel->dcommandF, _("Command to Open Files"));
705 panel->dcommandT = WMCreateTextField(panel->dcommandF);
706 WMResizeWidget(panel->dcommandT, width - 20, 20);
707 WMMoveWidget(panel->dcommandT, 10, 20);
709 WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->dcommandT);
711 label = WMCreateLabel(panel->dcommandF);
712 WMResizeWidget(label, width - 20, 45);
713 WMMoveWidget(label, 10, 40);
714 WMSetLabelText(label, _("Enter the command you want to use to open the\n"
715 "files in the directories listed below."));
717 WMMapSubwidgets(panel->dcommandF);
719 panel->dpathF = WMCreateFrame(panel->optionsF);
720 WMResizeWidget(panel->dpathF, width, 80);
721 WMMoveWidget(panel->dpathF, 10, 125);
722 WMSetFrameTitle(panel->dpathF, _("Directories with Files"));
724 panel->dpathT = WMCreateTextField(panel->dpathF);
725 WMResizeWidget(panel->dpathT, width - 20, 20);
726 WMMoveWidget(panel->dpathT, 10, 20);
728 WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->dpathT);
730 panel->dstripB = WMCreateSwitchButton(panel->dpathF);
731 WMResizeWidget(panel->dstripB, width - 20, 20);
732 WMMoveWidget(panel->dstripB, 10, 50);
733 WMSetButtonText(panel->dstripB, _("Strip extensions from file names"));
735 WMSetButtonAction(panel->dstripB, buttonClicked, panel);
737 WMMapSubwidgets(panel->dpathF);
739 /* shortcut */
741 panel->shortF = WMCreateFrame(panel->optionsF);
742 WMResizeWidget(panel->shortF, width, 50);
743 WMMoveWidget(panel->shortF, 10, 160);
744 WMSetFrameTitle(panel->shortF, _("Keyboard Shortcut"));
746 panel->shortT = WMCreateTextField(panel->shortF);
747 WMResizeWidget(panel->shortT, width - 20 - 150, 20);
748 WMMoveWidget(panel->shortT, 10, 20);
750 WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->shortT);
752 panel->sgrabB = WMCreateCommandButton(panel->shortF);
753 WMResizeWidget(panel->sgrabB, 70, 24);
754 WMMoveWidget(panel->sgrabB, width - 80, 18);
755 WMSetButtonText(panel->sgrabB, _("Capture"));
756 WMSetButtonAction(panel->sgrabB, sgrabClicked, panel);
758 panel->sclearB = WMCreateCommandButton(panel->shortF);
759 WMResizeWidget(panel->sclearB, 70, 24);
760 WMMoveWidget(panel->sclearB, width - 155, 18);
761 WMSetButtonText(panel->sclearB, _("Clear"));
762 WMSetButtonAction(panel->sclearB, sgrabClicked, panel);
764 WMMapSubwidgets(panel->shortF);
766 /* internal command */
768 panel->icommandL = WMCreateList(panel->optionsF);
769 WMResizeWidget(panel->icommandL, width, 80);
770 WMMoveWidget(panel->icommandL, 10, 20);
772 WMSetListAction(panel->icommandL, icommandLClicked, panel);
774 WMAddNotificationObserver(dataChanged, panel, WMListSelectionDidChangeNotification, panel->icommandL);
776 WMInsertListItem(panel->icommandL, 0, _("Arrange Icons"));
777 WMInsertListItem(panel->icommandL, 1, _("Hide All Windows Except For The Focused One"));
778 WMInsertListItem(panel->icommandL, 2, _("Show All Windows"));
780 WMInsertListItem(panel->icommandL, 3, _("Exit Window Maker"));
781 WMInsertListItem(panel->icommandL, 4, _("Exit X Session"));
782 WMInsertListItem(panel->icommandL, 5, _("Restart Window Maker"));
783 WMInsertListItem(panel->icommandL, 6, _("Start Another Window Manager : ("));
785 WMInsertListItem(panel->icommandL, 7, _("Save Current Session"));
786 WMInsertListItem(panel->icommandL, 8, _("Clear Saved Session"));
787 WMInsertListItem(panel->icommandL, 9, _("Refresh Screen"));
788 WMInsertListItem(panel->icommandL, 10, _("Open Info Panel"));
789 WMInsertListItem(panel->icommandL, 11, _("Open Copyright Panel"));
791 panel->paramF = WMCreateFrame(panel->optionsF);
792 WMResizeWidget(panel->paramF, width, 50);
793 WMMoveWidget(panel->paramF, 10, 105);
794 WMSetFrameTitle(panel->paramF, _("Window Manager to Start"));
796 panel->paramT = WMCreateTextField(panel->paramF);
797 WMResizeWidget(panel->paramT, width - 20, 20);
798 WMMoveWidget(panel->paramT, 10, 20);
800 WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->paramT);
802 WMMapSubwidgets(panel->paramF);
804 panel->quickB = WMCreateSwitchButton(panel->optionsF);
805 WMResizeWidget(panel->quickB, width, 20);
806 WMMoveWidget(panel->quickB, 10, 120);
807 WMSetButtonText(panel->quickB, _("Do not confirm action."));
808 WMSetButtonAction(panel->quickB, buttonClicked, panel);
810 label = WMCreateLabel(panel->optionsF);
811 WMResizeWidget(label, width + 5, FRAME_HEIGHT - 50);
812 WMMoveWidget(label, 7, 20);
813 WMSetLabelText(label,
814 _("Instructions:\n\n"
815 " - drag items from the left to the menu to add new items\n"
816 " - drag items out of the menu to remove items\n"
817 " - drag items in menu to change their position\n"
818 " - drag items with Control pressed to copy them\n"
819 " - double click in a menu item to change the label\n"
820 " - click on a menu item to change related information"));
821 WMMapWidget(label);
823 WMRealizeWidget(panel->box);
824 WMMapSubwidgets(panel->box);
825 WMMapWidget(panel->box);
828 int i;
829 for (i = 0; i < 3; i++)
830 WMUnmapWidget(panel->itemPad[i]);
832 changedItemPad(panel->typeP, panel);
834 panel->sections[NoInfo][0] = label;
836 panel->sections[ExecInfo][0] = panel->commandF;
837 panel->sections[ExecInfo][1] = panel->shortF;
839 panel->sections[CommandInfo][0] = panel->icommandL;
840 panel->sections[CommandInfo][1] = panel->shortF;
842 panel->sections[ExternalInfo][0] = panel->pathF;
844 panel->sections[PipeInfo][0] = panel->pipeF;
846 panel->sections[DirectoryInfo][0] = panel->dpathF;
847 panel->sections[DirectoryInfo][1] = panel->dcommandF;
849 panel->currentType = NoInfo;
851 showData(panel);
854 WMPoint pos;
856 pos = WMGetViewScreenPosition(WMWidgetView(panel->box));
858 if (pos.x < 200) {
859 pos.x += FRAME_WIDTH + 20;
860 } else {
861 pos.x = 10;
864 pos.y = WMAX(pos.y - 100, 0);
866 if (panel->menu)
867 WEditMenuShowAt(panel->menu, pos.x, pos.y);
871 static void freeItemData(ItemData * data)
873 #define CFREE(d) if (d) wfree(d)
875 /* TODO */
876 switch (data->type) {
877 case CommandInfo:
878 CFREE(data->param.command.parameter);
879 CFREE(data->param.command.shortcut);
880 break;
882 case ExecInfo:
883 CFREE(data->param.exec.command);
884 CFREE(data->param.exec.shortcut);
885 break;
887 case PipeInfo:
888 CFREE(data->param.pipe.command);
889 break;
891 case ExternalInfo:
892 CFREE(data->param.external.path);
893 break;
895 case DirectoryInfo:
896 CFREE(data->param.directory.command);
897 CFREE(data->param.directory.directory);
898 break;
900 default:
901 break;
904 wfree(data);
905 #undef CFREE
908 static ItemData *parseCommand(WMPropList * item)
910 ItemData *data = NEW(ItemData);
911 WMPropList *p;
912 char *command = NULL;
913 char *parameter = NULL;
914 char *shortcut = NULL;
915 int i = 1;
917 p = WMGetFromPLArray(item, i++);
918 command = WMGetFromPLString(p);
919 if (strcmp(command, "SHORTCUT") == 0) {
920 p = WMGetFromPLArray(item, i++);
921 shortcut = WMGetFromPLString(p);
922 p = WMGetFromPLArray(item, i++);
923 command = WMGetFromPLString(p);
925 p = WMGetFromPLArray(item, i++);
926 if (p)
927 parameter = WMGetFromPLString(p);
929 if (strcmp(command, "EXEC") == 0 || strcmp(command, "SHEXEC") == 0) {
931 data->type = ExecInfo;
933 data->param.exec.command = wstrdup(parameter);
934 if (shortcut)
935 data->param.exec.shortcut = wstrdup(shortcut);
937 } else if (strcmp(command, "OPEN_MENU") == 0) {
938 char *p;
940 * dir menu, menu file
941 * dir WITH
942 * |pipe
944 p = parameter;
945 while (isspace(*p) && *p)
946 p++;
947 if (*p == '|') {
948 if (*(p + 1) == '|') {
949 p++;
950 data->param.pipe.cached = 0;
951 } else {
952 data->param.pipe.cached = 1;
954 data->type = PipeInfo;
955 data->param.pipe.command = wtrimspace(p + 1);
956 } else {
957 char *s;
959 p = wstrdup(p);
961 s = strstr(p, "WITH");
962 if (s) {
963 char **tokens;
964 char **ctokens;
965 int tokn;
966 int i, j;
968 data->type = DirectoryInfo;
970 *s = '\0';
971 s += 5;
972 while (*s && isspace(*s))
973 s++;
974 data->param.directory.command = wstrdup(s);
976 wtokensplit(p, &tokens, &tokn);
977 wfree(p);
979 ctokens = wmalloc(sizeof(char *) * tokn);
981 for (i = 0, j = 0; i < tokn; i++) {
982 if (strcmp(tokens[i], "-noext") == 0) {
983 data->param.directory.stripExt = 1;
984 } else {
985 ctokens[j++] = tokens[i];
988 data->param.directory.directory = wtokenjoin(ctokens, j);
989 wfree(ctokens);
991 wtokenfree(tokens, tokn);
992 } else {
993 data->type = ExternalInfo;
994 data->param.external.path = p;
997 } else if (strcmp(command, "WORKSPACE_MENU") == 0) {
998 data->type = WSMenuInfo;
999 } else if (strcmp(command, "WINDOWS_MENU") == 0) {
1000 data->type = WWindowListInfo;
1001 } else {
1002 int cmd;
1004 if (strcmp(command, "ARRANGE_ICONS") == 0) {
1005 cmd = 0;
1006 } else if (strcmp(command, "HIDE_OTHERS") == 0) {
1007 cmd = 1;
1008 } else if (strcmp(command, "SHOW_ALL") == 0) {
1009 cmd = 2;
1010 } else if (strcmp(command, "EXIT") == 0) {
1011 cmd = 3;
1012 } else if (strcmp(command, "SHUTDOWN") == 0) {
1013 cmd = 4;
1014 } else if (strcmp(command, "RESTART") == 0) {
1015 if (parameter) {
1016 cmd = 6;
1017 } else {
1018 cmd = 5;
1020 } else if (strcmp(command, "SAVE_SESSION") == 0) {
1021 cmd = 7;
1022 } else if (strcmp(command, "CLEAR_SESSION") == 0) {
1023 cmd = 8;
1024 } else if (strcmp(command, "REFRESH") == 0) {
1025 cmd = 9;
1026 } else if (strcmp(command, "INFO_PANEL") == 0) {
1027 cmd = 10;
1028 } else if (strcmp(command, "LEGAL_PANEL") == 0) {
1029 cmd = 11;
1030 } else {
1031 wwarning(_("unknown command '%s' in menu"), command);
1032 wfree(data);
1033 return NULL;
1036 data->type = CommandInfo;
1038 data->param.command.command = cmd;
1039 if (shortcut)
1040 data->param.command.shortcut = wstrdup(shortcut);
1041 if (parameter)
1042 data->param.command.parameter = wstrdup(parameter);
1045 return data;
1048 static void updateFrameTitle(_Panel * panel, char *title, InfoType type)
1050 if (type != NoInfo) {
1051 char *tmp;
1053 switch (type) {
1054 case ExecInfo:
1055 tmp = wstrconcat(title, _(": Execute Program"));
1056 break;
1058 case CommandInfo:
1059 tmp = wstrconcat(title, _(": Perform Internal Command"));
1060 break;
1062 case ExternalInfo:
1063 tmp = wstrconcat(title, _(": Open a Submenu"));
1064 break;
1066 case PipeInfo:
1067 tmp = wstrconcat(title, _(": Program Generated Submenu"));
1068 break;
1070 case DirectoryInfo:
1071 tmp = wstrconcat(title, _(": Directory Contents Menu"));
1072 break;
1074 case WSMenuInfo:
1075 tmp = wstrconcat(title, _(": Open Workspaces Submenu"));
1076 break;
1078 case WWindowListInfo:
1079 tmp = wstrconcat(title, _(": Open Window List Submenu"));
1080 break;
1082 default:
1083 tmp = NULL;
1084 break;
1086 WMSetFrameTitle(panel->optionsF, tmp);
1087 wfree(tmp);
1088 } else {
1089 WMSetFrameTitle(panel->optionsF, NULL);
1093 static void changeInfoType(_Panel * panel, char *title, InfoType type)
1095 WMWidget **w;
1097 if (panel->currentType != type) {
1099 w = panel->sections[panel->currentType];
1101 while (*w) {
1102 WMUnmapWidget(*w);
1103 w++;
1105 WMUnmapWidget(panel->paramF);
1106 WMUnmapWidget(panel->quickB);
1108 w = panel->sections[type];
1110 while (*w) {
1111 WMMapWidget(*w);
1112 w++;
1116 updateFrameTitle(panel, title, type);
1118 panel->currentType = type;
1121 static void updateMenuItem(_Panel * panel, WEditMenuItem * item, WMWidget * changedWidget)
1123 ItemData *data = WGetEditMenuItemData(item);
1125 assert(data != NULL);
1127 #define REPLACE(v, d) if (v) wfree(v); v = d
1129 switch (data->type) {
1130 case ExecInfo:
1131 if (changedWidget == panel->commandT) {
1132 REPLACE(data->param.exec.command, WMGetTextFieldText(panel->commandT));
1134 if (changedWidget == panel->shortT) {
1135 REPLACE(data->param.exec.shortcut, WMGetTextFieldText(panel->shortT));
1137 break;
1139 case CommandInfo:
1140 if (changedWidget == panel->icommandL) {
1141 data->param.command.command = WMGetListSelectedItemRow(panel->icommandL);
1143 switch (data->param.command.command) {
1144 case 3:
1145 case 4:
1146 if (changedWidget == panel->quickB) {
1147 REPLACE(data->param.command.parameter, WMGetButtonSelected(panel->quickB)
1148 ? wstrdup("QUICK") : NULL);
1150 break;
1152 case 6:
1153 if (changedWidget == panel->paramT) {
1154 REPLACE(data->param.command.parameter, WMGetTextFieldText(panel->paramT));
1156 break;
1158 if (changedWidget == panel->shortT) {
1159 REPLACE(data->param.command.shortcut, WMGetTextFieldText(panel->shortT));
1162 break;
1164 case PipeInfo:
1165 if (changedWidget == panel->pipeT) {
1166 REPLACE(data->param.pipe.command, WMGetTextFieldText(panel->pipeT));
1168 if (changedWidget == panel->pipeCacheB) {
1169 data->param.pipe.cached = WMGetButtonSelected(panel->pipeCacheB);
1171 break;
1173 case ExternalInfo:
1174 if (changedWidget == panel->pathT) {
1175 REPLACE(data->param.external.path, WMGetTextFieldText(panel->pathT));
1177 break;
1179 case DirectoryInfo:
1180 if (changedWidget == panel->dpathT) {
1181 REPLACE(data->param.directory.directory, WMGetTextFieldText(panel->dpathT));
1183 if (changedWidget == panel->dcommandT) {
1184 REPLACE(data->param.directory.command, WMGetTextFieldText(panel->dcommandT));
1186 if (changedWidget == panel->dstripB) {
1187 data->param.directory.stripExt = WMGetButtonSelected(panel->dstripB);
1189 break;
1191 default:
1192 assert(0);
1193 break;
1196 #undef REPLACE
1199 static void
1200 menuItemCloned(WEditMenuDelegate * delegate, WEditMenu * menu, WEditMenuItem * origItem, WEditMenuItem * newItem)
1202 ItemData *data = WGetEditMenuItemData(origItem);
1203 ItemData *newData;
1205 if (!data)
1206 return;
1208 #define DUP(s) (s) ? wstrdup(s) : NULL
1210 newData = NEW(ItemData);
1212 newData->type = data->type;
1214 switch (data->type) {
1215 case ExecInfo:
1216 newData->param.exec.command = DUP(data->param.exec.command);
1217 newData->param.exec.shortcut = DUP(data->param.exec.shortcut);
1218 break;
1220 case CommandInfo:
1221 newData->param.command.command = data->param.command.command;
1222 newData->param.command.parameter = DUP(data->param.command.parameter);
1223 newData->param.command.shortcut = DUP(data->param.command.shortcut);
1224 break;
1226 case PipeInfo:
1227 newData->param.pipe.command = DUP(data->param.pipe.command);
1228 newData->param.pipe.cached = data->param.pipe.cached;
1229 break;
1231 case ExternalInfo:
1232 newData->param.external.path = DUP(data->param.external.path);
1233 break;
1235 case DirectoryInfo:
1236 newData->param.directory.directory = DUP(data->param.directory.directory);
1237 newData->param.directory.command = DUP(data->param.directory.command);
1238 newData->param.directory.stripExt = data->param.directory.stripExt;
1239 break;
1241 default:
1242 break;
1245 #undef DUP
1247 WSetEditMenuItemData(newItem, newData, (WMCallback *) freeItemData);
1250 static void menuItemEdited(struct WEditMenuDelegate *delegate, WEditMenu * menu, WEditMenuItem * item)
1252 _Panel *panel = (_Panel *) delegate->data;
1253 WEditMenu *submenu;
1255 updateFrameTitle(panel, WGetEditMenuItemTitle(item), panel->currentType);
1257 submenu = WGetEditMenuSubmenu(menu, item);
1258 if (submenu) {
1259 WSetEditMenuTitle(submenu, WGetEditMenuItemTitle(item));
1263 static Bool shouldRemoveItem(struct WEditMenuDelegate *delegate, WEditMenu * menu, WEditMenuItem * item)
1265 _Panel *panel = (_Panel *) delegate->data;
1267 if (panel->dontAsk)
1268 return True;
1270 if (WGetEditMenuSubmenu(menu, item)) {
1271 int res;
1273 res = WMRunAlertPanel(WMWidgetScreen(menu), NULL,
1274 _("Remove Submenu"),
1275 _("Removing this item will destroy all items inside\n"
1276 "the submenu. Do you really want to do that?"),
1277 _("Yes"), _("No"), _("Yes, don't ask again."));
1278 switch (res) {
1279 case WAPRDefault:
1280 return True;
1281 case WAPRAlternate:
1282 return False;
1283 case WAPROther:
1284 panel->dontAsk = True;
1285 return True;
1288 return True;
1291 static void menuItemDeselected(WEditMenuDelegate * delegate, WEditMenu * menu, WEditMenuItem * item)
1293 _Panel *panel = (_Panel *) delegate->data;
1295 changeInfoType(panel, NULL, NoInfo);
1298 static void menuItemSelected(WEditMenuDelegate * delegate, WEditMenu * menu, WEditMenuItem * item)
1300 ItemData *data = WGetEditMenuItemData(item);
1301 _Panel *panel = (_Panel *) delegate->data;
1303 panel->currentItem = item;
1305 if (data) {
1306 changeInfoType(panel, WGetEditMenuItemTitle(item), data->type);
1308 switch (data->type) {
1309 case NoInfo:
1310 break;
1312 case ExecInfo:
1313 WMSetTextFieldText(panel->commandT, data->param.exec.command);
1314 WMSetTextFieldText(panel->shortT, data->param.exec.shortcut);
1315 break;
1317 case CommandInfo:
1318 WMSelectListItem(panel->icommandL, data->param.command.command);
1319 WMSetListPosition(panel->icommandL, data->param.command.command - 2);
1320 WMSetTextFieldText(panel->shortT, data->param.command.shortcut);
1322 switch (data->param.command.command) {
1323 case 3:
1324 case 4:
1325 WMSetButtonSelected(panel->quickB, data->param.command.parameter != NULL);
1326 break;
1327 case 6:
1328 WMSetTextFieldText(panel->paramT, data->param.command.parameter);
1329 break;
1332 icommandLClicked(panel->icommandL, panel);
1333 break;
1335 case PipeInfo:
1336 WMSetTextFieldText(panel->pipeT, data->param.pipe.command);
1337 WMSetButtonSelected(panel->pipeCacheB, data->param.pipe.cached);
1338 break;
1340 case ExternalInfo:
1341 WMSetTextFieldText(panel->pathT, data->param.external.path);
1342 break;
1344 case DirectoryInfo:
1345 WMSetTextFieldText(panel->dpathT, data->param.directory.directory);
1346 WMSetTextFieldText(panel->dcommandT, data->param.directory.command);
1347 WMSetButtonSelected(panel->dstripB, data->param.directory.stripExt);
1348 break;
1350 case WSMenuInfo:
1351 break;
1353 default:
1354 break;
1359 static WEditMenu *buildSubmenu(_Panel * panel, WMPropList * pl)
1361 WMScreen *scr = WMWidgetScreen(panel->parent);
1362 WEditMenu *menu;
1363 WEditMenuItem *item;
1364 char *title;
1365 WMPropList *tp, *bp;
1366 int i;
1368 tp = WMGetFromPLArray(pl, 0);
1369 title = WMGetFromPLString(tp);
1371 menu = WCreateEditMenu(scr, title);
1373 for (i = 1; i < WMGetPropListItemCount(pl); i++) {
1374 WMPropList *pi;
1376 pi = WMGetFromPLArray(pl, i);
1378 tp = WMGetFromPLArray(pi, 0);
1379 bp = WMGetFromPLArray(pi, 1);
1381 title = WMGetFromPLString(tp);
1383 if (!bp || WMIsPLArray(bp)) { /* it's a submenu */
1384 WEditMenu *submenu;
1386 submenu = buildSubmenu(panel, pi);
1388 item = WAddMenuItemWithTitle(menu, title);
1390 WSetEditMenuSubmenu(menu, item, submenu);
1391 } else {
1392 ItemData *data;
1394 data = parseCommand(pi);
1396 if (data != NULL) {
1397 item = WAddMenuItemWithTitle(menu, title);
1398 if (panel->markerPix[data->type])
1399 WSetEditMenuItemImage(item, panel->markerPix[data->type]);
1400 WSetEditMenuItemData(item, data, (WMCallback *) freeItemData);
1401 } else {
1402 char *buf = wmalloc(1024);
1403 snprintf(buf, 1024, _("Invalid menu command \"%s\" with label \"%s\" cleared"),
1404 WMGetFromPLString(WMGetFromPLArray(pi, 1)),
1405 WMGetFromPLString(WMGetFromPLArray(pi, 0)));
1406 WMRunAlertPanel(scr, panel->parent, _("Warning"), buf, _("OK"), NULL, NULL);
1407 wfree(buf);
1413 WSetEditMenuAcceptsDrop(menu, True);
1414 WSetEditMenuDelegate(menu, &menuDelegate);
1416 WMRealizeWidget(menu);
1418 return menu;
1421 static void buildMenuFromPL(_Panel * panel, WMPropList * pl)
1423 panel->menu = buildSubmenu(panel, pl);
1426 static WMPropList *getDefaultMenu(_Panel * panel)
1428 WMPropList *menu;
1429 char *menuPath, *gspath;
1431 gspath = wusergnusteppath();
1433 menuPath = wmalloc(strlen(gspath) + 128);
1434 sprintf(menuPath, "%s/Library/WindowMaker/plmenu", gspath);
1436 menu = WMReadPropListFromFile(menuPath);
1438 if (!menu) {
1439 char *buffer, *msg;
1441 msg = _("Could not open default menu from '%s'");
1442 buffer = wmalloc(strlen(msg) + strlen(menuPath) + 10);
1443 sprintf(buffer, msg, menuPath);
1444 WMRunAlertPanel(WMWidgetScreen(panel->parent), panel->parent,
1445 _("Error"), buffer, _("OK"), NULL, NULL);
1446 wfree(buffer);
1449 wfree(menuPath);
1451 return menu;
1454 static void showData(_Panel * panel)
1456 char *gspath;
1457 char *menuPath;
1458 WMPropList *pmenu;
1460 gspath = wusergnusteppath();
1462 menuPath = wmalloc(strlen(gspath) + 32);
1463 strcpy(menuPath, gspath);
1464 strcat(menuPath, "/Defaults/WMRootMenu");
1466 pmenu = WMReadPropListFromFile(menuPath);
1468 if (!pmenu || !WMIsPLArray(pmenu)) {
1469 int res;
1471 res = WMRunAlertPanel(WMWidgetScreen(panel->parent), panel->parent,
1472 _("Warning"),
1473 _("The menu file format currently in use is not supported\n"
1474 "by this tool. Do you want to discard the current menu\n"
1475 "to use this tool?"),
1476 _("Yes, Discard and Update"), _("No, Keep Current Menu"), NULL);
1478 if (res == WAPRDefault) {
1479 pmenu = getDefaultMenu(panel);
1481 if (!pmenu) {
1482 pmenu = WMCreatePLArray(WMCreatePLString("Applications"), NULL);
1484 } else {
1485 panel->dontSave = True;
1486 return;
1490 panel->menuPath = menuPath;
1492 buildMenuFromPL(panel, pmenu);
1494 WMReleasePropList(pmenu);
1497 static Bool notblank(char *s)
1499 if (s) {
1500 while (*s++) {
1501 if (!isspace(*s))
1502 return True;
1505 return False;
1508 static WMPropList *processData(char *title, ItemData * data)
1510 WMPropList *item;
1511 char *s1;
1512 static WMPropList *pscut = NULL;
1513 static WMPropList *pomenu = NULL;
1514 int i;
1516 if (data == NULL)
1517 return NULL;
1519 if (!pscut) {
1520 pscut = WMCreatePLString("SHORTCUT");
1521 pomenu = WMCreatePLString("OPEN_MENU");
1524 item = WMCreatePLArray(WMCreatePLString(title), NULL);
1526 switch (data->type) {
1527 case ExecInfo:
1528 if (data->param.exec.command == NULL)
1529 return NULL;
1530 #if 1
1531 if (strpbrk(data->param.exec.command, "&$*|><?`=;")) {
1532 s1 = "SHEXEC";
1533 } else {
1534 s1 = "EXEC";
1536 #else
1537 s1 = "SHEXEC";
1538 #endif
1540 if (notblank(data->param.exec.shortcut)) {
1541 WMAddToPLArray(item, pscut);
1542 WMAddToPLArray(item, WMCreatePLString(data->param.exec.shortcut));
1545 WMAddToPLArray(item, WMCreatePLString(s1));
1546 WMAddToPLArray(item, WMCreatePLString(data->param.exec.command));
1547 break;
1549 case CommandInfo:
1550 if (notblank(data->param.command.shortcut)) {
1551 WMAddToPLArray(item, pscut);
1552 WMAddToPLArray(item, WMCreatePLString(data->param.command.shortcut));
1555 i = data->param.command.command;
1557 WMAddToPLArray(item, WMCreatePLString(commandNames[i]));
1559 switch (i) {
1560 case 3:
1561 case 4:
1562 if (data->param.command.parameter) {
1563 WMAddToPLArray(item, WMCreatePLString(data->param.command.parameter));
1565 break;
1567 case 6: /* restart */
1568 if (data->param.command.parameter) {
1569 WMAddToPLArray(item, WMCreatePLString(data->param.command.parameter));
1571 break;
1574 break;
1576 case PipeInfo:
1577 if (!data->param.pipe.command)
1578 return NULL;
1579 WMAddToPLArray(item, pomenu);
1580 if (data->param.pipe.cached)
1581 s1 = wstrconcat("| ", data->param.pipe.command);
1582 else
1583 s1 = wstrconcat("|| ", data->param.pipe.command);
1584 WMAddToPLArray(item, WMCreatePLString(s1));
1585 wfree(s1);
1586 break;
1588 case ExternalInfo:
1589 if (!data->param.external.path)
1590 return NULL;
1591 WMAddToPLArray(item, pomenu);
1592 WMAddToPLArray(item, WMCreatePLString(data->param.external.path));
1593 break;
1595 case DirectoryInfo:
1596 if (!data->param.directory.directory || !data->param.directory.command)
1597 return NULL;
1599 int l;
1600 char *tmp;
1602 l = strlen(data->param.directory.directory);
1603 l += strlen(data->param.directory.command);
1604 l += 32;
1606 WMAddToPLArray(item, pomenu);
1608 tmp = wmalloc(l);
1609 sprintf(tmp, "%s%s WITH %s",
1610 data->param.directory.stripExt ? "-noext " : "",
1611 data->param.directory.directory, data->param.directory.command);
1613 WMAddToPLArray(item, WMCreatePLString(tmp));
1614 wfree(tmp);
1616 break;
1618 case WSMenuInfo:
1619 WMAddToPLArray(item, WMCreatePLString("WORKSPACE_MENU"));
1620 break;
1622 case WWindowListInfo:
1623 WMAddToPLArray(item, WMCreatePLString("WINDOWS_MENU"));
1624 break;
1626 default:
1627 assert(0);
1628 break;
1631 return item;
1634 static WMPropList *processSubmenu(WEditMenu * menu)
1636 WEditMenuItem *item;
1637 WMPropList *pmenu;
1638 WMPropList *pl;
1639 char *s;
1640 int i;
1642 s = WGetEditMenuTitle(menu);
1643 pl = WMCreatePLString(s);
1645 pmenu = WMCreatePLArray(pl, NULL);
1647 i = 0;
1648 while ((item = WGetEditMenuItem(menu, i++))) {
1649 WEditMenu *submenu;
1651 s = WGetEditMenuItemTitle(item);
1653 submenu = WGetEditMenuSubmenu(menu, item);
1654 if (submenu) {
1655 pl = processSubmenu(submenu);
1656 } else {
1657 pl = processData(s, WGetEditMenuItemData(item));
1660 if (!pl)
1661 continue;
1663 WMAddToPLArray(pmenu, pl);
1666 return pmenu;
1669 static WMPropList *buildPLFromMenu(_Panel * panel)
1671 WMPropList *menu;
1673 menu = processSubmenu(panel->menu);
1675 return menu;
1678 static void storeData(_Panel * panel)
1680 WMPropList *menu;
1682 if (panel->dontSave)
1683 return;
1685 menu = buildPLFromMenu(panel);
1687 WMWritePropListToFile(menu, panel->menuPath);
1689 WMReleasePropList(menu);
1692 static void showMenus(_Panel * panel)
1694 if (panel->menu)
1695 WEditMenuUnhide(panel->menu);
1698 static void hideMenus(_Panel * panel)
1700 if (panel->menu)
1701 WEditMenuHide(panel->menu);
1704 Panel *InitMenu(WMScreen * scr, WMWidget * parent)
1706 _Panel *panel;
1708 panel = wmalloc(sizeof(_Panel));
1709 memset(panel, 0, sizeof(_Panel));
1711 panel->sectionName = _("Applications Menu Definition");
1713 panel->description = _("Edit the menu for launching applications.");
1715 panel->parent = parent;
1717 panel->callbacks.createWidgets = createPanel;
1718 panel->callbacks.updateDomain = storeData;
1719 panel->callbacks.showPanel = showMenus;
1720 panel->callbacks.hidePanel = hideMenus;
1722 AddSection(panel, ICON_FILE);
1724 return panel;