2 * parse.c -- Functions for parsing splashutils cfg files
4 * Copyright (C) 2004-2008, Michal Januszewski <spock@gentoo.org>
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License v2. See the file COPYING in the main directory of this archive for
23 t_int
, t_path
, t_box
, t_icon
, t_rect
, t_color
, t_fontpath
,
24 t_type_open
, t_type_close
, t_anim
, t_text
, t_textbox_open
, t_textbox_close
,
38 static bool is_textbox
= false;
40 /* Note that pic256 and silentpic256 have to be located before pic and
41 * silentpic or we are gonna get a parse error @ pic256/silentpic256. */
42 struct cfg_opt opts
[] =
46 .val
= &tmptheme
.pic
},
50 .val
= &tmptheme
.pic256
},
52 { .name
= "silentpic256",
54 .val
= &tmptheme
.silentpic256
},
56 { .name
= "silentjpeg",
58 .val
= &tmptheme
.silentpic
},
62 .val
= &tmptheme
.pic
},
64 { .name
= "silentpic",
66 .val
= &tmptheme
.silentpic
},
70 .val
= &tmptheme
.bg_color
},
74 .val
= &tmptheme
.tx
},
78 .val
= &tmptheme
.ty
},
82 .val
= &tmptheme
.tw
},
86 .val
= &tmptheme
.th
},
105 .type
= t_type_close
,
108 { .name
= "<textbox>",
109 .type
= t_textbox_open
,
112 { .name
= "</textbox>",
113 .type
= t_textbox_close
,
122 { .name
= "log_lines",
124 .val
= &tmptheme
.log_lines
},
126 { .name
= "log_cols",
128 .val
= &tmptheme
.log_cols
},
138 { .name
= "text_size",
142 { .name
= "text_color",
144 .val
= &text_color
},
146 { .name
= "text_font",
157 #define parse_error(msg, args...) \
159 iprint(MSG_ERROR, "Parse error at '%s', line %d: " msg "\n", curr_cfgfile, line, ## args); \
162 #define checknskip(label, req, msg, args...) \
165 iprint(MSG_ERROR, "Parse error at '%s', line %d: " msg "\n", curr_cfgfile, line, ## args); \
169 if (!skip_whitespace(&t, req)) \
173 static char *get_filepath(char *path
)
180 snprintf(buf
, 512, FBSPL_THEME_DIR
"/%s/%s", config
.theme
, path
);
184 static int ishexdigit(char c
)
186 return (isdigit(c
) || (c
>= 'A' && c
<= 'F') || (c
>= 'a' && c
<= 'f')) ? 1 : 0;
189 static bool skip_whitespace(char **buf
, bool req
)
191 if (req
&& (**buf
!= ' ' && **buf
!= '\t' && **buf
)) {
192 parse_error("expected a non-zero amount of whitespace instead of '%s'", *buf
);
198 while ((**buf
== ' ' || **buf
== '\t') && **buf
)
204 static bool skip_nonwhitespace(char **buf
, bool req
)
206 if (req
&& ((**buf
== ' ' || **buf
== '\t') && **buf
)) {
207 parse_error("expected a non-zero amount of non-whitespace instead of '%s'", *buf
);
213 while ((**buf
!= ' ' && **buf
!= '\t') && **buf
)
219 static void parse_int(char *t
, struct cfg_opt opt
)
222 parse_error("expected '=' instead of '%c'", *t
);
226 t
++; skip_whitespace(&t
, false);
227 *(u16
*)opt
.val
= strtol(t
,NULL
,0);
230 static void parse_path(char *t
, struct cfg_opt opt
)
233 parse_error("expected '=' instead of'%c'", *t
);
237 t
++; skip_whitespace(&t
, false);
238 *(char**)opt
.val
= get_filepath(t
);
241 static char *get_fontpath(char *t
)
245 struct stat st1
, st2
;
251 snprintf(buf
, 512, "%s/%s/%s", FBSPL_THEME_DIR
, config
.theme
, t
);
252 snprintf(buf2
, 512, "%s/%s", FBSPL_THEME_DIR
, t
);
257 if (S_ISREG(st1
.st_mode
) || S_ISLNK(st1
.st_mode
)) {
259 } else if (S_ISREG(st2
.st_mode
) || S_ISLNK(st2
.st_mode
)) {
268 static void parse_fontpath(char *t
, struct cfg_opt opt
)
271 parse_error("expected '=' instead of '%c'", *t
);
275 t
++; skip_whitespace(&t
, false);
276 *(char**)opt
.val
= get_fontpath(t
);
279 static int parse_color(char **t
, struct color
*cl
)
285 if (strncmp(*t
, "0x", 2))
293 for (p
= *t
; ishexdigit(*p
); p
++, len
++);
295 if (len
!= 6 && len
!= 8)
299 h
= strtoul(*t
, &p
, 16);
305 cl
->r
= (h
>> 24) & 0xff;
306 cl
->g
= (h
>> 16) & 0xff;
307 cl
->b
= (h
>> 8) & 0xff;
310 cl
->r
= (h
>> 16) & 0xff;
311 cl
->g
= (h
>> 8 ) & 0xff;
320 static int parse_4vec(char **t
, rect
*r
)
328 skip_whitespace(t
, false);
331 r
->x1
= strtol(p
, t
, 0);
334 skip_whitespace(t
, false);
340 r
->y1
= strtol(p
, t
, 0);
343 skip_whitespace(t
, false);
349 r
->x2
= strtol(p
, t
, 0);
352 skip_whitespace(t
, false);
358 r
->y2
= strtol(p
, t
, 0);
362 skip_whitespace(t
, false);
370 int parse_svc_state(char *t
, enum ESVC
*state
)
372 if (!strncmp(t
, "svc_inactive_start", 18)) {
373 *state
= e_svc_inact_start
; return 18;
374 } else if (!strncmp(t
, "svc_inactive_stop", 17)) {
375 *state
= e_svc_inact_stop
; return 17;
376 } else if (!strncmp(t
, "svc_started", 11)) {
377 *state
= e_svc_started
; return 11;
378 } else if (!strncmp(t
, "svc_stopped", 11)) {
379 *state
= e_svc_stopped
; return 11;
380 } else if (!strncmp(t
, "svc_start_failed", 16)) {
381 *state
= e_svc_start_failed
; return 16;
382 } else if (!strncmp(t
, "svc_stop_failed", 15)) {
383 *state
= e_svc_stop_failed
; return 15;
384 } else if (!strncmp(t
, "svc_stop", 8)) {
385 *state
= e_svc_stop
; return 8;
386 } else if (!strncmp(t
, "svc_start", 9)) {
387 *state
= e_svc_start
; return 9;
393 void obj_add(void *x
) {
394 obj
*o
= container_of(x
);
396 if (tmptheme
.objs
.tail
)
397 o
->id
= ((obj
*)(tmptheme
.objs
.tail
->p
))->id
+ 1;
401 list_add(&tmptheme
.objs
, o
);
404 list_add(&tmptheme
.textbox
, o
);
407 bool parse_effects(char *t
, obj
*o
)
410 skip_whitespace(&t
, false);
412 while (isalpha(*t
)) {
413 if (!strncmp(t
, "blendin(", 8)) {
415 o
->blendin
= strtol(t
, &p
, 0);
416 checknskip(pe_err
, false, "expected a number instead of '%s'", t
);
418 parse_error("expected ')' instead of '%s'", t
);
422 } else if (!strncmp(t
, "blendout(", 9)) {
424 o
->blendout
= strtol(t
, &p
, 0);
425 checknskip(pe_err
, false, "expected a number instead of '%s'", t
);
427 parse_error("expected ')' instead of '%s'", t
);
432 parse_error("expected 'blendin(..)' or 'blendout(..)' instead of '%s'", t
);
437 skip_whitespace(&t
, false);
443 bool parse_icon(char *t
)
445 char *filename
= NULL
;
448 icon
*cic
= obj_alloc(icon
, FBSPL_MODE_SILENT
);
454 iprint(MSG_ERROR
, "%s: failed to allocate memory.\n", __func__
);
458 o
= container_of(cic
);
461 if (!skip_whitespace(&t
, true))
464 for (i
= 0; t
[i
] != ' ' && t
[i
] != '\t' && t
[i
] != '\0'; i
++);
467 filename
= get_filepath(t
);
470 skip_whitespace(&t
, false);
471 cic
->x
= strtol(t
, &p
, 0);
472 checknskip(pi_err
, true, "expected a number instead of '%s'", t
);
474 cic
->y
= strtol(t
,&p
,0);
475 checknskip(pi_err
, true, "expected a number instead of '%s'", t
);
477 /* Do we need to crop this icon? */
478 if (!strncmp(t
, "crop", 4)) {
481 if (!skip_whitespace(&t
, true))
484 if (parse_4vec(&t
, &cic
->crop_from
)) {
485 parse_error("expected a 4-tuple instead of '%s'", t
);
489 if (!skip_whitespace(&t
, true))
492 if (parse_4vec(&t
, &cic
->crop_to
)) {
493 parse_error("expected a 4-tuple instead of '%s'", t
);
497 if (!skip_whitespace(&t
, true))
501 rect_interpolate(&cic
->crop_from
, &cic
->crop_to
, &cic
->crop_curr
);
506 i
= parse_svc_state(t
, &cic
->type
);
509 cic
->type
= e_display
;
513 /* Find the service name */
514 if (!skip_whitespace(&t
, true))
516 for (i
= 0; t
[i
] != ' ' && t
[i
] != '\t' && t
[i
] != '\0'; i
++);
522 parse_error("expected service name");
526 cic
->svc
= strdup(t
);
530 if (!parse_effects(t
, o
))
533 for (ti
= tmptheme
.icons
.head
; ti
!= NULL
; ti
= ti
->next
) {
534 icon_img
*ii
= (icon_img
*) ti
->p
;
536 if (!strcmp(ii
->filename
, filename
)) {
542 /* Allocate a new entry in the icons list */
543 cim
= malloc(sizeof(icon_img
));
546 cim
->filename
= filename
;
549 list_add(&tmptheme
.icons
, cim
);
562 free(container_of(cic
));
565 iprint(MSG_ERROR
, "%s: failed to allocate memory\n", __func__
);
569 void parse_rect(char *t
)
572 rect
*crect
= malloc(sizeof(rect
));
575 iprint(MSG_ERROR
, "%s: failed to allocate memory\n", __func__
);
579 skip_whitespace(&t
, true);
581 while (!isdigit(*t
)) {
585 crect
->x1
= strtol(t
, &p
, 0);
586 checknskip(pr_err
, true, "expected a number instead of '%s'", t
);
588 crect
->y1
= strtol(t
, &p
, 0);
589 checknskip(pr_err
, true, "expected a number instead of '%s'", t
);
591 crect
->x2
= strtol(t
,&p
,0);
592 checknskip(pr_err
, true, "expected a number instead of '%s'", t
);
594 crect
->y2
= strtol(t
,&p
,0);
595 checknskip(pr_err
, true, "expected a number instead of '%s'", t
);
598 if (crect
->x1
>= tmptheme
.xres
)
599 crect
->x1
= tmptheme
.xres
-1;
600 if (crect
->x2
>= tmptheme
.xres
)
601 crect
->x2
= tmptheme
.xres
-1;
602 if (crect
->y1
>= tmptheme
.yres
)
603 crect
->y1
= tmptheme
.yres
-1;
604 if (crect
->y2
>= tmptheme
.yres
)
605 crect
->y2
= tmptheme
.yres
-1;
607 list_add(&tmptheme
.rects
, crect
);
615 bool parse_anim(char *t
)
619 anim
*canim
= obj_alloc(anim
, FBSPL_MODE_SILENT
);
624 iprint(MSG_ERROR
, "%s: failed to allocate memory\n", __func__
);
628 o
= container_of(canim
);
629 obj_setmode(container_of(canim
), FBSPL_MODE_SILENT
);
631 if (!skip_whitespace(&t
, true))
636 if (!strncmp(t
, "once", 4)) {
637 canim
->flags
|= F_ANIM_ONCE
;
639 } else if (!strncmp(t
, "loop", 4)) {
640 canim
->flags
|= F_ANIM_LOOP
;
642 } else if (!strncmp(t
, "proportional", 12)) {
643 canim
->flags
|= F_ANIM_PROPORTIONAL
;
646 parse_error("an anim has to be flagged with one of the following:\n"
647 "'once', 'loop' or 'proportional' (got '%s' instead)", t
);
651 if (!skip_whitespace(&t
, true))
656 if (!skip_nonwhitespace(&t
, true))
661 /* We don't require whitespace, as we already had one which
662 * we have just replaced with 0. */
663 skip_whitespace(&t
, false);
665 canim
->x
= strtol(t
, &p
, 0);
666 checknskip(pa_err
, true, "expected a number instead of '%s'", t
);
668 canim
->y
= strtol(t
, &p
, 0);
669 checknskip(pa_err
, true, "expected a number instead of '%s'", t
);
672 if (canim
->x
>= tmptheme
.xres
)
673 canim
->x
= tmptheme
.xres
-1;
674 if (canim
->y
>= tmptheme
.yres
)
675 canim
->y
= tmptheme
.yres
-1;
679 i
= parse_svc_state(t
, &canim
->type
);
681 canim
->type
= e_display
;
685 /* Find the service name */
686 skip_whitespace(&t
, true);
687 for (i
= 0; t
[i
] != ' ' && t
[i
] != '\t' && t
[i
] != '\0'; i
++);
694 parse_error("expected service name");
698 canim
->svc
= strdup(t
);
699 if (!skip_nonwhitespace(&t
, true))
703 if (!parse_effects(t
, o
))
706 canim
->filename
= get_filepath(filename
);
707 list_add(&tmptheme
.anims
, canim
);
711 free(container_of(canim
));
714 #endif /* WANT_MNG */
716 box
* parse_box(char *t
)
720 box
*cbox
= obj_alloc(box
, FBSPL_MODE_VERBOSE
);
725 if (!skip_whitespace(&t
, true))
731 while (!isdigit(*t
)) {
732 if (!strncmp(t
,"noover",6)) {
733 cbox
->attr
|= BOX_NOOVER
;
735 } else if (!strncmp(t
, "inter", 5)) {
736 cbox
->attr
|= BOX_INTER
;
738 } else if (!strncmp(t
, "silent", 6)) {
739 obj_setmode(container_of(cbox
), FBSPL_MODE_SILENT
);
742 parse_error("expected 'noover', 'inter' or 'silent' instead of '%s'", t
);
746 skip_whitespace(&t
, false);
749 cbox
->re
.x1
= strtol(t
, &p
, 0);
750 checknskip(pb_err
, true, "expected a number instead of '%s'", t
);
752 cbox
->re
.y1
= strtol(t
, &p
, 0);
753 checknskip(pb_err
, true, "expected a number instead of '%s'", t
);
755 cbox
->re
.x2
= strtol(t
, &p
, 0);
756 checknskip(pb_err
, true, "expected a number instead of '%s'", t
);
758 cbox
->re
.y2
= strtol(t
, &p
, 0);
759 checknskip(pb_err
, true, "expected a number instead of '%s'", t
);
762 if (cbox
->re
.x1
>= tmptheme
.xres
)
763 cbox
->re
.x1
= tmptheme
.xres
-1;
764 if (cbox
->re
.x2
>= tmptheme
.xres
)
765 cbox
->re
.x2
= tmptheme
.xres
-1;
766 if (cbox
->re
.y1
>= tmptheme
.yres
)
767 cbox
->re
.y1
= tmptheme
.yres
-1;
768 if (cbox
->re
.y2
>= tmptheme
.yres
)
769 cbox
->re
.y2
= tmptheme
.yres
-1;
771 if (cbox
->re
.x2
< cbox
->re
.x1
) {
772 parse_error("x2 has to be larger or equal to x1");
776 if (cbox
->re
.y2
< cbox
->re
.y1
) {
777 parse_error("y2 has to be larger or equal to y1");
781 #define zero_color(cl) *(u32*)(&cl) = 0;
782 #define is_zero_color(cl) (*(u32*)(&cl) == 0)
783 #define assign_color(c1, c2) *(u32*)(&c1) = *(u32*)(&c2);
785 zero_color(cbox
->c_ul
);
786 zero_color(cbox
->c_ur
);
787 zero_color(cbox
->c_ll
);
788 zero_color(cbox
->c_lr
);
790 if (parse_color(&t
, &cbox
->c_ul
)) {
791 parse_error("expected a color instead of '%s'", t
);
795 skip_whitespace(&t
, false);
797 ret
= parse_color(&t
, &cbox
->c_ur
);
800 assign_color(cbox
->c_ur
, cbox
->c_ul
);
801 assign_color(cbox
->c_lr
, cbox
->c_ul
);
802 assign_color(cbox
->c_ll
, cbox
->c_ul
);
804 } else if (ret
== -2) {
805 parse_error("failed to parse color");
809 if (!skip_whitespace(&t
, true))
812 if (parse_color(&t
, &cbox
->c_ll
)) {
813 parse_error("expected a color instead of '%s'", t
);
817 if (!skip_whitespace(&t
, true))
820 if (parse_color(&t
, &cbox
->c_lr
)) {
821 parse_error("expected a color instead of '%s'", t
);
826 if (!parse_effects(t
, container_of(cbox
)))
832 free(container_of(cbox
));
836 static char *parse_quoted_string(char *t
, u8 keepvar
)
849 while ((*p
!= '"' || *(p
-1) == '\\') && *p
!= 0) {
864 out
= malloc(len
- cnt
+ 1);
866 iprint(MSG_ERROR
, "Failed to allocate memory for a quoted string.\n");
870 for (i
= 0; i
< len
; i
++, t
++) {
871 if (*t
== '\\' && i
< len
-1) {
884 bool parse_text(char *t
)
886 char *p
, *fontname
= NULL
, *fpath
= NULL
;
888 text
*ct
= obj_alloc(text
, 0);
894 iprint(MSG_ERROR
, "%s: failed to allocate memory\n", __func__
);
898 if (!skip_whitespace(&t
, true))
904 ct
->style
= TTF_STYLE_NORMAL
;
907 while (!isdigit(*t
) && ret
) {
908 if (!strncmp(t
, "silent", 6)) {
909 mode
|= FBSPL_MODE_SILENT
;
912 } else if (!strncmp(t
, "verbose", 7)) {
913 mode
|= FBSPL_MODE_VERBOSE
;
920 skip_whitespace(&t
, false);
924 mode
= FBSPL_MODE_SILENT
| FBSPL_MODE_VERBOSE
;
926 obj_setmode(container_of(ct
), mode
);
930 if (!skip_nonwhitespace(&p
, true))
937 /* We have already skipped at least one whitespace (replaced with 0)
938 * -- no need to enforce any more here. */
939 skip_whitespace(&t
, false);
941 /* Parse the style selector */
942 while (!isdigit(*t
)) {
944 ct
->style
|= TTF_STYLE_BOLD
;
945 } else if (*t
== 'i') {
946 ct
->style
|= TTF_STYLE_ITALIC
;
947 } else if (*t
== 'u') {
948 ct
->style
|= TTF_STYLE_UNDERLINE
;
949 } else if (*t
!= ' ' && *t
!= '\t') {
950 parse_error("expected a style specifier instead of '%s'", t
);
956 skip_whitespace(&t
, false);
958 /* Parse font size */
959 fontsize
= strtol(t
, &p
, 0);
960 checknskip(pt_err
, true, "expected font size (a number) instead of '%s'", t
);
962 /* Parse x position */
963 ct
->x
= strtol(t
,&p
,0);
964 checknskip(pt_err
, true, "expected x position (a number) instead of '%s'", t
);
967 if (!strncmp(t
, "left", 4)) {
968 ct
->hotspot
|= F_HS_LEFT
;
970 } else if (!strncmp(t
, "right", 5)) {
971 ct
->hotspot
|= F_HS_RIGHT
;
973 } else if (!strncmp(t
, "middle", 6)) {
974 ct
->hotspot
|= F_HS_HMIDDLE
;
977 parse_error("expected 'left', 'right' or 'middle' instead of '%s'", t
);
981 if (!skip_whitespace(&t
, true))
984 ct
->hotspot
|= F_HS_LEFT
;
987 /* Parse y position */
988 ct
->y
= strtol(t
,&p
,0);
989 checknskip(pt_err
, true, "expected y position (a number) instead of '%s'", t
);
991 if (!strncmp(t
, "top", 3)) {
992 ct
->hotspot
|= F_HS_TOP
;
994 } else if (!strncmp(t
, "bottom", 6)) {
995 ct
->hotspot
|= F_HS_BOTTOM
;
997 } else if (!strncmp(t
, "middle", 6)) {
998 ct
->hotspot
|= F_HS_VMIDDLE
;
1001 ct
->hotspot
|= F_HS_TOP
;
1004 skip_whitespace(&t
, false);
1007 if (ct
->x
>= tmptheme
.xres
) {
1008 parse_error("the x position is invalid (larger than x resolution)");
1015 if (ct
->y
>= tmptheme
.yres
) {
1016 parse_error("the y position is invalid (larger than y resolution)");
1023 zero_color(ct
->col
);
1025 if (parse_color(&t
, &ct
->col
)) {
1026 parse_error("expected a color instead of '%s'", t
);
1030 ct
->curr_progress
= -1;
1032 if (!skip_whitespace(&t
, true))
1036 if (!strncmp(t
, "exec", 4)) {
1037 ct
->flags
|= F_TXT_EXEC
;
1040 } else if (!strncmp(t
, "eval", 4)) {
1041 ct
->flags
|= F_TXT_EVAL
;
1044 } else if (!strncmp(t
, "msglog", 6)) {
1045 ct
->flags
|= F_TXT_MSGLOG
;
1051 skip_whitespace(&t
, false);
1053 ct
->val
= parse_quoted_string(t
, (ct
->flags
& F_TXT_EVAL
) ? 1 : 0);
1055 parse_error("failed to parse a quoted string: '%s'", t
);
1059 if (strstr(ct
->val
, "$progress")) {
1060 ct
->curr_progress
= config
.progress
;
1064 if (!parse_effects(t
, container_of(ct
)))
1068 fontname
= DEFAULT_FONT
;
1070 fpath
= get_fontpath(fontname
);
1072 for (ti
= tmptheme
.fonts
.head
; ti
!= NULL
; ti
= ti
->next
) {
1073 fe
= (font_e
*) ti
->p
;
1075 if (!strcmp(fe
->file
, fpath
) && fe
->size
== fontsize
) {
1081 /* Allocate a new entry in the fonts list */
1082 fe
= malloc(sizeof(font_e
));
1084 iprint(MSG_ERROR
, "%s: failed to allocate memory\n", __func__
);
1088 fe
->size
= fontsize
;
1091 list_add(&tmptheme
.fonts
, fe
);
1099 free(container_of(ct
));
1108 text
*ct
= obj_alloc(text
, FBSPL_MODE_SILENT
);
1113 iprint(MSG_ERROR
, "%s: failed to allocate memory\n", __func__
);
1117 ct
->hotspot
= F_HS_LEFT
| F_HS_TOP
;
1118 ct
->style
= TTF_STYLE_NORMAL
;
1121 ct
->col
= text_color
;
1122 ct
->val
= strdup(config
.message
);
1123 ct
->curr_progress
= config
.progress
;
1124 ct
->flags
= F_TXT_EVAL
;
1130 for (ti
= tmptheme
.fonts
.head
; ti
!= NULL
; ti
= ti
->next
) {
1131 fe
= (font_e
*) ti
->p
;
1133 if (!strcmp(fe
->file
, fpath
) && fe
->size
== text_size
) {
1139 /* Allocate a new entry in the fonts list */
1140 fe
= malloc(sizeof(font_e
));
1142 iprint(MSG_ERROR
, "%s: failed to allocate memory\n", __func__
);
1146 fe
->size
= text_size
;
1149 list_add(&tmptheme
.fonts
, fe
);
1157 free(container_of(ct
));
1165 int parse_cfg(char *cfgfile
, stheme_t
*theme
)
1171 bool ignore
= false;
1174 if ((cfgfp
= fopen(cfgfile
,"r")) == NULL
) {
1175 iprint(MSG_ERROR
, "Can't open cfg file %s.\n", cfgfile
);
1179 /* Save the path of the file that is currently being parsed, so that
1180 * it can be used when printing error messages. */
1181 curr_cfgfile
= cfgfile
;
1183 memcpy(&tmptheme
, theme
, sizeof(tmptheme
));
1185 while (fgets(buf
, sizeof(buf
), cfgfp
)) {
1191 if (len
== 0 || len
== sizeof(buf
)-1)
1194 buf
[len
-1] = 0; /* get rid of \n */
1197 skip_whitespace(&t
, false);
1203 for (i
= 0; i
< sizeof(opts
) / sizeof(struct cfg_opt
); i
++)
1205 if (!strncmp(opts
[i
].name
, t
, strlen(opts
[i
].name
))) {
1207 if (ignore
&& opts
[i
].type
!= t_type_close
)
1210 t
+= strlen(opts
[i
].name
);
1212 switch (opts
[i
].type
) {
1215 skip_whitespace(&t
, false);
1216 parse_path(t
, opts
[i
]);
1220 skip_whitespace(&t
, false);
1221 parse_fontpath(t
, opts
[i
]);
1227 parse_error("expected '=' instead of '%c'", *t
);
1232 skip_whitespace(&t
, false);
1233 parse_color(&t
, opts
[i
].val
);
1238 skip_whitespace(&t
, false);
1239 parse_int(t
, opts
[i
]);
1244 box
*tbox
= parse_box(t
);
1248 if (tbox
->attr
& BOX_INTER
) {
1251 } else if (bprev
!= NULL
) {
1252 bprev
->inter
= tbox
;
1253 bprev
->curr
= malloc(sizeof(box
));
1254 box_interpolate(bprev
, tbox
, bprev
->curr
);
1256 free(container_of(tbox
));
1257 free(container_of(bprev
));
1258 iprint(MSG_ERROR
, "Failed to allocate cache for an interpolated box.\n");
1262 if (!memcmp(&bprev
->c_ul
, &tbox
->c_ul
, sizeof(color
)) &&
1263 !memcmp(&bprev
->c_ll
, &tbox
->c_ll
, sizeof(color
)) &&
1264 !memcmp(&bprev
->c_ur
, &tbox
->c_ur
, sizeof(color
)) &&
1265 !memcmp(&bprev
->c_lr
, &tbox
->c_lr
, sizeof(color
)))
1267 if (!memcmp(&bprev
->c_ul
, &bprev
->c_ur
, sizeof(color
))) {
1268 if (!memcmp(&bprev
->c_ll
, &bprev
->c_lr
, sizeof(color
))) {
1269 if (!memcmp(&bprev
->c_ll
, &bprev
->c_ul
, sizeof(color
)))
1270 bprev
->attr
|= BOX_SOLID
;
1272 bprev
->attr
|= BOX_VGRAD
;
1274 } else if (!memcmp(&bprev
->c_ul
, &bprev
->c_ll
, sizeof(color
)) &&
1275 !memcmp(&bprev
->c_ur
, &bprev
->c_lr
, sizeof(color
))) {
1276 bprev
->attr
|= BOX_HGRAD
;
1281 /* Non-interpolated box */
1283 if (!memcmp(&tbox
->c_ul
, &tbox
->c_ur
, sizeof(color
)) &&
1284 !memcmp(&tbox
->c_ll
, &tbox
->c_lr
, sizeof(color
)) &&
1285 !memcmp(&tbox
->c_ll
, &tbox
->c_ul
, sizeof(color
))) {
1286 tbox
->attr
|= BOX_SOLID
;
1304 skip_whitespace(&t
, true);
1305 if (!strncmp(t
, "bootup", 6)) {
1306 if (config
.type
== fbspl_bootup
)
1309 } else if (!strncmp(t
, "reboot", 6)) {
1310 if (config
.type
== fbspl_reboot
)
1313 } else if (!strncmp(t
, "shutdown", 8)) {
1314 if (config
.type
== fbspl_shutdown
)
1317 } else if (!strncmp(t
, "suspend", 7)) {
1318 if (config
.type
== fbspl_suspend
)
1321 } else if (!strncmp(t
, "resume", 6)) {
1322 if (config
.type
== fbspl_resume
)
1325 } else if (!strncmp(t
, "other", 5)) {
1326 if (config
.type
== fbspl_undef
)
1330 parse_error("expected 'other', 'bootup', 'reboot' or 'shutdown' instead of '%s'", t
);
1340 case t_textbox_open
:
1344 case t_textbox_close
:
1363 parse_error("an 'inter' box must be directly followed by another box");
1364 free(container_of(bprev
));
1373 parse_error("unclosed <textbox> section");
1378 memcpy(theme
, &tmptheme
, sizeof(tmptheme
));