Jitterbug no more.
[fvwm.git] / modules / FvwmButtons / parse.c
blob92a387549dc7e56ed2bca8453a5fc552f4965217
1 /* -*-c-*- */
2 /*
3 * FvwmButtons, copyright 1996, Jarl Totland
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
9 * Copyright 1993, Robert Nation. No guarantees or warantees or anything
10 * are provided or implied in any way whatsoever. Use this program at your
11 * own risk. Permission to use this program for any purpose is given,
12 * as long as the copyright is kept intact.
16 /* This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 #include "config.h"
33 #include <ctype.h>
34 #include <stdio.h>
36 #include <X11/Xlib.h>
37 #include <X11/Intrinsic.h>
39 #include "libs/fvwmlib.h"
40 #include "libs/FScreen.h"
41 #include "libs/Module.h"
42 #include "libs/Colorset.h"
43 #include "libs/Parse.h"
44 #include "libs/Strings.h"
45 #include "FvwmButtons.h"
46 #include "button.h"
47 #include "parse.h"
49 extern int w, h, x, y, xneg, yneg; /* used in ParseConfigLine */
50 extern char *config_file;
51 extern int button_width;
52 extern int button_height;
53 extern int has_button_geometry;
54 extern int screen;
56 /* contains the character that terminated the last string from seekright */
57 static char terminator = '\0';
59 /* ----------------------------------- macros ------------------------------ */
61 static char *trimleft(char *s)
63 while (s && isspace((unsigned char)*s))
65 s++;
67 return s;
70 /**
71 *** seekright()
72 ***
73 *** split off the first continous section of the string into a new allocated
74 *** string and move the old pointer forward. Accepts and strips quoting with
75 *** ['"`], and the current quote q can be escaped inside the string with \q.
76 **/
77 static char *seekright(char **s)
79 char *token = NULL;
80 char *line = *s;
82 line = DoGetNextToken(line, &token, NULL, "),", &terminator);
83 if (*s != NULL && line == NULL)
85 line = strchr(*s, '\0');
87 *s = line;
89 return token;
92 static char *my_get_font(char **s)
94 char *option;
95 int len;
97 *s = GetNextFullOption(*s, &option);
98 if (option)
100 for (len = strlen(option) - 1; len >= 0 && isspace(option[len]); len--)
102 /* remove trailing whitespace */
103 option[len] = 0;
105 for ( ; *option && isspace(*option); option++)
107 /* remove leading whitespace */
111 len = strlen(option) -1;
112 if (option[len] == ')' )
114 option[len] = 0;
117 return option;
121 *** ParseBack()
122 *** Parses the options possible to Back
123 *** This function appears to be obsolete & should be removed -- SS.
125 static int ParseBack(char **ss)
127 char *opts[] =
129 "icon",
130 NULL
132 char *t, *s = *ss;
133 int r = 0;
135 while (*s && *s != ')')
137 s = trimleft(s);
138 if (*s == ',')
140 s++;
141 continue;
144 switch (GetTokenIndex(s, opts, -1, &s))
146 case 0: /* Icon */
147 r = 1;
148 fprintf(stderr,
149 "%s: Back(Icon) not supported yet\n",
150 MyName);
151 break;
152 default:
153 t = seekright(&s);
154 fprintf(stderr,
155 "%s: Illegal back option \"%s\"\n",
156 MyName, (t) ? t : "");
157 if (t)
159 free(t);
163 if (*s)
165 s++;
167 *ss = s;
169 return r;
173 *** ParseBoxSize()
174 *** Parses the options possible to BoxSize
176 static void ParseBoxSize(char **ss, flags_type *flags)
178 char *opts[] =
180 "dumb",
181 "fixed",
182 "smart",
183 NULL
185 char *s = *ss;
186 int m;
188 if (!s)
190 return;
192 *ss = GetNextTokenIndex(*ss, opts, 0, &m);
193 switch (m)
195 case 0:
196 flags->b_SizeFixed = 0;
197 flags->b_SizeSmart = 0;
198 break;
199 case 1:
200 flags->b_SizeFixed = 1;
201 flags->b_SizeSmart = 0;
202 break;
203 case 2:
204 flags->b_SizeSmart = 1;
205 flags->b_SizeFixed = 0;
206 break;
207 default:
208 flags->b_SizeFixed = 0;
209 flags->b_SizeSmart = 0;
210 fprintf(stderr,
211 "%s: Illegal boxsize option \"%s\"\n",
212 MyName, s);
213 break;
215 return;
219 *** ParseTitle()
220 *** Parses the options possible to Title
222 static void ParseTitle(char **ss, byte *flags, byte *mask)
224 char *titleopts[] =
226 "left",
227 "right",
228 "center",
229 "side",
230 NULL
232 char *t, *s = *ss;
234 while (*s && *s != ')')
236 s = trimleft(s);
237 if (*s == ',')
239 s++;
240 continue;
243 switch (GetTokenIndex(s, titleopts, -1, &s))
245 case 0: /* Left */
246 *flags &= ~b_TitleHoriz;
247 *flags &= ~3;
248 *mask |= b_TitleHoriz;
249 break;
250 case 1: /* Right */
251 *flags &= ~b_TitleHoriz;
252 *flags &= ~3;
253 *flags |= 2;
254 *mask |= b_TitleHoriz;
255 break;
256 case 2: /* Center */
257 *flags &= ~b_TitleHoriz;
258 *flags &= ~3;
259 *flags |= 1;
260 *mask |= b_TitleHoriz;
261 break;
262 case 3: /* Side */
263 *flags |= b_Horizontal;
264 *flags &= ~3;
265 *mask |= b_Horizontal;
266 break;
267 default:
268 t = seekright(&s);
269 fprintf(stderr,
270 "%s: Illegal title option \"%s\"\n",
271 MyName, (t) ? t : "");
272 if (t)
274 free(t);
278 if (*s)
280 s++;
282 *ss = s;
286 *** ParseSwallow()
287 *** Parses the options possible to Swallow
289 static void ParseSwallow(
290 char **ss, unsigned int *flags, unsigned int *mask, button_info *b)
292 char *swallowopts[] =
294 "nohints", "hints",
295 "nokill", "kill",
296 "noclose", "close",
297 "respawn", "norespawn",
298 "useold", "noold",
299 "usetitle", "notitle",
300 "fvwmmodule", "nofvwmmodule",
301 "swallownew",
302 NULL
304 char *t, *s = *ss;
306 while (*s && *s != ')')
308 s = trimleft(s);
309 if (*s == ',')
311 s++;
312 continue;
315 switch (GetTokenIndex(s, swallowopts, -1, &s))
317 case 0: /* NoHints */
318 *flags |= b_NoHints;
319 *mask |= b_NoHints;
320 break;
321 case 1: /* Hints */
322 *flags &= ~b_NoHints;
323 *mask |= b_NoHints;
324 break;
325 case 2: /* NoKill */
326 *flags &= ~b_Kill;
327 *mask |= b_Kill;
328 break;
329 case 3: /* Kill */
330 *flags |= b_Kill;
331 *mask |= b_Kill;
332 break;
333 case 4: /* NoClose */
334 *flags |= b_NoClose;
335 *mask |= b_NoClose;
336 break;
337 case 5: /* Close */
338 *flags &= ~b_NoClose;
339 *mask |= b_NoClose;
340 break;
341 case 6: /* Respawn */
342 *flags |= b_Respawn;
343 *mask |= b_Respawn;
344 b->newflags.do_swallow_new = 0;
345 break;
346 case 7: /* NoRespawn */
347 *flags &= ~b_Respawn;
348 *mask |= b_Respawn;
349 b->newflags.do_swallow_new = 0;
350 break;
351 case 8: /* UseOld */
352 *flags |= b_UseOld;
353 *mask |= b_UseOld;
354 break;
355 case 9: /* NoOld */
356 *flags &= ~b_UseOld;
357 *mask |= b_UseOld;
358 break;
359 case 10: /* UseTitle */
360 *flags |= b_UseTitle;
361 *mask |= b_UseTitle;
362 break;
363 case 11: /* NoTitle */
364 *flags &= ~b_UseTitle;
365 *mask |= b_UseTitle;
366 break;
367 case 12: /* FvwmModule */
368 *flags |= b_FvwmModule;
369 *mask |= b_FvwmModule;
370 break;
371 case 13: /* NoFvwmModule */
372 *flags &= ~b_FvwmModule;
373 *mask |= b_FvwmModule;
374 break;
375 case 14: /* SwallowNew */
376 *flags &= ~b_Respawn;
377 *mask |= b_Respawn;
378 b->newflags.do_swallow_new = 1;
379 break;
380 default:
381 t = seekright(&s);
382 fprintf(stderr,
383 "%s: Illegal Swallow option \"%s\"\n", MyName,
384 (t) ? t : "");
385 if (t)
387 free(t);
391 if (*s)
393 s++;
395 *ss = s;
399 *** ParsePanel()
400 *** Parses the options possible to Panel
402 static void ParsePanel(
403 char **ss, unsigned int *flags, unsigned int *mask, char *direction,
404 int *steps, int *delay, panel_flags_type *panel_flags,
405 int *indicator_size, int *rela_x, int *rela_y, char *position,
406 char *context)
408 char *swallowopts[] =
410 "nohints", "hints",
411 "nokill", "kill",
412 "noclose", "close",
413 "respawn", "norespawn",
414 "useold", "noold",
415 "usetitle", "notitle",
416 "up", "down", "left", "right",
417 "steps",
418 "delay",
419 "smooth",
420 "noborder",
421 "indicator",
422 "position",
423 NULL
426 char *positionopts[] =
428 "button", "module", "root", "center", "left", "top", "right",
429 "bottom", "noplr", "noptb", "mlr", "mtb", NULL
432 char *t, *s = *ss;
433 int n;
435 while (*s && *s != ')')
437 s = trimleft(s);
438 if (*s == ',')
440 s++;
441 continue;
444 switch (GetTokenIndex(s, swallowopts, -1, &s))
446 case 0: /* NoHints */
447 *flags |= b_NoHints;
448 *mask |= b_NoHints;
449 break;
450 case 1: /* Hints */
451 *flags &= ~b_NoHints;
452 *mask |= b_NoHints;
453 break;
454 case 2: /* NoKill */
455 *flags &= ~b_Kill;
456 *mask |= b_Kill;
457 break;
458 case 3: /* Kill */
459 *flags |= b_Kill;
460 *mask |= b_Kill;
461 break;
462 case 4: /* NoClose */
463 *flags |= b_NoClose;
464 *mask |= b_NoClose;
465 break;
466 case 5: /* Close */
467 *flags &= ~b_NoClose;
468 *mask |= b_NoClose;
469 break;
470 case 6: /* Respawn */
471 *flags |= b_Respawn;
472 *mask |= b_Respawn;
473 break;
474 case 7: /* NoRespawn */
475 *flags &= ~b_Respawn;
476 *mask |= b_Respawn;
477 break;
478 case 8: /* UseOld */
479 *flags |= b_UseOld;
480 *mask |= b_UseOld;
481 break;
482 case 9: /* NoOld */
483 *flags &= ~b_UseOld;
484 *mask |= b_UseOld;
485 break;
486 case 10: /* UseTitle */
487 *flags |= b_UseTitle;
488 *mask |= b_UseTitle;
489 break;
490 case 11: /* NoTitle */
491 *flags &= ~b_UseTitle;
492 *mask |= b_UseTitle;
493 break;
494 case 12: /* up */
495 *direction = SLIDE_UP;
496 break;
497 case 13: /* down */
498 *direction = SLIDE_DOWN;
499 break;
500 case 14: /* left */
501 *direction = SLIDE_LEFT;
502 break;
503 case 15: /* right */
504 *direction = SLIDE_RIGHT;
505 break;
506 case 16: /* steps */
507 sscanf(s, "%d%n", steps, &n);
508 s += n;
509 break;
510 case 17: /* delay */
511 sscanf(s, "%d%n", delay, &n);
512 s += n;
513 break;
514 case 18: /* smooth */
515 (*panel_flags).smooth = 1;
516 break;
517 case 19: /* noborder */
518 (*panel_flags).ignore_lrborder = 1;
519 (*panel_flags).ignore_tbborder = 1;
520 break;
521 case 20: /* indicator */
522 n = 0;
523 (*panel_flags).panel_indicator = 1;
524 *indicator_size = 0;
525 sscanf(s, "%d%n", indicator_size, &n);
526 if (*indicator_size < 0 || *indicator_size > 100)
528 *indicator_size = 0;
530 s += n;
531 break;
532 case 21: /* position */
533 n = 0;
534 *rela_x = *rela_y = 0;
535 while (*s != ',' && *s != ')' && *s)
537 s = trimleft(s);
538 /* get x and y offset */
539 if (isdigit(*s) || *s == '+' || *s == '-')
541 sscanf(s, "%i%n", rela_x, &n);
542 s += n;
543 if (*s == 'p' || *s == 'P')
545 (*panel_flags).relative_x_pixel = 1;
546 s++;
548 n = 0;
549 s = trimleft(s);
550 sscanf(s, "%i%n", rela_y, &n);
551 s += n;
552 if (*s == 'p' || *s == 'P')
554 (*panel_flags).relative_y_pixel = 1;
555 s++;
557 s = trimleft(s);
559 switch (GetTokenIndex(s, positionopts, -1, &s))
561 case 0: /* button */
562 *context = SLIDE_CONTEXT_PB;
563 break;
564 case 1: /* module */
565 *context = SLIDE_CONTEXT_MODULE;
566 break;
567 case 2: /* root */
568 *context = SLIDE_CONTEXT_ROOT;
569 break;
570 case 3: /* center */
571 *position = SLIDE_POSITION_CENTER;
572 break;
573 case 4: /* left */
574 *position = SLIDE_POSITION_LEFT_TOP;
575 break;
576 case 5: /* top */
577 *position = SLIDE_POSITION_LEFT_TOP;
578 break;
579 case 6: /* right */
580 *position = SLIDE_POSITION_RIGHT_BOTTOM;
581 break;
582 case 7: /* bottom */
583 *position = SLIDE_POSITION_RIGHT_BOTTOM;
584 break;
585 case 8: /* noplr */
586 (*panel_flags).ignore_lrborder = 1;
587 break;
588 case 9: /* noptb */
589 (*panel_flags).ignore_tbborder = 1;
590 break;
591 case 10: /* mlr */
592 (*panel_flags).buttons_lrborder = 1;
593 break;
594 case 11: /* mtb */
595 (*panel_flags).buttons_tbborder = 1;
596 break;
597 default:
598 t = seekright(&s);
599 s--;
600 if (t)
602 fprintf(stderr,
603 "%s: Illegal Panel "
604 "position option %s\n",
605 MyName, (t) ? t : "");
606 free(t);
610 break;
611 default:
612 t = seekright(&s);
613 fprintf(stderr,
614 "%s: Illegal Panel option \"%s\"\n", MyName,
615 (t) ? t : "");
616 if (t)
618 free(t);
622 if (*s)
624 s++;
626 *ss = s;
630 *** ParseContainer()
631 *** Parses the options possible to Container
633 static void ParseContainer(char **ss,button_info *b)
635 char *conts[] =
637 "columns",
638 "rows",
639 "font",
640 "frame",
641 "back",
642 "fore",
643 "padding",
644 "title",
645 "swallow",
646 "nosize",
647 "size",
648 "boxsize",
649 "colorset",
650 NULL
652 char *t, *o, *s = *ss;
653 int i, j;
655 while (*s && *s != ')')
657 s = trimleft(s);
658 if (*s == ',')
660 s++;
661 continue;
664 switch (GetTokenIndex(s, conts, -1, &s))
666 case 0: /* Columns */
667 b->c->num_columns = max(1, strtol(s, &t, 10));
668 s = t;
669 break;
670 case 1: /* Rows */
671 b->c->num_rows = max(1, strtol(s, &t, 10));
672 s = t;
673 break;
674 case 2: /* Font */
675 if (b->c->font_string)
677 free(b->c->font_string);
679 b->c->font_string = my_get_font(&s);
680 b->c->flags.b_Font = (b->c->font_string ? 1 : 0);
681 break;
682 case 3: /* Frame */
683 b->c->framew = strtol(s, &t, 10);
684 b->c->flags.b_Frame = 1;
685 s = t;
686 break;
687 case 4: /* Back */
688 s = trimleft(s);
689 if (*s == '(' && s++ && ParseBack(&s))
691 b->c->flags.b_IconBack = 1;
693 if (b->c->back)
695 free(b->c->back);
697 b->c->back = seekright(&s);
698 if (b->c->back)
700 b->c->flags.b_Back = 1;
702 else
704 b->c->flags.b_IconBack = 0;
705 b->c->flags.b_Back = 0;
707 break;
708 case 5: /* Fore */
709 if (b->c->fore) free(b->c->fore);
710 b->c->fore = seekright(&s);
711 b->c->flags.b_Fore = (b->c->fore ? 1 : 0);
712 break;
713 case 6: /* Padding */
714 i = strtol(s, &t, 10);
715 if (t > s)
717 b->c->xpad = b->c->ypad = i;
718 s = t;
719 i = strtol(s, &t, 10);
720 if (t > s)
722 b->c->ypad = i;
723 s = t;
725 b->c->flags.b_Padding = 1;
727 else
728 fprintf(stderr,"%s: Illegal padding argument\n",MyName);
729 break;
730 case 7: /* Title - flags */
731 s = trimleft(s);
732 if (*s == '(' && s++)
734 b->c->justify = 0;
735 b->c->justify_mask = 0;
736 ParseTitle(&s, &b->c->justify, &b->c->justify_mask);
737 if (b->c->justify_mask)
739 b->c->flags.b_Justify = 1;
742 else
744 char *temp;
745 fprintf(stderr,
746 "%s: Illegal title in container options\n",
747 MyName);
748 temp = seekright(&s);
749 if (temp)
751 free(temp);
754 break;
755 case 8: /* Swallow - flags */
757 Bool failed = False;
759 s = trimleft(s);
760 if (b->c->flags.b_Swallow || b->c->flags.b_Panel)
762 fprintf(stderr, "%s: Multiple Swallow or Panel options are not"
763 " allowed in a single button", MyName);
764 failed = True;
766 else if (*s == '(' && s++)
768 b->c->swallow = 0;
769 b->c->swallow_mask = 0;
770 ParseSwallow(&s, &b->c->swallow, &b->c->swallow_mask, b);
771 if (b->c->swallow_mask)
773 b->c->flags.b_Swallow = 1;
776 else
778 fprintf(stderr,
779 "%s: Illegal swallow or panel in container options\n",
780 MyName);
781 failed = True;
783 if (failed)
785 char *temp;
787 temp = seekright(&s);
788 if (temp)
789 free(temp);
792 break;
793 case 9: /* NoSize */
794 b->c->flags.b_Size = 1;
795 b->c->minx = b->c->miny = 0;
796 break;
798 case 10: /* Size */
799 i = strtol(s, &t, 10);
800 j = strtol(t, &o, 10);
801 if (t > s && o > t)
803 b->c->minx = i;
804 b->c->miny = j;
805 b->c->flags.b_Size = 1;
806 s = o;
808 else
809 fprintf(stderr,"%s: Illegal size arguments\n",MyName);
810 break;
812 case 11: /* BoxSize */
813 ParseBoxSize(&s, &b->c->flags);
814 break;
816 case 12: /* Colorset */
817 i = strtol(s, &t, 10);
818 if (t > s)
820 b->c->colorset = i;
821 b->c->flags.b_Colorset = 1;
822 AllocColorset(i);
823 s = t;
825 else
827 b->c->flags.b_Colorset = 0;
829 break;
831 default:
832 t = seekright(&s);
833 fprintf(stderr,"%s: Illegal container option \"%s\"\n",MyName, (t)?t:"");
834 if (t)
835 free(t);
838 if (*s)
840 s++;
842 *ss = s;
846 *** ParseButton()
848 *** parse a buttonconfig string.
849 *** *FvwmButtons: (option[ options]) title iconname command
851 /*#define DEBUG_PARSER*/
852 static void ParseButton(button_info **uberb, char *s)
854 button_info *b, *ub = *uberb;
855 int i, j;
856 char *t, *o;
858 b = alloc_button(ub, (ub->c->num_buttons)++);
859 s = trimleft(s);
861 if (*s == '(' && s++)
863 char *opts[] =
865 "back",
866 "fore",
867 "font",
868 "title",
869 "icon",
870 "frame",
871 "padding",
872 "swallow",
873 "panel",
874 "actionignoresclientwindow",
875 "actiononpress",
876 "container",
877 "end",
878 "nosize",
879 "size",
880 "left",
881 "right",
882 "center",
883 "colorset",
884 "action",
885 "id",
886 "activeicon",
887 "activetitle",
888 "pressicon",
889 "presstitle",
890 "activecolorset",
891 "presscolorset",
892 "top",
893 NULL
895 s = trimleft(s);
896 while (*s && *s != ')')
898 Bool is_swallow = False;
900 if (*s == ',')
902 s++;
903 s = trimleft(s);
904 continue;
906 if (isdigit(*s) || *s == '+' || *s == '-')
908 char *geom;
909 int x, y, flags;
910 unsigned int w, h;
911 geom = seekright(&s);
912 if (geom)
914 flags = XParseGeometry(geom, &x, &y, &w, &h);
915 if (flags&WidthValue)
917 b->BWidth = w;
919 if (flags&HeightValue)
921 b->BHeight = h;
923 if (flags & XValue)
925 b->BPosX = x;
926 b->flags.b_PosFixed = 1;
928 if (flags & YValue)
930 b->BPosY = y;
931 b->flags.b_PosFixed = 1;
933 if (flags & XNegative)
935 b->BPosX = -1 - x;
937 if (flags & YNegative)
939 b->BPosY = -1 - y;
941 free(geom);
943 s = trimleft(s);
944 continue;
946 switch (GetTokenIndex(s, opts, -1, &s))
948 case 0: /* Back */
949 s = trimleft(s);
950 if (*s == '(' && s++ && ParseBack(&s))
952 b->flags.b_IconBack = 1;
954 if (b->flags.b_Back && b->back)
956 free(b->back);
958 b->back = seekright(&s);
959 if (b->back)
961 b->flags.b_Back = 1;
963 else
965 b->flags.b_IconBack = 0;
966 b->flags.b_Back = 0;
968 break;
970 case 1: /* Fore */
971 if (b->flags.b_Fore && b->fore)
973 free(b->fore);
975 b->fore = seekright(&s);
976 b->flags.b_Fore = (b->fore ? 1 : 0);
977 break;
979 case 2: /* Font */
980 if (b->flags.b_Font && b->font_string)
982 free(b->font_string);
984 b->font_string = my_get_font(&s);
985 b->flags.b_Font = (b->font_string ? 1 : 0);
986 break;
988 /* ----------------- title --------------- */
990 case 3: /* Title */
991 s = trimleft(s);
992 if (*s == '(' && s++)
994 b->justify = 0;
995 b->justify_mask = 0;
996 ParseTitle(
997 &s, &b->justify,
998 &b->justify_mask);
999 if (b->justify_mask)
1001 b->flags.b_Justify = 1;
1004 t = seekright(&s);
1005 if (t && *t && (t[0] != '-' || t[1] != 0))
1007 if (b->title)
1009 free(b->title);
1011 b->title = t;
1012 #ifdef DEBUG_PARSER
1013 fprintf(stderr,
1014 "PARSE: Title \"%s\"\n",
1015 b->title);
1016 #endif
1017 b->flags.b_Title = 1;
1019 else
1021 fprintf(stderr,
1022 "%s: Missing title argument\n",
1023 MyName);
1024 if (t)
1026 free(t);
1029 break;
1031 /* ------------------ icon --------------- */
1033 case 4: /* Icon */
1034 t = seekright(&s);
1035 if (t && *t && (t[0] != '-' || t[1] != 0))
1037 if (b->flags.b_Swallow)
1039 fprintf(stderr,
1040 "%s: a button can not "
1041 "have an icon and a "
1042 "swallowed window at "
1043 "the same time. "
1044 "Ignoring icon\n",
1045 MyName);
1047 else
1049 if (b->icon_file)
1051 free(b->icon_file);
1053 b->icon_file = t;
1054 b->flags.b_Icon = 1;
1057 else
1059 fprintf(stderr,
1060 "%s: Missing Icon argument\n",
1061 MyName);
1062 if (t)
1064 free(t);
1067 break;
1069 /* ----------------- frame --------------- */
1071 case 5: /* Frame */
1072 i = strtol(s, &t, 10);
1073 if (t > s)
1075 b->flags.b_Frame = 1;
1076 b->framew = i;
1077 s = t;
1079 else
1081 fprintf(stderr,
1082 "%s: Illegal frame argument\n",
1083 MyName);
1085 break;
1087 /* ---------------- padding -------------- */
1089 case 6: /* Padding */
1090 i = strtol(s,&t,10);
1091 if (t>s)
1093 b->xpad = b->ypad = i;
1094 b->flags.b_Padding = 1;
1095 s = t;
1096 i = strtol(s, &t, 10);
1097 if (t > s)
1099 b->ypad = i;
1100 s = t;
1103 else
1105 fprintf(stderr,
1106 "%s: Illegal padding "
1107 "argument\n", MyName);
1109 break;
1111 /* ---------------- swallow -------------- */
1113 case 7: /* Swallow */
1114 is_swallow = True;
1115 /* fall through */
1117 case 8: /* Panel */
1118 s = trimleft(s);
1119 if (is_swallow)
1121 b->swallow = 0;
1122 b->swallow_mask = 0;
1124 else
1126 /* set defaults */
1127 b->swallow = b_Respawn;
1128 b->swallow_mask = b_Respawn;
1129 b->slide_direction = SLIDE_UP;
1130 b->slide_position = SLIDE_POSITION_CENTER;
1131 b->slide_context = SLIDE_CONTEXT_PB;
1132 b->relative_x = 0;
1133 b->relative_y = 0;
1134 b->slide_steps = 12;
1135 b->slide_delay_ms = 5;
1137 if (*s == '(' && s++)
1139 if (is_swallow)
1141 ParseSwallow(
1142 &s, &b->swallow,
1143 &b->swallow_mask, b);
1145 else
1147 ParsePanel(
1148 &s, &b->swallow,
1149 &b->swallow_mask,
1150 &b->slide_direction,
1151 &b->slide_steps,
1152 &b->slide_delay_ms,
1153 &b->panel_flags,
1154 &b->indicator_size,
1155 &b->relative_x,
1156 &b->relative_y,
1157 &b->slide_position,
1158 &b->slide_context);
1161 t = seekright(&s);
1162 o = seekright(&s);
1163 if (t)
1165 if (b->hangon)
1167 free(b->hangon);
1169 b->hangon = t;
1170 if (is_swallow)
1172 if (b->flags.b_Icon)
1174 fprintf(stderr,
1175 "%s: a button can not "
1176 "have an icon and a "
1177 "swallowed window at "
1178 "the same time. "
1179 "Ignoring icon\n",
1180 MyName);
1181 b->flags.b_Icon = 0;
1184 b->flags.b_Swallow = 1;
1185 b->flags.b_Hangon = 1;
1187 else
1189 b->flags.b_Panel = 1;
1190 b->flags.b_Hangon = 1;
1191 b->newflags.is_panel = 1;
1192 b->newflags.panel_mapped = 0;
1194 b->swallow |= 1;
1195 if (!(b->swallow & b_NoHints))
1197 b->hints = (XSizeHints*)
1198 mymalloc(sizeof(XSizeHints));
1200 if (o)
1202 char *p;
1204 p = module_expand_action(
1205 Dpy, screen, o, NULL,
1206 UberButton->c->fore,
1207 UberButton->c->back);
1208 if (p)
1210 if (!(buttonSwallow(b)&b_UseOld))
1212 exec_swallow(p,b);
1214 if (b->spawn)
1216 free(b->spawn);
1219 /* Might be needed if
1220 * respawning sometime
1222 b->spawn = o;
1223 free(p);
1227 else
1229 fprintf(stderr,
1230 "%s: Missing swallow "
1231 "argument\n", MyName);
1232 if (t)
1234 free(t);
1236 if (o)
1238 free(o);
1241 /* check if it is a module by command line inspection if
1242 * this hints has not been given in the swallow option */
1243 if (is_swallow && !(b->swallow_mask & b_FvwmModule))
1245 if (b->spawn != NULL &&
1246 (strncasecmp(b->spawn, "module", 6) == 0 ||
1247 strncasecmp(b->spawn, "fvwm", 4) == 0))
1249 b->swallow |= b_FvwmModule;
1252 break;
1254 case 9: /* ActionIgnoresClientWindow */
1255 b->flags.b_ActionIgnoresClientWindow = 1;
1256 break;
1258 case 10: /* ActionOnPress */
1259 b->flags.b_ActionOnPress = 1;
1260 break;
1262 /* ---------------- container ------------ */
1264 case 11: /* Container */
1266 * SS: This looks very buggy! The FvwmButtons
1267 * man page suggests it's here to restrict the
1268 * options used with "Container", but it only
1269 * restricts those options appearing _before_
1270 * the "Container" keyword for a button.
1271 * b->flags&=b_Frame|b_Back|b_Fore|b_Padding|b_Action;
1274 MakeContainer(b);
1275 *uberb = b;
1276 s = trimleft(s);
1277 if (*s == '(' && s++)
1279 ParseContainer(&s,b);
1281 break;
1283 case 12: /* End */
1284 *uberb = ub->parent;
1285 ub->c->buttons[--(ub->c->num_buttons)] = NULL;
1286 free(b);
1287 if (!ub->parent)
1289 fprintf(stderr,"%s: Unmatched END in config file\n",MyName);
1290 exit(1);
1292 if (ub->parent->c->flags.b_Colorset ||
1293 ub->parent->c->flags.b_ColorsetParent)
1295 ub->c->flags.b_ColorsetParent = 1;
1297 if (ub->parent->c->flags.b_IconBack || ub->parent->c->flags.b_IconParent)
1299 ub->c->flags.b_IconParent = 1;
1301 return;
1303 case 13: /* NoSize */
1304 b->flags.b_Size = 1;
1305 b->minx = b->miny = 0;
1306 break;
1308 case 14: /* Size */
1309 i = strtol(s, &t, 10);
1310 j = strtol(t, &o, 10);
1311 if (t > s && o > t)
1313 b->minx = i;
1314 b->miny = j;
1315 b->flags.b_Size = 1;
1316 s = o;
1318 else
1320 fprintf(stderr,
1321 "%s: Illegal size arguments\n",
1322 MyName);
1324 break;
1326 case 15: /* Left */
1327 b->flags.b_Left = 1;
1328 b->flags.b_Right = 0;
1329 break;
1331 case 16: /* Right */
1332 b->flags.b_Right = 1;
1333 b->flags.b_Left = 0;
1334 break;
1336 case 17: /* Center */
1337 b->flags.b_Right = 0;
1338 b->flags.b_Left = 0;
1339 break;
1341 case 18: /* Colorset */
1342 i = strtol(s, &t, 10);
1343 if (t > s)
1345 b->colorset = i;
1346 b->flags.b_Colorset = 1;
1347 s = t;
1348 AllocColorset(i);
1350 else
1352 b->flags.b_Colorset = 0;
1354 break;
1356 /* ----------------- action -------------- */
1358 case 19: /* Action */
1359 s = trimleft(s);
1360 i = 0;
1361 if (*s == '(')
1363 s++;
1364 if (strncasecmp(s, "mouse", 5) != 0)
1366 fprintf(stderr,
1367 "%s: Couldn't parse "
1368 "action\n", MyName);
1370 s += 5;
1371 i = strtol(s, &t, 10);
1372 s = t;
1373 while (*s && *s != ')')
1375 s++;
1377 if (*s == ')')
1379 s++;
1383 char *r;
1384 char *u = s;
1386 s = GetQuotedString(s, &t, ",)", NULL, "(", ")");
1387 r = s;
1388 if (t && r > u + 1)
1390 /* remove unquoted trailing spaces */
1391 r -= 2;
1392 while (r >= u && isspace(*r))
1394 r--;
1396 r++;
1397 if (isspace(*r))
1399 t[strlen(t) - (s - r - 1)] = 0;
1403 if (t)
1405 AddButtonAction(b,i,t);
1406 free(t);
1408 else
1410 fprintf(stderr,
1411 "%s: Missing action argument\n",
1412 MyName);
1414 break;
1416 case 20: /* Id */
1417 s = trimleft(s);
1418 s = DoGetNextToken(s, &t, NULL, ",)", &terminator);
1420 /* it should include the delimiter */
1421 if (s && terminator == ')')
1423 s--;
1426 if (t)
1428 if (isalpha(t[0]))
1430 /* should check for duplicate ids first... */
1431 b->flags.b_Id = 1;
1432 if (b->id)
1434 free(b->id);
1436 CopyString(&b->id, t);
1438 else
1440 fprintf(stderr,
1441 "%s: Incorrect id '%s' "
1442 "ignored\n", MyName, t);
1444 free(t);
1446 else
1448 fprintf(stderr,
1449 "%s: Missing id argument\n",
1450 MyName);
1452 break;
1454 /* ------------------ ActiveIcon --------------- */
1455 case 21: /* ActiveIcon */
1456 t = seekright(&s);
1457 if (t && *t && (t[0] != '-' || t[1] != 0))
1459 if (b->flags.b_Swallow)
1461 fprintf(stderr,
1462 "%s: a button can not "
1463 "have a ActiveIcon and "
1464 "a swallowed window at "
1465 "the same time. "
1466 "Ignoring ActiveIcon.\n",
1467 MyName);
1469 else
1471 if (b->active_icon_file)
1473 free(b->active_icon_file);
1475 b->active_icon_file = t;
1476 b->flags.b_ActiveIcon = 1;
1479 else
1481 fprintf(stderr,
1482 "%s: Missing ActiveIcon "
1483 "argument\n", MyName);
1484 if (t)
1486 free(t);
1489 break;
1491 /* --------------- ActiveTitle --------------- */
1492 case 22: /* ActiveTitle */
1493 s = trimleft(s);
1494 if (*s == '(')
1496 fprintf(stderr,
1497 "%s: justification not allowed "
1498 "for ActiveTitle.\n", MyName);
1500 t = seekright(&s);
1501 if (t && *t && (t[0] != '-' || t[1] != 0))
1503 if (b->activeTitle)
1505 free(b->activeTitle);
1507 b->activeTitle = t;
1508 #ifdef DEBUG_PARSER
1509 fprintf(stderr,
1510 "PARSE: ActiveTitle \"%s\"\n",
1511 b->activeTitle);
1512 #endif
1513 b->flags.b_ActiveTitle = 1;
1515 else
1517 fprintf(stderr,
1518 "%s: Missing ActiveTitle "
1519 "argument\n", MyName);
1520 if (t)
1522 free(t);
1525 break;
1527 /* --------------- PressIcon --------------- */
1528 case 23: /* PressIcon */
1529 t = seekright(&s);
1530 if (t && *t && (t[0] != '-' || t[1] != 0))
1532 if (b->flags.b_Swallow)
1534 fprintf(stderr,
1535 "%s: a button can not "
1536 "have a PressIcon and "
1537 "a swallowed window at "
1538 "the same time. "
1539 "Ignoring PressIcon.\n",
1540 MyName);
1542 else
1544 if (b->press_icon_file)
1546 free(b->press_icon_file);
1548 b->press_icon_file = t;
1549 b->flags.b_PressIcon = 1;
1552 else
1554 fprintf(stderr,
1555 "%s: Missing PressIcon "
1556 "argument\n", MyName);
1557 if (t)
1559 free(t);
1562 break;
1564 /* --------------- PressTitle --------------- */
1565 case 24: /* PressTitle */
1566 s = trimleft(s);
1567 if (*s == '(')
1569 fprintf(stderr,
1570 "%s: justification not allowed "
1571 "for PressTitle.\n", MyName);
1573 t = seekright(&s);
1574 if (t && *t && (t[0] != '-' || t[1] != 0))
1576 if (b->pressTitle)
1578 free(b->pressTitle);
1580 b->pressTitle = t;
1581 #ifdef DEBUG_PARSER
1582 fprintf(stderr,
1583 "PARSE: PressTitle \"%s\"\n",
1584 b->pressTitle);
1585 #endif
1586 b->flags.b_PressTitle = 1;
1588 else
1590 fprintf(stderr,
1591 "%s: Missing PressTitle "
1592 "argument\n", MyName);
1593 if (t)
1595 free(t);
1598 break;
1600 /* --------------- --------------- */
1601 case 25: /* ActiveColorset */
1602 i = strtol(s, &t, 10);
1603 if (t > s)
1605 b->activeColorset = i;
1606 b->flags.b_ActiveColorset = 1;
1607 s = t;
1608 AllocColorset(i);
1610 else
1612 b->flags.b_ActiveColorset = 0;
1614 break;
1616 /* --------------- --------------- */
1617 case 26: /* PressColorset */
1618 i = strtol(s, &t, 10);
1619 if (t > s)
1621 b->pressColorset = i;
1622 b->flags.b_PressColorset = 1;
1623 s = t;
1624 AllocColorset(i);
1626 else
1628 b->flags.b_PressColorset = 0;
1630 break;
1632 case 27: /* top */
1633 b->flags.b_Top = 1;
1634 break;
1635 /* --------------- --------------- */
1636 default:
1637 t = seekright(&s);
1638 fprintf(stderr,
1639 "%s: Illegal button option \"%s\"\n",
1640 MyName, (t) ? t : "");
1641 if (t)
1643 free(t);
1645 break;
1646 } /* end switch */
1647 s = trimleft(s);
1649 if (s && *s)
1651 s++;
1652 s = trimleft(s);
1656 /* get title and iconname */
1657 if (!b->flags.b_Title)
1659 b->title = seekright(&s);
1660 if (b->title && *b->title &&
1661 ((b->title)[0] != '-' || (b->title)[1] != 0))
1663 b->flags.b_Title = 1;
1665 else if (b->title)
1667 free(b->title);
1670 else
1672 char *temp;
1673 temp = seekright(&s);
1674 if (temp)
1676 free(temp);
1680 if (!b->flags.b_Icon)
1682 b->icon_file = seekright(&s);
1683 if (b->icon_file && b->icon_file &&
1684 ((b->icon_file)[0] != '-'||(b->icon_file)[1] != 0))
1686 b->flags.b_Icon = 1;
1688 else if (b->icon_file)
1690 free(b->icon_file);
1693 else
1695 char *temp;
1696 temp = seekright(&s);
1697 if (temp)
1699 free(temp);
1703 s = trimleft(s);
1705 /* Swallow hangon command */
1706 if (strncasecmp(s, "swallow", 7) == 0 || strncasecmp(s, "panel", 7) == 0)
1708 if (b->flags.b_Swallow || b->flags.b_Panel)
1710 fprintf(stderr,
1711 "%s: Illegal with both old and new swallow!\n",
1712 MyName);
1713 exit(1);
1715 s += 7;
1717 * Swallow old 'swallowmodule' command
1719 if (strncasecmp(s, "module", 6) == 0)
1721 s += 6;
1723 if (b->hangon)
1725 free(b->hangon);
1727 b->hangon = seekright(&s);
1728 if (!b->hangon)
1730 b->hangon = safestrdup("");
1732 if (tolower(*s) == 's')
1734 b->flags.b_Swallow = 1;
1735 b->flags.b_Hangon = 1;
1737 else
1739 b->flags.b_Panel = 1;
1740 b->flags.b_Hangon = 1;
1742 b->swallow |= 1;
1743 s = trimleft(s);
1744 if (!(b->swallow & b_NoHints))
1746 b->hints = (XSizeHints*)mymalloc(sizeof(XSizeHints));
1748 if (*s)
1750 if (!(buttonSwallow(b) & b_UseOld))
1752 SendText(fd, s, 0);
1754 b->spawn = safestrdup(s);
1757 else if (*s)
1759 AddButtonAction(b, 0, s);
1761 return;
1765 *** ParseConfigLine
1767 static void ParseConfigLine(button_info **ubb, char *s)
1769 button_info *ub = *ubb;
1770 char *opts[] =
1772 "geometry",
1773 "buttongeometry",
1774 "font",
1775 "padding",
1776 "columns",
1777 "rows",
1778 "back",
1779 "fore",
1780 "frame",
1781 "file",
1782 "pixmap",
1783 "boxsize",
1784 "colorset",
1785 "activecolorset",
1786 "presscolorset",
1787 NULL
1789 int i, j, k;
1791 switch (GetTokenIndex(s, opts, -1, &s))
1793 case 0:/* Geometry */
1795 char geom[64];
1797 i = sscanf(s, "%63s", geom);
1798 if (i == 1)
1800 parse_window_geometry(geom, 0);
1802 break;
1804 case 1:/* ButtonGeometry */
1806 char geom[64];
1808 i = sscanf(s, "%63s", geom);
1809 if (i == 1)
1811 parse_window_geometry(geom, 1);
1813 break;
1815 case 2:/* Font */
1816 if (ub->c->font_string)
1818 free(ub->c->font_string);
1820 CopyStringWithQuotes(&ub->c->font_string, s);
1821 break;
1822 case 3:/* Padding */
1823 i = sscanf(s, "%d %d", &j, &k);
1824 if (i > 0)
1826 ub->c->xpad = ub->c->ypad = j;
1828 if (i > 1)
1830 ub->c->ypad = k;
1832 break;
1833 case 4:/* Columns */
1834 i = sscanf(s, "%d", &j);
1835 if (i > 0)
1837 ub->c->num_columns = j;
1839 break;
1840 case 5:/* Rows */
1841 i = sscanf(s, "%d", &j);
1842 if (i > 0)
1844 ub->c->num_rows = j;
1846 break;
1847 case 6:/* Back */
1848 if (ub->c->back)
1850 free(ub->c->back);
1852 CopyString(&(ub->c->back), s);
1853 break;
1854 case 7:/* Fore */
1855 if (ub->c->fore)
1857 free(ub->c->fore);
1859 CopyString(&(ub->c->fore), s);
1860 break;
1861 case 8:/* Frame */
1862 i = sscanf(s,"%d",&j);
1863 if (i > 0)
1865 ub->c->framew = j;
1867 break;
1868 case 9:/* File */
1869 s = trimleft(s);
1870 if (config_file)
1872 free(config_file);
1874 config_file = seekright(&s);
1875 break;
1876 case 10:/* Pixmap */
1877 s = trimleft(s);
1878 if (strncasecmp(s, "none", 4) == 0)
1880 ub->c->flags.b_TransBack = 1;
1882 else
1884 if (ub->c->back_file)
1886 free(ub->c->back_file);
1888 CopyString(&(ub->c->back_file),s);
1890 ub->c->flags.b_IconBack = 1;
1891 break;
1892 case 11: /* BoxSize */
1893 ParseBoxSize(&s, &ub->c->flags);
1894 break;
1895 case 12: /* Colorset */
1896 i = sscanf(s, "%d", &j);
1897 if (i > 0)
1899 ub->c->colorset = j;
1900 ub->c->flags.b_Colorset = 1;
1901 AllocColorset(j);
1903 else
1905 ub->c->flags.b_Colorset = 0;
1907 break;
1908 case 13: /* ActiveColorset */
1909 i = sscanf(s, "%d", &j);
1910 if (i > 0)
1912 ub->c->activeColorset = j;
1913 ub->c->flags.b_ActiveColorset = 1;
1914 AllocColorset(j);
1916 else
1918 ub->c->flags.b_ActiveColorset = 0;
1920 break;
1921 case 14: /* PressColorset */
1922 i = sscanf(s, "%d", &j);
1923 if (i > 0)
1925 ub->c->pressColorset = j;
1926 ub->c->flags.b_PressColorset = 1;
1927 AllocColorset(j);
1929 else
1931 ub->c->flags.b_PressColorset = 0;
1933 break;
1935 default:
1936 s = trimleft(s);
1937 ParseButton(ubb, s);
1938 break;
1943 *** ParseConfigFile()
1944 *** Parses optional separate configuration file for FvwmButtons
1946 static void ParseConfigFile(button_info *ub)
1948 char s[1024], *t;
1949 FILE *f = fopen(config_file, "r");
1950 int l;
1951 if (!f)
1953 fprintf(stderr,
1954 "%s: Couldn't open config file %s\n", MyName,
1955 config_file);
1956 return;
1959 while (fgets(s, 1023, f))
1961 /* Allow for line continuation: */
1962 while ((l = strlen(s)) < sizeof(s)
1963 && l >= 2 && s[l - 1] == '\n' && s[l - 2] == '\\')
1965 fgets(s + l - 2, sizeof(s) - l, f);
1968 /* And comments: */
1969 t = s;
1970 while (*t)
1972 if (*t == '#' && (t == s || *(t - 1) != '\\'))
1974 *t = 0;
1975 break;
1977 t++;
1979 t = s;
1980 t = trimleft(t);
1981 if (*t)
1983 ParseConfigLine(&ub, t);
1987 fclose(f);
1990 void parse_window_geometry(char *geom, int is_button_geometry)
1992 int flags;
1993 int g_x;
1994 int g_y;
1995 unsigned int width;
1996 unsigned int height;
1998 flags = FScreenParseGeometry(geom, &g_x, &g_y, &width, &height);
1999 UberButton->w = 0;
2000 UberButton->h = 0;
2001 UberButton->x = 0;
2002 UberButton->y = 0;
2003 if (is_button_geometry)
2005 if (flags&WidthValue)
2007 button_width = width;
2009 if (flags&HeightValue)
2011 button_height = height;
2014 else
2016 if (flags&WidthValue)
2018 w = width;
2020 if (flags&HeightValue)
2022 h = height;
2025 if (flags&XValue)
2027 UberButton->x = g_x;
2029 if (flags&YValue)
2031 UberButton->y = g_y;
2033 if (flags&XNegative)
2035 UberButton->w = 1;
2037 if (flags&YNegative)
2039 UberButton->h = 1;
2041 has_button_geometry = is_button_geometry;
2043 return;
2047 *** ParseOptions()
2049 void ParseConfiguration(button_info *ub)
2051 char *s;
2052 char *items[] =
2054 NULL, /* filled out below */
2055 "imagepath",
2056 "colorset",
2057 XINERAMA_CONFIG_STRING,
2058 NULL
2061 items[0] = mymalloc(strlen(MyName) + 2);
2062 sprintf(items[0], "*%s", MyName);
2064 /* send config lines with MyName */
2065 InitGetConfigLine(fd, items[0]);
2066 GetConfigLine(fd, &s);
2067 while (s && s[0])
2069 char *rest;
2070 switch (GetTokenIndex(s,items,-1,&rest))
2072 case -1:
2073 break;
2074 case 0:
2075 if (rest && rest[0] && !config_file)
2077 ParseConfigLine(&ub, rest);
2079 break;
2080 case 1:
2081 if (imagePath)
2083 free(imagePath);
2085 CopyString(&imagePath, rest);
2086 break;
2087 case 2:
2088 /* store colorset sent by fvwm */
2089 LoadColorset(rest);
2090 break;
2091 case 3:
2092 /* Xinerama state */
2093 FScreenConfigureModule(rest);
2094 break;
2096 GetConfigLine(fd,&s);
2099 if (config_file)
2101 ParseConfigFile(ub);
2104 free(items[0]);
2105 return;