1
0
mirror of https://github.com/gryf/wmaker.git synced 2025-12-19 20:38:08 +01:00
Files
wmaker/WPrefs.app/Menu.c
Pedro Martelletto 2706f7217c WPrefs: Fix crash due to wtokenfree() memory leak fix
After the fix to avoid a memory leak in wtokenfree(), WPrefs crashes
when opening the 'Applications Menu Definition' dialogue.

The problem is that WPrefs code relied on the fact that the first token
in the array would not be free'd by wtokenfree(), a misbehaviour which
is correctly addressed with this patch.

Retrieved-from: http://www.mail-archive.com/ports@openbsd.org/msg12731.html

[crmafra: small changes in the commit log from the webpage]
2009-08-22 20:51:47 +02:00

1719 lines
42 KiB
C

/* Menu.c- menu definition
*
* WPrefs - Window Maker Preferences Program
*
* Copyright (c) 2000-2003 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include "WPrefs.h"
#include <assert.h>
#include <ctype.h>
#include <X11/keysym.h>
#include <X11/cursorfont.h>
#include "editmenu.h"
typedef enum {
NoInfo,
ExecInfo,
CommandInfo,
ExternalInfo,
PipeInfo,
DirectoryInfo,
WSMenuInfo,
WWindowListInfo,
LastInfo
} InfoType;
#define MAX_SECTION_SIZE 4
typedef struct _Panel {
WMBox *box;
char *sectionName;
char *description;
CallbackRec callbacks;
WMWidget *parent;
WMFont *boldFont;
WMFont *normalFont;
WMColor *white;
WMColor *gray;
WMColor *black;
WMPixmap *markerPix[LastInfo];
WMPopUpButton *typeP;
WMWidget *itemPad[3];
int currentPad;
WEditMenu *menu;
char *menuPath;
WMFrame *optionsF;
WMFrame *commandF;
WMTextField *commandT; /* command to run */
WMButton *browseB;
WMButton *xtermC; /* inside xterm? */
WMFrame *pathF;
WMTextField *pathT;
WMFrame *pipeF;
WMTextField *pipeT;
WMButton *pipeCacheB;
WMFrame *dpathF;
WMTextField *dpathT;
WMFrame *dcommandF;
WMTextField *dcommandT;
WMButton *dstripB;
WMFrame *shortF;
WMTextField *shortT;
WMButton *sgrabB;
WMButton *sclearB;
WMList *icommandL;
WMFrame *paramF;
WMTextField *paramT;
WMButton *quickB;
Bool dontAsk; /* whether to comfirm submenu remove */
Bool dontSave;
Bool capturing;
/* about the currently selected item */
WEditMenuItem *currentItem;
InfoType currentType;
WMWidget *sections[LastInfo][MAX_SECTION_SIZE];
} _Panel;
typedef struct {
InfoType type;
union {
struct {
int command;
char *parameter;
char *shortcut;
} command;
struct {
char *command;
char *shortcut;
} exec;
struct {
char *path;
} external;
struct {
char *command;
unsigned cached:1;
} pipe;
struct {
char *directory;
char *command;
unsigned stripExt:1;
} directory;
} param;
} ItemData;
static char *commandNames[] = {
"ARRANGE_ICONS",
"HIDE_OTHERS",
"SHOW_ALL",
"EXIT",
"SHUTDOWN",
"RESTART",
"RESTART",
"SAVE_SESSION",
"CLEAR_SESSION",
"REFRESH",
"INFO_PANEL",
"LEGAL_PANEL"
};
#define NEW(type) memset(wmalloc(sizeof(type)), 0, sizeof(type))
#define ICON_FILE "menus"
static void showData(_Panel * panel);
static void updateMenuItem(_Panel * panel, WEditMenuItem * item, WMWidget * changedWidget);
static void menuItemSelected(struct WEditMenuDelegate *delegate, WEditMenu * menu, WEditMenuItem * item);
static void menuItemDeselected(struct WEditMenuDelegate *delegate, WEditMenu * menu, WEditMenuItem * item);
static void menuItemCloned(struct WEditMenuDelegate *delegate, WEditMenu * menu,
WEditMenuItem * origItem, WEditMenuItem * newItem);
static void menuItemEdited(struct WEditMenuDelegate *delegate, WEditMenu * menu, WEditMenuItem * item);
static Bool shouldRemoveItem(struct WEditMenuDelegate *delegate, WEditMenu * menu, WEditMenuItem * item);
static void freeItemData(ItemData * data);
static WEditMenuDelegate menuDelegate = {
NULL,
menuItemCloned,
menuItemEdited,
menuItemSelected,
menuItemDeselected,
shouldRemoveItem
};
static void dataChanged(void *self, WMNotification * notif)
{
_Panel *panel = (_Panel *) self;
WEditMenuItem *item = panel->currentItem;
WMWidget *w = (WMWidget *) WMGetNotificationObject(notif);
updateMenuItem(panel, item, w);
}
static void buttonClicked(WMWidget * w, void *data)
{
_Panel *panel = (_Panel *) data;
WEditMenuItem *item = panel->currentItem;
updateMenuItem(panel, item, w);
}
static void icommandLClicked(WMWidget * w, void *data)
{
_Panel *panel = (_Panel *) data;
int cmd;
cmd = WMGetListSelectedItemRow(w);
if (cmd == 3 || cmd == 4) {
WMMapWidget(panel->quickB);
} else {
WMUnmapWidget(panel->quickB);
}
if (cmd == 6) {
WMMapWidget(panel->paramF);
} else {
WMUnmapWidget(panel->paramF);
}
}
static void browseForFile(WMWidget * self, void *clientData)
{
_Panel *panel = (_Panel *) clientData;
WMFilePanel *filePanel;
char *text, *oldprog, *newprog;
filePanel = WMGetOpenPanel(WMWidgetScreen(self));
text = WMGetTextFieldText(panel->commandT);
oldprog = wtrimspace(text);
wfree(text);
if (oldprog[0] == 0 || oldprog[0] != '/') {
wfree(oldprog);
oldprog = wstrdup("/");
} else {
char *ptr = oldprog;
while (*ptr && !isspace(*ptr))
ptr++;
*ptr = 0;
}
WMSetFilePanelCanChooseDirectories(filePanel, False);
if (WMRunModalFilePanelForDirectory(filePanel, panel->parent, oldprog, _("Select Program"), NULL) == True) {
newprog = WMGetFilePanelFileName(filePanel);
WMSetTextFieldText(panel->commandT, newprog);
updateMenuItem(panel, panel->currentItem, panel->commandT);
wfree(newprog);
}
wfree(oldprog);
}
static char *captureShortcut(Display * dpy, _Panel * panel)
{
XEvent ev;
KeySym ksym;
char buffer[64];
char *key = NULL;
while (panel->capturing) {
XAllowEvents(dpy, AsyncKeyboard, CurrentTime);
WMNextEvent(dpy, &ev);
if (ev.type == KeyPress && ev.xkey.keycode != 0) {
ksym = XKeycodeToKeysym(dpy, ev.xkey.keycode, 0);
if (!IsModifierKey(ksym)) {
key = XKeysymToString(ksym);
panel->capturing = 0;
break;
}
}
WMHandleEvent(&ev);
}
if (!key)
return NULL;
buffer[0] = 0;
if (ev.xkey.state & ControlMask) {
strcat(buffer, "Control+");
}
if (ev.xkey.state & ShiftMask) {
strcat(buffer, "Shift+");
}
if (ev.xkey.state & Mod1Mask) {
strcat(buffer, "Mod1+");
}
if (ev.xkey.state & Mod2Mask) {
strcat(buffer, "Mod2+");
}
if (ev.xkey.state & Mod3Mask) {
strcat(buffer, "Mod3+");
}
if (ev.xkey.state & Mod4Mask) {
strcat(buffer, "Mod4+");
}
if (ev.xkey.state & Mod5Mask) {
strcat(buffer, "Mod5+");
}
strcat(buffer, key);
return wstrdup(buffer);
}
static void sgrabClicked(WMWidget * w, void *data)
{
_Panel *panel = (_Panel *) data;
Display *dpy = WMScreenDisplay(WMWidgetScreen(panel->parent));
char *shortcut;
if (w == panel->sclearB) {
WMSetTextFieldText(panel->shortT, "");
updateMenuItem(panel, panel->currentItem, panel->shortT);
return;
}
if (!panel->capturing) {
panel->capturing = 1;
WMSetButtonText(w, _("Cancel"));
XGrabKeyboard(dpy, WMWidgetXID(panel->parent), True, GrabModeAsync, GrabModeAsync, CurrentTime);
shortcut = captureShortcut(dpy, panel);
if (shortcut) {
WMSetTextFieldText(panel->shortT, shortcut);
updateMenuItem(panel, panel->currentItem, panel->shortT);
wfree(shortcut);
}
}
panel->capturing = 0;
WMSetButtonText(w, _("Capture"));
XUngrabKeyboard(dpy, CurrentTime);
}
static void changedItemPad(WMWidget * w, void *data)
{
_Panel *panel = (_Panel *) data;
int padn = WMGetPopUpButtonSelectedItem(w);
WMUnmapWidget(panel->itemPad[panel->currentPad]);
WMMapWidget(panel->itemPad[padn]);
panel->currentPad = padn;
}
static WEditMenu *putNewSubmenu(WEditMenu * menu, char *title)
{
WEditMenu *tmp;
WEditMenuItem *item;
item = WAddMenuItemWithTitle(menu, title);
tmp = WCreateEditMenu(WMWidgetScreen(menu), title);
WSetEditMenuAcceptsDrop(tmp, True);
WSetEditMenuDelegate(tmp, &menuDelegate);
WSetEditMenuSubmenu(menu, item, tmp);
return tmp;
}
static ItemData *putNewItem(_Panel * panel, WEditMenu * menu, int type, char *title)
{
WEditMenuItem *item;
ItemData *data;
item = WAddMenuItemWithTitle(menu, title);
data = NEW(ItemData);
data->type = type;
WSetEditMenuItemData(item, data, (WMCallback *) freeItemData);
WSetEditMenuItemImage(item, panel->markerPix[type]);
return data;
}
static WEditMenu *makeFactoryMenu(WMWidget * parent, int width)
{
WEditMenu *pad;
pad = WCreateEditMenuPad(parent);
WMResizeWidget(pad, width, 10);
WSetEditMenuMinSize(pad, wmksize(width, 0));
WSetEditMenuMaxSize(pad, wmksize(width, 0));
WSetEditMenuSelectable(pad, False);
WSetEditMenuEditable(pad, False);
WSetEditMenuIsFactory(pad, True);
WSetEditMenuDelegate(pad, &menuDelegate);
return pad;
}
static void createPanel(_Panel * p)
{
_Panel *panel = (_Panel *) p;
WMScreen *scr = WMWidgetScreen(panel->parent);
WMColor *black = WMBlackColor(scr);
WMColor *white = WMWhiteColor(scr);
WMColor *gray = WMGrayColor(scr);
WMFont *bold = WMBoldSystemFontOfSize(scr, 12);
WMFont *font = WMSystemFontOfSize(scr, 12);
WMLabel *label;
int width;
menuDelegate.data = panel;
panel->boldFont = bold;
panel->normalFont = font;
panel->black = black;
panel->white = white;
panel->gray = gray;
{
Pixmap pix;
Display *dpy = WMScreenDisplay(scr);
GC gc;
WMPixmap *pixm;
pixm = WMCreatePixmap(scr, 7, 7, WMScreenDepth(scr), True);
pix = WMGetPixmapXID(pixm);
XDrawLine(dpy, pix, WMColorGC(black), 0, 3, 6, 3);
XDrawLine(dpy, pix, WMColorGC(black), 3, 0, 3, 6);
/*
XDrawLine(dpy, pix, WMColorGC(black), 1, 0, 3, 3);
XDrawLine(dpy, pix, WMColorGC(black), 1, 6, 3, 3);
XDrawLine(dpy, pix, WMColorGC(black), 0, 0, 0, 6);
*/
pix = WMGetPixmapMaskXID(pixm);
gc = XCreateGC(dpy, pix, 0, NULL);
XSetForeground(dpy, gc, 0);
XFillRectangle(dpy, pix, gc, 0, 0, 7, 7);
XSetForeground(dpy, gc, 1);
XDrawLine(dpy, pix, gc, 0, 3, 6, 3);
XDrawLine(dpy, pix, gc, 3, 0, 3, 6);
panel->markerPix[ExternalInfo] = pixm;
panel->markerPix[PipeInfo] = pixm;
panel->markerPix[DirectoryInfo] = pixm;
panel->markerPix[WSMenuInfo] = pixm;
panel->markerPix[WWindowListInfo] = pixm;
XFreeGC(dpy, gc);
}
panel->box = WMCreateBox(panel->parent);
WMSetViewExpandsToParent(WMWidgetView(panel->box), 2, 2, 2, 2);
panel->typeP = WMCreatePopUpButton(panel->box);
WMResizeWidget(panel->typeP, 150, 20);
WMMoveWidget(panel->typeP, 10, 10);
WMAddPopUpButtonItem(panel->typeP, _("New Items"));
WMAddPopUpButtonItem(panel->typeP, _("Sample Commands"));
WMAddPopUpButtonItem(panel->typeP, _("Sample Submenus"));
WMSetPopUpButtonAction(panel->typeP, changedItemPad, panel);
WMSetPopUpButtonSelectedItem(panel->typeP, 0);
{
WEditMenu *pad;
WEditMenu *smenu;
ItemData *data;
pad = makeFactoryMenu(panel->box, 150);
WMMoveWidget(pad, 10, 40);
data = putNewItem(panel, pad, ExecInfo, _("Run Program"));
data = putNewItem(panel, pad, CommandInfo, _("Internal Command"));
smenu = putNewSubmenu(pad, _("Submenu"));
data = putNewItem(panel, pad, ExternalInfo, _("External Submenu"));
data = putNewItem(panel, pad, PipeInfo, _("Generated Submenu"));
data = putNewItem(panel, pad, DirectoryInfo, _("Directory Contents"));
data = putNewItem(panel, pad, WSMenuInfo, _("Workspace Menu"));
data = putNewItem(panel, pad, WWindowListInfo, _("Window List Menu"));
panel->itemPad[0] = pad;
}
{
WEditMenu *pad;
ItemData *data;
WMScrollView *sview;
sview = WMCreateScrollView(panel->box);
WMResizeWidget(sview, 150, 180);
WMMoveWidget(sview, 10, 40);
WMSetScrollViewHasVerticalScroller(sview, True);
pad = makeFactoryMenu(panel->box, 130);
WMSetScrollViewContentView(sview, WMWidgetView(pad));
data = putNewItem(panel, pad, ExecInfo, _("XTerm"));
data->param.exec.command = "xterm -sb -sl 2000 -bg black -fg white";
data = putNewItem(panel, pad, ExecInfo, _("rxvt"));
data->param.exec.command = "rxvt";
data = putNewItem(panel, pad, ExecInfo, _("ETerm"));
data->param.exec.command = "eterm";
data = putNewItem(panel, pad, ExecInfo, _("Run..."));
data->param.exec.command = _("%a(Run,Type command to run)");
data = putNewItem(panel, pad, ExecInfo, _("Netscape"));
data->param.exec.command = "netscape";
data = putNewItem(panel, pad, ExecInfo, _("gimp"));
data->param.exec.command = "gimp";
data = putNewItem(panel, pad, ExecInfo, _("epic"));
data->param.exec.command = "xterm -e epic";
data = putNewItem(panel, pad, ExecInfo, _("ee"));
data->param.exec.command = "ee";
data = putNewItem(panel, pad, ExecInfo, _("xv"));
data->param.exec.command = "xv";
data = putNewItem(panel, pad, ExecInfo, _("Acrobat Reader"));
data->param.exec.command = "acroread || /usr/local/Acrobat4/bin/acroread";
data = putNewItem(panel, pad, ExecInfo, _("ghostview"));
data->param.exec.command = "gv";
data = putNewItem(panel, pad, CommandInfo, _("Exit Window Maker"));
data->param.command.command = 3;
WMMapWidget(pad);
panel->itemPad[1] = sview;
}
{
WEditMenu *pad, *smenu;
ItemData *data;
WMScrollView *sview;
sview = WMCreateScrollView(panel->box);
WMResizeWidget(sview, 150, 180);
WMMoveWidget(sview, 10, 40);
WMSetScrollViewHasVerticalScroller(sview, True);
pad = makeFactoryMenu(panel->box, 130);
WMSetScrollViewContentView(sview, WMWidgetView(pad));
data = putNewItem(panel, pad, ExternalInfo, _("Debian Menu"));
data->param.pipe.command = "/etc/X11/WindowMaker/menu.hook";
data = putNewItem(panel, pad, PipeInfo, _("RedHat Menu"));
data->param.pipe.command = "wmconfig --output wmaker";
data = putNewItem(panel, pad, PipeInfo, _("Menu Conectiva"));
data->param.pipe.command = "wmconfig --output wmaker";
data = putNewItem(panel, pad, DirectoryInfo, _("Themes"));
data->param.directory.command = "setstyle";
data->param.directory.directory =
"/usr/share/WindowMaker/Themes /usr/local/share/WindowMaker/Themes $HOME/GNUstep/Library/WindowMaker/Themes";
data->param.directory.stripExt = 1;
data = putNewItem(panel, pad, DirectoryInfo, _("Bg Images (scale)"));
data->param.directory.command = "wmsetbg -u -s";
data->param.directory.directory =
"/opt/kde2/share/wallpapers /usr/share/WindowMaker/Backgrounds $HOME/GNUstep/Library/WindowMaker/Backgrounds";
data->param.directory.stripExt = 1;
data = putNewItem(panel, pad, DirectoryInfo, _("Bg Images (tile)"));
data->param.directory.command = "wmsetbg -u -t";
data->param.directory.directory =
"/opt/kde2/share/wallpapers /usr/share/WindowMaker/Backgrounds $HOME/GNUstep/Library/WindowMaker/Backgrounds";
data->param.directory.stripExt = 1;
smenu = putNewSubmenu(pad, _("Assorted XTerms"));
data = putNewItem(panel, smenu, ExecInfo, _("XTerm Yellow on Blue"));
data->param.exec.command = "xterm -sb -sl 2000 -bg midnightblue -fg yellow";
data = putNewItem(panel, smenu, ExecInfo, _("XTerm White on Black"));
data->param.exec.command = "xterm -sb -sl 2000 -bg black -fg white";
data = putNewItem(panel, smenu, ExecInfo, _("XTerm Black on White"));
data->param.exec.command = "xterm -sb -sl 2000 -bg white -fg black";
data = putNewItem(panel, smenu, ExecInfo, _("XTerm Black on Beige"));
data->param.exec.command = "xterm -sb -sl 2000 -bg '#bbbb99' -fg black";
data = putNewItem(panel, smenu, ExecInfo, _("XTerm White on Green"));
data->param.exec.command = "xterm -sb -sl 2000 -bg '#228822' -fg white";
data = putNewItem(panel, smenu, ExecInfo, _("XTerm White on Olive"));
data->param.exec.command = "xterm -sb -sl 2000 -bg '#335533' -fg white";
data = putNewItem(panel, smenu, ExecInfo, _("XTerm Blue on Blue"));
data->param.exec.command = "xterm -sb -sl 2000 -bg '#112244' -fg '#88aabb'";
data = putNewItem(panel, smenu, ExecInfo, _("XTerm BIG FONTS"));
data->param.exec.command = "xterm -sb -sl 2000 -bg black -fg white -fn 10x20";
WMMapWidget(pad);
panel->itemPad[2] = sview;
}
width = FRAME_WIDTH - 20 - 150 - 10 - 2;
panel->optionsF = WMCreateFrame(panel->box);
WMResizeWidget(panel->optionsF, width, FRAME_HEIGHT - 15);
WMMoveWidget(panel->optionsF, 10 + 150 + 10, 5);
width -= 20;
/* command */
panel->commandF = WMCreateFrame(panel->optionsF);
WMResizeWidget(panel->commandF, width, 50);
WMMoveWidget(panel->commandF, 10, 20);
WMSetFrameTitle(panel->commandF, _("Program to Run"));
WMSetFrameTitlePosition(panel->commandF, WTPAtTop);
panel->commandT = WMCreateTextField(panel->commandF);
WMResizeWidget(panel->commandT, width - 95, 20);
WMMoveWidget(panel->commandT, 10, 20);
panel->browseB = WMCreateCommandButton(panel->commandF);
WMResizeWidget(panel->browseB, 70, 24);
WMMoveWidget(panel->browseB, width - 80, 18);
WMSetButtonText(panel->browseB, _("Browse"));
WMSetButtonAction(panel->browseB, browseForFile, panel);
WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->commandT);
#if 0
panel->xtermC = WMCreateSwitchButton(panel->commandF);
WMResizeWidget(panel->xtermC, width - 20, 20);
WMMoveWidget(panel->xtermC, 10, 50);
WMSetButtonText(panel->xtermC, _("Run the program inside a Xterm"));
#endif
WMMapSubwidgets(panel->commandF);
/* path */
panel->pathF = WMCreateFrame(panel->optionsF);
WMResizeWidget(panel->pathF, width, 150);
WMMoveWidget(panel->pathF, 10, 40);
WMSetFrameTitle(panel->pathF, _("Path for Menu"));
panel->pathT = WMCreateTextField(panel->pathF);
WMResizeWidget(panel->pathT, width - 20, 20);
WMMoveWidget(panel->pathT, 10, 20);
WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->pathT);
label = WMCreateLabel(panel->pathF);
WMResizeWidget(label, width - 20, 80);
WMMoveWidget(label, 10, 50);
WMSetLabelText(label, _("Enter the path for a file containing a menu\n"
"or a list of directories with the programs you\n"
"want to have listed in the menu. Ex:\n"
"~/GNUstep/Library/WindowMaker/menu\n" "or\n" "/usr/X11R6/bin ~/xbin"));
WMMapSubwidgets(panel->pathF);
/* pipe */
panel->pipeF = WMCreateFrame(panel->optionsF);
WMResizeWidget(panel->pipeF, width, 155);
WMMoveWidget(panel->pipeF, 10, 30);
WMSetFrameTitle(panel->pipeF, _("Command"));
panel->pipeT = WMCreateTextField(panel->pipeF);
WMResizeWidget(panel->pipeT, width - 20, 20);
WMMoveWidget(panel->pipeT, 10, 20);
WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->pipeT);
label = WMCreateLabel(panel->pipeF);
WMResizeWidget(label, width - 20, 40);
WMMoveWidget(label, 10, 50);
WMSetLabelText(label, _("Enter a command that outputs a menu\n" "definition to stdout when invoked."));
panel->pipeCacheB = WMCreateSwitchButton(panel->pipeF);
WMResizeWidget(panel->pipeCacheB, width - 20, 40);
WMMoveWidget(panel->pipeCacheB, 10, 110);
WMSetButtonText(panel->pipeCacheB, _("Cache menu contents after opening for\n" "the first time"));
WMMapSubwidgets(panel->pipeF);
/* directory menu */
panel->dcommandF = WMCreateFrame(panel->optionsF);
WMResizeWidget(panel->dcommandF, width, 90);
WMMoveWidget(panel->dcommandF, 10, 25);
WMSetFrameTitle(panel->dcommandF, _("Command to Open Files"));
panel->dcommandT = WMCreateTextField(panel->dcommandF);
WMResizeWidget(panel->dcommandT, width - 20, 20);
WMMoveWidget(panel->dcommandT, 10, 20);
WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->dcommandT);
label = WMCreateLabel(panel->dcommandF);
WMResizeWidget(label, width - 20, 45);
WMMoveWidget(label, 10, 40);
WMSetLabelText(label, _("Enter the command you want to use to open the\n"
"files in the directories listed below."));
WMMapSubwidgets(panel->dcommandF);
panel->dpathF = WMCreateFrame(panel->optionsF);
WMResizeWidget(panel->dpathF, width, 80);
WMMoveWidget(panel->dpathF, 10, 125);
WMSetFrameTitle(panel->dpathF, _("Directories with Files"));
panel->dpathT = WMCreateTextField(panel->dpathF);
WMResizeWidget(panel->dpathT, width - 20, 20);
WMMoveWidget(panel->dpathT, 10, 20);
WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->dpathT);
panel->dstripB = WMCreateSwitchButton(panel->dpathF);
WMResizeWidget(panel->dstripB, width - 20, 20);
WMMoveWidget(panel->dstripB, 10, 50);
WMSetButtonText(panel->dstripB, _("Strip extensions from file names"));
WMSetButtonAction(panel->dstripB, buttonClicked, panel);
WMMapSubwidgets(panel->dpathF);
/* shortcut */
panel->shortF = WMCreateFrame(panel->optionsF);
WMResizeWidget(panel->shortF, width, 50);
WMMoveWidget(panel->shortF, 10, 160);
WMSetFrameTitle(panel->shortF, _("Keyboard Shortcut"));
panel->shortT = WMCreateTextField(panel->shortF);
WMResizeWidget(panel->shortT, width - 20 - 150, 20);
WMMoveWidget(panel->shortT, 10, 20);
WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->shortT);
panel->sgrabB = WMCreateCommandButton(panel->shortF);
WMResizeWidget(panel->sgrabB, 70, 24);
WMMoveWidget(panel->sgrabB, width - 80, 18);
WMSetButtonText(panel->sgrabB, _("Capture"));
WMSetButtonAction(panel->sgrabB, sgrabClicked, panel);
panel->sclearB = WMCreateCommandButton(panel->shortF);
WMResizeWidget(panel->sclearB, 70, 24);
WMMoveWidget(panel->sclearB, width - 155, 18);
WMSetButtonText(panel->sclearB, _("Clear"));
WMSetButtonAction(panel->sclearB, sgrabClicked, panel);
WMMapSubwidgets(panel->shortF);
/* internal command */
panel->icommandL = WMCreateList(panel->optionsF);
WMResizeWidget(panel->icommandL, width, 80);
WMMoveWidget(panel->icommandL, 10, 20);
WMSetListAction(panel->icommandL, icommandLClicked, panel);
WMAddNotificationObserver(dataChanged, panel, WMListSelectionDidChangeNotification, panel->icommandL);
WMInsertListItem(panel->icommandL, 0, _("Arrange Icons"));
WMInsertListItem(panel->icommandL, 1, _("Hide All Windows Except For The Focused One"));
WMInsertListItem(panel->icommandL, 2, _("Show All Windows"));
WMInsertListItem(panel->icommandL, 3, _("Exit Window Maker"));
WMInsertListItem(panel->icommandL, 4, _("Exit X Session"));
WMInsertListItem(panel->icommandL, 5, _("Restart Window Maker"));
WMInsertListItem(panel->icommandL, 6, _("Start Another Window Manager : ("));
WMInsertListItem(panel->icommandL, 7, _("Save Current Session"));
WMInsertListItem(panel->icommandL, 8, _("Clear Saved Session"));
WMInsertListItem(panel->icommandL, 9, _("Refresh Screen"));
WMInsertListItem(panel->icommandL, 10, _("Open Info Panel"));
WMInsertListItem(panel->icommandL, 11, _("Open Copyright Panel"));
panel->paramF = WMCreateFrame(panel->optionsF);
WMResizeWidget(panel->paramF, width, 50);
WMMoveWidget(panel->paramF, 10, 105);
WMSetFrameTitle(panel->paramF, _("Window Manager to Start"));
panel->paramT = WMCreateTextField(panel->paramF);
WMResizeWidget(panel->paramT, width - 20, 20);
WMMoveWidget(panel->paramT, 10, 20);
WMAddNotificationObserver(dataChanged, panel, WMTextDidChangeNotification, panel->paramT);
WMMapSubwidgets(panel->paramF);
panel->quickB = WMCreateSwitchButton(panel->optionsF);
WMResizeWidget(panel->quickB, width, 20);
WMMoveWidget(panel->quickB, 10, 120);
WMSetButtonText(panel->quickB, _("Do not confirm action."));
WMSetButtonAction(panel->quickB, buttonClicked, panel);
label = WMCreateLabel(panel->optionsF);
WMResizeWidget(label, width + 5, FRAME_HEIGHT - 50);
WMMoveWidget(label, 7, 20);
WMSetLabelText(label,
_("Instructions:\n\n"
" - drag items from the left to the menu to add new items\n"
" - drag items out of the menu to remove items\n"
" - drag items in menu to change their position\n"
" - drag items with Control pressed to copy them\n"
" - double click in a menu item to change the label\n"
" - click on a menu item to change related information"));
WMMapWidget(label);
WMRealizeWidget(panel->box);
WMMapSubwidgets(panel->box);
WMMapWidget(panel->box);
{
int i;
for (i = 0; i < 3; i++)
WMUnmapWidget(panel->itemPad[i]);
}
changedItemPad(panel->typeP, panel);
panel->sections[NoInfo][0] = label;
panel->sections[ExecInfo][0] = panel->commandF;
panel->sections[ExecInfo][1] = panel->shortF;
panel->sections[CommandInfo][0] = panel->icommandL;
panel->sections[CommandInfo][1] = panel->shortF;
panel->sections[ExternalInfo][0] = panel->pathF;
panel->sections[PipeInfo][0] = panel->pipeF;
panel->sections[DirectoryInfo][0] = panel->dpathF;
panel->sections[DirectoryInfo][1] = panel->dcommandF;
panel->currentType = NoInfo;
showData(panel);
{
WMPoint pos;
pos = WMGetViewScreenPosition(WMWidgetView(panel->box));
if (pos.x < 200) {
pos.x += FRAME_WIDTH + 20;
} else {
pos.x = 10;
}
pos.y = WMAX(pos.y - 100, 0);
if (panel->menu)
WEditMenuShowAt(panel->menu, pos.x, pos.y);
}
}
static void freeItemData(ItemData * data)
{
#define CFREE(d) if (d) wfree(d)
/* TODO */
switch (data->type) {
case CommandInfo:
CFREE(data->param.command.parameter);
CFREE(data->param.command.shortcut);
break;
case ExecInfo:
CFREE(data->param.exec.command);
CFREE(data->param.exec.shortcut);
break;
case PipeInfo:
CFREE(data->param.pipe.command);
break;
case ExternalInfo:
CFREE(data->param.external.path);
break;
case DirectoryInfo:
CFREE(data->param.directory.command);
CFREE(data->param.directory.directory);
break;
default:
break;
}
wfree(data);
#undef CFREE
}
static ItemData *parseCommand(WMPropList * item)
{
ItemData *data = NEW(ItemData);
WMPropList *p;
char *command = NULL;
char *parameter = NULL;
char *shortcut = NULL;
int i = 1;
p = WMGetFromPLArray(item, i++);
command = WMGetFromPLString(p);
if (strcmp(command, "SHORTCUT") == 0) {
p = WMGetFromPLArray(item, i++);
shortcut = WMGetFromPLString(p);
p = WMGetFromPLArray(item, i++);
command = WMGetFromPLString(p);
}
p = WMGetFromPLArray(item, i++);
if (p)
parameter = WMGetFromPLString(p);
if (strcmp(command, "EXEC") == 0 || strcmp(command, "SHEXEC") == 0) {
data->type = ExecInfo;
data->param.exec.command = wstrdup(parameter);
if (shortcut)
data->param.exec.shortcut = wstrdup(shortcut);
} else if (strcmp(command, "OPEN_MENU") == 0) {
char *p;
/*
* dir menu, menu file
* dir WITH
* |pipe
*/
p = parameter;
while (isspace(*p) && *p)
p++;
if (*p == '|') {
if (*(p + 1) == '|') {
p++;
data->param.pipe.cached = 0;
} else {
data->param.pipe.cached = 1;
}
data->type = PipeInfo;
data->param.pipe.command = wtrimspace(p + 1);
} else {
char *s;
p = wstrdup(p);
s = strstr(p, "WITH");
if (s) {
char **tokens;
char **ctokens;
int tokn;
int i, j;
data->type = DirectoryInfo;
*s = '\0';
s += 5;
while (*s && isspace(*s))
s++;
data->param.directory.command = wstrdup(s);
wtokensplit(p, &tokens, &tokn);
wfree(p);
ctokens = wmalloc(sizeof(char *) * tokn);
for (i = 0, j = 0; i < tokn; i++) {
if (strcmp(tokens[i], "-noext") == 0) {
data->param.directory.stripExt = 1;
} else {
ctokens[j++] = tokens[i];
}
}
data->param.directory.directory = wtokenjoin(ctokens, j);
wfree(ctokens);
wtokenfree(tokens, tokn);
} else {
data->type = ExternalInfo;
data->param.external.path = p;
}
}
} else if (strcmp(command, "WORKSPACE_MENU") == 0) {
data->type = WSMenuInfo;
} else if (strcmp(command, "WINDOWS_MENU") == 0) {
data->type = WWindowListInfo;
} else {
int cmd;
if (strcmp(command, "ARRANGE_ICONS") == 0) {
cmd = 0;
} else if (strcmp(command, "HIDE_OTHERS") == 0) {
cmd = 1;
} else if (strcmp(command, "SHOW_ALL") == 0) {
cmd = 2;
} else if (strcmp(command, "EXIT") == 0) {
cmd = 3;
} else if (strcmp(command, "SHUTDOWN") == 0) {
cmd = 4;
} else if (strcmp(command, "RESTART") == 0) {
if (parameter) {
cmd = 6;
} else {
cmd = 5;
}
} else if (strcmp(command, "SAVE_SESSION") == 0) {
cmd = 7;
} else if (strcmp(command, "CLEAR_SESSION") == 0) {
cmd = 8;
} else if (strcmp(command, "REFRESH") == 0) {
cmd = 9;
} else if (strcmp(command, "INFO_PANEL") == 0) {
cmd = 10;
} else if (strcmp(command, "LEGAL_PANEL") == 0) {
cmd = 11;
} else {
wwarning(_("unknown command '%s' in menu"), command);
goto error;
}
data->type = CommandInfo;
data->param.command.command = cmd;
if (shortcut)
data->param.command.shortcut = wstrdup(shortcut);
if (parameter)
data->param.command.parameter = wstrdup(parameter);
}
return data;
error:
wfree(data);
return NULL;
}
static void updateFrameTitle(_Panel * panel, char *title, InfoType type)
{
if (type != NoInfo) {
char *tmp;
switch (type) {
case ExecInfo:
tmp = wstrconcat(title, _(": Execute Program"));
break;
case CommandInfo:
tmp = wstrconcat(title, _(": Perform Internal Command"));
break;
case ExternalInfo:
tmp = wstrconcat(title, _(": Open a Submenu"));
break;
case PipeInfo:
tmp = wstrconcat(title, _(": Program Generated Submenu"));
break;
case DirectoryInfo:
tmp = wstrconcat(title, _(": Directory Contents Menu"));
break;
case WSMenuInfo:
tmp = wstrconcat(title, _(": Open Workspaces Submenu"));
break;
case WWindowListInfo:
tmp = wstrconcat(title, _(": Open Window List Submenu"));
break;
default:
tmp = NULL;
break;
}
WMSetFrameTitle(panel->optionsF, tmp);
wfree(tmp);
} else {
WMSetFrameTitle(panel->optionsF, NULL);
}
}
static void changeInfoType(_Panel * panel, char *title, InfoType type)
{
WMWidget **w;
if (panel->currentType != type) {
w = panel->sections[panel->currentType];
while (*w) {
WMUnmapWidget(*w);
w++;
}
WMUnmapWidget(panel->paramF);
WMUnmapWidget(panel->quickB);
w = panel->sections[type];
while (*w) {
WMMapWidget(*w);
w++;
}
}
updateFrameTitle(panel, title, type);
panel->currentType = type;
}
static void updateMenuItem(_Panel * panel, WEditMenuItem * item, WMWidget * changedWidget)
{
ItemData *data = WGetEditMenuItemData(item);
assert(data != NULL);
#define REPLACE(v, d) if (v) wfree(v); v = d
switch (data->type) {
case ExecInfo:
if (changedWidget == panel->commandT) {
REPLACE(data->param.exec.command, WMGetTextFieldText(panel->commandT));
}
if (changedWidget == panel->shortT) {
REPLACE(data->param.exec.shortcut, WMGetTextFieldText(panel->shortT));
}
break;
case CommandInfo:
if (changedWidget == panel->icommandL) {
data->param.command.command = WMGetListSelectedItemRow(panel->icommandL);
}
switch (data->param.command.command) {
case 3:
case 4:
if (changedWidget == panel->quickB) {
REPLACE(data->param.command.parameter, WMGetButtonSelected(panel->quickB)
? wstrdup("QUICK") : NULL);
}
break;
case 6:
if (changedWidget == panel->paramT) {
REPLACE(data->param.command.parameter, WMGetTextFieldText(panel->paramT));
}
break;
}
if (changedWidget == panel->shortT) {
REPLACE(data->param.command.shortcut, WMGetTextFieldText(panel->shortT));
}
break;
case PipeInfo:
if (changedWidget == panel->pipeT) {
REPLACE(data->param.pipe.command, WMGetTextFieldText(panel->pipeT));
}
if (changedWidget == panel->pipeCacheB) {
data->param.pipe.cached = WMGetButtonSelected(panel->pipeCacheB);
}
break;
case ExternalInfo:
if (changedWidget == panel->pathT) {
REPLACE(data->param.external.path, WMGetTextFieldText(panel->pathT));
}
break;
case DirectoryInfo:
if (changedWidget == panel->dpathT) {
REPLACE(data->param.directory.directory, WMGetTextFieldText(panel->dpathT));
}
if (changedWidget == panel->dcommandT) {
REPLACE(data->param.directory.command, WMGetTextFieldText(panel->dcommandT));
}
if (changedWidget == panel->dstripB) {
data->param.directory.stripExt = WMGetButtonSelected(panel->dstripB);
}
break;
default:
assert(0);
break;
}
#undef REPLACE
}
static void
menuItemCloned(WEditMenuDelegate * delegate, WEditMenu * menu, WEditMenuItem * origItem, WEditMenuItem * newItem)
{
ItemData *data = WGetEditMenuItemData(origItem);
ItemData *newData;
if (!data)
return;
#define DUP(s) (s) ? wstrdup(s) : NULL
newData = NEW(ItemData);
newData->type = data->type;
switch (data->type) {
case ExecInfo:
newData->param.exec.command = DUP(data->param.exec.command);
newData->param.exec.shortcut = DUP(data->param.exec.shortcut);
break;
case CommandInfo:
newData->param.command.command = data->param.command.command;
newData->param.command.parameter = DUP(data->param.command.parameter);
newData->param.command.shortcut = DUP(data->param.command.shortcut);
break;
case PipeInfo:
newData->param.pipe.command = DUP(data->param.pipe.command);
newData->param.pipe.cached = data->param.pipe.cached;
break;
case ExternalInfo:
newData->param.external.path = DUP(data->param.external.path);
break;
case DirectoryInfo:
newData->param.directory.directory = DUP(data->param.directory.directory);
newData->param.directory.command = DUP(data->param.directory.command);
newData->param.directory.stripExt = data->param.directory.stripExt;
break;
default:
break;
}
#undef DUP
WSetEditMenuItemData(newItem, newData, (WMCallback *) freeItemData);
}
static void menuItemEdited(struct WEditMenuDelegate *delegate, WEditMenu * menu, WEditMenuItem * item)
{
_Panel *panel = (_Panel *) delegate->data;
WEditMenu *submenu;
updateFrameTitle(panel, WGetEditMenuItemTitle(item), panel->currentType);
submenu = WGetEditMenuSubmenu(menu, item);
if (submenu) {
WSetEditMenuTitle(submenu, WGetEditMenuItemTitle(item));
}
}
static Bool shouldRemoveItem(struct WEditMenuDelegate *delegate, WEditMenu * menu, WEditMenuItem * item)
{
_Panel *panel = (_Panel *) delegate->data;
if (panel->dontAsk)
return True;
if (WGetEditMenuSubmenu(menu, item)) {
int res;
res = WMRunAlertPanel(WMWidgetScreen(menu), NULL,
_("Remove Submenu"),
_("Removing this item will destroy all items inside\n"
"the submenu. Do you really want to do that?"),
_("Yes"), _("No"), _("Yes, don't ask again."));
switch (res) {
case WAPRDefault:
return True;
case WAPRAlternate:
return False;
case WAPROther:
panel->dontAsk = True;
return True;
}
}
return True;
}
static void menuItemDeselected(WEditMenuDelegate * delegate, WEditMenu * menu, WEditMenuItem * item)
{
_Panel *panel = (_Panel *) delegate->data;
changeInfoType(panel, NULL, NoInfo);
}
static void menuItemSelected(WEditMenuDelegate * delegate, WEditMenu * menu, WEditMenuItem * item)
{
ItemData *data = WGetEditMenuItemData(item);
_Panel *panel = (_Panel *) delegate->data;
panel->currentItem = item;
if (data) {
changeInfoType(panel, WGetEditMenuItemTitle(item), data->type);
switch (data->type) {
case NoInfo:
break;
case ExecInfo:
WMSetTextFieldText(panel->commandT, data->param.exec.command);
WMSetTextFieldText(panel->shortT, data->param.exec.shortcut);
break;
case CommandInfo:
WMSelectListItem(panel->icommandL, data->param.command.command);
WMSetListPosition(panel->icommandL, data->param.command.command - 2);
WMSetTextFieldText(panel->shortT, data->param.command.shortcut);
switch (data->param.command.command) {
case 3:
case 4:
WMSetButtonSelected(panel->quickB, data->param.command.parameter != NULL);
break;
case 6:
WMSetTextFieldText(panel->paramT, data->param.command.parameter);
break;
}
icommandLClicked(panel->icommandL, panel);
break;
case PipeInfo:
WMSetTextFieldText(panel->pipeT, data->param.pipe.command);
WMSetButtonSelected(panel->pipeCacheB, data->param.pipe.cached);
break;
case ExternalInfo:
WMSetTextFieldText(panel->pathT, data->param.external.path);
break;
case DirectoryInfo:
WMSetTextFieldText(panel->dpathT, data->param.directory.directory);
WMSetTextFieldText(panel->dcommandT, data->param.directory.command);
WMSetButtonSelected(panel->dstripB, data->param.directory.stripExt);
break;
case WSMenuInfo:
break;
default:
break;
}
}
}
static WEditMenu *buildSubmenu(_Panel * panel, WMPropList * pl)
{
WMScreen *scr = WMWidgetScreen(panel->parent);
WEditMenu *menu;
WEditMenuItem *item;
char *title;
WMPropList *tp, *bp;
int i;
tp = WMGetFromPLArray(pl, 0);
title = WMGetFromPLString(tp);
menu = WCreateEditMenu(scr, title);
for (i = 1; i < WMGetPropListItemCount(pl); i++) {
WMPropList *pi;
pi = WMGetFromPLArray(pl, i);
tp = WMGetFromPLArray(pi, 0);
bp = WMGetFromPLArray(pi, 1);
title = WMGetFromPLString(tp);
if (!bp || WMIsPLArray(bp)) { /* it's a submenu */
WEditMenu *submenu;
submenu = buildSubmenu(panel, pi);
item = WAddMenuItemWithTitle(menu, title);
WSetEditMenuSubmenu(menu, item, submenu);
} else {
ItemData *data;
item = WAddMenuItemWithTitle(menu, title);
data = parseCommand(pi);
if (panel->markerPix[data->type])
WSetEditMenuItemImage(item, panel->markerPix[data->type]);
WSetEditMenuItemData(item, data, (WMCallback *) freeItemData);
}
}
WSetEditMenuAcceptsDrop(menu, True);
WSetEditMenuDelegate(menu, &menuDelegate);
WMRealizeWidget(menu);
return menu;
}
static void buildMenuFromPL(_Panel * panel, WMPropList * pl)
{
panel->menu = buildSubmenu(panel, pl);
}
static WMPropList *getDefaultMenu(_Panel * panel)
{
WMPropList *menu;
char *menuPath, *gspath;
gspath = wusergnusteppath();
menuPath = wmalloc(strlen(gspath) + 128);
sprintf(menuPath, "%s/Library/WindowMaker/plmenu", gspath);
menu = WMReadPropListFromFile(menuPath);
if (!menu) {
char *buffer, *msg;
msg = _("Could not open default menu from '%s'");
buffer = wmalloc(strlen(msg) + strlen(menuPath) + 10);
sprintf(buffer, msg, menuPath);
WMRunAlertPanel(WMWidgetScreen(panel->parent), panel->parent,
_("Error"), buffer, _("OK"), NULL, NULL);
wfree(buffer);
}
wfree(menuPath);
return menu;
}
static void showData(_Panel * panel)
{
char *gspath;
char *menuPath;
WMPropList *pmenu;
gspath = wusergnusteppath();
menuPath = wmalloc(strlen(gspath) + 32);
strcpy(menuPath, gspath);
strcat(menuPath, "/Defaults/WMRootMenu");
pmenu = WMReadPropListFromFile(menuPath);
if (!pmenu || !WMIsPLArray(pmenu)) {
int res;
res = WMRunAlertPanel(WMWidgetScreen(panel->parent), panel->parent,
_("Warning"),
_("The menu file format currently in use is not supported\n"
"by this tool. Do you want to discard the current menu\n"
"to use this tool?"),
_("Yes, Discard and Update"), _("No, Keep Current Menu"), NULL);
if (res == WAPRDefault) {
pmenu = getDefaultMenu(panel);
if (!pmenu) {
pmenu = WMCreatePLArray(WMCreatePLString("Applications"), NULL);
}
} else {
panel->dontSave = True;
return;
}
}
panel->menuPath = menuPath;
buildMenuFromPL(panel, pmenu);
WMReleasePropList(pmenu);
}
static Bool notblank(char *s)
{
if (s) {
while (*s++) {
if (!isspace(*s))
return True;
}
}
return False;
}
static WMPropList *processData(char *title, ItemData * data)
{
WMPropList *item;
char *s1;
static WMPropList *pscut = NULL;
static WMPropList *pomenu = NULL;
int i;
if (!pscut) {
pscut = WMCreatePLString("SHORTCUT");
pomenu = WMCreatePLString("OPEN_MENU");
}
item = WMCreatePLArray(WMCreatePLString(title), NULL);
switch (data->type) {
case ExecInfo:
if (data->param.exec.command == NULL)
return NULL;
#if 1
if (strpbrk(data->param.exec.command, "&$*|><?`=;")) {
s1 = "SHEXEC";
} else {
s1 = "EXEC";
}
#else
s1 = "SHEXEC";
#endif
if (notblank(data->param.exec.shortcut)) {
WMAddToPLArray(item, pscut);
WMAddToPLArray(item, WMCreatePLString(data->param.exec.shortcut));
}
WMAddToPLArray(item, WMCreatePLString(s1));
WMAddToPLArray(item, WMCreatePLString(data->param.exec.command));
break;
case CommandInfo:
if (notblank(data->param.command.shortcut)) {
WMAddToPLArray(item, pscut);
WMAddToPLArray(item, WMCreatePLString(data->param.command.shortcut));
}
i = data->param.command.command;
WMAddToPLArray(item, WMCreatePLString(commandNames[i]));
switch (i) {
case 3:
case 4:
if (data->param.command.parameter) {
WMAddToPLArray(item, WMCreatePLString(data->param.command.parameter));
}
break;
case 6: /* restart */
if (data->param.command.parameter) {
WMAddToPLArray(item, WMCreatePLString(data->param.command.parameter));
}
break;
}
break;
case PipeInfo:
if (!data->param.pipe.command)
return NULL;
WMAddToPLArray(item, pomenu);
if (data->param.pipe.cached)
s1 = wstrconcat("| ", data->param.pipe.command);
else
s1 = wstrconcat("|| ", data->param.pipe.command);
WMAddToPLArray(item, WMCreatePLString(s1));
wfree(s1);
break;
case ExternalInfo:
if (!data->param.external.path)
return NULL;
WMAddToPLArray(item, pomenu);
WMAddToPLArray(item, WMCreatePLString(data->param.external.path));
break;
case DirectoryInfo:
if (!data->param.directory.directory || !data->param.directory.command)
return NULL;
{
int l;
char *tmp;
l = strlen(data->param.directory.directory);
l += strlen(data->param.directory.command);
l += 32;
WMAddToPLArray(item, pomenu);
tmp = wmalloc(l);
sprintf(tmp, "%s%s WITH %s",
data->param.directory.stripExt ? "-noext " : "",
data->param.directory.directory, data->param.directory.command);
WMAddToPLArray(item, WMCreatePLString(tmp));
wfree(tmp);
}
break;
case WSMenuInfo:
WMAddToPLArray(item, WMCreatePLString("WORKSPACE_MENU"));
break;
case WWindowListInfo:
WMAddToPLArray(item, WMCreatePLString("WINDOWS_MENU"));
break;
default:
assert(0);
break;
}
return item;
}
static WMPropList *processSubmenu(WEditMenu * menu)
{
WEditMenuItem *item;
WMPropList *pmenu;
WMPropList *pl;
char *s;
int i;
s = WGetEditMenuTitle(menu);
pl = WMCreatePLString(s);
pmenu = WMCreatePLArray(pl, NULL);
i = 0;
while ((item = WGetEditMenuItem(menu, i++))) {
WEditMenu *submenu;
s = WGetEditMenuItemTitle(item);
submenu = WGetEditMenuSubmenu(menu, item);
if (submenu) {
pl = processSubmenu(submenu);
} else {
pl = processData(s, WGetEditMenuItemData(item));
}
if (!pl)
continue;
WMAddToPLArray(pmenu, pl);
}
return pmenu;
}
static WMPropList *buildPLFromMenu(_Panel * panel)
{
WMPropList *menu;
menu = processSubmenu(panel->menu);
return menu;
}
static void storeData(_Panel * panel)
{
WMPropList *menu;
if (panel->dontSave)
return;
menu = buildPLFromMenu(panel);
WMWritePropListToFile(menu, panel->menuPath, True);
WMReleasePropList(menu);
}
static void showMenus(_Panel * panel)
{
if (panel->menu)
WEditMenuUnhide(panel->menu);
}
static void hideMenus(_Panel * panel)
{
if (panel->menu)
WEditMenuHide(panel->menu);
}
Panel *InitMenu(WMScreen * scr, WMWidget * parent)
{
_Panel *panel;
panel = wmalloc(sizeof(_Panel));
memset(panel, 0, sizeof(_Panel));
panel->sectionName = _("Applications Menu Definition");
panel->description = _("Edit the menu for launching applications.");
panel->parent = parent;
panel->callbacks.createWidgets = createPanel;
panel->callbacks.updateDomain = storeData;
panel->callbacks.showPanel = showMenus;
panel->callbacks.hidePanel = hideMenus;
AddSection(panel, ICON_FILE);
return panel;
}