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,
26 #include <sys/types.h>
29 #include "WindowMaker.h"
35 typedef struct PLMenuReaderData
{
36 WRootMenuReader
*reader
;
47 typedef struct TextMenuReaderData
{
48 WRootMenuReader
*reader
;
54 typedef struct PipeMenuReaderData
{
55 WRootMenuReader
*reader
;
59 typedef struct DirMenuReaderData
{
60 WRootMenuReader
*reader
;
68 typedef struct GNOMEMenuReaderData {
69 } GNOMEMenuReaderData;
72 static WRootMenuData
*pl_openMenu(WMPropList
* pl
);
73 static Bool
pl_hasMoreData(WRootMenuData
* data
);
74 static Bool
pl_nextCommand(WRootMenuData
* data
, char **title
, char **command
, char **parameter
, char **shortcut
);
75 static void pl_closeMenuFile(WRootMenuData
* data
);
77 static WRootMenuData
*text_openMenuFile(char *path
);
78 static Bool
text_hasMoreData(WRootMenuData
* data
);
79 static Bool
text_nextCommand(WRootMenuData
* data
,
80 char **title
, char **command
, char **parameter
, char **shortcut
);
81 static void text_closeMenuFile(WRootMenuData
* data
);
83 static WRootMenuData
*dir_openMenuFile(char *path
);
84 static Bool
dir_hasMoreData(WRootMenuData
* data
);
85 static Bool
dir_nextCommand(WRootMenuData
* data
, char **title
, char **command
, char **parameter
, char **shortcut
);
86 static void dir_closeMenuFile(WRootMenuData
* data
);
88 static WRootMenuReader PLMenuReader
= {
94 static WRootMenuReader TextMenuReader
= {
100 static WRootMenuReader DirMenuReaderData
= {
107 WRootMenuReader GNOMEMenuReaderData = {
111 #define LINESIZE 1024
113 static char linebuf
[LINESIZE
];
115 /* ---------- proplist ---------- */
117 static WRootMenuData
*pl_openMenuFile(WMPropList
* pl
)
119 PLRootMenuData
*data
= wmalloc(sizeof(PLRootMenuData
));
121 data
->reader
= PLMenuReader
;
126 data
->submenu
= NULL
;
127 data
->curSubIndex
= NULL
;
128 data
->submenuDepth
= 0;
133 static Bool
pl_hasMoreData(WRootMenuData
* data
)
137 static Bool
pl_nextCommand(WRootMenuData
* data
, char **title
, char **command
, char **parameter
, char **shortcut
)
141 static void pl_closeMenuFile(WRootMenuData
* data
)
144 wfree(data
->submenu
);
145 if (data
->curSubIndex
)
146 wfree(data
->curSubIndex
);
148 WMReleasePropList(data
->pl
);
153 /* ---------- text ---------- */
155 static WRootMenuData
*text_openMenuFile(char *path
)
157 TextMenuReaderData
*data
;
159 data
= wmalloc(sizeof(TextMenuReaderData
));
160 data
->reader
= TextMenuReader
;
162 data
->file
= fopen(path
, "rb");
169 static Bool
text_hasMoreData(WRootMenuData
* data
)
173 static Bool
text_nextCommand(WRootMenuData
* data
, char **title
, char **command
, char **parameter
, char **shortcut
)
177 static void text_closeMenuFile(WRootMenuData
* data
)
181 /* ---------- directory ---------- */
183 static WRootMenuData
*dir_openMenuFile(char *paths
, time_t * timestamp
)
185 DirMenuReaderData
*data
;
191 /* timestamp for directory is a "checksum" of the directory times */
193 wtokensplit(paths
, &dirs
, &dirN
);
199 for (c
= 0, i
= 0; i
< dirN
; i
++) {
202 if (strcmp(dirs
[i
], "-noext") == 0) {
207 tmp
= wexpandpath(dirs
[i
]);
211 if (stat(dirs
[i
], &stat_buf
) < 0) {
212 wsyserror(_("%s:could not stat menu"), dirs
[i
]);
217 checksum
+= stat_buf
.st_mtime
;
221 if (*timestamp
== checksum
&& *timestamp
!= 0) {
226 for (i
= 0; i
< dirN
; i
++) {
235 data
= wmalloc(sizeof(DirMenuReaderData
));
236 data
->reader
= DirMenuReader
;
240 static Bool
dir_hasMoreData(WRootMenuData
* data
)
244 static Bool
dir_nextCommand(WRootMenuData
* data
, char **title
, char **command
, char **parameter
, char **shortcut
)
248 static void dir_closeMenuFile(WRootMenuData
* data
)
252 WRootMenuData
*OpenMenu(char *path
, time_t * menuTime
)
255 struct stat stat_buf
;
258 /* check whether it's a piped menu */
260 /* piped menus have the following semantics for menuTime:
261 * if it's 0, then it wasnt loaded yet
262 * if it's 1, it was already loaded, so do not reload
263 * (would be too slow)
264 * now, menuTime will only be set to 1 if the pipe command is
265 * specified as ||command instead of |command
266 * in other words ||command means force the submenu to always refresh
268 if (*menuTime
== 0) {
269 data
= pipe_openMenu(path
);
271 if (path
[1] != '|') {
277 if (stat(path
, &stat_buf
) < 0) {
278 wsyserror(_("could not stat() menu file '%s'"));
282 /* check whether it's a directory */
283 if (S_ISDIR(stat_buf
.st_mode
)) {
284 return dir_openMenuFile(path
, menuTime
);
287 if (*menuTime
>= stat_buf
.st_mtime
&& *menuTime
!= 0) {
288 /* no changes in the menu file */
292 /* then check whether it's a proplist menu */
293 pl
= WMReadPropListFromFile(path
);
294 if (pl
&& WMIsPLArray(pl
)) {
295 *menuTime
= stat_buf
.st_mtime
;
296 return pl_openMenu(pl
);
299 *menuTime
= stat_buf
.st_mtime
;
300 /* assume its a plain text menu */
301 return text_openMenuFile(path
);
304 WRootMenuData
*ReopenRootMenu(time_t * checkTime
, char **menuPath
, time_t * menuTimestamp
)
307 struct stat stat_buf
;
310 if (stat(path
, &stat_buf
) < 0) {
311 wsyserror(_("could not stat() menu file '%s'"));
315 if (*menuTime
>= stat_buf
.st_mtime
&& *checkTime
!= 0) {
316 /* no changes in WMRootMenu, see if the contents changed */
317 if (*menuPath
!= NULL
) {
318 return OpenMenu(*menuPath
, menuTimestamp
);
324 *checkTime
= stat_buf
.st_mtime
;
326 pl
= WMReadPropListFromFile(path
);
328 wwarning(_("could not load domain %s from user defaults database"), "WMRootMenu");
332 if (WMIsPLString(pl
)) {
335 Bool menu_is_default
= False
;
337 tmp
= wexpandpath(WMGetFromPLString(pl
));
339 path
= getLocalizedMenuFile(tmp
);
342 path
= wfindfile(DEF_CONFIG_PATHS
, tmp
);
346 wwarning(_("could not find menu file '%s' referenced in WMRootMenu"), tmp
);
347 path
= wfindfile(DEF_CONFIG_PATHS
, DEF_MENU_FILE
);
348 menu_is_default
= True
;
352 wwarning(_("could not find any usable menu files. Please check '%s'"), tmp
);
360 if (strcmp(*menuPath
, path
) != 0) {
365 if (menu_is_default
) {
367 ("using default menu file \"%s\" as the menu referenced in WMRootMenu could not be found "),
371 /* the menu path didn't change, but the
372 * pointed file might have changed, so we don't return
379 return OpenMenu(*menuPath
, menuTimestamp
);
380 } else if (WMIsPLArray(pl
)) {
382 *menuTimestamp
= stat_buf
.st_mtime
;
384 return pl_openMenu(pl
);
387 ("invalid content in menu file '%s'.\nIt should either be a property list menu or the path to the file, enclosed in \"."),