1 /* -*-c-*- */
2 /*
3 * FvwmButtons, copyright 1996, Jarl Totland
4 *
5 * This module, and the entire GoodStuff program, and the concept for
6 * interfacing this module to the Window Manager, are all original work
7 * by Robert Nation
8 */
9
10 /* This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, see: <http://www.gnu.org/licenses/>
22 */
23
24 #include "config.h"
25
26 #include <ctype.h>
27 #include <stdio.h>
28
29 #include <X11/Xlib.h>
30 #include <X11/Intrinsic.h>
31
32 #include "libs/fvwmlib.h"
33 #include "libs/FScreen.h"
34 #include "libs/Module.h"
35 #include "libs/Colorset.h"
36 #include "libs/Parse.h"
37 #include "libs/Strings.h"
38 #include "FvwmButtons.h"
39 #include "button.h"
40 #include "parse.h"
41
42 extern int w, h, x, y, xneg, yneg; /* used in ParseConfigLine */
43 extern char *config_file;
44 extern int button_width;
45 extern int button_height;
46 extern int has_button_geometry;
47 extern int screen;
48
49 /* contains the character that terminated the last string from seekright */
50 static char terminator = '\0';
51
52 /* ----------------------------------- macros ------------------------------ */
53
trimleft(char * s)54 static char *trimleft(char *s)
55 {
56 while (s && isspace((unsigned char)*s))
57 {
58 s++;
59 }
60 return s;
61 }
62
63 /**
64 *** seekright()
65 ***
66 *** split off the first continous section of the string into a new allocated
67 *** string and move the old pointer forward. Accepts and strips quoting with
68 *** ['"`], and the current quote q can be escaped inside the string with \q.
69 **/
seekright(char ** s)70 static char *seekright(char **s)
71 {
72 char *token = NULL;
73 char *line = *s;
74
75 line = DoGetNextToken(line, &token, NULL, "),", &terminator);
76 if (*s != NULL && line == NULL)
77 {
78 line = strchr(*s, '\0');
79 }
80 *s = line;
81
82 return token;
83 }
84
my_get_font(char ** s)85 static char *my_get_font(char **s)
86 {
87 char *option;
88 int len;
89
90 *s = GetNextFullOption(*s, &option);
91 if (option)
92 {
93 for (len = strlen(option) - 1; len >= 0 && isspace(option[len]); len--)
94 {
95 /* remove trailing whitespace */
96 option[len] = 0;
97 }
98 for ( ; *option && isspace(*option); option++)
99 {
100 /* remove leading whitespace */
101 }
102 }
103
104 len = strlen(option) -1;
105 if (option[len] == ')' )
106 {
107 option[len] = 0;
108 }
109
110 return option;
111 }
112
113 /**
114 *** ParseBack()
115 *** Parses the options possible to Back
116 *** This function appears to be obsolete & should be removed -- SS.
117 **/
ParseBack(char ** ss)118 static int ParseBack(char **ss)
119 {
120 char *opts[] =
121 {
122 "icon",
123 NULL
124 };
125 char *t, *s = *ss;
126 int r = 0;
127
128 while (*s && *s != ')')
129 {
130 s = trimleft(s);
131 if (*s == ',')
132 {
133 s++;
134 continue;
135 }
136
137 switch (GetTokenIndex(s, opts, -1, &s))
138 {
139 case 0: /* Icon */
140 r = 1;
141 fprintf(stderr,
142 "%s: Back(Icon) not supported yet\n",
143 MyName);
144 break;
145 default:
146 t = seekright(&s);
147 fprintf(stderr,
148 "%s: Illegal back option \"%s\"\n",
149 MyName, (t) ? t : "");
150 if (t)
151 {
152 free(t);
153 }
154 }
155 }
156 if (*s)
157 {
158 s++;
159 }
160 *ss = s;
161
162 return r;
163 }
164
165 /**
166 *** ParseBoxSize()
167 *** Parses the options possible to BoxSize
168 **/
ParseBoxSize(char ** ss,flags_type * flags)169 static void ParseBoxSize(char **ss, flags_type *flags)
170 {
171 char *opts[] =
172 {
173 "dumb",
174 "fixed",
175 "smart",
176 NULL
177 };
178 char *s = *ss;
179 int m;
180
181 if (!s)
182 {
183 return;
184 }
185 *ss = GetNextTokenIndex(*ss, opts, 0, &m);
186 switch (m)
187 {
188 case 0:
189 flags->b_SizeFixed = 0;
190 flags->b_SizeSmart = 0;
191 break;
192 case 1:
193 flags->b_SizeFixed = 1;
194 flags->b_SizeSmart = 0;
195 break;
196 case 2:
197 flags->b_SizeSmart = 1;
198 flags->b_SizeFixed = 0;
199 break;
200 default:
201 flags->b_SizeFixed = 0;
202 flags->b_SizeSmart = 0;
203 fprintf(stderr,
204 "%s: Illegal boxsize option \"%s\"\n",
205 MyName, s);
206 break;
207 }
208 return;
209 }
210
211 /**
212 *** ParseTitle()
213 *** Parses the options possible to Title
214 **/
ParseTitle(char ** ss,byte * flags,byte * mask)215 static void ParseTitle(char **ss, byte *flags, byte *mask)
216 {
217 char *titleopts[] =
218 {
219 "left",
220 "right",
221 "center",
222 "side",
223 NULL
224 };
225 char *t, *s = *ss;
226
227 while (*s && *s != ')')
228 {
229 s = trimleft(s);
230 if (*s == ',')
231 {
232 s++;
233 continue;
234 }
235
236 switch (GetTokenIndex(s, titleopts, -1, &s))
237 {
238 case 0: /* Left */
239 *flags &= ~b_TitleHoriz;
240 *flags &= ~3;
241 *mask |= b_TitleHoriz;
242 break;
243 case 1: /* Right */
244 *flags &= ~b_TitleHoriz;
245 *flags &= ~3;
246 *flags |= 2;
247 *mask |= b_TitleHoriz;
248 break;
249 case 2: /* Center */
250 *flags &= ~b_TitleHoriz;
251 *flags &= ~3;
252 *flags |= 1;
253 *mask |= b_TitleHoriz;
254 break;
255 case 3: /* Side */
256 *flags |= b_Horizontal;
257 *flags &= ~3;
258 *mask |= b_Horizontal;
259 break;
260 default:
261 t = seekright(&s);
262 fprintf(stderr,
263 "%s: Illegal title option \"%s\"\n",
264 MyName, (t) ? t : "");
265 if (t)
266 {
267 free(t);
268 }
269 }
270 }
271 if (*s)
272 {
273 s++;
274 }
275 *ss = s;
276 }
277
278 /**
279 *** ParseSwallow()
280 *** Parses the options possible to Swallow
281 **/
ParseSwallow(char ** ss,unsigned int * flags,unsigned int * mask,button_info * b)282 static void ParseSwallow(
283 char **ss, unsigned int *flags, unsigned int *mask, button_info *b)
284 {
285 char *swallowopts[] =
286 {
287 "nohints", "hints",
288 "nokill", "kill",
289 "noclose", "close",
290 "respawn", "norespawn",
291 "useold", "noold",
292 "usetitle", "notitle",
293 "fvwmmodule", "nofvwmmodule",
294 "swallownew",
295 NULL
296 };
297 char *t, *s = *ss;
298
299 while (*s && *s != ')')
300 {
301 s = trimleft(s);
302 if (*s == ',')
303 {
304 s++;
305 continue;
306 }
307
308 switch (GetTokenIndex(s, swallowopts, -1, &s))
309 {
310 case 0: /* NoHints */
311 *flags |= b_NoHints;
312 *mask |= b_NoHints;
313 break;
314 case 1: /* Hints */
315 *flags &= ~b_NoHints;
316 *mask |= b_NoHints;
317 break;
318 case 2: /* NoKill */
319 *flags &= ~b_Kill;
320 *mask |= b_Kill;
321 break;
322 case 3: /* Kill */
323 *flags |= b_Kill;
324 *mask |= b_Kill;
325 break;
326 case 4: /* NoClose */
327 *flags |= b_NoClose;
328 *mask |= b_NoClose;
329 break;
330 case 5: /* Close */
331 *flags &= ~b_NoClose;
332 *mask |= b_NoClose;
333 break;
334 case 6: /* Respawn */
335 *flags |= b_Respawn;
336 *mask |= b_Respawn;
337 b->newflags.do_swallow_new = 0;
338 break;
339 case 7: /* NoRespawn */
340 *flags &= ~b_Respawn;
341 *mask |= b_Respawn;
342 b->newflags.do_swallow_new = 0;
343 break;
344 case 8: /* UseOld */
345 *flags |= b_UseOld;
346 *mask |= b_UseOld;
347 break;
348 case 9: /* NoOld */
349 *flags &= ~b_UseOld;
350 *mask |= b_UseOld;
351 break;
352 case 10: /* UseTitle */
353 *flags |= b_UseTitle;
354 *mask |= b_UseTitle;
355 break;
356 case 11: /* NoTitle */
357 *flags &= ~b_UseTitle;
358 *mask |= b_UseTitle;
359 break;
360 case 12: /* FvwmModule */
361 *flags |= b_FvwmModule;
362 *mask |= b_FvwmModule;
363 break;
364 case 13: /* NoFvwmModule */
365 *flags &= ~b_FvwmModule;
366 *mask |= b_FvwmModule;
367 break;
368 case 14: /* SwallowNew */
369 *flags &= ~b_Respawn;
370 *mask |= b_Respawn;
371 b->newflags.do_swallow_new = 1;
372 break;
373 default:
374 t = seekright(&s);
375 fprintf(stderr,
376 "%s: Illegal Swallow option \"%s\"\n", MyName,
377 (t) ? t : "");
378 if (t)
379 {
380 free(t);
381 }
382 }
383 }
384 if (*s)
385 {
386 s++;
387 }
388 *ss = s;
389 }
390
391 /**
392 *** ParsePanel()
393 *** Parses the options possible to Panel
394 **/
ParsePanel(char ** ss,unsigned int * flags,unsigned int * mask,char * direction,int * steps,int * delay,panel_flags_type * panel_flags,int * indicator_size,int * rela_x,int * rela_y,char * position,char * context)395 static void ParsePanel(
396 char **ss, unsigned int *flags, unsigned int *mask, char *direction,
397 int *steps, int *delay, panel_flags_type *panel_flags,
398 int *indicator_size, int *rela_x, int *rela_y, char *position,
399 char *context)
400 {
401 char *swallowopts[] =
402 {
403 "nohints", "hints",
404 "nokill", "kill",
405 "noclose", "close",
406 "respawn", "norespawn",
407 "useold", "noold",
408 "usetitle", "notitle",
409 "up", "down", "left", "right",
410 "steps",
411 "delay",
412 "smooth",
413 "noborder",
414 "indicator",
415 "position",
416 NULL
417 };
418
419 char *positionopts[] =
420 {
421 "button", "module", "root", "center", "left", "top", "right",
422 "bottom", "noplr", "noptb", "mlr", "mtb", NULL
423 };
424
425 char *t, *s = *ss;
426 int n;
427
428 while (*s && *s != ')')
429 {
430 s = trimleft(s);
431 if (*s == ',')
432 {
433 s++;
434 continue;
435 }
436
437 switch (GetTokenIndex(s, swallowopts, -1, &s))
438 {
439 case 0: /* NoHints */
440 *flags |= b_NoHints;
441 *mask |= b_NoHints;
442 break;
443 case 1: /* Hints */
444 *flags &= ~b_NoHints;
445 *mask |= b_NoHints;
446 break;
447 case 2: /* NoKill */
448 *flags &= ~b_Kill;
449 *mask |= b_Kill;
450 break;
451 case 3: /* Kill */
452 *flags |= b_Kill;
453 *mask |= b_Kill;
454 break;
455 case 4: /* NoClose */
456 *flags |= b_NoClose;
457 *mask |= b_NoClose;
458 break;
459 case 5: /* Close */
460 *flags &= ~b_NoClose;
461 *mask |= b_NoClose;
462 break;
463 case 6: /* Respawn */
464 *flags |= b_Respawn;
465 *mask |= b_Respawn;
466 break;
467 case 7: /* NoRespawn */
468 *flags &= ~b_Respawn;
469 *mask |= b_Respawn;
470 break;
471 case 8: /* UseOld */
472 *flags |= b_UseOld;
473 *mask |= b_UseOld;
474 break;
475 case 9: /* NoOld */
476 *flags &= ~b_UseOld;
477 *mask |= b_UseOld;
478 break;
479 case 10: /* UseTitle */
480 *flags |= b_UseTitle;
481 *mask |= b_UseTitle;
482 break;
483 case 11: /* NoTitle */
484 *flags &= ~b_UseTitle;
485 *mask |= b_UseTitle;
486 break;
487 case 12: /* up */
488 *direction = SLIDE_UP;
489 break;
490 case 13: /* down */
491 *direction = SLIDE_DOWN;
492 break;
493 case 14: /* left */
494 *direction = SLIDE_LEFT;
495 break;
496 case 15: /* right */
497 *direction = SLIDE_RIGHT;
498 break;
499 case 16: /* steps */
500 sscanf(s, "%d%n", steps, &n);
501 s += n;
502 break;
503 case 17: /* delay */
504 sscanf(s, "%d%n", delay, &n);
505 s += n;
506 break;
507 case 18: /* smooth */
508 (*panel_flags).smooth = 1;
509 break;
510 case 19: /* noborder */
511 (*panel_flags).ignore_lrborder = 1;
512 (*panel_flags).ignore_tbborder = 1;
513 break;
514 case 20: /* indicator */
515 n = 0;
516 (*panel_flags).panel_indicator = 1;
517 *indicator_size = 0;
518 sscanf(s, "%d%n", indicator_size, &n);
519 if (*indicator_size < 0 || *indicator_size > 100)
520 {
521 *indicator_size = 0;
522 }
523 s += n;
524 break;
525 case 21: /* position */
526 n = 0;
527 *rela_x = *rela_y = 0;
528 while (*s != ',' && *s != ')' && *s)
529 {
530 s = trimleft(s);
531 /* get x and y offset */
532 if (isdigit(*s) || *s == '+' || *s == '-')
533 {
534 sscanf(s, "%i%n", rela_x, &n);
535 s += n;
536 if (*s == 'p' || *s == 'P')
537 {
538 (*panel_flags).relative_x_pixel = 1;
539 s++;
540 }
541 n = 0;
542 s = trimleft(s);
543 sscanf(s, "%i%n", rela_y, &n);
544 s += n;
545 if (*s == 'p' || *s == 'P')
546 {
547 (*panel_flags).relative_y_pixel = 1;
548 s++;
549 }
550 s = trimleft(s);
551 }
552 switch (GetTokenIndex(s, positionopts, -1, &s))
553 {
554 case 0: /* button */
555 *context = SLIDE_CONTEXT_PB;
556 break;
557 case 1: /* module */
558 *context = SLIDE_CONTEXT_MODULE;
559 break;
560 case 2: /* root */
561 *context = SLIDE_CONTEXT_ROOT;
562 break;
563 case 3: /* center */
564 *position = SLIDE_POSITION_CENTER;
565 break;
566 case 4: /* left */
567 *position = SLIDE_POSITION_LEFT_TOP;
568 break;
569 case 5: /* top */
570 *position = SLIDE_POSITION_LEFT_TOP;
571 break;
572 case 6: /* right */
573 *position = SLIDE_POSITION_RIGHT_BOTTOM;
574 break;
575 case 7: /* bottom */
576 *position = SLIDE_POSITION_RIGHT_BOTTOM;
577 break;
578 case 8: /* noplr */
579 (*panel_flags).ignore_lrborder = 1;
580 break;
581 case 9: /* noptb */
582 (*panel_flags).ignore_tbborder = 1;
583 break;
584 case 10: /* mlr */
585 (*panel_flags).buttons_lrborder = 1;
586 break;
587 case 11: /* mtb */
588 (*panel_flags).buttons_tbborder = 1;
589 break;
590 default:
591 t = seekright(&s);
592 s--;
593 if (t)
594 {
595 fprintf(stderr,
596 "%s: Illegal Panel "
597 "position option %s\n",
598 MyName, (t) ? t : "");
599 free(t);
600 }
601 }
602 }
603 break;
604 default:
605 t = seekright(&s);
606 fprintf(stderr,
607 "%s: Illegal Panel option \"%s\"\n", MyName,
608 (t) ? t : "");
609 if (t)
610 {
611 free(t);
612 }
613 }
614 }
615 if (*s)
616 {
617 s++;
618 }
619 *ss = s;
620 }
621
622 /**
623 *** ParseContainer()
624 *** Parses the options possible to Container
625 **/
ParseContainer(char ** ss,button_info * b)626 static void ParseContainer(char **ss,button_info *b)
627 {
628 char *conts[] =
629 {
630 "columns",
631 "rows",
632 "font",
633 "frame",
634 "back",
635 "fore",
636 "padding",
637 "title",
638 "swallow",
639 "nosize",
640 "size",
641 "boxsize",
642 "colorset",
643 NULL
644 };
645 char *t, *o, *s = *ss;
646 int i, j;
647
648 while (*s && *s != ')')
649 {
650 s = trimleft(s);
651 if (*s == ',')
652 {
653 s++;
654 continue;
655 }
656
657 switch (GetTokenIndex(s, conts, -1, &s))
658 {
659 case 0: /* Columns */
660 b->c->num_columns = max(1, strtol(s, &t, 10));
661 s = t;
662 break;
663 case 1: /* Rows */
664 b->c->num_rows = max(1, strtol(s, &t, 10));
665 s = t;
666 break;
667 case 2: /* Font */
668 if (b->c->font_string)
669 {
670 free(b->c->font_string);
671 }
672 b->c->font_string = my_get_font(&s);
673 b->c->flags.b_Font = (b->c->font_string ? 1 : 0);
674 break;
675 case 3: /* Frame */
676 b->c->framew = strtol(s, &t, 10);
677 b->c->flags.b_Frame = 1;
678 s = t;
679 break;
680 case 4: /* Back */
681 s = trimleft(s);
682 if (*s == '(' && s++ && ParseBack(&s))
683 {
684 b->c->flags.b_IconBack = 1;
685 }
686 if (b->c->back)
687 {
688 free(b->c->back);
689 }
690 b->c->back = seekright(&s);
691 if (b->c->back)
692 {
693 b->c->flags.b_Back = 1;
694 }
695 else
696 {
697 b->c->flags.b_IconBack = 0;
698 b->c->flags.b_Back = 0;
699 }
700 break;
701 case 5: /* Fore */
702 if (b->c->fore) free(b->c->fore);
703 b->c->fore = seekright(&s);
704 b->c->flags.b_Fore = (b->c->fore ? 1 : 0);
705 break;
706 case 6: /* Padding */
707 i = strtol(s, &t, 10);
708 if (t > s)
709 {
710 b->c->xpad = b->c->ypad = i;
711 s = t;
712 i = strtol(s, &t, 10);
713 if (t > s)
714 {
715 b->c->ypad = i;
716 s = t;
717 }
718 b->c->flags.b_Padding = 1;
719 }
720 else
721 fprintf(stderr,"%s: Illegal padding argument\n",MyName);
722 break;
723 case 7: /* Title - flags */
724 s = trimleft(s);
725 if (*s == '(' && s++)
726 {
727 b->c->justify = 0;
728 b->c->justify_mask = 0;
729 ParseTitle(&s, &b->c->justify, &b->c->justify_mask);
730 if (b->c->justify_mask)
731 {
732 b->c->flags.b_Justify = 1;
733 }
734 }
735 else
736 {
737 char *temp;
738 fprintf(stderr,
739 "%s: Illegal title in container options\n",
740 MyName);
741 temp = seekright(&s);
742 if (temp)
743 {
744 free(temp);
745 }
746 }
747 break;
748 case 8: /* Swallow - flags */
749 {
750 Bool failed = False;
751
752 s = trimleft(s);
753 if (b->c->flags.b_Swallow || b->c->flags.b_Panel)
754 {
755 fprintf(stderr, "%s: Multiple Swallow or Panel options are not"
756 " allowed in a single button", MyName);
757 failed = True;
758 }
759 else if (*s == '(' && s++)
760 {
761 b->c->swallow = 0;
762 b->c->swallow_mask = 0;
763 ParseSwallow(&s, &b->c->swallow, &b->c->swallow_mask, b);
764 if (b->c->swallow_mask)
765 {
766 b->c->flags.b_Swallow = 1;
767 }
768 }
769 else
770 {
771 fprintf(stderr,
772 "%s: Illegal swallow or panel in container options\n",
773 MyName);
774 failed = True;
775 }
776 if (failed)
777 {
778 char *temp;
779
780 temp = seekright(&s);
781 if (temp)
782 free(temp);
783 }
784 }
785 break;
786 case 9: /* NoSize */
787 b->c->flags.b_Size = 1;
788 b->c->minx = b->c->miny = 0;
789 break;
790
791 case 10: /* Size */
792 i = strtol(s, &t, 10);
793 j = strtol(t, &o, 10);
794 if (t > s && o > t)
795 {
796 b->c->minx = i;
797 b->c->miny = j;
798 b->c->flags.b_Size = 1;
799 s = o;
800 }
801 else
802 fprintf(stderr,"%s: Illegal size arguments\n",MyName);
803 break;
804
805 case 11: /* BoxSize */
806 ParseBoxSize(&s, &b->c->flags);
807 break;
808
809 case 12: /* Colorset */
810 i = strtol(s, &t, 10);
811 if (t > s)
812 {
813 b->c->colorset = i;
814 b->c->flags.b_Colorset = 1;
815 AllocColorset(i);
816 s = t;
817 }
818 else
819 {
820 b->c->flags.b_Colorset = 0;
821 }
822 break;
823
824 default:
825 t = seekright(&s);
826 fprintf(stderr,"%s: Illegal container option \"%s\"\n",MyName, (t)?t:"");
827 if (t)
828 free(t);
829 }
830 }
831 if (*s)
832 {
833 s++;
834 }
835 *ss = s;
836 }
837
838 /**
839 *** ParseButton()
840 ***
841 *** parse a buttonconfig string.
842 *** *FvwmButtons: (option[ options]) title iconname command
843 **/
844 /*#define DEBUG_PARSER*/
ParseButton(button_info ** uberb,char * s)845 static void ParseButton(button_info **uberb, char *s)
846 {
847 button_info *b, *ub = *uberb;
848 int i, j;
849 char *t, *o;
850
851 b = alloc_button(ub, (ub->c->num_buttons)++);
852 s = trimleft(s);
853
854 if (*s == '(' && s++)
855 {
856 char *opts[] =
857 {
858 "back",
859 "fore",
860 "font",
861 "title",
862 "icon",
863 "frame",
864 "padding",
865 "swallow",
866 "panel",
867 "actionignoresclientwindow",
868 "actiononpress",
869 "container",
870 "end",
871 "nosize",
872 "size",
873 "left",
874 "right",
875 "center",
876 "colorset",
877 "action",
878 "id",
879 "activeicon",
880 "activetitle",
881 "pressicon",
882 "presstitle",
883 "activecolorset",
884 "presscolorset",
885 "top",
886 NULL
887 };
888 s = trimleft(s);
889 while (*s && *s != ')')
890 {
891 Bool is_swallow = False;
892
893 if (*s == ',')
894 {
895 s++;
896 s = trimleft(s);
897 continue;
898 }
899 if (isdigit(*s) || *s == '+' || *s == '-')
900 {
901 char *geom;
902 int x, y, flags;
903 unsigned int w, h;
904 geom = seekright(&s);
905 if (geom)
906 {
907 flags = XParseGeometry(geom, &x, &y, &w, &h);
908 if (flags&WidthValue)
909 {
910 b->BWidth = w;
911 }
912 if (flags&HeightValue)
913 {
914 b->BHeight = h;
915 }
916 if (flags & XValue)
917 {
918 b->BPosX = x;
919 b->flags.b_PosFixed = 1;
920 }
921 if (flags & YValue)
922 {
923 b->BPosY = y;
924 b->flags.b_PosFixed = 1;
925 }
926 if (flags & XNegative)
927 {
928 b->BPosX = -1 - x;
929 }
930 if (flags & YNegative)
931 {
932 b->BPosY = -1 - y;
933 }
934 free(geom);
935 }
936 s = trimleft(s);
937 continue;
938 }
939 switch (GetTokenIndex(s, opts, -1, &s))
940 {
941 case 0: /* Back */
942 s = trimleft(s);
943 if (*s == '(' && s++ && ParseBack(&s))
944 {
945 b->flags.b_IconBack = 1;
946 }
947 if (b->flags.b_Back && b->back)
948 {
949 free(b->back);
950 }
951 b->back = seekright(&s);
952 if (b->back)
953 {
954 b->flags.b_Back = 1;
955 }
956 else
957 {
958 b->flags.b_IconBack = 0;
959 b->flags.b_Back = 0;
960 }
961 break;
962
963 case 1: /* Fore */
964 if (b->flags.b_Fore && b->fore)
965 {
966 free(b->fore);
967 }
968 b->fore = seekright(&s);
969 b->flags.b_Fore = (b->fore ? 1 : 0);
970 break;
971
972 case 2: /* Font */
973 if (b->flags.b_Font && b->font_string)
974 {
975 free(b->font_string);
976 }
977 b->font_string = my_get_font(&s);
978 b->flags.b_Font = (b->font_string ? 1 : 0);
979 break;
980
981 /* ----------------- title --------------- */
982
983 case 3: /* Title */
984 s = trimleft(s);
985 if (*s == '(' && s++)
986 {
987 b->justify = 0;
988 b->justify_mask = 0;
989 ParseTitle(
990 &s, &b->justify,
991 &b->justify_mask);
992 if (b->justify_mask)
993 {
994 b->flags.b_Justify = 1;
995 }
996 }
997 t = seekright(&s);
998 if (t && *t && (t[0] != '-' || t[1] != 0))
999 {
1000 if (b->title)
1001 {
1002 free(b->title);
1003 }
1004 b->title = t;
1005 #ifdef DEBUG_PARSER
1006 fprintf(stderr,
1007 "PARSE: Title \"%s\"\n",
1008 b->title);
1009 #endif
1010 b->flags.b_Title = 1;
1011 }
1012 else
1013 {
1014 fprintf(stderr,
1015 "%s: Missing title argument\n",
1016 MyName);
1017 if (t)
1018 {
1019 free(t);
1020 }
1021 }
1022 break;
1023
1024 /* ------------------ icon --------------- */
1025
1026 case 4: /* Icon */
1027 t = seekright(&s);
1028 if (t && *t && (t[0] != '-' || t[1] != 0))
1029 {
1030 if (b->flags.b_Swallow)
1031 {
1032 fprintf(stderr,
1033 "%s: a button can not "
1034 "have an icon and a "
1035 "swallowed window at "
1036 "the same time. "
1037 "Ignoring icon\n",
1038 MyName);
1039 }
1040 else
1041 {
1042 if (b->icon_file)
1043 {
1044 free(b->icon_file);
1045 }
1046 b->icon_file = t;
1047 b->flags.b_Icon = 1;
1048 }
1049 }
1050 else
1051 {
1052 fprintf(stderr,
1053 "%s: Missing Icon argument\n",
1054 MyName);
1055 if (t)
1056 {
1057 free(t);
1058 }
1059 }
1060 break;
1061
1062 /* ----------------- frame --------------- */
1063
1064 case 5: /* Frame */
1065 i = strtol(s, &t, 10);
1066 if (t > s)
1067 {
1068 b->flags.b_Frame = 1;
1069 b->framew = i;
1070 s = t;
1071 }
1072 else
1073 {
1074 fprintf(stderr,
1075 "%s: Illegal frame argument\n",
1076 MyName);
1077 }
1078 break;
1079
1080 /* ---------------- padding -------------- */
1081
1082 case 6: /* Padding */
1083 i = strtol(s,&t,10);
1084 if (t>s)
1085 {
1086 b->xpad = b->ypad = i;
1087 b->flags.b_Padding = 1;
1088 s = t;
1089 i = strtol(s, &t, 10);
1090 if (t > s)
1091 {
1092 b->ypad = i;
1093 s = t;
1094 }
1095 }
1096 else
1097 {
1098 fprintf(stderr,
1099 "%s: Illegal padding "
1100 "argument\n", MyName);
1101 }
1102 break;
1103
1104 /* ---------------- swallow -------------- */
1105
1106 case 7: /* Swallow */
1107 is_swallow = True;
1108 /* fall through */
1109
1110 case 8: /* Panel */
1111 s = trimleft(s);
1112 if (is_swallow)
1113 {
1114 b->swallow = 0;
1115 b->swallow_mask = 0;
1116 }
1117 else
1118 {
1119 /* set defaults */
1120 b->swallow = b_Respawn;
1121 b->swallow_mask = b_Respawn;
1122 b->slide_direction = SLIDE_UP;
1123 b->slide_position = SLIDE_POSITION_CENTER;
1124 b->slide_context = SLIDE_CONTEXT_PB;
1125 b->relative_x = 0;
1126 b->relative_y = 0;
1127 b->slide_steps = 12;
1128 b->slide_delay_ms = 5;
1129 }
1130 if (*s == '(' && s++)
1131 {
1132 if (is_swallow)
1133 {
1134 ParseSwallow(
1135 &s, &b->swallow,
1136 &b->swallow_mask, b);
1137 }
1138 else
1139 {
1140 ParsePanel(
1141 &s, &b->swallow,
1142 &b->swallow_mask,
1143 &b->slide_direction,
1144 &b->slide_steps,
1145 &b->slide_delay_ms,
1146 &b->panel_flags,
1147 &b->indicator_size,
1148 &b->relative_x,
1149 &b->relative_y,
1150 &b->slide_position,
1151 &b->slide_context);
1152 }
1153 }
1154 t = seekright(&s);
1155 o = seekright(&s);
1156 if (t)
1157 {
1158 if (b->hangon)
1159 {
1160 free(b->hangon);
1161 }
1162 b->hangon = t;
1163 if (is_swallow)
1164 {
1165 if (b->flags.b_Icon)
1166 {
1167 fprintf(stderr,
1168 "%s: a button can not "
1169 "have an icon and a "
1170 "swallowed window at "
1171 "the same time. "
1172 "Ignoring icon\n",
1173 MyName);
1174 b->flags.b_Icon = 0;
1175 }
1176
1177 b->flags.b_Swallow = 1;
1178 b->flags.b_Hangon = 1;
1179 }
1180 else
1181 {
1182 b->flags.b_Panel = 1;
1183 b->flags.b_Hangon = 1;
1184 b->newflags.is_panel = 1;
1185 b->newflags.panel_mapped = 0;
1186 }
1187 b->swallow |= 1;
1188 if (!(b->swallow & b_NoHints))
1189 {
1190 b->hints = (XSizeHints*)
1191 mymalloc(sizeof(XSizeHints));
1192 }
1193 if (o)
1194 {
1195 char *p;
1196
1197 p = module_expand_action(
1198 Dpy, screen, o, NULL,
1199 UberButton->c->fore,
1200 UberButton->c->back);
1201 if (p)
1202 {
1203 if (!(buttonSwallow(b)&b_UseOld))
1204 {
1205 exec_swallow(p,b);
1206 }
1207 if (b->spawn)
1208 {
1209 free(b->spawn);
1210 }
1211
1212 /* Might be needed if
1213 * respawning sometime
1214 */
1215 b->spawn = o;
1216 free(p);
1217 }
1218 }
1219 }
1220 else
1221 {
1222 fprintf(stderr,
1223 "%s: Missing swallow "
1224 "argument\n", MyName);
1225 if (t)
1226 {
1227 free(t);
1228 }
1229 if (o)
1230 {
1231 free(o);
1232 }
1233 }
1234 /* check if it is a module by command line inspection if
1235 * this hints has not been given in the swallow option */
1236 if (is_swallow && !(b->swallow_mask & b_FvwmModule))
1237 {
1238 if (b->spawn != NULL &&
1239 (strncasecmp(b->spawn, "module", 6) == 0 ||
1240 strncasecmp(b->spawn, "fvwm", 4) == 0))
1241 {
1242 b->swallow |= b_FvwmModule;
1243 }
1244 }
1245 break;
1246
1247 case 9: /* ActionIgnoresClientWindow */
1248 b->flags.b_ActionIgnoresClientWindow = 1;
1249 break;
1250
1251 case 10: /* ActionOnPress */
1252 b->flags.b_ActionOnPress = 1;
1253 break;
1254
1255 /* ---------------- container ------------ */
1256
1257 case 11: /* Container */
1258 /*
1259 * SS: This looks very buggy! The FvwmButtons
1260 * man page suggests it's here to restrict the
1261 * options used with "Container", but it only
1262 * restricts those options appearing _before_
1263 * the "Container" keyword for a button.
1264 * b->flags&=b_Frame|b_Back|b_Fore|b_Padding|b_Action;
1265 */
1266
1267 MakeContainer(b);
1268 *uberb = b;
1269 s = trimleft(s);
1270 if (*s == '(' && s++)
1271 {
1272 ParseContainer(&s,b);
1273 }
1274 break;
1275
1276 case 12: /* End */
1277 *uberb = ub->parent;
1278 ub->c->buttons[--(ub->c->num_buttons)] = NULL;
1279 free(b);
1280 if (!ub->parent)
1281 {
1282 fprintf(stderr,"%s: Unmatched END in config file\n",MyName);
1283 exit(1);
1284 }
1285 if (ub->parent->c->flags.b_Colorset ||
1286 ub->parent->c->flags.b_ColorsetParent)
1287 {
1288 ub->c->flags.b_ColorsetParent = 1;
1289 }
1290 if (ub->parent->c->flags.b_IconBack || ub->parent->c->flags.b_IconParent)
1291 {
1292 ub->c->flags.b_IconParent = 1;
1293 }
1294 return;
1295
1296 case 13: /* NoSize */
1297 b->flags.b_Size = 1;
1298 b->minx = b->miny = 0;
1299 break;
1300
1301 case 14: /* Size */
1302 i = strtol(s, &t, 10);
1303 j = strtol(t, &o, 10);
1304 if (t > s && o > t)
1305 {
1306 b->minx = i;
1307 b->miny = j;
1308 b->flags.b_Size = 1;
1309 s = o;
1310 }
1311 else
1312 {
1313 fprintf(stderr,
1314 "%s: Illegal size arguments\n",
1315 MyName);
1316 }
1317 break;
1318
1319 case 15: /* Left */
1320 b->flags.b_Left = 1;
1321 b->flags.b_Right = 0;
1322 break;
1323
1324 case 16: /* Right */
1325 b->flags.b_Right = 1;
1326 b->flags.b_Left = 0;
1327 break;
1328
1329 case 17: /* Center */
1330 b->flags.b_Right = 0;
1331 b->flags.b_Left = 0;
1332 break;
1333
1334 case 18: /* Colorset */
1335 i = strtol(s, &t, 10);
1336 if (t > s)
1337 {
1338 b->colorset = i;
1339 b->flags.b_Colorset = 1;
1340 s = t;
1341 AllocColorset(i);
1342 }
1343 else
1344 {
1345 b->flags.b_Colorset = 0;
1346 }
1347 break;
1348
1349 /* ----------------- action -------------- */
1350
1351 case 19: /* Action */
1352 s = trimleft(s);
1353 i = 0;
1354 if (*s == '(')
1355 {
1356 s++;
1357 if (strncasecmp(s, "mouse", 5) != 0)
1358 {
1359 fprintf(stderr,
1360 "%s: Couldn't parse "
1361 "action\n", MyName);
1362 }
1363 s += 5;
1364 i = strtol(s, &t, 10);
1365 s = t;
1366 while (*s && *s != ')')
1367 {
1368 s++;
1369 }
1370 if (*s == ')')
1371 {
1372 s++;
1373 }
1374 }
1375 {
1376 char *r;
1377 char *u = s;
1378
1379 s = GetQuotedString(s, &t, ",)", NULL, "(", ")");
1380 r = s;
1381 if (t && r > u + 1)
1382 {
1383 /* remove unquoted trailing spaces */
1384 r -= 2;
1385 while (r >= u && isspace(*r))
1386 {
1387 r--;
1388 }
1389 r++;
1390 if (isspace(*r))
1391 {
1392 t[strlen(t) - (s - r - 1)] = 0;
1393 }
1394 }
1395 }
1396 if (t)
1397 {
1398 AddButtonAction(b,i,t);
1399 free(t);
1400 }
1401 else
1402 {
1403 fprintf(stderr,
1404 "%s: Missing action argument\n",
1405 MyName);
1406 }
1407 break;
1408
1409 case 20: /* Id */
1410 s = trimleft(s);
1411 s = DoGetNextToken(s, &t, NULL, ",)", &terminator);
1412
1413 /* it should include the delimiter */
1414 if (s && terminator == ')')
1415 {
1416 s--;
1417 }
1418
1419 if (t)
1420 {
1421 if (isalpha(t[0]))
1422 {
1423 /* should check for duplicate ids first... */
1424 b->flags.b_Id = 1;
1425 if (b->id)
1426 {
1427 free(b->id);
1428 }
1429 CopyString(&b->id, t);
1430 }
1431 else
1432 {
1433 fprintf(stderr,
1434 "%s: Incorrect id '%s' "
1435 "ignored\n", MyName, t);
1436 }
1437 free(t);
1438 }
1439 else
1440 {
1441 fprintf(stderr,
1442 "%s: Missing id argument\n",
1443 MyName);
1444 }
1445 break;
1446
1447 /* ------------------ ActiveIcon --------------- */
1448 case 21: /* ActiveIcon */
1449 t = seekright(&s);
1450 if (t && *t && (t[0] != '-' || t[1] != 0))
1451 {
1452 if (b->flags.b_Swallow)
1453 {
1454 fprintf(stderr,
1455 "%s: a button can not "
1456 "have a ActiveIcon and "
1457 "a swallowed window at "
1458 "the same time. "
1459 "Ignoring ActiveIcon.\n",
1460 MyName);
1461 }
1462 else
1463 {
1464 if (b->active_icon_file)
1465 {
1466 free(b->active_icon_file);
1467 }
1468 b->active_icon_file = t;
1469 b->flags.b_ActiveIcon = 1;
1470 }
1471 }
1472 else
1473 {
1474 fprintf(stderr,
1475 "%s: Missing ActiveIcon "
1476 "argument\n", MyName);
1477 if (t)
1478 {
1479 free(t);
1480 }
1481 }
1482 break;
1483
1484 /* --------------- ActiveTitle --------------- */
1485 case 22: /* ActiveTitle */
1486 s = trimleft(s);
1487 if (*s == '(')
1488 {
1489 fprintf(stderr,
1490 "%s: justification not allowed "
1491 "for ActiveTitle.\n", MyName);
1492 }
1493 t = seekright(&s);
1494 if (t && *t && (t[0] != '-' || t[1] != 0))
1495 {
1496 if (b->activeTitle)
1497 {
1498 free(b->activeTitle);
1499 }
1500 b->activeTitle = t;
1501 #ifdef DEBUG_PARSER
1502 fprintf(stderr,
1503 "PARSE: ActiveTitle \"%s\"\n",
1504 b->activeTitle);
1505 #endif
1506 b->flags.b_ActiveTitle = 1;
1507 }
1508 else
1509 {
1510 fprintf(stderr,
1511 "%s: Missing ActiveTitle "
1512 "argument\n", MyName);
1513 if (t)
1514 {
1515 free(t);
1516 }
1517 }
1518 break;
1519
1520 /* --------------- PressIcon --------------- */
1521 case 23: /* PressIcon */
1522 t = seekright(&s);
1523 if (t && *t && (t[0] != '-' || t[1] != 0))
1524 {
1525 if (b->flags.b_Swallow)
1526 {
1527 fprintf(stderr,
1528 "%s: a button can not "
1529 "have a PressIcon and "
1530 "a swallowed window at "
1531 "the same time. "
1532 "Ignoring PressIcon.\n",
1533 MyName);
1534 }
1535 else
1536 {
1537 if (b->press_icon_file)
1538 {
1539 free(b->press_icon_file);
1540 }
1541 b->press_icon_file = t;
1542 b->flags.b_PressIcon = 1;
1543 }
1544 }
1545 else
1546 {
1547 fprintf(stderr,
1548 "%s: Missing PressIcon "
1549 "argument\n", MyName);
1550 if (t)
1551 {
1552 free(t);
1553 }
1554 }
1555 break;
1556
1557 /* --------------- PressTitle --------------- */
1558 case 24: /* PressTitle */
1559 s = trimleft(s);
1560 if (*s == '(')
1561 {
1562 fprintf(stderr,
1563 "%s: justification not allowed "
1564 "for PressTitle.\n", MyName);
1565 }
1566 t = seekright(&s);
1567 if (t && *t && (t[0] != '-' || t[1] != 0))
1568 {
1569 if (b->pressTitle)
1570 {
1571 free(b->pressTitle);
1572 }
1573 b->pressTitle = t;
1574 #ifdef DEBUG_PARSER
1575 fprintf(stderr,
1576 "PARSE: PressTitle \"%s\"\n",
1577 b->pressTitle);
1578 #endif
1579 b->flags.b_PressTitle = 1;
1580 }
1581 else
1582 {
1583 fprintf(stderr,
1584 "%s: Missing PressTitle "
1585 "argument\n", MyName);
1586 if (t)
1587 {
1588 free(t);
1589 }
1590 }
1591 break;
1592
1593 /* --------------- --------------- */
1594 case 25: /* ActiveColorset */
1595 i = strtol(s, &t, 10);
1596 if (t > s)
1597 {
1598 b->activeColorset = i;
1599 b->flags.b_ActiveColorset = 1;
1600 s = t;
1601 AllocColorset(i);
1602 }
1603 else
1604 {
1605 b->flags.b_ActiveColorset = 0;
1606 }
1607 break;
1608
1609 /* --------------- --------------- */
1610 case 26: /* PressColorset */
1611 i = strtol(s, &t, 10);
1612 if (t > s)
1613 {
1614 b->pressColorset = i;
1615 b->flags.b_PressColorset = 1;
1616 s = t;
1617 AllocColorset(i);
1618 }
1619 else
1620 {
1621 b->flags.b_PressColorset = 0;
1622 }
1623 break;
1624
1625 case 27: /* top */
1626 b->flags.b_Top = 1;
1627 break;
1628 /* --------------- --------------- */
1629 default:
1630 t = seekright(&s);
1631 fprintf(stderr,
1632 "%s: Illegal button option \"%s\"\n",
1633 MyName, (t) ? t : "");
1634 if (t)
1635 {
1636 free(t);
1637 }
1638 break;
1639 } /* end switch */
1640 s = trimleft(s);
1641 }
1642 if (s && *s)
1643 {
1644 s++;
1645 s = trimleft(s);
1646 }
1647 }
1648
1649 /* get title and iconname */
1650 if (!b->flags.b_Title)
1651 {
1652 b->title = seekright(&s);
1653 if (b->title && *b->title &&
1654 ((b->title)[0] != '-' || (b->title)[1] != 0))
1655 {
1656 b->flags.b_Title = 1;
1657 }
1658 else if (b->title)
1659 {
1660 free(b->title);
1661 }
1662 }
1663 else
1664 {
1665 char *temp;
1666 temp = seekright(&s);
1667 if (temp)
1668 {
1669 free(temp);
1670 }
1671 }
1672
1673 if (!b->flags.b_Icon)
1674 {
1675 b->icon_file = seekright(&s);
1676 if (b->icon_file && b->icon_file &&
1677 ((b->icon_file)[0] != '-'||(b->icon_file)[1] != 0))
1678 {
1679 b->flags.b_Icon = 1;
1680 }
1681 else if (b->icon_file)
1682 {
1683 free(b->icon_file);
1684 }
1685 }
1686 else
1687 {
1688 char *temp;
1689 temp = seekright(&s);
1690 if (temp)
1691 {
1692 free(temp);
1693 }
1694 }
1695
1696 s = trimleft(s);
1697
1698 /* Swallow hangon command */
1699 if (strncasecmp(s, "swallow", 7) == 0 || strncasecmp(s, "panel", 7) == 0)
1700 {
1701 if (b->flags.b_Swallow || b->flags.b_Panel)
1702 {
1703 fprintf(stderr,
1704 "%s: Illegal with both old and new swallow!\n",
1705 MyName);
1706 exit(1);
1707 }
1708 s += 7;
1709 /*
1710 * Swallow old 'swallowmodule' command
1711 */
1712 if (strncasecmp(s, "module", 6) == 0)
1713 {
1714 s += 6;
1715 }
1716 if (b->hangon)
1717 {
1718 free(b->hangon);
1719 }
1720 b->hangon = seekright(&s);
1721 if (!b->hangon)
1722 {
1723 b->hangon = safestrdup("");
1724 }
1725 if (tolower(*s) == 's')
1726 {
1727 b->flags.b_Swallow = 1;
1728 b->flags.b_Hangon = 1;
1729 }
1730 else
1731 {
1732 b->flags.b_Panel = 1;
1733 b->flags.b_Hangon = 1;
1734 }
1735 b->swallow |= 1;
1736 s = trimleft(s);
1737 if (!(b->swallow & b_NoHints))
1738 {
1739 b->hints = (XSizeHints*)mymalloc(sizeof(XSizeHints));
1740 }
1741 if (*s)
1742 {
1743 if (!(buttonSwallow(b) & b_UseOld))
1744 {
1745 SendText(fd, s, 0);
1746 }
1747 b->spawn = safestrdup(s);
1748 }
1749 }
1750 else if (*s)
1751 {
1752 AddButtonAction(b, 0, s);
1753 }
1754 return;
1755 }
1756
1757 /**
1758 *** ParseConfigLine
1759 **/
ParseConfigLine(button_info ** ubb,char * s)1760 static void ParseConfigLine(button_info **ubb, char *s)
1761 {
1762 button_info *ub = *ubb;
1763 char *opts[] =
1764 {
1765 "geometry",
1766 "buttongeometry",
1767 "font",
1768 "padding",
1769 "columns",
1770 "rows",
1771 "back",
1772 "fore",
1773 "frame",
1774 "file",
1775 "pixmap",
1776 "boxsize",
1777 "colorset",
1778 "activecolorset",
1779 "presscolorset",
1780 NULL
1781 };
1782 int i, j, k;
1783
1784 switch (GetTokenIndex(s, opts, -1, &s))
1785 {
1786 case 0:/* Geometry */
1787 {
1788 char geom[64];
1789
1790 i = sscanf(s, "%63s", geom);
1791 if (i == 1)
1792 {
1793 parse_window_geometry(geom, 0);
1794 }
1795 break;
1796 }
1797 case 1:/* ButtonGeometry */
1798 {
1799 char geom[64];
1800
1801 i = sscanf(s, "%63s", geom);
1802 if (i == 1)
1803 {
1804 parse_window_geometry(geom, 1);
1805 }
1806 break;
1807 }
1808 case 2:/* Font */
1809 if (ub->c->font_string)
1810 {
1811 free(ub->c->font_string);
1812 }
1813 CopyStringWithQuotes(&ub->c->font_string, s);
1814 break;
1815 case 3:/* Padding */
1816 i = sscanf(s, "%d %d", &j, &k);
1817 if (i > 0)
1818 {
1819 ub->c->xpad = ub->c->ypad = j;
1820 }
1821 if (i > 1)
1822 {
1823 ub->c->ypad = k;
1824 }
1825 break;
1826 case 4:/* Columns */
1827 i = sscanf(s, "%d", &j);
1828 if (i > 0)
1829 {
1830 ub->c->num_columns = j;
1831 }
1832 break;
1833 case 5:/* Rows */
1834 i = sscanf(s, "%d", &j);
1835 if (i > 0)
1836 {
1837 ub->c->num_rows = j;
1838 }
1839 break;
1840 case 6:/* Back */
1841 if (ub->c->back)
1842 {
1843 free(ub->c->back);
1844 }
1845 CopyString(&(ub->c->back), s);
1846 break;
1847 case 7:/* Fore */
1848 if (ub->c->fore)
1849 {
1850 free(ub->c->fore);
1851 }
1852 CopyString(&(ub->c->fore), s);
1853 break;
1854 case 8:/* Frame */
1855 i = sscanf(s,"%d",&j);
1856 if (i > 0)
1857 {
1858 ub->c->framew = j;
1859 }
1860 break;
1861 case 9:/* File */
1862 s = trimleft(s);
1863 if (config_file)
1864 {
1865 free(config_file);
1866 }
1867 config_file = seekright(&s);
1868 break;
1869 case 10:/* Pixmap */
1870 s = trimleft(s);
1871 if (strncasecmp(s, "none", 4) == 0)
1872 {
1873 ub->c->flags.b_TransBack = 1;
1874 }
1875 else
1876 {
1877 if (ub->c->back_file)
1878 {
1879 free(ub->c->back_file);
1880 }
1881 CopyString(&(ub->c->back_file),s);
1882 }
1883 ub->c->flags.b_IconBack = 1;
1884 break;
1885 case 11: /* BoxSize */
1886 ParseBoxSize(&s, &ub->c->flags);
1887 break;
1888 case 12: /* Colorset */
1889 i = sscanf(s, "%d", &j);
1890 if (i > 0)
1891 {
1892 ub->c->colorset = j;
1893 ub->c->flags.b_Colorset = 1;
1894 AllocColorset(j);
1895 }
1896 else
1897 {
1898 ub->c->flags.b_Colorset = 0;
1899 }
1900 break;
1901 case 13: /* ActiveColorset */
1902 i = sscanf(s, "%d", &j);
1903 if (i > 0)
1904 {
1905 ub->c->activeColorset = j;
1906 ub->c->flags.b_ActiveColorset = 1;
1907 AllocColorset(j);
1908 }
1909 else
1910 {
1911 ub->c->flags.b_ActiveColorset = 0;
1912 }
1913 break;
1914 case 14: /* PressColorset */
1915 i = sscanf(s, "%d", &j);
1916 if (i > 0)
1917 {
1918 ub->c->pressColorset = j;
1919 ub->c->flags.b_PressColorset = 1;
1920 AllocColorset(j);
1921 }
1922 else
1923 {
1924 ub->c->flags.b_PressColorset = 0;
1925 }
1926 break;
1927
1928 default:
1929 s = trimleft(s);
1930 ParseButton(ubb, s);
1931 break;
1932 }
1933 }
1934
1935 /**
1936 *** ParseConfigFile()
1937 *** Parses optional separate configuration file for FvwmButtons
1938 **/
ParseConfigFile(button_info * ub)1939 static void ParseConfigFile(button_info *ub)
1940 {
1941 char s[1024], *t;
1942 FILE *f = fopen(config_file, "r");
1943 int l;
1944 if (!f)
1945 {
1946 fprintf(stderr,
1947 "%s: Couldn't open config file %s\n", MyName,
1948 config_file);
1949 return;
1950 }
1951
1952 while (fgets(s, 1023, f))
1953 {
1954 /* Allow for line continuation: */
1955 while ((l = strlen(s)) < sizeof(s)
1956 && l >= 2 && s[l - 1] == '\n' && s[l - 2] == '\\')
1957 {
1958 char *p;
1959
1960 p = fgets(s + l - 2, sizeof(s) - l, f);
1961 (void)p;
1962 }
1963
1964 /* And comments: */
1965 t = s;
1966 while (*t)
1967 {
1968 if (*t == '#' && (t == s || *(t - 1) != '\\'))
1969 {
1970 *t = 0;
1971 break;
1972 }
1973 t++;
1974 }
1975 t = s;
1976 t = trimleft(t);
1977 if (*t)
1978 {
1979 ParseConfigLine(&ub, t);
1980 }
1981 }
1982
1983 fclose(f);
1984 }
1985
parse_window_geometry(char * geom,int is_button_geometry)1986 void parse_window_geometry(char *geom, int is_button_geometry)
1987 {
1988 int flags;
1989 int g_x;
1990 int g_y;
1991 unsigned int width;
1992 unsigned int height;
1993
1994 flags = FScreenParseGeometry(geom, &g_x, &g_y, &width, &height);
1995 UberButton->w = 0;
1996 UberButton->h = 0;
1997 UberButton->x = 0;
1998 UberButton->y = 0;
1999 if (is_button_geometry)
2000 {
2001 if (flags&WidthValue)
2002 {
2003 button_width = width;
2004 }
2005 if (flags&HeightValue)
2006 {
2007 button_height = height;
2008 }
2009 }
2010 else
2011 {
2012 if (flags&WidthValue)
2013 {
2014 w = width;
2015 }
2016 if (flags&HeightValue)
2017 {
2018 h = height;
2019 }
2020 }
2021 if (flags&XValue)
2022 {
2023 UberButton->x = g_x;
2024 }
2025 if (flags&YValue)
2026 {
2027 UberButton->y = g_y;
2028 }
2029 if (flags&XNegative)
2030 {
2031 UberButton->w = 1;
2032 }
2033 if (flags&YNegative)
2034 {
2035 UberButton->h = 1;
2036 }
2037 has_button_geometry = is_button_geometry;
2038
2039 return;
2040 }
2041
2042 /**
2043 *** ParseOptions()
2044 **/
ParseConfiguration(button_info * ub)2045 void ParseConfiguration(button_info *ub)
2046 {
2047 char *s;
2048 char *items[] =
2049 {
2050 NULL, /* filled out below */
2051 "imagepath",
2052 "colorset",
2053 XINERAMA_CONFIG_STRING,
2054 NULL
2055 };
2056
2057 items[0] = mymalloc(strlen(MyName) + 2);
2058 sprintf(items[0], "*%s", MyName);
2059
2060 /* send config lines with MyName */
2061 InitGetConfigLine(fd, items[0]);
2062 GetConfigLine(fd, &s);
2063 while (s && s[0])
2064 {
2065 char *rest;
2066 switch (GetTokenIndex(s,items,-1,&rest))
2067 {
2068 case -1:
2069 break;
2070 case 0:
2071 if (rest && rest[0] && !config_file)
2072 {
2073 ParseConfigLine(&ub, rest);
2074 }
2075 break;
2076 case 1:
2077 if (imagePath)
2078 {
2079 free(imagePath);
2080 }
2081 CopyString(&imagePath, rest);
2082 break;
2083 case 2:
2084 /* store colorset sent by fvwm */
2085 LoadColorset(rest);
2086 break;
2087 case 3:
2088 /* Xinerama state */
2089 FScreenConfigureModule(rest);
2090 break;
2091 }
2092 GetConfigLine(fd,&s);
2093 }
2094
2095 if (config_file)
2096 {
2097 ParseConfigFile(ub);
2098 }
2099
2100 free(items[0]);
2101 return;
2102 }
2103