adapted for SetViewExpands...
[wmaker-crm.git] / WPrefs.app / Menu.c
blob9f38b7770aa943a8ee31bb45a5d6138449b856fc
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, 0, 0);
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;
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 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(proplist_t item)
952 ItemData *data = NEW(ItemData);
953 proplist_t p;
954 char *command = NULL;
955 char *parameter = NULL;
956 char *shortcut = NULL;
957 int i = 1;
960 p = PLGetArrayElement(item, i++);
961 command = PLGetString(p);
962 if (strcmp(command, "SHORTCUT") == 0) {
963 p = PLGetArrayElement(item, i++);
964 shortcut = PLGetString(p);
965 p = PLGetArrayElement(item, i++);
966 command = PLGetString(p);
968 p = PLGetArrayElement(item, i++);
969 if (p)
970 parameter = PLGetString(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, proplist_t pl)
1443 WMScreen *scr = WMWidgetScreen(panel->parent);
1444 WEditMenu *menu;
1445 WEditMenuItem *item;
1446 char *title;
1447 proplist_t tp, bp;
1448 int i;
1450 tp = PLGetArrayElement(pl, 0);
1451 title = PLGetString(tp);
1453 menu = WCreateEditMenu(scr, title);
1455 for (i = 1; i < PLGetNumberOfElements(pl); i++) {
1456 proplist_t pi;
1458 pi = PLGetArrayElement(pl, i);
1460 tp = PLGetArrayElement(pi, 0);
1461 bp = PLGetArrayElement(pi, 1);
1463 title = PLGetString(tp);
1465 if (!bp || PLIsArray(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, proplist_t pl)
1499 panel->menu = buildSubmenu(panel, pl);
1504 static proplist_t
1505 getDefaultMenu(_Panel *panel)
1507 proplist_t 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 = PLGetProplistWithPath(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 = PLGetProplistWithPath(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 proplist_t pmenu;
1556 gspath = wusergnusteppath();
1558 menuPath = wmalloc(strlen(gspath)+32);
1559 strcpy(menuPath, gspath);
1560 strcat(menuPath, "/Defaults/WMRootMenu");
1562 pmenu = PLGetProplistWithPath(menuPath);
1564 if (!pmenu || !PLIsArray(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 = PLMakeArrayFromElements(PLMakeString("Applications"),
1580 NULL);
1582 } else {
1583 panel->dontSave = True;
1584 return;
1588 panel->menuPath = menuPath;
1590 buildMenuFromPL(panel, pmenu);
1592 PLRelease(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 proplist_t
1610 processData(char *title, ItemData *data)
1612 proplist_t item;
1613 char *s1;
1614 static char *pscut = NULL;
1615 static char *pomenu = NULL;
1616 int i;
1618 if (!pscut) {
1619 pscut = PLMakeString("SHORTCUT");
1620 pomenu = PLMakeString("OPEN_MENU");
1623 item = PLMakeArrayFromElements(PLMakeString(title), NULL);
1626 switch (data->type) {
1627 case ExecInfo:
1628 #if 1
1629 if (strpbrk(data->param.exec.command, "&$*|><?`=")) {
1630 s1 = "SHEXEC";
1631 } else {
1632 s1 = "EXEC";
1634 #else
1635 s1 = "SHEXEC";
1636 #endif
1638 if (notblank(data->param.exec.shortcut)) {
1639 PLAppendArrayElement(item, pscut);
1640 PLAppendArrayElement(item,
1641 PLMakeString(data->param.exec.shortcut));
1644 PLAppendArrayElement(item, PLMakeString(s1));
1645 PLAppendArrayElement(item, PLMakeString(data->param.exec.command));
1646 break;
1648 case CommandInfo:
1649 if (notblank(data->param.command.shortcut)) {
1650 PLAppendArrayElement(item, pscut);
1651 PLAppendArrayElement(item,
1652 PLMakeString(data->param.command.shortcut));
1655 i = data->param.command.command;
1657 PLAppendArrayElement(item, PLMakeString(commandNames[i]));
1659 switch (i) {
1660 case 3:
1661 case 4:
1662 if (data->param.command.parameter) {
1663 PLAppendArrayElement(item,
1664 PLMakeString(data->param.command.parameter));
1666 break;
1668 case 6: /* restart */
1669 if (data->param.command.parameter) {
1670 PLAppendArrayElement(item,
1671 PLMakeString(data->param.command.parameter));
1673 break;
1676 break;
1678 case PipeInfo:
1679 PLAppendArrayElement(item, pomenu);
1680 s1 = wstrconcat("| ", data->param.pipe.command);
1681 PLAppendArrayElement(item, PLMakeString(s1));
1682 wfree(s1);
1683 break;
1685 case ExternalInfo:
1686 PLAppendArrayElement(item, pomenu);
1687 PLAppendArrayElement(item, PLMakeString(data->param.external.path));
1688 break;
1690 case DirectoryInfo:
1692 int l;
1693 char *tmp;
1695 l = strlen(data->param.directory.directory);
1696 l += strlen(data->param.directory.command);
1697 l += 32;
1699 PLAppendArrayElement(item, pomenu);
1701 tmp = wmalloc(l);
1702 sprintf(tmp, "%s%s WITH %s",
1703 data->param.directory.stripExt ? "-noext " : "",
1704 data->param.directory.directory,
1705 data->param.directory.command);
1707 PLAppendArrayElement(item, PLMakeString(tmp));
1708 wfree(tmp);
1710 break;
1712 case WSMenuInfo:
1713 PLAppendArrayElement(item, PLMakeString("WORKSPACE_MENU"));
1714 break;
1716 case WWindowListInfo:
1717 PLAppendArrayElement(item, PLMakeString("WINDOWS_MENU"));
1718 break;
1720 default:
1721 assert(0);
1722 break;
1725 return item;
1729 static proplist_t
1730 processSubmenu(WEditMenu *menu)
1732 WEditMenuItem *item;
1733 proplist_t pmenu;
1734 proplist_t pl;
1735 char *s;
1736 int i;
1739 s = WGetEditMenuTitle(menu);
1740 pl = PLMakeString(s);
1742 pmenu = PLMakeArrayFromElements(pl, NULL);
1744 i = 0;
1745 while ((item = WGetEditMenuItem(menu, i++))) {
1746 WEditMenu *submenu;
1748 s = WGetEditMenuItemTitle(item);
1750 submenu = WGetEditMenuSubmenu(menu, item);
1751 if (submenu) {
1752 pl = processSubmenu(submenu);
1753 } else {
1754 pl = processData(s, WGetEditMenuItemData(item));
1757 PLAppendArrayElement(pmenu, pl);
1760 return pmenu;
1765 static proplist_t
1766 buildPLFromMenu(_Panel *panel)
1768 proplist_t menu;
1770 menu = processSubmenu(panel->menu);
1772 return menu;
1778 static void
1779 storeData(_Panel *panel)
1781 proplist_t menu;
1783 if (panel->dontSave)
1784 return;
1786 menu = buildPLFromMenu(panel);
1788 PLSetFilename(menu, PLMakeString(panel->menuPath));
1790 PLSave(menu, YES);
1792 PLRelease(menu);
1797 static void
1798 showMenus(_Panel *panel)
1800 WEditMenuUnhide(panel->menu);
1804 static void
1805 hideMenus(_Panel *panel)
1807 WEditMenuHide(panel->menu);
1813 Panel*
1814 InitMenu(WMScreen *scr, WMWidget *parent)
1816 _Panel *panel;
1818 panel = wmalloc(sizeof(_Panel));
1819 memset(panel, 0, sizeof(_Panel));
1821 panel->sectionName = _("Applications Menu Definition");
1823 panel->description = _("Edit the menu for launching applications.");
1825 panel->parent = parent;
1827 panel->callbacks.createWidgets = createPanel;
1828 panel->callbacks.updateDomain = storeData;
1829 panel->callbacks.showPanel = showMenus;
1830 panel->callbacks.hidePanel = hideMenus;
1833 AddSection(panel, ICON_FILE);
1835 return panel;