- fixed a frame size in WPrefs menu editor
[wmaker-crm.git] / WPrefs.app / Menu.c
blobd7027df8cbf1e2cde75c4fa1fa7766c20fedb28d
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 *browseB;
80 WMButton *xtermC; /* inside xterm? */
82 WMFrame *pathF;
83 WMTextField *pathT;
85 WMFrame *pipeF;
86 WMTextField *pipeT;
87 WMButton *pipeCacheB;
89 WMFrame *dpathF;
90 WMTextField *dpathT;
92 WMFrame *dcommandF;
93 WMTextField *dcommandT;
95 WMButton *dstripB;
97 WMFrame *shortF;
98 WMTextField *shortT;
99 WMButton *sgrabB;
100 WMButton *sclearB;
102 WMList *icommandL;
104 WMFrame *paramF;
105 WMTextField *paramT;
107 WMButton *quickB;
109 Bool dontAsk; /* whether to comfirm submenu remove */
110 Bool dontSave;
112 Bool capturing;
115 /* about the currently selected item */
116 WEditMenuItem *currentItem;
117 InfoType currentType;
118 WMWidget *sections[LastInfo][MAX_SECTION_SIZE];
119 } _Panel;
122 typedef struct {
123 InfoType type;
124 union {
125 struct {
126 int command;
127 char *parameter;
128 char *shortcut;
129 } command;
130 struct {
131 char *command;
132 char *shortcut;
133 } exec;
134 struct {
135 char *path;
136 } external;
137 struct {
138 char *command;
139 unsigned cached:1;
140 } pipe;
141 struct {
142 char *directory;
143 char *command;
144 unsigned stripExt:1;
145 } directory;
146 } param;
147 } ItemData;
151 static char *commandNames[] = {
152 "ARRANGE_ICONS",
153 "HIDE_OTHERS",
154 "SHOW_ALL",
155 "EXIT",
156 "SHUTDOWN",
157 "RESTART",
158 "RESTART",
159 "SAVE_SESSION",
160 "CLEAR_SESSION",
161 "REFRESH",
162 "INFO_PANEL",
163 "LEGAL_PANEL"
168 #define NEW(type) memset(wmalloc(sizeof(type)), 0, sizeof(type))
171 #define ICON_FILE "menus"
175 static void showData(_Panel *panel);
178 static void updateMenuItem(_Panel *panel, WEditMenuItem *item,
179 WMWidget *changedWidget);
181 static void menuItemSelected(struct WEditMenuDelegate *delegate,
182 WEditMenu *menu, WEditMenuItem *item);
184 static void menuItemDeselected(struct WEditMenuDelegate *delegate,
185 WEditMenu *menu, WEditMenuItem *item);
187 static void menuItemCloned(struct WEditMenuDelegate *delegate, WEditMenu *menu,
188 WEditMenuItem *origItem, WEditMenuItem *newItem);
190 static void menuItemEdited(struct WEditMenuDelegate *delegate, WEditMenu *menu,
191 WEditMenuItem *item);
193 static Bool shouldRemoveItem(struct WEditMenuDelegate *delegate,
194 WEditMenu *menu, WEditMenuItem *item);
197 static void freeItemData(ItemData *data);
201 static WEditMenuDelegate menuDelegate = {
202 NULL,
203 menuItemCloned,
204 menuItemEdited,
205 menuItemSelected,
206 menuItemDeselected,
207 shouldRemoveItem
211 static void
212 dataChanged(void *self, WMNotification *notif)
214 _Panel *panel = (_Panel*)self;
215 WEditMenuItem *item = panel->currentItem;
216 WMWidget *w = (WMWidget*)WMGetNotificationObject(notif);
218 updateMenuItem(panel, item, w);
222 static void
223 buttonClicked(WMWidget *w, void *data)
225 _Panel *panel = (_Panel*)data;
226 WEditMenuItem *item = panel->currentItem;
228 updateMenuItem(panel, item, w);
232 static void
233 icommandLClicked(WMWidget *w, void *data)
235 _Panel *panel = (_Panel*)data;
236 int cmd;
238 cmd = WMGetListSelectedItemRow(w);
239 if (cmd == 3 || cmd == 4) {
240 WMMapWidget(panel->quickB);
241 } else {
242 WMUnmapWidget(panel->quickB);
244 if (cmd == 6) {
245 WMMapWidget(panel->paramF);
246 } else {
247 WMUnmapWidget(panel->paramF);
252 static void
253 browseForFile(WMWidget *self, void *clientData)
255 _Panel *panel = (_Panel*)clientData;
256 WMFilePanel *filePanel;
257 char *text, *oldprog, *newprog;
259 filePanel = WMGetOpenPanel(WMWidgetScreen(self));
260 text = WMGetTextFieldText(panel->commandT);
262 oldprog = wtrimspace(text);
263 wfree(text);
265 if (oldprog[0]==0 || oldprog[0]!='/') {
266 wfree(oldprog);
267 oldprog = wstrdup("/");
268 } else {
269 char *ptr = oldprog;
270 while (*ptr && !isspace(*ptr))
271 ptr++;
272 *ptr = 0;
275 WMSetFilePanelCanChooseDirectories(filePanel, False);
277 if (WMRunModalFilePanelForDirectory(filePanel, panel->parent, oldprog,
278 _("Select Program"), NULL)==True) {
279 newprog = WMGetFilePanelFileName(filePanel);
280 WMSetTextFieldText(panel->commandT, newprog);
281 updateMenuItem(panel, panel->currentItem, panel->commandT);
282 wfree(newprog);
285 wfree(oldprog);
289 static char*
290 captureShortcut(Display *dpy, _Panel *panel)
292 XEvent ev;
293 KeySym ksym;
294 char buffer[64];
295 char *key = NULL;
297 while (panel->capturing) {
298 XAllowEvents(dpy, AsyncKeyboard, CurrentTime);
299 WMNextEvent(dpy, &ev);
300 if (ev.type==KeyPress && ev.xkey.keycode!=0) {
301 ksym = XKeycodeToKeysym(dpy, ev.xkey.keycode, 0);
302 if (!IsModifierKey(ksym)) {
303 key=XKeysymToString(ksym);
304 panel->capturing = 0;
305 break;
308 WMHandleEvent(&ev);
311 if (!key)
312 return NULL;
314 buffer[0] = 0;
316 if (ev.xkey.state & ControlMask) {
317 strcat(buffer, "Control+");
319 if (ev.xkey.state & ShiftMask) {
320 strcat(buffer, "Shift+");
322 if (ev.xkey.state & Mod1Mask) {
323 strcat(buffer, "Mod1+");
325 if (ev.xkey.state & Mod2Mask) {
326 strcat(buffer, "Mod2+");
328 if (ev.xkey.state & Mod3Mask) {
329 strcat(buffer, "Mod3+");
331 if (ev.xkey.state & Mod4Mask) {
332 strcat(buffer, "Mod4+");
334 if (ev.xkey.state & Mod5Mask) {
335 strcat(buffer, "Mod5+");
337 strcat(buffer, key);
339 return wstrdup(buffer);
344 static void
345 sgrabClicked(WMWidget *w, void *data)
347 _Panel *panel = (_Panel*)data;
348 Display *dpy = WMScreenDisplay(WMWidgetScreen(panel->parent));
349 char *shortcut;
352 if (w == panel->sclearB) {
353 WMSetTextFieldText(panel->shortT, "");
354 updateMenuItem(panel, panel->currentItem, panel->shortT);
355 return;
358 if (!panel->capturing) {
359 panel->capturing = 1;
360 WMSetButtonText(w, _("Cancel"));
361 XGrabKeyboard(dpy, WMWidgetXID(panel->parent), True, GrabModeAsync,
362 GrabModeAsync, CurrentTime);
363 shortcut = captureShortcut(dpy, panel);
364 if (shortcut) {
365 WMSetTextFieldText(panel->shortT, shortcut);
366 updateMenuItem(panel, panel->currentItem, panel->shortT);
367 wfree(shortcut);
370 panel->capturing = 0;
371 WMSetButtonText(w, _("Capture"));
372 XUngrabKeyboard(dpy, CurrentTime);
376 static void
377 changedItemPad(WMWidget *w, void *data)
379 _Panel *panel = (_Panel*)data;
380 int padn = WMGetPopUpButtonSelectedItem(w);
382 WMUnmapWidget(panel->itemPad[panel->currentPad]);
383 WMMapWidget(panel->itemPad[padn]);
385 panel->currentPad = padn;
389 static WEditMenu*
390 putNewSubmenu(WEditMenu *menu, char *title)
392 WEditMenu *tmp;
393 WEditMenuItem *item;
395 item = WAddMenuItemWithTitle(menu, title);
397 tmp = WCreateEditMenu(WMWidgetScreen(menu), title);
398 WSetEditMenuAcceptsDrop(tmp, True);
399 WSetEditMenuDelegate(tmp, &menuDelegate);
400 WSetEditMenuSubmenu(menu, item, tmp);
402 return tmp;
406 static ItemData*
407 putNewItem(_Panel *panel, WEditMenu *menu, int type, char *title)
409 WEditMenuItem *item;
410 ItemData *data;
412 item = WAddMenuItemWithTitle(menu, title);
414 data = NEW(ItemData);
415 data->type = type;
416 WSetEditMenuItemData(item, data, (WMCallback*)freeItemData);
417 WSetEditMenuItemImage(item, panel->markerPix[type]);
419 return data;
423 static WEditMenu*
424 makeFactoryMenu(WMWidget *parent, int width)
426 WEditMenu *pad;
428 pad = WCreateEditMenuPad(parent);
429 WMResizeWidget(pad, width, 10);
430 WSetEditMenuMinSize(pad, wmksize(width, 0));
431 WSetEditMenuMaxSize(pad, wmksize(width, 0));
432 WSetEditMenuSelectable(pad, False);
433 WSetEditMenuEditable(pad, False);
434 WSetEditMenuIsFactory(pad, True);
435 WSetEditMenuDelegate(pad, &menuDelegate);
437 return pad;
441 static void
442 createPanel(_Panel *p)
444 _Panel *panel = (_Panel*)p;
445 WMScreen *scr = WMWidgetScreen(panel->parent);
446 WMColor *black = WMBlackColor(scr);
447 WMColor *white = WMWhiteColor(scr);
448 WMColor *gray = WMGrayColor(scr);
449 WMFont *bold = WMBoldSystemFontOfSize(scr, 12);
450 WMFont *font = WMSystemFontOfSize(scr, 12);
451 WMLabel *label;
452 int width;
455 menuDelegate.data = panel;
458 panel->boldFont = bold;
459 panel->normalFont = font;
461 panel->black = black;
462 panel->white = white;
463 panel->gray = gray;
466 Pixmap pix;
467 Display *dpy = WMScreenDisplay(scr);
468 GC gc;
469 WMPixmap *pixm;
471 pixm = WMCreatePixmap(scr, 7, 7, WMScreenDepth(scr), True);
473 pix = WMGetPixmapXID(pixm);
475 XDrawLine(dpy, pix, WMColorGC(black), 0, 3, 6, 3);
476 XDrawLine(dpy, pix, WMColorGC(black), 3, 0, 3, 6);
478 XDrawLine(dpy, pix, WMColorGC(black), 1, 0, 3, 3);
479 XDrawLine(dpy, pix, WMColorGC(black), 1, 6, 3, 3);
480 XDrawLine(dpy, pix, WMColorGC(black), 0, 0, 0, 6);
483 pix = WMGetPixmapMaskXID(pixm);
485 gc = XCreateGC(dpy, pix, 0, NULL);
487 XSetForeground(dpy, gc, 0);
488 XFillRectangle(dpy, pix, gc, 0, 0, 7, 7);
490 XSetForeground(dpy, gc, 1);
491 XDrawLine(dpy, pix, gc, 0, 3, 6, 3);
492 XDrawLine(dpy, pix, gc, 3, 0, 3, 6);
494 panel->markerPix[ExternalInfo] = pixm;
495 panel->markerPix[PipeInfo] = pixm;
496 panel->markerPix[DirectoryInfo] = pixm;
497 panel->markerPix[WSMenuInfo] = pixm;
498 panel->markerPix[WWindowListInfo] = pixm;
500 XFreeGC(dpy, gc);
503 panel->box = WMCreateBox(panel->parent);
504 WMSetViewExpandsToParent(WMWidgetView(panel->box), 2, 2, 2, 2);
506 panel->typeP = WMCreatePopUpButton(panel->box);
507 WMResizeWidget(panel->typeP, 150, 20);
508 WMMoveWidget(panel->typeP, 10, 10);
510 WMAddPopUpButtonItem(panel->typeP, _("New Items"));
511 WMAddPopUpButtonItem(panel->typeP, _("Sample Commands"));
512 WMAddPopUpButtonItem(panel->typeP, _("Sample Submenus"));
514 WMSetPopUpButtonAction(panel->typeP, changedItemPad, panel);
516 WMSetPopUpButtonSelectedItem(panel->typeP, 0);
519 WEditMenu *pad;
520 WEditMenu *smenu;
521 ItemData *data;
523 pad = makeFactoryMenu(panel->box, 150);
524 WMMoveWidget(pad, 10, 40);
526 data = putNewItem(panel, pad, ExecInfo, _("Run Program"));
527 data = putNewItem(panel, pad, CommandInfo, _("Internal Command"));
528 smenu = putNewSubmenu(pad, _("Submenu"));
529 data = putNewItem(panel, pad, ExternalInfo, _("External Submenu"));
530 data = putNewItem(panel, pad, PipeInfo, _("Generated Submenu"));
531 data = putNewItem(panel, pad, DirectoryInfo, _("Directory Contents"));
532 data = putNewItem(panel, pad, WSMenuInfo, _("Workspace Menu"));
533 data = putNewItem(panel, pad, WWindowListInfo, _("Window List Menu"));
535 panel->itemPad[0] = pad;
539 WEditMenu *pad;
540 ItemData *data;
541 WMScrollView *sview;
543 sview = WMCreateScrollView(panel->box);
544 WMResizeWidget(sview, 150, 180);
545 WMMoveWidget(sview, 10, 40);
546 WMSetScrollViewHasVerticalScroller(sview, True);
548 pad = makeFactoryMenu(panel->box, 130);
550 WMSetScrollViewContentView(sview, WMWidgetView(pad));
552 data = putNewItem(panel, pad, ExecInfo, _("XTerm"));
553 data->param.exec.command = "xterm -sb -sl 2000 -bg black -fg white";
555 data = putNewItem(panel, pad, ExecInfo, _("rxvt"));
556 data->param.exec.command = "rxvt";
558 data = putNewItem(panel, pad, ExecInfo, _("ETerm"));
559 data->param.exec.command = "eterm";
561 data = putNewItem(panel, pad, ExecInfo, _("Run..."));
562 data->param.exec.command = _("%a(Run,Type command to run)");
564 data = putNewItem(panel, pad, ExecInfo, _("Netscape"));
565 data->param.exec.command = "netscape";
567 data = putNewItem(panel, pad, ExecInfo, _("gimp"));
568 data->param.exec.command = "gimp";
570 data = putNewItem(panel, pad, ExecInfo, _("epic"));
571 data->param.exec.command = "xterm -e epic";
573 data = putNewItem(panel, pad, ExecInfo, _("ee"));
574 data->param.exec.command = "ee";
576 data = putNewItem(panel, pad, ExecInfo, _("xv"));
577 data->param.exec.command = "xv";
579 data = putNewItem(panel, pad, ExecInfo, _("Acrobat Reader"));
580 data->param.exec.command = "acroread || /usr/local/Acrobat4/bin/acroread";
582 data = putNewItem(panel, pad, ExecInfo, _("ghostview"));
583 data->param.exec.command = "gv";
585 data = putNewItem(panel, pad, CommandInfo, _("Exit Window Maker"));
586 data->param.command.command = 3;
588 WMMapWidget(pad);
590 panel->itemPad[1] = sview;
595 WEditMenu *pad, *smenu;
596 ItemData *data;
597 WMScrollView *sview;
599 sview = WMCreateScrollView(panel->box);
600 WMResizeWidget(sview, 150, 180);
601 WMMoveWidget(sview, 10, 40);
602 WMSetScrollViewHasVerticalScroller(sview, True);
604 pad = makeFactoryMenu(panel->box, 130);
606 WMSetScrollViewContentView(sview, WMWidgetView(pad));
608 data = putNewItem(panel, pad, ExternalInfo, _("Debian Menu"));
609 data->param.pipe.command = "/etc/X11/WindowMaker/menu.hook";
611 data = putNewItem(panel, pad, PipeInfo, _("RedHat Menu"));
612 data->param.pipe.command = "wmconfig --output wmaker";
614 data = putNewItem(panel, pad, PipeInfo, _("Menu Conectiva"));
615 data->param.pipe.command = "wmconfig --output wmaker";
617 data = putNewItem(panel, pad, DirectoryInfo, _("Themes"));
618 data->param.directory.command = "setstyle";
619 data->param.directory.directory = "/usr/share/WindowMaker/Themes /usr/local/share/WindowMaker/Themes $HOME/GNUstep/Library/WindowMaker/Themes";
620 data->param.directory.stripExt = 1;
622 data = putNewItem(panel, pad, DirectoryInfo, _("Bg Images (scale)"));
623 data->param.directory.command = "wmsetbg -u -s";
624 data->param.directory.directory = "/opt/kde2/share/wallpapers /usr/share/WindowMaker/Backgrounds $HOME/GNUstep/Library/WindowMaker/Backgrounds";
625 data->param.directory.stripExt = 1;
627 data = putNewItem(panel, pad, DirectoryInfo, _("Bg Images (tile)"));
628 data->param.directory.command = "wmsetbg -u -t";
629 data->param.directory.directory = "/opt/kde2/share/wallpapers /usr/share/WindowMaker/Backgrounds $HOME/GNUstep/Library/WindowMaker/Backgrounds";
630 data->param.directory.stripExt = 1;
632 smenu = putNewSubmenu(pad, _("Assorted XTerms"));
634 data = putNewItem(panel, smenu, ExecInfo, _("XTerm Yellow on Blue"));
635 data->param.exec.command = "xterm -sb -sl 2000 -bg midnightblue -fg yellow";
637 data = putNewItem(panel, smenu, ExecInfo, _("XTerm White on Black"));
638 data->param.exec.command = "xterm -sb -sl 2000 -bg black -fg white";
640 data = putNewItem(panel, smenu, ExecInfo, _("XTerm Black on White"));
641 data->param.exec.command = "xterm -sb -sl 2000 -bg white -fg black";
643 data = putNewItem(panel, smenu, ExecInfo, _("XTerm Black on Beige"));
644 data->param.exec.command = "xterm -sb -sl 2000 -bg '#bbbb99' -fg black";
646 data = putNewItem(panel, smenu, ExecInfo, _("XTerm White on Green"));
647 data->param.exec.command = "xterm -sb -sl 2000 -bg '#228822' -fg white";
649 data = putNewItem(panel, smenu, ExecInfo, _("XTerm White on Olive"));
650 data->param.exec.command = "xterm -sb -sl 2000 -bg '#335533' -fg white";
652 data = putNewItem(panel, smenu, ExecInfo, _("XTerm Blue on Blue"));
653 data->param.exec.command = "xterm -sb -sl 2000 -bg '#112244' -fg '#88aabb'";
655 data = putNewItem(panel, smenu, ExecInfo, _("XTerm BIG FONTS"));
656 data->param.exec.command = "xterm -sb -sl 2000 -bg black -fg white -fn 10x20";
658 WMMapWidget(pad);
660 panel->itemPad[2] = sview;
664 width = FRAME_WIDTH - 20 - 150 - 10 - 2;
666 panel->optionsF = WMCreateFrame(panel->box);
667 WMResizeWidget(panel->optionsF, width, FRAME_HEIGHT - 15);
668 WMMoveWidget(panel->optionsF, 10 + 150 + 10, 5);
670 width -= 20;
672 /* command */
674 panel->commandF = WMCreateFrame(panel->optionsF);
675 WMResizeWidget(panel->commandF, width, 50);
676 WMMoveWidget(panel->commandF, 10, 20);
677 WMSetFrameTitle(panel->commandF, _("Program to Run"));
678 WMSetFrameTitlePosition(panel->commandF, WTPAtTop);
680 panel->commandT = WMCreateTextField(panel->commandF);
681 WMResizeWidget(panel->commandT, width - 95, 20);
682 WMMoveWidget(panel->commandT, 10, 20);
684 panel->browseB = WMCreateCommandButton(panel->commandF);
685 WMResizeWidget(panel->browseB, 70, 24);
686 WMMoveWidget(panel->browseB, width - 80, 18);
687 WMSetButtonText(panel->browseB, _("Browse"));
688 WMSetButtonAction(panel->browseB, browseForFile, panel);
690 WMAddNotificationObserver(dataChanged, panel,
691 WMTextDidChangeNotification,
692 panel->commandT);
694 #if 0
695 panel->xtermC = WMCreateSwitchButton(panel->commandF);
696 WMResizeWidget(panel->xtermC, width - 20, 20);
697 WMMoveWidget(panel->xtermC, 10, 50);
698 WMSetButtonText(panel->xtermC, _("Run the program inside a Xterm"));
699 #endif
700 WMMapSubwidgets(panel->commandF);
703 /* path */
705 panel->pathF = WMCreateFrame(panel->optionsF);
706 WMResizeWidget(panel->pathF, width, 150);
707 WMMoveWidget(panel->pathF, 10, 40);
708 WMSetFrameTitle(panel->pathF, _("Path for Menu"));
710 panel->pathT = WMCreateTextField(panel->pathF);
711 WMResizeWidget(panel->pathT, width - 20, 20);
712 WMMoveWidget(panel->pathT, 10, 20);
714 WMAddNotificationObserver(dataChanged, panel,
715 WMTextDidChangeNotification,
716 panel->pathT);
718 label = WMCreateLabel(panel->pathF);
719 WMResizeWidget(label, width - 20, 80);
720 WMMoveWidget(label, 10, 50);
721 WMSetLabelText(label, _("Enter the path for a file containing a menu\n"
722 "or a list of directories with the programs you\n"
723 "want to have listed in the menu. Ex:\n"
724 "~/GNUstep/Library/WindowMaker/menu\n"
725 "or\n"
726 "/usr/X11R6/bin ~/xbin"));
728 WMMapSubwidgets(panel->pathF);
731 /* pipe */
733 panel->pipeF = WMCreateFrame(panel->optionsF);
734 WMResizeWidget(panel->pipeF, width, 155);
735 WMMoveWidget(panel->pipeF, 10, 30);
736 WMSetFrameTitle(panel->pipeF, _("Command"));
738 panel->pipeT = WMCreateTextField(panel->pipeF);
739 WMResizeWidget(panel->pipeT, width - 20, 20);
740 WMMoveWidget(panel->pipeT, 10, 20);
742 WMAddNotificationObserver(dataChanged, panel,
743 WMTextDidChangeNotification,
744 panel->pipeT);
747 label = WMCreateLabel(panel->pipeF);
748 WMResizeWidget(label, width - 20, 40);
749 WMMoveWidget(label, 10, 50);
750 WMSetLabelText(label, _("Enter a command that outputs a menu\n"
751 "definition to stdout when invoked."));
754 panel->pipeCacheB = WMCreateSwitchButton(panel->pipeF);
755 WMResizeWidget(panel->pipeCacheB, width - 20, 40);
756 WMMoveWidget(panel->pipeCacheB, 10, 110);
757 WMSetButtonText(panel->pipeCacheB,
758 _("Cache menu contents after opening for\n"
759 "the first time"));
761 WMMapSubwidgets(panel->pipeF);
764 /* directory menu */
766 panel->dcommandF = WMCreateFrame(panel->optionsF);
767 WMResizeWidget(panel->dcommandF, width, 90);
768 WMMoveWidget(panel->dcommandF, 10, 25);
769 WMSetFrameTitle(panel->dcommandF, _("Command to Open Files"));
771 panel->dcommandT = WMCreateTextField(panel->dcommandF);
772 WMResizeWidget(panel->dcommandT, width - 20, 20);
773 WMMoveWidget(panel->dcommandT, 10, 20);
775 WMAddNotificationObserver(dataChanged, panel,
776 WMTextDidChangeNotification,
777 panel->dcommandT);
780 label = WMCreateLabel(panel->dcommandF);
781 WMResizeWidget(label, width - 20, 45);
782 WMMoveWidget(label, 10, 40);
783 WMSetLabelText(label, _("Enter the command you want to use to open the\n"
784 "files in the directories listed below."));
786 WMMapSubwidgets(panel->dcommandF);
789 panel->dpathF = WMCreateFrame(panel->optionsF);
790 WMResizeWidget(panel->dpathF, width, 80);
791 WMMoveWidget(panel->dpathF, 10, 125);
792 WMSetFrameTitle(panel->dpathF, _("Directories with Files"));
794 panel->dpathT = WMCreateTextField(panel->dpathF);
795 WMResizeWidget(panel->dpathT, width - 20, 20);
796 WMMoveWidget(panel->dpathT, 10, 20);
798 WMAddNotificationObserver(dataChanged, panel,
799 WMTextDidChangeNotification,
800 panel->dpathT);
802 panel->dstripB = WMCreateSwitchButton(panel->dpathF);
803 WMResizeWidget(panel->dstripB, width - 20, 20);
804 WMMoveWidget(panel->dstripB, 10, 50);
805 WMSetButtonText(panel->dstripB, _("Strip extensions from file names"));
807 WMSetButtonAction(panel->dstripB, buttonClicked, panel);
809 WMMapSubwidgets(panel->dpathF);
812 /* shortcut */
814 panel->shortF = WMCreateFrame(panel->optionsF);
815 WMResizeWidget(panel->shortF, width, 50);
816 WMMoveWidget(panel->shortF, 10, 160);
817 WMSetFrameTitle(panel->shortF, _("Keyboard Shortcut"));
819 panel->shortT = WMCreateTextField(panel->shortF);
820 WMResizeWidget(panel->shortT, width - 20 - 150, 20);
821 WMMoveWidget(panel->shortT, 10, 20);
823 WMAddNotificationObserver(dataChanged, panel,
824 WMTextDidChangeNotification,
825 panel->shortT);
827 panel->sgrabB = WMCreateCommandButton(panel->shortF);
828 WMResizeWidget(panel->sgrabB, 70, 24);
829 WMMoveWidget(panel->sgrabB, width - 80, 18);
830 WMSetButtonText(panel->sgrabB, _("Capture"));
831 WMSetButtonAction(panel->sgrabB, sgrabClicked, panel);
833 panel->sclearB = WMCreateCommandButton(panel->shortF);
834 WMResizeWidget(panel->sclearB, 70, 24);
835 WMMoveWidget(panel->sclearB, width - 155, 18);
836 WMSetButtonText(panel->sclearB, _("Clear"));
837 WMSetButtonAction(panel->sclearB, sgrabClicked, panel);
839 WMMapSubwidgets(panel->shortF);
841 /* internal command */
843 panel->icommandL = WMCreateList(panel->optionsF);
844 WMResizeWidget(panel->icommandL, width, 80);
845 WMMoveWidget(panel->icommandL, 10, 20);
847 WMSetListAction(panel->icommandL, icommandLClicked, panel);
849 WMAddNotificationObserver(dataChanged, panel,
850 WMListSelectionDidChangeNotification,
851 panel->icommandL);
853 WMInsertListItem(panel->icommandL, 0, _("Arrange Icons"));
854 WMInsertListItem(panel->icommandL, 1, _("Hide All Windows Except For The Focused One"));
855 WMInsertListItem(panel->icommandL, 2, _("Show All Windows"));
857 WMInsertListItem(panel->icommandL, 3, _("Exit Window Maker"));
858 WMInsertListItem(panel->icommandL, 4, _("Exit X Session"));
859 WMInsertListItem(panel->icommandL, 5, _("Restart Window Maker"));
860 WMInsertListItem(panel->icommandL, 6, _("Start Another Window Manager : ("));
862 WMInsertListItem(panel->icommandL, 7, _("Save Current Session"));
863 WMInsertListItem(panel->icommandL, 8, _("Clear Saved Session"));
864 WMInsertListItem(panel->icommandL, 9, _("Refresh Screen"));
865 WMInsertListItem(panel->icommandL, 10, _("Open Info Panel"));
866 WMInsertListItem(panel->icommandL, 11, _("Open Copyright Panel"));
869 panel->paramF = WMCreateFrame(panel->optionsF);
870 WMResizeWidget(panel->paramF, width, 50);
871 WMMoveWidget(panel->paramF, 10, 105);
872 WMSetFrameTitle(panel->paramF, _("Window Manager to Start"));
874 panel->paramT = WMCreateTextField(panel->paramF);
875 WMResizeWidget(panel->paramT, width - 20, 20);
876 WMMoveWidget(panel->paramT, 10, 20);
878 WMAddNotificationObserver(dataChanged, panel,
879 WMTextDidChangeNotification,
880 panel->paramT);
882 WMMapSubwidgets(panel->paramF);
885 panel->quickB = WMCreateSwitchButton(panel->optionsF);
886 WMResizeWidget(panel->quickB, width, 20);
887 WMMoveWidget(panel->quickB, 10, 120);
888 WMSetButtonText(panel->quickB, _("Do not confirm action."));
889 WMSetButtonAction(panel->quickB, buttonClicked, panel);
894 label = WMCreateLabel(panel->optionsF);
895 WMResizeWidget(label, width - 10, FRAME_HEIGHT - 50);
896 WMMoveWidget(label, 10, 20);
897 WMSetLabelText(label,
898 _("Instructions:\n\n"
899 " - drag items from the left to the menu to add new items\n"
900 " - drag items out of the menu to remove items\n"
901 " - drag items in menu to change their position\n"
902 " - drag items with Control pressed to copy them\n"
903 " - double click in a menu item to change the label\n"
904 " - click on a menu item to change related information"));
905 WMMapWidget(label);
907 WMRealizeWidget(panel->box);
908 WMMapSubwidgets(panel->box);
909 WMMapWidget(panel->box);
913 int i;
914 for (i = 0; i < 3; i++)
915 WMUnmapWidget(panel->itemPad[i]);
917 changedItemPad(panel->typeP, panel);
919 panel->sections[NoInfo][0] = label;
921 panel->sections[ExecInfo][0] = panel->commandF;
922 panel->sections[ExecInfo][1] = panel->shortF;
924 panel->sections[CommandInfo][0] = panel->icommandL;
925 panel->sections[CommandInfo][1] = panel->shortF;
927 panel->sections[ExternalInfo][0] = panel->pathF;
929 panel->sections[PipeInfo][0] = panel->pipeF;
931 panel->sections[DirectoryInfo][0] = panel->dpathF;
932 panel->sections[DirectoryInfo][1] = panel->dcommandF;
934 panel->currentType = NoInfo;
936 showData(panel);
939 WMPoint pos;
941 pos = WMGetViewScreenPosition(WMWidgetView(panel->box));
943 if (pos.x < 200) {
944 pos.x += FRAME_WIDTH + 20;
945 } else {
946 pos.x = 10;
949 pos.y = WMAX(pos.y - 100, 0);
951 if (panel->menu)
952 WEditMenuShowAt(panel->menu, pos.x, pos.y);
959 static void
960 freeItemData(ItemData *data)
962 #define CFREE(d) if (d) wfree(d)
964 /* TODO */
965 switch (data->type) {
966 case CommandInfo:
967 CFREE(data->param.command.parameter);
968 CFREE(data->param.command.shortcut);
969 break;
971 case ExecInfo:
972 CFREE(data->param.exec.command);
973 CFREE(data->param.exec.shortcut);
974 break;
976 case PipeInfo:
977 CFREE(data->param.pipe.command);
978 break;
980 case ExternalInfo:
981 CFREE(data->param.external.path);
982 break;
984 case DirectoryInfo:
985 CFREE(data->param.directory.command);
986 CFREE(data->param.directory.directory);
987 break;
989 default:
990 break;
993 wfree(data);
994 #undef CFREE
998 static ItemData*
999 parseCommand(WMPropList *item)
1001 ItemData *data = NEW(ItemData);
1002 WMPropList *p;
1003 char *command = NULL;
1004 char *parameter = NULL;
1005 char *shortcut = NULL;
1006 int i = 1;
1009 p = WMGetFromPLArray(item, i++);
1010 command = WMGetFromPLString(p);
1011 if (strcmp(command, "SHORTCUT") == 0) {
1012 p = WMGetFromPLArray(item, i++);
1013 shortcut = WMGetFromPLString(p);
1014 p = WMGetFromPLArray(item, i++);
1015 command = WMGetFromPLString(p);
1017 p = WMGetFromPLArray(item, i++);
1018 if (p)
1019 parameter = WMGetFromPLString(p);
1021 if (strcmp(command, "EXEC") == 0 || strcmp(command, "SHEXEC") == 0) {
1023 data->type = ExecInfo;
1025 data->param.exec.command = wstrdup(parameter);
1026 if (shortcut)
1027 data->param.exec.shortcut = wstrdup(shortcut);
1029 } else if (strcmp(command, "OPEN_MENU") == 0) {
1030 char *p;
1032 * dir menu, menu file
1033 * dir WITH
1034 * |pipe
1036 p = parameter;
1037 while (isspace(*p) && *p) p++;
1038 if (*p == '|') {
1039 if (*(p+1) == '|') {
1040 p++;
1041 data->param.pipe.cached = 0;
1042 } else {
1043 data->param.pipe.cached = 1;
1045 data->type = PipeInfo;
1046 data->param.pipe.command = wtrimspace(p+1);
1047 } else {
1048 char *s;
1050 p = wstrdup(p);
1052 s = strstr(p, "WITH");
1053 if (s) {
1054 char **tokens;
1055 char **ctokens;
1056 int tokn;
1057 int i, j;
1059 data->type = DirectoryInfo;
1061 *s = '\0';
1062 s += 5;
1063 while (*s && isspace(*s)) s++;
1064 data->param.directory.command = wstrdup(s);
1066 wtokensplit(p, &tokens, &tokn);
1067 wfree(p);
1069 ctokens = wmalloc(sizeof(char*)*tokn);
1071 for (i = 0, j = 0; i < tokn; i++) {
1072 if (strcmp(tokens[i], "-noext") == 0) {
1073 wfree(tokens[i]);
1074 data->param.directory.stripExt = 1;
1075 } else {
1076 ctokens[j++] = tokens[i];
1079 data->param.directory.directory = wtokenjoin(ctokens, j);
1080 wfree(ctokens);
1082 wtokenfree(tokens, tokn);
1083 } else {
1084 data->type = ExternalInfo;
1085 data->param.external.path = p;
1088 } else if (strcmp(command, "WORKSPACE_MENU") == 0) {
1089 data->type = WSMenuInfo;
1090 } else if (strcmp(command, "WINDOWS_MENU") == 0) {
1091 data->type = WWindowListInfo;
1092 } else {
1093 int cmd;
1095 if (strcmp(command, "ARRANGE_ICONS") == 0) {
1096 cmd = 0;
1097 } else if (strcmp(command, "HIDE_OTHERS") == 0) {
1098 cmd = 1;
1099 } else if (strcmp(command, "SHOW_ALL") == 0) {
1100 cmd = 2;
1101 } else if (strcmp(command, "EXIT") == 0) {
1102 cmd = 3;
1103 } else if (strcmp(command, "SHUTDOWN") == 0) {
1104 cmd = 4;
1105 } else if (strcmp(command, "RESTART") == 0) {
1106 if (parameter) {
1107 cmd = 6;
1108 } else {
1109 cmd = 5;
1111 } else if (strcmp(command, "SAVE_SESSION") == 0) {
1112 cmd = 7;
1113 } else if (strcmp(command, "CLEAR_SESSION") == 0) {
1114 cmd = 8;
1115 } else if (strcmp(command, "REFRESH") == 0) {
1116 cmd = 9;
1117 } else if (strcmp(command, "INFO_PANEL") == 0) {
1118 cmd = 10;
1119 } else if (strcmp(command, "LEGAL_PANEL") == 0) {
1120 cmd = 11;
1121 } else {
1122 wwarning(_("unknown command '%s' in menu"), command);
1123 goto error;
1126 data->type = CommandInfo;
1128 data->param.command.command = cmd;
1129 if (shortcut)
1130 data->param.command.shortcut = wstrdup(shortcut);
1131 if (parameter)
1132 data->param.command.parameter = wstrdup(parameter);
1135 return data;
1137 error:
1138 wfree(data);
1140 return NULL;
1146 static void
1147 updateFrameTitle(_Panel *panel, char *title, InfoType type)
1149 if (type != NoInfo) {
1150 char *tmp;
1152 switch (type) {
1153 case ExecInfo:
1154 tmp = wstrconcat(title, _(": Execute Program"));
1155 break;
1157 case CommandInfo:
1158 tmp = wstrconcat(title, _(": Perform Internal Command"));
1159 break;
1161 case ExternalInfo:
1162 tmp = wstrconcat(title, _(": Open a Submenu"));
1163 break;
1165 case PipeInfo:
1166 tmp = wstrconcat(title, _(": Program Generated Submenu"));
1167 break;
1169 case DirectoryInfo:
1170 tmp = wstrconcat(title, _(": Directory Contents Menu"));
1171 break;
1173 case WSMenuInfo:
1174 tmp = wstrconcat(title, _(": Open Workspaces Submenu"));
1175 break;
1177 case WWindowListInfo:
1178 tmp = wstrconcat(title, _(": Open Window List Submenu"));
1179 break;
1181 default:
1182 tmp = NULL;
1183 break;
1185 WMSetFrameTitle(panel->optionsF, tmp);
1186 wfree(tmp);
1187 } else {
1188 WMSetFrameTitle(panel->optionsF, NULL);
1194 static void
1195 changeInfoType(_Panel *panel, char *title, InfoType type)
1197 WMWidget **w;
1199 if (panel->currentType != type) {
1201 w = panel->sections[panel->currentType];
1203 while (*w) {
1204 WMUnmapWidget(*w);
1205 w++;
1207 WMUnmapWidget(panel->paramF);
1208 WMUnmapWidget(panel->quickB);
1211 w = panel->sections[type];
1213 while (*w) {
1214 WMMapWidget(*w);
1215 w++;
1219 updateFrameTitle(panel, title, type);
1221 panel->currentType = type;
1227 static void
1228 updateMenuItem(_Panel *panel, WEditMenuItem *item, WMWidget *changedWidget)
1230 ItemData *data = WGetEditMenuItemData(item);
1232 assert(data != NULL);
1234 #define REPLACE(v, d) if (v) wfree(v); v = d
1236 switch (data->type) {
1237 case ExecInfo:
1238 if (changedWidget == panel->commandT) {
1239 REPLACE(data->param.exec.command,
1240 WMGetTextFieldText(panel->commandT));
1242 if (changedWidget == panel->shortT) {
1243 REPLACE(data->param.exec.shortcut,
1244 WMGetTextFieldText(panel->shortT));
1246 break;
1248 case CommandInfo:
1249 if (changedWidget == panel->icommandL) {
1250 data->param.command.command =
1251 WMGetListSelectedItemRow(panel->icommandL);
1253 switch (data->param.command.command) {
1254 case 3:
1255 case 4:
1256 if (changedWidget == panel->quickB) {
1257 REPLACE(data->param.command.parameter,
1258 WMGetButtonSelected(panel->quickB)
1259 ? wstrdup("QUICK") : NULL);
1261 break;
1263 case 6:
1264 if (changedWidget == panel->paramT) {
1265 REPLACE(data->param.command.parameter,
1266 WMGetTextFieldText(panel->paramT));
1268 break;
1270 if (changedWidget == panel->shortT) {
1271 REPLACE(data->param.command.shortcut,
1272 WMGetTextFieldText(panel->shortT));
1276 break;
1278 case PipeInfo:
1279 if (changedWidget == panel->pipeT) {
1280 REPLACE(data->param.pipe.command,
1281 WMGetTextFieldText(panel->pipeT));
1283 if (changedWidget == panel->pipeCacheB) {
1284 data->param.pipe.cached =
1285 WMGetButtonSelected(panel->pipeCacheB);
1287 break;
1289 case ExternalInfo:
1290 if (changedWidget == panel->pathT) {
1291 REPLACE(data->param.external.path,
1292 WMGetTextFieldText(panel->pathT));
1294 break;
1296 case DirectoryInfo:
1297 if (changedWidget == panel->dpathT) {
1298 REPLACE(data->param.directory.directory,
1299 WMGetTextFieldText(panel->dpathT));
1301 if (changedWidget == panel->dcommandT) {
1302 REPLACE(data->param.directory.command,
1303 WMGetTextFieldText(panel->dcommandT));
1305 if (changedWidget == panel->dstripB) {
1306 data->param.directory.stripExt =
1307 WMGetButtonSelected(panel->dstripB);
1309 break;
1311 default:
1312 assert(0);
1313 break;
1316 #undef REPLACE
1321 static void
1322 menuItemCloned(WEditMenuDelegate *delegate, WEditMenu *menu,
1323 WEditMenuItem *origItem, WEditMenuItem *newItem)
1325 ItemData *data = WGetEditMenuItemData(origItem);
1326 ItemData *newData;
1328 if (!data)
1329 return;
1331 #define DUP(s) (s) ? wstrdup(s) : NULL
1333 newData = NEW(ItemData);
1335 newData->type = data->type;
1337 switch (data->type) {
1338 case ExecInfo:
1339 newData->param.exec.command = DUP(data->param.exec.command);
1340 newData->param.exec.shortcut = DUP(data->param.exec.shortcut);
1341 break;
1343 case CommandInfo:
1344 newData->param.command.command = data->param.command.command;
1345 newData->param.command.parameter = DUP(data->param.command.parameter);
1346 newData->param.command.shortcut = DUP(data->param.command.shortcut);
1347 break;
1349 case PipeInfo:
1350 newData->param.pipe.command = DUP(data->param.pipe.command);
1351 newData->param.pipe.cached = data->param.pipe.cached;
1352 break;
1354 case ExternalInfo:
1355 newData->param.external.path = DUP(data->param.external.path);
1356 break;
1358 case DirectoryInfo:
1359 newData->param.directory.directory = DUP(data->param.directory.directory);
1360 newData->param.directory.command = DUP(data->param.directory.command);
1361 newData->param.directory.stripExt = data->param.directory.stripExt;
1362 break;
1364 default:
1365 break;
1368 #undef DUP
1370 WSetEditMenuItemData(newItem, newData, (WMCallback*)freeItemData);
1374 static void
1375 menuItemEdited(struct WEditMenuDelegate *delegate, WEditMenu *menu,
1376 WEditMenuItem *item)
1378 _Panel *panel = (_Panel*)delegate->data;
1379 WEditMenu *submenu;
1381 updateFrameTitle(panel, WGetEditMenuItemTitle(item), panel->currentType);
1383 submenu = WGetEditMenuSubmenu(menu, item);
1384 if (submenu) {
1385 WSetEditMenuTitle(submenu, WGetEditMenuItemTitle(item));
1390 static Bool
1391 shouldRemoveItem(struct WEditMenuDelegate *delegate, WEditMenu *menu,
1392 WEditMenuItem *item)
1394 _Panel *panel = (_Panel*)delegate->data;
1396 if (panel->dontAsk)
1397 return True;
1399 if (WGetEditMenuSubmenu(menu, item)) {
1400 int res;
1402 res = WMRunAlertPanel(WMWidgetScreen(menu), NULL,
1403 _("Remove Submenu"),
1404 _("Removing this item will destroy all items inside\n"
1405 "the submenu. Do you really want to do that?"),
1406 _("Yes"), _("No"),
1407 _("Yes, don't ask again."));
1408 switch (res) {
1409 case WAPRDefault:
1410 return True;
1411 case WAPRAlternate:
1412 return False;
1413 case WAPROther:
1414 panel->dontAsk = True;
1415 return True;
1418 return True;
1422 static void
1423 menuItemDeselected(WEditMenuDelegate *delegate, WEditMenu *menu,
1424 WEditMenuItem *item)
1426 _Panel *panel = (_Panel*)delegate->data;
1428 changeInfoType(panel, NULL, NoInfo);
1432 static void
1433 menuItemSelected(WEditMenuDelegate *delegate, WEditMenu *menu,
1434 WEditMenuItem *item)
1436 ItemData *data = WGetEditMenuItemData(item);
1437 _Panel *panel = (_Panel*)delegate->data;
1439 panel->currentItem = item;
1441 if (data) {
1442 changeInfoType(panel, WGetEditMenuItemTitle(item), data->type);
1444 switch (data->type) {
1445 case NoInfo:
1446 break;
1448 case ExecInfo:
1449 WMSetTextFieldText(panel->commandT, data->param.exec.command);
1450 WMSetTextFieldText(panel->shortT, data->param.exec.shortcut);
1451 break;
1453 case CommandInfo:
1454 WMSelectListItem(panel->icommandL,
1455 data->param.command.command);
1456 WMSetListPosition(panel->icommandL,
1457 data->param.command.command - 2);
1458 WMSetTextFieldText(panel->shortT, data->param.command.shortcut);
1460 switch (data->param.command.command) {
1461 case 3:
1462 case 4:
1463 WMSetButtonSelected(panel->quickB,
1464 data->param.command.parameter!=NULL);
1465 break;
1466 case 6:
1467 WMSetTextFieldText(panel->paramT,
1468 data->param.command.parameter);
1469 break;
1472 icommandLClicked(panel->icommandL, panel);
1473 break;
1475 case PipeInfo:
1476 WMSetTextFieldText(panel->pipeT, data->param.pipe.command);
1477 WMSetButtonSelected(panel->pipeCacheB, data->param.pipe.cached);
1478 break;
1480 case ExternalInfo:
1481 WMSetTextFieldText(panel->pathT, data->param.external.path);
1482 break;
1484 case DirectoryInfo:
1485 WMSetTextFieldText(panel->dpathT, data->param.directory.directory);
1486 WMSetTextFieldText(panel->dcommandT, data->param.directory.command);
1487 WMSetButtonSelected(panel->dstripB, data->param.directory.stripExt);
1488 break;
1490 case WSMenuInfo:
1491 break;
1493 default:
1494 break;
1501 static WEditMenu*
1502 buildSubmenu(_Panel *panel, WMPropList *pl)
1504 WMScreen *scr = WMWidgetScreen(panel->parent);
1505 WEditMenu *menu;
1506 WEditMenuItem *item;
1507 char *title;
1508 WMPropList *tp, *bp;
1509 int i;
1511 tp = WMGetFromPLArray(pl, 0);
1512 title = WMGetFromPLString(tp);
1514 menu = WCreateEditMenu(scr, title);
1516 for (i = 1; i < WMGetPropListItemCount(pl); i++) {
1517 WMPropList *pi;
1519 pi = WMGetFromPLArray(pl, i);
1521 tp = WMGetFromPLArray(pi, 0);
1522 bp = WMGetFromPLArray(pi, 1);
1524 title = WMGetFromPLString(tp);
1526 if (!bp || WMIsPLArray(bp)) { /* it's a submenu */
1527 WEditMenu *submenu;
1529 submenu = buildSubmenu(panel, pi);
1531 item = WAddMenuItemWithTitle(menu, title);
1533 WSetEditMenuSubmenu(menu, item, submenu);
1534 } else {
1535 ItemData *data;
1537 item = WAddMenuItemWithTitle(menu, title);
1539 data = parseCommand(pi);
1541 if (panel->markerPix[data->type])
1542 WSetEditMenuItemImage(item, panel->markerPix[data->type]);
1543 WSetEditMenuItemData(item, data, (WMCallback*)freeItemData);
1547 WSetEditMenuAcceptsDrop(menu, True);
1548 WSetEditMenuDelegate(menu, &menuDelegate);
1550 WMRealizeWidget(menu);
1552 return menu;
1557 static void
1558 buildMenuFromPL(_Panel *panel, WMPropList *pl)
1560 panel->menu = buildSubmenu(panel, pl);
1565 static WMPropList*
1566 getDefaultMenu(_Panel *panel)
1568 WMPropList *menu, *pmenu;
1569 char *menuPath, *gspath;
1571 gspath = wusergnusteppath();
1573 menuPath = wmalloc(strlen(gspath)+128);
1574 /* if there is a localized plmenu for the tongue put it's filename here */
1575 sprintf(menuPath, _("%s/Library/WindowMaker/plmenu"), gspath);
1577 menu = WMReadPropListFromFile(menuPath);
1578 if (!menu) {
1579 wwarning("%s:could not read property list menu", menuPath);
1581 if (strcmp("%s/Library/WindowMaker/plmenu",
1582 _("%s/Library/WindowMaker/plmenu"))!=0) {
1584 sprintf(menuPath, "%s/Library/WindowMaker/plmenu", gspath);
1585 menu = WMReadPropListFromFile(menuPath);
1586 wwarning("%s:could not read property list menu", menuPath);
1588 if (!menu) {
1589 char buffer[512];
1591 sprintf(buffer, _("Could not open default menu from '%s'"),
1592 menuPath);
1593 WMRunAlertPanel(WMWidgetScreen(panel->parent), panel->parent,
1594 _("Error"), buffer, _("OK"), NULL, NULL);
1598 wfree(menuPath);
1600 if (menu) {
1601 pmenu = menu;
1602 } else {
1603 pmenu = NULL;
1606 return pmenu;
1610 static void
1611 showData(_Panel *panel)
1613 char *gspath;
1614 char *menuPath;
1615 WMPropList *pmenu;
1617 gspath = wusergnusteppath();
1619 menuPath = wmalloc(strlen(gspath)+32);
1620 strcpy(menuPath, gspath);
1621 strcat(menuPath, "/Defaults/WMRootMenu");
1623 pmenu = WMReadPropListFromFile(menuPath);
1625 if (!pmenu || !WMIsPLArray(pmenu)) {
1626 int res;
1628 res = WMRunAlertPanel(WMWidgetScreen(panel->parent), panel->parent,
1629 _("Warning"),
1630 _("The menu file format currently in use is not supported\n"
1631 "by this tool. Do you want to discard the current menu\n"
1632 "to use this tool?"),
1633 _("Yes, Discard and Update"),
1634 _("No, Keep Current Menu"), NULL);
1636 if (res == WAPRDefault) {
1637 pmenu = getDefaultMenu(panel);
1639 if (!pmenu) {
1640 pmenu = WMCreatePLArray(WMCreatePLString("Applications"),
1641 NULL);
1643 } else {
1644 panel->dontSave = True;
1645 return;
1649 panel->menuPath = menuPath;
1651 buildMenuFromPL(panel, pmenu);
1653 WMReleasePropList(pmenu);
1657 static Bool
1658 notblank(char *s)
1660 if (s) {
1661 while (*s++) {
1662 if (!isspace(*s))
1663 return True;
1666 return False;
1670 static WMPropList*
1671 processData(char *title, ItemData *data)
1673 WMPropList *item;
1674 char *s1;
1675 static WMPropList *pscut = NULL;
1676 static WMPropList *pomenu = NULL;
1677 int i;
1679 if (!pscut) {
1680 pscut = WMCreatePLString("SHORTCUT");
1681 pomenu = WMCreatePLString("OPEN_MENU");
1684 item = WMCreatePLArray(WMCreatePLString(title), NULL);
1687 switch (data->type) {
1688 case ExecInfo:
1689 if (data->param.exec.command == NULL)
1690 return NULL;
1691 #if 1
1692 if (strpbrk(data->param.exec.command, "&$*|><?`=;")) {
1693 s1 = "SHEXEC";
1694 } else {
1695 s1 = "EXEC";
1697 #else
1698 s1 = "SHEXEC";
1699 #endif
1701 if (notblank(data->param.exec.shortcut)) {
1702 WMAddToPLArray(item, pscut);
1703 WMAddToPLArray(item,
1704 WMCreatePLString(data->param.exec.shortcut));
1707 WMAddToPLArray(item, WMCreatePLString(s1));
1708 WMAddToPLArray(item, WMCreatePLString(data->param.exec.command));
1709 break;
1711 case CommandInfo:
1712 if (notblank(data->param.command.shortcut)) {
1713 WMAddToPLArray(item, pscut);
1714 WMAddToPLArray(item,
1715 WMCreatePLString(data->param.command.shortcut));
1718 i = data->param.command.command;
1720 WMAddToPLArray(item, WMCreatePLString(commandNames[i]));
1722 switch (i) {
1723 case 3:
1724 case 4:
1725 if (data->param.command.parameter) {
1726 WMAddToPLArray(item,
1727 WMCreatePLString(data->param.command.parameter));
1729 break;
1731 case 6: /* restart */
1732 if (data->param.command.parameter) {
1733 WMAddToPLArray(item,
1734 WMCreatePLString(data->param.command.parameter));
1736 break;
1739 break;
1741 case PipeInfo:
1742 if (!data->param.pipe.command)
1743 return NULL;
1744 WMAddToPLArray(item, pomenu);
1745 if (data->param.pipe.cached)
1746 s1 = wstrconcat("| ", data->param.pipe.command);
1747 else
1748 s1 = wstrconcat("|| ", data->param.pipe.command);
1749 WMAddToPLArray(item, WMCreatePLString(s1));
1750 wfree(s1);
1751 break;
1753 case ExternalInfo:
1754 if (!data->param.external.path)
1755 return NULL;
1756 WMAddToPLArray(item, pomenu);
1757 WMAddToPLArray(item, WMCreatePLString(data->param.external.path));
1758 break;
1760 case DirectoryInfo:
1761 if (!data->param.directory.directory
1762 || !data->param.directory.command)
1763 return NULL;
1765 int l;
1766 char *tmp;
1768 l = strlen(data->param.directory.directory);
1769 l += strlen(data->param.directory.command);
1770 l += 32;
1772 WMAddToPLArray(item, pomenu);
1774 tmp = wmalloc(l);
1775 sprintf(tmp, "%s%s WITH %s",
1776 data->param.directory.stripExt ? "-noext " : "",
1777 data->param.directory.directory,
1778 data->param.directory.command);
1780 WMAddToPLArray(item, WMCreatePLString(tmp));
1781 wfree(tmp);
1783 break;
1785 case WSMenuInfo:
1786 WMAddToPLArray(item, WMCreatePLString("WORKSPACE_MENU"));
1787 break;
1789 case WWindowListInfo:
1790 WMAddToPLArray(item, WMCreatePLString("WINDOWS_MENU"));
1791 break;
1793 default:
1794 assert(0);
1795 break;
1798 return item;
1802 static WMPropList*
1803 processSubmenu(WEditMenu *menu)
1805 WEditMenuItem *item;
1806 WMPropList *pmenu;
1807 WMPropList *pl;
1808 char *s;
1809 int i;
1812 s = WGetEditMenuTitle(menu);
1813 pl = WMCreatePLString(s);
1815 pmenu = WMCreatePLArray(pl, NULL);
1817 i = 0;
1818 while ((item = WGetEditMenuItem(menu, i++))) {
1819 WEditMenu *submenu;
1821 s = WGetEditMenuItemTitle(item);
1823 submenu = WGetEditMenuSubmenu(menu, item);
1824 if (submenu) {
1825 pl = processSubmenu(submenu);
1826 } else {
1827 pl = processData(s, WGetEditMenuItemData(item));
1830 if (!pl)
1831 continue;
1833 WMAddToPLArray(pmenu, pl);
1836 return pmenu;
1841 static WMPropList*
1842 buildPLFromMenu(_Panel *panel)
1844 WMPropList *menu;
1846 menu = processSubmenu(panel->menu);
1848 return menu;
1854 static void
1855 storeData(_Panel *panel)
1857 WMPropList *menu;
1859 if (panel->dontSave)
1860 return;
1862 menu = buildPLFromMenu(panel);
1864 WMWritePropListToFile(menu, panel->menuPath, True);
1866 WMReleasePropList(menu);
1871 static void
1872 showMenus(_Panel *panel)
1874 if (panel->menu)
1875 WEditMenuUnhide(panel->menu);
1879 static void
1880 hideMenus(_Panel *panel)
1882 if (panel->menu)
1883 WEditMenuHide(panel->menu);
1889 Panel*
1890 InitMenu(WMScreen *scr, WMWidget *parent)
1892 _Panel *panel;
1894 panel = wmalloc(sizeof(_Panel));
1895 memset(panel, 0, sizeof(_Panel));
1897 panel->sectionName = _("Applications Menu Definition");
1899 panel->description = _("Edit the menu for launching applications.");
1901 panel->parent = parent;
1903 panel->callbacks.createWidgets = createPanel;
1904 panel->callbacks.updateDomain = storeData;
1905 panel->callbacks.showPanel = showMenus;
1906 panel->callbacks.hidePanel = hideMenus;
1909 AddSection(panel, ICON_FILE);
1911 return panel;