1 /* wmDrawer (c) 2002-2004 Valery Febvre <vfebvre@easter-eggs.com>
2  *
3  * wmDrawer is a dock application (dockapp) which provides a
4  * drawer (button bar) to launch applications from.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  */
20 
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 
24 #if defined USE_GETOPT
25 #include <unistd.h>
26 #else
27 #include <getopt.h>
28 #endif
29 
30 #include "types_defs.h"
31 #include "config.h"
32 
33 static void parseLine (char *line, int line_num);
34 static void usage (void);
35 static void freeUnusedMemory (void);
36 
37 enum section {
38   general,
39   images_paths,
40   column
41 };
42 
43 drawerConfig config;
44 drawerButton **entries;
45 static char configFilePath[FILENAME_MAX];
46 struct stat buf;
47 static unsigned int currentSection;
48 static unsigned int rowsCnt;
49 static unsigned int *nbRowsPerCol;
50 static char *line;
51 unsigned int nbEntries, nbImagesPaths;
52 unsigned int nbCols, nbRows;
53 unsigned int useDefaultIconsBg, useDefaultDockIcon, useDefaultHighlightImg;
54 unsigned int drawerOK;
55 
parseConfig()56 void parseConfig () {
57   FILE *f = NULL;
58   const char *home;
59   unsigned char c;
60   unsigned int col, row;
61   unsigned int line_num = 0;
62   unsigned int line_point = 0;
63   /* init vars */
64   currentSection = -1;
65   nbEntries = nbCols = rowsCnt = nbRows = nbImagesPaths = 0;
66   useDefaultIconsBg = useDefaultDockIcon = useDefaultHighlightImg = drawerOK = 1;
67   entries = NULL;
68   freeAllMemory ();
69 
70   /* default adjustments */
71   config.iconsExpand    = 1;
72   config.transparency   = 0;
73   config.dockW          = 64;
74   config.dockH          = 64;
75   config.btnsSize       = 0;
76   config.direction      = -1;
77   config.animationSpeed = 1;
78   config.cursor         = 30; /* XC_hand2 / 2 */
79   config.borderSize     = 1;
80   config.showOnHover    = 0;
81   config.hideOnOut      = 0;
82   config.hideTimeout    = 800;
83   config.highlight      = 2;
84   config.highlightShading.shading = 60;
85   config.highlightShading.tintColor.red   = 255;
86   config.highlightShading.tintColor.green = 255;
87   config.highlightShading.tintColor.blue  = 255;
88   config.tooltips = 1;
89   config.tooltipsFont = (char *) malloc (6 * sizeof (char));
90   sprintf (config.tooltipsFont, "fixed");
91 
92   if (*configFilePath == '\0') {
93     if ((home = getenv ("HOME")) != NULL && *home != '\0')
94       sprintf (configFilePath, "%s/%s", home, ".wmdrawerrc");
95     else {
96       printf ("%s error: can't find HOME directory\n", PACKAGE);
97       exit (EXIT_FAILURE);
98     }
99   }
100   if ((f = fopen (configFilePath, "r")) == NULL) {
101     printf ("%s error: can't open config file %s\n", PACKAGE, configFilePath);
102     exit (EXIT_FAILURE);
103   }
104 
105   if (stat (configFilePath, &buf) == 0) {
106     config.lastModif = buf.st_mtime;
107   }
108 
109   line = xcalloc (FILENAME_MAX, sizeof (char));
110   /* fgets ??? */
111   while (fscanf (f, "%c", &c) != EOF) {
112     if (c != '\n') {
113       line[line_point++] = c;
114     }
115     else {
116       line_num++;
117       parseLine (line, line_num);
118       free (line);
119       line_point = 0;
120       line = xcalloc (FILENAME_MAX, sizeof (char));
121     }
122   }
123   fclose (f);
124   if (config.direction < 0) {
125     freeUnusedMemory ();
126     exit (EXIT_FAILURE);
127   }
128   if (nbRows * nbCols > 0) {
129     /* create and alloc an (nbCols x nbRows) array */
130     config.entries = (drawerButton **) xcalloc (nbCols,
131 						sizeof (drawerButton *));
132     for (col = 0; col < nbCols; col++)
133       config.entries[col] = (drawerButton *) xcalloc (nbRows,
134 						      sizeof (drawerButton));
135     /* Add empty buttons to array entries */
136     for (col = 0; col < nbCols; col++) {
137       if (nbRowsPerCol[col] < nbRows) {
138 	entries[col] = xrealloc (entries[col], sizeof (drawerButton) * nbRows);
139 	for (row = nbRowsPerCol[col]; row < nbRows; row++) {
140 	  /* alloc empty string for tooltip, image, command */
141 	  entries[col][row].tooltip = (char *) malloc (sizeof (char));
142 	  entries[col][row].image   = (char *) malloc (sizeof (char));
143 	  entries[col][row].command = (char *) malloc (sizeof (char));
144 	  entries[col][row].isEmpty = 1;
145 	}
146       }
147     }
148     /* rotate array */
149     for (col = 0; col < nbCols; col++) {
150       for (row = 0; row < nbRows; row++) {
151 	switch (config.direction) {
152 	case leftToRight:
153 	case topToBottom:
154 	  config.entries[col][row].isEmpty = entries[col][row].isEmpty;
155 	  config.entries[col][row].tooltip = (char *) malloc ((strlen (entries[col][row].tooltip)+1) * sizeof (char));
156 	  sprintf (config.entries[col][row].tooltip, "%s", entries[col][row].tooltip);
157 	  config.entries[col][row].image = (char *) malloc((strlen (entries[col][row].image)+1) * sizeof (char));
158 	  sprintf (config.entries[col][row].image, "%s", entries[col][row].image);
159 	  config.entries[col][row].command = (char *) malloc((strlen (entries[col][row].command)+1) * sizeof(char));
160 	  sprintf (config.entries[col][row].command, "%s", entries[col][row].command);
161 	  break;
162 	case rightToLeft:
163 	case bottomToTop:
164 	  config.entries[col][row].isEmpty = entries[col][nbRows - row - 1].isEmpty;
165 	  config.entries[col][row].tooltip = (char *) malloc ((strlen (entries[col][nbRows-row-1].tooltip)+1) * sizeof (char));
166 	  sprintf (config.entries[col][row].tooltip, "%s", entries[col][nbRows-row-1].tooltip);
167 	  config.entries[col][row].image = (char *) malloc((strlen (entries[col][nbRows-row-1].image)+1) * sizeof (char));
168 	  sprintf (config.entries[col][row].image, "%s", entries[col][nbRows-row-1].image);
169 	  config.entries[col][row].command = (char *) malloc((strlen (entries[col][nbRows-row-1].command)+1) * sizeof (char));
170 	  sprintf (config.entries[col][row].command, "%s", entries[col][nbRows - row - 1].command);
171 	  break;
172 	}
173 	dbg_msg (1, "(%d,%d) %s %s %s %d\n", col, row,
174 		 config.entries[col][row].tooltip,
175 		 config.entries[col][row].image,
176 		 config.entries[col][row].command,
177 		 config.entries[col][row].isEmpty);
178       }
179     }
180   }
181   else {
182     printf ("%s warning: any button defined !!!\n", PACKAGE);
183     drawerOK = nbCols = 0;
184   }
185   freeUnusedMemory ();
186 }
187 
parseLine(char * line,int line_num)188 static void parseLine (char *line, int line_num) {
189   unsigned int i, empty, error = 0, flag = 0, cntc = 0, cnte = 0;
190   char c;
191   const char *regex_general = "^[[:space:]]*[a-z_]+[[:space:]]+.+$";
192   const char *regex_column  = "^[[:space:]]*\\(.*\\)[[:space:]]*\\(.*\\)[[:space:]]*\\(.*\\)[[:space:]]*$";
193   char *param, *field;
194   int field_point = 0;
195 
196   /* detect comment lines and empty lines */
197   empty = 1;
198   for(i=0; i<strlen (line); i++) {
199     if (line[i] != ' ' && line[i] != '\t') {
200       empty = 0;
201       break;
202     }
203   }
204   if (line[i] == '#' || line[i] == '!' || line[i] == ';' || line[i] == '\0') {
205     return;
206   }
207   if (empty == 1) return;
208   /* detect comment lines and sections*/
209   if (strstr (line, "[general]") != NULL) {
210     currentSection = general;
211     return;
212   }
213   if (strstr (line, "[images_paths]") != NULL) {
214     currentSection = images_paths;
215     return;
216   }
217   if (strstr (line, "[column]") != NULL) {
218     currentSection = column;
219     nbCols++;
220     if (entries == NULL && nbCols == 1) {
221       /* alloc memory for first column */
222       entries = (drawerButton **) xcalloc (1, sizeof (drawerButton *));
223       nbRowsPerCol = (unsigned int *) xcalloc (1, sizeof (unsigned int));
224     }
225     else {
226       /* realloc memory for a new column */
227       entries = xrealloc (entries, sizeof (drawerButton *) * nbCols);
228       nbRowsPerCol = xrealloc (nbRowsPerCol, sizeof (unsigned int) * nbCols);
229     }
230     nbRowsPerCol[nbCols - 1] = 0;
231     rowsCnt = 0;
232     return;
233   }
234 
235   param = (char *) malloc (strlen (line) * sizeof (char));
236   field = (char *) malloc (strlen (line) * sizeof (char));
237   switch (currentSection) {
238   case general:
239     /* first verify if line match regexp else it's skipped */
240     if (match_regex (line, regex_general) == 0) {
241       printf ("%s warning: line %d is invalid (skipped)\n", PACKAGE, line_num);
242       printf ("Line %d: %s\n", line_num, line);
243       break;
244     }
245     if (strstr (line, "dock_icon")) {
246       sscanf (line, "%s %s", param, field);
247       config.dockIcon = (char *) malloc ((strlen (field)+1) * sizeof (char));
248       sprintf(config.dockIcon, "%s", field);
249       useDefaultDockIcon = 0;
250       break;
251     }
252     else if (strstr (line, "icons_bg")) {
253       sscanf (line, "%s %s", param, field);
254       config.iconsBg = (char *) malloc ((strlen (field)+1) * sizeof (char));
255       sprintf(config.iconsBg, "%s", field);
256       useDefaultIconsBg = 0;
257       break;
258     }
259     else if (strstr (line, "icons_expand")) {
260       sscanf (line, "%s %d", param, &(config.iconsExpand));
261       if (config.iconsExpand != 0 && config.iconsExpand != 1) {
262 	printf ("%s error: bad value for 'icons_expand' param, it must be 0 or 1 (use default value: 1)\n", PACKAGE);
263 	config.iconsExpand = 1;
264       }
265       break;
266     }
267     else if (strstr (line, "transparency")) {
268       sscanf (line, "%s %d", param, &(config.transparency));
269       if (config.transparency != 0 && config.transparency != 1) {
270 	printf ("%s warning: bad value for 'transparency' param, it must be 0 or 1 (use default value: 0)\n", PACKAGE);
271 	config.transparency = 0;
272       }
273       break;
274     }
275     else if (strstr (line, "dock_size")) {
276       printf ("%s warning: old option 'dock_size' found, use dock_width and dock_height instead\n", PACKAGE);
277       break;
278     }
279     else if (strstr (line, "dock_width")) {
280       sscanf (line, "%s %d", param, &(config.dockW));
281       if (config.dockW > MAX_ICON_SIZE) {
282 	printf ("%s warning: bad value for 'dock_width' param, max=%d (use max value: %d)\n",
283 		PACKAGE, MAX_ICON_SIZE, MAX_ICON_SIZE);
284 	config.dockW = MAX_ICON_SIZE;
285       }
286       if (config.dockW < MIN_ICON_SIZE) {
287         printf ("%s warning: bad value for 'dock_width' param, min=%d (use min value: %d)\n",
288 		PACKAGE, MIN_ICON_SIZE, MIN_ICON_SIZE);
289         config.dockW = MIN_ICON_SIZE;
290       }
291       break;
292     }
293     else if (strstr (line, "dock_height")) {
294       sscanf (line, "%s %d", param, &(config.dockH));
295       if (config.dockH > MAX_ICON_SIZE) {
296         printf ("%s warning: bad value for 'dock_height' param, max=%d (use max value: %d)\n",
297                 PACKAGE, MAX_ICON_SIZE, MAX_ICON_SIZE);
298         config.dockH = MAX_ICON_SIZE;
299       }
300       if (config.dockH < MIN_ICON_SIZE) {
301         printf ("%s warning: bad value for 'dock_height' param, min=%d (use min value: %d)\n",
302                 PACKAGE, MIN_ICON_SIZE, MIN_ICON_SIZE);
303         config.dockH = MIN_ICON_SIZE;
304       }
305       break;
306     }
307     else if (strstr (line, "btns_size")) {
308       sscanf (line, "%s %d", param, &(config.btnsSize));
309       if (config.btnsSize > MAX_ICON_SIZE) {
310 	printf ("%s warning: bad value for 'btns_size' param, max=%d (use max value: %d)\n",
311 		PACKAGE, MAX_ICON_SIZE, MAX_ICON_SIZE);
312 	config.btnsSize = MAX_ICON_SIZE;
313       }
314       if (config.btnsSize < MIN_ICON_SIZE) {
315 	printf ("%s warning: bad value for 'btns_size' param, min=%d (use min value: %d)\n",
316 		PACKAGE, MIN_ICON_SIZE, MIN_ICON_SIZE);
317 	config.btnsSize = MIN_ICON_SIZE;
318       }
319       break;
320     }
321     else if (strstr (line, "direction")) {
322       sscanf (line, "%s %d", param, &(config.direction));
323       if (config.direction < 0 || config.direction > 3) {
324 	printf ("%s error: bad value for 'direction' param, it must be 0, 1, 2 or 3\n", PACKAGE);
325 	config.direction = -1;
326       }
327       break;
328     }
329     else if (strstr (line, "animation_speed")) {
330       sscanf (line, "%s %d", param, &(config.animationSpeed));
331       if (config.animationSpeed < 0) {
332 	printf ("%s warning: bad value for 'animation_speed' param, it must be 0, 1, 2, 3 or 4 (use default value: 1)\n", PACKAGE);
333 	config.animationSpeed = 1;
334       }
335       if (config.animationSpeed > 4) {
336 	printf ("%s warning: bad value for 'animation_speed' param, it must be 0, 1, 2, 3 or 4 (use max value: 4)\n", PACKAGE);
337 	config.animationSpeed = 4;
338       }
339       break;
340     }
341     else if (strstr (line, "cursor")) {
342       sscanf (line, "%s %d", param, &(config.cursor));
343       if (config.cursor < 0 || config.cursor > 76) {
344 	printf ("%s warning: bad value for 'cursor' param, it must be >= 0 and <= 76 (use default value: 30)\n", PACKAGE);
345 	config.cursor = 30; /* XC_hand2 / 2 */
346       }
347       break;
348     }
349     else if (strstr (line, "border_size")) {
350       sscanf (line, "%s %d", param, &(config.borderSize));
351       if (config.borderSize < 0 || config.borderSize > 8) {
352 	printf ("%s warning: bad value for 'border_size' param, it must be >= 0 and not too big (use default value: 1)\n", PACKAGE);
353 	config.borderSize = 1;
354       }
355       break;
356     }
357     else if (strstr (line, "show_on_hover") || strstr (line, "show_on_over")) {
358       sscanf (line, "%s %d", param, &(config.showOnHover));
359       if (config.showOnHover != 0 && config.showOnHover != 1) {
360 	printf ("%s warning: bad value for 'show_on_hover' param, it must be 0 or 1 (use default value: 0)\n", PACKAGE);
361 	config.showOnHover = 0;
362       }
363       break;
364     }
365     else if (strstr (line, "hide_on_out")) {
366       sscanf (line, "%s %d", param, &(config.hideOnOut));
367       if (config.hideOnOut != 0 && config.hideOnOut != 1) {
368 	printf ("%s warning: bad value for 'hide_on_out' param, it must be 0 or 1 (use default value: 0)\n", PACKAGE);
369 	config.hideOnOut = 0;
370       }
371       break;
372     }
373     else if (strstr (line, "hide_timeout")) {
374       sscanf (line, "%s %d", param, &(config.hideTimeout));
375       if (config.hideTimeout < 0) {
376 	printf ("%s warning: bad value for 'hide_timeout' param, it must be >= to 0 (use default value: 1000)\n", PACKAGE);
377 	config.hideTimeout = 1000;
378       }
379       break;
380     }
381     else if (strstr (line, "windowed_mode")) {
382       if (config.windowedModeLocked == 0) {
383 	sscanf (line, "%s %d", param, &(config.windowedMode));
384 	if (config.windowedMode != 0 && config.windowedMode != 1) {
385 	  printf ("%s warning: bad value for 'windowed_mode' param, it must be 0 or 1 (use default value: 0)\n", PACKAGE);
386 	  config.windowedMode = 0;
387 	}
388       }
389       break;
390     }
391     else if (strstr (line, "instance_name")) {
392       /* Ed Goforth <e.goforth@computer.org> */
393       /* Allow to specify instance name for multiple clients in their */
394       /* config file. This will override a -n given on the command line. */
395       sscanf (line, "%s %s", param, field);
396       config.instanceName = (char *) malloc ((strlen (field)+1)*sizeof (char));
397       sprintf(config.instanceName, "%s", field);
398       break;
399     }
400     else if (strstr (line, "highlight_img")) {
401       sscanf (line, "%s %s", param, field);
402       config.highlightImg = (char *) malloc ((strlen (field)+1)*sizeof (char));
403       sprintf(config.highlightImg, "%s", field);
404       useDefaultHighlightImg = 0;
405       break;
406     }
407     else if (strstr (line, "highlight_sh")) {
408       sscanf (line, "%s %d", param, &(config.highlightShading.shading));
409       if (config.highlightShading.shading < 0 ||
410 	  config.highlightShading.shading > 100) {
411 	printf ("%s warning: bad value for 'highlight_sh' param, it must be >= 0 and <= 100 (use default value: 60)\n", PACKAGE);
412 	config.highlightShading.shading = 60;
413       }
414       break;
415     }
416     else if (strstr (line, "highlight_tint")) {
417       unsigned int r,g,b;
418       sscanf (line, "%s %c%02X%02X%02X", param, &c, &r, &g, &b);
419       if (c != '#') {
420 	printf ("%s warning: bad value for 'highlight_tint' param (use default value: #ffffff)\n", PACKAGE);
421 	config.highlightShading.tintColor.red   = 255;
422 	config.highlightShading.tintColor.green = 255;
423 	config.highlightShading.tintColor.blue  = 255;
424       }
425       else {
426 	config.highlightShading.tintColor.red   = (unsigned short) r;
427 	config.highlightShading.tintColor.green = (unsigned short) g;
428 	config.highlightShading.tintColor.blue  = (unsigned short) b;
429       }
430       break;
431     }
432     else if (strstr (line, "highlight")) {
433       sscanf (line, "%s %d", param, &(config.highlight));
434       if (config.highlight < 0 || config.highlight > 2) {
435 	printf ("%s warning: bad value for 'highlight' param, it must be 0, 1 or 2 (use default value: 2)\n", PACKAGE);
436 	config.highlight = 2;
437       }
438       break;
439     }
440     else if (strstr (line, "tooltips_font")) {
441       free (config.tooltipsFont);
442       sscanf (line, "%s %s", param, field);
443       config.tooltipsFont = (char *) malloc ((strlen (field)+1)*sizeof (char));
444       sprintf(config.tooltipsFont, "%s", field);
445       break;
446     }
447     else if (strstr (line, "tooltips")) {
448       sscanf (line, "%s %d", param, &(config.tooltips));
449       if (config.tooltips != 0 && config.tooltips != 1) {
450 	printf ("%s warning: bad value for 'tooltips' param, it must be 0 or 1 (use default value: 1)\n", PACKAGE);
451 	config.tooltips = 1;
452       }
453       break;
454     }
455     break;
456   case images_paths:
457     nbImagesPaths++;
458     if (config.imagesPaths == NULL && nbImagesPaths == 1) {
459       config.imagesPaths = (char **) xcalloc (1, sizeof (char *));
460     }
461     else {
462       config.imagesPaths = (char **) xrealloc (config.imagesPaths, sizeof (char *) * nbImagesPaths);
463     }
464     config.imagesPaths[nbImagesPaths - 1] = (char *) xcalloc (strlen(line)+1,
465 							      sizeof (char));
466     sscanf (line, "%s", config.imagesPaths[nbImagesPaths - 1]);
467     break;
468   case column:
469     /* if a line don't match regexp => it's skipped */
470     if (match_regex (line, regex_column) == 0) {
471       printf ("%s warning: line %d is invalid (skipped)\n", PACKAGE, line_num);
472       printf ("Line %d: %s\n", line_num, line);
473       break;
474     }
475     rowsCnt++;
476     if (rowsCnt == 1) {
477       /* alloc memory for first button */
478       entries[nbCols-1] = (drawerButton *) xcalloc (1, sizeof (drawerButton));
479     }
480     else {
481       /* realloc memory for new button */
482       entries[nbCols-1] = (drawerButton *) xrealloc (entries[nbCols - 1],
483 						     sizeof (drawerButton) * rowsCnt);
484     }
485     /* parse entry line */
486     while (sscanf (line + cntc, "%c", &c)) {
487       switch (c) {
488       case '(':
489 	flag = 1;
490 	break;
491       case ')':
492 	flag = 0;
493 	field[field_point] = '\0';
494         switch (cnte++) {
495 	case 0:
496 	  entries[nbCols - 1][rowsCnt - 1].tooltip = (char *) xcalloc (strlen (field)+1, sizeof (char));
497 	  sprintf (entries[nbCols - 1][rowsCnt - 1].tooltip, "%s", field);
498 	  break;
499 	case 1:
500 	  entries[nbCols - 1][rowsCnt - 1].image = (char *) xcalloc (strlen (field)+1, sizeof (char));
501 	  sprintf (entries[nbCols - 1][rowsCnt - 1].image, "%s", field);
502 	  break;
503 	case 2:
504 	  entries[nbCols - 1][rowsCnt - 1].command = (char *) xcalloc (strlen (field)+1, sizeof (char));
505 	  sprintf (entries[nbCols - 1][rowsCnt - 1].command, "%s", field);
506 	  break;
507         }
508 	field_point = 0;
509 	break;
510       default:
511 	if (flag == 1) {
512 	  field[field_point++] = c;
513 	  field[field_point] = '\0';
514 	}
515 	break;
516       }
517       cntc++;
518       dbg_msg (1, "%c %d %d %d %s\n", c, flag, cnte, cntc, field);
519       if (cnte == 3) {
520             dbg_msg (1, "%d %d %d | %s | %s | %s\n", flag, cnte, cntc,
521 		     entries[nbCols - 1][rowsCnt - 1].tooltip,
522 		     entries[nbCols - 1][rowsCnt - 1].image,
523 		     entries[nbCols - 1][rowsCnt - 1].command);
524       }
525       if (cntc >= strlen (line)) break;
526     }
527     dbg_msg (1, "%s\t%s\t%s\n", entries[nbCols - 1][rowsCnt - 1].tooltip,
528 	     entries[nbCols - 1][rowsCnt - 1].image,
529 	     entries[nbCols - 1][rowsCnt - 1].command);
530     entries[nbCols - 1][rowsCnt - 1].isEmpty = 0;
531     /* we count the number of buttons per column */
532     nbRowsPerCol[nbCols - 1]++;
533     if (rowsCnt > nbRows) {
534       nbRows = rowsCnt;
535     }
536     break;
537   default:
538     error++;
539   }
540   free (field);
541   free (param);
542   if (error > 0) {
543     dbg_msg (1, "%s\n", line);
544     printf ("%s error: parsing error.\n", PACKAGE);
545     printf ("Line %d: %s\n", line_num, line);
546     freeAllMemory ();
547     exit (EXIT_FAILURE);
548   }
549 }
550 
configChanged(void)551 int configChanged (void) {
552   struct stat buf;
553 
554   if (stat (configFilePath, &buf) == 0 && buf.st_mtime > config.lastModif) {
555     return 1;
556   }
557   else {
558     return 0;
559   }
560 }
561 
usage(void)562 static void usage (void) {
563 #if defined USE_GETOPT
564   printf ("Usage: %s [OPTIONS]\n\n"
565 	  "Valid options are:\n"
566 	  "  -c FILE   config file to use (default ~/.wmdrawerrc)\n"
567 	  "  -n NAME   set dock instance name\n"
568 	  "  -w        runs the application in windowed mode\n"
569 	  "  -v        show program version and exit\n"
570 	  "  -h        show this help text and exit\n\n", PACKAGE);
571 #else
572   printf ("Usage: %s [OPTIONS]\n\n"
573 	  "Valid options are:\n"
574 	  "  -c, --configfile=FILE     config file to use (default ~/.wmdrawerrc)\n"
575 	  "  -n, --instancename=NAME   set dock instance name\n"
576 	  "  -w, --windowed            runs the application in windowed mode\n"
577 	  "  -v, --version             show program version and exit\n"
578 	  "  -h, --help                show this help text and exit\n\n", PACKAGE);
579 #endif
580 }
581 
parseOptions(int argc,char ** argv)582 void parseOptions (int argc, char **argv) {
583   int opt;
584 
585 #if defined USE_GETOPT
586 #else
587   int longopt_index = 0;
588   static struct option long_options[] = {
589     {"configfile",   1, NULL, 'c'},
590     {"help",         0, NULL, 'h'},
591     {"instancename", 1, NULL, 'n'},
592     {"version",      0, NULL, 'v'},
593     {"windowed",     0, NULL, 'w'},
594     {NULL, 0, NULL, 0} /* marks end-of-list */
595   };
596 #endif
597 
598   config.windowedMode = 0;
599   /* Ed Goforth <e.goforth@computer.org> */
600   /* use the package name as the default instance name */
601   config.instanceName=(char *)malloc((strlen(PACKAGE)+1)*sizeof(char));
602   sprintf (config.instanceName, "%s", PACKAGE);
603 
604 #if defined USE_GETOPT
605   while ((opt = getopt (argc, argv, "hvw?c:n:")) != EOF) {
606 #else
607   while ((opt = getopt_long (argc, argv, "c:h?n:vw", long_options,
608 			     &longopt_index)) > 0) {
609 #endif
610     dbg_msg (1, "Between while & switch: opt = '%c'\n", opt);
611     switch (opt) {
612     case '?':
613     case 'h':
614       usage ();
615       exit (EXIT_SUCCESS);
616     case 'w':
617       config.windowedMode = 1;
618       config.windowedModeLocked = 1;
619       break;
620     case 'v':
621       printf ("Version %s, %s\n"
622 	      "%s (c) 2002-2004 Val�ry Febvre <vfebvre@easter-eggs.com>\n\n",
623 	      VERSION, RELEASE_DATE, PACKAGE);
624       exit (EXIT_SUCCESS);
625     case 'c':
626       sprintf (configFilePath, "%s", optarg);
627       break;
628     case 'n':
629       /* Ed Goforth <e.goforth@computer.org> */
630       /* allow on command-line, but config file overrides it if given there */
631       config.instanceName = (char *) malloc ((strlen (optarg)+1)*sizeof(char));
632       sprintf (config.instanceName, "%s", optarg);
633       break;
634     }
635   }
636 }
637 
638 void freeUnusedMemory (void) {
639   unsigned int i, j;
640 
641   free (line);
642   free (nbRowsPerCol);
643   for (i=0; i<nbCols; i++) {
644     for (j=0; j<nbRows; j++) {
645       free (entries[i][j].tooltip);
646       free (entries[i][j].image);
647       free (entries[i][j].command);
648     }
649     free (entries[i]);
650   }
651   free (entries);
652 }
653 
654 void freeAllMemory (void) {
655   unsigned int i;
656 
657   for (i=0; i<nbImagesPaths; i++) {
658     free (config.imagesPaths[i]);
659   }
660   free (config.imagesPaths);
661   config.imagesPaths = NULL;
662   for (i=0; i<nbCols; i++) {
663     free (config.entries[i]);
664   }
665   free (config.entries);
666   config.entries = NULL;
667 }
668