wmail: use pkg-config for X11 and dockapp.
[dockapps.git] / wmmenu / menu.c
blob10da3d16ef9e48db8f3ff2aedf56137682b44535
1 #define _POSIX_SOURCE
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include <string.h>
6 #include <time.h>
7 #include <assert.h>
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include <unistd.h>
13 #include "menu.h"
14 #include "utils.h"
15 #include "types.h"
16 #include "error.h"
18 #define MAXENTRIES 50
20 #define BLANKS " \t\f\r\n"
21 #define SPACES " \t\f"
22 #define ENDLINE "\r\n"
24 static int NbEntries = 0 ;
25 static int Rows = 1 ;
26 static const char * Pixmaps [MAXENTRIES] ;
27 static const char * Commands [MAXENTRIES] ;
28 static char * MenuFileText = NULL ;
29 static char MenuPath [FILENAME_MAX] = "" ;
30 static time_t MenuAge = 0 ;
32 static void ParseMenu (void)
34 char * p ;
36 assert (MenuFileText != NULL) ;
37 p = MenuFileText ;
38 p += strspn (p, BLANKS) ;
39 NbEntries = 0 ;
40 Pixmaps[0] = NULL ;
41 Commands[0] = NULL ;
43 while (NbEntries < MAXENTRIES && *p != EOS) switch (*p++)
45 case '#' :
46 p += strcspn (p, ENDLINE) ;
47 p += strspn (p, BLANKS) ;
48 break ;
50 case '"' :
51 Pixmaps[NbEntries] = p ;
52 p += strcspn (p, "\"") ;
53 *p++ = EOS ;
54 p += strspn (p, SPACES) ;
55 break ;
57 default :
58 if (Pixmaps[NbEntries] == NULL)
59 warn ("entry #%d has no pixmap", NbEntries) ;
60 else Commands[NbEntries++] = p-1 ;
62 p += strcspn (p, ENDLINE) ;
63 *p++ = EOS ;
64 p += strspn (p, BLANKS) ;
66 Commands[NbEntries] = NULL ;
67 Pixmaps[NbEntries] = NULL ;
68 break ;
71 if (*p != EOS)
72 warn ("too many entries") ;
75 extern void Menu_LoadFromFile (const char * name)
77 char path [FILENAME_MAX] ;
78 const char * home ;
79 FILE * f ;
80 struct stat finfo ;
82 assert (name != NULL) ;
84 if (strchr (name, '/') == NULL && (home = getenv ("HOME")) != NULL &&
85 home[0] != EOS)
86 sprintf (path, "%s/.wmmenu/%s", home, name) ;
87 else sprintf (path, "%s", name) ;
89 if ((f = fopen (path, "r")) == NULL)
90 error ("can't open %s", path) ;
91 else
93 if (fstat (fileno (f), & finfo) == 0)
95 MenuAge = finfo.st_mtime ;
98 sprintf (MenuPath, "%.*s", (int)(sizeof MenuPath)-1, path) ;
100 if (MenuFileText != NULL) free (MenuFileText) ;
101 MenuFileText = File_ReadAll (f) ;
104 fclose (f) ;
106 ParseMenu () ;
109 extern int Menu_GetNbRows(void)
111 assert (Rows > 0) ;
112 return Rows ;
115 extern void Menu_SetNbRows (const char *s)
117 int h;
119 h = atoi(s) ;
120 if (h > 0) Rows = h ;
123 extern int Menu_GetNbColumns (void)
125 assert (NbEntries > 1 && Rows > 0) ;
127 Remove 1 entry used for header, then apply the formula:
128 UNITS = int (floor ((USED - 1) / PERUNIT)) + 1
129 (USED is NbEntries - 1)
131 return ((NbEntries - 2) / Rows) + 1 ;
134 extern int Menu_GetNbEntries (void)
136 assert (NbEntries > 1) ;
137 return NbEntries-1 ;
140 extern const char * Menu_GetEntryPixmap (int i)
142 assert (0 <= i && i < NbEntries-1) ;
143 return Pixmaps[i+1] ;
146 extern const char * Menu_GetEntryCommand (int i)
148 assert (0 <= i && i < NbEntries-1) ;
149 return Commands[i+1] ;
152 extern const char * Menu_GetPixmap (void)
154 assert (0 < NbEntries) ;
155 return Pixmaps[0] ;
158 extern const char * Menu_GetTitle (void)
160 assert (0 < NbEntries) ;
161 return Commands[0] ;
164 extern int Menu_HasChanged (void)
166 struct stat finfo ;
168 if (stat (MenuPath, & finfo) == 0 && finfo.st_mtime > MenuAge)
170 return 1 ; /* should reload */
172 else
174 return 0 ; /* don't try to reload */
178 extern void Menu_Reload (void)
180 FILE * f ;
181 struct stat finfo ;
183 if ((f = fopen (MenuPath, "r")) != NULL)
185 if (fstat (fileno (f), & finfo) == 0)
187 MenuAge = finfo.st_mtime ;
190 if (MenuFileText != NULL) free (MenuFileText) ;
191 MenuFileText = File_ReadAll (f) ;
192 fclose (f) ;
194 ParseMenu () ;