diff --git a/src/dock.c b/src/dock.c index b8ac8845..1bdd2f5a 100644 --- a/src/dock.c +++ b/src/dock.c @@ -2940,7 +2940,7 @@ execCommand(WAppIcon *btn, char *command, WSavedState *state) return 0; } - ParseCommand(cmdline, &argv, &argc); + TokenizeString(cmdline, &argv, &argc); if (argv==NULL) { if (cmdline) diff --git a/src/funcs.h b/src/funcs.h index aabe1e8f..94fcf243 100644 --- a/src/funcs.h +++ b/src/funcs.h @@ -151,8 +151,7 @@ void wHackedGrabButton(unsigned int button, unsigned int modifiers, int keyboard_mode, Window confine_to, Cursor cursor); -/* this function is in dock.c */ -void ParseCommand(char *command, char ***argv, int *argc); +void TokenizeString(char *command, char ***argv, int *argc); void ExecExitScript(); diff --git a/src/menureader.c b/src/menureader.c new file mode 100644 index 00000000..f0218172 --- /dev/null +++ b/src/menureader.c @@ -0,0 +1,464 @@ +/* menureader.c- root menu definition readers + * + * Window Maker window manager + * + * Copyright (c) 2000 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 +#include +#include +#include +#include + +#include "WindowMaker.h" + +#include "misc.h" + +#include "rootmenu.h" + + +typedef struct PLMenuReaderData { + WRootMenuReader *reader; + + proplist_t pl; + int curIndex; + + proplist_t *submenu; + int *curSubIndex; + int submenuDepth; + +} PLMenuReaderData; + + +typedef struct TextMenuReaderData { + WRootMenuReader *reader; + + FILE *file; + +} TextMenuReaderData; + + +typedef struct PipeMenuReaderData { + WRootMenuReader *reader; + +} PipeMenuReaderData; + + +typedef struct DirMenuReaderData { + WRootMenuReader *reader; + + char **dirList; + int dirCount; + +} DirMenuReaderData; + +/* +typedef struct GNOMEMenuReaderData { +} GNOMEMenuReaderData; +*/ + + + + + +static WRootMenuData *pl_openMenu(proplist_t pl); +static Bool pl_hasMoreData(WRootMenuData *data); +static Bool pl_nextCommand(WRootMenuData *data, + char **title, + char **command, + char **parameter, + char **shortcut); +static void pl_closeMenuFile(WRootMenuData *data); + + + +static WRootMenuData *text_openMenuFile(char *path); +static Bool text_hasMoreData(WRootMenuData *data); +static Bool text_nextCommand(WRootMenuData *data, + char **title, + char **command, + char **parameter, + char **shortcut); +static void text_closeMenuFile(WRootMenuData *data); + + +static WRootMenuData *dir_openMenuFile(char *path); +static Bool dir_hasMoreData(WRootMenuData *data); +static Bool dir_nextCommand(WRootMenuData *data, + char **title, + char **command, + char **parameter, + char **shortcut); +static void dir_closeMenuFile(WRootMenuData *data); + + + + + + +static WRootMenuReader PLMenuReader = { + pl_hasMoreData, + pl_nextCommand, + pl_closeMenuFile +}; + +static WRootMenuReader TextMenuReader = { + text_hasMoreData, + text_nextCommand, + text_closeMenuFile +}; + +static WRootMenuReader DirMenuReaderData = { + dir_hasMoreData, + dir_nextCommand, + dir_closeMenuFile +}; + +/* +WRootMenuReader GNOMEMenuReaderData = { +}; +*/ + + + + +#define LINESIZE 1024 + +static char linebuf[LINESIZE]; + + + +/* ---------- proplist ---------- */ + + +static WRootMenuData *pl_openMenuFile(proplist_t pl) +{ + PLRootMenuData *data = wmalloc(sizeof(PLRootMenuData)); + + data->reader = PLMenuReader; + + data->pl = pl; + data->curIndex = 0; + + data->submenu = NULL; + data->curSubIndex = NULL; + data->submenuDepth = 0; + + return data; +} + + +static Bool pl_hasMoreData(WRootMenuData *data) +{ +} + + +static Bool pl_nextCommand(WRootMenuData *data, + char **title, + char **command, + char **parameter, + char **shortcut) +{ +} + + +static void pl_closeMenuFile(WRootMenuData *data) +{ + if (data->submenu) + free(data->submenu); + if (data->curSubIndex) + free(data->curSubIndex); + + PLRelease(data->pl); + + free(data); +} + + +/* ---------- text ---------- */ + + +static WRootMenuData *text_openMenuFile(char *path) +{ + TextMenuReaderData *data; + + data = wmalloc(sizeof(TextMenuReaderData)); + data->reader = TextMenuReader; + + data->file = fopen(path, "r"); + if (!data->file) { + + return NULL; + } +} + + +static Bool text_hasMoreData(WRootMenuData *data) +{ +} + + +static Bool text_nextCommand(WRootMenuData *data, + char **title, + char **command, + char **parameter, + char **shortcut) +{ +} + + +static void text_closeMenuFile(WRootMenuData *data) +{ +} + + +/* ---------- directory ---------- */ + + +static WRootMenuData *dir_openMenuFile(char *paths, time_t *timestamp) +{ + DirMenuReaderData *data; + char **dirs; + int dirN; + time_t checksum = 0; + int i, c; + + /* timestamp for directory is a "checksum" of the directory times */ + + TokenizeString(paths, &dirs, &dirN); + + if (dirN == 0) { + return NULL; + } + + for (c = 0, i = 0; i < dirN; i++) { + char *tmp; + + if (strcmp(dirs[i], "-noext")==0) { + i++; + continue; + } + + tmp = wexpandpath(dirs[i]); + free(dirs[i]); + dirs[i] = tmp; + + if (stat(dirs[i], &stat_buf)<0) { + wsyserror(_("%s:could not stat menu"), dirs[i]); + free(dirs[i]); + dirs[i] = NULL; + } else { + c++; + checksum += stat_buf.st_mtime; + } + } + + if (*timestamp == checksum && *timestamp != 0) { + return NULL; + } + + if (c == 0) { + for (i = 0; i < dirN; i++) { + if (dirs[i]) + free(dirs[i]); + } + free(dirs); + + return NULL; + } + + data = wmalloc(sizeof(DirMenuReaderData)); + data->reader = DirMenuReader; + + + +} + + +static Bool dir_hasMoreData(WRootMenuData *data) +{ +} + +static Bool dir_nextCommand(WRootMenuData *data, + char **title, + char **command, + char **parameter, + char **shortcut) +{ +} + +static void dir_closeMenuFile(WRootMenuData *data) +{ +} + + + + + +WRootMenuData *OpenMenu(char *path, time_t *menuTime) +{ + proplist pl; + struct stat stat_buf; + WRootMenuData *data; + + /* check whether it's a piped menu */ + if (*path == '|') { + /* piped menus have the following semantics for menuTime: + * if it's 0, then it wasnt loaded yet + * if it's 1, it was already loaded, so do not reload + * (would be too slow) + * now, menuTime will only be set to 1 if the pipe command is + * specified as ||command instead of |command + * in other words ||command means force the submenu to always refresh + */ + if (*menuTime == 0) { + data = pipe_openMenu(path); + } + if (path[1] != '|') { + *menuTime = 1; + } + return data; + } + + if (stat(path, &stat_buf) < 0) { + wsyserror(_("could not stat() menu file '%s'")); + return NULL; + } + + /* check whether it's a directory */ + if (S_ISDIR(stat_buf.st_mode)) { + return dir_openMenuFile(path, menuTime); + } + + + if (*menuTime >= stat_buf.st_mtime && *menuTime != 0) { + /* no changes in the menu file */ + return NULL; + } + + /* then check whether it's a proplist menu */ + pl = ReadProplistFromFile(path); + if (pl && PLIsArray(pl)) { + *menuTime = stat_buf.st_mtime; + return pl_openMenu(pl); + } + + *menuTime = stat_buf.st_mtime; + /* assume its a plain text menu */ + return text_openMenuFile(path); +} + + + +WRootMenuData *ReopenRootMenu(time_t *checkTime, + char **menuPath, + time_t *menuTimestamp) +{ + proplist pl; + struct stat stat_buf; + char *path; + + + if (stat(path, &stat_buf) < 0) { + wsyserror(_("could not stat() menu file '%s'")); + return NULL; + } + + if (*menuTime >= stat_buf.st_mtime && *checkTime != 0) { + /* no changes in WMRootMenu, see if the contents changed */ + if (*menuPath != NULL) { + return OpenMenu(*menuPath, menuTimestamp); + } else { + return NULL; + } + } + + *checkTime = stat_buf.st_mtime; + + pl = ReadProplistFromFile(path); + if (!pl) { + wwarning(_("could not load domain %s from user defaults database"), + "WMRootMenu"); + return NULL; + } + + if (PLIsString(pl)) { + char *tmp; + char *path; + Bool menu_is_default = False; + + tmp = wexpandpath(PLGetString(pl)); + + path = getLocalizedMenuFile(tmp); + + if (!path) { + path = wfindfile(DEF_CONFIG_PATHS, tmp); + } + + if (!path) { + wwarning(_("could not find menu file '%s' referenced in WMRootMenu"), + tmp); + path = wfindfile(DEF_CONFIG_PATHS, DEF_MENU_FILE); + menu_is_default = True; + } + + if (!path) { + wwarning(_("could not find any usable menu files. Please check '%s'"), + tmp); + free(tmp); + return NULL; + } + + free(tmp); + + if (*menuPath) { + if (strcmp(*menuPath, path) != 0) { + *menuTimestamp = 0; + free(*menuPath); + *menuPath = path; + + if (menu_is_default) { + wwarning(_("using default menu file \"%s\" as the menu referenced in WMRootMenu could not be found "), + path); + } + } else { + /* the menu path didn't change, but the + * pointed file might have changed, so we don't return + */ + } + } else { + *menuPath = path; + } + + return OpenMenu(*menuPath, menuTimestamp); + } else if (PLIsArray(pl)) { + + *menuTimestamp = stat_buf.st_mtime; + + return pl_openMenu(pl); + } else { + wwarning(_("invalid content in menu file '%s'.\nIt should either be a property list menu or the path to the file, enclosed in \"."), + path); + return NULL; + } +} + + + diff --git a/src/misc.c b/src/misc.c index 524a4eb0..b0812368 100644 --- a/src/misc.c +++ b/src/misc.c @@ -625,29 +625,27 @@ next_token(char *word, char **next) } +/* separate a string in tokens, taking " and ' into account */ void -ParseCommand(char *command, char ***argv, int *argc) +TokenizeString(char *command, char ***argv, int *argc) { - WMBag *bag = WMCreateBag(4); char *token, *line; - int count, j; + int count; + count = 0; line = command; do { token = next_token(line, &line); if (token) { - WMPutInBag(bag, token); + if (count == 0) + *argv = wmalloc(sizeof(char**)); + else + *argv = wrealloc(*argv, (count+1)*sizeof(char**)); + (*argv)[count++] = token; } } while (token!=NULL && line!=NULL); - count = WMGetBagItemCount(bag); - *argv = wmalloc(sizeof(char*)*count); - for (j = 0; j < count; j++) { - (*argv)[j] = WMGetFromBag(bag, j); - } *argc = count; - - WMFreeBag(bag); } diff --git a/src/session.c b/src/session.c index a4a334c8..d4e45b49 100644 --- a/src/session.c +++ b/src/session.c @@ -381,7 +381,7 @@ execCommand(WScreen *scr, char *command, char *host) char **argv; int argc; - ParseCommand(command, &argv, &argc); + TokenizeString(command, &argv, &argc); if (argv==NULL) { return 0;