wmclockmon: handle fgets NULL returns and zero-length lines
[dockapps.git] / wmmenu / options.c
blob0a059a28d04b9843664d104940ce67f0d13f8aad
1 /* ANSI */
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <assert.h>
6 /* POSIX */
7 #include <getopt.h>
9 #include "options.h"
10 #include "version.h"
11 #include "error.h"
12 #include "utils.h"
13 #include "types.h"
14 #include "menu.h"
16 #define MAXOPTIONS (20)
18 #ifndef ETCDIR
19 #define ETCDIR "/usr/local/etc"
20 #endif
21 #define DEFAULTPATH (ETCDIR ":.")
23 #define BLANKS " \t\f\r\n"
24 #define SPACES " \t\f"
25 #define ENDLINE "\r\n"
27 int TileXSize = 0 ;
28 int TileYSize = 0 ;
30 char MenuName [40] = "" ;
32 static char MyPixmapPath [1024] = "" ;
33 char * PixmapPath = MyPixmapPath ;
35 static char MyTilePath [FILENAME_MAX] = "" ;
36 char * TilePath = MyTilePath ;
38 static char MyHighlightPath [FILENAME_MAX] = "" ;
39 char * HighlightPath = MyHighlightPath ;
41 bool ClickOnly = false ;
42 bool AutoScale = true ;
43 bool HighlightBehind = false ;
44 int HideTimeout = 1 ;
46 int Options_Argc = 0 ;
47 char * Options_Argv [MAXOPTIONS] ;
49 static void Usage (void)
51 printf("Usage: wmmenu [<options>...][-- <dockoptions>...]\n");
52 printf("Normal options:\n");
53 printf("-m MENUNAME set the name of the menu file to load from ~/.wmmenu\n");
54 printf("-g WxH force width and height of tile\n");
55 printf("-l XPMFILE set the pixmap used to highlight icon under cursor\n");
56 printf("-t XPMFILE set the pixmap used as button bar background\n");
57 printf("-O click bar is only triggered by clicks on the tile, not moves\n");
58 printf("-O noautoscale disable automatic pixmap scaling to tile size\n");
59 printf("-O behind draw highlight pixmap behind icon, not above\n");
60 printf("-O hide=N set bar hiding timeout to N ms (default one)\n");
61 printf("-r ROWS set number of menu rows (default one)\n");
62 printf("-v print version information\n");
63 printf("-h print this help message\n");
64 printf("Note:\n");
65 printf(" -t, -l and '-O behind' can also be specified with the defaults file.\n");
68 static void SetGeometry (const char * val)
70 if (sscanf (val, "%dx%d", &TileXSize, &TileYSize) != 2)
71 error ("bad tile geometry \"%s\"", val) ;
72 else
73 if (64 < TileXSize || TileXSize < 0)
74 error ("incorrect tile width %d", TileXSize) ;
75 else
76 if (64 < TileYSize || TileYSize < 0)
77 error ("incorrect tile height %d", TileYSize) ;
80 static void SetTilePath (const char * value)
82 char *ptrToFree = NULL ;
84 if (value != NULL && value[0] == '!')
86 ptrToFree = File_ReadOutputFromCommand (value+1) ;
88 if ((value = ptrToFree) == NULL)
89 value = "" ;
92 sprintf (MyTilePath, "%.*s", (int)(sizeof MyTilePath)-1, value) ;
94 if (ptrToFree != NULL)
95 free (ptrToFree) ;
98 static void SetHighlightPath (const char * value)
100 sprintf (MyHighlightPath, "%.*s", (int)(sizeof MyHighlightPath)-1, value) ;
103 static void SetHideTimeout (const char * value)
105 HideTimeout = atoi (value) ;
106 if (HideTimeout <= 0)
108 warn ("hide_timeout must be a strictly positive integer") ;
109 HideTimeout = 1 ;
111 /* no maximum -- for players */
114 static void AddPixmapPath (const char * value)
116 int curLen ;
117 int szLeft ;
119 curLen = strlen (MyPixmapPath) ;
120 szLeft = (sizeof MyPixmapPath) - curLen ;
122 /* don't forget to count space for ':' and ending EOS */
123 sprintf (MyPixmapPath+curLen, ":%.*s", szLeft-2, value) ;
126 static void InitDefaults (void)
128 char dftPixmapPath [FILENAME_MAX] ;
129 const char * home ;
131 if ((home = getenv ("HOME")) != NULL && home[0] != EOS)
133 sprintf (dftPixmapPath, "%.*s/.wmmenu",
134 (int)(sizeof dftPixmapPath)-10, home) ;
136 else
138 strcpy (dftPixmapPath, ".") ;
141 strcpy (MyPixmapPath, dftPixmapPath) ;
144 static void ParseDefaults (char * text)
146 char * p ;
147 const char * name ;
148 const char * value ;
150 assert (text != NULL) ;
151 p = text ;
152 p += strspn (p, BLANKS) ;
154 while (*p != EOS) switch (*p++)
156 case '#' :
157 p += strcspn (p, ENDLINE) ;
158 p += strspn (p, BLANKS) ;
159 break ;
161 default :
162 name = p-1 ;
163 p += strcspn (p, SPACES) ;
164 *p++ = EOS ;
165 p += strspn (p, SPACES) ;
166 value = p ;
167 p += strcspn (p, ENDLINE) ;
168 *p++ = EOS ;
169 p += strspn (p, BLANKS) ;
171 if (streq (name, "geometry")) SetGeometry (value) ;
172 else
173 if (streq (name, "xpmpath"))
175 AddPixmapPath (value) ;
177 else
178 if (streq (name, "tile"))
180 SetTilePath (value) ;
182 else
183 if (streq (name, "highlight"))
185 SetHighlightPath (value) ;
187 else
188 if (streq (name, "highlight_behind"))
190 HighlightBehind = true ;
192 else
193 if (streq (name, "hide_timeout"))
195 SetHideTimeout (value) ;
197 else error ("unknown setting \"%s\"", name) ;
199 break ;
203 extern void Options_ParseDefaults (void)
205 char pathList [1000] ;
206 char path [FILENAME_MAX] ;
207 const char * home ;
208 FILE * f ;
210 if ((home = getenv ("HOME")) != NULL && *home != EOS)
212 sprintf (pathList, "%s/.wmmenu:%s", home, DEFAULTPATH) ;
214 else
216 strcpy (pathList, DEFAULTPATH) ;
219 if (File_FindInPath (path, sizeof path, pathList, "defaults") &&
220 (f = fopen (path, "r")) != NULL)
222 char * text ;
224 text = File_ReadAll (f) ;
225 fclose (f) ;
227 InitDefaults () ;
228 ParseDefaults (text) ;
229 free (text) ;
233 extern void Options_Parse (int argc, char ** argv)
235 int opt ;
237 assert (argv != NULL) ;
238 assert (argc > 0) ;
240 Options_Argc = 0 ;
241 Options_Argv[Options_Argc++] = MenuName ;
243 while ((opt = getopt (argc, argv, "hg:l:m:r:t:vO:")) != EOF) switch (opt)
245 case 'g' :
246 SetGeometry (optarg) ;
247 break ;
249 case 'm' :
250 sprintf (MenuName, "%.*s", (int)(sizeof MenuName)-1, optarg) ;
251 break ;
253 case 'r' :
254 Menu_SetNbRows (optarg) ;
255 break ;
257 case 't' :
258 SetTilePath (optarg) ;
259 break ;
261 case 'l' :
262 sprintf (MyHighlightPath, "%.*s",
263 (int)(sizeof MyHighlightPath)-1, optarg) ;
264 break ;
266 case 'O' :
267 if (streq (optarg, "click")) ClickOnly = true ;
268 else if (streq (optarg, "noautoscale")) AutoScale = false ;
269 else if (streq (optarg, "behind")) HighlightBehind = true ;
270 else if (streql (optarg, "hide=", 5)) SetHideTimeout (optarg+5) ;
271 else printf ("ignoring unknown feature \"%s\"\n", optarg) ;
272 break ;
274 case 'v' :
275 printf ("wmmenu (c) F.COUTANT v%s\n", VERSION) ;
276 exit (EXIT_SUCCESS) ;
277 break ;
279 case 'h' :
280 Usage () ;
281 exit (EXIT_SUCCESS) ;
282 break ;
284 case '?' :
285 Usage () ;
286 exit (EXIT_FAILURE) ;
287 break ;
290 if (MenuName[0] == EOS)
291 error ("no menu file name specified") ;
292 if (MyTilePath[0] == EOS)
293 warn ("no tile pixmap specified, using internal default") ;
295 while (optind < argc && Options_Argc < MAXOPTIONS)
296 Options_Argv[Options_Argc++] = argv[optind++] ;
299 extern void Options_SetMenuName (const char * name)
301 sprintf (MenuName, "%.*s", (int)(sizeof MenuName)-1, name) ;