changed indentation to use spaces only
[wmaker-crm.git] / src / menureader.c
blob6aa3cf6d128425541cfbddf82a27eec15b2b9db7
1 /* menureader.c- root menu definition readers
3 * Window Maker window manager
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
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20 * USA.
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <sys/types.h>
28 #include <unistd.h>
30 #include "WindowMaker.h"
32 #include "misc.h"
34 #include "rootmenu.h"
37 typedef struct PLMenuReaderData {
38 WRootMenuReader *reader;
40 WMPropList *pl;
41 int curIndex;
43 WMPropList **submenu;
44 int *curSubIndex;
45 int submenuDepth;
47 } PLMenuReaderData;
50 typedef struct TextMenuReaderData {
51 WRootMenuReader *reader;
53 FILE *file;
55 } TextMenuReaderData;
58 typedef struct PipeMenuReaderData {
59 WRootMenuReader *reader;
61 } PipeMenuReaderData;
64 typedef struct DirMenuReaderData {
65 WRootMenuReader *reader;
67 char **dirList;
68 int dirCount;
70 } DirMenuReaderData;
73 typedef struct GNOMEMenuReaderData {
74 } GNOMEMenuReaderData;
81 static WRootMenuData *pl_openMenu(WMPropList *pl);
82 static Bool pl_hasMoreData(WRootMenuData *data);
83 static Bool pl_nextCommand(WRootMenuData *data,
84 char **title,
85 char **command,
86 char **parameter,
87 char **shortcut);
88 static void pl_closeMenuFile(WRootMenuData *data);
92 static WRootMenuData *text_openMenuFile(char *path);
93 static Bool text_hasMoreData(WRootMenuData *data);
94 static Bool text_nextCommand(WRootMenuData *data,
95 char **title,
96 char **command,
97 char **parameter,
98 char **shortcut);
99 static void text_closeMenuFile(WRootMenuData *data);
102 static WRootMenuData *dir_openMenuFile(char *path);
103 static Bool dir_hasMoreData(WRootMenuData *data);
104 static Bool dir_nextCommand(WRootMenuData *data,
105 char **title,
106 char **command,
107 char **parameter,
108 char **shortcut);
109 static void dir_closeMenuFile(WRootMenuData *data);
116 static WRootMenuReader PLMenuReader = {
117 pl_hasMoreData,
118 pl_nextCommand,
119 pl_closeMenuFile
122 static WRootMenuReader TextMenuReader = {
123 text_hasMoreData,
124 text_nextCommand,
125 text_closeMenuFile
128 static WRootMenuReader DirMenuReaderData = {
129 dir_hasMoreData,
130 dir_nextCommand,
131 dir_closeMenuFile
135 WRootMenuReader GNOMEMenuReaderData = {
142 #define LINESIZE 1024
144 static char linebuf[LINESIZE];
148 /* ---------- proplist ---------- */
151 static WRootMenuData*
152 pl_openMenuFile(WMPropList *pl)
154 PLRootMenuData *data = wmalloc(sizeof(PLRootMenuData));
156 data->reader = PLMenuReader;
158 data->pl = pl;
159 data->curIndex = 0;
161 data->submenu = NULL;
162 data->curSubIndex = NULL;
163 data->submenuDepth = 0;
165 return data;
169 static Bool
170 pl_hasMoreData(WRootMenuData *data)
175 static Bool
176 pl_nextCommand(WRootMenuData *data, char **title, char **command,
177 char **parameter, char **shortcut)
182 static void
183 pl_closeMenuFile(WRootMenuData *data)
185 if (data->submenu)
186 wfree(data->submenu);
187 if (data->curSubIndex)
188 wfree(data->curSubIndex);
190 WMReleasePropList(data->pl);
192 wfree(data);
196 /* ---------- text ---------- */
199 static WRootMenuData*
200 text_openMenuFile(char *path)
202 TextMenuReaderData *data;
204 data = wmalloc(sizeof(TextMenuReaderData));
205 data->reader = TextMenuReader;
207 data->file = fopen(path, "rb");
208 if (!data->file) {
210 return NULL;
215 static Bool
216 text_hasMoreData(WRootMenuData *data)
221 static Bool
222 text_nextCommand(WRootMenuData *data, char **title, char **command,
223 char **parameter, char **shortcut)
228 static void
229 text_closeMenuFile(WRootMenuData *data)
234 /* ---------- directory ---------- */
237 static WRootMenuData*
238 dir_openMenuFile(char *paths, time_t *timestamp)
240 DirMenuReaderData *data;
241 char **dirs;
242 int dirN;
243 time_t checksum = 0;
244 int i, c;
246 /* timestamp for directory is a "checksum" of the directory times */
248 wtokensplit(paths, &dirs, &dirN);
250 if (dirN == 0) {
251 return NULL;
254 for (c = 0, i = 0; i < dirN; i++) {
255 char *tmp;
257 if (strcmp(dirs[i], "-noext")==0) {
258 i++;
259 continue;
262 tmp = wexpandpath(dirs[i]);
263 wfree(dirs[i]);
264 dirs[i] = tmp;
266 if (stat(dirs[i], &stat_buf)<0) {
267 wsyserror(_("%s:could not stat menu"), dirs[i]);
268 wfree(dirs[i]);
269 dirs[i] = NULL;
270 } else {
271 c++;
272 checksum += stat_buf.st_mtime;
276 if (*timestamp == checksum && *timestamp != 0) {
277 return NULL;
280 if (c == 0) {
281 for (i = 0; i < dirN; i++) {
282 if (dirs[i])
283 wfree(dirs[i]);
285 wfree(dirs);
287 return NULL;
290 data = wmalloc(sizeof(DirMenuReaderData));
291 data->reader = DirMenuReader;
298 static Bool
299 dir_hasMoreData(WRootMenuData *data)
303 static Bool
304 dir_nextCommand(WRootMenuData *data, char **title, char **command,
305 char **parameter, char **shortcut)
309 static void
310 dir_closeMenuFile(WRootMenuData *data)
315 WRootMenuData*
316 OpenMenu(char *path, time_t *menuTime)
318 proplist pl;
319 struct stat stat_buf;
320 WRootMenuData *data;
322 /* check whether it's a piped menu */
323 if (*path == '|') {
324 /* piped menus have the following semantics for menuTime:
325 * if it's 0, then it wasnt loaded yet
326 * if it's 1, it was already loaded, so do not reload
327 * (would be too slow)
328 * now, menuTime will only be set to 1 if the pipe command is
329 * specified as ||command instead of |command
330 * in other words ||command means force the submenu to always refresh
332 if (*menuTime == 0) {
333 data = pipe_openMenu(path);
335 if (path[1] != '|') {
336 *menuTime = 1;
338 return data;
341 if (stat(path, &stat_buf) < 0) {
342 wsyserror(_("could not stat() menu file '%s'"));
343 return NULL;
346 /* check whether it's a directory */
347 if (S_ISDIR(stat_buf.st_mode)) {
348 return dir_openMenuFile(path, menuTime);
352 if (*menuTime >= stat_buf.st_mtime && *menuTime != 0) {
353 /* no changes in the menu file */
354 return NULL;
357 /* then check whether it's a proplist menu */
358 pl = WMReadPropListFromFile(path);
359 if (pl && WMIsPLArray(pl)) {
360 *menuTime = stat_buf.st_mtime;
361 return pl_openMenu(pl);
364 *menuTime = stat_buf.st_mtime;
365 /* assume its a plain text menu */
366 return text_openMenuFile(path);
370 WRootMenuData*
371 ReopenRootMenu(time_t *checkTime, char **menuPath, time_t *menuTimestamp)
373 proplist pl;
374 struct stat stat_buf;
375 char *path;
378 if (stat(path, &stat_buf) < 0) {
379 wsyserror(_("could not stat() menu file '%s'"));
380 return NULL;
383 if (*menuTime >= stat_buf.st_mtime && *checkTime != 0) {
384 /* no changes in WMRootMenu, see if the contents changed */
385 if (*menuPath != NULL) {
386 return OpenMenu(*menuPath, menuTimestamp);
387 } else {
388 return NULL;
392 *checkTime = stat_buf.st_mtime;
394 pl = WMReadPropListFromFile(path);
395 if (!pl) {
396 wwarning(_("could not load domain %s from user defaults database"),
397 "WMRootMenu");
398 return NULL;
401 if (WMIsPLString(pl)) {
402 char *tmp;
403 char *path;
404 Bool menu_is_default = False;
406 tmp = wexpandpath(WMGetFromPLString(pl));
408 path = getLocalizedMenuFile(tmp);
410 if (!path) {
411 path = wfindfile(DEF_CONFIG_PATHS, tmp);
414 if (!path) {
415 wwarning(_("could not find menu file '%s' referenced in WMRootMenu"),
416 tmp);
417 path = wfindfile(DEF_CONFIG_PATHS, DEF_MENU_FILE);
418 menu_is_default = True;
421 if (!path) {
422 wwarning(_("could not find any usable menu files. Please check '%s'"),
423 tmp);
424 wfree(tmp);
425 return NULL;
428 wfree(tmp);
430 if (*menuPath) {
431 if (strcmp(*menuPath, path) != 0) {
432 *menuTimestamp = 0;
433 wfree(*menuPath);
434 *menuPath = path;
436 if (menu_is_default) {
437 wwarning(_("using default menu file \"%s\" as the menu referenced in WMRootMenu could not be found "),
438 path);
440 } else {
441 /* the menu path didn't change, but the
442 * pointed file might have changed, so we don't return
445 } else {
446 *menuPath = path;
449 return OpenMenu(*menuPath, menuTimestamp);
450 } else if (WMIsPLArray(pl)) {
452 *menuTimestamp = stat_buf.st_mtime;
454 return pl_openMenu(pl);
455 } else {
456 wwarning(_("invalid content in menu file '%s'.\nIt should either be a property list menu or the path to the file, enclosed in \"."),
457 path);
458 return NULL;