fixed bug in builtin xpm loader
[wmaker-crm.git] / WPrefs.app / Menu.c
blobbc567f553fd9176208c4b0ef326e683b9ac5f17e
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;
112 /* about the currently selected item */
113 WEditMenuItem *currentItem;
114 InfoType currentType;
115 WMWidget *sections[LastInfo][MAX_SECTION_SIZE];
116 } _Panel;
119 typedef struct {
120 InfoType type;
121 union {
122 struct {
123 int command;
124 char *parameter;
125 char *shortcut;
126 } command;
127 struct {
128 char *command;
129 char *shortcut;
130 } exec;
131 struct {
132 char *path;
133 } external;
134 struct {
135 char *command;
136 } pipe;
137 struct {
138 char *directory;
139 char *command;
140 unsigned stripExt:1;
141 } directory;
142 } param;
143 } ItemData;
147 static char *commandNames[] = {
148 "ARRANGE_ICONS",
149 "HIDE_OTHERS",
150 "SHOW_ALL",
151 "EXIT",
152 "SHUTDOWN",
153 "RESTART",
154 "RESTART",
155 "SAVE_SESSION",
156 "CLEAR_SESSION",
157 "REFRESH",
158 "INFO_PANEL",
159 "LEGAL_PANEL"
164 #define NEW(type) memset(wmalloc(sizeof(type)), 0, sizeof(type))
167 #define ICON_FILE "menus"
171 static void showData(_Panel *panel);
174 static void updateMenuItem(_Panel *panel, WEditMenuItem *item,
175 WMWidget *changedWidget);
177 static void menuItemSelected(struct WEditMenuDelegate *delegate,
178 WEditMenu *menu, WEditMenuItem *item);
180 static void menuItemDeselected(struct WEditMenuDelegate *delegate,
181 WEditMenu *menu, WEditMenuItem *item);
183 static void menuItemCloned(struct WEditMenuDelegate *delegate, WEditMenu *menu,
184 WEditMenuItem *origItem, WEditMenuItem *newItem);
186 static void menuItemEdited(struct WEditMenuDelegate *delegate, WEditMenu *menu,
187 WEditMenuItem *item);
189 static Bool shouldRemoveItem(struct WEditMenuDelegate *delegate,
190 WEditMenu *menu, WEditMenuItem *item);
193 static void freeItemData(ItemData *data);
197 static WEditMenuDelegate menuDelegate = {
198 NULL,
199 menuItemCloned,
200 menuItemEdited,
201 menuItemSelected,
202 menuItemDeselected,
203 shouldRemoveItem
207 static void
208 dataChanged(void *self, WMNotification *notif)
210 _Panel *panel = (_Panel*)self;
211 WEditMenuItem *item = panel->currentItem;
212 WMWidget *w = (WMWidget*)WMGetNotificationObject(notif);
214 updateMenuItem(panel, item, w);
218 static void
219 buttonClicked(WMWidget *w, void *data)
221 _Panel *panel = (_Panel*)data;
222 WEditMenuItem *item = panel->currentItem;
224 updateMenuItem(panel, item, w);
228 static void
229 icommandLClicked(WMWidget *w, void *data)
231 _Panel *panel = (_Panel*)data;
232 int cmd;
234 cmd = WMGetListSelectedItemRow(w);
235 if (cmd == 3 || cmd == 4) {
236 WMMapWidget(panel->quickB);
237 } else {
238 WMUnmapWidget(panel->quickB);
240 if (cmd == 6) {
241 WMMapWidget(panel->paramF);
242 } else {
243 WMUnmapWidget(panel->paramF);
255 static char*
256 captureShortcut(Display *dpy, _Panel *panel)
258 XEvent ev;
259 KeySym ksym;
260 char buffer[64];
261 char *key = NULL;
263 while (panel->capturing) {
264 XAllowEvents(dpy, AsyncKeyboard, CurrentTime);
265 WMNextEvent(dpy, &ev);
266 if (ev.type==KeyPress && ev.xkey.keycode!=0) {
267 ksym = XKeycodeToKeysym(dpy, ev.xkey.keycode, 0);
268 if (!IsModifierKey(ksym)) {
269 key=XKeysymToString(ksym);
270 panel->capturing = 0;
271 break;
274 WMHandleEvent(&ev);
277 if (!key)
278 return NULL;
280 buffer[0] = 0;
282 if (ev.xkey.state & ControlMask) {
283 strcat(buffer, "Control+");
285 if (ev.xkey.state & ShiftMask) {
286 strcat(buffer, "Shift+");
288 if (ev.xkey.state & Mod1Mask) {
289 strcat(buffer, "Mod1+");
291 if (ev.xkey.state & Mod2Mask) {
292 strcat(buffer, "Mod2+");
294 if (ev.xkey.state & Mod3Mask) {
295 strcat(buffer, "Mod3+");
297 if (ev.xkey.state & Mod4Mask) {
298 strcat(buffer, "Mod4+");
300 if (ev.xkey.state & Mod5Mask) {
301 strcat(buffer, "Mod5+");
303 strcat(buffer, key);
305 return wstrdup(buffer);
310 static void
311 sgrabClicked(WMWidget *w, void *data)
313 _Panel *panel = (_Panel*)data;
314 Display *dpy = WMScreenDisplay(WMWidgetScreen(panel->win));
315 char *shortcut;
318 if (w == panel->sclearB) {
319 WMSetTextFieldText(panel->shortT, "");
320 updateMenuItem(panel, panel->currentItem, panel->shortT);
321 return;
324 if (!panel->capturing) {
325 panel->capturing = 1;
326 WMSetButtonText(w, _("Cancel"));
327 XGrabKeyboard(dpy, WMWidgetXID(panel->win), True, GrabModeAsync,
328 GrabModeAsync, CurrentTime);
329 shortcut = captureShortcut(dpy, panel);
330 if (shortcut) {
331 WMSetTextFieldText(panel->shortT, shortcut);
332 updateMenuItem(panel, panel->currentItem, panel->shortT);
333 wfree(shortcut);
336 panel->capturing = 0;
337 WMSetButtonText(w, _("Capture"));
338 XUngrabKeyboard(dpy, CurrentTime);
342 static void
343 changedItemPad(WMWidget *w, void *data)
345 _Panel *panel = (_Panel*)data;
346 int padn = WMGetPopUpButtonSelectedItem(w);
348 WMUnmapWidget(panel->itemPad[panel->currentPad]);
349 WMMapWidget(panel->itemPad[padn]);
351 panel->currentPad = padn;
355 static WEditMenu*
356 putNewSubmenu(WEditMenu *menu, char *title)
358 WEditMenu *tmp;
359 WEditMenuItem *item;
361 item = WAddMenuItemWithTitle(menu, title);
363 tmp = WCreateEditMenu(WMWidgetScreen(menu), title);
364 WSetEditMenuAcceptsDrop(tmp, True);
365 WSetEditMenuDelegate(tmp, &menuDelegate);
366 WSetEditMenuSubmenu(menu, item, tmp);
368 return tmp;
372 static ItemData*
373 putNewItem(_Panel *panel, WEditMenu *menu, int type, char *title)
375 WEditMenuItem *item;
376 ItemData *data;
378 item = WAddMenuItemWithTitle(menu, title);
380 data = NEW(ItemData);
381 data->type = type;
382 WSetEditMenuItemData(item, data, (WMCallback*)freeItemData);
383 WSetEditMenuItemImage(item, panel->markerPix[type]);
385 return data;
389 static WEditMenu*
390 makeFactoryMenu(WMWidget *parent, int width)
392 WEditMenu *pad;
394 pad = WCreateEditMenuPad(parent);
395 WMResizeWidget(pad, width, 10);
396 WSetEditMenuMinSize(pad, wmksize(width, 0));
397 WSetEditMenuMaxSize(pad, wmksize(width, 0));
398 WSetEditMenuSelectable(pad, False);
399 WSetEditMenuEditable(pad, False);
400 WSetEditMenuIsFactory(pad, True);
401 WSetEditMenuDelegate(pad, &menuDelegate);
403 return pad;
407 static void
408 createPanel(_Panel *p)
410 _Panel *panel = (_Panel*)p;
411 WMScreen *scr = WMWidgetScreen(panel->win);
412 WMColor *black = WMBlackColor(scr);
413 WMColor *white = WMWhiteColor(scr);
414 WMColor *gray = WMGrayColor(scr);
415 WMFont *bold = WMBoldSystemFontOfSize(scr, 12);
416 WMFont *font = WMSystemFontOfSize(scr, 12);
417 WMLabel *label;
418 int width;
421 menuDelegate.data = panel;
424 panel->boldFont = bold;
425 panel->normalFont = font;
427 panel->black = black;
428 panel->white = white;
429 panel->gray = gray;
432 Pixmap pix;
433 Display *dpy = WMScreenDisplay(scr);
434 GC gc;
435 WMPixmap *pixm;
437 pixm = WMCreatePixmap(scr, 7, 7, WMScreenDepth(scr), True);
439 pix = WMGetPixmapXID(pixm);
441 XDrawLine(dpy, pix, WMColorGC(black), 0, 3, 6, 3);
442 XDrawLine(dpy, pix, WMColorGC(black), 3, 0, 3, 6);
444 XDrawLine(dpy, pix, WMColorGC(black), 1, 0, 3, 3);
445 XDrawLine(dpy, pix, WMColorGC(black), 1, 6, 3, 3);
446 XDrawLine(dpy, pix, WMColorGC(black), 0, 0, 0, 6);
449 pix = WMGetPixmapMaskXID(pixm);
451 gc = XCreateGC(dpy, pix, 0, NULL);
453 XSetForeground(dpy, gc, 0);
454 XFillRectangle(dpy, pix, gc, 0, 0, 7, 7);
456 XSetForeground(dpy, gc, 1);
457 XDrawLine(dpy, pix, gc, 0, 3, 6, 3);
458 XDrawLine(dpy, pix, gc, 3, 0, 3, 6);
460 panel->markerPix[ExternalInfo] = pixm;
461 panel->markerPix[PipeInfo] = pixm;
462 panel->markerPix[DirectoryInfo] = pixm;
463 panel->markerPix[WSMenuInfo] = pixm;
465 XFreeGC(dpy, gc);
469 panel->frame = WMCreateFrame(panel->win);
470 WMResizeWidget(panel->frame, FRAME_WIDTH, FRAME_HEIGHT);
471 WMMoveWidget(panel->frame, FRAME_LEFT, FRAME_TOP);
473 panel->typeP = WMCreatePopUpButton(panel->frame);
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->frame, 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");
501 panel->itemPad[0] = pad;
505 WEditMenu *pad;
506 ItemData *data;
507 WMScrollView *sview;
509 sview = WMCreateScrollView(panel->frame);
510 WMResizeWidget(sview, 150, 180);
511 WMMoveWidget(sview, 10, 40);
512 WMSetScrollViewHasVerticalScroller(sview, True);
514 pad = makeFactoryMenu(panel->frame, 130);
516 WMSetScrollViewContentView(sview, WMWidgetView(pad));
518 data = putNewItem(panel, pad, ExecInfo, _("XTerm"));
519 data->param.exec.command = "xterm -sb -sl 2000 -bg black -fg white";
521 data = putNewItem(panel, pad, ExecInfo, _("rxvt"));
522 data->param.exec.command = "rxvt";
524 data = putNewItem(panel, pad, ExecInfo, _("ETerm"));
525 data->param.exec.command = "eterm";
527 data = putNewItem(panel, pad, ExecInfo, _("Run..."));
528 data->param.exec.command = "%a(Run,Type command to run)";
530 data = putNewItem(panel, pad, ExecInfo, _("Netscape"));
531 data->param.exec.command = "netscape";
533 data = putNewItem(panel, pad, ExecInfo, _("gimp"));
534 data->param.exec.command = "gimp";
536 data = putNewItem(panel, pad, ExecInfo, _("epic"));
537 data->param.exec.command = "xterm -e epic";
539 data = putNewItem(panel, pad, ExecInfo, _("ee"));
540 data->param.exec.command = "ee";
542 data = putNewItem(panel, pad, ExecInfo, _("xv"));
543 data->param.exec.command = "xv";
545 data = putNewItem(panel, pad, ExecInfo, _("Acrobat Reader"));
546 data->param.exec.command = "acroread || /usr/local/Acrobat4/bin/acroread";
548 data = putNewItem(panel, pad, ExecInfo, _("ghostview"));
549 data->param.exec.command = "gv";
551 data = putNewItem(panel, pad, CommandInfo, _("Exit Window Maker"));
552 data->param.command.command = 3;
554 WMMapWidget(pad);
556 panel->itemPad[1] = sview;
561 WEditMenu *pad, *smenu;
562 ItemData *data;
563 WMScrollView *sview;
565 sview = WMCreateScrollView(panel->frame);
566 WMResizeWidget(sview, 150, 180);
567 WMMoveWidget(sview, 10, 40);
568 WMSetScrollViewHasVerticalScroller(sview, True);
570 pad = makeFactoryMenu(panel->frame, 130);
572 WMSetScrollViewContentView(sview, WMWidgetView(pad));
574 data = putNewItem(panel, pad, ExternalInfo, _("Debian Menu"));
575 data->param.pipe.command = "/etc/X11/WindowMaker/menu.hook";
577 data = putNewItem(panel, pad, PipeInfo, _("RedHat Menu"));
578 data->param.pipe.command = "wmconfig --output wmaker";
580 data = putNewItem(panel, pad, PipeInfo, _("Menu Conectiva"));
581 data->param.pipe.command = "wmconfig --output wmaker";
583 data = putNewItem(panel, pad, DirectoryInfo, _("Themes"));
584 data->param.directory.command = "setstyle";
585 data->param.directory.directory = "/usr/share/WindowMaker/Themes /usr/local/share/WindowMaker/Themes $HOME/GNUstep/Library/WindowMaker/Themes";
586 data->param.directory.stripExt = 1;
588 data = putNewItem(panel, pad, DirectoryInfo, _("Bg Images (scale)"));
589 data->param.directory.command = "wmsetbg -u -s";
590 data->param.directory.directory = "/opt/kde2/share/wallpapers /usr/share/WindowMaker/Backgrounds $HOME/GNUstep/Library/WindowMaker/Backgrounds";
591 data->param.directory.stripExt = 1;
593 data = putNewItem(panel, pad, DirectoryInfo, _("Bg Images (tile)"));
594 data->param.directory.command = "wmsetbg -u -t";
595 data->param.directory.directory = "/opt/kde2/share/wallpapers /usr/share/WindowMaker/Backgrounds $HOME/GNUstep/Library/WindowMaker/Backgrounds";
596 data->param.directory.stripExt = 1;
598 smenu = putNewSubmenu(pad, _("Assorted XTerms"));
600 data = putNewItem(panel, smenu, ExecInfo, _("XTerm Yellow on Blue"));
601 data->param.exec.command = "xterm -sb -sl 2000 -bg midnightblue -fg yellow";
603 data = putNewItem(panel, smenu, ExecInfo, _("XTerm White on Black"));
604 data->param.exec.command = "xterm -sb -sl 2000 -bg black -fg white";
606 data = putNewItem(panel, smenu, ExecInfo, _("XTerm Black on White"));
607 data->param.exec.command = "xterm -sb -sl 2000 -bg white -fg black";
609 data = putNewItem(panel, smenu, ExecInfo, _("XTerm Black on Beige"));
610 data->param.exec.command = "xterm -sb -sl 2000 -bg '#bbbb99' -fg black";
612 data = putNewItem(panel, smenu, ExecInfo, _("XTerm White on Green"));
613 data->param.exec.command = "xterm -sb -sl 2000 -bg '#228822' -fg white";
615 data = putNewItem(panel, smenu, ExecInfo, _("XTerm White on Olive"));
616 data->param.exec.command = "xterm -sb -sl 2000 -bg '#335533' -fg white";
618 data = putNewItem(panel, smenu, ExecInfo, _("XTerm Blue on Blue"));
619 data->param.exec.command = "xterm -sb -sl 2000 -bg '#112244' -fg '#88aabb'";
621 data = putNewItem(panel, smenu, ExecInfo, _("XTerm BIG FONTS"));
622 data->param.exec.command = "xterm -sb -sl 2000 -bg black -fg white -fn 10x20";
624 WMMapWidget(pad);
626 panel->itemPad[2] = sview;
630 width = FRAME_WIDTH - 20 - 150 - 10;
632 panel->optionsF = WMCreateFrame(panel->frame);
633 WMResizeWidget(panel->optionsF, width, FRAME_HEIGHT - 15);
634 WMMoveWidget(panel->optionsF, 10 + 150 + 10, 5);
636 width -= 20;
638 /* command */
640 panel->commandF = WMCreateFrame(panel->optionsF);
641 WMResizeWidget(panel->commandF, width, 50);
642 WMMoveWidget(panel->commandF, 10, 20);
643 WMSetFrameTitle(panel->commandF, _("Program to Run"));
645 panel->commandT = WMCreateTextField(panel->commandF);
646 WMResizeWidget(panel->commandT, width - 20, 20);
647 WMMoveWidget(panel->commandT, 10, 20);
649 WMAddNotificationObserver(dataChanged, panel,
650 WMTextDidChangeNotification,
651 panel->commandT);
653 #if 0
654 panel->xtermC = WMCreateSwitchButton(panel->commandF);
655 WMResizeWidget(panel->xtermC, width - 20, 20);
656 WMMoveWidget(panel->xtermC, 10, 50);
657 WMSetButtonText(panel->xtermC, _("Run the program inside a Xterm"));
658 #endif
659 WMMapSubwidgets(panel->commandF);
662 /* path */
664 panel->pathF = WMCreateFrame(panel->optionsF);
665 WMResizeWidget(panel->pathF, width, 150);
666 WMMoveWidget(panel->pathF, 10, 40);
667 WMSetFrameTitle(panel->pathF, _("Path for Menu"));
669 panel->pathT = WMCreateTextField(panel->pathF);
670 WMResizeWidget(panel->pathT, width - 20, 20);
671 WMMoveWidget(panel->pathT, 10, 20);
673 WMAddNotificationObserver(dataChanged, panel,
674 WMTextDidChangeNotification,
675 panel->pathT);
677 label = WMCreateLabel(panel->pathF);
678 WMResizeWidget(label, width - 20, 80);
679 WMMoveWidget(label, 10, 50);
680 WMSetLabelText(label, _("Enter the path for a file containing a menu\n"
681 "or a list of directories with the programs you\n"
682 "want to have listed in the menu. Ex:\n"
683 "~/GNUstep/Library/WindowMaker/menu\n"
684 "or\n"
685 "/usr/X11R6/bin ~/xbin"));
687 WMMapSubwidgets(panel->pathF);
690 /* pipe */
692 panel->pipeF = WMCreateFrame(panel->optionsF);
693 WMResizeWidget(panel->pipeF, width, 100);
694 WMMoveWidget(panel->pipeF, 10, 50);
695 WMSetFrameTitle(panel->pipeF, _("Command"));
697 panel->pipeT = WMCreateTextField(panel->pipeF);
698 WMResizeWidget(panel->pipeT, width - 20, 20);
699 WMMoveWidget(panel->pipeT, 10, 20);
701 WMAddNotificationObserver(dataChanged, panel,
702 WMTextDidChangeNotification,
703 panel->pipeT);
706 label = WMCreateLabel(panel->pipeF);
707 WMResizeWidget(label, width - 20, 40);
708 WMMoveWidget(label, 10, 50);
709 WMSetLabelText(label, _("Enter a command that outputs a menu\n"
710 "definition to stdout when invoked."));
712 WMMapSubwidgets(panel->pipeF);
715 /* directory menu */
717 panel->dcommandF = WMCreateFrame(panel->optionsF);
718 WMResizeWidget(panel->dcommandF, width, 90);
719 WMMoveWidget(panel->dcommandF, 10, 25);
720 WMSetFrameTitle(panel->dcommandF, _("Command to Open Files"));
722 panel->dcommandT = WMCreateTextField(panel->dcommandF);
723 WMResizeWidget(panel->dcommandT, width - 20, 20);
724 WMMoveWidget(panel->dcommandT, 10, 20);
726 WMAddNotificationObserver(dataChanged, panel,
727 WMTextDidChangeNotification,
728 panel->dcommandT);
731 label = WMCreateLabel(panel->dcommandF);
732 WMResizeWidget(label, width - 20, 45);
733 WMMoveWidget(label, 10, 40);
734 WMSetLabelText(label, _("Enter the command you want to use to open the\n"
735 "files in the directories listed below."));
737 WMMapSubwidgets(panel->dcommandF);
740 panel->dpathF = WMCreateFrame(panel->optionsF);
741 WMResizeWidget(panel->dpathF, width, 80);
742 WMMoveWidget(panel->dpathF, 10, 125);
743 WMSetFrameTitle(panel->dpathF, _("Directories with Files"));
745 panel->dpathT = WMCreateTextField(panel->dpathF);
746 WMResizeWidget(panel->dpathT, width - 20, 20);
747 WMMoveWidget(panel->dpathT, 10, 20);
749 WMAddNotificationObserver(dataChanged, panel,
750 WMTextDidChangeNotification,
751 panel->dpathT);
753 panel->dstripB = WMCreateSwitchButton(panel->dpathF);
754 WMResizeWidget(panel->dstripB, width - 20, 20);
755 WMMoveWidget(panel->dstripB, 10, 50);
756 WMSetButtonText(panel->dstripB, _("Strip extensions from file names"));
758 WMSetButtonAction(panel->dstripB, buttonClicked, panel);
760 WMMapSubwidgets(panel->dpathF);
763 /* shortcut */
765 panel->shortF = WMCreateFrame(panel->optionsF);
766 WMResizeWidget(panel->shortF, width, 50);
767 WMMoveWidget(panel->shortF, 10, 160);
768 WMSetFrameTitle(panel->shortF, _("Keyboard Shortcut"));
770 panel->shortT = WMCreateTextField(panel->shortF);
771 WMResizeWidget(panel->shortT, width - 20 - 170, 20);
772 WMMoveWidget(panel->shortT, 10, 20);
774 WMAddNotificationObserver(dataChanged, panel,
775 WMTextDidChangeNotification,
776 panel->shortT);
778 panel->sgrabB = WMCreateCommandButton(panel->shortF);
779 WMResizeWidget(panel->sgrabB, 80, 24);
780 WMMoveWidget(panel->sgrabB, width - 90, 18);
781 WMSetButtonText(panel->sgrabB, _("Capture"));
782 WMSetButtonAction(panel->sgrabB, sgrabClicked, panel);
784 panel->sclearB = WMCreateCommandButton(panel->shortF);
785 WMResizeWidget(panel->sclearB, 80, 24);
786 WMMoveWidget(panel->sclearB, width - 175, 18);
787 WMSetButtonText(panel->sclearB, _("Clear"));
788 WMSetButtonAction(panel->sclearB, sgrabClicked, panel);
790 WMMapSubwidgets(panel->shortF);
792 /* internal command */
794 panel->icommandL = WMCreateList(panel->optionsF);
795 WMResizeWidget(panel->icommandL, width, 80);
796 WMMoveWidget(panel->icommandL, 10, 20);
798 WMSetListAction(panel->icommandL, icommandLClicked, panel);
800 WMAddNotificationObserver(dataChanged, panel,
801 WMListSelectionDidChangeNotification,
802 panel->icommandL);
804 WMInsertListItem(panel->icommandL, 0, _("Arrange Icons"));
805 WMInsertListItem(panel->icommandL, 1, _("Hide All Windows Except For The Focused One"));
806 WMInsertListItem(panel->icommandL, 2, _("Show All Windows"));
808 WMInsertListItem(panel->icommandL, 3, _("Exit Window Maker"));
809 WMInsertListItem(panel->icommandL, 4, _("Exit X Session"));
810 WMInsertListItem(panel->icommandL, 5, _("Restart Window Maker"));
811 WMInsertListItem(panel->icommandL, 6, _("Start Another Window Manager : ("));
813 WMInsertListItem(panel->icommandL, 7, _("Save Current Session"));
814 WMInsertListItem(panel->icommandL, 8, _("Clear Saved Session"));
815 WMInsertListItem(panel->icommandL, 9, _("Refresh Screen"));
816 WMInsertListItem(panel->icommandL, 10, _("Open Info Panel"));
817 WMInsertListItem(panel->icommandL, 11, _("Open Copyright Panel"));
820 panel->paramF = WMCreateFrame(panel->optionsF);
821 WMResizeWidget(panel->paramF, width, 50);
822 WMMoveWidget(panel->paramF, 10, 105);
823 WMSetFrameTitle(panel->paramF, _("Window Manager to Start"));
825 panel->paramT = WMCreateTextField(panel->paramF);
826 WMResizeWidget(panel->paramT, width - 20, 20);
827 WMMoveWidget(panel->paramT, 10, 20);
829 WMAddNotificationObserver(dataChanged, panel,
830 WMTextDidChangeNotification,
831 panel->paramT);
833 WMMapSubwidgets(panel->paramF);
836 panel->quickB = WMCreateSwitchButton(panel->optionsF);
837 WMResizeWidget(panel->quickB, width, 20);
838 WMMoveWidget(panel->quickB, 10, 120);
839 WMSetButtonText(panel->quickB, _("Do not confirm action."));
840 WMSetButtonAction(panel->quickB, buttonClicked, panel);
845 label = WMCreateLabel(panel->optionsF);
846 WMResizeWidget(label, width - 20, FRAME_HEIGHT - 50);
847 WMMoveWidget(label, 10, 20);
848 WMSetLabelText(label,
849 _("Instructions:\n\n"
850 " - drag items from the left to the menu to add new items\n"
851 " - drag items out of the menu to remove items\n"
852 " - drag items in menu to change their position\n"
853 " - drag items with Control pressed to copy them\n"
854 " - double click in a menu item to change the label\n"
855 " - click on a menu item to change related information"));
856 WMMapWidget(label);
858 WMRealizeWidget(panel->frame);
859 WMMapSubwidgets(panel->frame);
860 WMMapWidget(panel->frame);
864 int i;
865 for (i = 0; i < 3; i++)
866 WMUnmapWidget(panel->itemPad[i]);
868 changedItemPad(panel->typeP, panel);
870 panel->sections[NoInfo][0] = label;
872 panel->sections[ExecInfo][0] = panel->commandF;
873 panel->sections[ExecInfo][1] = panel->shortF;
875 panel->sections[CommandInfo][0] = panel->icommandL;
876 panel->sections[CommandInfo][1] = panel->shortF;
878 panel->sections[ExternalInfo][0] = panel->pathF;
880 panel->sections[PipeInfo][0] = panel->pipeF;
882 panel->sections[DirectoryInfo][0] = panel->dpathF;
883 panel->sections[DirectoryInfo][1] = panel->dcommandF;
885 panel->currentType = NoInfo;
887 showData(panel);
890 WMPoint pos;
892 pos = WMGetViewScreenPosition(WMWidgetView(panel->frame));
894 if (pos.x < 200) {
895 pos.x += FRAME_WIDTH + 20;
896 } else {
897 pos.x = 10;
900 pos.y = WMAX(pos.y - 100, 0);
902 WEditMenuShowAt(panel->menu, pos.x, pos.y);
909 static void
910 freeItemData(ItemData *data)
912 #define CFREE(d) if (d) wfree(d)
914 /* TODO */
915 switch (data->type) {
916 case CommandInfo:
917 CFREE(data->param.command.parameter);
918 CFREE(data->param.command.shortcut);
919 break;
921 case ExecInfo:
922 CFREE(data->param.exec.command);
923 CFREE(data->param.exec.shortcut);
924 break;
926 case PipeInfo:
927 CFREE(data->param.pipe.command);
928 break;
930 case ExternalInfo:
931 CFREE(data->param.external.path);
932 break;
934 case DirectoryInfo:
935 CFREE(data->param.directory.command);
936 CFREE(data->param.directory.directory);
937 break;
939 default:
940 break;
943 wfree(data);
944 #undef CFREE
948 static ItemData*
949 parseCommand(proplist_t item)
951 ItemData *data = NEW(ItemData);
952 proplist_t p;
953 char *command = NULL;
954 char *parameter = NULL;
955 char *shortcut = NULL;
956 int i = 1;
959 p = PLGetArrayElement(item, i++);
960 command = PLGetString(p);
961 if (strcmp(command, "SHORTCUT") == 0) {
962 p = PLGetArrayElement(item, i++);
963 shortcut = PLGetString(p);
964 p = PLGetArrayElement(item, i++);
965 command = PLGetString(p);
967 p = PLGetArrayElement(item, i++);
968 if (p)
969 parameter = PLGetString(p);
971 if (strcmp(command, "EXEC") == 0 || strcmp(command, "SHEXEC") == 0) {
973 data->type = ExecInfo;
975 data->param.exec.command = wstrdup(parameter);
976 if (shortcut)
977 data->param.exec.shortcut = wstrdup(shortcut);
979 } else if (strcmp(command, "OPEN_MENU") == 0) {
980 char *p;
982 * dir menu, menu file
983 * dir WITH
984 * |pipe (TODO: ||pipe)
986 p = parameter;
987 while (isspace(*p) && *p) p++;
988 if (*p == '|') {
989 data->type = PipeInfo;
990 data->param.pipe.command = wtrimspace(p+1);
991 } else {
992 char *s;
994 p = wstrdup(p);
996 s = strstr(p, "WITH");
997 if (s) {
998 char **tokens;
999 char **ctokens;
1000 int tokn;
1001 int i, j;
1003 data->type = DirectoryInfo;
1005 *s = '\0';
1006 s += 5;
1007 while (*s && isspace(*s)) s++;
1008 data->param.directory.command = wstrdup(s);
1010 wtokensplit(p, &tokens, &tokn);
1011 wfree(p);
1013 ctokens = wmalloc(sizeof(char*)*tokn);
1015 for (i = 0, j = 0; i < tokn; i++) {
1016 if (strcmp(tokens[i], "-noext") == 0) {
1017 wfree(tokens[i]);
1018 data->param.directory.stripExt = 1;
1019 } else {
1020 ctokens[j++] = tokens[i];
1023 data->param.directory.directory = wtokenjoin(ctokens, j);
1024 wfree(ctokens);
1026 wtokenfree(tokens, tokn);
1027 } else {
1028 data->type = ExternalInfo;
1029 data->param.external.path = p;
1032 } else if (strcmp(command, "WORKSPACE_MENU") == 0) {
1033 data->type = WSMenuInfo;
1034 } else {
1035 int cmd;
1037 if (strcmp(command, "ARRANGE_ICONS") == 0) {
1038 cmd = 0;
1039 } else if (strcmp(command, "HIDE_OTHERS") == 0) {
1040 cmd = 1;
1041 } else if (strcmp(command, "SHOW_ALL") == 0) {
1042 cmd = 2;
1043 } else if (strcmp(command, "EXIT") == 0) {
1044 cmd = 3;
1045 } else if (strcmp(command, "SHUTDOWN") == 0) {
1046 cmd = 4;
1047 } else if (strcmp(command, "RESTART") == 0) {
1048 if (parameter) {
1049 cmd = 6;
1050 } else {
1051 cmd = 5;
1053 } else if (strcmp(command, "SAVE_SESSION") == 0) {
1054 cmd = 7;
1055 } else if (strcmp(command, "CLEAR_SESSION") == 0) {
1056 cmd = 8;
1057 } else if (strcmp(command, "REFRESH") == 0) {
1058 cmd = 9;
1059 } else if (strcmp(command, "INFO_PANEL") == 0) {
1060 cmd = 10;
1061 } else if (strcmp(command, "LEGAL_PANEL") == 0) {
1062 cmd = 11;
1063 } else {
1064 wwarning(_("unknown command '%s' in menu"), command);
1065 goto error;
1068 data->type = CommandInfo;
1070 data->param.command.command = cmd;
1071 if (shortcut)
1072 data->param.command.shortcut = wstrdup(shortcut);
1073 if (parameter)
1074 data->param.command.parameter = wstrdup(parameter);
1077 return data;
1079 error:
1080 wfree(data);
1082 return NULL;
1088 static void
1089 updateFrameTitle(_Panel *panel, char *title, InfoType type)
1091 if (type != NoInfo) {
1092 char *tmp;
1094 switch (type) {
1095 case ExecInfo:
1096 tmp = wstrconcat(title, _(": Execute Program"));
1097 break;
1099 case CommandInfo:
1100 tmp = wstrconcat(title, _(": Perform Internal Command"));
1101 break;
1103 case ExternalInfo:
1104 tmp = wstrconcat(title, _(": Open a Submenu"));
1105 break;
1107 case PipeInfo:
1108 tmp = wstrconcat(title, _(": Program Generated Submenu"));
1109 break;
1111 case DirectoryInfo:
1112 tmp = wstrconcat(title, _(": Directory Contents Menu"));
1113 break;
1115 case WSMenuInfo:
1116 tmp = wstrconcat(title, _(": Open Workspaces Submenu"));
1117 break;
1119 default:
1120 tmp = NULL;
1121 break;
1123 WMSetFrameTitle(panel->optionsF, tmp);
1124 wfree(tmp);
1125 } else {
1126 WMSetFrameTitle(panel->optionsF, NULL);
1132 static void
1133 changeInfoType(_Panel *panel, char *title, InfoType type)
1135 WMWidget **w;
1137 if (panel->currentType != type) {
1139 w = panel->sections[panel->currentType];
1141 while (*w) {
1142 WMUnmapWidget(*w);
1143 w++;
1145 WMUnmapWidget(panel->paramF);
1146 WMUnmapWidget(panel->quickB);
1149 w = panel->sections[type];
1151 while (*w) {
1152 WMMapWidget(*w);
1153 w++;
1157 updateFrameTitle(panel, title, type);
1159 panel->currentType = type;
1165 static void
1166 updateMenuItem(_Panel *panel, WEditMenuItem *item, WMWidget *changedWidget)
1168 ItemData *data = WGetEditMenuItemData(item);
1170 assert(data != NULL);
1172 #define REPLACE(v, d) if (v) wfree(v); v = d
1174 switch (data->type) {
1175 case ExecInfo:
1176 if (changedWidget == panel->commandT) {
1177 REPLACE(data->param.exec.command,
1178 WMGetTextFieldText(panel->commandT));
1180 if (changedWidget == panel->shortT) {
1181 REPLACE(data->param.exec.shortcut,
1182 WMGetTextFieldText(panel->shortT));
1184 break;
1186 case CommandInfo:
1187 if (changedWidget == panel->icommandL) {
1188 data->param.command.command =
1189 WMGetListSelectedItemRow(panel->icommandL);
1191 switch (data->param.command.command) {
1192 case 3:
1193 case 4:
1194 if (changedWidget == panel->quickB) {
1195 REPLACE(data->param.command.parameter,
1196 WMGetButtonSelected(panel->quickB)
1197 ? wstrdup("QUICK") : NULL);
1199 break;
1201 case 6:
1202 if (changedWidget == panel->paramT) {
1203 REPLACE(data->param.command.parameter,
1204 WMGetTextFieldText(panel->paramT));
1206 break;
1208 if (changedWidget == panel->shortT) {
1209 REPLACE(data->param.command.shortcut,
1210 WMGetTextFieldText(panel->shortT));
1214 break;
1216 case PipeInfo:
1217 if (changedWidget == panel->pipeT) {
1218 REPLACE(data->param.pipe.command,
1219 WMGetTextFieldText(panel->pipeT));
1221 break;
1223 case ExternalInfo:
1224 if (changedWidget == panel->pathT) {
1225 REPLACE(data->param.external.path,
1226 WMGetTextFieldText(panel->pathT));
1228 break;
1230 case DirectoryInfo:
1231 if (changedWidget == panel->dpathT) {
1232 REPLACE(data->param.directory.directory,
1233 WMGetTextFieldText(panel->dpathT));
1235 if (changedWidget == panel->dcommandT) {
1236 REPLACE(data->param.directory.command,
1237 WMGetTextFieldText(panel->dcommandT));
1239 if (changedWidget == panel->dstripB) {
1240 data->param.directory.stripExt =
1241 WMGetButtonSelected(panel->dstripB);
1243 break;
1245 default:
1246 assert(0);
1247 break;
1250 #undef REPLACE
1255 static void
1256 menuItemCloned(WEditMenuDelegate *delegate, WEditMenu *menu,
1257 WEditMenuItem *origItem, WEditMenuItem *newItem)
1259 ItemData *data = WGetEditMenuItemData(origItem);
1260 ItemData *newData;
1262 if (!data)
1263 return;
1265 #define DUP(s) (s) ? wstrdup(s) : NULL
1267 newData = NEW(ItemData);
1269 newData->type = data->type;
1271 switch (data->type) {
1272 case ExecInfo:
1273 newData->param.exec.command = DUP(data->param.exec.command);
1274 newData->param.exec.shortcut = DUP(data->param.exec.shortcut);
1275 break;
1277 case CommandInfo:
1278 newData->param.command.command = data->param.command.command;
1279 newData->param.command.parameter = DUP(data->param.command.parameter);
1280 newData->param.command.shortcut = DUP(data->param.command.shortcut);
1281 break;
1283 case PipeInfo:
1284 newData->param.pipe.command = DUP(data->param.pipe.command);
1285 break;
1287 case ExternalInfo:
1288 newData->param.external.path = DUP(data->param.external.path);
1289 break;
1291 case DirectoryInfo:
1292 newData->param.directory.directory = DUP(data->param.directory.directory);
1293 newData->param.directory.command = DUP(data->param.directory.command);
1294 newData->param.directory.stripExt = data->param.directory.stripExt;
1295 break;
1297 default:
1298 break;
1301 #undef DUP
1303 WSetEditMenuItemData(newItem, newData, (WMCallback*)freeItemData);
1307 static void
1308 menuItemEdited(struct WEditMenuDelegate *delegate, WEditMenu *menu,
1309 WEditMenuItem *item)
1311 _Panel *panel = (_Panel*)delegate->data;
1312 WEditMenu *submenu;
1314 updateFrameTitle(panel, WGetEditMenuItemTitle(item), panel->currentType);
1316 submenu = WGetEditMenuSubmenu(menu, item);
1317 if (submenu) {
1318 WSetEditMenuTitle(submenu, WGetEditMenuItemTitle(item));
1323 static Bool
1324 shouldRemoveItem(struct WEditMenuDelegate *delegate, WEditMenu *menu,
1325 WEditMenuItem *item)
1327 _Panel *panel = (_Panel*)delegate->data;
1329 if (panel->dontAsk)
1330 return True;
1332 if (WGetEditMenuSubmenu(menu, item)) {
1333 int res;
1335 res = WMRunAlertPanel(WMWidgetScreen(menu), NULL,
1336 _("Remove Submenu"),
1337 _("Removing this item will destroy all items inside\n"
1338 "the submenu. Do you really want to do that?"),
1339 _("Yes"), _("No"),
1340 _("Yes, don't ask again."));
1341 switch (res) {
1342 case WAPRDefault:
1343 return True;
1344 case WAPRAlternate:
1345 return False;
1346 case WAPROther:
1347 panel->dontAsk = True;
1348 return True;
1351 return True;
1355 static void
1356 menuItemDeselected(WEditMenuDelegate *delegate, WEditMenu *menu,
1357 WEditMenuItem *item)
1359 _Panel *panel = (_Panel*)delegate->data;
1361 changeInfoType(panel, NULL, NoInfo);
1365 static void
1366 menuItemSelected(WEditMenuDelegate *delegate, WEditMenu *menu,
1367 WEditMenuItem *item)
1369 ItemData *data = WGetEditMenuItemData(item);
1370 _Panel *panel = (_Panel*)delegate->data;
1372 panel->currentItem = item;
1374 if (data) {
1375 changeInfoType(panel, WGetEditMenuItemTitle(item), data->type);
1377 switch (data->type) {
1378 case NoInfo:
1379 break;
1381 case ExecInfo:
1382 WMSetTextFieldText(panel->commandT, data->param.exec.command);
1383 WMSetTextFieldText(panel->shortT, data->param.exec.shortcut);
1384 break;
1386 case CommandInfo:
1387 WMSelectListItem(panel->icommandL,
1388 data->param.command.command);
1389 WMSetListPosition(panel->icommandL,
1390 data->param.command.command - 2);
1391 WMSetTextFieldText(panel->shortT, data->param.command.shortcut);
1393 switch (data->param.command.command) {
1394 case 3:
1395 case 4:
1396 WMSetButtonSelected(panel->quickB,
1397 data->param.command.parameter!=NULL);
1398 break;
1399 case 6:
1400 WMSetTextFieldText(panel->paramT,
1401 data->param.command.parameter);
1402 break;
1405 icommandLClicked(panel->icommandL, panel);
1406 break;
1408 case PipeInfo:
1409 WMSetTextFieldText(panel->pipeT, data->param.pipe.command);
1410 break;
1412 case ExternalInfo:
1413 WMSetTextFieldText(panel->pathT, data->param.external.path);
1414 break;
1416 case DirectoryInfo:
1417 WMSetTextFieldText(panel->dpathT, data->param.directory.directory);
1418 WMSetTextFieldText(panel->dcommandT, data->param.directory.command);
1419 WMSetButtonSelected(panel->dstripB, data->param.directory.stripExt);
1420 break;
1422 case WSMenuInfo:
1423 break;
1425 default:
1426 break;
1433 static WEditMenu*
1434 buildSubmenu(_Panel *panel, proplist_t pl)
1436 WMScreen *scr = WMWidgetScreen(panel->win);
1437 WEditMenu *menu;
1438 WEditMenuItem *item;
1439 char *title;
1440 proplist_t tp, bp;
1441 int i;
1443 tp = PLGetArrayElement(pl, 0);
1444 title = PLGetString(tp);
1446 menu = WCreateEditMenu(scr, title);
1448 for (i = 1; i < PLGetNumberOfElements(pl); i++) {
1449 proplist_t pi;
1451 pi = PLGetArrayElement(pl, i);
1453 tp = PLGetArrayElement(pi, 0);
1454 bp = PLGetArrayElement(pi, 1);
1456 title = PLGetString(tp);
1458 if (!bp || PLIsArray(bp)) { /* it's a submenu */
1459 WEditMenu *submenu;
1461 submenu = buildSubmenu(panel, pi);
1463 item = WAddMenuItemWithTitle(menu, title);
1465 WSetEditMenuSubmenu(menu, item, submenu);
1466 } else {
1467 ItemData *data;
1469 item = WAddMenuItemWithTitle(menu, title);
1471 data = parseCommand(pi);
1473 if (panel->markerPix[data->type])
1474 WSetEditMenuItemImage(item, panel->markerPix[data->type]);
1475 WSetEditMenuItemData(item, data, (WMCallback*)freeItemData);
1479 WSetEditMenuAcceptsDrop(menu, True);
1480 WSetEditMenuDelegate(menu, &menuDelegate);
1482 WMRealizeWidget(menu);
1484 return menu;
1489 static void
1490 buildMenuFromPL(_Panel *panel, proplist_t pl)
1492 panel->menu = buildSubmenu(panel, pl);
1497 static proplist_t
1498 getDefaultMenu(_Panel *panel)
1500 proplist_t menu, pmenu;
1501 char *menuPath, *gspath;
1503 gspath = wusergnusteppath();
1505 menuPath = wmalloc(strlen(gspath)+128);
1506 /* if there is a localized plmenu for the tongue put it's filename here */
1507 sprintf(menuPath, _("%s/Library/WindowMaker/plmenu"), gspath);
1509 menu = PLGetProplistWithPath(menuPath);
1510 if (!menu) {
1511 wwarning("%s:could not read property list menu", menuPath);
1513 if (strcmp("%s/Library/WindowMaker/plmenu",
1514 _("%s/Library/WindowMaker/plmenu"))!=0) {
1516 sprintf(menuPath, "%s/Library/WindowMaker/plmenu", gspath);
1517 menu = PLGetProplistWithPath(menuPath);
1518 wwarning("%s:could not read property list menu", menuPath);
1520 if (!menu) {
1521 char buffer[512];
1523 sprintf(buffer, _("Could not open default menu from '%s'"),
1524 menuPath);
1525 WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
1526 _("Error"), buffer, _("OK"), NULL, NULL);
1530 wfree(menuPath);
1532 if (menu) {
1533 pmenu = menu;
1534 } else {
1535 pmenu = NULL;
1538 return pmenu;
1542 static void
1543 showData(_Panel *panel)
1545 char *gspath;
1546 char *menuPath;
1547 proplist_t pmenu;
1549 gspath = wusergnusteppath();
1551 menuPath = wmalloc(strlen(gspath)+32);
1552 strcpy(menuPath, gspath);
1553 strcat(menuPath, "/Defaults/WMRootMenu");
1555 pmenu = PLGetProplistWithPath(menuPath);
1557 if (!pmenu || !PLIsArray(pmenu)) {
1558 int res;
1560 res = WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
1561 _("Warning"),
1562 _("The menu file format currently in use is not supported\n"
1563 "by this tool. Do you want to discard the current menu\n"
1564 "to use this tool?"),
1565 _("Yes, Discard and Update"),
1566 _("No, Keep Current Menu"), NULL);
1568 if (res == WAPRDefault) {
1569 pmenu = getDefaultMenu(panel);
1571 if (!pmenu) {
1572 pmenu = PLMakeArrayFromElements(PLMakeString("Applications"),
1573 NULL);
1575 } else {
1576 panel->dontSave = True;
1577 return;
1581 panel->menuPath = menuPath;
1583 buildMenuFromPL(panel, pmenu);
1585 PLRelease(pmenu);
1589 static Bool
1590 notblank(char *s)
1592 if (s) {
1593 while (*s++) {
1594 if (!isspace(*s))
1595 return True;
1598 return False;
1602 static proplist_t
1603 processData(char *title, ItemData *data)
1605 proplist_t item;
1606 char *s1;
1607 static char *pscut = NULL;
1608 static char *pomenu = NULL;
1609 int i;
1611 if (!pscut) {
1612 pscut = PLMakeString("SHORTCUT");
1613 pomenu = PLMakeString("OPEN_MENU");
1616 item = PLMakeArrayFromElements(PLMakeString(title), NULL);
1619 switch (data->type) {
1620 case ExecInfo:
1621 #if 1
1622 if (strpbrk(data->param.exec.command, "&$*|><?`=")) {
1623 s1 = "SHEXEC";
1624 } else {
1625 s1 = "EXEC";
1627 #else
1628 s1 = "SHEXEC";
1629 #endif
1631 if (notblank(data->param.exec.shortcut)) {
1632 PLAppendArrayElement(item, pscut);
1633 PLAppendArrayElement(item,
1634 PLMakeString(data->param.exec.shortcut));
1637 PLAppendArrayElement(item, PLMakeString(s1));
1638 PLAppendArrayElement(item, PLMakeString(data->param.exec.command));
1639 break;
1641 case CommandInfo:
1642 if (notblank(data->param.command.shortcut)) {
1643 PLAppendArrayElement(item, pscut);
1644 PLAppendArrayElement(item,
1645 PLMakeString(data->param.command.shortcut));
1648 i = data->param.command.command;
1650 PLAppendArrayElement(item, PLMakeString(commandNames[i]));
1652 switch (i) {
1653 case 3:
1654 case 4:
1655 if (data->param.command.parameter) {
1656 PLAppendArrayElement(item,
1657 PLMakeString(data->param.command.parameter));
1659 break;
1661 case 6: /* restart */
1662 if (data->param.command.parameter) {
1663 PLAppendArrayElement(item,
1664 PLMakeString(data->param.command.parameter));
1666 break;
1669 break;
1671 case PipeInfo:
1672 PLAppendArrayElement(item, pomenu);
1673 s1 = wstrconcat("| ", data->param.pipe.command);
1674 PLAppendArrayElement(item, PLMakeString(s1));
1675 wfree(s1);
1676 break;
1678 case ExternalInfo:
1679 PLAppendArrayElement(item, pomenu);
1680 PLAppendArrayElement(item, PLMakeString(data->param.external.path));
1681 break;
1683 case DirectoryInfo:
1685 int l;
1686 char *tmp;
1688 l = strlen(data->param.directory.directory);
1689 l += strlen(data->param.directory.command);
1690 l += 32;
1692 PLAppendArrayElement(item, pomenu);
1694 tmp = wmalloc(l);
1695 sprintf(tmp, "%s%s WITH %s",
1696 data->param.directory.stripExt ? "-noext " : "",
1697 data->param.directory.directory,
1698 data->param.directory.command);
1700 PLAppendArrayElement(item, PLMakeString(tmp));
1701 wfree(tmp);
1703 break;
1705 case WSMenuInfo:
1706 PLAppendArrayElement(item, PLMakeString("WORKSPACE_MENU"));
1707 break;
1709 default:
1710 assert(0);
1711 break;
1714 return item;
1718 static proplist_t
1719 processSubmenu(WEditMenu *menu)
1721 WEditMenuItem *item;
1722 proplist_t pmenu;
1723 proplist_t pl;
1724 char *s;
1725 int i;
1728 s = WGetEditMenuTitle(menu);
1729 pl = PLMakeString(s);
1731 pmenu = PLMakeArrayFromElements(pl, NULL);
1733 i = 0;
1734 while ((item = WGetEditMenuItem(menu, i++))) {
1735 WEditMenu *submenu;
1737 s = WGetEditMenuItemTitle(item);
1739 submenu = WGetEditMenuSubmenu(menu, item);
1740 if (submenu) {
1741 pl = processSubmenu(submenu);
1742 } else {
1743 pl = processData(s, WGetEditMenuItemData(item));
1746 PLAppendArrayElement(pmenu, pl);
1749 return pmenu;
1754 static proplist_t
1755 buildPLFromMenu(_Panel *panel)
1757 proplist_t menu;
1759 menu = processSubmenu(panel->menu);
1761 return menu;
1767 static void
1768 storeData(_Panel *panel)
1770 proplist_t menu;
1772 if (panel->dontSave)
1773 return;
1775 menu = buildPLFromMenu(panel);
1777 PLSetFilename(menu, PLMakeString(panel->menuPath));
1779 PLSave(menu, YES);
1781 PLRelease(menu);
1786 static void
1787 showMenus(_Panel *panel)
1789 WEditMenuUnhide(panel->menu);
1793 static void
1794 hideMenus(_Panel *panel)
1796 WEditMenuHide(panel->menu);
1802 Panel*
1803 InitMenu(WMScreen *scr, WMWindow *win)
1805 _Panel *panel;
1807 panel = wmalloc(sizeof(_Panel));
1808 memset(panel, 0, sizeof(_Panel));
1810 panel->sectionName = _("Applications Menu Definition");
1812 panel->description = _("Edit the menu for launching applications.");
1814 panel->win = win;
1816 panel->callbacks.createWidgets = createPanel;
1817 panel->callbacks.updateDomain = storeData;
1818 panel->callbacks.showPanel = showMenus;
1819 panel->callbacks.hidePanel = hideMenus;
1822 AddSection(panel, ICON_FILE);
1824 return panel;