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,
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(WMPropList
*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
*
152 pl_openMenuFile(WMPropList
*pl
)
154 PLRootMenuData
*data
= wmalloc(sizeof(PLRootMenuData
));
156 data
->reader
= PLMenuReader
;
161 data
->submenu
= NULL
;
162 data
->curSubIndex
= NULL
;
163 data
->submenuDepth
= 0;
170 pl_hasMoreData(WRootMenuData
*data
)
176 pl_nextCommand(WRootMenuData
*data
, char **title
, char **command
,
177 char **parameter
, char **shortcut
)
183 pl_closeMenuFile(WRootMenuData
*data
)
186 wfree(data
->submenu
);
187 if (data
->curSubIndex
)
188 wfree(data
->curSubIndex
);
190 WMReleasePropList(data
->pl
);
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");
216 text_hasMoreData(WRootMenuData
*data
)
222 text_nextCommand(WRootMenuData
*data
, char **title
, char **command
,
223 char **parameter
, char **shortcut
)
229 text_closeMenuFile(WRootMenuData
*data
)
234 /* ---------- directory ---------- */
237 static WRootMenuData
*
238 dir_openMenuFile(char *paths
, time_t *timestamp
)
240 DirMenuReaderData
*data
;
246 /* timestamp for directory is a "checksum" of the directory times */
248 wtokensplit(paths
, &dirs
, &dirN
);
254 for (c
= 0, i
= 0; i
< dirN
; i
++) {
257 if (strcmp(dirs
[i
], "-noext")==0) {
262 tmp
= wexpandpath(dirs
[i
]);
266 if (stat(dirs
[i
], &stat_buf
)<0) {
267 wsyserror(_("%s:could not stat menu"), dirs
[i
]);
272 checksum
+= stat_buf
.st_mtime
;
276 if (*timestamp
== checksum
&& *timestamp
!= 0) {
281 for (i
= 0; i
< dirN
; i
++) {
290 data
= wmalloc(sizeof(DirMenuReaderData
));
291 data
->reader
= DirMenuReader
;
299 dir_hasMoreData(WRootMenuData
*data
)
304 dir_nextCommand(WRootMenuData
*data
, char **title
, char **command
,
305 char **parameter
, char **shortcut
)
310 dir_closeMenuFile(WRootMenuData
*data
)
316 OpenMenu(char *path
, time_t *menuTime
)
319 struct stat stat_buf
;
322 /* check whether it's a piped menu */
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] != '|') {
341 if (stat(path
, &stat_buf
) < 0) {
342 wsyserror(_("could not stat() menu file '%s'"));
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 */
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
);
371 ReopenRootMenu(time_t *checkTime
, char **menuPath
, time_t *menuTimestamp
)
374 struct stat stat_buf
;
378 if (stat(path
, &stat_buf
) < 0) {
379 wsyserror(_("could not stat() menu file '%s'"));
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
);
392 *checkTime
= stat_buf
.st_mtime
;
394 pl
= WMReadPropListFromFile(path
);
396 wwarning(_("could not load domain %s from user defaults database"),
401 if (WMIsPLString(pl
)) {
404 Bool menu_is_default
= False
;
406 tmp
= wexpandpath(WMGetFromPLString(pl
));
408 path
= getLocalizedMenuFile(tmp
);
411 path
= wfindfile(DEF_CONFIG_PATHS
, tmp
);
415 wwarning(_("could not find menu file '%s' referenced in WMRootMenu"),
417 path
= wfindfile(DEF_CONFIG_PATHS
, DEF_MENU_FILE
);
418 menu_is_default
= True
;
422 wwarning(_("could not find any usable menu files. Please check '%s'"),
431 if (strcmp(*menuPath
, path
) != 0) {
436 if (menu_is_default
) {
437 wwarning(_("using default menu file \"%s\" as the menu referenced in WMRootMenu could not be found "),
441 /* the menu path didn't change, but the
442 * pointed file might have changed, so we don't return
449 return OpenMenu(*menuPath
, menuTimestamp
);
450 } else if (WMIsPLArray(pl
)) {
452 *menuTimestamp
= stat_buf
.st_mtime
;
454 return pl_openMenu(pl
);
456 wwarning(_("invalid content in menu file '%s'.\nIt should either be a property list menu or the path to the file, enclosed in \"."),