missing header
[wmaker-crm.git] / src / menureader.c
blobe4e7aa15a019d14a66ab9dfa8bb45b0587d6e57e
1 /* menureader.c- root menu definition readers
2 *
3 * Window Maker window manager
4 *
5 * Copyright (c) 2000 Alfredo K. Kojima
6 *
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 proplist_t pl;
41 int curIndex;
43 proplist_t *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(proplist_t 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 *pl_openMenuFile(proplist_t pl)
153 PLRootMenuData *data = wmalloc(sizeof(PLRootMenuData));
155 data->reader = PLMenuReader;
157 data->pl = pl;
158 data->curIndex = 0;
160 data->submenu = NULL;
161 data->curSubIndex = NULL;
162 data->submenuDepth = 0;
164 return data;
168 static Bool pl_hasMoreData(WRootMenuData *data)
173 static Bool pl_nextCommand(WRootMenuData *data,
174 char **title,
175 char **command,
176 char **parameter,
177 char **shortcut)
182 static void pl_closeMenuFile(WRootMenuData *data)
184 if (data->submenu)
185 wfree(data->submenu);
186 if (data->curSubIndex)
187 wfree(data->curSubIndex);
189 PLRelease(data->pl);
191 wfree(data);
195 /* ---------- text ---------- */
198 static WRootMenuData *text_openMenuFile(char *path)
200 TextMenuReaderData *data;
202 data = wmalloc(sizeof(TextMenuReaderData));
203 data->reader = TextMenuReader;
205 data->file = fopen(path, "r");
206 if (!data->file) {
208 return NULL;
213 static Bool text_hasMoreData(WRootMenuData *data)
218 static Bool text_nextCommand(WRootMenuData *data,
219 char **title,
220 char **command,
221 char **parameter,
222 char **shortcut)
227 static void text_closeMenuFile(WRootMenuData *data)
232 /* ---------- directory ---------- */
235 static WRootMenuData *dir_openMenuFile(char *paths, time_t *timestamp)
237 DirMenuReaderData *data;
238 char **dirs;
239 int dirN;
240 time_t checksum = 0;
241 int i, c;
243 /* timestamp for directory is a "checksum" of the directory times */
245 wtokensplit(paths, &dirs, &dirN);
247 if (dirN == 0) {
248 return NULL;
251 for (c = 0, i = 0; i < dirN; i++) {
252 char *tmp;
254 if (strcmp(dirs[i], "-noext")==0) {
255 i++;
256 continue;
259 tmp = wexpandpath(dirs[i]);
260 wfree(dirs[i]);
261 dirs[i] = tmp;
263 if (stat(dirs[i], &stat_buf)<0) {
264 wsyserror(_("%s:could not stat menu"), dirs[i]);
265 wfree(dirs[i]);
266 dirs[i] = NULL;
267 } else {
268 c++;
269 checksum += stat_buf.st_mtime;
273 if (*timestamp == checksum && *timestamp != 0) {
274 return NULL;
277 if (c == 0) {
278 for (i = 0; i < dirN; i++) {
279 if (dirs[i])
280 wfree(dirs[i]);
282 wfree(dirs);
284 return NULL;
287 data = wmalloc(sizeof(DirMenuReaderData));
288 data->reader = DirMenuReader;
295 static Bool dir_hasMoreData(WRootMenuData *data)
299 static Bool dir_nextCommand(WRootMenuData *data,
300 char **title,
301 char **command,
302 char **parameter,
303 char **shortcut)
307 static void dir_closeMenuFile(WRootMenuData *data)
315 WRootMenuData *OpenMenu(char *path, time_t *menuTime)
317 proplist pl;
318 struct stat stat_buf;
319 WRootMenuData *data;
321 /* check whether it's a piped menu */
322 if (*path == '|') {
323 /* piped menus have the following semantics for menuTime:
324 * if it's 0, then it wasnt loaded yet
325 * if it's 1, it was already loaded, so do not reload
326 * (would be too slow)
327 * now, menuTime will only be set to 1 if the pipe command is
328 * specified as ||command instead of |command
329 * in other words ||command means force the submenu to always refresh
331 if (*menuTime == 0) {
332 data = pipe_openMenu(path);
334 if (path[1] != '|') {
335 *menuTime = 1;
337 return data;
340 if (stat(path, &stat_buf) < 0) {
341 wsyserror(_("could not stat() menu file '%s'"));
342 return NULL;
345 /* check whether it's a directory */
346 if (S_ISDIR(stat_buf.st_mode)) {
347 return dir_openMenuFile(path, menuTime);
351 if (*menuTime >= stat_buf.st_mtime && *menuTime != 0) {
352 /* no changes in the menu file */
353 return NULL;
356 /* then check whether it's a proplist menu */
357 pl = ReadProplistFromFile(path);
358 if (pl && PLIsArray(pl)) {
359 *menuTime = stat_buf.st_mtime;
360 return pl_openMenu(pl);
363 *menuTime = stat_buf.st_mtime;
364 /* assume its a plain text menu */
365 return text_openMenuFile(path);
370 WRootMenuData *ReopenRootMenu(time_t *checkTime,
371 char **menuPath,
372 time_t *menuTimestamp)
374 proplist pl;
375 struct stat stat_buf;
376 char *path;
379 if (stat(path, &stat_buf) < 0) {
380 wsyserror(_("could not stat() menu file '%s'"));
381 return NULL;
384 if (*menuTime >= stat_buf.st_mtime && *checkTime != 0) {
385 /* no changes in WMRootMenu, see if the contents changed */
386 if (*menuPath != NULL) {
387 return OpenMenu(*menuPath, menuTimestamp);
388 } else {
389 return NULL;
393 *checkTime = stat_buf.st_mtime;
395 pl = ReadProplistFromFile(path);
396 if (!pl) {
397 wwarning(_("could not load domain %s from user defaults database"),
398 "WMRootMenu");
399 return NULL;
402 if (PLIsString(pl)) {
403 char *tmp;
404 char *path;
405 Bool menu_is_default = False;
407 tmp = wexpandpath(PLGetString(pl));
409 path = getLocalizedMenuFile(tmp);
411 if (!path) {
412 path = wfindfile(DEF_CONFIG_PATHS, tmp);
415 if (!path) {
416 wwarning(_("could not find menu file '%s' referenced in WMRootMenu"),
417 tmp);
418 path = wfindfile(DEF_CONFIG_PATHS, DEF_MENU_FILE);
419 menu_is_default = True;
422 if (!path) {
423 wwarning(_("could not find any usable menu files. Please check '%s'"),
424 tmp);
425 wfree(tmp);
426 return NULL;
429 wfree(tmp);
431 if (*menuPath) {
432 if (strcmp(*menuPath, path) != 0) {
433 *menuTimestamp = 0;
434 wfree(*menuPath);
435 *menuPath = path;
437 if (menu_is_default) {
438 wwarning(_("using default menu file \"%s\" as the menu referenced in WMRootMenu could not be found "),
439 path);
441 } else {
442 /* the menu path didn't change, but the
443 * pointed file might have changed, so we don't return
446 } else {
447 *menuPath = path;
450 return OpenMenu(*menuPath, menuTimestamp);
451 } else if (PLIsArray(pl)) {
453 *menuTimestamp = stat_buf.st_mtime;
455 return pl_openMenu(pl);
456 } else {
457 wwarning(_("invalid content in menu file '%s'.\nIt should either be a property list menu or the path to the file, enclosed in \"."),
458 path);
459 return NULL;