1f00d53685e26954cc553398e8338e8b2e1444f4
[wmaker-crm.git] / WPrefs.app / Menu.c
blob1f00d53685e26954cc553398e8338e8b2e1444f4
1 /* Menu.c- menu definition
3 * WPrefs - Window Maker Preferences Program
5 * Copyright (c) 2000-2003 Alfredo K. Kojima
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 along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include "WPrefs.h"
23 #include <assert.h>
24 #include <ctype.h>
26 #include <X11/keysym.h>
27 #include <X11/cursorfont.h>
29 #include "editmenu.h"
31 typedef enum {
32 NoInfo,
33 ExecInfo,
34 CommandInfo,
35 ExternalInfo,
36 PipeInfo,
37 PLPipeInfo,
38 DirectoryInfo,
39 WSMenuInfo,
40 WWindowListInfo,
41 LastInfo
42 } InfoType;
44 #define MAX_SECTION_SIZE 4
45 #define PATH_LEN 256
47 typedef struct _Panel {
48 WMBox *box;
49 char *sectionName;
51 char *description;
53 CallbackRec callbacks;
54 WMWidget *parent;
56 WMFont *boldFont;
57 WMFont *normalFont;
58 WMColor *white;
59 WMColor *gray;
60 WMColor *black;
62 WMPixmap *markerPix[LastInfo];
64 WMPopUpButton *typeP;
66 WMWidget *itemPad[3];
67 int currentPad;
69 WEditMenu *menu;
70 char *menuPath;
72 WMFrame *optionsF;
74 WMFrame *commandF;
75 WMTextField *commandT; /* command to run */
76 WMButton *browseB;
77 WMButton *xtermC; /* inside xterm? */
79 WMFrame *pathF;
80 WMTextField *pathT;
82 WMFrame *pipeF;
83 WMTextField *pipeT;
84 WMButton *pipeCacheB;
86 WMFrame *plpipeF;
87 WMTextField *plpipeT;
88 WMButton *plpipeCacheB;
90 WMFrame *dpathF;
91 WMTextField *dpathT;
93 WMFrame *dcommandF;
94 WMTextField *dcommandT;
96 WMButton *dstripB;
98 WMFrame *shortF;
99 WMTextField *shortT;
100 WMButton *sgrabB;
101 WMButton *sclearB;
103 WMList *icommandL;
105 WMFrame *paramF;
106 WMTextField *paramT;
108 WMButton *quickB;
110 Bool dontAsk; /* whether to comfirm submenu remove */
111 Bool dontSave;
113 Bool capturing;
115 /* about the currently selected item */
116 WEditMenuItem *currentItem;
117 InfoType currentType;
118 WMWidget *sections[LastInfo][MAX_SECTION_SIZE];
119 } _Panel;
121 typedef struct {
122 InfoType type;
123 union {
124 struct {
125 int command;
126 char *parameter;
127 char *shortcut;
128 } command;
129 struct {
130 char *command;
131 char *shortcut;
132 } exec;
133 struct {
134 char *path;
135 } external;
136 struct {
137 char *command;
138 unsigned cached:1;
139 } pipe;
140 struct {
141 char *directory;
142 char *command;
143 unsigned stripExt:1;
144 } directory;
145 } param;
146 } 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"
163 #define ICON_FILE "menus"
165 static void showData(_Panel * panel);
167 static void updateMenuItem(_Panel * panel, WEditMenuItem * item, WMWidget * changedWidget);
169 static void menuItemSelected(struct WEditMenuDelegate *delegate, WEditMenu * menu, WEditMenuItem * item);
171 static void menuItemDeselected(struct WEditMenuDelegate *delegate, WEditMenu * menu, WEditMenuItem * item);
173 static void menuItemCloned(struct WEditMenuDelegate *delegate, WEditMenu * menu,
174 WEditMenuItem * origItem, WEditMenuItem * newItem);
176 static void menuItemEdited(struct WEditMenuDelegate *delegate, WEditMenu * menu, WEditMenuItem * item);
178 static Bool shouldRemoveItem(struct WEditMenuDelegate *delegate, WEditMenu * menu, WEditMenuItem * item);
180 static void freeItemData(ItemData * data);
182 extern char *capture_shortcut(Display *dpy, Bool *capturing, Bool convert_case);
184 static WEditMenuDelegate menuDelegate = {
185 NULL,
186 menuItemCloned,
187 menuItemEdited,
188 menuItemSelected,
189 menuItemDeselected,
190 shouldRemoveItem
193 static void dataChanged(void *self, WMNotification * notif)
195 _Panel *panel = (_Panel *) self;
196 WEditMenuItem *item = panel->currentItem;
197 WMWidget *w = (WMWidget *) WMGetNotificationObject(notif);
199 updateMenuItem(panel, item, w);
202 static void buttonClicked(WMWidget * w, void *data)
204 _Panel *panel = (_Panel *) data;
205 WEditMenuItem *item = panel->currentItem;
207 updateMenuItem(panel, item, w);
210 static void icommandLClicked(WMWidget * w, void *data)
212 _Panel *panel = (_Panel *) data;
213 int cmd;
215 cmd = WMGetListSelectedItemRow(w);
216 if (cmd == 3 || cmd == 4) {
217 WMMapWidget(panel->quickB);
218 } else {
219 WMUnmapWidget(panel->quickB);
221 if (cmd == 6) {
222 WMMapWidget(panel->paramF);
223 } else {
224 WMUnmapWidget(panel->paramF);
228 static void browseForFile(WMWidget * self, void *clientData)
230 _Panel *panel = (_Panel *) clientData;
231 WMFilePanel *filePanel;
232 char *text, *oldprog, *newprog;
234 filePanel = WMGetOpenPanel(WMWidgetScreen(self));
235 text = WMGetTextFieldText(panel->commandT);
237 oldprog = wtrimspace(text);
238 wfree(text);
240 if (oldprog[0] == 0 || oldprog[0] != '/') {
241 wfree(oldprog);
242 oldprog = wstrdup("/");
243 } else {
244 char *ptr = oldprog;
245 while (*ptr && !isspace(*ptr))
246 ptr++;
247 *ptr = 0;
250 WMSetFilePanelCanChooseDirectories(filePanel, False);
252 if (WMRunModalFilePanelForDirectory(filePanel, panel->parent, oldprog, _("Select Program"), NULL) == True) {
253 newprog = WMGetFilePanelFileName(filePanel);
254 WMSetTextFieldText(panel->commandT, newprog);
255 updateMenuItem(panel, panel->currentItem, panel->commandT);
256 wfree(newprog);
259 wfree(oldprog);
262 static void sgrabClicked(WMWidget * w, void *data)
264 _Panel *panel = (_Panel *) data;
265 Display *dpy = WMScreenDisplay(WMWidgetScreen(panel->parent));
266 char *shortcut;
268 if (w == panel->sclearB) {
269 WMSetTextFieldText(panel->shortT, "");
270 updateMenuItem(panel, panel->currentItem, panel->shortT);
271 return;
274 if (!panel->capturing) {
275 panel->capturing = 1;
276 WMSetButtonText(w, _("Cancel"));
277 XGrabKeyboard(dpy, WMWidgetXID(panel->parent), True, GrabModeAsync, GrabModeAsync, CurrentTime);
278 shortcut = capture_shortcut(dpy, &panel->capturing, 0);
279 if (shortcut) {
280 WMSetTextFieldText(panel->shortT, shortcut);
281 updateMenuItem(panel, panel->currentItem, panel->shortT);
282 wfree(shortcut);
285 panel->capturing = 0;
286 WMSetButtonText(w, _("Capture"));
287 XUngrabKeyboard(dpy, CurrentTime);
290 static void changedItemPad(WMWidget * w, void *data)
292 _Panel *panel = (_Panel *) data;
293 int padn = WMGetPopUpButtonSelectedItem(w);
295 WMUnmapWidget(panel->itemPad[panel->currentPad]);
296 WMMapWidget(panel->itemPad[padn]);
298 panel->currentPad = padn;
301 static WEditMenu *putNewSubmenu(WEditMenu * menu, const char *title)
303 WEditMenu *tmp;
304 WEditMenuItem *item;
306 item = WAddMenuItemWithTitle(menu, title);
308 tmp = WCreateEditMenu(WMWidgetScreen(menu), title);
309 WSetEditMenuAcceptsDrop(tmp, True);
310 WSetEditMenuDelegate(tmp, &menuDelegate);
311 WSetEditMenuSubmenu(menu, item, tmp);
313 return tmp;
316 static ItemData *putNewItem(_Panel * panel, WEditMenu * menu, int type, const char *title)
318 WEditMenuItem *item;
319 ItemData *data;
321 item = WAddMenuItemWithTitle(menu, title);
323 data = wmalloc(sizeof(ItemData));
324 data->type = type;
325 WSetEditMenuItemData(item, data, (WMCallback *) freeItemData);
326 WSetEditMenuItemImage(item, panel->markerPix[type]);
328 return data;
331 static WEditMenu *makeFactoryMenu(WMWidget * parent, int width)
333 WEditMenu *pad;
335 pad = WCreateEditMenuPad(parent);
336 WMResizeWidget(pad, width, 10);
337 WSetEditMenuMinSize(pad, wmksize(width, 0));
338 WSetEditMenuMaxSize(pad, wmksize(width, 0));
339 WSetEditMenuSelectable(pad, False);
340 WSetEditMenuEditable(pad, False);
341 WSetEditMenuIsFactory(pad, True);
342 WSetEditMenuDelegate(pad, &menuDelegate);
344 return pad;
347 static void createPanel(_Panel * p)
349 _Panel *panel = (_Panel *) p;
350 WMScreen *scr = WMWidgetScreen(panel->parent);
351 WMColor *black = WMBlackColor(scr);
352 WMColor *white = WMWhiteColor(scr);
353 WMColor *gray = WMGrayColor(scr);
354 WMFont *bold = WMBoldSystemFontOfSize(scr, 12);
355 WMFont *font = WMSystemFontOfSize(scr, 12);
356 WMLabel *label;
357 int width;
359 menuDelegate.data = panel;
361 panel->boldFont = bold;
362 panel->normalFont = font;
364 panel->black = black;
365 panel->white = white;
366 panel->gray = gray;
369 Pixmap pix;
370 Display *dpy = WMScreenDisplay(scr);
371 GC gc;
372 WMPixmap *pixm;
374 pixm = WMCreatePixmap(scr, 7, 7, WMScreenDepth(scr), True);
376 pix = WMGetPixmapXID(pixm);
378 XDrawLine(dpy, pix, WMColorGC(black), 0, 3, 6, 3);
379 XDrawLine(dpy, pix, WMColorGC(black), 3, 0, 3, 6);
381 XDrawLine(dpy, pix, WMColorGC(black), 1, 0, 3, 3);
382 XDrawLine(dpy, pix, WMColorGC(black), 1, 6, 3, 3);
383 XDrawLine(dpy, pix, WMColorGC(black), 0, 0, 0, 6);
386 pix = WMGetPixmapMaskXID(pixm);
388 gc = XCreateGC(dpy, pix, 0, NULL);
390 XSetForeground(dpy, gc, 0);
391 XFillRectangle(dpy, pix, gc, 0, 0, 7, 7);
393 XSetForeground(dpy, gc, 1);
394 XDrawLine(dpy, pix, gc, 0, 3, 6, 3);
395 XDrawLine(dpy, pix, gc, 3, 0, 3, 6);
397 panel->markerPix[ExternalInfo] = pixm;
398 panel->markerPix[PipeInfo] = pixm;
399 panel->markerPix[PLPipeInfo] = pixm;
400 panel->markerPix[DirectoryInfo] = pixm;
401 panel->markerPix[WSMenuInfo] = pixm;
402 panel->markerPix[WWindowListInfo] = pixm;
404 XFreeGC(dpy, gc);
407 panel->box = WMCreateBox(panel->parent);
408 WMSetViewExpandsToParent(WMWidgetView(panel->box), 2, 2, 2, 2);
410 panel->typeP = WMCreatePopUpButton(panel->box);
411 WMResizeWidget(panel->typeP, 150, 20);
412 WMMoveWidget(panel->typeP, 10, 10);
414 WMAddPopUpButtonItem(panel->typeP, _("New Items"));
415 WMAddPopUpButtonItem(panel->typeP, _("Sample Commands"));
416 WMAddPopUpButtonItem(panel->typeP, _("Sample Submenus"));
418 WMSetPopUpButtonAction(panel->typeP, changedItemPad, panel);
420 WMSetPopUpButtonSelectedItem(panel->typeP, 0);
423 WEditMenu *pad;
425 pad = makeFactoryMenu(panel->box, 150);
426 WMMoveWidget(pad, 10, 40);
428 putNewItem(panel, pad, ExecInfo, _("Run Program"));
429 putNewItem(panel, pad, CommandInfo, _("Internal Command"));
430 putNewSubmenu(pad, _("Submenu"));
431 putNewItem(panel, pad, ExternalInfo, _("External Submenu"));
432 putNewItem(panel, pad, PipeInfo, _("Generated Submenu"));
433 putNewItem(panel, pad, PLPipeInfo, _("Generated PL Menu"));
434 putNewItem(panel, pad, DirectoryInfo, _("Directory Contents"));
435 putNewItem(panel, pad, WSMenuInfo, _("Workspace Menu"));
436 putNewItem(panel, pad, WWindowListInfo, _("Window List Menu"));
438 panel->itemPad[0] = pad;
442 WEditMenu *pad;
443 ItemData *data;
444 WMScrollView *sview;
446 sview = WMCreateScrollView(panel->box);
447 WMResizeWidget(sview, 150, 180);
448 WMMoveWidget(sview, 10, 40);
449 WMSetScrollViewHasVerticalScroller(sview, True);
451 pad = makeFactoryMenu(panel->box, 130);
453 WMSetScrollViewContentView(sview, WMWidgetView(pad));
455 data = putNewItem(panel, pad, ExecInfo, _("XTerm"));
456 data->param.exec.command = "xterm -sb -sl 2000 -bg black -fg white";
458 data = putNewItem(panel, pad, ExecInfo, _("rxvt"));
459 data->param.exec.command = "rxvt";
461 data = putNewItem(panel, pad, ExecInfo, _("ETerm"));
462 data->param.exec.command = "eterm";
464 data = putNewItem(panel, pad, ExecInfo, _("Run..."));
465 data->param.exec.command = _("%A(Run,Type command to run)");
467 data = putNewItem(panel, pad, ExecInfo, _("Firefox"));
468 data->param.exec.command = "firefox";
470 data = putNewItem(panel, pad, ExecInfo, _("gimp"));
471 data->param.exec.command = "gimp";
473 data = putNewItem(panel, pad, ExecInfo, _("epic"));
474 data->param.exec.command = "xterm -e epic";
476 data = putNewItem(panel, pad, ExecInfo, _("ee"));
477 data->param.exec.command = "ee";
479 data = putNewItem(panel, pad, ExecInfo, _("xv"));
480 data->param.exec.command = "xv";
482 data = putNewItem(panel, pad, ExecInfo, _("Evince"));
483 data->param.exec.command = "evince";
485 data = putNewItem(panel, pad, ExecInfo, _("ghostview"));
486 data->param.exec.command = "gv";
488 data = putNewItem(panel, pad, CommandInfo, _("Exit Window Maker"));
489 data->param.command.command = 3;
491 WMMapWidget(pad);
493 panel->itemPad[1] = sview;
497 WEditMenu *pad, *smenu;
498 ItemData *data;
499 WMScrollView *sview;
501 sview = WMCreateScrollView(panel->box);
502 WMResizeWidget(sview, 150, 180);
503 WMMoveWidget(sview, 10, 40);
504 WMSetScrollViewHasVerticalScroller(sview, True);
506 pad = makeFactoryMenu(panel->box, 130);
508 WMSetScrollViewContentView(sview, WMWidgetView(pad));
510 data = putNewItem(panel, pad, ExternalInfo, _("Debian Menu"));
511 data->param.pipe.command = "/etc/X11/WindowMaker/menu.hook";
513 data = putNewItem(panel, pad, PipeInfo, _("RedHat Menu"));
514 data->param.pipe.command = "wmconfig --output wmaker";
516 data = putNewItem(panel, pad, PipeInfo, _("Menu Conectiva"));
517 data->param.pipe.command = "wmconfig --output wmaker";
519 data = putNewItem(panel, pad, DirectoryInfo, _("Themes"));
520 data->param.directory.command = "setstyle";
521 data->param.directory.directory =
522 "/usr/share/WindowMaker/Themes /usr/local/share/WindowMaker/Themes $HOME/GNUstep/Library/WindowMaker/Themes";
523 data->param.directory.stripExt = 1;
525 data = putNewItem(panel, pad, DirectoryInfo, _("Bg Images (scale)"));
526 data->param.directory.command = "wmsetbg -u -s";
527 data->param.directory.directory =
528 "/opt/kde2/share/wallpapers /usr/share/WindowMaker/Backgrounds $HOME/GNUstep/Library/WindowMaker/Backgrounds";
529 data->param.directory.stripExt = 1;
531 data = putNewItem(panel, pad, DirectoryInfo, _("Bg Images (tile)"));
532 data->param.directory.command = "wmsetbg -u -t";
533 data->param.directory.directory =
534 "/opt/kde2/share/wallpapers /usr/share/WindowMaker/Backgrounds $HOME/GNUstep/Library/WindowMaker/Backgrounds";
535 data->param.directory.stripExt = 1;
537 smenu = putNewSubmenu(pad, _("Assorted XTerms"));
539 data = putNewItem(panel, smenu, ExecInfo, _("XTerm Yellow on Blue"));
540 data->param.exec.command = "xterm -sb -sl 2000 -bg midnightblue -fg yellow";
542 data = putNewItem(panel, smenu, ExecInfo, _("XTerm White on Black"));
543 data->param.exec.command = "xterm -sb -sl 2000 -bg black -fg white";
545 data = putNewItem(panel, smenu, ExecInfo, _("XTerm Black on White"));
546 data->param.exec.command = "xterm -sb -sl 2000 -bg white -fg black";
548 data = putNewItem(panel, smenu, ExecInfo, _("XTerm Black on Beige"));
549 data->param.exec.command = "xterm -sb -sl 2000 -bg '#bbbb99' -fg black";
551 data = putNewItem(panel, smenu, ExecInfo, _("XTerm White on Green"));
552 data->param.exec.command = "xterm -sb -sl 2000 -bg '#228822' -fg white";
554 data = putNewItem(panel, smenu, ExecInfo, _("XTerm White on Olive"));
555 data->param.exec.command = "xterm -sb -sl 2000 -bg '#335533' -fg white";
557 data = putNewItem(panel, smenu, ExecInfo, _("XTerm Blue on Blue"));
558 data->param.exec.command = "xterm -sb -sl 2000 -bg '#112244' -fg '#88aabb'";
560 data = putNewItem(panel, smenu, ExecInfo, _("XTerm BIG FONTS"));
561 data->param.exec.command = "xterm -sb -sl 2000 -bg black -fg white -fn 10x20";
563 WMMapWidget(pad);
565 panel->itemPad[2] = sview;
568 width = FRAME_WIDTH - 20 - 150 - 10 - 2;
570 panel->optionsF = WMCreateFrame(panel->box);
571 WMResizeWidget(panel->optionsF, width, FRAME_HEIGHT - 15);
572 WMMoveWidget(panel->optionsF, 10 + 150 + 10, 5);
574 width -= 20;
576 /* command */
578 panel->commandF = WMCreateFrame(panel->optionsF);
579 WMResizeWidget(panel->commandF, width, 50);
580 WMMoveWidget(panel->commandF, 10, 20);
581 WMSetFrameTitle(panel->commandF, _("Program to Run"));
582 WMSetFrameTitlePosition(panel->commandF, WTPAtTop);
584 panel->commandT = WMCreateTextField(panel->commandF);
585 WMResizeWidget(panel->commandT, width - 95, 20);
586 WMMoveWidget(panel->commandT, 10, 20);
588 panel->browseB = WMCreateCommandButton(panel->commandF);
589 WMResizeWidget(panel->browseB, 70, 24);
590 WMMoveWidget(panel->browseB, width - 80, 18);
591 WMSetButtonText(panel->browseB, _("Browse"));
592 WMSetButtonAction(panel->browseB, browseForFile, panel);
594 WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->commandT);
596 #if 0
597 panel->xtermC = WMCreateSwitchButton(panel->commandF);
598 WMResizeWidget(panel->xtermC, width - 20, 20);
599 WMMoveWidget(panel->xtermC, 10, 50);
600 WMSetButtonText(panel->xtermC, _("Run the program inside a Xterm"));
601 #endif
602 WMMapSubwidgets(panel->commandF);
604 /* path */
606 panel->pathF = WMCreateFrame(panel->optionsF);
607 WMResizeWidget(panel->pathF, width, 150);
608 WMMoveWidget(panel->pathF, 10, 40);
609 WMSetFrameTitle(panel->pathF, _("Path for Menu"));
611 panel->pathT = WMCreateTextField(panel->pathF);
612 WMResizeWidget(panel->pathT, width - 20, 20);
613 WMMoveWidget(panel->pathT, 10, 20);
615 WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->pathT);
617 label = WMCreateLabel(panel->pathF);
618 WMResizeWidget(label, width - 20, 80);
619 WMMoveWidget(label, 10, 50);
620 WMSetLabelText(label, _("Enter the path for a file containing a menu\n"
621 "or a list of directories with the programs you\n"
622 "want to have listed in the menu. Ex:\n"
623 "~/GNUstep/Library/WindowMaker/menu\n" "or\n" "/usr/bin ~/xbin"));
625 WMMapSubwidgets(panel->pathF);
627 /* pipe */
629 panel->pipeF = WMCreateFrame(panel->optionsF);
630 WMResizeWidget(panel->pipeF, width, 155);
631 WMMoveWidget(panel->pipeF, 10, 30);
632 WMSetFrameTitle(panel->pipeF, _("Command"));
634 panel->pipeT = WMCreateTextField(panel->pipeF);
635 WMResizeWidget(panel->pipeT, width - 20, 20);
636 WMMoveWidget(panel->pipeT, 10, 20);
638 WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->pipeT);
640 label = WMCreateLabel(panel->pipeF);
641 WMResizeWidget(label, width - 20, 40);
642 WMMoveWidget(label, 10, 50);
643 WMSetLabelText(label, _("Enter a command that outputs a menu\n" "definition to stdout when invoked."));
645 panel->pipeCacheB = WMCreateSwitchButton(panel->pipeF);
646 WMResizeWidget(panel->pipeCacheB, width - 20, 40);
647 WMMoveWidget(panel->pipeCacheB, 10, 110);
648 WMSetButtonText(panel->pipeCacheB, _("Cache menu contents after opening for\n" "the first time"));
650 WMMapSubwidgets(panel->pipeF);
652 /* proplist pipe */
654 panel->plpipeF = WMCreateFrame(panel->optionsF);
655 WMResizeWidget(panel->plpipeF, width, 155);
656 WMMoveWidget(panel->plpipeF, 10, 30);
657 WMSetFrameTitle(panel->plpipeF, _("Command"));
659 panel->plpipeT = WMCreateTextField(panel->plpipeF);
660 WMResizeWidget(panel->plpipeT, width - 20, 20);
661 WMMoveWidget(panel->plpipeT, 10, 20);
663 WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->plpipeT);
665 label = WMCreateLabel(panel->plpipeF);
666 WMResizeWidget(label, width - 20, 40);
667 WMMoveWidget(label, 10, 50);
668 WMSetLabelText(label, _("Enter a command that outputs a proplist menu\n" "definition to stdout when invoked."));
670 panel->plpipeCacheB = WMCreateSwitchButton(panel->plpipeF);
671 WMResizeWidget(panel->plpipeCacheB, width - 20, 40);
672 WMMoveWidget(panel->plpipeCacheB, 10, 110);
673 WMSetButtonText(panel->plpipeCacheB, _("Cache menu contents after opening for\n" "the first time"));
675 WMMapSubwidgets(panel->plpipeF);
677 /* directory menu */
679 panel->dcommandF = WMCreateFrame(panel->optionsF);
680 WMResizeWidget(panel->dcommandF, width, 90);
681 WMMoveWidget(panel->dcommandF, 10, 25);
682 WMSetFrameTitle(panel->dcommandF, _("Command to Open Files"));
684 panel->dcommandT = WMCreateTextField(panel->dcommandF);
685 WMResizeWidget(panel->dcommandT, width - 20, 20);
686 WMMoveWidget(panel->dcommandT, 10, 20);
688 WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->dcommandT);
690 label = WMCreateLabel(panel->dcommandF);
691 WMResizeWidget(label, width - 20, 45);
692 WMMoveWidget(label, 10, 40);
693 WMSetLabelText(label, _("Enter the command you want to use to open the\n"
694 "files in the directories listed below."));
696 WMMapSubwidgets(panel->dcommandF);
698 panel->dpathF = WMCreateFrame(panel->optionsF);
699 WMResizeWidget(panel->dpathF, width, 80);
700 WMMoveWidget(panel->dpathF, 10, 125);
701 WMSetFrameTitle(panel->dpathF, _("Directories with Files"));
703 panel->dpathT = WMCreateTextField(panel->dpathF);
704 WMResizeWidget(panel->dpathT, width - 20, 20);
705 WMMoveWidget(panel->dpathT, 10, 20);
707 WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->dpathT);
709 panel->dstripB = WMCreateSwitchButton(panel->dpathF);
710 WMResizeWidget(panel->dstripB, width - 20, 20);
711 WMMoveWidget(panel->dstripB, 10, 50);
712 WMSetButtonText(panel->dstripB, _("Strip extensions from file names"));
714 WMSetButtonAction(panel->dstripB, buttonClicked, panel);
716 WMMapSubwidgets(panel->dpathF);
718 /* shortcut */
720 panel->shortF = WMCreateFrame(panel->optionsF);
721 WMResizeWidget(panel->shortF, width, 50);
722 WMMoveWidget(panel->shortF, 10, 160);
723 WMSetFrameTitle(panel->shortF, _("Keyboard Shortcut"));
725 panel->shortT = WMCreateTextField(panel->shortF);
726 WMResizeWidget(panel->shortT, width - 20 - 150, 20);
727 WMMoveWidget(panel->shortT, 10, 20);
729 WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->shortT);
731 panel->sgrabB = WMCreateCommandButton(panel->shortF);
732 WMResizeWidget(panel->sgrabB, 70, 24);
733 WMMoveWidget(panel->sgrabB, width - 80, 18);
734 WMSetButtonText(panel->sgrabB, _("Capture"));
735 WMSetButtonAction(panel->sgrabB, sgrabClicked, panel);
737 panel->sclearB = WMCreateCommandButton(panel->shortF);
738 WMResizeWidget(panel->sclearB, 70, 24);
739 WMMoveWidget(panel->sclearB, width - 155, 18);
740 WMSetButtonText(panel->sclearB, _("Clear"));
741 WMSetButtonAction(panel->sclearB, sgrabClicked, panel);
743 WMMapSubwidgets(panel->shortF);
745 /* internal command */
747 panel->icommandL = WMCreateList(panel->optionsF);
748 WMResizeWidget(panel->icommandL, width, 80);
749 WMMoveWidget(panel->icommandL, 10, 20);
751 WMSetListAction(panel->icommandL, icommandLClicked, panel);
753 WMAddNotificationObserver(dataChanged, panel, WMListSelectionDidChangeNotification, panel->icommandL);
755 WMInsertListItem(panel->icommandL, 0, _("Arrange Icons"));
756 WMInsertListItem(panel->icommandL, 1, _("Hide All Windows Except For The Focused One"));
757 WMInsertListItem(panel->icommandL, 2, _("Show All Windows"));
759 WMInsertListItem(panel->icommandL, 3, _("Exit Window Maker"));
760 WMInsertListItem(panel->icommandL, 4, _("Exit X Session"));
761 WMInsertListItem(panel->icommandL, 5, _("Restart Window Maker"));
762 WMInsertListItem(panel->icommandL, 6, _("Start Another Window Manager : ("));
764 WMInsertListItem(panel->icommandL, 7, _("Save Current Session"));
765 WMInsertListItem(panel->icommandL, 8, _("Clear Saved Session"));
766 WMInsertListItem(panel->icommandL, 9, _("Refresh Screen"));
767 WMInsertListItem(panel->icommandL, 10, _("Open Info Panel"));
768 WMInsertListItem(panel->icommandL, 11, _("Open Copyright Panel"));
770 panel->paramF = WMCreateFrame(panel->optionsF);
771 WMResizeWidget(panel->paramF, width, 50);
772 WMMoveWidget(panel->paramF, 10, 105);
773 WMSetFrameTitle(panel->paramF, _("Window Manager to Start"));
775 panel->paramT = WMCreateTextField(panel->paramF);
776 WMResizeWidget(panel->paramT, width - 20, 20);
777 WMMoveWidget(panel->paramT, 10, 20);
779 WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->paramT);
781 WMMapSubwidgets(panel->paramF);
783 panel->quickB = WMCreateSwitchButton(panel->optionsF);
784 WMResizeWidget(panel->quickB, width, 20);
785 WMMoveWidget(panel->quickB, 10, 120);
786 WMSetButtonText(panel->quickB, _("Do not confirm action."));
787 WMSetButtonAction(panel->quickB, buttonClicked, panel);
789 label = WMCreateLabel(panel->optionsF);
790 WMResizeWidget(label, width + 5, FRAME_HEIGHT - 50);
791 WMMoveWidget(label, 7, 20);
792 WMSetLabelText(label,
793 _("Instructions:\n\n"
794 " - drag items from the left to the menu to add new items\n"
795 " - drag items out of the menu to remove items\n"
796 " - drag items in menu to change their position\n"
797 " - drag items with Control pressed to copy them\n"
798 " - double click in a menu item to change the label\n"
799 " - click on a menu item to change related information"));
800 WMMapWidget(label);
802 WMRealizeWidget(panel->box);
803 WMMapSubwidgets(panel->box);
804 WMMapWidget(panel->box);
807 int i;
808 for (i = 0; i < 3; i++)
809 WMUnmapWidget(panel->itemPad[i]);
811 changedItemPad(panel->typeP, panel);
813 panel->sections[NoInfo][0] = label;
815 panel->sections[ExecInfo][0] = panel->commandF;
816 panel->sections[ExecInfo][1] = panel->shortF;
818 panel->sections[CommandInfo][0] = panel->icommandL;
819 panel->sections[CommandInfo][1] = panel->shortF;
821 panel->sections[ExternalInfo][0] = panel->pathF;
823 panel->sections[PipeInfo][0] = panel->pipeF;
825 panel->sections[PLPipeInfo][0] = panel->plpipeF;
827 panel->sections[DirectoryInfo][0] = panel->dpathF;
828 panel->sections[DirectoryInfo][1] = panel->dcommandF;
830 panel->currentType = NoInfo;
832 showData(panel);
835 WMPoint pos;
837 pos = WMGetViewScreenPosition(WMWidgetView(panel->box));
839 if (pos.x < 200) {
840 pos.x += FRAME_WIDTH + 20;
841 } else {
842 pos.x = 10;
845 pos.y = WMAX(pos.y - 100, 0);
847 if (panel->menu)
848 WEditMenuShowAt(panel->menu, pos.x, pos.y);
852 static void freeItemData(ItemData * data)
854 #define CFREE(d) if (d) wfree(d)
856 /* TODO */
857 switch (data->type) {
858 case CommandInfo:
859 CFREE(data->param.command.parameter);
860 CFREE(data->param.command.shortcut);
861 break;
863 case ExecInfo:
864 CFREE(data->param.exec.command);
865 CFREE(data->param.exec.shortcut);
866 break;
868 case PipeInfo:
869 CFREE(data->param.pipe.command);
870 break;
872 case PLPipeInfo:
873 CFREE(data->param.pipe.command);
874 break;
876 case ExternalInfo:
877 CFREE(data->param.external.path);
878 break;
880 case DirectoryInfo:
881 CFREE(data->param.directory.command);
882 CFREE(data->param.directory.directory);
883 break;
885 default:
886 break;
889 wfree(data);
890 #undef CFREE
893 static ItemData *parseCommand(WMPropList * item)
895 ItemData *data = wmalloc(sizeof(ItemData));
896 WMPropList *p;
897 char *command = NULL;
898 char *parameter = NULL;
899 char *shortcut = NULL;
900 int i = 1;
902 p = WMGetFromPLArray(item, i++);
903 command = WMGetFromPLString(p);
904 if (strcmp(command, "SHORTCUT") == 0) {
905 p = WMGetFromPLArray(item, i++);
906 shortcut = WMGetFromPLString(p);
907 p = WMGetFromPLArray(item, i++);
908 command = WMGetFromPLString(p);
910 p = WMGetFromPLArray(item, i++);
911 if (p)
912 parameter = WMGetFromPLString(p);
914 if (strcmp(command, "EXEC") == 0 || strcmp(command, "SHEXEC") == 0) {
916 data->type = ExecInfo;
918 data->param.exec.command = wstrdup(parameter);
919 if (shortcut)
920 data->param.exec.shortcut = wstrdup(shortcut);
922 } else if (strcmp(command, "OPEN_MENU") == 0) {
923 char *p;
925 * dir menu, menu file
926 * dir WITH
927 * |pipe
929 p = parameter;
930 while (isspace(*p) && *p)
931 p++;
932 if (*p == '|') {
933 if (*(p + 1) == '|') {
934 p++;
935 data->param.pipe.cached = 0;
936 } else {
937 data->param.pipe.cached = 1;
939 data->type = PipeInfo;
940 data->param.pipe.command = wtrimspace(p + 1);
941 } else {
942 char *s;
944 p = wstrdup(p);
946 s = strstr(p, "WITH");
947 if (s) {
948 char **tokens;
949 char **ctokens;
950 int tokn;
951 int i, j;
953 data->type = DirectoryInfo;
955 *s = '\0';
956 s += 5;
957 while (*s && isspace(*s))
958 s++;
959 data->param.directory.command = wstrdup(s);
961 wtokensplit(p, &tokens, &tokn);
962 wfree(p);
964 ctokens = wmalloc(sizeof(char *) * tokn);
966 for (i = 0, j = 0; i < tokn; i++) {
967 if (strcmp(tokens[i], "-noext") == 0) {
968 data->param.directory.stripExt = 1;
969 } else {
970 ctokens[j++] = tokens[i];
973 data->param.directory.directory = wtokenjoin(ctokens, j);
974 wfree(ctokens);
976 wtokenfree(tokens, tokn);
977 } else {
978 data->type = ExternalInfo;
979 data->param.external.path = p;
982 } else if (strcmp(command, "OPEN_PLMENU") == 0) {
983 char *p;
985 p = parameter;
986 while (isspace(*p) && *p)
987 p++;
988 if (*p == '|') {
989 if (*(p + 1) == '|') {
990 p++;
991 data->param.pipe.cached = 0;
992 } else {
993 data->param.pipe.cached = 1;
995 data->type = PLPipeInfo;
996 data->param.pipe.command = wtrimspace(p + 1);
998 } else if (strcmp(command, "WORKSPACE_MENU") == 0) {
999 data->type = WSMenuInfo;
1000 } else if (strcmp(command, "WINDOWS_MENU") == 0) {
1001 data->type = WWindowListInfo;
1002 } else {
1003 int cmd;
1005 if (strcmp(command, "ARRANGE_ICONS") == 0) {
1006 cmd = 0;
1007 } else if (strcmp(command, "HIDE_OTHERS") == 0) {
1008 cmd = 1;
1009 } else if (strcmp(command, "SHOW_ALL") == 0) {
1010 cmd = 2;
1011 } else if (strcmp(command, "EXIT") == 0) {
1012 cmd = 3;
1013 } else if (strcmp(command, "SHUTDOWN") == 0) {
1014 cmd = 4;
1015 } else if (strcmp(command, "RESTART") == 0) {
1016 if (parameter) {
1017 cmd = 6;
1018 } else {
1019 cmd = 5;
1021 } else if (strcmp(command, "SAVE_SESSION") == 0) {
1022 cmd = 7;
1023 } else if (strcmp(command, "CLEAR_SESSION") == 0) {
1024 cmd = 8;
1025 } else if (strcmp(command, "REFRESH") == 0) {
1026 cmd = 9;
1027 } else if (strcmp(command, "INFO_PANEL") == 0) {
1028 cmd = 10;
1029 } else if (strcmp(command, "LEGAL_PANEL") == 0) {
1030 cmd = 11;
1031 } else {
1032 wwarning(_("unknown command '%s' in menu"), command);
1033 wfree(data);
1034 return NULL;
1037 data->type = CommandInfo;
1039 data->param.command.command = cmd;
1040 if (shortcut)
1041 data->param.command.shortcut = wstrdup(shortcut);
1042 if (parameter)
1043 data->param.command.parameter = wstrdup(parameter);
1046 return data;
1049 static void updateFrameTitle(_Panel * panel, const char *title, InfoType type)
1051 if (type != NoInfo) {
1052 char *tmp;
1054 switch (type) {
1055 case ExecInfo:
1056 tmp = wstrconcat(title, _(": Execute Program"));
1057 break;
1059 case CommandInfo:
1060 tmp = wstrconcat(title, _(": Perform Internal Command"));
1061 break;
1063 case ExternalInfo:
1064 tmp = wstrconcat(title, _(": Open a Submenu"));
1065 break;
1067 case PipeInfo:
1068 tmp = wstrconcat(title, _(": Program Generated Submenu"));
1069 break;
1071 case PLPipeInfo:
1072 tmp = wstrconcat(title, _(": Program Generated Proplist Submenu"));
1073 break;
1075 case DirectoryInfo:
1076 tmp = wstrconcat(title, _(": Directory Contents Menu"));
1077 break;
1079 case WSMenuInfo:
1080 tmp = wstrconcat(title, _(": Open Workspaces Submenu"));
1081 break;
1083 case WWindowListInfo:
1084 tmp = wstrconcat(title, _(": Open Window List Submenu"));
1085 break;
1087 default:
1088 tmp = NULL;
1089 break;
1091 WMSetFrameTitle(panel->optionsF, tmp);
1092 wfree(tmp);
1093 } else {
1094 WMSetFrameTitle(panel->optionsF, NULL);
1098 static void changeInfoType(_Panel * panel, const char *title, InfoType type)
1100 WMWidget **w;
1102 if (panel->currentType != type) {
1104 w = panel->sections[panel->currentType];
1106 while (*w) {
1107 WMUnmapWidget(*w);
1108 w++;
1110 WMUnmapWidget(panel->paramF);
1111 WMUnmapWidget(panel->quickB);
1113 w = panel->sections[type];
1115 while (*w) {
1116 WMMapWidget(*w);
1117 w++;
1121 updateFrameTitle(panel, title, type);
1123 panel->currentType = type;
1126 static void updateMenuItem(_Panel * panel, WEditMenuItem * item, WMWidget * changedWidget)
1128 ItemData *data = WGetEditMenuItemData(item);
1130 assert(data != NULL);
1132 #define REPLACE(v, d) if (v) wfree(v); v = d
1134 switch (data->type) {
1135 case ExecInfo:
1136 if (changedWidget == panel->commandT) {
1137 REPLACE(data->param.exec.command, WMGetTextFieldText(panel->commandT));
1139 if (changedWidget == panel->shortT) {
1140 REPLACE(data->param.exec.shortcut, WMGetTextFieldText(panel->shortT));
1142 break;
1144 case CommandInfo:
1145 if (changedWidget == panel->icommandL) {
1146 data->param.command.command = WMGetListSelectedItemRow(panel->icommandL);
1148 switch (data->param.command.command) {
1149 case 3:
1150 case 4:
1151 if (changedWidget == panel->quickB) {
1152 REPLACE(data->param.command.parameter, WMGetButtonSelected(panel->quickB)
1153 ? wstrdup("QUICK") : NULL);
1155 break;
1157 case 6:
1158 if (changedWidget == panel->paramT) {
1159 REPLACE(data->param.command.parameter, WMGetTextFieldText(panel->paramT));
1161 break;
1163 if (changedWidget == panel->shortT) {
1164 REPLACE(data->param.command.shortcut, WMGetTextFieldText(panel->shortT));
1167 break;
1169 case PipeInfo:
1170 if (changedWidget == panel->pipeT) {
1171 REPLACE(data->param.pipe.command, WMGetTextFieldText(panel->pipeT));
1173 if (changedWidget == panel->pipeCacheB) {
1174 data->param.pipe.cached = WMGetButtonSelected(panel->pipeCacheB);
1176 break;
1178 case PLPipeInfo:
1179 if (changedWidget == panel->plpipeT) {
1180 REPLACE(data->param.pipe.command, WMGetTextFieldText(panel->plpipeT));
1182 if (changedWidget == panel->plpipeCacheB) {
1183 data->param.pipe.cached = WMGetButtonSelected(panel->plpipeCacheB);
1185 break;
1187 case ExternalInfo:
1188 if (changedWidget == panel->pathT) {
1189 REPLACE(data->param.external.path, WMGetTextFieldText(panel->pathT));
1191 break;
1193 case DirectoryInfo:
1194 if (changedWidget == panel->dpathT) {
1195 REPLACE(data->param.directory.directory, WMGetTextFieldText(panel->dpathT));
1197 if (changedWidget == panel->dcommandT) {
1198 REPLACE(data->param.directory.command, WMGetTextFieldText(panel->dcommandT));
1200 if (changedWidget == panel->dstripB) {
1201 data->param.directory.stripExt = WMGetButtonSelected(panel->dstripB);
1203 break;
1205 default:
1206 assert(0);
1207 break;
1210 #undef REPLACE
1213 static void
1214 menuItemCloned(WEditMenuDelegate * delegate, WEditMenu * menu, WEditMenuItem * origItem, WEditMenuItem * newItem)
1216 ItemData *data = WGetEditMenuItemData(origItem);
1217 ItemData *newData;
1219 if (!data)
1220 return;
1222 #define DUP(s) (s) ? wstrdup(s) : NULL
1224 newData = wmalloc(sizeof(ItemData));
1226 newData->type = data->type;
1228 switch (data->type) {
1229 case ExecInfo:
1230 newData->param.exec.command = DUP(data->param.exec.command);
1231 newData->param.exec.shortcut = DUP(data->param.exec.shortcut);
1232 break;
1234 case CommandInfo:
1235 newData->param.command.command = data->param.command.command;
1236 newData->param.command.parameter = DUP(data->param.command.parameter);
1237 newData->param.command.shortcut = DUP(data->param.command.shortcut);
1238 break;
1240 case PipeInfo:
1241 newData->param.pipe.command = DUP(data->param.pipe.command);
1242 newData->param.pipe.cached = data->param.pipe.cached;
1243 break;
1245 case PLPipeInfo:
1246 newData->param.pipe.command = DUP(data->param.pipe.command);
1247 newData->param.pipe.cached = data->param.pipe.cached;
1248 break;
1250 case ExternalInfo:
1251 newData->param.external.path = DUP(data->param.external.path);
1252 break;
1254 case DirectoryInfo:
1255 newData->param.directory.directory = DUP(data->param.directory.directory);
1256 newData->param.directory.command = DUP(data->param.directory.command);
1257 newData->param.directory.stripExt = data->param.directory.stripExt;
1258 break;
1260 default:
1261 break;
1264 #undef DUP
1266 WSetEditMenuItemData(newItem, newData, (WMCallback *) freeItemData);
1269 static void menuItemEdited(struct WEditMenuDelegate *delegate, WEditMenu * menu, WEditMenuItem * item)
1271 _Panel *panel = (_Panel *) delegate->data;
1272 WEditMenu *submenu;
1274 updateFrameTitle(panel, WGetEditMenuItemTitle(item), panel->currentType);
1276 submenu = WGetEditMenuSubmenu(menu, item);
1277 if (submenu) {
1278 WSetEditMenuTitle(submenu, WGetEditMenuItemTitle(item));
1282 static Bool shouldRemoveItem(struct WEditMenuDelegate *delegate, WEditMenu * menu, WEditMenuItem * item)
1284 _Panel *panel = (_Panel *) delegate->data;
1286 if (panel->dontAsk)
1287 return True;
1289 if (WGetEditMenuSubmenu(menu, item)) {
1290 int res;
1292 res = WMRunAlertPanel(WMWidgetScreen(menu), NULL,
1293 _("Remove Submenu"),
1294 _("Removing this item will destroy all items inside\n"
1295 "the submenu. Do you really want to do that?"),
1296 _("Yes"), _("No"), _("Yes, don't ask again."));
1297 switch (res) {
1298 case WAPRDefault:
1299 return True;
1300 case WAPRAlternate:
1301 return False;
1302 case WAPROther:
1303 panel->dontAsk = True;
1304 return True;
1307 return True;
1310 static void menuItemDeselected(WEditMenuDelegate * delegate, WEditMenu * menu, WEditMenuItem * item)
1312 _Panel *panel = (_Panel *) delegate->data;
1314 changeInfoType(panel, NULL, NoInfo);
1317 static void menuItemSelected(WEditMenuDelegate * delegate, WEditMenu * menu, WEditMenuItem * item)
1319 ItemData *data = WGetEditMenuItemData(item);
1320 _Panel *panel = (_Panel *) delegate->data;
1322 panel->currentItem = item;
1324 if (data) {
1325 changeInfoType(panel, WGetEditMenuItemTitle(item), data->type);
1327 switch (data->type) {
1328 case NoInfo:
1329 break;
1331 case ExecInfo:
1332 WMSetTextFieldText(panel->commandT, data->param.exec.command);
1333 WMSetTextFieldText(panel->shortT, data->param.exec.shortcut);
1334 break;
1336 case CommandInfo:
1337 WMSelectListItem(panel->icommandL, data->param.command.command);
1338 WMSetListPosition(panel->icommandL, data->param.command.command - 2);
1339 WMSetTextFieldText(panel->shortT, data->param.command.shortcut);
1341 switch (data->param.command.command) {
1342 case 3:
1343 case 4:
1344 WMSetButtonSelected(panel->quickB, data->param.command.parameter != NULL);
1345 break;
1346 case 6:
1347 WMSetTextFieldText(panel->paramT, data->param.command.parameter);
1348 break;
1351 icommandLClicked(panel->icommandL, panel);
1352 break;
1354 case PipeInfo:
1355 WMSetTextFieldText(panel->pipeT, data->param.pipe.command);
1356 WMSetButtonSelected(panel->pipeCacheB, data->param.pipe.cached);
1357 break;
1359 case PLPipeInfo:
1360 WMSetTextFieldText(panel->plpipeT, data->param.pipe.command);
1361 WMSetButtonSelected(panel->plpipeCacheB, data->param.pipe.cached);
1362 break;
1364 case ExternalInfo:
1365 WMSetTextFieldText(panel->pathT, data->param.external.path);
1366 break;
1368 case DirectoryInfo:
1369 WMSetTextFieldText(panel->dpathT, data->param.directory.directory);
1370 WMSetTextFieldText(panel->dcommandT, data->param.directory.command);
1371 WMSetButtonSelected(panel->dstripB, data->param.directory.stripExt);
1372 break;
1374 case WSMenuInfo:
1375 break;
1377 default:
1378 break;
1383 static WEditMenu *buildSubmenu(_Panel * panel, WMPropList * pl)
1385 WMScreen *scr = WMWidgetScreen(panel->parent);
1386 WEditMenu *menu;
1387 WEditMenuItem *item;
1388 char *title;
1389 WMPropList *tp, *bp;
1390 int i;
1392 tp = WMGetFromPLArray(pl, 0);
1393 title = WMGetFromPLString(tp);
1395 menu = WCreateEditMenu(scr, title);
1397 for (i = 1; i < WMGetPropListItemCount(pl); i++) {
1398 WMPropList *pi;
1400 pi = WMGetFromPLArray(pl, i);
1402 tp = WMGetFromPLArray(pi, 0);
1403 bp = WMGetFromPLArray(pi, 1);
1405 title = WMGetFromPLString(tp);
1407 if (!bp || WMIsPLArray(bp)) { /* it's a submenu */
1408 WEditMenu *submenu;
1410 submenu = buildSubmenu(panel, pi);
1412 item = WAddMenuItemWithTitle(menu, title);
1414 WSetEditMenuSubmenu(menu, item, submenu);
1415 } else {
1416 ItemData *data;
1418 data = parseCommand(pi);
1420 if (data != NULL) {
1421 item = WAddMenuItemWithTitle(menu, title);
1422 if (panel->markerPix[data->type])
1423 WSetEditMenuItemImage(item, panel->markerPix[data->type]);
1424 WSetEditMenuItemData(item, data, (WMCallback *) freeItemData);
1425 } else {
1426 char *buf = wmalloc(1024);
1427 snprintf(buf, 1024, _("Invalid menu command \"%s\" with label \"%s\" cleared"),
1428 WMGetFromPLString(WMGetFromPLArray(pi, 1)),
1429 WMGetFromPLString(WMGetFromPLArray(pi, 0)));
1430 WMRunAlertPanel(scr, panel->parent, _("Warning"), buf, _("OK"), NULL, NULL);
1431 wfree(buf);
1437 WSetEditMenuAcceptsDrop(menu, True);
1438 WSetEditMenuDelegate(menu, &menuDelegate);
1440 WMRealizeWidget(menu);
1442 return menu;
1445 static void buildMenuFromPL(_Panel * panel, WMPropList * pl)
1447 panel->menu = buildSubmenu(panel, pl);
1450 static WMPropList *getDefaultMenu(_Panel * panel)
1452 WMPropList *menu;
1453 static const char menuPath[] = WMAKER_RESOURCE_PATH "/plmenu";
1455 menu = WMReadPropListFromFile(menuPath);
1456 if (!menu) {
1457 char *buffer, *msg;
1459 msg = _("Could not open default menu from '%s'");
1460 buffer = wmalloc(strlen(msg) + strlen(menuPath) + 10);
1461 sprintf(buffer, msg, menuPath);
1462 WMRunAlertPanel(WMWidgetScreen(panel->parent), panel->parent,
1463 _("Error"), buffer, _("OK"), NULL, NULL);
1464 wfree(buffer);
1467 return menu;
1470 static void showData(_Panel * panel)
1472 const char *gspath;
1473 char *menuPath;
1474 WMPropList *pmenu;
1476 gspath = wusergnusteppath();
1478 menuPath = wmalloc(strlen(gspath) + 32);
1479 strcpy(menuPath, gspath);
1480 strcat(menuPath, "/Defaults/WMRootMenu");
1482 pmenu = WMReadPropListFromFile(menuPath);
1484 if (!pmenu || !WMIsPLArray(pmenu)) {
1485 int res;
1487 res = WMRunAlertPanel(WMWidgetScreen(panel->parent), panel->parent,
1488 _("Warning"),
1489 _("The menu file format currently in use is not supported\n"
1490 "by this tool. Do you want to discard the current menu\n"
1491 "to use this tool?"),
1492 _("Yes, Discard and Update"), _("No, Keep Current Menu"), NULL);
1494 if (res == WAPRDefault) {
1495 pmenu = getDefaultMenu(panel);
1497 if (!pmenu) {
1498 pmenu = WMCreatePLArray(WMCreatePLString("Applications"), NULL);
1500 } else {
1501 panel->dontSave = True;
1502 return;
1506 panel->menuPath = menuPath;
1508 buildMenuFromPL(panel, pmenu);
1510 WMReleasePropList(pmenu);
1513 static Bool notblank(const char *s)
1515 if (s) {
1516 while (*s++) {
1517 if (!isspace(*s))
1518 return True;
1521 return False;
1524 static WMPropList *processData(const char *title, ItemData * data)
1526 WMPropList *item;
1527 char *s1;
1528 static WMPropList *pscut = NULL;
1529 static WMPropList *pomenu = NULL;
1530 static WMPropList *poplmenu = NULL;
1531 int i;
1533 if (data == NULL)
1534 return NULL;
1536 if (!pscut) {
1537 pscut = WMCreatePLString("SHORTCUT");
1538 pomenu = WMCreatePLString("OPEN_MENU");
1539 poplmenu = WMCreatePLString("OPEN_PLMENU");
1542 item = WMCreatePLArray(WMCreatePLString(title), NULL);
1544 switch (data->type) {
1545 case ExecInfo:
1546 if (data->param.exec.command == NULL)
1547 return NULL;
1548 #if 1
1549 if (strpbrk(data->param.exec.command, "&$*|><?`=;")) {
1550 s1 = "SHEXEC";
1551 } else {
1552 s1 = "EXEC";
1554 #else
1555 s1 = "SHEXEC";
1556 #endif
1558 if (notblank(data->param.exec.shortcut)) {
1559 WMAddToPLArray(item, pscut);
1560 WMAddToPLArray(item, WMCreatePLString(data->param.exec.shortcut));
1563 WMAddToPLArray(item, WMCreatePLString(s1));
1564 WMAddToPLArray(item, WMCreatePLString(data->param.exec.command));
1565 break;
1567 case CommandInfo:
1568 if (notblank(data->param.command.shortcut)) {
1569 WMAddToPLArray(item, pscut);
1570 WMAddToPLArray(item, WMCreatePLString(data->param.command.shortcut));
1573 i = data->param.command.command;
1575 WMAddToPLArray(item, WMCreatePLString(commandNames[i]));
1577 switch (i) {
1578 case 3:
1579 case 4:
1580 if (data->param.command.parameter) {
1581 WMAddToPLArray(item, WMCreatePLString(data->param.command.parameter));
1583 break;
1585 case 6: /* restart */
1586 if (data->param.command.parameter) {
1587 WMAddToPLArray(item, WMCreatePLString(data->param.command.parameter));
1589 break;
1592 break;
1594 case PipeInfo:
1595 case PLPipeInfo:
1596 if (!data->param.pipe.command)
1597 return NULL;
1598 if (data->type == PLPipeInfo)
1599 WMAddToPLArray(item, poplmenu);
1600 else
1601 WMAddToPLArray(item, pomenu);
1603 if (data->param.pipe.cached)
1604 s1 = wstrconcat("| ", data->param.pipe.command);
1605 else
1606 s1 = wstrconcat("|| ", data->param.pipe.command);
1607 WMAddToPLArray(item, WMCreatePLString(s1));
1608 wfree(s1);
1609 break;
1611 case ExternalInfo:
1612 if (!data->param.external.path)
1613 return NULL;
1614 WMAddToPLArray(item, pomenu);
1615 WMAddToPLArray(item, WMCreatePLString(data->param.external.path));
1616 break;
1618 case DirectoryInfo:
1619 if (!data->param.directory.directory || !data->param.directory.command)
1620 return NULL;
1622 int l;
1623 char *tmp;
1625 l = strlen(data->param.directory.directory);
1626 l += strlen(data->param.directory.command);
1627 l += 32;
1629 WMAddToPLArray(item, pomenu);
1631 tmp = wmalloc(l);
1632 sprintf(tmp, "%s%s WITH %s",
1633 data->param.directory.stripExt ? "-noext " : "",
1634 data->param.directory.directory, data->param.directory.command);
1636 WMAddToPLArray(item, WMCreatePLString(tmp));
1637 wfree(tmp);
1639 break;
1641 case WSMenuInfo:
1642 WMAddToPLArray(item, WMCreatePLString("WORKSPACE_MENU"));
1643 break;
1645 case WWindowListInfo:
1646 WMAddToPLArray(item, WMCreatePLString("WINDOWS_MENU"));
1647 break;
1649 default:
1650 assert(0);
1651 break;
1654 return item;
1657 static WMPropList *processSubmenu(WEditMenu * menu)
1659 WEditMenuItem *item;
1660 WMPropList *pmenu;
1661 WMPropList *pl;
1662 char *s;
1663 int i;
1665 s = WGetEditMenuTitle(menu);
1666 pl = WMCreatePLString(s);
1668 pmenu = WMCreatePLArray(pl, NULL);
1670 i = 0;
1671 while ((item = WGetEditMenuItem(menu, i++))) {
1672 WEditMenu *submenu;
1674 s = WGetEditMenuItemTitle(item);
1676 submenu = WGetEditMenuSubmenu(menu, item);
1677 if (submenu) {
1678 pl = processSubmenu(submenu);
1679 } else {
1680 pl = processData(s, WGetEditMenuItemData(item));
1683 if (!pl)
1684 continue;
1686 WMAddToPLArray(pmenu, pl);
1689 return pmenu;
1692 static WMPropList *buildPLFromMenu(_Panel * panel)
1694 WMPropList *menu;
1696 menu = processSubmenu(panel->menu);
1698 return menu;
1701 static void storeData(_Panel * panel)
1703 WMPropList *menu;
1705 if (panel->dontSave)
1706 return;
1708 menu = buildPLFromMenu(panel);
1710 WMWritePropListToFile(menu, panel->menuPath);
1712 WMReleasePropList(menu);
1715 static void showMenus(_Panel * panel)
1717 if (panel->menu)
1718 WEditMenuUnhide(panel->menu);
1721 static void hideMenus(_Panel * panel)
1723 if (panel->menu)
1724 WEditMenuHide(panel->menu);
1727 Panel *InitMenu(WMScreen * scr, WMWidget * parent)
1729 _Panel *panel;
1731 panel = wmalloc(sizeof(_Panel));
1733 panel->sectionName = _("Applications Menu Definition");
1735 panel->description = _("Edit the menu for launching applications.");
1737 panel->parent = parent;
1739 panel->callbacks.createWidgets = createPanel;
1740 panel->callbacks.updateDomain = storeData;
1741 panel->callbacks.showPanel = showMenus;
1742 panel->callbacks.hidePanel = hideMenus;
1744 AddSection(panel, ICON_FILE);
1746 return panel;