debian: Small updates in menus etc
[wmaker-crm.git] / WPrefs.app / Menu.c
blob342e7f0f06fab893d954d75c71a76d03c24671bf
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 DirectoryInfo,
38 WSMenuInfo,
39 WWindowListInfo,
40 LastInfo
41 } InfoType;
43 #define MAX_SECTION_SIZE 4
44 #define PATH_LEN 256
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 *dpathF;
86 WMTextField *dpathT;
88 WMFrame *dcommandF;
89 WMTextField *dcommandT;
91 WMButton *dstripB;
93 WMFrame *shortF;
94 WMTextField *shortT;
95 WMButton *sgrabB;
96 WMButton *sclearB;
98 WMList *icommandL;
100 WMFrame *paramF;
101 WMTextField *paramT;
103 WMButton *quickB;
105 Bool dontAsk; /* whether to comfirm submenu remove */
106 Bool dontSave;
108 Bool capturing;
110 /* about the currently selected item */
111 WEditMenuItem *currentItem;
112 InfoType currentType;
113 WMWidget *sections[LastInfo][MAX_SECTION_SIZE];
114 } _Panel;
116 typedef struct {
117 InfoType type;
118 union {
119 struct {
120 int command;
121 char *parameter;
122 char *shortcut;
123 } command;
124 struct {
125 char *command;
126 char *shortcut;
127 } exec;
128 struct {
129 char *path;
130 } external;
131 struct {
132 char *command;
133 unsigned cached:1;
134 } pipe;
135 struct {
136 char *directory;
137 char *command;
138 unsigned stripExt:1;
139 } directory;
140 } param;
141 } ItemData;
143 static char *commandNames[] = {
144 "ARRANGE_ICONS",
145 "HIDE_OTHERS",
146 "SHOW_ALL",
147 "EXIT",
148 "SHUTDOWN",
149 "RESTART",
150 "RESTART",
151 "SAVE_SESSION",
152 "CLEAR_SESSION",
153 "REFRESH",
154 "INFO_PANEL",
155 "LEGAL_PANEL"
158 #define NEW(type) memset(wmalloc(sizeof(type)), 0, sizeof(type))
160 #define ICON_FILE "menus"
162 static void showData(_Panel * panel);
164 static void updateMenuItem(_Panel * panel, WEditMenuItem * item, WMWidget * changedWidget);
166 static void menuItemSelected(struct WEditMenuDelegate *delegate, WEditMenu * menu, WEditMenuItem * item);
168 static void menuItemDeselected(struct WEditMenuDelegate *delegate, WEditMenu * menu, WEditMenuItem * item);
170 static void menuItemCloned(struct WEditMenuDelegate *delegate, WEditMenu * menu,
171 WEditMenuItem * origItem, WEditMenuItem * newItem);
173 static void menuItemEdited(struct WEditMenuDelegate *delegate, WEditMenu * menu, WEditMenuItem * item);
175 static Bool shouldRemoveItem(struct WEditMenuDelegate *delegate, WEditMenu * menu, WEditMenuItem * item);
177 static void freeItemData(ItemData * data);
179 extern char *capture_shortcut(Display *dpy, Bool *capturing, Bool convert_case);
181 static WEditMenuDelegate menuDelegate = {
182 NULL,
183 menuItemCloned,
184 menuItemEdited,
185 menuItemSelected,
186 menuItemDeselected,
187 shouldRemoveItem
190 static void dataChanged(void *self, WMNotification * notif)
192 _Panel *panel = (_Panel *) self;
193 WEditMenuItem *item = panel->currentItem;
194 WMWidget *w = (WMWidget *) WMGetNotificationObject(notif);
196 updateMenuItem(panel, item, w);
199 static void buttonClicked(WMWidget * w, void *data)
201 _Panel *panel = (_Panel *) data;
202 WEditMenuItem *item = panel->currentItem;
204 updateMenuItem(panel, item, w);
207 static void icommandLClicked(WMWidget * w, void *data)
209 _Panel *panel = (_Panel *) data;
210 int cmd;
212 cmd = WMGetListSelectedItemRow(w);
213 if (cmd == 3 || cmd == 4) {
214 WMMapWidget(panel->quickB);
215 } else {
216 WMUnmapWidget(panel->quickB);
218 if (cmd == 6) {
219 WMMapWidget(panel->paramF);
220 } else {
221 WMUnmapWidget(panel->paramF);
225 static void browseForFile(WMWidget * self, void *clientData)
227 _Panel *panel = (_Panel *) clientData;
228 WMFilePanel *filePanel;
229 char *text, *oldprog, *newprog;
231 filePanel = WMGetOpenPanel(WMWidgetScreen(self));
232 text = WMGetTextFieldText(panel->commandT);
234 oldprog = wtrimspace(text);
235 wfree(text);
237 if (oldprog[0] == 0 || oldprog[0] != '/') {
238 wfree(oldprog);
239 oldprog = wstrdup("/");
240 } else {
241 char *ptr = oldprog;
242 while (*ptr && !isspace(*ptr))
243 ptr++;
244 *ptr = 0;
247 WMSetFilePanelCanChooseDirectories(filePanel, False);
249 if (WMRunModalFilePanelForDirectory(filePanel, panel->parent, oldprog, _("Select Program"), NULL) == True) {
250 newprog = WMGetFilePanelFileName(filePanel);
251 WMSetTextFieldText(panel->commandT, newprog);
252 updateMenuItem(panel, panel->currentItem, panel->commandT);
253 wfree(newprog);
256 wfree(oldprog);
259 static void sgrabClicked(WMWidget * w, void *data)
261 _Panel *panel = (_Panel *) data;
262 Display *dpy = WMScreenDisplay(WMWidgetScreen(panel->parent));
263 char *shortcut;
265 if (w == panel->sclearB) {
266 WMSetTextFieldText(panel->shortT, "");
267 updateMenuItem(panel, panel->currentItem, panel->shortT);
268 return;
271 if (!panel->capturing) {
272 panel->capturing = 1;
273 WMSetButtonText(w, _("Cancel"));
274 XGrabKeyboard(dpy, WMWidgetXID(panel->parent), True, GrabModeAsync, GrabModeAsync, CurrentTime);
275 shortcut = capture_shortcut(dpy, &panel->capturing, 0);
276 if (shortcut) {
277 WMSetTextFieldText(panel->shortT, shortcut);
278 updateMenuItem(panel, panel->currentItem, panel->shortT);
279 wfree(shortcut);
282 panel->capturing = 0;
283 WMSetButtonText(w, _("Capture"));
284 XUngrabKeyboard(dpy, CurrentTime);
287 static void changedItemPad(WMWidget * w, void *data)
289 _Panel *panel = (_Panel *) data;
290 int padn = WMGetPopUpButtonSelectedItem(w);
292 WMUnmapWidget(panel->itemPad[panel->currentPad]);
293 WMMapWidget(panel->itemPad[padn]);
295 panel->currentPad = padn;
298 static WEditMenu *putNewSubmenu(WEditMenu * menu, char *title)
300 WEditMenu *tmp;
301 WEditMenuItem *item;
303 item = WAddMenuItemWithTitle(menu, title);
305 tmp = WCreateEditMenu(WMWidgetScreen(menu), title);
306 WSetEditMenuAcceptsDrop(tmp, True);
307 WSetEditMenuDelegate(tmp, &menuDelegate);
308 WSetEditMenuSubmenu(menu, item, tmp);
310 return tmp;
313 static ItemData *putNewItem(_Panel * panel, WEditMenu * menu, int type, char *title)
315 WEditMenuItem *item;
316 ItemData *data;
318 item = WAddMenuItemWithTitle(menu, title);
320 data = NEW(ItemData);
321 data->type = type;
322 WSetEditMenuItemData(item, data, (WMCallback *) freeItemData);
323 WSetEditMenuItemImage(item, panel->markerPix[type]);
325 return data;
328 static WEditMenu *makeFactoryMenu(WMWidget * parent, int width)
330 WEditMenu *pad;
332 pad = WCreateEditMenuPad(parent);
333 WMResizeWidget(pad, width, 10);
334 WSetEditMenuMinSize(pad, wmksize(width, 0));
335 WSetEditMenuMaxSize(pad, wmksize(width, 0));
336 WSetEditMenuSelectable(pad, False);
337 WSetEditMenuEditable(pad, False);
338 WSetEditMenuIsFactory(pad, True);
339 WSetEditMenuDelegate(pad, &menuDelegate);
341 return pad;
344 static void createPanel(_Panel * p)
346 _Panel *panel = (_Panel *) p;
347 WMScreen *scr = WMWidgetScreen(panel->parent);
348 WMColor *black = WMBlackColor(scr);
349 WMColor *white = WMWhiteColor(scr);
350 WMColor *gray = WMGrayColor(scr);
351 WMFont *bold = WMBoldSystemFontOfSize(scr, 12);
352 WMFont *font = WMSystemFontOfSize(scr, 12);
353 WMLabel *label;
354 int width;
356 menuDelegate.data = panel;
358 panel->boldFont = bold;
359 panel->normalFont = font;
361 panel->black = black;
362 panel->white = white;
363 panel->gray = gray;
366 Pixmap pix;
367 Display *dpy = WMScreenDisplay(scr);
368 GC gc;
369 WMPixmap *pixm;
371 pixm = WMCreatePixmap(scr, 7, 7, WMScreenDepth(scr), True);
373 pix = WMGetPixmapXID(pixm);
375 XDrawLine(dpy, pix, WMColorGC(black), 0, 3, 6, 3);
376 XDrawLine(dpy, pix, WMColorGC(black), 3, 0, 3, 6);
378 XDrawLine(dpy, pix, WMColorGC(black), 1, 0, 3, 3);
379 XDrawLine(dpy, pix, WMColorGC(black), 1, 6, 3, 3);
380 XDrawLine(dpy, pix, WMColorGC(black), 0, 0, 0, 6);
383 pix = WMGetPixmapMaskXID(pixm);
385 gc = XCreateGC(dpy, pix, 0, NULL);
387 XSetForeground(dpy, gc, 0);
388 XFillRectangle(dpy, pix, gc, 0, 0, 7, 7);
390 XSetForeground(dpy, gc, 1);
391 XDrawLine(dpy, pix, gc, 0, 3, 6, 3);
392 XDrawLine(dpy, pix, gc, 3, 0, 3, 6);
394 panel->markerPix[ExternalInfo] = pixm;
395 panel->markerPix[PipeInfo] = pixm;
396 panel->markerPix[DirectoryInfo] = pixm;
397 panel->markerPix[WSMenuInfo] = pixm;
398 panel->markerPix[WWindowListInfo] = pixm;
400 XFreeGC(dpy, gc);
403 panel->box = WMCreateBox(panel->parent);
404 WMSetViewExpandsToParent(WMWidgetView(panel->box), 2, 2, 2, 2);
406 panel->typeP = WMCreatePopUpButton(panel->box);
407 WMResizeWidget(panel->typeP, 150, 20);
408 WMMoveWidget(panel->typeP, 10, 10);
410 WMAddPopUpButtonItem(panel->typeP, _("New Items"));
411 WMAddPopUpButtonItem(panel->typeP, _("Sample Commands"));
412 WMAddPopUpButtonItem(panel->typeP, _("Sample Submenus"));
414 WMSetPopUpButtonAction(panel->typeP, changedItemPad, panel);
416 WMSetPopUpButtonSelectedItem(panel->typeP, 0);
419 WEditMenu *pad;
421 pad = makeFactoryMenu(panel->box, 150);
422 WMMoveWidget(pad, 10, 40);
424 putNewItem(panel, pad, ExecInfo, _("Run Program"));
425 putNewItem(panel, pad, CommandInfo, _("Internal Command"));
426 putNewSubmenu(pad, _("Submenu"));
427 putNewItem(panel, pad, ExternalInfo, _("External Submenu"));
428 putNewItem(panel, pad, PipeInfo, _("Generated Submenu"));
429 putNewItem(panel, pad, DirectoryInfo, _("Directory Contents"));
430 putNewItem(panel, pad, WSMenuInfo, _("Workspace Menu"));
431 putNewItem(panel, pad, WWindowListInfo, _("Window List Menu"));
433 panel->itemPad[0] = pad;
437 WEditMenu *pad;
438 ItemData *data;
439 WMScrollView *sview;
441 sview = WMCreateScrollView(panel->box);
442 WMResizeWidget(sview, 150, 180);
443 WMMoveWidget(sview, 10, 40);
444 WMSetScrollViewHasVerticalScroller(sview, True);
446 pad = makeFactoryMenu(panel->box, 130);
448 WMSetScrollViewContentView(sview, WMWidgetView(pad));
450 data = putNewItem(panel, pad, ExecInfo, _("XTerm"));
451 data->param.exec.command = "xterm -sb -sl 2000 -bg black -fg white";
453 data = putNewItem(panel, pad, ExecInfo, _("rxvt"));
454 data->param.exec.command = "rxvt";
456 data = putNewItem(panel, pad, ExecInfo, _("ETerm"));
457 data->param.exec.command = "eterm";
459 data = putNewItem(panel, pad, ExecInfo, _("Run..."));
460 data->param.exec.command = _("%A(Run,Type command to run)");
462 data = putNewItem(panel, pad, ExecInfo, _("Firefox"));
463 data->param.exec.command = "firefox";
465 data = putNewItem(panel, pad, ExecInfo, _("gimp"));
466 data->param.exec.command = "gimp";
468 data = putNewItem(panel, pad, ExecInfo, _("epic"));
469 data->param.exec.command = "xterm -e epic";
471 data = putNewItem(panel, pad, ExecInfo, _("ee"));
472 data->param.exec.command = "ee";
474 data = putNewItem(panel, pad, ExecInfo, _("xv"));
475 data->param.exec.command = "xv";
477 data = putNewItem(panel, pad, ExecInfo, _("Evince"));
478 data->param.exec.command = "evince";
480 data = putNewItem(panel, pad, ExecInfo, _("ghostview"));
481 data->param.exec.command = "gv";
483 data = putNewItem(panel, pad, CommandInfo, _("Exit Window Maker"));
484 data->param.command.command = 3;
486 WMMapWidget(pad);
488 panel->itemPad[1] = sview;
492 WEditMenu *pad, *smenu;
493 ItemData *data;
494 WMScrollView *sview;
496 sview = WMCreateScrollView(panel->box);
497 WMResizeWidget(sview, 150, 180);
498 WMMoveWidget(sview, 10, 40);
499 WMSetScrollViewHasVerticalScroller(sview, True);
501 pad = makeFactoryMenu(panel->box, 130);
503 WMSetScrollViewContentView(sview, WMWidgetView(pad));
505 data = putNewItem(panel, pad, ExternalInfo, _("Debian Menu"));
506 data->param.pipe.command = "/etc/X11/WindowMaker/menu.hook";
508 data = putNewItem(panel, pad, PipeInfo, _("RedHat Menu"));
509 data->param.pipe.command = "wmconfig --output wmaker";
511 data = putNewItem(panel, pad, PipeInfo, _("Menu Conectiva"));
512 data->param.pipe.command = "wmconfig --output wmaker";
514 data = putNewItem(panel, pad, DirectoryInfo, _("Themes"));
515 data->param.directory.command = "setstyle";
516 data->param.directory.directory =
517 "/usr/share/WindowMaker/Themes /usr/local/share/WindowMaker/Themes $HOME/GNUstep/Library/WindowMaker/Themes";
518 data->param.directory.stripExt = 1;
520 data = putNewItem(panel, pad, DirectoryInfo, _("Bg Images (scale)"));
521 data->param.directory.command = "wmsetbg -u -s";
522 data->param.directory.directory =
523 "/opt/kde2/share/wallpapers /usr/share/WindowMaker/Backgrounds $HOME/GNUstep/Library/WindowMaker/Backgrounds";
524 data->param.directory.stripExt = 1;
526 data = putNewItem(panel, pad, DirectoryInfo, _("Bg Images (tile)"));
527 data->param.directory.command = "wmsetbg -u -t";
528 data->param.directory.directory =
529 "/opt/kde2/share/wallpapers /usr/share/WindowMaker/Backgrounds $HOME/GNUstep/Library/WindowMaker/Backgrounds";
530 data->param.directory.stripExt = 1;
532 smenu = putNewSubmenu(pad, _("Assorted XTerms"));
534 data = putNewItem(panel, smenu, ExecInfo, _("XTerm Yellow on Blue"));
535 data->param.exec.command = "xterm -sb -sl 2000 -bg midnightblue -fg yellow";
537 data = putNewItem(panel, smenu, ExecInfo, _("XTerm White on Black"));
538 data->param.exec.command = "xterm -sb -sl 2000 -bg black -fg white";
540 data = putNewItem(panel, smenu, ExecInfo, _("XTerm Black on White"));
541 data->param.exec.command = "xterm -sb -sl 2000 -bg white -fg black";
543 data = putNewItem(panel, smenu, ExecInfo, _("XTerm Black on Beige"));
544 data->param.exec.command = "xterm -sb -sl 2000 -bg '#bbbb99' -fg black";
546 data = putNewItem(panel, smenu, ExecInfo, _("XTerm White on Green"));
547 data->param.exec.command = "xterm -sb -sl 2000 -bg '#228822' -fg white";
549 data = putNewItem(panel, smenu, ExecInfo, _("XTerm White on Olive"));
550 data->param.exec.command = "xterm -sb -sl 2000 -bg '#335533' -fg white";
552 data = putNewItem(panel, smenu, ExecInfo, _("XTerm Blue on Blue"));
553 data->param.exec.command = "xterm -sb -sl 2000 -bg '#112244' -fg '#88aabb'";
555 data = putNewItem(panel, smenu, ExecInfo, _("XTerm BIG FONTS"));
556 data->param.exec.command = "xterm -sb -sl 2000 -bg black -fg white -fn 10x20";
558 WMMapWidget(pad);
560 panel->itemPad[2] = sview;
563 width = FRAME_WIDTH - 20 - 150 - 10 - 2;
565 panel->optionsF = WMCreateFrame(panel->box);
566 WMResizeWidget(panel->optionsF, width, FRAME_HEIGHT - 15);
567 WMMoveWidget(panel->optionsF, 10 + 150 + 10, 5);
569 width -= 20;
571 /* command */
573 panel->commandF = WMCreateFrame(panel->optionsF);
574 WMResizeWidget(panel->commandF, width, 50);
575 WMMoveWidget(panel->commandF, 10, 20);
576 WMSetFrameTitle(panel->commandF, _("Program to Run"));
577 WMSetFrameTitlePosition(panel->commandF, WTPAtTop);
579 panel->commandT = WMCreateTextField(panel->commandF);
580 WMResizeWidget(panel->commandT, width - 95, 20);
581 WMMoveWidget(panel->commandT, 10, 20);
583 panel->browseB = WMCreateCommandButton(panel->commandF);
584 WMResizeWidget(panel->browseB, 70, 24);
585 WMMoveWidget(panel->browseB, width - 80, 18);
586 WMSetButtonText(panel->browseB, _("Browse"));
587 WMSetButtonAction(panel->browseB, browseForFile, panel);
589 WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->commandT);
591 #if 0
592 panel->xtermC = WMCreateSwitchButton(panel->commandF);
593 WMResizeWidget(panel->xtermC, width - 20, 20);
594 WMMoveWidget(panel->xtermC, 10, 50);
595 WMSetButtonText(panel->xtermC, _("Run the program inside a Xterm"));
596 #endif
597 WMMapSubwidgets(panel->commandF);
599 /* path */
601 panel->pathF = WMCreateFrame(panel->optionsF);
602 WMResizeWidget(panel->pathF, width, 150);
603 WMMoveWidget(panel->pathF, 10, 40);
604 WMSetFrameTitle(panel->pathF, _("Path for Menu"));
606 panel->pathT = WMCreateTextField(panel->pathF);
607 WMResizeWidget(panel->pathT, width - 20, 20);
608 WMMoveWidget(panel->pathT, 10, 20);
610 WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->pathT);
612 label = WMCreateLabel(panel->pathF);
613 WMResizeWidget(label, width - 20, 80);
614 WMMoveWidget(label, 10, 50);
615 WMSetLabelText(label, _("Enter the path for a file containing a menu\n"
616 "or a list of directories with the programs you\n"
617 "want to have listed in the menu. Ex:\n"
618 "~/GNUstep/Library/WindowMaker/menu\n" "or\n" "/usr/bin ~/xbin"));
620 WMMapSubwidgets(panel->pathF);
622 /* pipe */
624 panel->pipeF = WMCreateFrame(panel->optionsF);
625 WMResizeWidget(panel->pipeF, width, 155);
626 WMMoveWidget(panel->pipeF, 10, 30);
627 WMSetFrameTitle(panel->pipeF, _("Command"));
629 panel->pipeT = WMCreateTextField(panel->pipeF);
630 WMResizeWidget(panel->pipeT, width - 20, 20);
631 WMMoveWidget(panel->pipeT, 10, 20);
633 WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->pipeT);
635 label = WMCreateLabel(panel->pipeF);
636 WMResizeWidget(label, width - 20, 40);
637 WMMoveWidget(label, 10, 50);
638 WMSetLabelText(label, _("Enter a command that outputs a menu\n" "definition to stdout when invoked."));
640 panel->pipeCacheB = WMCreateSwitchButton(panel->pipeF);
641 WMResizeWidget(panel->pipeCacheB, width - 20, 40);
642 WMMoveWidget(panel->pipeCacheB, 10, 110);
643 WMSetButtonText(panel->pipeCacheB, _("Cache menu contents after opening for\n" "the first time"));
645 WMMapSubwidgets(panel->pipeF);
647 /* directory menu */
649 panel->dcommandF = WMCreateFrame(panel->optionsF);
650 WMResizeWidget(panel->dcommandF, width, 90);
651 WMMoveWidget(panel->dcommandF, 10, 25);
652 WMSetFrameTitle(panel->dcommandF, _("Command to Open Files"));
654 panel->dcommandT = WMCreateTextField(panel->dcommandF);
655 WMResizeWidget(panel->dcommandT, width - 20, 20);
656 WMMoveWidget(panel->dcommandT, 10, 20);
658 WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->dcommandT);
660 label = WMCreateLabel(panel->dcommandF);
661 WMResizeWidget(label, width - 20, 45);
662 WMMoveWidget(label, 10, 40);
663 WMSetLabelText(label, _("Enter the command you want to use to open the\n"
664 "files in the directories listed below."));
666 WMMapSubwidgets(panel->dcommandF);
668 panel->dpathF = WMCreateFrame(panel->optionsF);
669 WMResizeWidget(panel->dpathF, width, 80);
670 WMMoveWidget(panel->dpathF, 10, 125);
671 WMSetFrameTitle(panel->dpathF, _("Directories with Files"));
673 panel->dpathT = WMCreateTextField(panel->dpathF);
674 WMResizeWidget(panel->dpathT, width - 20, 20);
675 WMMoveWidget(panel->dpathT, 10, 20);
677 WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->dpathT);
679 panel->dstripB = WMCreateSwitchButton(panel->dpathF);
680 WMResizeWidget(panel->dstripB, width - 20, 20);
681 WMMoveWidget(panel->dstripB, 10, 50);
682 WMSetButtonText(panel->dstripB, _("Strip extensions from file names"));
684 WMSetButtonAction(panel->dstripB, buttonClicked, panel);
686 WMMapSubwidgets(panel->dpathF);
688 /* shortcut */
690 panel->shortF = WMCreateFrame(panel->optionsF);
691 WMResizeWidget(panel->shortF, width, 50);
692 WMMoveWidget(panel->shortF, 10, 160);
693 WMSetFrameTitle(panel->shortF, _("Keyboard Shortcut"));
695 panel->shortT = WMCreateTextField(panel->shortF);
696 WMResizeWidget(panel->shortT, width - 20 - 150, 20);
697 WMMoveWidget(panel->shortT, 10, 20);
699 WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->shortT);
701 panel->sgrabB = WMCreateCommandButton(panel->shortF);
702 WMResizeWidget(panel->sgrabB, 70, 24);
703 WMMoveWidget(panel->sgrabB, width - 80, 18);
704 WMSetButtonText(panel->sgrabB, _("Capture"));
705 WMSetButtonAction(panel->sgrabB, sgrabClicked, panel);
707 panel->sclearB = WMCreateCommandButton(panel->shortF);
708 WMResizeWidget(panel->sclearB, 70, 24);
709 WMMoveWidget(panel->sclearB, width - 155, 18);
710 WMSetButtonText(panel->sclearB, _("Clear"));
711 WMSetButtonAction(panel->sclearB, sgrabClicked, panel);
713 WMMapSubwidgets(panel->shortF);
715 /* internal command */
717 panel->icommandL = WMCreateList(panel->optionsF);
718 WMResizeWidget(panel->icommandL, width, 80);
719 WMMoveWidget(panel->icommandL, 10, 20);
721 WMSetListAction(panel->icommandL, icommandLClicked, panel);
723 WMAddNotificationObserver(dataChanged, panel, WMListSelectionDidChangeNotification, panel->icommandL);
725 WMInsertListItem(panel->icommandL, 0, _("Arrange Icons"));
726 WMInsertListItem(panel->icommandL, 1, _("Hide All Windows Except For The Focused One"));
727 WMInsertListItem(panel->icommandL, 2, _("Show All Windows"));
729 WMInsertListItem(panel->icommandL, 3, _("Exit Window Maker"));
730 WMInsertListItem(panel->icommandL, 4, _("Exit X Session"));
731 WMInsertListItem(panel->icommandL, 5, _("Restart Window Maker"));
732 WMInsertListItem(panel->icommandL, 6, _("Start Another Window Manager : ("));
734 WMInsertListItem(panel->icommandL, 7, _("Save Current Session"));
735 WMInsertListItem(panel->icommandL, 8, _("Clear Saved Session"));
736 WMInsertListItem(panel->icommandL, 9, _("Refresh Screen"));
737 WMInsertListItem(panel->icommandL, 10, _("Open Info Panel"));
738 WMInsertListItem(panel->icommandL, 11, _("Open Copyright Panel"));
740 panel->paramF = WMCreateFrame(panel->optionsF);
741 WMResizeWidget(panel->paramF, width, 50);
742 WMMoveWidget(panel->paramF, 10, 105);
743 WMSetFrameTitle(panel->paramF, _("Window Manager to Start"));
745 panel->paramT = WMCreateTextField(panel->paramF);
746 WMResizeWidget(panel->paramT, width - 20, 20);
747 WMMoveWidget(panel->paramT, 10, 20);
749 WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->paramT);
751 WMMapSubwidgets(panel->paramF);
753 panel->quickB = WMCreateSwitchButton(panel->optionsF);
754 WMResizeWidget(panel->quickB, width, 20);
755 WMMoveWidget(panel->quickB, 10, 120);
756 WMSetButtonText(panel->quickB, _("Do not confirm action."));
757 WMSetButtonAction(panel->quickB, buttonClicked, panel);
759 label = WMCreateLabel(panel->optionsF);
760 WMResizeWidget(label, width + 5, FRAME_HEIGHT - 50);
761 WMMoveWidget(label, 7, 20);
762 WMSetLabelText(label,
763 _("Instructions:\n\n"
764 " - drag items from the left to the menu to add new items\n"
765 " - drag items out of the menu to remove items\n"
766 " - drag items in menu to change their position\n"
767 " - drag items with Control pressed to copy them\n"
768 " - double click in a menu item to change the label\n"
769 " - click on a menu item to change related information"));
770 WMMapWidget(label);
772 WMRealizeWidget(panel->box);
773 WMMapSubwidgets(panel->box);
774 WMMapWidget(panel->box);
777 int i;
778 for (i = 0; i < 3; i++)
779 WMUnmapWidget(panel->itemPad[i]);
781 changedItemPad(panel->typeP, panel);
783 panel->sections[NoInfo][0] = label;
785 panel->sections[ExecInfo][0] = panel->commandF;
786 panel->sections[ExecInfo][1] = panel->shortF;
788 panel->sections[CommandInfo][0] = panel->icommandL;
789 panel->sections[CommandInfo][1] = panel->shortF;
791 panel->sections[ExternalInfo][0] = panel->pathF;
793 panel->sections[PipeInfo][0] = panel->pipeF;
795 panel->sections[DirectoryInfo][0] = panel->dpathF;
796 panel->sections[DirectoryInfo][1] = panel->dcommandF;
798 panel->currentType = NoInfo;
800 showData(panel);
803 WMPoint pos;
805 pos = WMGetViewScreenPosition(WMWidgetView(panel->box));
807 if (pos.x < 200) {
808 pos.x += FRAME_WIDTH + 20;
809 } else {
810 pos.x = 10;
813 pos.y = WMAX(pos.y - 100, 0);
815 if (panel->menu)
816 WEditMenuShowAt(panel->menu, pos.x, pos.y);
820 static void freeItemData(ItemData * data)
822 #define CFREE(d) if (d) wfree(d)
824 /* TODO */
825 switch (data->type) {
826 case CommandInfo:
827 CFREE(data->param.command.parameter);
828 CFREE(data->param.command.shortcut);
829 break;
831 case ExecInfo:
832 CFREE(data->param.exec.command);
833 CFREE(data->param.exec.shortcut);
834 break;
836 case PipeInfo:
837 CFREE(data->param.pipe.command);
838 break;
840 case ExternalInfo:
841 CFREE(data->param.external.path);
842 break;
844 case DirectoryInfo:
845 CFREE(data->param.directory.command);
846 CFREE(data->param.directory.directory);
847 break;
849 default:
850 break;
853 wfree(data);
854 #undef CFREE
857 static ItemData *parseCommand(WMPropList * item)
859 ItemData *data = NEW(ItemData);
860 WMPropList *p;
861 char *command = NULL;
862 char *parameter = NULL;
863 char *shortcut = NULL;
864 int i = 1;
866 p = WMGetFromPLArray(item, i++);
867 command = WMGetFromPLString(p);
868 if (strcmp(command, "SHORTCUT") == 0) {
869 p = WMGetFromPLArray(item, i++);
870 shortcut = WMGetFromPLString(p);
871 p = WMGetFromPLArray(item, i++);
872 command = WMGetFromPLString(p);
874 p = WMGetFromPLArray(item, i++);
875 if (p)
876 parameter = WMGetFromPLString(p);
878 if (strcmp(command, "EXEC") == 0 || strcmp(command, "SHEXEC") == 0) {
880 data->type = ExecInfo;
882 data->param.exec.command = wstrdup(parameter);
883 if (shortcut)
884 data->param.exec.shortcut = wstrdup(shortcut);
886 } else if (strcmp(command, "OPEN_MENU") == 0) {
887 char *p;
889 * dir menu, menu file
890 * dir WITH
891 * |pipe
893 p = parameter;
894 while (isspace(*p) && *p)
895 p++;
896 if (*p == '|') {
897 if (*(p + 1) == '|') {
898 p++;
899 data->param.pipe.cached = 0;
900 } else {
901 data->param.pipe.cached = 1;
903 data->type = PipeInfo;
904 data->param.pipe.command = wtrimspace(p + 1);
905 } else {
906 char *s;
908 p = wstrdup(p);
910 s = strstr(p, "WITH");
911 if (s) {
912 char **tokens;
913 char **ctokens;
914 int tokn;
915 int i, j;
917 data->type = DirectoryInfo;
919 *s = '\0';
920 s += 5;
921 while (*s && isspace(*s))
922 s++;
923 data->param.directory.command = wstrdup(s);
925 wtokensplit(p, &tokens, &tokn);
926 wfree(p);
928 ctokens = wmalloc(sizeof(char *) * tokn);
930 for (i = 0, j = 0; i < tokn; i++) {
931 if (strcmp(tokens[i], "-noext") == 0) {
932 data->param.directory.stripExt = 1;
933 } else {
934 ctokens[j++] = tokens[i];
937 data->param.directory.directory = wtokenjoin(ctokens, j);
938 wfree(ctokens);
940 wtokenfree(tokens, tokn);
941 } else {
942 data->type = ExternalInfo;
943 data->param.external.path = p;
946 } else if (strcmp(command, "WORKSPACE_MENU") == 0) {
947 data->type = WSMenuInfo;
948 } else if (strcmp(command, "WINDOWS_MENU") == 0) {
949 data->type = WWindowListInfo;
950 } else {
951 int cmd;
953 if (strcmp(command, "ARRANGE_ICONS") == 0) {
954 cmd = 0;
955 } else if (strcmp(command, "HIDE_OTHERS") == 0) {
956 cmd = 1;
957 } else if (strcmp(command, "SHOW_ALL") == 0) {
958 cmd = 2;
959 } else if (strcmp(command, "EXIT") == 0) {
960 cmd = 3;
961 } else if (strcmp(command, "SHUTDOWN") == 0) {
962 cmd = 4;
963 } else if (strcmp(command, "RESTART") == 0) {
964 if (parameter) {
965 cmd = 6;
966 } else {
967 cmd = 5;
969 } else if (strcmp(command, "SAVE_SESSION") == 0) {
970 cmd = 7;
971 } else if (strcmp(command, "CLEAR_SESSION") == 0) {
972 cmd = 8;
973 } else if (strcmp(command, "REFRESH") == 0) {
974 cmd = 9;
975 } else if (strcmp(command, "INFO_PANEL") == 0) {
976 cmd = 10;
977 } else if (strcmp(command, "LEGAL_PANEL") == 0) {
978 cmd = 11;
979 } else {
980 wwarning(_("unknown command '%s' in menu"), command);
981 wfree(data);
982 return NULL;
985 data->type = CommandInfo;
987 data->param.command.command = cmd;
988 if (shortcut)
989 data->param.command.shortcut = wstrdup(shortcut);
990 if (parameter)
991 data->param.command.parameter = wstrdup(parameter);
994 return data;
997 static void updateFrameTitle(_Panel * panel, char *title, InfoType type)
999 if (type != NoInfo) {
1000 char *tmp;
1002 switch (type) {
1003 case ExecInfo:
1004 tmp = wstrconcat(title, _(": Execute Program"));
1005 break;
1007 case CommandInfo:
1008 tmp = wstrconcat(title, _(": Perform Internal Command"));
1009 break;
1011 case ExternalInfo:
1012 tmp = wstrconcat(title, _(": Open a Submenu"));
1013 break;
1015 case PipeInfo:
1016 tmp = wstrconcat(title, _(": Program Generated Submenu"));
1017 break;
1019 case DirectoryInfo:
1020 tmp = wstrconcat(title, _(": Directory Contents Menu"));
1021 break;
1023 case WSMenuInfo:
1024 tmp = wstrconcat(title, _(": Open Workspaces Submenu"));
1025 break;
1027 case WWindowListInfo:
1028 tmp = wstrconcat(title, _(": Open Window List Submenu"));
1029 break;
1031 default:
1032 tmp = NULL;
1033 break;
1035 WMSetFrameTitle(panel->optionsF, tmp);
1036 wfree(tmp);
1037 } else {
1038 WMSetFrameTitle(panel->optionsF, NULL);
1042 static void changeInfoType(_Panel * panel, char *title, InfoType type)
1044 WMWidget **w;
1046 if (panel->currentType != type) {
1048 w = panel->sections[panel->currentType];
1050 while (*w) {
1051 WMUnmapWidget(*w);
1052 w++;
1054 WMUnmapWidget(panel->paramF);
1055 WMUnmapWidget(panel->quickB);
1057 w = panel->sections[type];
1059 while (*w) {
1060 WMMapWidget(*w);
1061 w++;
1065 updateFrameTitle(panel, title, type);
1067 panel->currentType = type;
1070 static void updateMenuItem(_Panel * panel, WEditMenuItem * item, WMWidget * changedWidget)
1072 ItemData *data = WGetEditMenuItemData(item);
1074 assert(data != NULL);
1076 #define REPLACE(v, d) if (v) wfree(v); v = d
1078 switch (data->type) {
1079 case ExecInfo:
1080 if (changedWidget == panel->commandT) {
1081 REPLACE(data->param.exec.command, WMGetTextFieldText(panel->commandT));
1083 if (changedWidget == panel->shortT) {
1084 REPLACE(data->param.exec.shortcut, WMGetTextFieldText(panel->shortT));
1086 break;
1088 case CommandInfo:
1089 if (changedWidget == panel->icommandL) {
1090 data->param.command.command = WMGetListSelectedItemRow(panel->icommandL);
1092 switch (data->param.command.command) {
1093 case 3:
1094 case 4:
1095 if (changedWidget == panel->quickB) {
1096 REPLACE(data->param.command.parameter, WMGetButtonSelected(panel->quickB)
1097 ? wstrdup("QUICK") : NULL);
1099 break;
1101 case 6:
1102 if (changedWidget == panel->paramT) {
1103 REPLACE(data->param.command.parameter, WMGetTextFieldText(panel->paramT));
1105 break;
1107 if (changedWidget == panel->shortT) {
1108 REPLACE(data->param.command.shortcut, WMGetTextFieldText(panel->shortT));
1111 break;
1113 case PipeInfo:
1114 if (changedWidget == panel->pipeT) {
1115 REPLACE(data->param.pipe.command, WMGetTextFieldText(panel->pipeT));
1117 if (changedWidget == panel->pipeCacheB) {
1118 data->param.pipe.cached = WMGetButtonSelected(panel->pipeCacheB);
1120 break;
1122 case ExternalInfo:
1123 if (changedWidget == panel->pathT) {
1124 REPLACE(data->param.external.path, WMGetTextFieldText(panel->pathT));
1126 break;
1128 case DirectoryInfo:
1129 if (changedWidget == panel->dpathT) {
1130 REPLACE(data->param.directory.directory, WMGetTextFieldText(panel->dpathT));
1132 if (changedWidget == panel->dcommandT) {
1133 REPLACE(data->param.directory.command, WMGetTextFieldText(panel->dcommandT));
1135 if (changedWidget == panel->dstripB) {
1136 data->param.directory.stripExt = WMGetButtonSelected(panel->dstripB);
1138 break;
1140 default:
1141 assert(0);
1142 break;
1145 #undef REPLACE
1148 static void
1149 menuItemCloned(WEditMenuDelegate * delegate, WEditMenu * menu, WEditMenuItem * origItem, WEditMenuItem * newItem)
1151 ItemData *data = WGetEditMenuItemData(origItem);
1152 ItemData *newData;
1154 if (!data)
1155 return;
1157 #define DUP(s) (s) ? wstrdup(s) : NULL
1159 newData = NEW(ItemData);
1161 newData->type = data->type;
1163 switch (data->type) {
1164 case ExecInfo:
1165 newData->param.exec.command = DUP(data->param.exec.command);
1166 newData->param.exec.shortcut = DUP(data->param.exec.shortcut);
1167 break;
1169 case CommandInfo:
1170 newData->param.command.command = data->param.command.command;
1171 newData->param.command.parameter = DUP(data->param.command.parameter);
1172 newData->param.command.shortcut = DUP(data->param.command.shortcut);
1173 break;
1175 case PipeInfo:
1176 newData->param.pipe.command = DUP(data->param.pipe.command);
1177 newData->param.pipe.cached = data->param.pipe.cached;
1178 break;
1180 case ExternalInfo:
1181 newData->param.external.path = DUP(data->param.external.path);
1182 break;
1184 case DirectoryInfo:
1185 newData->param.directory.directory = DUP(data->param.directory.directory);
1186 newData->param.directory.command = DUP(data->param.directory.command);
1187 newData->param.directory.stripExt = data->param.directory.stripExt;
1188 break;
1190 default:
1191 break;
1194 #undef DUP
1196 WSetEditMenuItemData(newItem, newData, (WMCallback *) freeItemData);
1199 static void menuItemEdited(struct WEditMenuDelegate *delegate, WEditMenu * menu, WEditMenuItem * item)
1201 _Panel *panel = (_Panel *) delegate->data;
1202 WEditMenu *submenu;
1204 updateFrameTitle(panel, WGetEditMenuItemTitle(item), panel->currentType);
1206 submenu = WGetEditMenuSubmenu(menu, item);
1207 if (submenu) {
1208 WSetEditMenuTitle(submenu, WGetEditMenuItemTitle(item));
1212 static Bool shouldRemoveItem(struct WEditMenuDelegate *delegate, WEditMenu * menu, WEditMenuItem * item)
1214 _Panel *panel = (_Panel *) delegate->data;
1216 if (panel->dontAsk)
1217 return True;
1219 if (WGetEditMenuSubmenu(menu, item)) {
1220 int res;
1222 res = WMRunAlertPanel(WMWidgetScreen(menu), NULL,
1223 _("Remove Submenu"),
1224 _("Removing this item will destroy all items inside\n"
1225 "the submenu. Do you really want to do that?"),
1226 _("Yes"), _("No"), _("Yes, don't ask again."));
1227 switch (res) {
1228 case WAPRDefault:
1229 return True;
1230 case WAPRAlternate:
1231 return False;
1232 case WAPROther:
1233 panel->dontAsk = True;
1234 return True;
1237 return True;
1240 static void menuItemDeselected(WEditMenuDelegate * delegate, WEditMenu * menu, WEditMenuItem * item)
1242 _Panel *panel = (_Panel *) delegate->data;
1244 changeInfoType(panel, NULL, NoInfo);
1247 static void menuItemSelected(WEditMenuDelegate * delegate, WEditMenu * menu, WEditMenuItem * item)
1249 ItemData *data = WGetEditMenuItemData(item);
1250 _Panel *panel = (_Panel *) delegate->data;
1252 panel->currentItem = item;
1254 if (data) {
1255 changeInfoType(panel, WGetEditMenuItemTitle(item), data->type);
1257 switch (data->type) {
1258 case NoInfo:
1259 break;
1261 case ExecInfo:
1262 WMSetTextFieldText(panel->commandT, data->param.exec.command);
1263 WMSetTextFieldText(panel->shortT, data->param.exec.shortcut);
1264 break;
1266 case CommandInfo:
1267 WMSelectListItem(panel->icommandL, data->param.command.command);
1268 WMSetListPosition(panel->icommandL, data->param.command.command - 2);
1269 WMSetTextFieldText(panel->shortT, data->param.command.shortcut);
1271 switch (data->param.command.command) {
1272 case 3:
1273 case 4:
1274 WMSetButtonSelected(panel->quickB, data->param.command.parameter != NULL);
1275 break;
1276 case 6:
1277 WMSetTextFieldText(panel->paramT, data->param.command.parameter);
1278 break;
1281 icommandLClicked(panel->icommandL, panel);
1282 break;
1284 case PipeInfo:
1285 WMSetTextFieldText(panel->pipeT, data->param.pipe.command);
1286 WMSetButtonSelected(panel->pipeCacheB, data->param.pipe.cached);
1287 break;
1289 case ExternalInfo:
1290 WMSetTextFieldText(panel->pathT, data->param.external.path);
1291 break;
1293 case DirectoryInfo:
1294 WMSetTextFieldText(panel->dpathT, data->param.directory.directory);
1295 WMSetTextFieldText(panel->dcommandT, data->param.directory.command);
1296 WMSetButtonSelected(panel->dstripB, data->param.directory.stripExt);
1297 break;
1299 case WSMenuInfo:
1300 break;
1302 default:
1303 break;
1308 static WEditMenu *buildSubmenu(_Panel * panel, WMPropList * pl)
1310 WMScreen *scr = WMWidgetScreen(panel->parent);
1311 WEditMenu *menu;
1312 WEditMenuItem *item;
1313 char *title;
1314 WMPropList *tp, *bp;
1315 int i;
1317 tp = WMGetFromPLArray(pl, 0);
1318 title = WMGetFromPLString(tp);
1320 menu = WCreateEditMenu(scr, title);
1322 for (i = 1; i < WMGetPropListItemCount(pl); i++) {
1323 WMPropList *pi;
1325 pi = WMGetFromPLArray(pl, i);
1327 tp = WMGetFromPLArray(pi, 0);
1328 bp = WMGetFromPLArray(pi, 1);
1330 title = WMGetFromPLString(tp);
1332 if (!bp || WMIsPLArray(bp)) { /* it's a submenu */
1333 WEditMenu *submenu;
1335 submenu = buildSubmenu(panel, pi);
1337 item = WAddMenuItemWithTitle(menu, title);
1339 WSetEditMenuSubmenu(menu, item, submenu);
1340 } else {
1341 ItemData *data;
1343 data = parseCommand(pi);
1345 if (data != NULL) {
1346 item = WAddMenuItemWithTitle(menu, title);
1347 if (panel->markerPix[data->type])
1348 WSetEditMenuItemImage(item, panel->markerPix[data->type]);
1349 WSetEditMenuItemData(item, data, (WMCallback *) freeItemData);
1350 } else {
1351 char *buf = wmalloc(1024);
1352 snprintf(buf, 1024, _("Invalid menu command \"%s\" with label \"%s\" cleared"),
1353 WMGetFromPLString(WMGetFromPLArray(pi, 1)),
1354 WMGetFromPLString(WMGetFromPLArray(pi, 0)));
1355 WMRunAlertPanel(scr, panel->parent, _("Warning"), buf, _("OK"), NULL, NULL);
1356 wfree(buf);
1362 WSetEditMenuAcceptsDrop(menu, True);
1363 WSetEditMenuDelegate(menu, &menuDelegate);
1365 WMRealizeWidget(menu);
1367 return menu;
1370 static void buildMenuFromPL(_Panel * panel, WMPropList * pl)
1372 panel->menu = buildSubmenu(panel, pl);
1375 static WMPropList *getDefaultMenu(_Panel * panel)
1377 WMPropList *menu;
1378 char *menuPath, *gspath;
1380 gspath = wstrdup(WMAKER_RESOURCE_PATH);
1382 menuPath = wmalloc(strlen(gspath) + 128);
1383 sprintf(menuPath, "%s/plmenu", gspath);
1385 menu = WMReadPropListFromFile(menuPath);
1387 if (!menu) {
1388 char *buffer, *msg;
1390 msg = _("Could not open default menu from '%s'");
1391 buffer = wmalloc(strlen(msg) + strlen(menuPath) + 10);
1392 sprintf(buffer, msg, menuPath);
1393 WMRunAlertPanel(WMWidgetScreen(panel->parent), panel->parent,
1394 _("Error"), buffer, _("OK"), NULL, NULL);
1395 wfree(buffer);
1398 wfree(gspath);
1399 wfree(menuPath);
1401 return menu;
1404 static void showData(_Panel * panel)
1406 char *gspath;
1407 char *menuPath;
1408 WMPropList *pmenu;
1410 gspath = wusergnusteppath();
1412 menuPath = wmalloc(strlen(gspath) + 32);
1413 strcpy(menuPath, gspath);
1414 strcat(menuPath, "/Defaults/WMRootMenu");
1416 pmenu = WMReadPropListFromFile(menuPath);
1418 if (!pmenu || !WMIsPLArray(pmenu)) {
1419 int res;
1421 res = WMRunAlertPanel(WMWidgetScreen(panel->parent), panel->parent,
1422 _("Warning"),
1423 _("The menu file format currently in use is not supported\n"
1424 "by this tool. Do you want to discard the current menu\n"
1425 "to use this tool?"),
1426 _("Yes, Discard and Update"), _("No, Keep Current Menu"), NULL);
1428 if (res == WAPRDefault) {
1429 pmenu = getDefaultMenu(panel);
1431 if (!pmenu) {
1432 pmenu = WMCreatePLArray(WMCreatePLString("Applications"), NULL);
1434 } else {
1435 panel->dontSave = True;
1436 return;
1440 panel->menuPath = menuPath;
1442 buildMenuFromPL(panel, pmenu);
1444 WMReleasePropList(pmenu);
1447 static Bool notblank(char *s)
1449 if (s) {
1450 while (*s++) {
1451 if (!isspace(*s))
1452 return True;
1455 return False;
1458 static WMPropList *processData(char *title, ItemData * data)
1460 WMPropList *item;
1461 char *s1;
1462 static WMPropList *pscut = NULL;
1463 static WMPropList *pomenu = NULL;
1464 int i;
1466 if (data == NULL)
1467 return NULL;
1469 if (!pscut) {
1470 pscut = WMCreatePLString("SHORTCUT");
1471 pomenu = WMCreatePLString("OPEN_MENU");
1474 item = WMCreatePLArray(WMCreatePLString(title), NULL);
1476 switch (data->type) {
1477 case ExecInfo:
1478 if (data->param.exec.command == NULL)
1479 return NULL;
1480 #if 1
1481 if (strpbrk(data->param.exec.command, "&$*|><?`=;")) {
1482 s1 = "SHEXEC";
1483 } else {
1484 s1 = "EXEC";
1486 #else
1487 s1 = "SHEXEC";
1488 #endif
1490 if (notblank(data->param.exec.shortcut)) {
1491 WMAddToPLArray(item, pscut);
1492 WMAddToPLArray(item, WMCreatePLString(data->param.exec.shortcut));
1495 WMAddToPLArray(item, WMCreatePLString(s1));
1496 WMAddToPLArray(item, WMCreatePLString(data->param.exec.command));
1497 break;
1499 case CommandInfo:
1500 if (notblank(data->param.command.shortcut)) {
1501 WMAddToPLArray(item, pscut);
1502 WMAddToPLArray(item, WMCreatePLString(data->param.command.shortcut));
1505 i = data->param.command.command;
1507 WMAddToPLArray(item, WMCreatePLString(commandNames[i]));
1509 switch (i) {
1510 case 3:
1511 case 4:
1512 if (data->param.command.parameter) {
1513 WMAddToPLArray(item, WMCreatePLString(data->param.command.parameter));
1515 break;
1517 case 6: /* restart */
1518 if (data->param.command.parameter) {
1519 WMAddToPLArray(item, WMCreatePLString(data->param.command.parameter));
1521 break;
1524 break;
1526 case PipeInfo:
1527 if (!data->param.pipe.command)
1528 return NULL;
1529 WMAddToPLArray(item, pomenu);
1530 if (data->param.pipe.cached)
1531 s1 = wstrconcat("| ", data->param.pipe.command);
1532 else
1533 s1 = wstrconcat("|| ", data->param.pipe.command);
1534 WMAddToPLArray(item, WMCreatePLString(s1));
1535 wfree(s1);
1536 break;
1538 case ExternalInfo:
1539 if (!data->param.external.path)
1540 return NULL;
1541 WMAddToPLArray(item, pomenu);
1542 WMAddToPLArray(item, WMCreatePLString(data->param.external.path));
1543 break;
1545 case DirectoryInfo:
1546 if (!data->param.directory.directory || !data->param.directory.command)
1547 return NULL;
1549 int l;
1550 char *tmp;
1552 l = strlen(data->param.directory.directory);
1553 l += strlen(data->param.directory.command);
1554 l += 32;
1556 WMAddToPLArray(item, pomenu);
1558 tmp = wmalloc(l);
1559 sprintf(tmp, "%s%s WITH %s",
1560 data->param.directory.stripExt ? "-noext " : "",
1561 data->param.directory.directory, data->param.directory.command);
1563 WMAddToPLArray(item, WMCreatePLString(tmp));
1564 wfree(tmp);
1566 break;
1568 case WSMenuInfo:
1569 WMAddToPLArray(item, WMCreatePLString("WORKSPACE_MENU"));
1570 break;
1572 case WWindowListInfo:
1573 WMAddToPLArray(item, WMCreatePLString("WINDOWS_MENU"));
1574 break;
1576 default:
1577 assert(0);
1578 break;
1581 return item;
1584 static WMPropList *processSubmenu(WEditMenu * menu)
1586 WEditMenuItem *item;
1587 WMPropList *pmenu;
1588 WMPropList *pl;
1589 char *s;
1590 int i;
1592 s = WGetEditMenuTitle(menu);
1593 pl = WMCreatePLString(s);
1595 pmenu = WMCreatePLArray(pl, NULL);
1597 i = 0;
1598 while ((item = WGetEditMenuItem(menu, i++))) {
1599 WEditMenu *submenu;
1601 s = WGetEditMenuItemTitle(item);
1603 submenu = WGetEditMenuSubmenu(menu, item);
1604 if (submenu) {
1605 pl = processSubmenu(submenu);
1606 } else {
1607 pl = processData(s, WGetEditMenuItemData(item));
1610 if (!pl)
1611 continue;
1613 WMAddToPLArray(pmenu, pl);
1616 return pmenu;
1619 static WMPropList *buildPLFromMenu(_Panel * panel)
1621 WMPropList *menu;
1623 menu = processSubmenu(panel->menu);
1625 return menu;
1628 static void storeData(_Panel * panel)
1630 WMPropList *menu;
1632 if (panel->dontSave)
1633 return;
1635 menu = buildPLFromMenu(panel);
1637 WMWritePropListToFile(menu, panel->menuPath);
1639 WMReleasePropList(menu);
1642 static void showMenus(_Panel * panel)
1644 if (panel->menu)
1645 WEditMenuUnhide(panel->menu);
1648 static void hideMenus(_Panel * panel)
1650 if (panel->menu)
1651 WEditMenuHide(panel->menu);
1654 Panel *InitMenu(WMScreen * scr, WMWidget * parent)
1656 _Panel *panel;
1658 panel = wmalloc(sizeof(_Panel));
1659 memset(panel, 0, sizeof(_Panel));
1661 panel->sectionName = _("Applications Menu Definition");
1663 panel->description = _("Edit the menu for launching applications.");
1665 panel->parent = parent;
1667 panel->callbacks.createWidgets = createPanel;
1668 panel->callbacks.updateDomain = storeData;
1669 panel->callbacks.showPanel = showMenus;
1670 panel->callbacks.hidePanel = hideMenus;
1672 AddSection(panel, ICON_FILE);
1674 return panel;