- Fixed compilation include path issue in wrlib/tests
[wmaker-crm.git] / WPrefs.app / Menu.c
blob0f7f59fef35292336512cc34c5c45b6ecff302ac
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
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);
892 label = WMCreateLabel(panel->optionsF);
893 WMResizeWidget(label, width+5, FRAME_HEIGHT - 50);
894 WMMoveWidget(label, 7, 20);
895 WMSetLabelText(label,
896 _("Instructions:\n\n"
897 " - drag items from the left to the menu to add new items\n"
898 " - drag items out of the menu to remove items\n"
899 " - drag items in menu to change their position\n"
900 " - drag items with Control pressed to copy them\n"
901 " - double click in a menu item to change the label\n"
902 " - click on a menu item to change related information"));
903 WMMapWidget(label);
905 WMRealizeWidget(panel->box);
906 WMMapSubwidgets(panel->box);
907 WMMapWidget(panel->box);
911 int i;
912 for (i = 0; i < 3; i++)
913 WMUnmapWidget(panel->itemPad[i]);
915 changedItemPad(panel->typeP, panel);
917 panel->sections[NoInfo][0] = label;
919 panel->sections[ExecInfo][0] = panel->commandF;
920 panel->sections[ExecInfo][1] = panel->shortF;
922 panel->sections[CommandInfo][0] = panel->icommandL;
923 panel->sections[CommandInfo][1] = panel->shortF;
925 panel->sections[ExternalInfo][0] = panel->pathF;
927 panel->sections[PipeInfo][0] = panel->pipeF;
929 panel->sections[DirectoryInfo][0] = panel->dpathF;
930 panel->sections[DirectoryInfo][1] = panel->dcommandF;
932 panel->currentType = NoInfo;
934 showData(panel);
937 WMPoint pos;
939 pos = WMGetViewScreenPosition(WMWidgetView(panel->box));
941 if (pos.x < 200) {
942 pos.x += FRAME_WIDTH + 20;
943 } else {
944 pos.x = 10;
947 pos.y = WMAX(pos.y - 100, 0);
949 if (panel->menu)
950 WEditMenuShowAt(panel->menu, pos.x, pos.y);
957 static void
958 freeItemData(ItemData *data)
960 #define CFREE(d) if (d) wfree(d)
962 /* TODO */
963 switch (data->type) {
964 case CommandInfo:
965 CFREE(data->param.command.parameter);
966 CFREE(data->param.command.shortcut);
967 break;
969 case ExecInfo:
970 CFREE(data->param.exec.command);
971 CFREE(data->param.exec.shortcut);
972 break;
974 case PipeInfo:
975 CFREE(data->param.pipe.command);
976 break;
978 case ExternalInfo:
979 CFREE(data->param.external.path);
980 break;
982 case DirectoryInfo:
983 CFREE(data->param.directory.command);
984 CFREE(data->param.directory.directory);
985 break;
987 default:
988 break;
991 wfree(data);
992 #undef CFREE
996 static ItemData*
997 parseCommand(WMPropList *item)
999 ItemData *data = NEW(ItemData);
1000 WMPropList *p;
1001 char *command = NULL;
1002 char *parameter = NULL;
1003 char *shortcut = NULL;
1004 int i = 1;
1007 p = WMGetFromPLArray(item, i++);
1008 command = WMGetFromPLString(p);
1009 if (strcmp(command, "SHORTCUT") == 0) {
1010 p = WMGetFromPLArray(item, i++);
1011 shortcut = WMGetFromPLString(p);
1012 p = WMGetFromPLArray(item, i++);
1013 command = WMGetFromPLString(p);
1015 p = WMGetFromPLArray(item, i++);
1016 if (p)
1017 parameter = WMGetFromPLString(p);
1019 if (strcmp(command, "EXEC") == 0 || strcmp(command, "SHEXEC") == 0) {
1021 data->type = ExecInfo;
1023 data->param.exec.command = wstrdup(parameter);
1024 if (shortcut)
1025 data->param.exec.shortcut = wstrdup(shortcut);
1027 } else if (strcmp(command, "OPEN_MENU") == 0) {
1028 char *p;
1030 * dir menu, menu file
1031 * dir WITH
1032 * |pipe
1034 p = parameter;
1035 while (isspace(*p) && *p) p++;
1036 if (*p == '|') {
1037 if (*(p+1) == '|') {
1038 p++;
1039 data->param.pipe.cached = 0;
1040 } else {
1041 data->param.pipe.cached = 1;
1043 data->type = PipeInfo;
1044 data->param.pipe.command = wtrimspace(p+1);
1045 } else {
1046 char *s;
1048 p = wstrdup(p);
1050 s = strstr(p, "WITH");
1051 if (s) {
1052 char **tokens;
1053 char **ctokens;
1054 int tokn;
1055 int i, j;
1057 data->type = DirectoryInfo;
1059 *s = '\0';
1060 s += 5;
1061 while (*s && isspace(*s)) s++;
1062 data->param.directory.command = wstrdup(s);
1064 wtokensplit(p, &tokens, &tokn);
1065 wfree(p);
1067 ctokens = wmalloc(sizeof(char*)*tokn);
1069 for (i = 0, j = 0; i < tokn; i++) {
1070 if (strcmp(tokens[i], "-noext") == 0) {
1071 wfree(tokens[i]);
1072 data->param.directory.stripExt = 1;
1073 } else {
1074 ctokens[j++] = tokens[i];
1077 data->param.directory.directory = wtokenjoin(ctokens, j);
1078 wfree(ctokens);
1080 wtokenfree(tokens, tokn);
1081 } else {
1082 data->type = ExternalInfo;
1083 data->param.external.path = p;
1086 } else if (strcmp(command, "WORKSPACE_MENU") == 0) {
1087 data->type = WSMenuInfo;
1088 } else if (strcmp(command, "WINDOWS_MENU") == 0) {
1089 data->type = WWindowListInfo;
1090 } else {
1091 int cmd;
1093 if (strcmp(command, "ARRANGE_ICONS") == 0) {
1094 cmd = 0;
1095 } else if (strcmp(command, "HIDE_OTHERS") == 0) {
1096 cmd = 1;
1097 } else if (strcmp(command, "SHOW_ALL") == 0) {
1098 cmd = 2;
1099 } else if (strcmp(command, "EXIT") == 0) {
1100 cmd = 3;
1101 } else if (strcmp(command, "SHUTDOWN") == 0) {
1102 cmd = 4;
1103 } else if (strcmp(command, "RESTART") == 0) {
1104 if (parameter) {
1105 cmd = 6;
1106 } else {
1107 cmd = 5;
1109 } else if (strcmp(command, "SAVE_SESSION") == 0) {
1110 cmd = 7;
1111 } else if (strcmp(command, "CLEAR_SESSION") == 0) {
1112 cmd = 8;
1113 } else if (strcmp(command, "REFRESH") == 0) {
1114 cmd = 9;
1115 } else if (strcmp(command, "INFO_PANEL") == 0) {
1116 cmd = 10;
1117 } else if (strcmp(command, "LEGAL_PANEL") == 0) {
1118 cmd = 11;
1119 } else {
1120 wwarning(_("unknown command '%s' in menu"), command);
1121 goto error;
1124 data->type = CommandInfo;
1126 data->param.command.command = cmd;
1127 if (shortcut)
1128 data->param.command.shortcut = wstrdup(shortcut);
1129 if (parameter)
1130 data->param.command.parameter = wstrdup(parameter);
1133 return data;
1135 error:
1136 wfree(data);
1138 return NULL;
1144 static void
1145 updateFrameTitle(_Panel *panel, char *title, InfoType type)
1147 if (type != NoInfo) {
1148 char *tmp;
1150 switch (type) {
1151 case ExecInfo:
1152 tmp = wstrconcat(title, _(": Execute Program"));
1153 break;
1155 case CommandInfo:
1156 tmp = wstrconcat(title, _(": Perform Internal Command"));
1157 break;
1159 case ExternalInfo:
1160 tmp = wstrconcat(title, _(": Open a Submenu"));
1161 break;
1163 case PipeInfo:
1164 tmp = wstrconcat(title, _(": Program Generated Submenu"));
1165 break;
1167 case DirectoryInfo:
1168 tmp = wstrconcat(title, _(": Directory Contents Menu"));
1169 break;
1171 case WSMenuInfo:
1172 tmp = wstrconcat(title, _(": Open Workspaces Submenu"));
1173 break;
1175 case WWindowListInfo:
1176 tmp = wstrconcat(title, _(": Open Window List Submenu"));
1177 break;
1179 default:
1180 tmp = NULL;
1181 break;
1183 WMSetFrameTitle(panel->optionsF, tmp);
1184 wfree(tmp);
1185 } else {
1186 WMSetFrameTitle(panel->optionsF, NULL);
1192 static void
1193 changeInfoType(_Panel *panel, char *title, InfoType type)
1195 WMWidget **w;
1197 if (panel->currentType != type) {
1199 w = panel->sections[panel->currentType];
1201 while (*w) {
1202 WMUnmapWidget(*w);
1203 w++;
1205 WMUnmapWidget(panel->paramF);
1206 WMUnmapWidget(panel->quickB);
1209 w = panel->sections[type];
1211 while (*w) {
1212 WMMapWidget(*w);
1213 w++;
1217 updateFrameTitle(panel, title, type);
1219 panel->currentType = type;
1225 static void
1226 updateMenuItem(_Panel *panel, WEditMenuItem *item, WMWidget *changedWidget)
1228 ItemData *data = WGetEditMenuItemData(item);
1230 assert(data != NULL);
1232 #define REPLACE(v, d) if (v) wfree(v); v = d
1234 switch (data->type) {
1235 case ExecInfo:
1236 if (changedWidget == panel->commandT) {
1237 REPLACE(data->param.exec.command,
1238 WMGetTextFieldText(panel->commandT));
1240 if (changedWidget == panel->shortT) {
1241 REPLACE(data->param.exec.shortcut,
1242 WMGetTextFieldText(panel->shortT));
1244 break;
1246 case CommandInfo:
1247 if (changedWidget == panel->icommandL) {
1248 data->param.command.command =
1249 WMGetListSelectedItemRow(panel->icommandL);
1251 switch (data->param.command.command) {
1252 case 3:
1253 case 4:
1254 if (changedWidget == panel->quickB) {
1255 REPLACE(data->param.command.parameter,
1256 WMGetButtonSelected(panel->quickB)
1257 ? wstrdup("QUICK") : NULL);
1259 break;
1261 case 6:
1262 if (changedWidget == panel->paramT) {
1263 REPLACE(data->param.command.parameter,
1264 WMGetTextFieldText(panel->paramT));
1266 break;
1268 if (changedWidget == panel->shortT) {
1269 REPLACE(data->param.command.shortcut,
1270 WMGetTextFieldText(panel->shortT));
1274 break;
1276 case PipeInfo:
1277 if (changedWidget == panel->pipeT) {
1278 REPLACE(data->param.pipe.command,
1279 WMGetTextFieldText(panel->pipeT));
1281 if (changedWidget == panel->pipeCacheB) {
1282 data->param.pipe.cached =
1283 WMGetButtonSelected(panel->pipeCacheB);
1285 break;
1287 case ExternalInfo:
1288 if (changedWidget == panel->pathT) {
1289 REPLACE(data->param.external.path,
1290 WMGetTextFieldText(panel->pathT));
1292 break;
1294 case DirectoryInfo:
1295 if (changedWidget == panel->dpathT) {
1296 REPLACE(data->param.directory.directory,
1297 WMGetTextFieldText(panel->dpathT));
1299 if (changedWidget == panel->dcommandT) {
1300 REPLACE(data->param.directory.command,
1301 WMGetTextFieldText(panel->dcommandT));
1303 if (changedWidget == panel->dstripB) {
1304 data->param.directory.stripExt =
1305 WMGetButtonSelected(panel->dstripB);
1307 break;
1309 default:
1310 assert(0);
1311 break;
1314 #undef REPLACE
1319 static void
1320 menuItemCloned(WEditMenuDelegate *delegate, WEditMenu *menu,
1321 WEditMenuItem *origItem, WEditMenuItem *newItem)
1323 ItemData *data = WGetEditMenuItemData(origItem);
1324 ItemData *newData;
1326 if (!data)
1327 return;
1329 #define DUP(s) (s) ? wstrdup(s) : NULL
1331 newData = NEW(ItemData);
1333 newData->type = data->type;
1335 switch (data->type) {
1336 case ExecInfo:
1337 newData->param.exec.command = DUP(data->param.exec.command);
1338 newData->param.exec.shortcut = DUP(data->param.exec.shortcut);
1339 break;
1341 case CommandInfo:
1342 newData->param.command.command = data->param.command.command;
1343 newData->param.command.parameter = DUP(data->param.command.parameter);
1344 newData->param.command.shortcut = DUP(data->param.command.shortcut);
1345 break;
1347 case PipeInfo:
1348 newData->param.pipe.command = DUP(data->param.pipe.command);
1349 newData->param.pipe.cached = data->param.pipe.cached;
1350 break;
1352 case ExternalInfo:
1353 newData->param.external.path = DUP(data->param.external.path);
1354 break;
1356 case DirectoryInfo:
1357 newData->param.directory.directory = DUP(data->param.directory.directory);
1358 newData->param.directory.command = DUP(data->param.directory.command);
1359 newData->param.directory.stripExt = data->param.directory.stripExt;
1360 break;
1362 default:
1363 break;
1366 #undef DUP
1368 WSetEditMenuItemData(newItem, newData, (WMCallback*)freeItemData);
1372 static void
1373 menuItemEdited(struct WEditMenuDelegate *delegate, WEditMenu *menu,
1374 WEditMenuItem *item)
1376 _Panel *panel = (_Panel*)delegate->data;
1377 WEditMenu *submenu;
1379 updateFrameTitle(panel, WGetEditMenuItemTitle(item), panel->currentType);
1381 submenu = WGetEditMenuSubmenu(menu, item);
1382 if (submenu) {
1383 WSetEditMenuTitle(submenu, WGetEditMenuItemTitle(item));
1388 static Bool
1389 shouldRemoveItem(struct WEditMenuDelegate *delegate, WEditMenu *menu,
1390 WEditMenuItem *item)
1392 _Panel *panel = (_Panel*)delegate->data;
1394 if (panel->dontAsk)
1395 return True;
1397 if (WGetEditMenuSubmenu(menu, item)) {
1398 int res;
1400 res = WMRunAlertPanel(WMWidgetScreen(menu), NULL,
1401 _("Remove Submenu"),
1402 _("Removing this item will destroy all items inside\n"
1403 "the submenu. Do you really want to do that?"),
1404 _("Yes"), _("No"),
1405 _("Yes, don't ask again."));
1406 switch (res) {
1407 case WAPRDefault:
1408 return True;
1409 case WAPRAlternate:
1410 return False;
1411 case WAPROther:
1412 panel->dontAsk = True;
1413 return True;
1416 return True;
1420 static void
1421 menuItemDeselected(WEditMenuDelegate *delegate, WEditMenu *menu,
1422 WEditMenuItem *item)
1424 _Panel *panel = (_Panel*)delegate->data;
1426 changeInfoType(panel, NULL, NoInfo);
1430 static void
1431 menuItemSelected(WEditMenuDelegate *delegate, WEditMenu *menu,
1432 WEditMenuItem *item)
1434 ItemData *data = WGetEditMenuItemData(item);
1435 _Panel *panel = (_Panel*)delegate->data;
1437 panel->currentItem = item;
1439 if (data) {
1440 changeInfoType(panel, WGetEditMenuItemTitle(item), data->type);
1442 switch (data->type) {
1443 case NoInfo:
1444 break;
1446 case ExecInfo:
1447 WMSetTextFieldText(panel->commandT, data->param.exec.command);
1448 WMSetTextFieldText(panel->shortT, data->param.exec.shortcut);
1449 break;
1451 case CommandInfo:
1452 WMSelectListItem(panel->icommandL,
1453 data->param.command.command);
1454 WMSetListPosition(panel->icommandL,
1455 data->param.command.command - 2);
1456 WMSetTextFieldText(panel->shortT, data->param.command.shortcut);
1458 switch (data->param.command.command) {
1459 case 3:
1460 case 4:
1461 WMSetButtonSelected(panel->quickB,
1462 data->param.command.parameter!=NULL);
1463 break;
1464 case 6:
1465 WMSetTextFieldText(panel->paramT,
1466 data->param.command.parameter);
1467 break;
1470 icommandLClicked(panel->icommandL, panel);
1471 break;
1473 case PipeInfo:
1474 WMSetTextFieldText(panel->pipeT, data->param.pipe.command);
1475 WMSetButtonSelected(panel->pipeCacheB, data->param.pipe.cached);
1476 break;
1478 case ExternalInfo:
1479 WMSetTextFieldText(panel->pathT, data->param.external.path);
1480 break;
1482 case DirectoryInfo:
1483 WMSetTextFieldText(panel->dpathT, data->param.directory.directory);
1484 WMSetTextFieldText(panel->dcommandT, data->param.directory.command);
1485 WMSetButtonSelected(panel->dstripB, data->param.directory.stripExt);
1486 break;
1488 case WSMenuInfo:
1489 break;
1491 default:
1492 break;
1499 static WEditMenu*
1500 buildSubmenu(_Panel *panel, WMPropList *pl)
1502 WMScreen *scr = WMWidgetScreen(panel->parent);
1503 WEditMenu *menu;
1504 WEditMenuItem *item;
1505 char *title;
1506 WMPropList *tp, *bp;
1507 int i;
1509 tp = WMGetFromPLArray(pl, 0);
1510 title = WMGetFromPLString(tp);
1512 menu = WCreateEditMenu(scr, title);
1514 for (i = 1; i < WMGetPropListItemCount(pl); i++) {
1515 WMPropList *pi;
1517 pi = WMGetFromPLArray(pl, i);
1519 tp = WMGetFromPLArray(pi, 0);
1520 bp = WMGetFromPLArray(pi, 1);
1522 title = WMGetFromPLString(tp);
1524 if (!bp || WMIsPLArray(bp)) { /* it's a submenu */
1525 WEditMenu *submenu;
1527 submenu = buildSubmenu(panel, pi);
1529 item = WAddMenuItemWithTitle(menu, title);
1531 WSetEditMenuSubmenu(menu, item, submenu);
1532 } else {
1533 ItemData *data;
1535 item = WAddMenuItemWithTitle(menu, title);
1537 data = parseCommand(pi);
1539 if (panel->markerPix[data->type])
1540 WSetEditMenuItemImage(item, panel->markerPix[data->type]);
1541 WSetEditMenuItemData(item, data, (WMCallback*)freeItemData);
1545 WSetEditMenuAcceptsDrop(menu, True);
1546 WSetEditMenuDelegate(menu, &menuDelegate);
1548 WMRealizeWidget(menu);
1550 return menu;
1555 static void
1556 buildMenuFromPL(_Panel *panel, WMPropList *pl)
1558 panel->menu = buildSubmenu(panel, pl);
1563 static WMPropList*
1564 getDefaultMenu(_Panel *panel)
1566 WMPropList *menu;
1567 char *menuPath, *gspath;
1569 gspath = wusergnusteppath();
1571 menuPath = wmalloc(strlen(gspath)+128);
1572 sprintf(menuPath, "%s/Library/WindowMaker/plmenu", gspath);
1574 menu = WMReadPropListFromFile(menuPath);
1576 if (!menu) {
1577 char *buffer, *msg;
1579 msg = _("Could not open default menu from '%s'");
1580 buffer = wmalloc(strlen(msg) + strlen(menuPath) + 10);
1581 sprintf(buffer, msg, menuPath);
1582 WMRunAlertPanel(WMWidgetScreen(panel->parent), panel->parent,
1583 _("Error"), buffer, _("OK"), NULL, NULL);
1584 wfree(buffer);
1587 wfree(menuPath);
1589 return menu;
1593 static void
1594 showData(_Panel *panel)
1596 char *gspath;
1597 char *menuPath;
1598 WMPropList *pmenu;
1600 gspath = wusergnusteppath();
1602 menuPath = wmalloc(strlen(gspath)+32);
1603 strcpy(menuPath, gspath);
1604 strcat(menuPath, "/Defaults/WMRootMenu");
1606 pmenu = WMReadPropListFromFile(menuPath);
1608 if (!pmenu || !WMIsPLArray(pmenu)) {
1609 int res;
1611 res = WMRunAlertPanel(WMWidgetScreen(panel->parent), panel->parent,
1612 _("Warning"),
1613 _("The menu file format currently in use is not supported\n"
1614 "by this tool. Do you want to discard the current menu\n"
1615 "to use this tool?"),
1616 _("Yes, Discard and Update"),
1617 _("No, Keep Current Menu"), NULL);
1619 if (res == WAPRDefault) {
1620 pmenu = getDefaultMenu(panel);
1622 if (!pmenu) {
1623 pmenu = WMCreatePLArray(WMCreatePLString("Applications"),
1624 NULL);
1626 } else {
1627 panel->dontSave = True;
1628 return;
1632 panel->menuPath = menuPath;
1634 buildMenuFromPL(panel, pmenu);
1636 WMReleasePropList(pmenu);
1640 static Bool
1641 notblank(char *s)
1643 if (s) {
1644 while (*s++) {
1645 if (!isspace(*s))
1646 return True;
1649 return False;
1653 static WMPropList*
1654 processData(char *title, ItemData *data)
1656 WMPropList *item;
1657 char *s1;
1658 static WMPropList *pscut = NULL;
1659 static WMPropList *pomenu = NULL;
1660 int i;
1662 if (!pscut) {
1663 pscut = WMCreatePLString("SHORTCUT");
1664 pomenu = WMCreatePLString("OPEN_MENU");
1667 item = WMCreatePLArray(WMCreatePLString(title), NULL);
1670 switch (data->type) {
1671 case ExecInfo:
1672 if (data->param.exec.command == NULL)
1673 return NULL;
1674 #if 1
1675 if (strpbrk(data->param.exec.command, "&$*|><?`=;")) {
1676 s1 = "SHEXEC";
1677 } else {
1678 s1 = "EXEC";
1680 #else
1681 s1 = "SHEXEC";
1682 #endif
1684 if (notblank(data->param.exec.shortcut)) {
1685 WMAddToPLArray(item, pscut);
1686 WMAddToPLArray(item,
1687 WMCreatePLString(data->param.exec.shortcut));
1690 WMAddToPLArray(item, WMCreatePLString(s1));
1691 WMAddToPLArray(item, WMCreatePLString(data->param.exec.command));
1692 break;
1694 case CommandInfo:
1695 if (notblank(data->param.command.shortcut)) {
1696 WMAddToPLArray(item, pscut);
1697 WMAddToPLArray(item,
1698 WMCreatePLString(data->param.command.shortcut));
1701 i = data->param.command.command;
1703 WMAddToPLArray(item, WMCreatePLString(commandNames[i]));
1705 switch (i) {
1706 case 3:
1707 case 4:
1708 if (data->param.command.parameter) {
1709 WMAddToPLArray(item,
1710 WMCreatePLString(data->param.command.parameter));
1712 break;
1714 case 6: /* restart */
1715 if (data->param.command.parameter) {
1716 WMAddToPLArray(item,
1717 WMCreatePLString(data->param.command.parameter));
1719 break;
1722 break;
1724 case PipeInfo:
1725 if (!data->param.pipe.command)
1726 return NULL;
1727 WMAddToPLArray(item, pomenu);
1728 if (data->param.pipe.cached)
1729 s1 = wstrconcat("| ", data->param.pipe.command);
1730 else
1731 s1 = wstrconcat("|| ", data->param.pipe.command);
1732 WMAddToPLArray(item, WMCreatePLString(s1));
1733 wfree(s1);
1734 break;
1736 case ExternalInfo:
1737 if (!data->param.external.path)
1738 return NULL;
1739 WMAddToPLArray(item, pomenu);
1740 WMAddToPLArray(item, WMCreatePLString(data->param.external.path));
1741 break;
1743 case DirectoryInfo:
1744 if (!data->param.directory.directory
1745 || !data->param.directory.command)
1746 return NULL;
1748 int l;
1749 char *tmp;
1751 l = strlen(data->param.directory.directory);
1752 l += strlen(data->param.directory.command);
1753 l += 32;
1755 WMAddToPLArray(item, pomenu);
1757 tmp = wmalloc(l);
1758 sprintf(tmp, "%s%s WITH %s",
1759 data->param.directory.stripExt ? "-noext " : "",
1760 data->param.directory.directory,
1761 data->param.directory.command);
1763 WMAddToPLArray(item, WMCreatePLString(tmp));
1764 wfree(tmp);
1766 break;
1768 case WSMenuInfo:
1769 WMAddToPLArray(item, WMCreatePLString("WORKSPACE_MENU"));
1770 break;
1772 case WWindowListInfo:
1773 WMAddToPLArray(item, WMCreatePLString("WINDOWS_MENU"));
1774 break;
1776 default:
1777 assert(0);
1778 break;
1781 return item;
1785 static WMPropList*
1786 processSubmenu(WEditMenu *menu)
1788 WEditMenuItem *item;
1789 WMPropList *pmenu;
1790 WMPropList *pl;
1791 char *s;
1792 int i;
1795 s = WGetEditMenuTitle(menu);
1796 pl = WMCreatePLString(s);
1798 pmenu = WMCreatePLArray(pl, NULL);
1800 i = 0;
1801 while ((item = WGetEditMenuItem(menu, i++))) {
1802 WEditMenu *submenu;
1804 s = WGetEditMenuItemTitle(item);
1806 submenu = WGetEditMenuSubmenu(menu, item);
1807 if (submenu) {
1808 pl = processSubmenu(submenu);
1809 } else {
1810 pl = processData(s, WGetEditMenuItemData(item));
1813 if (!pl)
1814 continue;
1816 WMAddToPLArray(pmenu, pl);
1819 return pmenu;
1824 static WMPropList*
1825 buildPLFromMenu(_Panel *panel)
1827 WMPropList *menu;
1829 menu = processSubmenu(panel->menu);
1831 return menu;
1837 static void
1838 storeData(_Panel *panel)
1840 WMPropList *menu;
1842 if (panel->dontSave)
1843 return;
1845 menu = buildPLFromMenu(panel);
1847 WMWritePropListToFile(menu, panel->menuPath, True);
1849 WMReleasePropList(menu);
1854 static void
1855 showMenus(_Panel *panel)
1857 if (panel->menu)
1858 WEditMenuUnhide(panel->menu);
1862 static void
1863 hideMenus(_Panel *panel)
1865 if (panel->menu)
1866 WEditMenuHide(panel->menu);
1872 Panel*
1873 InitMenu(WMScreen *scr, WMWidget *parent)
1875 _Panel *panel;
1877 panel = wmalloc(sizeof(_Panel));
1878 memset(panel, 0, sizeof(_Panel));
1880 panel->sectionName = _("Applications Menu Definition");
1882 panel->description = _("Edit the menu for launching applications.");
1884 panel->parent = parent;
1886 panel->callbacks.createWidgets = createPanel;
1887 panel->callbacks.updateDomain = storeData;
1888 panel->callbacks.showPanel = showMenus;
1889 panel->callbacks.hidePanel = hideMenus;
1892 AddSection(panel, ICON_FILE);
1894 return panel;