1 /* menureader.c- root menu definition readers
3 * Window Maker window manager
5 * Copyright (c) 2000 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,
27 #include <sys/types.h>
30 #include "WindowMaker.h"
37 typedef struct PLMenuReaderData
{
38 WRootMenuReader
*reader
;
50 typedef struct TextMenuReaderData
{
51 WRootMenuReader
*reader
;
58 typedef struct PipeMenuReaderData
{
59 WRootMenuReader
*reader
;
64 typedef struct DirMenuReaderData
{
65 WRootMenuReader
*reader
;
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
,
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
,
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
,
109 static void dir_closeMenuFile(WRootMenuData
*data
);
116 static WRootMenuReader PLMenuReader
= {
122 static WRootMenuReader TextMenuReader
= {
128 static WRootMenuReader DirMenuReaderData
= {
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
;
160 data
->submenu
= NULL
;
161 data
->curSubIndex
= NULL
;
162 data
->submenuDepth
= 0;
168 static Bool
pl_hasMoreData(WRootMenuData
*data
)
173 static Bool
pl_nextCommand(WRootMenuData
*data
,
182 static void pl_closeMenuFile(WRootMenuData
*data
)
185 wfree(data
->submenu
);
186 if (data
->curSubIndex
)
187 wfree(data
->curSubIndex
);
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");
213 static Bool
text_hasMoreData(WRootMenuData
*data
)
218 static Bool
text_nextCommand(WRootMenuData
*data
,
227 static void text_closeMenuFile(WRootMenuData
*data
)
232 /* ---------- directory ---------- */
235 static WRootMenuData
*dir_openMenuFile(char *paths
, time_t *timestamp
)
237 DirMenuReaderData
*data
;
243 /* timestamp for directory is a "checksum" of the directory times */
245 wtokensplit(paths
, &dirs
, &dirN
);
251 for (c
= 0, i
= 0; i
< dirN
; i
++) {
254 if (strcmp(dirs
[i
], "-noext")==0) {
259 tmp
= wexpandpath(dirs
[i
]);
263 if (stat(dirs
[i
], &stat_buf
)<0) {
264 wsyserror(_("%s:could not stat menu"), dirs
[i
]);
269 checksum
+= stat_buf
.st_mtime
;
273 if (*timestamp
== checksum
&& *timestamp
!= 0) {
278 for (i
= 0; i
< dirN
; i
++) {
287 data
= wmalloc(sizeof(DirMenuReaderData
));
288 data
->reader
= DirMenuReader
;
295 static Bool
dir_hasMoreData(WRootMenuData
*data
)
299 static Bool
dir_nextCommand(WRootMenuData
*data
,
307 static void dir_closeMenuFile(WRootMenuData
*data
)
315 WRootMenuData
*OpenMenu(char *path
, time_t *menuTime
)
318 struct stat stat_buf
;
321 /* check whether it's a piped menu */
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] != '|') {
340 if (stat(path
, &stat_buf
) < 0) {
341 wsyserror(_("could not stat() menu file '%s'"));
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 */
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
,
372 time_t *menuTimestamp
)
375 struct stat stat_buf
;
379 if (stat(path
, &stat_buf
) < 0) {
380 wsyserror(_("could not stat() menu file '%s'"));
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
);
393 *checkTime
= stat_buf
.st_mtime
;
395 pl
= ReadProplistFromFile(path
);
397 wwarning(_("could not load domain %s from user defaults database"),
402 if (PLIsString(pl
)) {
405 Bool menu_is_default
= False
;
407 tmp
= wexpandpath(PLGetString(pl
));
409 path
= getLocalizedMenuFile(tmp
);
412 path
= wfindfile(DEF_CONFIG_PATHS
, tmp
);
416 wwarning(_("could not find menu file '%s' referenced in WMRootMenu"),
418 path
= wfindfile(DEF_CONFIG_PATHS
, DEF_MENU_FILE
);
419 menu_is_default
= True
;
423 wwarning(_("could not find any usable menu files. Please check '%s'"),
432 if (strcmp(*menuPath
, path
) != 0) {
437 if (menu_is_default
) {
438 wwarning(_("using default menu file \"%s\" as the menu referenced in WMRootMenu could not be found "),
442 /* the menu path didn't change, but the
443 * pointed file might have changed, so we don't return
450 return OpenMenu(*menuPath
, menuTimestamp
);
451 } else if (PLIsArray(pl
)) {
453 *menuTimestamp
= stat_buf
.st_mtime
;
455 return pl_openMenu(pl
);
457 wwarning(_("invalid content in menu file '%s'.\nIt should either be a property list menu or the path to the file, enclosed in \"."),