- Changelog update about latest fixes.
[wmaker-crm.git] / WPrefs.app / Menu.c
blob8fa1741d1da627c55709e949ace9a794cf395ac9
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)
904 WEditMenuShowAt(panel->menu, pos.x, pos.y);
911 static void
912 freeItemData(ItemData *data)
914 #define CFREE(d) if (d) wfree(d)
916 /* TODO */
917 switch (data->type) {
918 case CommandInfo:
919 CFREE(data->param.command.parameter);
920 CFREE(data->param.command.shortcut);
921 break;
923 case ExecInfo:
924 CFREE(data->param.exec.command);
925 CFREE(data->param.exec.shortcut);
926 break;
928 case PipeInfo:
929 CFREE(data->param.pipe.command);
930 break;
932 case ExternalInfo:
933 CFREE(data->param.external.path);
934 break;
936 case DirectoryInfo:
937 CFREE(data->param.directory.command);
938 CFREE(data->param.directory.directory);
939 break;
941 default:
942 break;
945 wfree(data);
946 #undef CFREE
950 static ItemData*
951 parseCommand(WMPropList *item)
953 ItemData *data = NEW(ItemData);
954 WMPropList *p;
955 char *command = NULL;
956 char *parameter = NULL;
957 char *shortcut = NULL;
958 int i = 1;
961 p = WMGetFromPLArray(item, i++);
962 command = WMGetFromPLString(p);
963 if (strcmp(command, "SHORTCUT") == 0) {
964 p = WMGetFromPLArray(item, i++);
965 shortcut = WMGetFromPLString(p);
966 p = WMGetFromPLArray(item, i++);
967 command = WMGetFromPLString(p);
969 p = WMGetFromPLArray(item, i++);
970 if (p)
971 parameter = WMGetFromPLString(p);
973 if (strcmp(command, "EXEC") == 0 || strcmp(command, "SHEXEC") == 0) {
975 data->type = ExecInfo;
977 data->param.exec.command = wstrdup(parameter);
978 if (shortcut)
979 data->param.exec.shortcut = wstrdup(shortcut);
981 } else if (strcmp(command, "OPEN_MENU") == 0) {
982 char *p;
984 * dir menu, menu file
985 * dir WITH
986 * |pipe (TODO: ||pipe)
988 p = parameter;
989 while (isspace(*p) && *p) p++;
990 if (*p == '|') {
991 data->type = PipeInfo;
992 data->param.pipe.command = wtrimspace(p+1);
993 } else {
994 char *s;
996 p = wstrdup(p);
998 s = strstr(p, "WITH");
999 if (s) {
1000 char **tokens;
1001 char **ctokens;
1002 int tokn;
1003 int i, j;
1005 data->type = DirectoryInfo;
1007 *s = '\0';
1008 s += 5;
1009 while (*s && isspace(*s)) s++;
1010 data->param.directory.command = wstrdup(s);
1012 wtokensplit(p, &tokens, &tokn);
1013 wfree(p);
1015 ctokens = wmalloc(sizeof(char*)*tokn);
1017 for (i = 0, j = 0; i < tokn; i++) {
1018 if (strcmp(tokens[i], "-noext") == 0) {
1019 wfree(tokens[i]);
1020 data->param.directory.stripExt = 1;
1021 } else {
1022 ctokens[j++] = tokens[i];
1025 data->param.directory.directory = wtokenjoin(ctokens, j);
1026 wfree(ctokens);
1028 wtokenfree(tokens, tokn);
1029 } else {
1030 data->type = ExternalInfo;
1031 data->param.external.path = p;
1034 } else if (strcmp(command, "WORKSPACE_MENU") == 0) {
1035 data->type = WSMenuInfo;
1036 } else if (strcmp(command, "WINDOWS_MENU") == 0) {
1037 data->type = WWindowListInfo;
1038 } else {
1039 int cmd;
1041 if (strcmp(command, "ARRANGE_ICONS") == 0) {
1042 cmd = 0;
1043 } else if (strcmp(command, "HIDE_OTHERS") == 0) {
1044 cmd = 1;
1045 } else if (strcmp(command, "SHOW_ALL") == 0) {
1046 cmd = 2;
1047 } else if (strcmp(command, "EXIT") == 0) {
1048 cmd = 3;
1049 } else if (strcmp(command, "SHUTDOWN") == 0) {
1050 cmd = 4;
1051 } else if (strcmp(command, "RESTART") == 0) {
1052 if (parameter) {
1053 cmd = 6;
1054 } else {
1055 cmd = 5;
1057 } else if (strcmp(command, "SAVE_SESSION") == 0) {
1058 cmd = 7;
1059 } else if (strcmp(command, "CLEAR_SESSION") == 0) {
1060 cmd = 8;
1061 } else if (strcmp(command, "REFRESH") == 0) {
1062 cmd = 9;
1063 } else if (strcmp(command, "INFO_PANEL") == 0) {
1064 cmd = 10;
1065 } else if (strcmp(command, "LEGAL_PANEL") == 0) {
1066 cmd = 11;
1067 } else {
1068 wwarning(_("unknown command '%s' in menu"), command);
1069 goto error;
1072 data->type = CommandInfo;
1074 data->param.command.command = cmd;
1075 if (shortcut)
1076 data->param.command.shortcut = wstrdup(shortcut);
1077 if (parameter)
1078 data->param.command.parameter = wstrdup(parameter);
1081 return data;
1083 error:
1084 wfree(data);
1086 return NULL;
1092 static void
1093 updateFrameTitle(_Panel *panel, char *title, InfoType type)
1095 if (type != NoInfo) {
1096 char *tmp;
1098 switch (type) {
1099 case ExecInfo:
1100 tmp = wstrconcat(title, _(": Execute Program"));
1101 break;
1103 case CommandInfo:
1104 tmp = wstrconcat(title, _(": Perform Internal Command"));
1105 break;
1107 case ExternalInfo:
1108 tmp = wstrconcat(title, _(": Open a Submenu"));
1109 break;
1111 case PipeInfo:
1112 tmp = wstrconcat(title, _(": Program Generated Submenu"));
1113 break;
1115 case DirectoryInfo:
1116 tmp = wstrconcat(title, _(": Directory Contents Menu"));
1117 break;
1119 case WSMenuInfo:
1120 tmp = wstrconcat(title, _(": Open Workspaces Submenu"));
1121 break;
1123 case WWindowListInfo:
1124 tmp = wstrconcat(title, _(": Open Window List Submenu"));
1125 break;
1127 default:
1128 tmp = NULL;
1129 break;
1131 WMSetFrameTitle(panel->optionsF, tmp);
1132 wfree(tmp);
1133 } else {
1134 WMSetFrameTitle(panel->optionsF, NULL);
1140 static void
1141 changeInfoType(_Panel *panel, char *title, InfoType type)
1143 WMWidget **w;
1145 if (panel->currentType != type) {
1147 w = panel->sections[panel->currentType];
1149 while (*w) {
1150 WMUnmapWidget(*w);
1151 w++;
1153 WMUnmapWidget(panel->paramF);
1154 WMUnmapWidget(panel->quickB);
1157 w = panel->sections[type];
1159 while (*w) {
1160 WMMapWidget(*w);
1161 w++;
1165 updateFrameTitle(panel, title, type);
1167 panel->currentType = type;
1173 static void
1174 updateMenuItem(_Panel *panel, WEditMenuItem *item, WMWidget *changedWidget)
1176 ItemData *data = WGetEditMenuItemData(item);
1178 assert(data != NULL);
1180 #define REPLACE(v, d) if (v) wfree(v); v = d
1182 switch (data->type) {
1183 case ExecInfo:
1184 if (changedWidget == panel->commandT) {
1185 REPLACE(data->param.exec.command,
1186 WMGetTextFieldText(panel->commandT));
1188 if (changedWidget == panel->shortT) {
1189 REPLACE(data->param.exec.shortcut,
1190 WMGetTextFieldText(panel->shortT));
1192 break;
1194 case CommandInfo:
1195 if (changedWidget == panel->icommandL) {
1196 data->param.command.command =
1197 WMGetListSelectedItemRow(panel->icommandL);
1199 switch (data->param.command.command) {
1200 case 3:
1201 case 4:
1202 if (changedWidget == panel->quickB) {
1203 REPLACE(data->param.command.parameter,
1204 WMGetButtonSelected(panel->quickB)
1205 ? wstrdup("QUICK") : NULL);
1207 break;
1209 case 6:
1210 if (changedWidget == panel->paramT) {
1211 REPLACE(data->param.command.parameter,
1212 WMGetTextFieldText(panel->paramT));
1214 break;
1216 if (changedWidget == panel->shortT) {
1217 REPLACE(data->param.command.shortcut,
1218 WMGetTextFieldText(panel->shortT));
1222 break;
1224 case PipeInfo:
1225 if (changedWidget == panel->pipeT) {
1226 REPLACE(data->param.pipe.command,
1227 WMGetTextFieldText(panel->pipeT));
1229 break;
1231 case ExternalInfo:
1232 if (changedWidget == panel->pathT) {
1233 REPLACE(data->param.external.path,
1234 WMGetTextFieldText(panel->pathT));
1236 break;
1238 case DirectoryInfo:
1239 if (changedWidget == panel->dpathT) {
1240 REPLACE(data->param.directory.directory,
1241 WMGetTextFieldText(panel->dpathT));
1243 if (changedWidget == panel->dcommandT) {
1244 REPLACE(data->param.directory.command,
1245 WMGetTextFieldText(panel->dcommandT));
1247 if (changedWidget == panel->dstripB) {
1248 data->param.directory.stripExt =
1249 WMGetButtonSelected(panel->dstripB);
1251 break;
1253 default:
1254 assert(0);
1255 break;
1258 #undef REPLACE
1263 static void
1264 menuItemCloned(WEditMenuDelegate *delegate, WEditMenu *menu,
1265 WEditMenuItem *origItem, WEditMenuItem *newItem)
1267 ItemData *data = WGetEditMenuItemData(origItem);
1268 ItemData *newData;
1270 if (!data)
1271 return;
1273 #define DUP(s) (s) ? wstrdup(s) : NULL
1275 newData = NEW(ItemData);
1277 newData->type = data->type;
1279 switch (data->type) {
1280 case ExecInfo:
1281 newData->param.exec.command = DUP(data->param.exec.command);
1282 newData->param.exec.shortcut = DUP(data->param.exec.shortcut);
1283 break;
1285 case CommandInfo:
1286 newData->param.command.command = data->param.command.command;
1287 newData->param.command.parameter = DUP(data->param.command.parameter);
1288 newData->param.command.shortcut = DUP(data->param.command.shortcut);
1289 break;
1291 case PipeInfo:
1292 newData->param.pipe.command = DUP(data->param.pipe.command);
1293 break;
1295 case ExternalInfo:
1296 newData->param.external.path = DUP(data->param.external.path);
1297 break;
1299 case DirectoryInfo:
1300 newData->param.directory.directory = DUP(data->param.directory.directory);
1301 newData->param.directory.command = DUP(data->param.directory.command);
1302 newData->param.directory.stripExt = data->param.directory.stripExt;
1303 break;
1305 default:
1306 break;
1309 #undef DUP
1311 WSetEditMenuItemData(newItem, newData, (WMCallback*)freeItemData);
1315 static void
1316 menuItemEdited(struct WEditMenuDelegate *delegate, WEditMenu *menu,
1317 WEditMenuItem *item)
1319 _Panel *panel = (_Panel*)delegate->data;
1320 WEditMenu *submenu;
1322 updateFrameTitle(panel, WGetEditMenuItemTitle(item), panel->currentType);
1324 submenu = WGetEditMenuSubmenu(menu, item);
1325 if (submenu) {
1326 WSetEditMenuTitle(submenu, WGetEditMenuItemTitle(item));
1331 static Bool
1332 shouldRemoveItem(struct WEditMenuDelegate *delegate, WEditMenu *menu,
1333 WEditMenuItem *item)
1335 _Panel *panel = (_Panel*)delegate->data;
1337 if (panel->dontAsk)
1338 return True;
1340 if (WGetEditMenuSubmenu(menu, item)) {
1341 int res;
1343 res = WMRunAlertPanel(WMWidgetScreen(menu), NULL,
1344 _("Remove Submenu"),
1345 _("Removing this item will destroy all items inside\n"
1346 "the submenu. Do you really want to do that?"),
1347 _("Yes"), _("No"),
1348 _("Yes, don't ask again."));
1349 switch (res) {
1350 case WAPRDefault:
1351 return True;
1352 case WAPRAlternate:
1353 return False;
1354 case WAPROther:
1355 panel->dontAsk = True;
1356 return True;
1359 return True;
1363 static void
1364 menuItemDeselected(WEditMenuDelegate *delegate, WEditMenu *menu,
1365 WEditMenuItem *item)
1367 _Panel *panel = (_Panel*)delegate->data;
1369 changeInfoType(panel, NULL, NoInfo);
1373 static void
1374 menuItemSelected(WEditMenuDelegate *delegate, WEditMenu *menu,
1375 WEditMenuItem *item)
1377 ItemData *data = WGetEditMenuItemData(item);
1378 _Panel *panel = (_Panel*)delegate->data;
1380 panel->currentItem = item;
1382 if (data) {
1383 changeInfoType(panel, WGetEditMenuItemTitle(item), data->type);
1385 switch (data->type) {
1386 case NoInfo:
1387 break;
1389 case ExecInfo:
1390 WMSetTextFieldText(panel->commandT, data->param.exec.command);
1391 WMSetTextFieldText(panel->shortT, data->param.exec.shortcut);
1392 break;
1394 case CommandInfo:
1395 WMSelectListItem(panel->icommandL,
1396 data->param.command.command);
1397 WMSetListPosition(panel->icommandL,
1398 data->param.command.command - 2);
1399 WMSetTextFieldText(panel->shortT, data->param.command.shortcut);
1401 switch (data->param.command.command) {
1402 case 3:
1403 case 4:
1404 WMSetButtonSelected(panel->quickB,
1405 data->param.command.parameter!=NULL);
1406 break;
1407 case 6:
1408 WMSetTextFieldText(panel->paramT,
1409 data->param.command.parameter);
1410 break;
1413 icommandLClicked(panel->icommandL, panel);
1414 break;
1416 case PipeInfo:
1417 WMSetTextFieldText(panel->pipeT, data->param.pipe.command);
1418 break;
1420 case ExternalInfo:
1421 WMSetTextFieldText(panel->pathT, data->param.external.path);
1422 break;
1424 case DirectoryInfo:
1425 WMSetTextFieldText(panel->dpathT, data->param.directory.directory);
1426 WMSetTextFieldText(panel->dcommandT, data->param.directory.command);
1427 WMSetButtonSelected(panel->dstripB, data->param.directory.stripExt);
1428 break;
1430 case WSMenuInfo:
1431 break;
1433 default:
1434 break;
1441 static WEditMenu*
1442 buildSubmenu(_Panel *panel, WMPropList *pl)
1444 WMScreen *scr = WMWidgetScreen(panel->parent);
1445 WEditMenu *menu;
1446 WEditMenuItem *item;
1447 char *title;
1448 WMPropList *tp, *bp;
1449 int i;
1451 tp = WMGetFromPLArray(pl, 0);
1452 title = WMGetFromPLString(tp);
1454 menu = WCreateEditMenu(scr, title);
1456 for (i = 1; i < WMGetPropListItemCount(pl); i++) {
1457 WMPropList *pi;
1459 pi = WMGetFromPLArray(pl, i);
1461 tp = WMGetFromPLArray(pi, 0);
1462 bp = WMGetFromPLArray(pi, 1);
1464 title = WMGetFromPLString(tp);
1466 if (!bp || WMIsPLArray(bp)) { /* it's a submenu */
1467 WEditMenu *submenu;
1469 submenu = buildSubmenu(panel, pi);
1471 item = WAddMenuItemWithTitle(menu, title);
1473 WSetEditMenuSubmenu(menu, item, submenu);
1474 } else {
1475 ItemData *data;
1477 item = WAddMenuItemWithTitle(menu, title);
1479 data = parseCommand(pi);
1481 if (panel->markerPix[data->type])
1482 WSetEditMenuItemImage(item, panel->markerPix[data->type]);
1483 WSetEditMenuItemData(item, data, (WMCallback*)freeItemData);
1487 WSetEditMenuAcceptsDrop(menu, True);
1488 WSetEditMenuDelegate(menu, &menuDelegate);
1490 WMRealizeWidget(menu);
1492 return menu;
1497 static void
1498 buildMenuFromPL(_Panel *panel, WMPropList *pl)
1500 panel->menu = buildSubmenu(panel, pl);
1505 static WMPropList*
1506 getDefaultMenu(_Panel *panel)
1508 WMPropList *menu, *pmenu;
1509 char *menuPath, *gspath;
1511 gspath = wusergnusteppath();
1513 menuPath = wmalloc(strlen(gspath)+128);
1514 /* if there is a localized plmenu for the tongue put it's filename here */
1515 sprintf(menuPath, _("%s/Library/WindowMaker/plmenu"), gspath);
1517 menu = WMReadPropListFromFile(menuPath);
1518 if (!menu) {
1519 wwarning("%s:could not read property list menu", menuPath);
1521 if (strcmp("%s/Library/WindowMaker/plmenu",
1522 _("%s/Library/WindowMaker/plmenu"))!=0) {
1524 sprintf(menuPath, "%s/Library/WindowMaker/plmenu", gspath);
1525 menu = WMReadPropListFromFile(menuPath);
1526 wwarning("%s:could not read property list menu", menuPath);
1528 if (!menu) {
1529 char buffer[512];
1531 sprintf(buffer, _("Could not open default menu from '%s'"),
1532 menuPath);
1533 WMRunAlertPanel(WMWidgetScreen(panel->parent), panel->parent,
1534 _("Error"), buffer, _("OK"), NULL, NULL);
1538 wfree(menuPath);
1540 if (menu) {
1541 pmenu = menu;
1542 } else {
1543 pmenu = NULL;
1546 return pmenu;
1550 static void
1551 showData(_Panel *panel)
1553 char *gspath;
1554 char *menuPath;
1555 WMPropList *pmenu;
1557 gspath = wusergnusteppath();
1559 menuPath = wmalloc(strlen(gspath)+32);
1560 strcpy(menuPath, gspath);
1561 strcat(menuPath, "/Defaults/WMRootMenu");
1563 pmenu = WMReadPropListFromFile(menuPath);
1565 if (!pmenu || !WMIsPLArray(pmenu)) {
1566 int res;
1568 res = WMRunAlertPanel(WMWidgetScreen(panel->parent), panel->parent,
1569 _("Warning"),
1570 _("The menu file format currently in use is not supported\n"
1571 "by this tool. Do you want to discard the current menu\n"
1572 "to use this tool?"),
1573 _("Yes, Discard and Update"),
1574 _("No, Keep Current Menu"), NULL);
1576 if (res == WAPRDefault) {
1577 pmenu = getDefaultMenu(panel);
1579 if (!pmenu) {
1580 pmenu = WMCreatePLArray(WMCreatePLString("Applications"),
1581 NULL);
1583 } else {
1584 panel->dontSave = True;
1585 return;
1589 panel->menuPath = menuPath;
1591 buildMenuFromPL(panel, pmenu);
1593 WMReleasePropList(pmenu);
1597 static Bool
1598 notblank(char *s)
1600 if (s) {
1601 while (*s++) {
1602 if (!isspace(*s))
1603 return True;
1606 return False;
1610 static WMPropList*
1611 processData(char *title, ItemData *data)
1613 WMPropList *item;
1614 char *s1;
1615 static WMPropList *pscut = NULL;
1616 static WMPropList *pomenu = NULL;
1617 int i;
1619 if (!pscut) {
1620 pscut = WMCreatePLString("SHORTCUT");
1621 pomenu = WMCreatePLString("OPEN_MENU");
1624 item = WMCreatePLArray(WMCreatePLString(title), NULL);
1627 switch (data->type) {
1628 case ExecInfo:
1629 if (data->param.exec.command == NULL)
1630 return NULL;
1631 #if 1
1632 if (strpbrk(data->param.exec.command, "&$*|><?`=;")) {
1633 s1 = "SHEXEC";
1634 } else {
1635 s1 = "EXEC";
1637 #else
1638 s1 = "SHEXEC";
1639 #endif
1641 if (notblank(data->param.exec.shortcut)) {
1642 WMAddToPLArray(item, pscut);
1643 WMAddToPLArray(item,
1644 WMCreatePLString(data->param.exec.shortcut));
1647 WMAddToPLArray(item, WMCreatePLString(s1));
1648 WMAddToPLArray(item, WMCreatePLString(data->param.exec.command));
1649 break;
1651 case CommandInfo:
1652 if (notblank(data->param.command.shortcut)) {
1653 WMAddToPLArray(item, pscut);
1654 WMAddToPLArray(item,
1655 WMCreatePLString(data->param.command.shortcut));
1658 i = data->param.command.command;
1660 WMAddToPLArray(item, WMCreatePLString(commandNames[i]));
1662 switch (i) {
1663 case 3:
1664 case 4:
1665 if (data->param.command.parameter) {
1666 WMAddToPLArray(item,
1667 WMCreatePLString(data->param.command.parameter));
1669 break;
1671 case 6: /* restart */
1672 if (data->param.command.parameter) {
1673 WMAddToPLArray(item,
1674 WMCreatePLString(data->param.command.parameter));
1676 break;
1679 break;
1681 case PipeInfo:
1682 if (!data->param.pipe.command)
1683 return NULL;
1684 WMAddToPLArray(item, pomenu);
1685 s1 = wstrconcat("| ", data->param.pipe.command);
1686 WMAddToPLArray(item, WMCreatePLString(s1));
1687 wfree(s1);
1688 break;
1690 case ExternalInfo:
1691 if (!data->param.external.path)
1692 return NULL;
1693 WMAddToPLArray(item, pomenu);
1694 WMAddToPLArray(item, WMCreatePLString(data->param.external.path));
1695 break;
1697 case DirectoryInfo:
1698 if (!data->param.directory.directory
1699 || !data->param.directory.command)
1700 return NULL;
1702 int l;
1703 char *tmp;
1705 l = strlen(data->param.directory.directory);
1706 l += strlen(data->param.directory.command);
1707 l += 32;
1709 WMAddToPLArray(item, pomenu);
1711 tmp = wmalloc(l);
1712 sprintf(tmp, "%s%s WITH %s",
1713 data->param.directory.stripExt ? "-noext " : "",
1714 data->param.directory.directory,
1715 data->param.directory.command);
1717 WMAddToPLArray(item, WMCreatePLString(tmp));
1718 wfree(tmp);
1720 break;
1722 case WSMenuInfo:
1723 WMAddToPLArray(item, WMCreatePLString("WORKSPACE_MENU"));
1724 break;
1726 case WWindowListInfo:
1727 WMAddToPLArray(item, WMCreatePLString("WINDOWS_MENU"));
1728 break;
1730 default:
1731 assert(0);
1732 break;
1735 return item;
1739 static WMPropList*
1740 processSubmenu(WEditMenu *menu)
1742 WEditMenuItem *item;
1743 WMPropList *pmenu;
1744 WMPropList *pl;
1745 char *s;
1746 int i;
1749 s = WGetEditMenuTitle(menu);
1750 pl = WMCreatePLString(s);
1752 pmenu = WMCreatePLArray(pl, NULL);
1754 i = 0;
1755 while ((item = WGetEditMenuItem(menu, i++))) {
1756 WEditMenu *submenu;
1758 s = WGetEditMenuItemTitle(item);
1760 submenu = WGetEditMenuSubmenu(menu, item);
1761 if (submenu) {
1762 pl = processSubmenu(submenu);
1763 } else {
1764 pl = processData(s, WGetEditMenuItemData(item));
1767 if (!pl)
1768 continue;
1770 WMAddToPLArray(pmenu, pl);
1773 return pmenu;
1778 static WMPropList*
1779 buildPLFromMenu(_Panel *panel)
1781 WMPropList *menu;
1783 menu = processSubmenu(panel->menu);
1785 return menu;
1791 static void
1792 storeData(_Panel *panel)
1794 WMPropList *menu;
1796 if (panel->dontSave)
1797 return;
1799 menu = buildPLFromMenu(panel);
1801 WMWritePropListToFile(menu, panel->menuPath, True);
1803 WMReleasePropList(menu);
1808 static void
1809 showMenus(_Panel *panel)
1811 if (panel->menu)
1812 WEditMenuUnhide(panel->menu);
1816 static void
1817 hideMenus(_Panel *panel)
1819 if (panel->menu)
1820 WEditMenuHide(panel->menu);
1826 Panel*
1827 InitMenu(WMScreen *scr, WMWidget *parent)
1829 _Panel *panel;
1831 panel = wmalloc(sizeof(_Panel));
1832 memset(panel, 0, sizeof(_Panel));
1834 panel->sectionName = _("Applications Menu Definition");
1836 panel->description = _("Edit the menu for launching applications.");
1838 panel->parent = parent;
1840 panel->callbacks.createWidgets = createPanel;
1841 panel->callbacks.updateDomain = storeData;
1842 panel->callbacks.showPanel = showMenus;
1843 panel->callbacks.hidePanel = hideMenus;
1846 AddSection(panel, ICON_FILE);
1848 return panel;