fixed crash bug with empty menus
[wmaker-crm.git] / WPrefs.app / Menu.c
blobb6fdcdf4e087eec02f3efc008eeb58c64cf18c90
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 WWindowListInfo,
44 LastInfo
45 } InfoType;
47 #define MAX_SECTION_SIZE 4
49 typedef struct _Panel {
50 WMBox *box;
51 char *sectionName;
53 char *description;
55 CallbackRec callbacks;
56 WMWidget *parent;
59 WMFont *boldFont;
60 WMFont *normalFont;
61 WMColor *white;
62 WMColor *gray;
63 WMColor *black;
65 WMPixmap *markerPix[LastInfo];
67 WMPopUpButton *typeP;
69 WMWidget *itemPad[3];
70 int currentPad;
72 WEditMenu *menu;
73 char *menuPath;
75 WMFrame *optionsF;
77 WMFrame *commandF;
78 WMTextField *commandT; /* command to run */
79 WMButton *xtermC; /* inside xterm? */
81 WMFrame *pathF;
82 WMTextField *pathT;
84 WMFrame *pipeF;
85 WMTextField *pipeT;
87 WMFrame *dpathF;
88 WMTextField *dpathT;
90 WMFrame *dcommandF;
91 WMTextField *dcommandT;
93 WMButton *dstripB;
95 WMFrame *shortF;
96 WMTextField *shortT;
97 WMButton *sgrabB;
98 WMButton *sclearB;
100 WMList *icommandL;
102 WMFrame *paramF;
103 WMTextField *paramT;
105 WMButton *quickB;
107 Bool dontAsk; /* whether to comfirm submenu remove */
108 Bool dontSave;
110 Bool capturing;
113 /* about the currently selected item */
114 WEditMenuItem *currentItem;
115 InfoType currentType;
116 WMWidget *sections[LastInfo][MAX_SECTION_SIZE];
117 } _Panel;
120 typedef struct {
121 InfoType type;
122 union {
123 struct {
124 int command;
125 char *parameter;
126 char *shortcut;
127 } command;
128 struct {
129 char *command;
130 char *shortcut;
131 } exec;
132 struct {
133 char *path;
134 } external;
135 struct {
136 char *command;
137 } pipe;
138 struct {
139 char *directory;
140 char *command;
141 unsigned stripExt:1;
142 } directory;
143 } param;
144 } ItemData;
148 static char *commandNames[] = {
149 "ARRANGE_ICONS",
150 "HIDE_OTHERS",
151 "SHOW_ALL",
152 "EXIT",
153 "SHUTDOWN",
154 "RESTART",
155 "RESTART",
156 "SAVE_SESSION",
157 "CLEAR_SESSION",
158 "REFRESH",
159 "INFO_PANEL",
160 "LEGAL_PANEL"
165 #define NEW(type) memset(wmalloc(sizeof(type)), 0, sizeof(type))
168 #define ICON_FILE "menus"
172 static void showData(_Panel *panel);
175 static void updateMenuItem(_Panel *panel, WEditMenuItem *item,
176 WMWidget *changedWidget);
178 static void menuItemSelected(struct WEditMenuDelegate *delegate,
179 WEditMenu *menu, WEditMenuItem *item);
181 static void menuItemDeselected(struct WEditMenuDelegate *delegate,
182 WEditMenu *menu, WEditMenuItem *item);
184 static void menuItemCloned(struct WEditMenuDelegate *delegate, WEditMenu *menu,
185 WEditMenuItem *origItem, WEditMenuItem *newItem);
187 static void menuItemEdited(struct WEditMenuDelegate *delegate, WEditMenu *menu,
188 WEditMenuItem *item);
190 static Bool shouldRemoveItem(struct WEditMenuDelegate *delegate,
191 WEditMenu *menu, WEditMenuItem *item);
194 static void freeItemData(ItemData *data);
198 static WEditMenuDelegate menuDelegate = {
199 NULL,
200 menuItemCloned,
201 menuItemEdited,
202 menuItemSelected,
203 menuItemDeselected,
204 shouldRemoveItem
208 static void
209 dataChanged(void *self, WMNotification *notif)
211 _Panel *panel = (_Panel*)self;
212 WEditMenuItem *item = panel->currentItem;
213 WMWidget *w = (WMWidget*)WMGetNotificationObject(notif);
215 updateMenuItem(panel, item, w);
219 static void
220 buttonClicked(WMWidget *w, void *data)
222 _Panel *panel = (_Panel*)data;
223 WEditMenuItem *item = panel->currentItem;
225 updateMenuItem(panel, item, w);
229 static void
230 icommandLClicked(WMWidget *w, void *data)
232 _Panel *panel = (_Panel*)data;
233 int cmd;
235 cmd = WMGetListSelectedItemRow(w);
236 if (cmd == 3 || cmd == 4) {
237 WMMapWidget(panel->quickB);
238 } else {
239 WMUnmapWidget(panel->quickB);
241 if (cmd == 6) {
242 WMMapWidget(panel->paramF);
243 } else {
244 WMUnmapWidget(panel->paramF);
256 static char*
257 captureShortcut(Display *dpy, _Panel *panel)
259 XEvent ev;
260 KeySym ksym;
261 char buffer[64];
262 char *key = NULL;
264 while (panel->capturing) {
265 XAllowEvents(dpy, AsyncKeyboard, CurrentTime);
266 WMNextEvent(dpy, &ev);
267 if (ev.type==KeyPress && ev.xkey.keycode!=0) {
268 ksym = XKeycodeToKeysym(dpy, ev.xkey.keycode, 0);
269 if (!IsModifierKey(ksym)) {
270 key=XKeysymToString(ksym);
271 panel->capturing = 0;
272 break;
275 WMHandleEvent(&ev);
278 if (!key)
279 return NULL;
281 buffer[0] = 0;
283 if (ev.xkey.state & ControlMask) {
284 strcat(buffer, "Control+");
286 if (ev.xkey.state & ShiftMask) {
287 strcat(buffer, "Shift+");
289 if (ev.xkey.state & Mod1Mask) {
290 strcat(buffer, "Mod1+");
292 if (ev.xkey.state & Mod2Mask) {
293 strcat(buffer, "Mod2+");
295 if (ev.xkey.state & Mod3Mask) {
296 strcat(buffer, "Mod3+");
298 if (ev.xkey.state & Mod4Mask) {
299 strcat(buffer, "Mod4+");
301 if (ev.xkey.state & Mod5Mask) {
302 strcat(buffer, "Mod5+");
304 strcat(buffer, key);
306 return wstrdup(buffer);
311 static void
312 sgrabClicked(WMWidget *w, void *data)
314 _Panel *panel = (_Panel*)data;
315 Display *dpy = WMScreenDisplay(WMWidgetScreen(panel->parent));
316 char *shortcut;
319 if (w == panel->sclearB) {
320 WMSetTextFieldText(panel->shortT, "");
321 updateMenuItem(panel, panel->currentItem, panel->shortT);
322 return;
325 if (!panel->capturing) {
326 panel->capturing = 1;
327 WMSetButtonText(w, _("Cancel"));
328 XGrabKeyboard(dpy, WMWidgetXID(panel->parent), True, GrabModeAsync,
329 GrabModeAsync, CurrentTime);
330 shortcut = captureShortcut(dpy, panel);
331 if (shortcut) {
332 WMSetTextFieldText(panel->shortT, shortcut);
333 updateMenuItem(panel, panel->currentItem, panel->shortT);
334 wfree(shortcut);
337 panel->capturing = 0;
338 WMSetButtonText(w, _("Capture"));
339 XUngrabKeyboard(dpy, CurrentTime);
343 static void
344 changedItemPad(WMWidget *w, void *data)
346 _Panel *panel = (_Panel*)data;
347 int padn = WMGetPopUpButtonSelectedItem(w);
349 WMUnmapWidget(panel->itemPad[panel->currentPad]);
350 WMMapWidget(panel->itemPad[padn]);
352 panel->currentPad = padn;
356 static WEditMenu*
357 putNewSubmenu(WEditMenu *menu, char *title)
359 WEditMenu *tmp;
360 WEditMenuItem *item;
362 item = WAddMenuItemWithTitle(menu, title);
364 tmp = WCreateEditMenu(WMWidgetScreen(menu), title);
365 WSetEditMenuAcceptsDrop(tmp, True);
366 WSetEditMenuDelegate(tmp, &menuDelegate);
367 WSetEditMenuSubmenu(menu, item, tmp);
369 return tmp;
373 static ItemData*
374 putNewItem(_Panel *panel, WEditMenu *menu, int type, char *title)
376 WEditMenuItem *item;
377 ItemData *data;
379 item = WAddMenuItemWithTitle(menu, title);
381 data = NEW(ItemData);
382 data->type = type;
383 WSetEditMenuItemData(item, data, (WMCallback*)freeItemData);
384 WSetEditMenuItemImage(item, panel->markerPix[type]);
386 return data;
390 static WEditMenu*
391 makeFactoryMenu(WMWidget *parent, int width)
393 WEditMenu *pad;
395 pad = WCreateEditMenuPad(parent);
396 WMResizeWidget(pad, width, 10);
397 WSetEditMenuMinSize(pad, wmksize(width, 0));
398 WSetEditMenuMaxSize(pad, wmksize(width, 0));
399 WSetEditMenuSelectable(pad, False);
400 WSetEditMenuEditable(pad, False);
401 WSetEditMenuIsFactory(pad, True);
402 WSetEditMenuDelegate(pad, &menuDelegate);
404 return pad;
408 static void
409 createPanel(_Panel *p)
411 _Panel *panel = (_Panel*)p;
412 WMScreen *scr = WMWidgetScreen(panel->parent);
413 WMColor *black = WMBlackColor(scr);
414 WMColor *white = WMWhiteColor(scr);
415 WMColor *gray = WMGrayColor(scr);
416 WMFont *bold = WMBoldSystemFontOfSize(scr, 12);
417 WMFont *font = WMSystemFontOfSize(scr, 12);
418 WMLabel *label;
419 int width;
422 menuDelegate.data = panel;
425 panel->boldFont = bold;
426 panel->normalFont = font;
428 panel->black = black;
429 panel->white = white;
430 panel->gray = gray;
433 Pixmap pix;
434 Display *dpy = WMScreenDisplay(scr);
435 GC gc;
436 WMPixmap *pixm;
438 pixm = WMCreatePixmap(scr, 7, 7, WMScreenDepth(scr), True);
440 pix = WMGetPixmapXID(pixm);
442 XDrawLine(dpy, pix, WMColorGC(black), 0, 3, 6, 3);
443 XDrawLine(dpy, pix, WMColorGC(black), 3, 0, 3, 6);
445 XDrawLine(dpy, pix, WMColorGC(black), 1, 0, 3, 3);
446 XDrawLine(dpy, pix, WMColorGC(black), 1, 6, 3, 3);
447 XDrawLine(dpy, pix, WMColorGC(black), 0, 0, 0, 6);
450 pix = WMGetPixmapMaskXID(pixm);
452 gc = XCreateGC(dpy, pix, 0, NULL);
454 XSetForeground(dpy, gc, 0);
455 XFillRectangle(dpy, pix, gc, 0, 0, 7, 7);
457 XSetForeground(dpy, gc, 1);
458 XDrawLine(dpy, pix, gc, 0, 3, 6, 3);
459 XDrawLine(dpy, pix, gc, 3, 0, 3, 6);
461 panel->markerPix[ExternalInfo] = pixm;
462 panel->markerPix[PipeInfo] = pixm;
463 panel->markerPix[DirectoryInfo] = pixm;
464 panel->markerPix[WSMenuInfo] = pixm;
465 panel->markerPix[WWindowListInfo] = pixm;
467 XFreeGC(dpy, gc);
470 panel->box = WMCreateBox(panel->parent);
471 WMSetViewExpandsToParent(WMWidgetView(panel->box), 2, 2, 2, 2);
473 panel->typeP = WMCreatePopUpButton(panel->box);
474 WMResizeWidget(panel->typeP, 150, 20);
475 WMMoveWidget(panel->typeP, 10, 10);
477 WMAddPopUpButtonItem(panel->typeP, _("New Items"));
478 WMAddPopUpButtonItem(panel->typeP, _("Sample Commands"));
479 WMAddPopUpButtonItem(panel->typeP, _("Sample Submenus"));
481 WMSetPopUpButtonAction(panel->typeP, changedItemPad, panel);
483 WMSetPopUpButtonSelectedItem(panel->typeP, 0);
486 WEditMenu *pad;
487 WEditMenu *smenu;
488 ItemData *data;
490 pad = makeFactoryMenu(panel->box, 150);
491 WMMoveWidget(pad, 10, 40);
493 data = putNewItem(panel, pad, ExecInfo, _("Run Program"));
494 data = putNewItem(panel, pad, CommandInfo, _("Internal Command"));
495 smenu = putNewSubmenu(pad, _("Submenu"));
496 data = putNewItem(panel, pad, ExternalInfo, _("External Submenu"));
497 data = putNewItem(panel, pad, PipeInfo, _("Generated Submenu"));
498 data = putNewItem(panel, pad, DirectoryInfo, _("Directory Contents"));
499 data = putNewItem(panel, pad, WSMenuInfo, _("Workspace Menu"));
500 data = putNewItem(panel, pad, WWindowListInfo, _("Window List Menu"));
502 panel->itemPad[0] = pad;
506 WEditMenu *pad;
507 ItemData *data;
508 WMScrollView *sview;
510 sview = WMCreateScrollView(panel->box);
511 WMResizeWidget(sview, 150, 180);
512 WMMoveWidget(sview, 10, 40);
513 WMSetScrollViewHasVerticalScroller(sview, True);
515 pad = makeFactoryMenu(panel->box, 130);
517 WMSetScrollViewContentView(sview, WMWidgetView(pad));
519 data = putNewItem(panel, pad, ExecInfo, _("XTerm"));
520 data->param.exec.command = "xterm -sb -sl 2000 -bg black -fg white";
522 data = putNewItem(panel, pad, ExecInfo, _("rxvt"));
523 data->param.exec.command = "rxvt";
525 data = putNewItem(panel, pad, ExecInfo, _("ETerm"));
526 data->param.exec.command = "eterm";
528 data = putNewItem(panel, pad, ExecInfo, _("Run..."));
529 data->param.exec.command = _("%a(Run,Type command to run)");
531 data = putNewItem(panel, pad, ExecInfo, _("Netscape"));
532 data->param.exec.command = "netscape";
534 data = putNewItem(panel, pad, ExecInfo, _("gimp"));
535 data->param.exec.command = "gimp";
537 data = putNewItem(panel, pad, ExecInfo, _("epic"));
538 data->param.exec.command = "xterm -e epic";
540 data = putNewItem(panel, pad, ExecInfo, _("ee"));
541 data->param.exec.command = "ee";
543 data = putNewItem(panel, pad, ExecInfo, _("xv"));
544 data->param.exec.command = "xv";
546 data = putNewItem(panel, pad, ExecInfo, _("Acrobat Reader"));
547 data->param.exec.command = "acroread || /usr/local/Acrobat4/bin/acroread";
549 data = putNewItem(panel, pad, ExecInfo, _("ghostview"));
550 data->param.exec.command = "gv";
552 data = putNewItem(panel, pad, CommandInfo, _("Exit Window Maker"));
553 data->param.command.command = 3;
555 WMMapWidget(pad);
557 panel->itemPad[1] = sview;
562 WEditMenu *pad, *smenu;
563 ItemData *data;
564 WMScrollView *sview;
566 sview = WMCreateScrollView(panel->box);
567 WMResizeWidget(sview, 150, 180);
568 WMMoveWidget(sview, 10, 40);
569 WMSetScrollViewHasVerticalScroller(sview, True);
571 pad = makeFactoryMenu(panel->box, 130);
573 WMSetScrollViewContentView(sview, WMWidgetView(pad));
575 data = putNewItem(panel, pad, ExternalInfo, _("Debian Menu"));
576 data->param.pipe.command = "/etc/X11/WindowMaker/menu.hook";
578 data = putNewItem(panel, pad, PipeInfo, _("RedHat Menu"));
579 data->param.pipe.command = "wmconfig --output wmaker";
581 data = putNewItem(panel, pad, PipeInfo, _("Menu Conectiva"));
582 data->param.pipe.command = "wmconfig --output wmaker";
584 data = putNewItem(panel, pad, DirectoryInfo, _("Themes"));
585 data->param.directory.command = "setstyle";
586 data->param.directory.directory = "/usr/share/WindowMaker/Themes /usr/local/share/WindowMaker/Themes $HOME/GNUstep/Library/WindowMaker/Themes";
587 data->param.directory.stripExt = 1;
589 data = putNewItem(panel, pad, DirectoryInfo, _("Bg Images (scale)"));
590 data->param.directory.command = "wmsetbg -u -s";
591 data->param.directory.directory = "/opt/kde2/share/wallpapers /usr/share/WindowMaker/Backgrounds $HOME/GNUstep/Library/WindowMaker/Backgrounds";
592 data->param.directory.stripExt = 1;
594 data = putNewItem(panel, pad, DirectoryInfo, _("Bg Images (tile)"));
595 data->param.directory.command = "wmsetbg -u -t";
596 data->param.directory.directory = "/opt/kde2/share/wallpapers /usr/share/WindowMaker/Backgrounds $HOME/GNUstep/Library/WindowMaker/Backgrounds";
597 data->param.directory.stripExt = 1;
599 smenu = putNewSubmenu(pad, _("Assorted XTerms"));
601 data = putNewItem(panel, smenu, ExecInfo, _("XTerm Yellow on Blue"));
602 data->param.exec.command = "xterm -sb -sl 2000 -bg midnightblue -fg yellow";
604 data = putNewItem(panel, smenu, ExecInfo, _("XTerm White on Black"));
605 data->param.exec.command = "xterm -sb -sl 2000 -bg black -fg white";
607 data = putNewItem(panel, smenu, ExecInfo, _("XTerm Black on White"));
608 data->param.exec.command = "xterm -sb -sl 2000 -bg white -fg black";
610 data = putNewItem(panel, smenu, ExecInfo, _("XTerm Black on Beige"));
611 data->param.exec.command = "xterm -sb -sl 2000 -bg '#bbbb99' -fg black";
613 data = putNewItem(panel, smenu, ExecInfo, _("XTerm White on Green"));
614 data->param.exec.command = "xterm -sb -sl 2000 -bg '#228822' -fg white";
616 data = putNewItem(panel, smenu, ExecInfo, _("XTerm White on Olive"));
617 data->param.exec.command = "xterm -sb -sl 2000 -bg '#335533' -fg white";
619 data = putNewItem(panel, smenu, ExecInfo, _("XTerm Blue on Blue"));
620 data->param.exec.command = "xterm -sb -sl 2000 -bg '#112244' -fg '#88aabb'";
622 data = putNewItem(panel, smenu, ExecInfo, _("XTerm BIG FONTS"));
623 data->param.exec.command = "xterm -sb -sl 2000 -bg black -fg white -fn 10x20";
625 WMMapWidget(pad);
627 panel->itemPad[2] = sview;
631 width = FRAME_WIDTH - 20 - 150 - 10 - 2;
633 panel->optionsF = WMCreateFrame(panel->box);
634 WMResizeWidget(panel->optionsF, width, FRAME_HEIGHT - 15);
635 WMMoveWidget(panel->optionsF, 10 + 150 + 10, 5);
637 width -= 20;
639 /* command */
641 panel->commandF = WMCreateFrame(panel->optionsF);
642 WMResizeWidget(panel->commandF, width, 50);
643 WMMoveWidget(panel->commandF, 10, 20);
644 WMSetFrameTitle(panel->commandF, _("Program to Run"));
646 panel->commandT = WMCreateTextField(panel->commandF);
647 WMResizeWidget(panel->commandT, width - 20, 20);
648 WMMoveWidget(panel->commandT, 10, 20);
650 WMAddNotificationObserver(dataChanged, panel,
651 WMTextDidChangeNotification,
652 panel->commandT);
654 #if 0
655 panel->xtermC = WMCreateSwitchButton(panel->commandF);
656 WMResizeWidget(panel->xtermC, width - 20, 20);
657 WMMoveWidget(panel->xtermC, 10, 50);
658 WMSetButtonText(panel->xtermC, _("Run the program inside a Xterm"));
659 #endif
660 WMMapSubwidgets(panel->commandF);
663 /* path */
665 panel->pathF = WMCreateFrame(panel->optionsF);
666 WMResizeWidget(panel->pathF, width, 150);
667 WMMoveWidget(panel->pathF, 10, 40);
668 WMSetFrameTitle(panel->pathF, _("Path for Menu"));
670 panel->pathT = WMCreateTextField(panel->pathF);
671 WMResizeWidget(panel->pathT, width - 20, 20);
672 WMMoveWidget(panel->pathT, 10, 20);
674 WMAddNotificationObserver(dataChanged, panel,
675 WMTextDidChangeNotification,
676 panel->pathT);
678 label = WMCreateLabel(panel->pathF);
679 WMResizeWidget(label, width - 20, 80);
680 WMMoveWidget(label, 10, 50);
681 WMSetLabelText(label, _("Enter the path for a file containing a menu\n"
682 "or a list of directories with the programs you\n"
683 "want to have listed in the menu. Ex:\n"
684 "~/GNUstep/Library/WindowMaker/menu\n"
685 "or\n"
686 "/usr/X11R6/bin ~/xbin"));
688 WMMapSubwidgets(panel->pathF);
691 /* pipe */
693 panel->pipeF = WMCreateFrame(panel->optionsF);
694 WMResizeWidget(panel->pipeF, width, 100);
695 WMMoveWidget(panel->pipeF, 10, 50);
696 WMSetFrameTitle(panel->pipeF, _("Command"));
698 panel->pipeT = WMCreateTextField(panel->pipeF);
699 WMResizeWidget(panel->pipeT, width - 20, 20);
700 WMMoveWidget(panel->pipeT, 10, 20);
702 WMAddNotificationObserver(dataChanged, panel,
703 WMTextDidChangeNotification,
704 panel->pipeT);
707 label = WMCreateLabel(panel->pipeF);
708 WMResizeWidget(label, width - 20, 40);
709 WMMoveWidget(label, 10, 50);
710 WMSetLabelText(label, _("Enter a command that outputs a menu\n"
711 "definition to stdout when invoked."));
713 WMMapSubwidgets(panel->pipeF);
716 /* directory menu */
718 panel->dcommandF = WMCreateFrame(panel->optionsF);
719 WMResizeWidget(panel->dcommandF, width, 90);
720 WMMoveWidget(panel->dcommandF, 10, 25);
721 WMSetFrameTitle(panel->dcommandF, _("Command to Open Files"));
723 panel->dcommandT = WMCreateTextField(panel->dcommandF);
724 WMResizeWidget(panel->dcommandT, width - 20, 20);
725 WMMoveWidget(panel->dcommandT, 10, 20);
727 WMAddNotificationObserver(dataChanged, panel,
728 WMTextDidChangeNotification,
729 panel->dcommandT);
732 label = WMCreateLabel(panel->dcommandF);
733 WMResizeWidget(label, width - 20, 45);
734 WMMoveWidget(label, 10, 40);
735 WMSetLabelText(label, _("Enter the command you want to use to open the\n"
736 "files in the directories listed below."));
738 WMMapSubwidgets(panel->dcommandF);
741 panel->dpathF = WMCreateFrame(panel->optionsF);
742 WMResizeWidget(panel->dpathF, width, 80);
743 WMMoveWidget(panel->dpathF, 10, 125);
744 WMSetFrameTitle(panel->dpathF, _("Directories with Files"));
746 panel->dpathT = WMCreateTextField(panel->dpathF);
747 WMResizeWidget(panel->dpathT, width - 20, 20);
748 WMMoveWidget(panel->dpathT, 10, 20);
750 WMAddNotificationObserver(dataChanged, panel,
751 WMTextDidChangeNotification,
752 panel->dpathT);
754 panel->dstripB = WMCreateSwitchButton(panel->dpathF);
755 WMResizeWidget(panel->dstripB, width - 20, 20);
756 WMMoveWidget(panel->dstripB, 10, 50);
757 WMSetButtonText(panel->dstripB, _("Strip extensions from file names"));
759 WMSetButtonAction(panel->dstripB, buttonClicked, panel);
761 WMMapSubwidgets(panel->dpathF);
764 /* shortcut */
766 panel->shortF = WMCreateFrame(panel->optionsF);
767 WMResizeWidget(panel->shortF, width, 50);
768 WMMoveWidget(panel->shortF, 10, 160);
769 WMSetFrameTitle(panel->shortF, _("Keyboard Shortcut"));
771 panel->shortT = WMCreateTextField(panel->shortF);
772 WMResizeWidget(panel->shortT, width - 20 - 170, 20);
773 WMMoveWidget(panel->shortT, 10, 20);
775 WMAddNotificationObserver(dataChanged, panel,
776 WMTextDidChangeNotification,
777 panel->shortT);
779 panel->sgrabB = WMCreateCommandButton(panel->shortF);
780 WMResizeWidget(panel->sgrabB, 80, 24);
781 WMMoveWidget(panel->sgrabB, width - 90, 18);
782 WMSetButtonText(panel->sgrabB, _("Capture"));
783 WMSetButtonAction(panel->sgrabB, sgrabClicked, panel);
785 panel->sclearB = WMCreateCommandButton(panel->shortF);
786 WMResizeWidget(panel->sclearB, 80, 24);
787 WMMoveWidget(panel->sclearB, width - 175, 18);
788 WMSetButtonText(panel->sclearB, _("Clear"));
789 WMSetButtonAction(panel->sclearB, sgrabClicked, panel);
791 WMMapSubwidgets(panel->shortF);
793 /* internal command */
795 panel->icommandL = WMCreateList(panel->optionsF);
796 WMResizeWidget(panel->icommandL, width, 80);
797 WMMoveWidget(panel->icommandL, 10, 20);
799 WMSetListAction(panel->icommandL, icommandLClicked, panel);
801 WMAddNotificationObserver(dataChanged, panel,
802 WMListSelectionDidChangeNotification,
803 panel->icommandL);
805 WMInsertListItem(panel->icommandL, 0, _("Arrange Icons"));
806 WMInsertListItem(panel->icommandL, 1, _("Hide All Windows Except For The Focused One"));
807 WMInsertListItem(panel->icommandL, 2, _("Show All Windows"));
809 WMInsertListItem(panel->icommandL, 3, _("Exit Window Maker"));
810 WMInsertListItem(panel->icommandL, 4, _("Exit X Session"));
811 WMInsertListItem(panel->icommandL, 5, _("Restart Window Maker"));
812 WMInsertListItem(panel->icommandL, 6, _("Start Another Window Manager : ("));
814 WMInsertListItem(panel->icommandL, 7, _("Save Current Session"));
815 WMInsertListItem(panel->icommandL, 8, _("Clear Saved Session"));
816 WMInsertListItem(panel->icommandL, 9, _("Refresh Screen"));
817 WMInsertListItem(panel->icommandL, 10, _("Open Info Panel"));
818 WMInsertListItem(panel->icommandL, 11, _("Open Copyright Panel"));
821 panel->paramF = WMCreateFrame(panel->optionsF);
822 WMResizeWidget(panel->paramF, width, 50);
823 WMMoveWidget(panel->paramF, 10, 105);
824 WMSetFrameTitle(panel->paramF, _("Window Manager to Start"));
826 panel->paramT = WMCreateTextField(panel->paramF);
827 WMResizeWidget(panel->paramT, width - 20, 20);
828 WMMoveWidget(panel->paramT, 10, 20);
830 WMAddNotificationObserver(dataChanged, panel,
831 WMTextDidChangeNotification,
832 panel->paramT);
834 WMMapSubwidgets(panel->paramF);
837 panel->quickB = WMCreateSwitchButton(panel->optionsF);
838 WMResizeWidget(panel->quickB, width, 20);
839 WMMoveWidget(panel->quickB, 10, 120);
840 WMSetButtonText(panel->quickB, _("Do not confirm action."));
841 WMSetButtonAction(panel->quickB, buttonClicked, panel);
846 label = WMCreateLabel(panel->optionsF);
847 WMResizeWidget(label, width - 10, FRAME_HEIGHT - 50);
848 WMMoveWidget(label, 10, 20);
849 WMSetLabelText(label,
850 _("Instructions:\n\n"
851 " - drag items from the left to the menu to add new items\n"
852 " - drag items out of the menu to remove items\n"
853 " - drag items in menu to change their position\n"
854 " - drag items with Control pressed to copy them\n"
855 " - double click in a menu item to change the label\n"
856 " - click on a menu item to change related information"));
857 WMMapWidget(label);
859 WMRealizeWidget(panel->box);
860 WMMapSubwidgets(panel->box);
861 WMMapWidget(panel->box);
865 int i;
866 for (i = 0; i < 3; i++)
867 WMUnmapWidget(panel->itemPad[i]);
869 changedItemPad(panel->typeP, panel);
871 panel->sections[NoInfo][0] = label;
873 panel->sections[ExecInfo][0] = panel->commandF;
874 panel->sections[ExecInfo][1] = panel->shortF;
876 panel->sections[CommandInfo][0] = panel->icommandL;
877 panel->sections[CommandInfo][1] = panel->shortF;
879 panel->sections[ExternalInfo][0] = panel->pathF;
881 panel->sections[PipeInfo][0] = panel->pipeF;
883 panel->sections[DirectoryInfo][0] = panel->dpathF;
884 panel->sections[DirectoryInfo][1] = panel->dcommandF;
886 panel->currentType = NoInfo;
888 showData(panel);
891 WMPoint pos;
893 pos = WMGetViewScreenPosition(WMWidgetView(panel->box));
895 if (pos.x < 200) {
896 pos.x += FRAME_WIDTH + 20;
897 } else {
898 pos.x = 10;
901 pos.y = WMAX(pos.y - 100, 0);
903 if( panel->menu ) WEditMenuShowAt(panel->menu, pos.x, pos.y);
910 static void
911 freeItemData(ItemData *data)
913 #define CFREE(d) if (d) wfree(d)
915 /* TODO */
916 switch (data->type) {
917 case CommandInfo:
918 CFREE(data->param.command.parameter);
919 CFREE(data->param.command.shortcut);
920 break;
922 case ExecInfo:
923 CFREE(data->param.exec.command);
924 CFREE(data->param.exec.shortcut);
925 break;
927 case PipeInfo:
928 CFREE(data->param.pipe.command);
929 break;
931 case ExternalInfo:
932 CFREE(data->param.external.path);
933 break;
935 case DirectoryInfo:
936 CFREE(data->param.directory.command);
937 CFREE(data->param.directory.directory);
938 break;
940 default:
941 break;
944 wfree(data);
945 #undef CFREE
949 static ItemData*
950 parseCommand(WMPropList *item)
952 ItemData *data = NEW(ItemData);
953 WMPropList *p;
954 char *command = NULL;
955 char *parameter = NULL;
956 char *shortcut = NULL;
957 int i = 1;
960 p = WMGetFromPLArray(item, i++);
961 command = WMGetFromPLString(p);
962 if (strcmp(command, "SHORTCUT") == 0) {
963 p = WMGetFromPLArray(item, i++);
964 shortcut = WMGetFromPLString(p);
965 p = WMGetFromPLArray(item, i++);
966 command = WMGetFromPLString(p);
968 p = WMGetFromPLArray(item, i++);
969 if (p)
970 parameter = WMGetFromPLString(p);
972 if (strcmp(command, "EXEC") == 0 || strcmp(command, "SHEXEC") == 0) {
974 data->type = ExecInfo;
976 data->param.exec.command = wstrdup(parameter);
977 if (shortcut)
978 data->param.exec.shortcut = wstrdup(shortcut);
980 } else if (strcmp(command, "OPEN_MENU") == 0) {
981 char *p;
983 * dir menu, menu file
984 * dir WITH
985 * |pipe (TODO: ||pipe)
987 p = parameter;
988 while (isspace(*p) && *p) p++;
989 if (*p == '|') {
990 data->type = PipeInfo;
991 data->param.pipe.command = wtrimspace(p+1);
992 } else {
993 char *s;
995 p = wstrdup(p);
997 s = strstr(p, "WITH");
998 if (s) {
999 char **tokens;
1000 char **ctokens;
1001 int tokn;
1002 int i, j;
1004 data->type = DirectoryInfo;
1006 *s = '\0';
1007 s += 5;
1008 while (*s && isspace(*s)) s++;
1009 data->param.directory.command = wstrdup(s);
1011 wtokensplit(p, &tokens, &tokn);
1012 wfree(p);
1014 ctokens = wmalloc(sizeof(char*)*tokn);
1016 for (i = 0, j = 0; i < tokn; i++) {
1017 if (strcmp(tokens[i], "-noext") == 0) {
1018 wfree(tokens[i]);
1019 data->param.directory.stripExt = 1;
1020 } else {
1021 ctokens[j++] = tokens[i];
1024 data->param.directory.directory = wtokenjoin(ctokens, j);
1025 wfree(ctokens);
1027 wtokenfree(tokens, tokn);
1028 } else {
1029 data->type = ExternalInfo;
1030 data->param.external.path = p;
1033 } else if (strcmp(command, "WORKSPACE_MENU") == 0) {
1034 data->type = WSMenuInfo;
1035 } else if (strcmp(command, "WINDOWS_MENU") == 0) {
1036 data->type = WWindowListInfo;
1037 } else {
1038 int cmd;
1040 if (strcmp(command, "ARRANGE_ICONS") == 0) {
1041 cmd = 0;
1042 } else if (strcmp(command, "HIDE_OTHERS") == 0) {
1043 cmd = 1;
1044 } else if (strcmp(command, "SHOW_ALL") == 0) {
1045 cmd = 2;
1046 } else if (strcmp(command, "EXIT") == 0) {
1047 cmd = 3;
1048 } else if (strcmp(command, "SHUTDOWN") == 0) {
1049 cmd = 4;
1050 } else if (strcmp(command, "RESTART") == 0) {
1051 if (parameter) {
1052 cmd = 6;
1053 } else {
1054 cmd = 5;
1056 } else if (strcmp(command, "SAVE_SESSION") == 0) {
1057 cmd = 7;
1058 } else if (strcmp(command, "CLEAR_SESSION") == 0) {
1059 cmd = 8;
1060 } else if (strcmp(command, "REFRESH") == 0) {
1061 cmd = 9;
1062 } else if (strcmp(command, "INFO_PANEL") == 0) {
1063 cmd = 10;
1064 } else if (strcmp(command, "LEGAL_PANEL") == 0) {
1065 cmd = 11;
1066 } else {
1067 wwarning(_("unknown command '%s' in menu"), command);
1068 goto error;
1071 data->type = CommandInfo;
1073 data->param.command.command = cmd;
1074 if (shortcut)
1075 data->param.command.shortcut = wstrdup(shortcut);
1076 if (parameter)
1077 data->param.command.parameter = wstrdup(parameter);
1080 return data;
1082 error:
1083 wfree(data);
1085 return NULL;
1091 static void
1092 updateFrameTitle(_Panel *panel, char *title, InfoType type)
1094 if (type != NoInfo) {
1095 char *tmp;
1097 switch (type) {
1098 case ExecInfo:
1099 tmp = wstrconcat(title, _(": Execute Program"));
1100 break;
1102 case CommandInfo:
1103 tmp = wstrconcat(title, _(": Perform Internal Command"));
1104 break;
1106 case ExternalInfo:
1107 tmp = wstrconcat(title, _(": Open a Submenu"));
1108 break;
1110 case PipeInfo:
1111 tmp = wstrconcat(title, _(": Program Generated Submenu"));
1112 break;
1114 case DirectoryInfo:
1115 tmp = wstrconcat(title, _(": Directory Contents Menu"));
1116 break;
1118 case WSMenuInfo:
1119 tmp = wstrconcat(title, _(": Open Workspaces Submenu"));
1120 break;
1122 case WWindowListInfo:
1123 tmp = wstrconcat(title, _(": Open Window List Submenu"));
1124 break;
1126 default:
1127 tmp = NULL;
1128 break;
1130 WMSetFrameTitle(panel->optionsF, tmp);
1131 wfree(tmp);
1132 } else {
1133 WMSetFrameTitle(panel->optionsF, NULL);
1139 static void
1140 changeInfoType(_Panel *panel, char *title, InfoType type)
1142 WMWidget **w;
1144 if (panel->currentType != type) {
1146 w = panel->sections[panel->currentType];
1148 while (*w) {
1149 WMUnmapWidget(*w);
1150 w++;
1152 WMUnmapWidget(panel->paramF);
1153 WMUnmapWidget(panel->quickB);
1156 w = panel->sections[type];
1158 while (*w) {
1159 WMMapWidget(*w);
1160 w++;
1164 updateFrameTitle(panel, title, type);
1166 panel->currentType = type;
1172 static void
1173 updateMenuItem(_Panel *panel, WEditMenuItem *item, WMWidget *changedWidget)
1175 ItemData *data = WGetEditMenuItemData(item);
1177 assert(data != NULL);
1179 #define REPLACE(v, d) if (v) wfree(v); v = d
1181 switch (data->type) {
1182 case ExecInfo:
1183 if (changedWidget == panel->commandT) {
1184 REPLACE(data->param.exec.command,
1185 WMGetTextFieldText(panel->commandT));
1187 if (changedWidget == panel->shortT) {
1188 REPLACE(data->param.exec.shortcut,
1189 WMGetTextFieldText(panel->shortT));
1191 break;
1193 case CommandInfo:
1194 if (changedWidget == panel->icommandL) {
1195 data->param.command.command =
1196 WMGetListSelectedItemRow(panel->icommandL);
1198 switch (data->param.command.command) {
1199 case 3:
1200 case 4:
1201 if (changedWidget == panel->quickB) {
1202 REPLACE(data->param.command.parameter,
1203 WMGetButtonSelected(panel->quickB)
1204 ? wstrdup("QUICK") : NULL);
1206 break;
1208 case 6:
1209 if (changedWidget == panel->paramT) {
1210 REPLACE(data->param.command.parameter,
1211 WMGetTextFieldText(panel->paramT));
1213 break;
1215 if (changedWidget == panel->shortT) {
1216 REPLACE(data->param.command.shortcut,
1217 WMGetTextFieldText(panel->shortT));
1221 break;
1223 case PipeInfo:
1224 if (changedWidget == panel->pipeT) {
1225 REPLACE(data->param.pipe.command,
1226 WMGetTextFieldText(panel->pipeT));
1228 break;
1230 case ExternalInfo:
1231 if (changedWidget == panel->pathT) {
1232 REPLACE(data->param.external.path,
1233 WMGetTextFieldText(panel->pathT));
1235 break;
1237 case DirectoryInfo:
1238 if (changedWidget == panel->dpathT) {
1239 REPLACE(data->param.directory.directory,
1240 WMGetTextFieldText(panel->dpathT));
1242 if (changedWidget == panel->dcommandT) {
1243 REPLACE(data->param.directory.command,
1244 WMGetTextFieldText(panel->dcommandT));
1246 if (changedWidget == panel->dstripB) {
1247 data->param.directory.stripExt =
1248 WMGetButtonSelected(panel->dstripB);
1250 break;
1252 default:
1253 assert(0);
1254 break;
1257 #undef REPLACE
1262 static void
1263 menuItemCloned(WEditMenuDelegate *delegate, WEditMenu *menu,
1264 WEditMenuItem *origItem, WEditMenuItem *newItem)
1266 ItemData *data = WGetEditMenuItemData(origItem);
1267 ItemData *newData;
1269 if (!data)
1270 return;
1272 #define DUP(s) (s) ? wstrdup(s) : NULL
1274 newData = NEW(ItemData);
1276 newData->type = data->type;
1278 switch (data->type) {
1279 case ExecInfo:
1280 newData->param.exec.command = DUP(data->param.exec.command);
1281 newData->param.exec.shortcut = DUP(data->param.exec.shortcut);
1282 break;
1284 case CommandInfo:
1285 newData->param.command.command = data->param.command.command;
1286 newData->param.command.parameter = DUP(data->param.command.parameter);
1287 newData->param.command.shortcut = DUP(data->param.command.shortcut);
1288 break;
1290 case PipeInfo:
1291 newData->param.pipe.command = DUP(data->param.pipe.command);
1292 break;
1294 case ExternalInfo:
1295 newData->param.external.path = DUP(data->param.external.path);
1296 break;
1298 case DirectoryInfo:
1299 newData->param.directory.directory = DUP(data->param.directory.directory);
1300 newData->param.directory.command = DUP(data->param.directory.command);
1301 newData->param.directory.stripExt = data->param.directory.stripExt;
1302 break;
1304 default:
1305 break;
1308 #undef DUP
1310 WSetEditMenuItemData(newItem, newData, (WMCallback*)freeItemData);
1314 static void
1315 menuItemEdited(struct WEditMenuDelegate *delegate, WEditMenu *menu,
1316 WEditMenuItem *item)
1318 _Panel *panel = (_Panel*)delegate->data;
1319 WEditMenu *submenu;
1321 updateFrameTitle(panel, WGetEditMenuItemTitle(item), panel->currentType);
1323 submenu = WGetEditMenuSubmenu(menu, item);
1324 if (submenu) {
1325 WSetEditMenuTitle(submenu, WGetEditMenuItemTitle(item));
1330 static Bool
1331 shouldRemoveItem(struct WEditMenuDelegate *delegate, WEditMenu *menu,
1332 WEditMenuItem *item)
1334 _Panel *panel = (_Panel*)delegate->data;
1336 if (panel->dontAsk)
1337 return True;
1339 if (WGetEditMenuSubmenu(menu, item)) {
1340 int res;
1342 res = WMRunAlertPanel(WMWidgetScreen(menu), NULL,
1343 _("Remove Submenu"),
1344 _("Removing this item will destroy all items inside\n"
1345 "the submenu. Do you really want to do that?"),
1346 _("Yes"), _("No"),
1347 _("Yes, don't ask again."));
1348 switch (res) {
1349 case WAPRDefault:
1350 return True;
1351 case WAPRAlternate:
1352 return False;
1353 case WAPROther:
1354 panel->dontAsk = True;
1355 return True;
1358 return True;
1362 static void
1363 menuItemDeselected(WEditMenuDelegate *delegate, WEditMenu *menu,
1364 WEditMenuItem *item)
1366 _Panel *panel = (_Panel*)delegate->data;
1368 changeInfoType(panel, NULL, NoInfo);
1372 static void
1373 menuItemSelected(WEditMenuDelegate *delegate, WEditMenu *menu,
1374 WEditMenuItem *item)
1376 ItemData *data = WGetEditMenuItemData(item);
1377 _Panel *panel = (_Panel*)delegate->data;
1379 panel->currentItem = item;
1381 if (data) {
1382 changeInfoType(panel, WGetEditMenuItemTitle(item), data->type);
1384 switch (data->type) {
1385 case NoInfo:
1386 break;
1388 case ExecInfo:
1389 WMSetTextFieldText(panel->commandT, data->param.exec.command);
1390 WMSetTextFieldText(panel->shortT, data->param.exec.shortcut);
1391 break;
1393 case CommandInfo:
1394 WMSelectListItem(panel->icommandL,
1395 data->param.command.command);
1396 WMSetListPosition(panel->icommandL,
1397 data->param.command.command - 2);
1398 WMSetTextFieldText(panel->shortT, data->param.command.shortcut);
1400 switch (data->param.command.command) {
1401 case 3:
1402 case 4:
1403 WMSetButtonSelected(panel->quickB,
1404 data->param.command.parameter!=NULL);
1405 break;
1406 case 6:
1407 WMSetTextFieldText(panel->paramT,
1408 data->param.command.parameter);
1409 break;
1412 icommandLClicked(panel->icommandL, panel);
1413 break;
1415 case PipeInfo:
1416 WMSetTextFieldText(panel->pipeT, data->param.pipe.command);
1417 break;
1419 case ExternalInfo:
1420 WMSetTextFieldText(panel->pathT, data->param.external.path);
1421 break;
1423 case DirectoryInfo:
1424 WMSetTextFieldText(panel->dpathT, data->param.directory.directory);
1425 WMSetTextFieldText(panel->dcommandT, data->param.directory.command);
1426 WMSetButtonSelected(panel->dstripB, data->param.directory.stripExt);
1427 break;
1429 case WSMenuInfo:
1430 break;
1432 default:
1433 break;
1440 static WEditMenu*
1441 buildSubmenu(_Panel *panel, WMPropList *pl)
1443 WMScreen *scr = WMWidgetScreen(panel->parent);
1444 WEditMenu *menu;
1445 WEditMenuItem *item;
1446 char *title;
1447 WMPropList *tp, *bp;
1448 int i;
1450 tp = WMGetFromPLArray(pl, 0);
1451 title = WMGetFromPLString(tp);
1453 menu = WCreateEditMenu(scr, title);
1455 for (i = 1; i < WMGetPropListItemCount(pl); i++) {
1456 WMPropList *pi;
1458 pi = WMGetFromPLArray(pl, i);
1460 tp = WMGetFromPLArray(pi, 0);
1461 bp = WMGetFromPLArray(pi, 1);
1463 title = WMGetFromPLString(tp);
1465 if (!bp || WMIsPLArray(bp)) { /* it's a submenu */
1466 WEditMenu *submenu;
1468 submenu = buildSubmenu(panel, pi);
1470 item = WAddMenuItemWithTitle(menu, title);
1472 WSetEditMenuSubmenu(menu, item, submenu);
1473 } else {
1474 ItemData *data;
1476 item = WAddMenuItemWithTitle(menu, title);
1478 data = parseCommand(pi);
1480 if (panel->markerPix[data->type])
1481 WSetEditMenuItemImage(item, panel->markerPix[data->type]);
1482 WSetEditMenuItemData(item, data, (WMCallback*)freeItemData);
1486 WSetEditMenuAcceptsDrop(menu, True);
1487 WSetEditMenuDelegate(menu, &menuDelegate);
1489 WMRealizeWidget(menu);
1491 return menu;
1496 static void
1497 buildMenuFromPL(_Panel *panel, WMPropList *pl)
1499 panel->menu = buildSubmenu(panel, pl);
1504 static WMPropList*
1505 getDefaultMenu(_Panel *panel)
1507 WMPropList *menu, *pmenu;
1508 char *menuPath, *gspath;
1510 gspath = wusergnusteppath();
1512 menuPath = wmalloc(strlen(gspath)+128);
1513 /* if there is a localized plmenu for the tongue put it's filename here */
1514 sprintf(menuPath, _("%s/Library/WindowMaker/plmenu"), gspath);
1516 menu = WMReadPropListFromFile(menuPath);
1517 if (!menu) {
1518 wwarning("%s:could not read property list menu", menuPath);
1520 if (strcmp("%s/Library/WindowMaker/plmenu",
1521 _("%s/Library/WindowMaker/plmenu"))!=0) {
1523 sprintf(menuPath, "%s/Library/WindowMaker/plmenu", gspath);
1524 menu = WMReadPropListFromFile(menuPath);
1525 wwarning("%s:could not read property list menu", menuPath);
1527 if (!menu) {
1528 char buffer[512];
1530 sprintf(buffer, _("Could not open default menu from '%s'"),
1531 menuPath);
1532 WMRunAlertPanel(WMWidgetScreen(panel->parent), panel->parent,
1533 _("Error"), buffer, _("OK"), NULL, NULL);
1537 wfree(menuPath);
1539 if (menu) {
1540 pmenu = menu;
1541 } else {
1542 pmenu = NULL;
1545 return pmenu;
1549 static void
1550 showData(_Panel *panel)
1552 char *gspath;
1553 char *menuPath;
1554 WMPropList *pmenu;
1556 gspath = wusergnusteppath();
1558 menuPath = wmalloc(strlen(gspath)+32);
1559 strcpy(menuPath, gspath);
1560 strcat(menuPath, "/Defaults/WMRootMenu");
1562 pmenu = WMReadPropListFromFile(menuPath);
1564 if (!pmenu || !WMIsPLArray(pmenu)) {
1565 int res;
1567 res = WMRunAlertPanel(WMWidgetScreen(panel->parent), panel->parent,
1568 _("Warning"),
1569 _("The menu file format currently in use is not supported\n"
1570 "by this tool. Do you want to discard the current menu\n"
1571 "to use this tool?"),
1572 _("Yes, Discard and Update"),
1573 _("No, Keep Current Menu"), NULL);
1575 if (res == WAPRDefault) {
1576 pmenu = getDefaultMenu(panel);
1578 if (!pmenu) {
1579 pmenu = WMCreatePLArray(WMCreatePLString("Applications"),
1580 NULL);
1582 } else {
1583 panel->dontSave = True;
1584 return;
1588 panel->menuPath = menuPath;
1590 buildMenuFromPL(panel, pmenu);
1592 WMReleasePropList(pmenu);
1596 static Bool
1597 notblank(char *s)
1599 if (s) {
1600 while (*s++) {
1601 if (!isspace(*s))
1602 return True;
1605 return False;
1609 static WMPropList*
1610 processData(char *title, ItemData *data)
1612 WMPropList *item;
1613 char *s1;
1614 static WMPropList *pscut = NULL;
1615 static WMPropList *pomenu = NULL;
1616 int i;
1618 if (!pscut) {
1619 pscut = WMCreatePLString("SHORTCUT");
1620 pomenu = WMCreatePLString("OPEN_MENU");
1623 item = WMCreatePLArray(WMCreatePLString(title), NULL);
1626 switch (data->type) {
1627 case ExecInfo:
1628 if (data->param.exec.command == NULL)
1629 return NULL;
1630 #if 1
1631 if (strpbrk(data->param.exec.command, "&$*|><?`=;")) {
1632 s1 = "SHEXEC";
1633 } else {
1634 s1 = "EXEC";
1636 #else
1637 s1 = "SHEXEC";
1638 #endif
1640 if (notblank(data->param.exec.shortcut)) {
1641 WMAddToPLArray(item, pscut);
1642 WMAddToPLArray(item,
1643 WMCreatePLString(data->param.exec.shortcut));
1646 WMAddToPLArray(item, WMCreatePLString(s1));
1647 WMAddToPLArray(item, WMCreatePLString(data->param.exec.command));
1648 break;
1650 case CommandInfo:
1651 if (notblank(data->param.command.shortcut)) {
1652 WMAddToPLArray(item, pscut);
1653 WMAddToPLArray(item,
1654 WMCreatePLString(data->param.command.shortcut));
1657 i = data->param.command.command;
1659 WMAddToPLArray(item, WMCreatePLString(commandNames[i]));
1661 switch (i) {
1662 case 3:
1663 case 4:
1664 if (data->param.command.parameter) {
1665 WMAddToPLArray(item,
1666 WMCreatePLString(data->param.command.parameter));
1668 break;
1670 case 6: /* restart */
1671 if (data->param.command.parameter) {
1672 WMAddToPLArray(item,
1673 WMCreatePLString(data->param.command.parameter));
1675 break;
1678 break;
1680 case PipeInfo:
1681 if (!data->param.pipe.command)
1682 return NULL;
1683 WMAddToPLArray(item, pomenu);
1684 s1 = wstrconcat("| ", data->param.pipe.command);
1685 WMAddToPLArray(item, WMCreatePLString(s1));
1686 wfree(s1);
1687 break;
1689 case ExternalInfo:
1690 if (!data->param.external.path)
1691 return NULL;
1692 WMAddToPLArray(item, pomenu);
1693 WMAddToPLArray(item, WMCreatePLString(data->param.external.path));
1694 break;
1696 case DirectoryInfo:
1697 if (!data->param.directory.directory
1698 || !data->param.directory.command)
1699 return NULL;
1701 int l;
1702 char *tmp;
1704 l = strlen(data->param.directory.directory);
1705 l += strlen(data->param.directory.command);
1706 l += 32;
1708 WMAddToPLArray(item, pomenu);
1710 tmp = wmalloc(l);
1711 sprintf(tmp, "%s%s WITH %s",
1712 data->param.directory.stripExt ? "-noext " : "",
1713 data->param.directory.directory,
1714 data->param.directory.command);
1716 WMAddToPLArray(item, WMCreatePLString(tmp));
1717 wfree(tmp);
1719 break;
1721 case WSMenuInfo:
1722 WMAddToPLArray(item, WMCreatePLString("WORKSPACE_MENU"));
1723 break;
1725 case WWindowListInfo:
1726 WMAddToPLArray(item, WMCreatePLString("WINDOWS_MENU"));
1727 break;
1729 default:
1730 assert(0);
1731 break;
1734 return item;
1738 static WMPropList*
1739 processSubmenu(WEditMenu *menu)
1741 WEditMenuItem *item;
1742 WMPropList *pmenu;
1743 WMPropList *pl;
1744 char *s;
1745 int i;
1748 s = WGetEditMenuTitle(menu);
1749 pl = WMCreatePLString(s);
1751 pmenu = WMCreatePLArray(pl, NULL);
1753 i = 0;
1754 while ((item = WGetEditMenuItem(menu, i++))) {
1755 WEditMenu *submenu;
1757 s = WGetEditMenuItemTitle(item);
1759 submenu = WGetEditMenuSubmenu(menu, item);
1760 if (submenu) {
1761 pl = processSubmenu(submenu);
1762 } else {
1763 pl = processData(s, WGetEditMenuItemData(item));
1766 if (!pl)
1767 continue;
1769 WMAddToPLArray(pmenu, pl);
1772 return pmenu;
1777 static WMPropList*
1778 buildPLFromMenu(_Panel *panel)
1780 WMPropList *menu;
1782 menu = processSubmenu(panel->menu);
1784 return menu;
1790 static void
1791 storeData(_Panel *panel)
1793 WMPropList *menu;
1795 if (panel->dontSave)
1796 return;
1798 menu = buildPLFromMenu(panel);
1800 WMWritePropListToFile(menu, panel->menuPath, True);
1802 WMReleasePropList(menu);
1807 static void
1808 showMenus(_Panel *panel)
1810 if( panel->menu ) WEditMenuUnhide(panel->menu);
1814 static void
1815 hideMenus(_Panel *panel)
1817 if( panel->menu ) WEditMenuHide(panel->menu);
1823 Panel*
1824 InitMenu(WMScreen *scr, WMWidget *parent)
1826 _Panel *panel;
1828 panel = wmalloc(sizeof(_Panel));
1829 memset(panel, 0, sizeof(_Panel));
1831 panel->sectionName = _("Applications Menu Definition");
1833 panel->description = _("Edit the menu for launching applications.");
1835 panel->parent = parent;
1837 panel->callbacks.createWidgets = createPanel;
1838 panel->callbacks.updateDomain = storeData;
1839 panel->callbacks.showPanel = showMenus;
1840 panel->callbacks.hidePanel = hideMenus;
1843 AddSection(panel, ICON_FILE);
1845 return panel;