wmaker: remove constants HORIZONTAL and VERTICAL from moveres.c
[wmaker-crm.git] / WPrefs.app / Menu.c
blob5f0f0171d30871b6ebce9f292d7c86d9c090a8e5
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
46 typedef struct _Panel {
47 WMBox *box;
48 char *sectionName;
50 char *description;
52 CallbackRec callbacks;
53 WMWidget *parent;
55 WMFont *boldFont;
56 WMFont *normalFont;
57 WMColor *white;
58 WMColor *gray;
59 WMColor *black;
61 WMPixmap *markerPix[LastInfo];
63 WMPopUpButton *typeP;
65 WMWidget *itemPad[3];
66 int currentPad;
68 WEditMenu *menu;
69 char *menuPath;
71 WMFrame *optionsF;
73 WMFrame *commandF;
74 WMTextField *commandT; /* command to run */
75 WMButton *browseB;
76 WMButton *xtermC; /* inside xterm? */
78 WMFrame *pathF;
79 WMTextField *pathT;
81 WMFrame *pipeF;
82 WMTextField *pipeT;
83 WMButton *pipeCacheB;
85 WMFrame *plpipeF;
86 WMTextField *plpipeT;
87 WMButton *plpipeCacheB;
89 WMFrame *dpathF;
90 WMTextField *dpathT;
92 WMFrame *dcommandF;
93 WMTextField *dcommandT;
95 WMButton *dstripB;
97 WMFrame *shortF;
98 WMTextField *shortT;
99 WMButton *sgrabB;
100 WMButton *sclearB;
102 WMList *icommandL;
104 WMFrame *paramF;
105 WMTextField *paramT;
107 WMButton *quickB;
109 Bool dontAsk; /* whether to comfirm submenu remove */
110 Bool dontSave;
112 Bool capturing;
114 /* about the currently selected item */
115 WEditMenuItem *currentItem;
116 InfoType currentType;
117 WMWidget *sections[LastInfo][MAX_SECTION_SIZE];
118 } _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 unsigned cached:1;
138 } pipe;
139 struct {
140 char *directory;
141 char *command;
142 unsigned stripExt:1;
143 } directory;
144 } param;
145 } 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"
162 #define ICON_FILE "menus"
164 static void showData(_Panel * panel);
166 static void updateMenuItem(_Panel * panel, WEditMenuItem * item, WMWidget * changedWidget);
168 static void menuItemSelected(struct WEditMenuDelegate *delegate, WEditMenu * menu, WEditMenuItem * item);
170 static void menuItemDeselected(struct WEditMenuDelegate *delegate, WEditMenu * menu, WEditMenuItem * item);
172 static void menuItemCloned(struct WEditMenuDelegate *delegate, WEditMenu * menu,
173 WEditMenuItem * origItem, WEditMenuItem * newItem);
175 static void menuItemEdited(struct WEditMenuDelegate *delegate, WEditMenu * menu, WEditMenuItem * item);
177 static Bool shouldRemoveItem(struct WEditMenuDelegate *delegate, WEditMenu * menu, WEditMenuItem * item);
179 static void freeItemData(ItemData * data);
182 static WEditMenuDelegate menuDelegate = {
183 NULL,
184 menuItemCloned,
185 menuItemEdited,
186 menuItemSelected,
187 menuItemDeselected,
188 shouldRemoveItem
191 static void dataChanged(void *self, WMNotification * notif)
193 _Panel *panel = (_Panel *) self;
194 WEditMenuItem *item = panel->currentItem;
195 WMWidget *w = (WMWidget *) WMGetNotificationObject(notif);
197 updateMenuItem(panel, item, w);
200 static void buttonClicked(WMWidget * w, void *data)
202 _Panel *panel = (_Panel *) data;
203 WEditMenuItem *item = panel->currentItem;
205 updateMenuItem(panel, item, w);
208 static void icommandLClicked(WMWidget * w, void *data)
210 _Panel *panel = (_Panel *) data;
211 int cmd;
213 cmd = WMGetListSelectedItemRow(w);
214 if (cmd == 3 || cmd == 4) {
215 WMMapWidget(panel->quickB);
216 } else {
217 WMUnmapWidget(panel->quickB);
219 if (cmd == 6) {
220 WMMapWidget(panel->paramF);
221 } else {
222 WMUnmapWidget(panel->paramF);
226 static void browseForFile(WMWidget * self, void *clientData)
228 _Panel *panel = (_Panel *) clientData;
229 WMFilePanel *filePanel;
230 char *text, *oldprog, *newprog;
232 filePanel = WMGetOpenPanel(WMWidgetScreen(self));
233 text = WMGetTextFieldText(panel->commandT);
235 oldprog = wtrimspace(text);
236 wfree(text);
238 if (oldprog[0] == 0 || oldprog[0] != '/') {
239 wfree(oldprog);
240 oldprog = wstrdup("/");
241 } else {
242 char *ptr = oldprog;
243 while (*ptr && !isspace(*ptr))
244 ptr++;
245 *ptr = 0;
248 WMSetFilePanelCanChooseDirectories(filePanel, False);
250 if (WMRunModalFilePanelForDirectory(filePanel, panel->parent, oldprog, _("Select Program"), NULL) == True) {
251 newprog = WMGetFilePanelFileName(filePanel);
252 WMSetTextFieldText(panel->commandT, newprog);
253 updateMenuItem(panel, panel->currentItem, panel->commandT);
254 wfree(newprog);
257 wfree(oldprog);
260 static void sgrabClicked(WMWidget * w, void *data)
262 _Panel *panel = (_Panel *) data;
263 Display *dpy = WMScreenDisplay(WMWidgetScreen(panel->parent));
264 char *shortcut;
266 if (w == panel->sclearB) {
267 WMSetTextFieldText(panel->shortT, "");
268 updateMenuItem(panel, panel->currentItem, panel->shortT);
269 return;
272 if (!panel->capturing) {
273 panel->capturing = 1;
274 WMSetButtonText(w, _("Cancel"));
275 XGrabKeyboard(dpy, WMWidgetXID(panel->parent), True, GrabModeAsync, GrabModeAsync, CurrentTime);
276 shortcut = capture_shortcut(dpy, &panel->capturing, 0);
277 if (shortcut) {
278 WMSetTextFieldText(panel->shortT, shortcut);
279 updateMenuItem(panel, panel->currentItem, panel->shortT);
280 wfree(shortcut);
283 panel->capturing = 0;
284 WMSetButtonText(w, _("Capture"));
285 XUngrabKeyboard(dpy, CurrentTime);
288 static void changedItemPad(WMWidget * w, void *data)
290 _Panel *panel = (_Panel *) data;
291 int padn = WMGetPopUpButtonSelectedItem(w);
293 WMUnmapWidget(panel->itemPad[panel->currentPad]);
294 WMMapWidget(panel->itemPad[padn]);
296 panel->currentPad = padn;
299 static WEditMenu *putNewSubmenu(WEditMenu * menu, const char *title)
301 WEditMenu *tmp;
302 WEditMenuItem *item;
304 item = WAddMenuItemWithTitle(menu, title);
306 tmp = WCreateEditMenu(WMWidgetScreen(menu), title);
307 WSetEditMenuAcceptsDrop(tmp, True);
308 WSetEditMenuDelegate(tmp, &menuDelegate);
309 WSetEditMenuSubmenu(menu, item, tmp);
311 return tmp;
314 static ItemData *putNewItem(_Panel * panel, WEditMenu * menu, int type, const char *title)
316 WEditMenuItem *item;
317 ItemData *data;
319 item = WAddMenuItemWithTitle(menu, title);
321 data = wmalloc(sizeof(ItemData));
322 data->type = type;
323 WSetEditMenuItemData(item, data, (WMCallback *) freeItemData);
324 WSetEditMenuItemImage(item, panel->markerPix[type]);
326 return data;
329 static WEditMenu *makeFactoryMenu(WMWidget * parent, int width)
331 WEditMenu *pad;
333 pad = WCreateEditMenuPad(parent);
334 WMResizeWidget(pad, width, 10);
335 WSetEditMenuMinSize(pad, wmksize(width, 0));
336 WSetEditMenuMaxSize(pad, wmksize(width, 0));
337 WSetEditMenuSelectable(pad, False);
338 WSetEditMenuEditable(pad, False);
339 WSetEditMenuIsFactory(pad, True);
340 WSetEditMenuDelegate(pad, &menuDelegate);
342 return pad;
345 static void createPanel(_Panel * p)
347 _Panel *panel = (_Panel *) p;
348 WMScreen *scr = WMWidgetScreen(panel->parent);
349 WMColor *black = WMBlackColor(scr);
350 WMColor *white = WMWhiteColor(scr);
351 WMColor *gray = WMGrayColor(scr);
352 WMFont *bold = WMBoldSystemFontOfSize(scr, 12);
353 WMFont *font = WMSystemFontOfSize(scr, 12);
354 WMLabel *label;
355 int width;
357 menuDelegate.data = panel;
359 panel->boldFont = bold;
360 panel->normalFont = font;
362 panel->black = black;
363 panel->white = white;
364 panel->gray = gray;
367 Pixmap pix;
368 Display *dpy = WMScreenDisplay(scr);
369 GC gc;
370 WMPixmap *pixm;
372 pixm = WMCreatePixmap(scr, 7, 7, WMScreenDepth(scr), True);
374 pix = WMGetPixmapXID(pixm);
376 XDrawLine(dpy, pix, WMColorGC(black), 0, 3, 6, 3);
377 XDrawLine(dpy, pix, WMColorGC(black), 3, 0, 3, 6);
379 XDrawLine(dpy, pix, WMColorGC(black), 1, 0, 3, 3);
380 XDrawLine(dpy, pix, WMColorGC(black), 1, 6, 3, 3);
381 XDrawLine(dpy, pix, WMColorGC(black), 0, 0, 0, 6);
384 pix = WMGetPixmapMaskXID(pixm);
386 gc = XCreateGC(dpy, pix, 0, NULL);
388 XSetForeground(dpy, gc, 0);
389 XFillRectangle(dpy, pix, gc, 0, 0, 7, 7);
391 XSetForeground(dpy, gc, 1);
392 XDrawLine(dpy, pix, gc, 0, 3, 6, 3);
393 XDrawLine(dpy, pix, gc, 3, 0, 3, 6);
395 panel->markerPix[ExternalInfo] = pixm;
396 panel->markerPix[PipeInfo] = pixm;
397 panel->markerPix[PLPipeInfo] = pixm;
398 panel->markerPix[DirectoryInfo] = pixm;
399 panel->markerPix[WSMenuInfo] = pixm;
400 panel->markerPix[WWindowListInfo] = pixm;
402 XFreeGC(dpy, gc);
405 panel->box = WMCreateBox(panel->parent);
406 WMSetViewExpandsToParent(WMWidgetView(panel->box), 2, 2, 2, 2);
408 panel->typeP = WMCreatePopUpButton(panel->box);
409 WMResizeWidget(panel->typeP, 150, 20);
410 WMMoveWidget(panel->typeP, 10, 10);
412 WMAddPopUpButtonItem(panel->typeP, _("New Items"));
413 WMAddPopUpButtonItem(panel->typeP, _("Sample Commands"));
414 WMAddPopUpButtonItem(panel->typeP, _("Sample Submenus"));
416 WMSetPopUpButtonAction(panel->typeP, changedItemPad, panel);
418 WMSetPopUpButtonSelectedItem(panel->typeP, 0);
421 WEditMenu *pad;
423 pad = makeFactoryMenu(panel->box, 150);
424 WMMoveWidget(pad, 10, 40);
426 putNewItem(panel, pad, ExecInfo, _("Run Program"));
427 putNewItem(panel, pad, CommandInfo, _("Internal Command"));
428 putNewSubmenu(pad, _("Submenu"));
429 putNewItem(panel, pad, ExternalInfo, _("External Submenu"));
430 putNewItem(panel, pad, PipeInfo, _("Generated Submenu"));
431 putNewItem(panel, pad, PLPipeInfo, _("Generated PL Menu"));
432 putNewItem(panel, pad, DirectoryInfo, _("Directory Contents"));
433 putNewItem(panel, pad, WSMenuInfo, _("Workspace Menu"));
434 putNewItem(panel, pad, WWindowListInfo, _("Window List Menu"));
436 panel->itemPad[0] = pad;
440 WEditMenu *pad;
441 ItemData *data;
442 WMScrollView *sview;
444 sview = WMCreateScrollView(panel->box);
445 WMResizeWidget(sview, 150, 180);
446 WMMoveWidget(sview, 10, 40);
447 WMSetScrollViewHasVerticalScroller(sview, True);
449 pad = makeFactoryMenu(panel->box, 130);
451 WMSetScrollViewContentView(sview, WMWidgetView(pad));
453 data = putNewItem(panel, pad, ExecInfo, _("XTerm"));
454 data->param.exec.command = "xterm -sb -sl 2000 -bg black -fg white";
456 data = putNewItem(panel, pad, ExecInfo, _("rxvt"));
457 data->param.exec.command = "rxvt";
459 data = putNewItem(panel, pad, ExecInfo, _("ETerm"));
460 data->param.exec.command = "eterm";
462 data = putNewItem(panel, pad, ExecInfo, _("Run..."));
463 data->param.exec.command = _("%A(Run,Type command to run)");
465 data = putNewItem(panel, pad, ExecInfo, _("Firefox"));
466 data->param.exec.command = "firefox";
468 data = putNewItem(panel, pad, ExecInfo, _("gimp"));
469 data->param.exec.command = "gimp";
471 data = putNewItem(panel, pad, ExecInfo, _("epic"));
472 data->param.exec.command = "xterm -e epic";
474 data = putNewItem(panel, pad, ExecInfo, _("ee"));
475 data->param.exec.command = "ee";
477 data = putNewItem(panel, pad, ExecInfo, _("xv"));
478 data->param.exec.command = "xv";
480 data = putNewItem(panel, pad, ExecInfo, _("Evince"));
481 data->param.exec.command = "evince";
483 data = putNewItem(panel, pad, ExecInfo, _("ghostview"));
484 data->param.exec.command = "gv";
486 data = putNewItem(panel, pad, CommandInfo, _("Exit Window Maker"));
487 data->param.command.command = 3;
489 WMMapWidget(pad);
491 panel->itemPad[1] = sview;
495 WEditMenu *pad, *smenu;
496 ItemData *data;
497 WMScrollView *sview;
499 sview = WMCreateScrollView(panel->box);
500 WMResizeWidget(sview, 150, 180);
501 WMMoveWidget(sview, 10, 40);
502 WMSetScrollViewHasVerticalScroller(sview, True);
504 pad = makeFactoryMenu(panel->box, 130);
506 WMSetScrollViewContentView(sview, WMWidgetView(pad));
508 data = putNewItem(panel, pad, ExternalInfo, _("Debian Menu"));
509 data->param.pipe.command = "/etc/X11/WindowMaker/menu.hook";
511 data = putNewItem(panel, pad, PipeInfo, _("RedHat Menu"));
512 data->param.pipe.command = "wmconfig --output wmaker";
514 data = putNewItem(panel, pad, PipeInfo, _("Menu Conectiva"));
515 data->param.pipe.command = "wmconfig --output wmaker";
517 data = putNewItem(panel, pad, DirectoryInfo, _("Themes"));
518 data->param.directory.command = "setstyle";
519 data->param.directory.directory =
520 "/usr/share/WindowMaker/Themes /usr/local/share/WindowMaker/Themes $HOME/GNUstep/Library/WindowMaker/Themes";
521 data->param.directory.stripExt = 1;
523 data = putNewItem(panel, pad, DirectoryInfo, _("Bg Images (scale)"));
524 data->param.directory.command = "wmsetbg -u -s";
525 data->param.directory.directory =
526 "/opt/kde2/share/wallpapers /usr/share/WindowMaker/Backgrounds $HOME/GNUstep/Library/WindowMaker/Backgrounds";
527 data->param.directory.stripExt = 1;
529 data = putNewItem(panel, pad, DirectoryInfo, _("Bg Images (tile)"));
530 data->param.directory.command = "wmsetbg -u -t";
531 data->param.directory.directory =
532 "/opt/kde2/share/wallpapers /usr/share/WindowMaker/Backgrounds $HOME/GNUstep/Library/WindowMaker/Backgrounds";
533 data->param.directory.stripExt = 1;
535 smenu = putNewSubmenu(pad, _("Assorted XTerms"));
537 data = putNewItem(panel, smenu, ExecInfo, _("XTerm Yellow on Blue"));
538 data->param.exec.command = "xterm -sb -sl 2000 -bg midnightblue -fg yellow";
540 data = putNewItem(panel, smenu, ExecInfo, _("XTerm White on Black"));
541 data->param.exec.command = "xterm -sb -sl 2000 -bg black -fg white";
543 data = putNewItem(panel, smenu, ExecInfo, _("XTerm Black on White"));
544 data->param.exec.command = "xterm -sb -sl 2000 -bg white -fg black";
546 data = putNewItem(panel, smenu, ExecInfo, _("XTerm Black on Beige"));
547 data->param.exec.command = "xterm -sb -sl 2000 -bg '#bbbb99' -fg black";
549 data = putNewItem(panel, smenu, ExecInfo, _("XTerm White on Green"));
550 data->param.exec.command = "xterm -sb -sl 2000 -bg '#228822' -fg white";
552 data = putNewItem(panel, smenu, ExecInfo, _("XTerm White on Olive"));
553 data->param.exec.command = "xterm -sb -sl 2000 -bg '#335533' -fg white";
555 data = putNewItem(panel, smenu, ExecInfo, _("XTerm Blue on Blue"));
556 data->param.exec.command = "xterm -sb -sl 2000 -bg '#112244' -fg '#88aabb'";
558 data = putNewItem(panel, smenu, ExecInfo, _("XTerm BIG FONTS"));
559 data->param.exec.command = "xterm -sb -sl 2000 -bg black -fg white -fn 10x20";
561 WMMapWidget(pad);
563 panel->itemPad[2] = sview;
566 width = FRAME_WIDTH - 20 - 150 - 10 - 2;
568 panel->optionsF = WMCreateFrame(panel->box);
569 WMResizeWidget(panel->optionsF, width, FRAME_HEIGHT - 15);
570 WMMoveWidget(panel->optionsF, 10 + 150 + 10, 5);
572 width -= 20;
574 /* command */
576 panel->commandF = WMCreateFrame(panel->optionsF);
577 WMResizeWidget(panel->commandF, width, 50);
578 WMMoveWidget(panel->commandF, 10, 20);
579 WMSetFrameTitle(panel->commandF, _("Program to Run"));
580 WMSetFrameTitlePosition(panel->commandF, WTPAtTop);
582 panel->commandT = WMCreateTextField(panel->commandF);
583 WMResizeWidget(panel->commandT, width - 95, 20);
584 WMMoveWidget(panel->commandT, 10, 20);
586 panel->browseB = WMCreateCommandButton(panel->commandF);
587 WMResizeWidget(panel->browseB, 70, 24);
588 WMMoveWidget(panel->browseB, width - 80, 18);
589 WMSetButtonText(panel->browseB, _("Browse"));
590 WMSetButtonAction(panel->browseB, browseForFile, panel);
592 WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->commandT);
594 #if 0
595 panel->xtermC = WMCreateSwitchButton(panel->commandF);
596 WMResizeWidget(panel->xtermC, width - 20, 20);
597 WMMoveWidget(panel->xtermC, 10, 50);
598 WMSetButtonText(panel->xtermC, _("Run the program inside a Xterm"));
599 #endif
600 WMMapSubwidgets(panel->commandF);
602 /* path */
604 panel->pathF = WMCreateFrame(panel->optionsF);
605 WMResizeWidget(panel->pathF, width, 150);
606 WMMoveWidget(panel->pathF, 10, 40);
607 WMSetFrameTitle(panel->pathF, _("Path for Menu"));
609 panel->pathT = WMCreateTextField(panel->pathF);
610 WMResizeWidget(panel->pathT, width - 20, 20);
611 WMMoveWidget(panel->pathT, 10, 20);
613 WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->pathT);
615 label = WMCreateLabel(panel->pathF);
616 WMResizeWidget(label, width - 20, 80);
617 WMMoveWidget(label, 10, 50);
618 WMSetLabelText(label, _("Enter the path for a file containing a menu\n"
619 "or a list of directories with the programs you\n"
620 "want to have listed in the menu. Ex:\n"
621 "~/GNUstep/Library/WindowMaker/menu\n" "or\n" "/usr/bin ~/xbin"));
623 WMMapSubwidgets(panel->pathF);
625 /* pipe */
627 panel->pipeF = WMCreateFrame(panel->optionsF);
628 WMResizeWidget(panel->pipeF, width, 155);
629 WMMoveWidget(panel->pipeF, 10, 30);
630 WMSetFrameTitle(panel->pipeF, _("Command"));
632 panel->pipeT = WMCreateTextField(panel->pipeF);
633 WMResizeWidget(panel->pipeT, width - 20, 20);
634 WMMoveWidget(panel->pipeT, 10, 20);
636 WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->pipeT);
638 label = WMCreateLabel(panel->pipeF);
639 WMResizeWidget(label, width - 20, 40);
640 WMMoveWidget(label, 10, 50);
641 WMSetLabelText(label, _("Enter a command that outputs a menu\n" "definition to stdout when invoked."));
643 panel->pipeCacheB = WMCreateSwitchButton(panel->pipeF);
644 WMResizeWidget(panel->pipeCacheB, width - 20, 40);
645 WMMoveWidget(panel->pipeCacheB, 10, 110);
646 WMSetButtonText(panel->pipeCacheB, _("Cache menu contents after opening for\n" "the first time"));
648 WMMapSubwidgets(panel->pipeF);
650 /* proplist pipe */
652 panel->plpipeF = WMCreateFrame(panel->optionsF);
653 WMResizeWidget(panel->plpipeF, width, 155);
654 WMMoveWidget(panel->plpipeF, 10, 30);
655 WMSetFrameTitle(panel->plpipeF, _("Command"));
657 panel->plpipeT = WMCreateTextField(panel->plpipeF);
658 WMResizeWidget(panel->plpipeT, width - 20, 20);
659 WMMoveWidget(panel->plpipeT, 10, 20);
661 WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->plpipeT);
663 label = WMCreateLabel(panel->plpipeF);
664 WMResizeWidget(label, width - 20, 40);
665 WMMoveWidget(label, 10, 50);
666 WMSetLabelText(label, _("Enter a command that outputs a proplist menu\n" "definition to stdout when invoked."));
668 panel->plpipeCacheB = WMCreateSwitchButton(panel->plpipeF);
669 WMResizeWidget(panel->plpipeCacheB, width - 20, 40);
670 WMMoveWidget(panel->plpipeCacheB, 10, 110);
671 WMSetButtonText(panel->plpipeCacheB, _("Cache menu contents after opening for\n" "the first time"));
673 WMMapSubwidgets(panel->plpipeF);
675 /* directory menu */
677 panel->dcommandF = WMCreateFrame(panel->optionsF);
678 WMResizeWidget(panel->dcommandF, width, 90);
679 WMMoveWidget(panel->dcommandF, 10, 25);
680 WMSetFrameTitle(panel->dcommandF, _("Command to Open Files"));
682 panel->dcommandT = WMCreateTextField(panel->dcommandF);
683 WMResizeWidget(panel->dcommandT, width - 20, 20);
684 WMMoveWidget(panel->dcommandT, 10, 20);
686 WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->dcommandT);
688 label = WMCreateLabel(panel->dcommandF);
689 WMResizeWidget(label, width - 20, 45);
690 WMMoveWidget(label, 10, 40);
691 WMSetLabelText(label, _("Enter the command you want to use to open the\n"
692 "files in the directories listed below."));
694 WMMapSubwidgets(panel->dcommandF);
696 panel->dpathF = WMCreateFrame(panel->optionsF);
697 WMResizeWidget(panel->dpathF, width, 80);
698 WMMoveWidget(panel->dpathF, 10, 125);
699 WMSetFrameTitle(panel->dpathF, _("Directories with Files"));
701 panel->dpathT = WMCreateTextField(panel->dpathF);
702 WMResizeWidget(panel->dpathT, width - 20, 20);
703 WMMoveWidget(panel->dpathT, 10, 20);
705 WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->dpathT);
707 panel->dstripB = WMCreateSwitchButton(panel->dpathF);
708 WMResizeWidget(panel->dstripB, width - 20, 20);
709 WMMoveWidget(panel->dstripB, 10, 50);
710 WMSetButtonText(panel->dstripB, _("Strip extensions from file names"));
712 WMSetButtonAction(panel->dstripB, buttonClicked, panel);
714 WMMapSubwidgets(panel->dpathF);
716 /* shortcut */
718 panel->shortF = WMCreateFrame(panel->optionsF);
719 WMResizeWidget(panel->shortF, width, 50);
720 WMMoveWidget(panel->shortF, 10, 160);
721 WMSetFrameTitle(panel->shortF, _("Keyboard Shortcut"));
723 panel->shortT = WMCreateTextField(panel->shortF);
724 WMResizeWidget(panel->shortT, width - 20 - 150, 20);
725 WMMoveWidget(panel->shortT, 10, 20);
727 WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->shortT);
729 panel->sgrabB = WMCreateCommandButton(panel->shortF);
730 WMResizeWidget(panel->sgrabB, 70, 24);
731 WMMoveWidget(panel->sgrabB, width - 80, 18);
732 WMSetButtonText(panel->sgrabB, _("Capture"));
733 WMSetButtonAction(panel->sgrabB, sgrabClicked, panel);
735 panel->sclearB = WMCreateCommandButton(panel->shortF);
736 WMResizeWidget(panel->sclearB, 70, 24);
737 WMMoveWidget(panel->sclearB, width - 155, 18);
738 WMSetButtonText(panel->sclearB, _("Clear"));
739 WMSetButtonAction(panel->sclearB, sgrabClicked, panel);
741 WMMapSubwidgets(panel->shortF);
743 /* internal command */
745 panel->icommandL = WMCreateList(panel->optionsF);
746 WMResizeWidget(panel->icommandL, width, 80);
747 WMMoveWidget(panel->icommandL, 10, 20);
749 WMSetListAction(panel->icommandL, icommandLClicked, panel);
751 WMAddNotificationObserver(dataChanged, panel, WMListSelectionDidChangeNotification, panel->icommandL);
753 WMInsertListItem(panel->icommandL, 0, _("Arrange Icons"));
754 WMInsertListItem(panel->icommandL, 1, _("Hide All Windows Except For The Focused One"));
755 WMInsertListItem(panel->icommandL, 2, _("Show All Windows"));
757 WMInsertListItem(panel->icommandL, 3, _("Exit Window Maker"));
758 WMInsertListItem(panel->icommandL, 4, _("Exit X Session"));
759 WMInsertListItem(panel->icommandL, 5, _("Restart Window Maker"));
760 WMInsertListItem(panel->icommandL, 6, _("Start Another Window Manager : ("));
762 WMInsertListItem(panel->icommandL, 7, _("Save Current Session"));
763 WMInsertListItem(panel->icommandL, 8, _("Clear Saved Session"));
764 WMInsertListItem(panel->icommandL, 9, _("Refresh Screen"));
765 WMInsertListItem(panel->icommandL, 10, _("Open Info Panel"));
766 WMInsertListItem(panel->icommandL, 11, _("Open Copyright Panel"));
768 panel->paramF = WMCreateFrame(panel->optionsF);
769 WMResizeWidget(panel->paramF, width, 50);
770 WMMoveWidget(panel->paramF, 10, 105);
771 WMSetFrameTitle(panel->paramF, _("Window Manager to Start"));
773 panel->paramT = WMCreateTextField(panel->paramF);
774 WMResizeWidget(panel->paramT, width - 20, 20);
775 WMMoveWidget(panel->paramT, 10, 20);
777 WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->paramT);
779 WMMapSubwidgets(panel->paramF);
781 panel->quickB = WMCreateSwitchButton(panel->optionsF);
782 WMResizeWidget(panel->quickB, width, 20);
783 WMMoveWidget(panel->quickB, 10, 120);
784 WMSetButtonText(panel->quickB, _("Do not confirm action."));
785 WMSetButtonAction(panel->quickB, buttonClicked, panel);
787 label = WMCreateLabel(panel->optionsF);
788 WMResizeWidget(label, width + 5, FRAME_HEIGHT - 50);
789 WMMoveWidget(label, 7, 20);
790 WMSetLabelText(label,
791 _("Instructions:\n\n"
792 " - drag items from the left to the menu to add new items\n"
793 " - drag items out of the menu to remove items\n"
794 " - drag items in menu to change their position\n"
795 " - drag items with Control pressed to copy them\n"
796 " - double click in a menu item to change the label\n"
797 " - click on a menu item to change related information"));
798 WMMapWidget(label);
800 WMRealizeWidget(panel->box);
801 WMMapSubwidgets(panel->box);
802 WMMapWidget(panel->box);
805 int i;
806 for (i = 0; i < wlengthof(panel->itemPad); i++)
807 WMUnmapWidget(panel->itemPad[i]);
809 changedItemPad(panel->typeP, panel);
811 panel->sections[NoInfo][0] = label;
813 panel->sections[ExecInfo][0] = panel->commandF;
814 panel->sections[ExecInfo][1] = panel->shortF;
816 panel->sections[CommandInfo][0] = panel->icommandL;
817 panel->sections[CommandInfo][1] = panel->shortF;
819 panel->sections[ExternalInfo][0] = panel->pathF;
821 panel->sections[PipeInfo][0] = panel->pipeF;
823 panel->sections[PLPipeInfo][0] = panel->plpipeF;
825 panel->sections[DirectoryInfo][0] = panel->dpathF;
826 panel->sections[DirectoryInfo][1] = panel->dcommandF;
828 panel->currentType = NoInfo;
830 showData(panel);
833 WMPoint pos;
835 pos = WMGetViewScreenPosition(WMWidgetView(panel->box));
837 if (pos.x < 200) {
838 pos.x += FRAME_WIDTH + 20;
839 } else {
840 pos.x = 10;
843 pos.y = WMAX(pos.y - 100, 0);
845 if (panel->menu)
846 WEditMenuShowAt(panel->menu, pos.x, pos.y);
850 static void freeItemData(ItemData * data)
852 #define CFREE(d) if (d) wfree(d)
854 /* TODO */
855 switch (data->type) {
856 case CommandInfo:
857 CFREE(data->param.command.parameter);
858 CFREE(data->param.command.shortcut);
859 break;
861 case ExecInfo:
862 CFREE(data->param.exec.command);
863 CFREE(data->param.exec.shortcut);
864 break;
866 case PipeInfo:
867 CFREE(data->param.pipe.command);
868 break;
870 case PLPipeInfo:
871 CFREE(data->param.pipe.command);
872 break;
874 case ExternalInfo:
875 CFREE(data->param.external.path);
876 break;
878 case DirectoryInfo:
879 CFREE(data->param.directory.command);
880 CFREE(data->param.directory.directory);
881 break;
883 default:
884 break;
887 wfree(data);
888 #undef CFREE
891 static ItemData *parseCommand(WMPropList * item)
893 ItemData *data = wmalloc(sizeof(ItemData));
894 WMPropList *p;
895 char *command = NULL;
896 char *parameter = NULL;
897 char *shortcut = NULL;
898 int i = 1;
900 p = WMGetFromPLArray(item, i++);
901 command = WMGetFromPLString(p);
902 if (strcmp(command, "SHORTCUT") == 0) {
903 p = WMGetFromPLArray(item, i++);
904 shortcut = WMGetFromPLString(p);
905 p = WMGetFromPLArray(item, i++);
906 command = WMGetFromPLString(p);
908 p = WMGetFromPLArray(item, i++);
909 if (p)
910 parameter = WMGetFromPLString(p);
912 if (strcmp(command, "EXEC") == 0 || strcmp(command, "SHEXEC") == 0) {
914 data->type = ExecInfo;
916 data->param.exec.command = wstrdup(parameter);
917 if (shortcut)
918 data->param.exec.shortcut = wstrdup(shortcut);
920 } else if (strcmp(command, "OPEN_MENU") == 0) {
921 char *p;
923 * dir menu, menu file
924 * dir WITH
925 * |pipe
927 p = parameter;
928 while (isspace(*p) && *p)
929 p++;
930 if (*p == '|') {
931 if (*(p + 1) == '|') {
932 p++;
933 data->param.pipe.cached = 0;
934 } else {
935 data->param.pipe.cached = 1;
937 data->type = PipeInfo;
938 data->param.pipe.command = wtrimspace(p + 1);
939 } else {
940 char *s;
942 p = wstrdup(p);
944 s = strstr(p, "WITH");
945 if (s) {
946 char **tokens;
947 char **ctokens;
948 int tokn;
949 int i, j;
951 data->type = DirectoryInfo;
953 *s = '\0';
954 s += 5;
955 while (*s && isspace(*s))
956 s++;
957 data->param.directory.command = wstrdup(s);
959 wtokensplit(p, &tokens, &tokn);
960 wfree(p);
962 ctokens = wmalloc(sizeof(char *) * tokn);
964 for (i = 0, j = 0; i < tokn; i++) {
965 if (strcmp(tokens[i], "-noext") == 0) {
966 data->param.directory.stripExt = 1;
967 } else {
968 ctokens[j++] = tokens[i];
971 data->param.directory.directory = wtokenjoin(ctokens, j);
972 wfree(ctokens);
974 wtokenfree(tokens, tokn);
975 } else {
976 data->type = ExternalInfo;
977 data->param.external.path = p;
980 } else if (strcmp(command, "OPEN_PLMENU") == 0) {
981 char *p;
983 p = parameter;
984 while (isspace(*p) && *p)
985 p++;
986 if (*p == '|') {
987 if (*(p + 1) == '|') {
988 p++;
989 data->param.pipe.cached = 0;
990 } else {
991 data->param.pipe.cached = 1;
993 data->type = PLPipeInfo;
994 data->param.pipe.command = wtrimspace(p + 1);
996 } else if (strcmp(command, "WORKSPACE_MENU") == 0) {
997 data->type = WSMenuInfo;
998 } else if (strcmp(command, "WINDOWS_MENU") == 0) {
999 data->type = WWindowListInfo;
1000 } else {
1001 int cmd;
1003 if (strcmp(command, "ARRANGE_ICONS") == 0) {
1004 cmd = 0;
1005 } else if (strcmp(command, "HIDE_OTHERS") == 0) {
1006 cmd = 1;
1007 } else if (strcmp(command, "SHOW_ALL") == 0) {
1008 cmd = 2;
1009 } else if (strcmp(command, "EXIT") == 0) {
1010 cmd = 3;
1011 } else if (strcmp(command, "SHUTDOWN") == 0) {
1012 cmd = 4;
1013 } else if (strcmp(command, "RESTART") == 0) {
1014 if (parameter) {
1015 cmd = 6;
1016 } else {
1017 cmd = 5;
1019 } else if (strcmp(command, "SAVE_SESSION") == 0) {
1020 cmd = 7;
1021 } else if (strcmp(command, "CLEAR_SESSION") == 0) {
1022 cmd = 8;
1023 } else if (strcmp(command, "REFRESH") == 0) {
1024 cmd = 9;
1025 } else if (strcmp(command, "INFO_PANEL") == 0) {
1026 cmd = 10;
1027 } else if (strcmp(command, "LEGAL_PANEL") == 0) {
1028 cmd = 11;
1029 } else {
1030 wwarning(_("unknown command '%s' in menu"), command);
1031 wfree(data);
1032 return NULL;
1035 data->type = CommandInfo;
1037 data->param.command.command = cmd;
1038 if (shortcut)
1039 data->param.command.shortcut = wstrdup(shortcut);
1040 if (parameter)
1041 data->param.command.parameter = wstrdup(parameter);
1044 return data;
1047 static void updateFrameTitle(_Panel * panel, const char *title, InfoType type)
1049 if (type != NoInfo) {
1050 char *tmp;
1052 switch (type) {
1053 case ExecInfo:
1054 tmp = wstrconcat(title, _(": Execute Program"));
1055 break;
1057 case CommandInfo:
1058 tmp = wstrconcat(title, _(": Perform Internal Command"));
1059 break;
1061 case ExternalInfo:
1062 tmp = wstrconcat(title, _(": Open a Submenu"));
1063 break;
1065 case PipeInfo:
1066 tmp = wstrconcat(title, _(": Program Generated Submenu"));
1067 break;
1069 case PLPipeInfo:
1070 tmp = wstrconcat(title, _(": Program Generated Proplist Submenu"));
1071 break;
1073 case DirectoryInfo:
1074 tmp = wstrconcat(title, _(": Directory Contents Menu"));
1075 break;
1077 case WSMenuInfo:
1078 tmp = wstrconcat(title, _(": Open Workspaces Submenu"));
1079 break;
1081 case WWindowListInfo:
1082 tmp = wstrconcat(title, _(": Open Window List Submenu"));
1083 break;
1085 default:
1086 tmp = NULL;
1087 break;
1089 WMSetFrameTitle(panel->optionsF, tmp);
1090 wfree(tmp);
1091 } else {
1092 WMSetFrameTitle(panel->optionsF, NULL);
1096 static void changeInfoType(_Panel * panel, const char *title, InfoType type)
1098 WMWidget **w;
1100 if (panel->currentType != type) {
1102 w = panel->sections[panel->currentType];
1104 while (*w) {
1105 WMUnmapWidget(*w);
1106 w++;
1108 WMUnmapWidget(panel->paramF);
1109 WMUnmapWidget(panel->quickB);
1111 w = panel->sections[type];
1113 while (*w) {
1114 WMMapWidget(*w);
1115 w++;
1119 updateFrameTitle(panel, title, type);
1121 panel->currentType = type;
1124 static void updateMenuItem(_Panel * panel, WEditMenuItem * item, WMWidget * changedWidget)
1126 ItemData *data = WGetEditMenuItemData(item);
1128 assert(data != NULL);
1130 #define REPLACE(v, d) if (v) wfree(v); v = d
1132 switch (data->type) {
1133 case ExecInfo:
1134 if (changedWidget == panel->commandT) {
1135 REPLACE(data->param.exec.command, WMGetTextFieldText(panel->commandT));
1137 if (changedWidget == panel->shortT) {
1138 REPLACE(data->param.exec.shortcut, WMGetTextFieldText(panel->shortT));
1140 break;
1142 case CommandInfo:
1143 if (changedWidget == panel->icommandL) {
1144 data->param.command.command = WMGetListSelectedItemRow(panel->icommandL);
1146 switch (data->param.command.command) {
1147 case 3:
1148 case 4:
1149 if (changedWidget == panel->quickB) {
1150 REPLACE(data->param.command.parameter, WMGetButtonSelected(panel->quickB)
1151 ? wstrdup("QUICK") : NULL);
1153 break;
1155 case 6:
1156 if (changedWidget == panel->paramT) {
1157 REPLACE(data->param.command.parameter, WMGetTextFieldText(panel->paramT));
1159 break;
1161 if (changedWidget == panel->shortT) {
1162 REPLACE(data->param.command.shortcut, WMGetTextFieldText(panel->shortT));
1165 break;
1167 case PipeInfo:
1168 if (changedWidget == panel->pipeT) {
1169 REPLACE(data->param.pipe.command, WMGetTextFieldText(panel->pipeT));
1171 if (changedWidget == panel->pipeCacheB) {
1172 data->param.pipe.cached = WMGetButtonSelected(panel->pipeCacheB);
1174 break;
1176 case PLPipeInfo:
1177 if (changedWidget == panel->plpipeT) {
1178 REPLACE(data->param.pipe.command, WMGetTextFieldText(panel->plpipeT));
1180 if (changedWidget == panel->plpipeCacheB) {
1181 data->param.pipe.cached = WMGetButtonSelected(panel->plpipeCacheB);
1183 break;
1185 case ExternalInfo:
1186 if (changedWidget == panel->pathT) {
1187 REPLACE(data->param.external.path, WMGetTextFieldText(panel->pathT));
1189 break;
1191 case DirectoryInfo:
1192 if (changedWidget == panel->dpathT) {
1193 REPLACE(data->param.directory.directory, WMGetTextFieldText(panel->dpathT));
1195 if (changedWidget == panel->dcommandT) {
1196 REPLACE(data->param.directory.command, WMGetTextFieldText(panel->dcommandT));
1198 if (changedWidget == panel->dstripB) {
1199 data->param.directory.stripExt = WMGetButtonSelected(panel->dstripB);
1201 break;
1203 default:
1204 assert(0);
1205 break;
1208 #undef REPLACE
1211 static void
1212 menuItemCloned(WEditMenuDelegate * delegate, WEditMenu * menu, WEditMenuItem * origItem, WEditMenuItem * newItem)
1214 ItemData *data = WGetEditMenuItemData(origItem);
1215 ItemData *newData;
1217 /* Parameter not used, but tell the compiler that it is ok */
1218 (void) delegate;
1219 (void) menu;
1221 if (!data)
1222 return;
1224 #define DUP(s) (s) ? wstrdup(s) : NULL
1226 newData = wmalloc(sizeof(ItemData));
1228 newData->type = data->type;
1230 switch (data->type) {
1231 case ExecInfo:
1232 newData->param.exec.command = DUP(data->param.exec.command);
1233 newData->param.exec.shortcut = DUP(data->param.exec.shortcut);
1234 break;
1236 case CommandInfo:
1237 newData->param.command.command = data->param.command.command;
1238 newData->param.command.parameter = DUP(data->param.command.parameter);
1239 newData->param.command.shortcut = DUP(data->param.command.shortcut);
1240 break;
1242 case PipeInfo:
1243 newData->param.pipe.command = DUP(data->param.pipe.command);
1244 newData->param.pipe.cached = data->param.pipe.cached;
1245 break;
1247 case PLPipeInfo:
1248 newData->param.pipe.command = DUP(data->param.pipe.command);
1249 newData->param.pipe.cached = data->param.pipe.cached;
1250 break;
1252 case ExternalInfo:
1253 newData->param.external.path = DUP(data->param.external.path);
1254 break;
1256 case DirectoryInfo:
1257 newData->param.directory.directory = DUP(data->param.directory.directory);
1258 newData->param.directory.command = DUP(data->param.directory.command);
1259 newData->param.directory.stripExt = data->param.directory.stripExt;
1260 break;
1262 default:
1263 break;
1266 #undef DUP
1268 WSetEditMenuItemData(newItem, newData, (WMCallback *) freeItemData);
1271 static void menuItemEdited(struct WEditMenuDelegate *delegate, WEditMenu * menu, WEditMenuItem * item)
1273 _Panel *panel = (_Panel *) delegate->data;
1274 WEditMenu *submenu;
1276 /* Parameter not used, but tell the compiler it is ok */
1277 (void) menu;
1279 updateFrameTitle(panel, WGetEditMenuItemTitle(item), panel->currentType);
1281 submenu = WGetEditMenuSubmenu(item);
1282 if (submenu) {
1283 WSetEditMenuTitle(submenu, WGetEditMenuItemTitle(item));
1287 static Bool shouldRemoveItem(struct WEditMenuDelegate *delegate, WEditMenu * menu, WEditMenuItem * item)
1289 _Panel *panel = (_Panel *) delegate->data;
1291 if (panel->dontAsk)
1292 return True;
1294 if (WGetEditMenuSubmenu(item)) {
1295 int res;
1297 res = WMRunAlertPanel(WMWidgetScreen(menu), NULL,
1298 _("Remove Submenu"),
1299 _("Removing this item will destroy all items inside\n"
1300 "the submenu. Do you really want to do that?"),
1301 _("Yes"), _("No"), _("Yes, don't ask again."));
1302 switch (res) {
1303 case WAPRDefault:
1304 return True;
1305 case WAPRAlternate:
1306 return False;
1307 case WAPROther:
1308 panel->dontAsk = True;
1309 return True;
1312 return True;
1315 static void menuItemDeselected(WEditMenuDelegate * delegate, WEditMenu * menu, WEditMenuItem * item)
1317 _Panel *panel = (_Panel *) delegate->data;
1319 /* Parameter not used, but tell the compiler that it is ok */
1320 (void) menu;
1321 (void) item;
1323 changeInfoType(panel, NULL, NoInfo);
1326 static void menuItemSelected(WEditMenuDelegate * delegate, WEditMenu * menu, WEditMenuItem * item)
1328 ItemData *data = WGetEditMenuItemData(item);
1329 _Panel *panel = (_Panel *) delegate->data;
1331 /* Parameter not used, but tell the compiler that it is ok */
1332 (void) menu;
1334 panel->currentItem = item;
1336 if (data) {
1337 changeInfoType(panel, WGetEditMenuItemTitle(item), data->type);
1339 switch (data->type) {
1340 case NoInfo:
1341 break;
1343 case ExecInfo:
1344 WMSetTextFieldText(panel->commandT, data->param.exec.command);
1345 WMSetTextFieldText(panel->shortT, data->param.exec.shortcut);
1346 break;
1348 case CommandInfo:
1349 WMSelectListItem(panel->icommandL, data->param.command.command);
1350 WMSetListPosition(panel->icommandL, data->param.command.command - 2);
1351 WMSetTextFieldText(panel->shortT, data->param.command.shortcut);
1353 switch (data->param.command.command) {
1354 case 3:
1355 case 4:
1356 WMSetButtonSelected(panel->quickB, data->param.command.parameter != NULL);
1357 break;
1358 case 6:
1359 WMSetTextFieldText(panel->paramT, data->param.command.parameter);
1360 break;
1363 icommandLClicked(panel->icommandL, panel);
1364 break;
1366 case PipeInfo:
1367 WMSetTextFieldText(panel->pipeT, data->param.pipe.command);
1368 WMSetButtonSelected(panel->pipeCacheB, data->param.pipe.cached);
1369 break;
1371 case PLPipeInfo:
1372 WMSetTextFieldText(panel->plpipeT, data->param.pipe.command);
1373 WMSetButtonSelected(panel->plpipeCacheB, data->param.pipe.cached);
1374 break;
1376 case ExternalInfo:
1377 WMSetTextFieldText(panel->pathT, data->param.external.path);
1378 break;
1380 case DirectoryInfo:
1381 WMSetTextFieldText(panel->dpathT, data->param.directory.directory);
1382 WMSetTextFieldText(panel->dcommandT, data->param.directory.command);
1383 WMSetButtonSelected(panel->dstripB, data->param.directory.stripExt);
1384 break;
1386 case WSMenuInfo:
1387 break;
1389 default:
1390 break;
1395 static WEditMenu *buildSubmenu(_Panel * panel, WMPropList * pl)
1397 WMScreen *scr = WMWidgetScreen(panel->parent);
1398 WEditMenu *menu;
1399 WEditMenuItem *item;
1400 char *title;
1401 WMPropList *tp, *bp;
1402 int i;
1404 tp = WMGetFromPLArray(pl, 0);
1405 title = WMGetFromPLString(tp);
1407 menu = WCreateEditMenu(scr, title);
1409 for (i = 1; i < WMGetPropListItemCount(pl); i++) {
1410 WMPropList *pi;
1412 pi = WMGetFromPLArray(pl, i);
1414 tp = WMGetFromPLArray(pi, 0);
1415 bp = WMGetFromPLArray(pi, 1);
1417 title = WMGetFromPLString(tp);
1419 if (!bp || WMIsPLArray(bp)) { /* it's a submenu */
1420 WEditMenu *submenu;
1422 submenu = buildSubmenu(panel, pi);
1424 item = WAddMenuItemWithTitle(menu, title);
1426 WSetEditMenuSubmenu(menu, item, submenu);
1427 } else {
1428 ItemData *data;
1430 data = parseCommand(pi);
1432 if (data != NULL) {
1433 item = WAddMenuItemWithTitle(menu, title);
1434 if (panel->markerPix[data->type])
1435 WSetEditMenuItemImage(item, panel->markerPix[data->type]);
1436 WSetEditMenuItemData(item, data, (WMCallback *) freeItemData);
1437 } else {
1438 char *buf = wmalloc(1024);
1439 snprintf(buf, 1024, _("Invalid menu command \"%s\" with label \"%s\" cleared"),
1440 WMGetFromPLString(WMGetFromPLArray(pi, 1)),
1441 WMGetFromPLString(WMGetFromPLArray(pi, 0)));
1442 WMRunAlertPanel(scr, panel->parent, _("Warning"), buf, _("OK"), NULL, NULL);
1443 wfree(buf);
1449 WSetEditMenuAcceptsDrop(menu, True);
1450 WSetEditMenuDelegate(menu, &menuDelegate);
1452 WMRealizeWidget(menu);
1454 return menu;
1457 static void buildMenuFromPL(_Panel * panel, WMPropList * pl)
1459 panel->menu = buildSubmenu(panel, pl);
1462 static WMPropList *getDefaultMenu(_Panel * panel)
1464 WMPropList *menu;
1465 static const char menuPath[] = WMAKER_RESOURCE_PATH "/plmenu";
1467 menu = WMReadPropListFromFile(menuPath);
1468 if (!menu) {
1469 char *buffer, *msg;
1471 msg = _("Could not open default menu from '%s'");
1472 buffer = wmalloc(strlen(msg) + strlen(menuPath) + 10);
1473 sprintf(buffer, msg, menuPath);
1474 WMRunAlertPanel(WMWidgetScreen(panel->parent), panel->parent,
1475 _("Error"), buffer, _("OK"), NULL, NULL);
1476 wfree(buffer);
1479 return menu;
1482 static void showData(_Panel * panel)
1484 const char *gspath;
1485 char *menuPath;
1486 WMPropList *pmenu;
1488 gspath = wusergnusteppath();
1490 menuPath = wmalloc(strlen(gspath) + 32);
1491 strcpy(menuPath, gspath);
1492 strcat(menuPath, "/Defaults/WMRootMenu");
1494 pmenu = WMReadPropListFromFile(menuPath);
1496 if (!pmenu || !WMIsPLArray(pmenu)) {
1497 int res;
1499 res = WMRunAlertPanel(WMWidgetScreen(panel->parent), panel->parent,
1500 _("Warning"),
1501 _("The menu file format currently in use is not supported\n"
1502 "by this tool. Do you want to discard the current menu\n"
1503 "to use this tool?"),
1504 _("Yes, Discard and Update"), _("No, Keep Current Menu"), NULL);
1506 if (res == WAPRDefault) {
1507 pmenu = getDefaultMenu(panel);
1509 if (!pmenu) {
1510 pmenu = WMCreatePLArray(WMCreatePLString("Applications"), NULL);
1512 } else {
1513 panel->dontSave = True;
1514 return;
1518 panel->menuPath = menuPath;
1520 buildMenuFromPL(panel, pmenu);
1522 WMReleasePropList(pmenu);
1525 static Bool notblank(const char *s)
1527 if (s) {
1528 while (*s++) {
1529 if (!isspace(*s))
1530 return True;
1533 return False;
1536 static WMPropList *processData(const char *title, ItemData * data)
1538 WMPropList *item;
1539 char *s1;
1540 static WMPropList *pscut = NULL;
1541 static WMPropList *pomenu = NULL;
1542 static WMPropList *poplmenu = NULL;
1543 int i;
1545 if (data == NULL)
1546 return NULL;
1548 if (!pscut) {
1549 pscut = WMCreatePLString("SHORTCUT");
1550 pomenu = WMCreatePLString("OPEN_MENU");
1551 poplmenu = WMCreatePLString("OPEN_PLMENU");
1554 item = WMCreatePLArray(WMCreatePLString(title), NULL);
1556 switch (data->type) {
1557 case ExecInfo:
1558 if (data->param.exec.command == NULL)
1559 goto return_null;
1560 #if 1
1561 if (strpbrk(data->param.exec.command, "&$*|><?`=;")) {
1562 s1 = "SHEXEC";
1563 } else {
1564 s1 = "EXEC";
1566 #else
1567 s1 = "SHEXEC";
1568 #endif
1570 if (notblank(data->param.exec.shortcut)) {
1571 WMAddToPLArray(item, pscut);
1572 WMAddToPLArray(item, WMCreatePLString(data->param.exec.shortcut));
1575 WMAddToPLArray(item, WMCreatePLString(s1));
1576 WMAddToPLArray(item, WMCreatePLString(data->param.exec.command));
1577 break;
1579 case CommandInfo:
1580 if (notblank(data->param.command.shortcut)) {
1581 WMAddToPLArray(item, pscut);
1582 WMAddToPLArray(item, WMCreatePLString(data->param.command.shortcut));
1585 i = data->param.command.command;
1587 WMAddToPLArray(item, WMCreatePLString(commandNames[i]));
1589 switch (i) {
1590 case 3:
1591 case 4:
1592 if (data->param.command.parameter) {
1593 WMAddToPLArray(item, WMCreatePLString(data->param.command.parameter));
1595 break;
1597 case 6: /* restart */
1598 if (data->param.command.parameter) {
1599 WMAddToPLArray(item, WMCreatePLString(data->param.command.parameter));
1601 break;
1604 break;
1606 case PipeInfo:
1607 case PLPipeInfo:
1608 if (!data->param.pipe.command)
1609 goto return_null;
1610 if (data->type == PLPipeInfo)
1611 WMAddToPLArray(item, poplmenu);
1612 else
1613 WMAddToPLArray(item, pomenu);
1615 if (data->param.pipe.cached)
1616 s1 = wstrconcat("| ", data->param.pipe.command);
1617 else
1618 s1 = wstrconcat("|| ", data->param.pipe.command);
1619 WMAddToPLArray(item, WMCreatePLString(s1));
1620 wfree(s1);
1621 break;
1623 case ExternalInfo:
1624 if (!data->param.external.path)
1625 goto return_null;
1626 WMAddToPLArray(item, pomenu);
1627 WMAddToPLArray(item, WMCreatePLString(data->param.external.path));
1628 break;
1630 case DirectoryInfo:
1632 int l;
1633 char *tmp;
1635 if (!data->param.directory.directory || !data->param.directory.command)
1636 goto return_null;
1638 l = strlen(data->param.directory.directory);
1639 l += strlen(data->param.directory.command);
1640 l += 32;
1642 WMAddToPLArray(item, pomenu);
1644 tmp = wmalloc(l);
1645 sprintf(tmp, "%s%s WITH %s",
1646 data->param.directory.stripExt ? "-noext " : "",
1647 data->param.directory.directory, data->param.directory.command);
1649 WMAddToPLArray(item, WMCreatePLString(tmp));
1650 wfree(tmp);
1652 break;
1654 case WSMenuInfo:
1655 WMAddToPLArray(item, WMCreatePLString("WORKSPACE_MENU"));
1656 break;
1658 case WWindowListInfo:
1659 WMAddToPLArray(item, WMCreatePLString("WINDOWS_MENU"));
1660 break;
1662 default:
1663 assert(0);
1664 break;
1667 return item;
1669 return_null:
1670 WMReleasePropList(item);
1671 return NULL;
1674 static WMPropList *processSubmenu(WEditMenu * menu)
1676 WEditMenuItem *item;
1677 WMPropList *pmenu;
1678 WMPropList *pl;
1679 char *s;
1680 int i;
1682 s = WGetEditMenuTitle(menu);
1683 pl = WMCreatePLString(s);
1685 pmenu = WMCreatePLArray(pl, NULL);
1687 i = 0;
1688 while ((item = WGetEditMenuItem(menu, i++))) {
1689 WEditMenu *submenu;
1691 s = WGetEditMenuItemTitle(item);
1693 submenu = WGetEditMenuSubmenu(item);
1694 if (submenu) {
1695 pl = processSubmenu(submenu);
1696 } else {
1697 pl = processData(s, WGetEditMenuItemData(item));
1700 if (!pl)
1701 continue;
1703 WMAddToPLArray(pmenu, pl);
1706 return pmenu;
1709 static WMPropList *buildPLFromMenu(_Panel * panel)
1711 WMPropList *menu;
1713 menu = processSubmenu(panel->menu);
1715 return menu;
1718 static void storeData(_Panel * panel)
1720 WMPropList *menu;
1722 if (panel->dontSave)
1723 return;
1725 menu = buildPLFromMenu(panel);
1727 WMWritePropListToFile(menu, panel->menuPath);
1729 WMReleasePropList(menu);
1732 static void showMenus(_Panel * panel)
1734 if (panel->menu)
1735 WEditMenuUnhide(panel->menu);
1738 static void hideMenus(_Panel * panel)
1740 if (panel->menu)
1741 WEditMenuHide(panel->menu);
1744 Panel *InitMenu(WMWidget *parent)
1746 _Panel *panel;
1748 panel = wmalloc(sizeof(_Panel));
1750 panel->sectionName = _("Applications Menu Definition");
1752 panel->description = _("Edit the menu for launching applications.");
1754 panel->parent = parent;
1756 panel->callbacks.createWidgets = createPanel;
1757 panel->callbacks.updateDomain = storeData;
1758 panel->callbacks.showPanel = showMenus;
1759 panel->callbacks.hidePanel = hideMenus;
1761 AddSection(panel, ICON_FILE);
1763 return panel;