fixed some bugs in menu editor
[wmaker-crm.git] / WPrefs.app / Menu.c
blob80687360a7b2488b868edebc9cb46412fe8e3d13
1 /* Menu.c- menu definition
2 *
3 * WPrefs - Window Maker Preferences Program
4 *
5 * Copyright (c) 2000 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 LastInfo
44 } InfoType;
46 #define MAX_SECTION_SIZE 4
48 typedef struct _Panel {
49 WMFrame *frame;
50 char *sectionName;
52 char *description;
54 CallbackRec callbacks;
55 WMWindow *win;
58 WMFont *boldFont;
59 WMFont *normalFont;
60 WMColor *white;
61 WMColor *gray;
62 WMColor *black;
64 WMPixmap *markerPix[LastInfo];
66 WMPopUpButton *typeP;
68 WMWidget *itemPad[3];
69 int currentPad;
71 WEditMenu *menu;
72 char *menuPath;
74 WMFrame *optionsF;
76 WMFrame *commandF;
77 WMTextField *commandT; /* command to run */
78 WMButton *xtermC; /* inside xterm? */
80 WMFrame *pathF;
81 WMTextField *pathT;
83 WMFrame *pipeF;
84 WMTextField *pipeT;
86 WMFrame *dpathF;
87 WMTextField *dpathT;
89 WMFrame *dcommandF;
90 WMTextField *dcommandT;
92 WMButton *dstripB;
94 WMFrame *shortF;
95 WMTextField *shortT;
96 WMButton *sgrabB;
97 WMButton *sclearB;
99 WMList *icommandL;
101 WMFrame *paramF;
102 WMTextField *paramT;
104 WMButton *quickB;
106 Bool dontAsk; /* whether to comfirm submenu remove */
107 Bool dontSave;
109 Bool capturing;
111 /* about the currently selected item */
112 WEditMenuItem *currentItem;
113 InfoType currentType;
114 WMWidget *sections[LastInfo][MAX_SECTION_SIZE];
115 } _Panel;
118 typedef struct {
119 InfoType type;
120 union {
121 struct {
122 int command;
123 char *parameter;
124 char *shortcut;
125 } command;
126 struct {
127 char *command;
128 char *shortcut;
129 } exec;
130 struct {
131 char *path;
132 } external;
133 struct {
134 char *command;
135 } pipe;
136 struct {
137 char *directory;
138 char *command;
139 unsigned stripExt:1;
140 } directory;
141 } param;
142 } ItemData;
146 static char *commandNames[] = {
147 "ARRANGE_ICONS",
148 "HIDE_OTHERS",
149 "SHOW_ALL",
150 "EXIT",
151 "SHUTDOWN",
152 "RESTART",
153 "RESTART",
154 "SAVE_SESSION",
155 "CLEAR_SESSION",
156 "REFRESH",
157 "INFO_PANEL",
158 "LEGAL_PANEL"
163 #define NEW(type) memset(wmalloc(sizeof(type)), 0, sizeof(type))
166 #define ICON_FILE "menus"
170 static void showData(_Panel *panel);
173 static void updateMenuItem(_Panel *panel, WEditMenuItem *item,
174 WMWidget *changedWidget);
176 static void menuItemSelected(struct WEditMenuDelegate *delegate,
177 WEditMenu *menu, WEditMenuItem *item);
179 static void menuItemDeselected(struct WEditMenuDelegate *delegate,
180 WEditMenu *menu, WEditMenuItem *item);
182 static void menuItemCloned(struct WEditMenuDelegate *delegate, WEditMenu *menu,
183 WEditMenuItem *origItem, WEditMenuItem *newItem);
185 static void menuItemEdited(struct WEditMenuDelegate *delegate, WEditMenu *menu,
186 WEditMenuItem *item);
188 static Bool shouldRemoveItem(struct WEditMenuDelegate *delegate,
189 WEditMenu *menu, WEditMenuItem *item);
192 static void freeItemData(ItemData *data);
196 static WEditMenuDelegate menuDelegate = {
197 NULL,
198 menuItemCloned,
199 menuItemEdited,
200 menuItemSelected,
201 menuItemDeselected,
202 shouldRemoveItem
206 static void
207 dataChanged(void *self, WMNotification *notif)
209 _Panel *panel = (_Panel*)self;
210 WEditMenuItem *item = panel->currentItem;
211 WMWidget *w = (WMWidget*)WMGetNotificationObject(notif);
213 updateMenuItem(panel, item, w);
217 static void
218 buttonClicked(WMWidget *w, void *data)
220 _Panel *panel = (_Panel*)data;
221 WEditMenuItem *item = panel->currentItem;
223 updateMenuItem(panel, item, w);
227 static void
228 icommandLClicked(WMWidget *w, void *data)
230 _Panel *panel = (_Panel*)data;
231 int cmd;
233 cmd = WMGetListSelectedItemRow(w);
234 if (cmd == 3 || cmd == 4) {
235 WMMapWidget(panel->quickB);
236 } else {
237 WMUnmapWidget(panel->quickB);
239 if (cmd == 6) {
240 WMMapWidget(panel->paramF);
241 } else {
242 WMUnmapWidget(panel->paramF);
254 static char*
255 captureShortcut(Display *dpy, _Panel *panel)
257 XEvent ev;
258 KeySym ksym;
259 char buffer[64];
260 char *key = NULL;
262 while (panel->capturing) {
263 XAllowEvents(dpy, AsyncKeyboard, CurrentTime);
264 WMNextEvent(dpy, &ev);
265 if (ev.type==KeyPress && ev.xkey.keycode!=0) {
266 ksym = XKeycodeToKeysym(dpy, ev.xkey.keycode, 0);
267 if (!IsModifierKey(ksym)) {
268 key=XKeysymToString(ksym);
269 panel->capturing = 0;
270 break;
273 WMHandleEvent(&ev);
276 if (!key)
277 return NULL;
279 buffer[0] = 0;
281 if (ev.xkey.state & ControlMask) {
282 strcat(buffer, "Control+");
284 if (ev.xkey.state & ShiftMask) {
285 strcat(buffer, "Shift+");
287 if (ev.xkey.state & Mod1Mask) {
288 strcat(buffer, "Mod1+");
290 if (ev.xkey.state & Mod2Mask) {
291 strcat(buffer, "Mod2+");
293 if (ev.xkey.state & Mod3Mask) {
294 strcat(buffer, "Mod3+");
296 if (ev.xkey.state & Mod4Mask) {
297 strcat(buffer, "Mod4+");
299 if (ev.xkey.state & Mod5Mask) {
300 strcat(buffer, "Mod5+");
302 strcat(buffer, key);
304 return wstrdup(buffer);
309 static void
310 sgrabClicked(WMWidget *w, void *data)
312 _Panel *panel = (_Panel*)data;
313 Display *dpy = WMScreenDisplay(WMWidgetScreen(panel->win));
314 char *shortcut;
317 if (w == panel->sclearB) {
318 WMSetTextFieldText(panel->shortT, "");
319 updateMenuItem(panel, panel->currentItem, panel->shortT);
320 return;
323 if (!panel->capturing) {
324 panel->capturing = 1;
325 WMSetButtonText(w, _("Cancel"));
326 XGrabKeyboard(dpy, WMWidgetXID(panel->win), True, GrabModeAsync,
327 GrabModeAsync, CurrentTime);
328 shortcut = captureShortcut(dpy, panel);
329 if (shortcut) {
330 WMSetTextFieldText(panel->shortT, shortcut);
331 updateMenuItem(panel, panel->currentItem, panel->shortT);
332 free(shortcut);
335 panel->capturing = 0;
336 WMSetButtonText(w, _("Capture"));
337 XUngrabKeyboard(dpy, CurrentTime);
341 static void
342 changedItemPad(WMWidget *w, void *data)
344 _Panel *panel = (_Panel*)data;
345 int padn = WMGetPopUpButtonSelectedItem(w);
347 WMUnmapWidget(panel->itemPad[panel->currentPad]);
348 WMMapWidget(panel->itemPad[padn]);
350 panel->currentPad = padn;
354 static WEditMenu*
355 putNewSubmenu(WEditMenu *menu, char *title)
357 WEditMenu *tmp;
358 WEditMenuItem *item;
360 item = WAddMenuItemWithTitle(menu, title);
362 tmp = WCreateEditMenu(WMWidgetScreen(menu), title);
363 WSetEditMenuAcceptsDrop(tmp, True);
364 WSetEditMenuDelegate(tmp, &menuDelegate);
365 WSetEditMenuSubmenu(menu, item, tmp);
367 return tmp;
371 static ItemData*
372 putNewItem(_Panel *panel, WEditMenu *menu, int type, char *title)
374 WEditMenuItem *item;
375 ItemData *data;
377 item = WAddMenuItemWithTitle(menu, title);
379 data = NEW(ItemData);
380 data->type = type;
381 WSetEditMenuItemData(item, data, (WMCallback*)freeItemData);
382 WSetEditMenuItemImage(item, panel->markerPix[type]);
384 return data;
388 static WEditMenu*
389 makeFactoryMenu(WMWidget *parent, int width)
391 WEditMenu *pad;
393 pad = WCreateEditMenuPad(parent);
394 WMResizeWidget(pad, width, 10);
395 WSetEditMenuMinSize(pad, wmksize(width, 0));
396 WSetEditMenuMaxSize(pad, wmksize(width, 0));
397 WSetEditMenuSelectable(pad, False);
398 WSetEditMenuEditable(pad, False);
399 WSetEditMenuIsFactory(pad, True);
400 WSetEditMenuDelegate(pad, &menuDelegate);
402 return pad;
406 static void
407 createPanel(_Panel *p)
409 _Panel *panel = (_Panel*)p;
410 WMScreen *scr = WMWidgetScreen(panel->win);
411 WMColor *black = WMBlackColor(scr);
412 WMColor *white = WMWhiteColor(scr);
413 WMColor *gray = WMGrayColor(scr);
414 WMFont *bold = WMBoldSystemFontOfSize(scr, 12);
415 WMFont *font = WMSystemFontOfSize(scr, 12);
416 WMLabel *label;
417 int width;
420 menuDelegate.data = panel;
423 panel->boldFont = bold;
424 panel->normalFont = font;
426 panel->black = black;
427 panel->white = white;
428 panel->gray = gray;
431 Pixmap pix;
432 Display *dpy = WMScreenDisplay(scr);
433 GC gc;
434 WMPixmap *pixm;
436 pixm = WMCreatePixmap(scr, 7, 7, WMScreenDepth(scr), True);
438 pix = WMGetPixmapXID(pixm);
440 XDrawLine(dpy, pix, WMColorGC(black), 0, 3, 6, 3);
441 XDrawLine(dpy, pix, WMColorGC(black), 3, 0, 3, 6);
443 XDrawLine(dpy, pix, WMColorGC(black), 1, 0, 3, 3);
444 XDrawLine(dpy, pix, WMColorGC(black), 1, 6, 3, 3);
445 XDrawLine(dpy, pix, WMColorGC(black), 0, 0, 0, 6);
448 pix = WMGetPixmapMaskXID(pixm);
450 gc = XCreateGC(dpy, pix, 0, NULL);
452 XSetForeground(dpy, gc, 0);
453 XFillRectangle(dpy, pix, gc, 0, 0, 7, 7);
455 XSetForeground(dpy, gc, 1);
456 XDrawLine(dpy, pix, gc, 0, 3, 6, 3);
457 XDrawLine(dpy, pix, gc, 3, 0, 3, 6);
459 panel->markerPix[ExternalInfo] = pixm;
460 panel->markerPix[PipeInfo] = pixm;
461 panel->markerPix[DirectoryInfo] = pixm;
462 panel->markerPix[WSMenuInfo] = pixm;
464 XFreeGC(dpy, gc);
468 panel->frame = WMCreateFrame(panel->win);
469 WMResizeWidget(panel->frame, FRAME_WIDTH, FRAME_HEIGHT);
470 WMMoveWidget(panel->frame, FRAME_LEFT, FRAME_TOP);
472 panel->typeP = WMCreatePopUpButton(panel->frame);
473 WMResizeWidget(panel->typeP, 150, 20);
474 WMMoveWidget(panel->typeP, 10, 10);
476 WMAddPopUpButtonItem(panel->typeP, _("New Items"));
477 WMAddPopUpButtonItem(panel->typeP, _("Sample Commands"));
478 WMAddPopUpButtonItem(panel->typeP, _("Sample Submenus"));
480 WMSetPopUpButtonAction(panel->typeP, changedItemPad, panel);
482 WMSetPopUpButtonSelectedItem(panel->typeP, 0);
485 WEditMenu *pad;
486 WEditMenu *smenu;
487 ItemData *data;
489 pad = makeFactoryMenu(panel->frame, 150);
490 WMMoveWidget(pad, 10, 40);
492 data = putNewItem(panel, pad, ExecInfo, "Run Program");
493 data = putNewItem(panel, pad, CommandInfo, "Internal Command");
494 smenu = putNewSubmenu(pad, "Submenu");
495 data = putNewItem(panel, pad, ExternalInfo, "External Submenu");
496 data = putNewItem(panel, pad, PipeInfo, "Generated Submenu");
497 data = putNewItem(panel, pad, DirectoryInfo, "Directory Contents");
498 data = putNewItem(panel, pad, WSMenuInfo, "Workspace Menu");
500 panel->itemPad[0] = pad;
504 WEditMenu *pad;
505 ItemData *data;
506 WMScrollView *sview;
508 sview = WMCreateScrollView(panel->frame);
509 WMResizeWidget(sview, 150, 180);
510 WMMoveWidget(sview, 10, 40);
511 WMSetScrollViewHasVerticalScroller(sview, True);
513 pad = makeFactoryMenu(panel->frame, 130);
515 WMSetScrollViewContentView(sview, WMWidgetView(pad));
517 data = putNewItem(panel, pad, ExecInfo, _("XTerm"));
518 data->param.exec.command = "xterm -sb -sl 2000 -bg black -fg white";
520 data = putNewItem(panel, pad, ExecInfo, _("rxvt"));
521 data->param.exec.command = "rxvt";
523 data = putNewItem(panel, pad, ExecInfo, _("ETerm"));
524 data->param.exec.command = "eterm";
526 data = putNewItem(panel, pad, ExecInfo, _("Run..."));
527 data->param.exec.command = "%a(Run,Type command to run)";
529 data = putNewItem(panel, pad, ExecInfo, _("Netscape"));
530 data->param.exec.command = "netscape";
532 data = putNewItem(panel, pad, ExecInfo, _("gimp"));
533 data->param.exec.command = "gimp";
535 data = putNewItem(panel, pad, ExecInfo, _("epic"));
536 data->param.exec.command = "xterm -e epic";
538 data = putNewItem(panel, pad, ExecInfo, _("ee"));
539 data->param.exec.command = "ee";
541 data = putNewItem(panel, pad, ExecInfo, _("xv"));
542 data->param.exec.command = "xv";
544 data = putNewItem(panel, pad, ExecInfo, _("Acrobat Reader"));
545 data->param.exec.command = "acroread || /usr/local/Acrobat4/bin/acroread";
547 data = putNewItem(panel, pad, ExecInfo, _("ghostview"));
548 data->param.exec.command = "gv";
550 data = putNewItem(panel, pad, CommandInfo, _("Exit Window Maker"));
551 data->param.command.command = 3;
553 WMMapWidget(pad);
555 panel->itemPad[1] = sview;
560 WEditMenu *pad, *smenu;
561 ItemData *data;
562 WMScrollView *sview;
564 sview = WMCreateScrollView(panel->frame);
565 WMResizeWidget(sview, 150, 180);
566 WMMoveWidget(sview, 10, 40);
567 WMSetScrollViewHasVerticalScroller(sview, True);
569 pad = makeFactoryMenu(panel->frame, 130);
571 WMSetScrollViewContentView(sview, WMWidgetView(pad));
573 /* data = putNewItem(panel, pad, ExternalInfo, _("Debian Menu"));
574 data->param.pipe.command = "/etc/X11/WindowMaker/menu.hook";
576 data = putNewItem(panel, pad, PipeInfo, _("RedHat Menu"));
577 data->param.pipe.command = "wmconfig --output wmaker";
579 data = putNewItem(panel, pad, PipeInfo, _("Menu Conectiva"));
580 data->param.pipe.command = "wmconfig --output wmaker";
582 data = putNewItem(panel, pad, DirectoryInfo, _("Themes"));
583 data->param.directory.command = "setstyle";
584 data->param.directory.directory = "/usr/share/WindowMaker/Themes /usr/local/share/WindowMaker/Themes $HOME/GNUstep/Library/WindowMaker/Themes";
585 data->param.directory.stripExt = 1;
587 data = putNewItem(panel, pad, DirectoryInfo, _("Bg Images (scale)"));
588 data->param.directory.command = "wmsetbg -u -s";
589 data->param.directory.directory = "/opt/kde2/share/wallpapers /usr/share/WindowMaker/Backgrounds $HOME/GNUstep/Library/WindowMaker/Backgrounds";
590 data->param.directory.stripExt = 1;
592 data = putNewItem(panel, pad, DirectoryInfo, _("Bg Images (tile)"));
593 data->param.directory.command = "wmsetbg -u -t";
594 data->param.directory.directory = "/opt/kde2/share/wallpapers /usr/share/WindowMaker/Backgrounds $HOME/GNUstep/Library/WindowMaker/Backgrounds";
595 data->param.directory.stripExt = 1;
597 smenu = putNewSubmenu(pad, _("Assorted XTerms"));
599 data = putNewItem(panel, smenu, ExecInfo, _("XTerm Yellow on Blue"));
600 data->param.exec.command = "xterm -sb -sl 2000 -bg midnightblue -fg yellow";
602 data = putNewItem(panel, smenu, ExecInfo, _("XTerm White on Black"));
603 data->param.exec.command = "xterm -sb -sl 2000 -bg black -fg white";
605 data = putNewItem(panel, smenu, ExecInfo, _("XTerm Black on White"));
606 data->param.exec.command = "xterm -sb -sl 2000 -bg white -fg black";
608 data = putNewItem(panel, smenu, ExecInfo, _("XTerm Black on Beige"));
609 data->param.exec.command = "xterm -sb -sl 2000 -bg '#bbbb99' -fg black";
611 data = putNewItem(panel, smenu, ExecInfo, _("XTerm White on Green"));
612 data->param.exec.command = "xterm -sb -sl 2000 -bg '#228822' -fg white";
614 data = putNewItem(panel, smenu, ExecInfo, _("XTerm White on Olive"));
615 data->param.exec.command = "xterm -sb -sl 2000 -bg '#335533' -fg white";
617 data = putNewItem(panel, smenu, ExecInfo, _("XTerm Blue on Blue"));
618 data->param.exec.command = "xterm -sb -sl 2000 -bg '#112244' -fg '#88aabb'";
620 data = putNewItem(panel, smenu, ExecInfo, _("XTerm BIG FONTS"));
621 data->param.exec.command = "xterm -sb -sl 2000 -bg black -fg white -fn 10x20";
623 WMMapWidget(pad);
625 panel->itemPad[2] = sview;
629 width = FRAME_WIDTH - 20 - 150 - 10;
631 panel->optionsF = WMCreateFrame(panel->frame);
632 WMResizeWidget(panel->optionsF, width, FRAME_HEIGHT - 15);
633 WMMoveWidget(panel->optionsF, 10 + 150 + 10, 5);
635 width -= 20;
637 /* command */
639 panel->commandF = WMCreateFrame(panel->optionsF);
640 WMResizeWidget(panel->commandF, width, 50);
641 WMMoveWidget(panel->commandF, 10, 20);
642 WMSetFrameTitle(panel->commandF, _("Program to Run"));
644 panel->commandT = WMCreateTextField(panel->commandF);
645 WMResizeWidget(panel->commandT, width - 20, 20);
646 WMMoveWidget(panel->commandT, 10, 20);
648 WMAddNotificationObserver(dataChanged, panel,
649 WMTextDidChangeNotification,
650 panel->commandT);
652 #if 0
653 panel->xtermC = WMCreateSwitchButton(panel->commandF);
654 WMResizeWidget(panel->xtermC, width - 20, 20);
655 WMMoveWidget(panel->xtermC, 10, 50);
656 WMSetButtonText(panel->xtermC, _("Run the program inside a Xterm"));
657 #endif
658 WMMapSubwidgets(panel->commandF);
661 /* path */
663 panel->pathF = WMCreateFrame(panel->optionsF);
664 WMResizeWidget(panel->pathF, width, 150);
665 WMMoveWidget(panel->pathF, 10, 40);
666 WMSetFrameTitle(panel->pathF, _("Path for Menu"));
668 panel->pathT = WMCreateTextField(panel->pathF);
669 WMResizeWidget(panel->pathT, width - 20, 20);
670 WMMoveWidget(panel->pathT, 10, 20);
672 WMAddNotificationObserver(dataChanged, panel,
673 WMTextDidChangeNotification,
674 panel->pathT);
676 label = WMCreateLabel(panel->pathF);
677 WMResizeWidget(label, width - 20, 80);
678 WMMoveWidget(label, 10, 50);
679 WMSetLabelText(label, _("Enter the path for a file containing a menu\n"
680 "or a list of directories with the programs you\n"
681 "want to have listed in the menu. Ex:\n"
682 "~/GNUstep/Library/WindowMaker/menu\n"
683 "or\n"
684 "/usr/X11R6/bin ~/xbin"));
686 WMMapSubwidgets(panel->pathF);
689 /* pipe */
691 panel->pipeF = WMCreateFrame(panel->optionsF);
692 WMResizeWidget(panel->pipeF, width, 100);
693 WMMoveWidget(panel->pipeF, 10, 50);
694 WMSetFrameTitle(panel->pipeF, _("Command"));
696 panel->pipeT = WMCreateTextField(panel->pipeF);
697 WMResizeWidget(panel->pipeT, width - 20, 20);
698 WMMoveWidget(panel->pipeT, 10, 20);
700 WMAddNotificationObserver(dataChanged, panel,
701 WMTextDidChangeNotification,
702 panel->pipeT);
705 label = WMCreateLabel(panel->pipeF);
706 WMResizeWidget(label, width - 20, 40);
707 WMMoveWidget(label, 10, 50);
708 WMSetLabelText(label, _("Enter a command that outputs a menu\n"
709 "definition to stdout when invoked."));
711 WMMapSubwidgets(panel->pipeF);
714 /* directory menu */
716 panel->dcommandF = WMCreateFrame(panel->optionsF);
717 WMResizeWidget(panel->dcommandF, width, 90);
718 WMMoveWidget(panel->dcommandF, 10, 25);
719 WMSetFrameTitle(panel->dcommandF, _("Command to Open Files"));
721 panel->dcommandT = WMCreateTextField(panel->dcommandF);
722 WMResizeWidget(panel->dcommandT, width - 20, 20);
723 WMMoveWidget(panel->dcommandT, 10, 20);
725 WMAddNotificationObserver(dataChanged, panel,
726 WMTextDidChangeNotification,
727 panel->dcommandT);
730 label = WMCreateLabel(panel->dcommandF);
731 WMResizeWidget(label, width - 20, 45);
732 WMMoveWidget(label, 10, 40);
733 WMSetLabelText(label, _("Enter the command you want to use to open the\n"
734 "files in the directories listed below."));
736 WMMapSubwidgets(panel->dcommandF);
739 panel->dpathF = WMCreateFrame(panel->optionsF);
740 WMResizeWidget(panel->dpathF, width, 80);
741 WMMoveWidget(panel->dpathF, 10, 125);
742 WMSetFrameTitle(panel->dpathF, _("Directories with Files"));
744 panel->dpathT = WMCreateTextField(panel->dpathF);
745 WMResizeWidget(panel->dpathT, width - 20, 20);
746 WMMoveWidget(panel->dpathT, 10, 20);
748 WMAddNotificationObserver(dataChanged, panel,
749 WMTextDidChangeNotification,
750 panel->dpathT);
752 panel->dstripB = WMCreateSwitchButton(panel->dpathF);
753 WMResizeWidget(panel->dstripB, width - 20, 20);
754 WMMoveWidget(panel->dstripB, 10, 50);
755 WMSetButtonText(panel->dstripB, _("Strip extensions from file names"));
757 WMSetButtonAction(panel->dstripB, buttonClicked, panel);
759 WMMapSubwidgets(panel->dpathF);
762 /* shortcut */
764 panel->shortF = WMCreateFrame(panel->optionsF);
765 WMResizeWidget(panel->shortF, width, 50);
766 WMMoveWidget(panel->shortF, 10, 160);
767 WMSetFrameTitle(panel->shortF, _("Keyboard Shortcut"));
769 panel->shortT = WMCreateTextField(panel->shortF);
770 WMResizeWidget(panel->shortT, width - 20 - 170, 20);
771 WMMoveWidget(panel->shortT, 10, 20);
773 WMAddNotificationObserver(dataChanged, panel,
774 WMTextDidChangeNotification,
775 panel->shortT);
777 panel->sgrabB = WMCreateCommandButton(panel->shortF);
778 WMResizeWidget(panel->sgrabB, 80, 24);
779 WMMoveWidget(panel->sgrabB, width - 90, 18);
780 WMSetButtonText(panel->sgrabB, _("Capture"));
781 WMSetButtonAction(panel->sgrabB, sgrabClicked, panel);
783 panel->sclearB = WMCreateCommandButton(panel->shortF);
784 WMResizeWidget(panel->sclearB, 80, 24);
785 WMMoveWidget(panel->sclearB, width - 175, 18);
786 WMSetButtonText(panel->sclearB, _("Clear"));
787 WMSetButtonAction(panel->sclearB, sgrabClicked, panel);
789 WMMapSubwidgets(panel->shortF);
791 /* internal command */
793 panel->icommandL = WMCreateList(panel->optionsF);
794 WMResizeWidget(panel->icommandL, width, 80);
795 WMMoveWidget(panel->icommandL, 10, 20);
797 WMSetListAction(panel->icommandL, icommandLClicked, panel);
799 WMAddNotificationObserver(dataChanged, panel,
800 WMListSelectionDidChangeNotification,
801 panel->icommandL);
803 WMInsertListItem(panel->icommandL, 0, _("Arrange Icons"));
804 WMInsertListItem(panel->icommandL, 1, _("Hide All Windows Except For The Focused One"));
805 WMInsertListItem(panel->icommandL, 2, _("Show All Windows"));
807 WMInsertListItem(panel->icommandL, 3, _("Exit Window Maker"));
808 WMInsertListItem(panel->icommandL, 4, _("Exit X Session"));
809 WMInsertListItem(panel->icommandL, 5, _("Restart Window Maker"));
810 WMInsertListItem(panel->icommandL, 6, _("Start Another Window Manager : ("));
812 WMInsertListItem(panel->icommandL, 7, _("Save Current Session"));
813 WMInsertListItem(panel->icommandL, 8, _("Clear Saved Session"));
814 WMInsertListItem(panel->icommandL, 9, _("Refresh Screen"));
815 WMInsertListItem(panel->icommandL, 10, _("Open Info Panel"));
816 WMInsertListItem(panel->icommandL, 11, _("Open Copyright Panel"));
819 panel->paramF = WMCreateFrame(panel->optionsF);
820 WMResizeWidget(panel->paramF, width, 50);
821 WMMoveWidget(panel->paramF, 10, 105);
822 WMSetFrameTitle(panel->paramF, _("Window Manager to Start"));
824 panel->paramT = WMCreateTextField(panel->paramF);
825 WMResizeWidget(panel->paramT, width - 20, 20);
826 WMMoveWidget(panel->paramT, 10, 20);
828 WMAddNotificationObserver(dataChanged, panel,
829 WMTextDidChangeNotification,
830 panel->paramT);
832 WMMapSubwidgets(panel->paramF);
835 panel->quickB = WMCreateSwitchButton(panel->optionsF);
836 WMResizeWidget(panel->quickB, width, 20);
837 WMMoveWidget(panel->quickB, 10, 120);
838 WMSetButtonText(panel->quickB, _("Do not confirm action."));
839 WMSetButtonAction(panel->quickB, buttonClicked, panel);
844 label = WMCreateLabel(panel->optionsF);
845 WMResizeWidget(label, width - 20, FRAME_HEIGHT - 50);
846 WMMoveWidget(label, 10, 20);
847 WMSetLabelText(label,
848 _("Instructions:\n\n"
849 " - drag items from the left to the menu to add new items\n"
850 " - drag items out of the menu to remove items\n"
851 " - drag items in menu to change their position\n"
852 " - double click in a menu item to change the label\n"
853 " - click on a menu item to change related information"));
856 WMRealizeWidget(panel->frame);
857 WMMapSubwidgets(panel->frame);
858 WMMapWidget(panel->frame);
862 int i;
863 for (i = 0; i < 3; i++)
864 WMUnmapWidget(panel->itemPad[i]);
866 changedItemPad(panel->typeP, panel);
868 panel->sections[NoInfo][0] = label;
870 panel->sections[ExecInfo][0] = panel->commandF;
871 panel->sections[ExecInfo][1] = panel->shortF;
873 panel->sections[CommandInfo][0] = panel->icommandL;
874 panel->sections[CommandInfo][1] = label;
875 panel->sections[CommandInfo][2] = panel->shortF;
877 panel->sections[ExternalInfo][0] = panel->pathF;
879 panel->sections[PipeInfo][0] = panel->pipeF;
881 panel->sections[DirectoryInfo][0] = panel->dpathF;
882 panel->sections[DirectoryInfo][1] = panel->dcommandF;
884 panel->currentType = NoInfo;
886 showData(panel);
892 static void
893 freeItemData(ItemData *data)
895 #define CFREE(d) if (d) free(d)
897 /* TODO */
898 switch (data->type) {
899 case CommandInfo:
900 CFREE(data->param.command.parameter);
901 CFREE(data->param.command.shortcut);
902 break;
904 case ExecInfo:
905 CFREE(data->param.exec.command);
906 CFREE(data->param.exec.shortcut);
907 break;
909 case PipeInfo:
910 CFREE(data->param.pipe.command);
911 break;
913 case ExternalInfo:
914 CFREE(data->param.external.path);
915 break;
917 case DirectoryInfo:
918 CFREE(data->param.directory.command);
919 CFREE(data->param.directory.directory);
920 break;
922 default:
923 break;
926 free(data);
927 #undef CFREE
931 static ItemData*
932 parseCommand(proplist_t item)
934 ItemData *data = NEW(ItemData);
935 proplist_t p;
936 char *command = NULL;
937 char *parameter = NULL;
938 char *shortcut = NULL;
939 int i = 1;
942 p = PLGetArrayElement(item, i++);
943 command = PLGetString(p);
944 if (strcmp(command, "SHORTCUT") == 0) {
945 p = PLGetArrayElement(item, i++);
946 shortcut = PLGetString(p);
947 p = PLGetArrayElement(item, i++);
948 command = PLGetString(p);
950 p = PLGetArrayElement(item, i++);
951 if (p)
952 parameter = PLGetString(p);
954 if (strcmp(command, "EXEC") == 0 || strcmp(command, "SHEXEC") == 0) {
956 data->type = ExecInfo;
958 data->param.exec.command = wstrdup(parameter);
959 if (shortcut)
960 data->param.exec.shortcut = wstrdup(shortcut);
962 } else if (strcmp(command, "OPEN_MENU") == 0) {
963 char *p;
965 * dir menu, menu file
966 * dir WITH
967 * |pipe (TODO: ||pipe)
969 p = parameter;
970 while (isspace(*p) && *p) p++;
971 if (*p == '|') {
972 data->type = PipeInfo;
973 data->param.pipe.command = wtrimspace(p+1);
974 } else {
975 char *s;
977 p = wstrdup(p);
979 s = strstr(p, "WITH");
980 if (s) {
981 char **tokens;
982 char **ctokens;
983 int tokn;
984 int i, j;
986 data->type = DirectoryInfo;
988 *s = '\0';
989 s += 5;
990 while (*s && isspace(*s)) s++;
991 data->param.directory.command = wstrdup(s);
993 wtokensplit(p, &tokens, &tokn);
994 free(p);
996 ctokens = wmalloc(sizeof(char*)*tokn);
998 for (i = 0, j = 0; i < tokn; i++) {
999 if (strcmp(tokens[i], "-noext") == 0) {
1000 free(tokens[i]);
1001 data->param.directory.stripExt = 1;
1002 } else {
1003 ctokens[j++] = tokens[i];
1006 data->param.directory.directory = wtokenjoin(ctokens, j);
1007 free(ctokens);
1009 wtokenfree(tokens, tokn);
1010 } else {
1011 data->type = ExternalInfo;
1012 data->param.external.path = p;
1015 } else if (strcmp(command, "WORKSPACE_MENU") == 0) {
1016 data->type = WSMenuInfo;
1017 } else {
1018 int cmd;
1020 if (strcmp(command, "ARRANGE_ICONS") == 0) {
1021 cmd = 0;
1022 } else if (strcmp(command, "HIDE_OTHERS") == 0) {
1023 cmd = 1;
1024 } else if (strcmp(command, "SHOW_ALL") == 0) {
1025 cmd = 2;
1026 } else if (strcmp(command, "EXIT") == 0) {
1027 cmd = 3;
1028 } else if (strcmp(command, "SHUTDOWN") == 0) {
1029 cmd = 4;
1030 } else if (strcmp(command, "RESTART") == 0) {
1031 if (parameter) {
1032 cmd = 6;
1033 } else {
1034 cmd = 5;
1036 } else if (strcmp(command, "SAVE_SESSION") == 0) {
1037 cmd = 7;
1038 } else if (strcmp(command, "CLEAR_SESSION") == 0) {
1039 cmd = 8;
1040 } else if (strcmp(command, "REFRESH") == 0) {
1041 cmd = 9;
1042 } else if (strcmp(command, "INFO_PANEL") == 0) {
1043 cmd = 10;
1044 } else if (strcmp(command, "LEGAL_PANEL") == 0) {
1045 cmd = 11;
1046 } else {
1047 wwarning(_("unknown command '%s' in menu"), command);
1048 goto error;
1051 data->type = CommandInfo;
1053 data->param.command.command = cmd;
1054 if (shortcut)
1055 data->param.command.shortcut = wstrdup(shortcut);
1056 if (parameter)
1057 data->param.command.parameter = wstrdup(parameter);
1060 return data;
1062 error:
1063 free(data);
1065 return NULL;
1071 static void
1072 updateFrameTitle(_Panel *panel, char *title, InfoType type)
1074 if (type != NoInfo) {
1075 char *tmp;
1077 switch (type) {
1078 case ExecInfo:
1079 tmp = wstrappend(title, _(": Execute Program"));
1080 break;
1082 case CommandInfo:
1083 tmp = wstrappend(title, _(": Perform Internal Command"));
1084 break;
1086 case ExternalInfo:
1087 tmp = wstrappend(title, _(": Open a Submenu"));
1088 break;
1090 case PipeInfo:
1091 tmp = wstrappend(title, _(": Program Generated Submenu"));
1092 break;
1094 case DirectoryInfo:
1095 tmp = wstrappend(title, _(": Directory Contents Menu"));
1096 break;
1098 case WSMenuInfo:
1099 tmp = wstrappend(title, _(": Open Workspaces Submenu"));
1100 break;
1102 default:
1103 tmp = NULL;
1104 break;
1106 WMSetFrameTitle(panel->optionsF, tmp);
1107 free(tmp);
1108 } else {
1109 WMSetFrameTitle(panel->optionsF, NULL);
1115 static void
1116 changeInfoType(_Panel *panel, char *title, InfoType type)
1118 WMWidget **w;
1120 if (panel->currentType != type) {
1122 w = panel->sections[panel->currentType];
1124 while (*w) {
1125 WMUnmapWidget(*w);
1126 w++;
1128 WMUnmapWidget(panel->paramF);
1129 WMUnmapWidget(panel->quickB);
1133 w = panel->sections[type];
1135 while (*w) {
1136 WMMapWidget(*w);
1137 w++;
1141 updateFrameTitle(panel, title, type);
1143 panel->currentType = type;
1149 static void
1150 updateMenuItem(_Panel *panel, WEditMenuItem *item, WMWidget *changedWidget)
1152 ItemData *data = WGetEditMenuItemData(item);
1154 assert(data != NULL);
1156 #define REPLACE(v, d) if (v) free(v); v = d
1158 switch (data->type) {
1159 case ExecInfo:
1160 if (changedWidget == panel->commandT) {
1161 REPLACE(data->param.exec.command,
1162 WMGetTextFieldText(panel->commandT));
1164 if (changedWidget == panel->shortT) {
1165 REPLACE(data->param.exec.shortcut,
1166 WMGetTextFieldText(panel->shortT));
1168 break;
1170 case CommandInfo:
1171 if (changedWidget == panel->icommandL) {
1172 data->param.command.command =
1173 WMGetListSelectedItemRow(panel->icommandL);
1175 switch (data->param.command.command) {
1176 case 3:
1177 case 4:
1178 if (changedWidget == panel->quickB) {
1179 REPLACE(data->param.command.parameter,
1180 WMGetButtonSelected(panel->quickB)
1181 ? wstrdup("QUICK") : NULL);
1183 break;
1185 case 6:
1186 if (changedWidget == panel->paramT) {
1187 REPLACE(data->param.command.parameter,
1188 WMGetTextFieldText(panel->paramT));
1190 break;
1192 if (changedWidget == panel->shortT) {
1193 REPLACE(data->param.command.shortcut,
1194 WMGetTextFieldText(panel->shortT));
1198 break;
1200 case PipeInfo:
1201 if (changedWidget == panel->pipeT) {
1202 REPLACE(data->param.pipe.command,
1203 WMGetTextFieldText(panel->pipeT));
1205 break;
1207 case ExternalInfo:
1208 if (changedWidget == panel->pathT) {
1209 REPLACE(data->param.external.path,
1210 WMGetTextFieldText(panel->pathT));
1212 break;
1214 case DirectoryInfo:
1215 if (changedWidget == panel->dpathT) {
1216 REPLACE(data->param.directory.directory,
1217 WMGetTextFieldText(panel->dpathT));
1219 if (changedWidget == panel->dcommandT) {
1220 REPLACE(data->param.directory.command,
1221 WMGetTextFieldText(panel->dcommandT));
1223 if (changedWidget == panel->dstripB) {
1224 data->param.directory.stripExt =
1225 WMGetButtonSelected(panel->dstripB);
1227 break;
1229 default:
1230 assert(0);
1231 break;
1234 #undef REPLACE
1239 static void
1240 menuItemCloned(WEditMenuDelegate *delegate, WEditMenu *menu,
1241 WEditMenuItem *origItem, WEditMenuItem *newItem)
1243 ItemData *data = WGetEditMenuItemData(origItem);
1244 ItemData *newData;
1246 if (!data)
1247 return;
1249 #define DUP(s) (s) ? wstrdup(s) : NULL
1251 newData = NEW(ItemData);
1253 newData->type = data->type;
1255 switch (data->type) {
1256 case ExecInfo:
1257 newData->param.exec.command = DUP(data->param.exec.command);
1258 newData->param.exec.shortcut = DUP(data->param.exec.shortcut);
1259 break;
1261 case CommandInfo:
1262 newData->param.command.command = data->param.command.command;
1263 newData->param.command.parameter = DUP(data->param.command.parameter);
1264 newData->param.command.shortcut = DUP(data->param.command.shortcut);
1265 break;
1267 case PipeInfo:
1268 newData->param.pipe.command = DUP(data->param.pipe.command);
1269 break;
1271 case ExternalInfo:
1272 newData->param.external.path = DUP(data->param.external.path);
1273 break;
1275 case DirectoryInfo:
1276 newData->param.directory.directory = DUP(data->param.directory.directory);
1277 newData->param.directory.command = DUP(data->param.directory.command);
1278 newData->param.directory.stripExt = data->param.directory.stripExt;
1279 break;
1281 default:
1282 break;
1285 #undef DUP
1287 WSetEditMenuItemData(newItem, newData, (WMCallback*)freeItemData);
1293 static void menuItemEdited(struct WEditMenuDelegate *delegate, WEditMenu *menu,
1294 WEditMenuItem *item)
1296 _Panel *panel = (_Panel*)delegate->data;
1297 WEditMenu *submenu;
1299 updateFrameTitle(panel, WGetEditMenuItemTitle(item), panel->currentType);
1301 submenu = WGetEditMenuSubmenu(menu, item);
1302 if (submenu) {
1303 WSetEditMenuTitle(submenu, WGetEditMenuItemTitle(item));
1311 static Bool shouldRemoveItem(struct WEditMenuDelegate *delegate,
1312 WEditMenu *menu, WEditMenuItem *item)
1314 _Panel *panel = (_Panel*)delegate->data;
1316 if (panel->dontAsk)
1317 return True;
1319 if (WGetEditMenuSubmenu(menu, item)) {
1320 int res;
1322 res = WMRunAlertPanel(WMWidgetScreen(menu), NULL,
1323 _("Remove Submenu"),
1324 _("Removing this item will destroy all items inside\n"
1325 "the submenu. Do you really want to do that?"),
1326 _("Yes"), _("No"),
1327 _("Yes, don't ask again."));
1328 switch (res) {
1329 case WAPRDefault:
1330 return True;
1331 case WAPRAlternate:
1332 return False;
1333 case WAPROther:
1334 panel->dontAsk = True;
1335 return True;
1338 return True;
1342 static void
1343 menuItemDeselected(WEditMenuDelegate *delegate, WEditMenu *menu,
1344 WEditMenuItem *item)
1346 _Panel *panel = (_Panel*)delegate->data;
1348 changeInfoType(panel, NULL, NoInfo);
1352 static void
1353 menuItemSelected(WEditMenuDelegate *delegate, WEditMenu *menu,
1354 WEditMenuItem *item)
1356 ItemData *data = WGetEditMenuItemData(item);
1357 _Panel *panel = (_Panel*)delegate->data;
1359 panel->currentItem = item;
1361 if (data) {
1362 changeInfoType(panel, WGetEditMenuItemTitle(item), data->type);
1364 switch (data->type) {
1365 case NoInfo:
1366 break;
1368 case ExecInfo:
1369 WMSetTextFieldText(panel->commandT, data->param.exec.command);
1370 WMSetTextFieldText(panel->shortT, data->param.exec.shortcut);
1371 break;
1373 case CommandInfo:
1374 WMSelectListItem(panel->icommandL,
1375 data->param.command.command);
1376 WMSetListPosition(panel->icommandL,
1377 data->param.command.command - 2);
1378 WMSetTextFieldText(panel->shortT, data->param.command.shortcut);
1380 switch (data->param.command.command) {
1381 case 3:
1382 case 4:
1383 WMSetButtonSelected(panel->quickB,
1384 data->param.command.parameter!=NULL);
1385 break;
1386 case 6:
1387 WMSetTextFieldText(panel->paramT,
1388 data->param.command.parameter);
1389 break;
1392 icommandLClicked(panel->icommandL, panel);
1393 break;
1395 case PipeInfo:
1396 WMSetTextFieldText(panel->pipeT, data->param.pipe.command);
1397 break;
1399 case ExternalInfo:
1400 WMSetTextFieldText(panel->pathT, data->param.external.path);
1401 break;
1403 case DirectoryInfo:
1404 WMSetTextFieldText(panel->dpathT, data->param.directory.directory);
1405 WMSetTextFieldText(panel->dcommandT, data->param.directory.command);
1406 WMSetButtonSelected(panel->dstripB, data->param.directory.stripExt);
1407 break;
1409 case WSMenuInfo:
1410 break;
1412 default:
1413 break;
1420 static WEditMenu*
1421 buildSubmenu(_Panel *panel, proplist_t pl)
1423 WMScreen *scr = WMWidgetScreen(panel->win);
1424 WEditMenu *menu;
1425 WEditMenuItem *item;
1426 char *title;
1427 proplist_t tp, bp;
1428 int i;
1430 tp = PLGetArrayElement(pl, 0);
1431 title = PLGetString(tp);
1433 menu = WCreateEditMenu(scr, title);
1435 for (i = 1; i < PLGetNumberOfElements(pl); i++) {
1436 proplist_t pi;
1438 pi = PLGetArrayElement(pl, i);
1440 tp = PLGetArrayElement(pi, 0);
1441 bp = PLGetArrayElement(pi, 1);
1443 title = PLGetString(tp);
1445 if (PLIsArray(bp)) { /* it's a submenu */
1446 WEditMenu *submenu;
1448 submenu = buildSubmenu(panel, pi);
1450 item = WAddMenuItemWithTitle(menu, title);
1452 WSetEditMenuSubmenu(menu, item, submenu);
1453 } else {
1454 ItemData *data;
1456 item = WAddMenuItemWithTitle(menu, title);
1458 data = parseCommand(pi);
1460 if (panel->markerPix[data->type])
1461 WSetEditMenuItemImage(item, panel->markerPix[data->type]);
1462 WSetEditMenuItemData(item, data, (WMCallback*)freeItemData);
1466 WSetEditMenuAcceptsDrop(menu, True);
1467 WSetEditMenuDelegate(menu, &menuDelegate);
1469 WMRealizeWidget(menu);
1471 return menu;
1476 static void
1477 buildMenuFromPL(_Panel *panel, proplist_t pl)
1479 panel->menu = buildSubmenu(panel, pl);
1480 WMMapWidget(panel->menu);
1485 static proplist_t
1486 getDefaultMenu(_Panel *panel)
1488 proplist_t menu, pmenu;
1489 char *menuPath, *gspath;
1491 gspath = wusergnusteppath();
1493 menuPath = wmalloc(strlen(gspath)+128);
1494 /* if there is a localized plmenu for the tongue put it's filename here */
1495 sprintf(menuPath, _("%s/Library/WindowMaker/plmenu"), gspath);
1497 menu = PLGetProplistWithPath(menuPath);
1498 if (!menu) {
1499 wwarning("%s:could not read property list menu", menuPath);
1501 if (strcmp("%s/Library/WindowMaker/plmenu",
1502 _("%s/Library/WindowMaker/plmenu"))!=0) {
1504 sprintf(menuPath, "%s/Library/WindowMaker/plmenu", gspath);
1505 menu = PLGetProplistWithPath(menuPath);
1506 wwarning("%s:could not read property list menu", menuPath);
1508 if (!menu) {
1509 char buffer[512];
1511 sprintf(buffer, _("Could not open default menu from '%s'"),
1512 menuPath);
1513 WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
1514 _("Error"), buffer, _("OK"), NULL, NULL);
1518 free(menuPath);
1520 if (menu) {
1521 pmenu = menu;
1522 } else {
1523 pmenu = NULL;
1526 return pmenu;
1530 static void
1531 showData(_Panel *panel)
1533 char *gspath;
1534 char *menuPath;
1535 proplist_t pmenu;
1537 gspath = wusergnusteppath();
1539 menuPath = wmalloc(strlen(gspath)+32);
1540 strcpy(menuPath, gspath);
1541 strcat(menuPath, "/Defaults/WMRootMenu");
1543 pmenu = PLGetProplistWithPath(menuPath);
1545 if (!pmenu || !PLIsArray(pmenu)) {
1546 int res;
1548 res = WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
1549 _("Warning"),
1550 _("The menu file format currently in use is not supported\n"
1551 "by this tool. Do you want to discard the current menu\n"
1552 "to use this tool?"),
1553 _("Yes, Discard and Update"),
1554 _("No, Keep Current Menu"), NULL);
1556 if (res == WAPRDefault) {
1557 pmenu = getDefaultMenu(panel);
1559 if (!pmenu) {
1560 pmenu = PLMakeArrayFromElements(PLMakeString("Applications"),
1561 NULL);
1563 } else {
1564 panel->dontSave = True;
1565 return;
1569 panel->menuPath = menuPath;
1571 buildMenuFromPL(panel, pmenu);
1573 PLRelease(pmenu);
1577 static Bool
1578 notblank(char *s)
1580 if (s) {
1581 while (*s++) {
1582 if (!isspace(*s))
1583 return True;
1586 return False;
1590 static proplist_t
1591 processData(char *title, ItemData *data)
1593 proplist_t item;
1594 char *s1;
1595 static char *pscut = NULL;
1596 static char *pomenu = NULL;
1597 int i;
1599 if (!pscut) {
1600 pscut = PLMakeString("SHORTCUT");
1601 pomenu = PLMakeString("OPEN_MENU");
1604 item = PLMakeArrayFromElements(PLMakeString(title), NULL);
1607 switch (data->type) {
1608 case ExecInfo:
1609 #if 1
1610 if (strpbrk(data->param.exec.command, "&$*|><?`")) {
1611 s1 = "SHEXEC";
1612 } else {
1613 s1 = "EXEC";
1615 #else
1616 s1 = "SHEXEC";
1617 #endif
1619 if (notblank(data->param.exec.shortcut)) {
1620 PLAppendArrayElement(item, pscut);
1621 PLAppendArrayElement(item,
1622 PLMakeString(data->param.exec.shortcut));
1625 PLAppendArrayElement(item, PLMakeString(s1));
1626 PLAppendArrayElement(item, PLMakeString(data->param.exec.command));
1627 break;
1629 case CommandInfo:
1630 if (notblank(data->param.command.shortcut)) {
1631 PLAppendArrayElement(item, pscut);
1632 PLAppendArrayElement(item,
1633 PLMakeString(data->param.command.shortcut));
1636 i = data->param.command.command;
1638 PLAppendArrayElement(item, PLMakeString(commandNames[i]));
1640 switch (i) {
1641 case 3:
1642 case 4:
1643 if (data->param.command.parameter)
1644 PLAppendArrayElement(item,
1645 PLMakeString(data->param.command.parameter));
1646 break;
1648 case 7: /* restart */
1649 if (data->param.command.parameter)
1650 PLAppendArrayElement(item,
1651 PLMakeString(data->param.command.parameter));
1652 break;
1655 break;
1657 case PipeInfo:
1658 PLAppendArrayElement(item, pomenu);
1659 s1 = wstrappend("| ", data->param.pipe.command);
1660 PLAppendArrayElement(item, PLMakeString(s1));
1661 free(s1);
1662 break;
1664 case ExternalInfo:
1665 PLAppendArrayElement(item, pomenu);
1666 PLAppendArrayElement(item, PLMakeString(data->param.external.path));
1667 break;
1669 case DirectoryInfo:
1671 int l;
1672 char *tmp;
1674 l = strlen(data->param.directory.directory);
1675 l += strlen(data->param.directory.command);
1676 l += 32;
1678 PLAppendArrayElement(item, pomenu);
1680 tmp = wmalloc(l);
1681 sprintf(tmp, "%s%s WITH %s",
1682 data->param.directory.stripExt ? "-noext " : "",
1683 data->param.directory.directory,
1684 data->param.directory.command);
1686 PLAppendArrayElement(item, PLMakeString(tmp));
1687 free(tmp);
1689 break;
1691 case WSMenuInfo:
1692 PLAppendArrayElement(item, PLMakeString("WORKSPACE_MENU"));
1693 break;
1695 default:
1696 assert(0);
1697 break;
1700 return item;
1704 static proplist_t
1705 processSubmenu(WEditMenu *menu)
1707 WEditMenuItem *item;
1708 proplist_t pmenu;
1709 proplist_t pl;
1710 char *s;
1711 int i;
1714 s = WGetEditMenuTitle(menu);
1715 pl = PLMakeString(s);
1717 pmenu = PLMakeArrayFromElements(pl, NULL);
1719 i = 0;
1720 while ((item = WGetEditMenuItem(menu, i++))) {
1721 WEditMenu *submenu;
1723 s = WGetEditMenuItemTitle(item);
1725 submenu = WGetEditMenuSubmenu(menu, item);
1726 if (submenu) {
1727 pl = processSubmenu(submenu);
1728 } else {
1729 pl = processData(s, WGetEditMenuItemData(item));
1732 PLAppendArrayElement(pmenu, pl);
1735 return pmenu;
1740 static proplist_t
1741 buildPLFromMenu(_Panel *panel)
1743 proplist_t menu;
1745 menu = processSubmenu(panel->menu);
1747 return menu;
1753 static void
1754 storeData(_Panel *panel)
1756 proplist_t menu;
1758 if (panel->dontSave)
1759 return;
1761 menu = buildPLFromMenu(panel);
1763 PLSetFilename(menu, PLMakeString(panel->menuPath));
1765 PLSave(menu, YES);
1767 PLRelease(menu);
1771 Panel*
1772 InitMenu(WMScreen *scr, WMWindow *win)
1774 _Panel *panel;
1776 panel = wmalloc(sizeof(_Panel));
1777 memset(panel, 0, sizeof(_Panel));
1779 panel->sectionName = _("Applications Menu Definition");
1781 panel->description = _("Edit the menu for launching applications.");
1783 panel->win = win;
1785 panel->callbacks.createWidgets = createPanel;
1786 panel->callbacks.updateDomain = storeData;
1788 AddSection(panel, ICON_FILE);
1790 return panel;