Dillo v3.1.1-46-g8a360e32
Loading...
Searching...
No Matches
cssparser.cc
Go to the documentation of this file.
1/*
2 * File: cssparser.cc
3 *
4 * Copyright 2004 Sebastian Geerken <sgeerken@dillo.org>
5 * Copyright 2008-2009 Johannes Hofmann <Johannes.Hofmann@gmx.de>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 */
12
13/*
14 * This file is heavily based on the CSS parser of dillo-0.8.0-css-3 -
15 * a dillo1 based CSS prototype written by Sebastian Geerken.
16 */
17
18#include <ctype.h>
19#include <stdlib.h>
20#include <stdio.h>
21
22#include "msg.h"
23#include "colors.h"
24#include "html_common.hh"
25#include "css.hh"
26#include "cssparser.hh"
27
28using namespace dw::core::style;
29
30//#define MSG_CSS(A, ...) _MSG(A, __VA_ARGS__)
31#define MSG_CSS(A, ...) do {} while(0)
32#define DEBUG_TOKEN_LEVEL 0
33#define DEBUG_PARSE_LEVEL 0
34#define DEBUG_CREATE_LEVEL 0
35
36#define DEBUG_LEVEL 10
37
38/* The last three ones are never parsed. */
39#define CSS_NUM_INTERNAL_PROPERTIES 3
40#define CSS_NUM_PARSED_PROPERTIES \
41 (CSS_PROPERTY_LAST - CSS_NUM_INTERNAL_PROPERTIES)
42
43
44typedef struct {
45 const char *symbol;
46 const CssValueType type[3];
47 const char *const *enum_symbols;
48} CssPropertyInfo;
49
50static const char *const Css_background_attachment_enum_vals[] = {
51 "scroll", "fixed", NULL
52};
53
54static const char *const Css_background_repeat_enum_vals[] = {
55 "repeat", "repeat-x", "repeat-y", "no-repeat", NULL
56};
57
58static const char *const Css_border_collapse_enum_vals[] = {
59 "separate", "collapse", NULL
60};
61
62static const char *const Css_border_color_enum_vals[] = {
63 "transparent", NULL
64};
65
66static const char *const Css_border_style_enum_vals[] = {
67 "none", "hidden", "dotted", "dashed", "solid", "double", "groove",
68 "ridge", "inset", "outset", NULL
69};
70
71static const char *const Css_border_width_enum_vals[] = {
72 "thin", "medium", "thick", NULL
73};
74
75static const char *const Css_clear_enum_vals[] = {
76 "left", "right", "both", "none", NULL
77};
78
79static const char *const Css_cursor_enum_vals[] = {
80 "crosshair", "default", "pointer", "move", "e-resize", "ne-resize",
81 "nw-resize", "n-resize", "se-resize", "sw-resize", "s-resize",
82 "w-resize", "text", "wait", "help", NULL
83};
84
85static const char *const Css_display_enum_vals[] = {
86 "block", "inline", "inline-block", "list-item", "none", "table",
87 "table-row-group", "table-header-group", "table-footer-group", "table-row",
88 "table-cell", NULL
89};
90
91static const char *const Css_float_enum_vals[] = {
92 "none", "left", "right", NULL
93};
94
95static const char *const Css_font_size_enum_vals[] = {
96 "large", "larger", "medium", "small", "smaller", "xx-large", "xx-small",
97 "x-large", "x-small", NULL
98};
99
100static const char *const Css_font_style_enum_vals[] = {
101 "normal", "italic", "oblique", NULL
102};
103
104static const char *const Css_font_variant_enum_vals[] = {
105 "normal", "small-caps", NULL
106};
107
108static const char *const Css_font_weight_enum_vals[] = {
109 "bold", "bolder", "light", "lighter", "normal", NULL
110};
111
112static const char *const Css_letter_spacing_enum_vals[] = {
113 "normal", NULL
114};
115
116static const char *const Css_list_style_position_enum_vals[] = {
117 "inside", "outside", NULL
118};
119
120static const char *const Css_line_height_enum_vals[] = {
121 "normal", NULL
122};
123
124static const char *const Css_list_style_type_enum_vals[] = {
125 "disc", "circle", "square", "decimal", "decimal-leading-zero",
126 "lower-roman", "upper-roman", "lower-greek", "lower-alpha",
127 "lower-latin", "upper-alpha", "upper-latin", "hebrew", "armenian",
128 "georgian", "cjk-ideographic", "hiragana", "katakana", "hiragana-iroha",
129 "katakana-iroha", "none", NULL
130};
131
132static const char *const Css_overflow_enum_vals[] = {
133 "visible", "hidden", "scroll", "auto", NULL
134};
135
136static const char *const Css_position_enum_vals[] = {
137 "static", "relative", "absolute", "fixed", NULL
138};
139
140static const char *const Css_text_align_enum_vals[] = {
141 "left", "right", "center", "justify", "string", NULL
142};
143
144static const char *const Css_text_decoration_enum_vals[] = {
145 "underline", "overline", "line-through", "blink", NULL
146};
147
148static const char *const Css_text_transform_enum_vals[] = {
149 "none", "capitalize", "uppercase", "lowercase", NULL
150};
151
152static const char *const Css_vertical_align_vals[] = {
153 "top", "bottom", "middle", "baseline", "sub", "super", "text-top",
154 "text-bottom", NULL
155};
156
157static const char *const Css_white_space_vals[] = {
158 "normal", "pre", "nowrap", "pre-wrap", "pre-line", NULL
159};
160
161static const char *const Css_word_spacing_enum_vals[] = {
162 "normal", NULL
163};
164
165const CssPropertyInfo Css_property_info[CSS_PROPERTY_LAST] = {
166 {"background-attachment", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED},
168 {"background-color", {CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, NULL},
169 {"background-image", {CSS_TYPE_URI, CSS_TYPE_UNUSED}, NULL},
170 {"background-position", {CSS_TYPE_BACKGROUND_POSITION, CSS_TYPE_UNUSED},
171 NULL},
172 {"background-repeat", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED},
174 {"border-bottom-color", {CSS_TYPE_ENUM, CSS_TYPE_COLOR, CSS_TYPE_UNUSED},
176 {"border-bottom-style", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED},
178 {"border-bottom-width", {CSS_TYPE_ENUM, CSS_TYPE_LENGTH, CSS_TYPE_UNUSED},
180 {"border-collapse", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED},
182 {"border-left-color", {CSS_TYPE_ENUM, CSS_TYPE_COLOR, CSS_TYPE_UNUSED},
184 {"border-left-style", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED},
186 {"border-left-width", {CSS_TYPE_ENUM, CSS_TYPE_LENGTH, CSS_TYPE_UNUSED},
188 {"border-right-color", {CSS_TYPE_ENUM, CSS_TYPE_COLOR, CSS_TYPE_UNUSED},
190 {"border-right-style", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED},
192 {"border-rigth-width", {CSS_TYPE_ENUM, CSS_TYPE_LENGTH, CSS_TYPE_UNUSED},
194 {"border-spacing", {CSS_TYPE_LENGTH, CSS_TYPE_UNUSED}, NULL},
195 {"border-top-color", {CSS_TYPE_ENUM, CSS_TYPE_COLOR, CSS_TYPE_UNUSED},
197 {"border-top-style", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED},
199 {"border-top-width", {CSS_TYPE_ENUM, CSS_TYPE_LENGTH, CSS_TYPE_UNUSED},
201 {"bottom", {CSS_TYPE_SIGNED_LENGTH, CSS_TYPE_UNUSED}, NULL},
202 {"caption-side", {CSS_TYPE_UNUSED}, NULL},
204 {"clip", {CSS_TYPE_UNUSED}, NULL},
205 {"color", {CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, NULL},
206 {"content", {CSS_TYPE_STRING, CSS_TYPE_UNUSED}, NULL},
207 {"counter-increment", {CSS_TYPE_UNUSED}, NULL},
208 {"counter-reset", {CSS_TYPE_UNUSED}, NULL},
210 {"direction", {CSS_TYPE_UNUSED}, NULL},
212 {"empty-cells", {CSS_TYPE_UNUSED}, NULL},
214 {"font-family", {CSS_TYPE_SYMBOL, CSS_TYPE_UNUSED}, NULL},
217 {"font-size-adjust", {CSS_TYPE_UNUSED}, NULL},
218 {"font-stretch", {CSS_TYPE_UNUSED}, NULL},
220 {"font-variant", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED},
225 {"left", {CSS_TYPE_SIGNED_LENGTH, CSS_TYPE_UNUSED}, NULL},
228 {"line-height",
231 {"list-style-image", {CSS_TYPE_UNUSED}, NULL},
232 {"list-style-position", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED},
234 {"list-style-type", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED},
236 {"margin-bottom",
238 {"margin-left",
240 {"margin-right",
242 {"margin-top",
244 {"marker-offset", {CSS_TYPE_UNUSED}, NULL},
245 {"marks", {CSS_TYPE_UNUSED}, NULL},
247 NULL},
249 NULL},
251 NULL},
253 NULL},
254 {"outline-color", {CSS_TYPE_UNUSED}, NULL},
255 {"outline-style", {CSS_TYPE_UNUSED}, NULL},
256 {"outline-width", {CSS_TYPE_UNUSED}, NULL},
258 {"padding-bottom", {CSS_TYPE_LENGTH, CSS_TYPE_UNUSED}, NULL},
259 {"padding-left", {CSS_TYPE_LENGTH, CSS_TYPE_UNUSED}, NULL},
260 {"padding-right", {CSS_TYPE_LENGTH, CSS_TYPE_UNUSED}, NULL},
261 {"padding-top", {CSS_TYPE_LENGTH, CSS_TYPE_UNUSED}, NULL},
263 {"quotes", {CSS_TYPE_UNUSED}, NULL},
264 {"right", {CSS_TYPE_SIGNED_LENGTH, CSS_TYPE_UNUSED}, NULL},
266 {"text-decoration", {CSS_TYPE_MULTI_ENUM, CSS_TYPE_UNUSED},
268 {"text-indent", {CSS_TYPE_LENGTH_PERCENTAGE, CSS_TYPE_UNUSED}, NULL},
269 {"text-shadow", {CSS_TYPE_UNUSED}, NULL},
270 {"text-transform", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED},
272 {"top", {CSS_TYPE_SIGNED_LENGTH, CSS_TYPE_UNUSED}, NULL},
273 {"unicode-bidi", {CSS_TYPE_UNUSED}, NULL},
275 {"visibility", {CSS_TYPE_UNUSED}, NULL},
280 {"z-index", {CSS_TYPE_INTEGER, CSS_TYPE_AUTO, CSS_TYPE_UNUSED}, NULL},
281
282 /* These are extensions, for internal used, and never parsed. */
283 {"x-link", {CSS_TYPE_INTEGER, CSS_TYPE_UNUSED}, NULL},
284 {"x-colspan", {CSS_TYPE_INTEGER, CSS_TYPE_UNUSED}, NULL},
285 {"x-rowspan", {CSS_TYPE_INTEGER, CSS_TYPE_UNUSED}, NULL},
286 {"last", {CSS_TYPE_UNUSED}, NULL},
287};
288
289typedef struct {
290 const char *symbol;
291 enum {
292 CSS_SHORTHAND_MULTIPLE,
294 CSS_SHORTHAND_DIRECTIONS,
295 CSS_SHORTHAND_BORDER,
296 CSS_SHORTHAND_FONT,
297 } type;
298 const CssPropertyName *properties; /* CSS_SHORTHAND_MULTIPLE:
299 * must be terminated by
300 * CSS_PROPERTY_END
301 * CSS_SHORTHAND_DIRECTIONS:
302 * must have length 4
303 * CSS_SHORTHAND_BORDERS:
304 * must have length 12
305 * CSS_SHORTHAND_FONT:
306 * unused */
307} CssShorthandInfo;
308
317
324
331
338
345
352
359
366
373
380
387
394
409
418
419static const CssShorthandInfo Css_shorthand_info[] = {
420 {"background", CssShorthandInfo::CSS_SHORTHAND_MULTIPLE,
422 {"border", CssShorthandInfo::CSS_SHORTHAND_BORDER,
424 {"border-bottom", CssShorthandInfo::CSS_SHORTHAND_MULTIPLE,
426 {"border-color", CssShorthandInfo::CSS_SHORTHAND_DIRECTIONS,
428 {"border-left", CssShorthandInfo::CSS_SHORTHAND_MULTIPLE,
430 {"border-right", CssShorthandInfo::CSS_SHORTHAND_MULTIPLE,
432 {"border-style", CssShorthandInfo::CSS_SHORTHAND_DIRECTIONS,
434 {"border-top", CssShorthandInfo::CSS_SHORTHAND_MULTIPLE,
436 {"border-width", CssShorthandInfo::CSS_SHORTHAND_DIRECTIONS,
438 {"font", CssShorthandInfo::CSS_SHORTHAND_FONT,
440 {"list-style", CssShorthandInfo::CSS_SHORTHAND_MULTIPLE,
442 {"margin", CssShorthandInfo::CSS_SHORTHAND_DIRECTIONS,
444 {"outline", CssShorthandInfo::CSS_SHORTHAND_MULTIPLE,
446 {"padding", CssShorthandInfo::CSS_SHORTHAND_DIRECTIONS,
448};
449
450#define CSS_SHORTHAND_NUM \
451 (sizeof(Css_shorthand_info) / sizeof(Css_shorthand_info[0]))
452
453/* ----------------------------------------------------------------------
454 * Parsing
455 * ---------------------------------------------------------------------- */
456
458 const DilloUrl *baseUrl,
459 const char *buf, int buflen)
460{
461 this->context = context;
462 this->origin = origin;
463 this->buf = buf;
464 this->buflen = buflen;
465 this->bufptr = 0;
466 this->spaceSeparated = false;
467 this->withinBlock = false;
468 this->baseUrl = baseUrl;
469
470 nextToken ();
471}
472
477{
478 int c;
479
480 if (bufptr >= buflen)
481 c = EOF;
482 else
483 c = buf[bufptr];
484
485 /* The buffer pointer is increased in any case, so that ungetChar works
486 * correctly at the end of the buffer. */
487 bufptr++;
488 return c;
489}
490
495{
496 bufptr--;
497}
498
505inline bool CssParser::skipString(int c, const char *str)
506{
507 for (int n = 0; str[n]; n++) {
508 if (n > 0)
509 c = getChar();
510
511 if (str[n] != c) {
512 while (n--)
513 ungetChar();
514 return false;
515 }
516 }
517
518 return true;
519}
520
522{
523 int c, c1, d, j;
524 char hexbuf[5];
525 int i = 0;
526
527 ttype = CSS_TK_CHAR; /* init */
528 spaceSeparated = false;
529
530 while (true) {
531 c = getChar();
532 if (isspace(c)) { // ignore whitespace
533 spaceSeparated = true;
534 } else if (skipString(c, "/*")) { // ignore comments
535 do {
536 c = getChar();
537 } while (c != EOF && ! skipString(c, "*/"));
538 } else if (skipString(c, "<!--")) { // ignore XML comment markers
539 } else if (skipString(c, "-->")) {
540 } else {
541 break;
542 }
543 }
544
545 // handle negative numbers
546 if (c == '-') {
547 if (i < maxStrLen - 1)
548 tval[i++] = c;
549 c = getChar();
550 }
551
552 if (isdigit(c)) {
554 do {
555 if (i < maxStrLen - 1) {
556 tval[i++] = c;
557 }
558 /* else silently truncated */
559 c = getChar();
560 } while (isdigit(c));
561 if (c != '.')
562 ungetChar();
563
564 /* ...but keep going to see whether it's really a float */
565 }
566
567 if (c == '.') {
568 c = getChar();
569 if (isdigit(c)) {
571 if (i < maxStrLen - 1)
572 tval[i++] = '.';
573 do {
574 if (i < maxStrLen - 1)
575 tval[i++] = c;
576 /* else silently truncated */
577 c = getChar();
578 } while (isdigit(c));
579
580 ungetChar();
581 tval[i] = 0;
582 DEBUG_MSG(DEBUG_TOKEN_LEVEL, "token number %s\n", tval);
583 return;
584 } else {
585 ungetChar();
586 if (ttype == CSS_TK_DECINT) {
587 ungetChar();
588 } else {
589 c = '.';
590 }
591 }
592 }
593
594 if (ttype == CSS_TK_DECINT) {
595 tval[i] = 0;
596 DEBUG_MSG(DEBUG_TOKEN_LEVEL, "token number %s\n", tval);
597 return;
598 }
599
600 if (i) {
601 ungetChar(); /* ungetChar '-' */
602 i--;
603 c = getChar();
604 }
605
606 if (isalpha(c) || c == '_' || c == '-') {
608
609 tval[0] = c;
610 i = 1;
611 c = getChar();
612 while (isalnum(c) || c == '_' || c == '-') {
613 if (i < maxStrLen - 1) {
614 tval[i] = c;
615 i++;
616 } /* else silently truncated */
617 c = getChar();
618 }
619 tval[i] = 0;
620 ungetChar();
621 DEBUG_MSG(DEBUG_TOKEN_LEVEL, "token symbol '%s'\n", tval);
622 return;
623 }
624
625 if (c == '"' || c == '\'') {
626 c1 = c;
628
629 i = 0;
630 c = getChar();
631
632 while (c != EOF && c != c1) {
633 if (c == '\\') {
634 d = getChar();
635 if (isxdigit(d)) {
636 /* Read hex Unicode char. (Actually, strings are yet only 8
637 * bit.) */
638 hexbuf[0] = d;
639 j = 1;
640 d = getChar();
641 while (j < 4 && isxdigit(d)) {
642 hexbuf[j] = d;
643 j++;
644 d = getChar();
645 }
646 hexbuf[j] = 0;
647 ungetChar();
648 c = strtol(hexbuf, NULL, 16);
649 } else {
650 /* Take character literally. */
651 c = d;
652 }
653 }
654
655 if (i < maxStrLen - 1) {
656 tval[i] = c;
657 i++;
658 } /* else silently truncated */
659 c = getChar();
660 }
661 tval[i] = 0;
662 /* No ungetChar(). */
663 DEBUG_MSG(DEBUG_TOKEN_LEVEL, "token string '%s'\n", tval);
664 return;
665 }
666
667 /*
668 * Within blocks, '#' starts a color, outside, it is used in selectors.
669 */
670 if (c == '#' && withinBlock) {
672
673 tval[0] = c;
674 i = 1;
675 c = getChar();
676 while (isxdigit(c)) {
677 if (i < maxStrLen - 1) {
678 tval[i] = c;
679 i++;
680 } /* else silently truncated */
681 c = getChar();
682 }
683 tval[i] = 0;
684 ungetChar();
685 DEBUG_MSG(DEBUG_TOKEN_LEVEL, "token color '%s'\n", tval);
686 return;
687 }
688
689 if (c == EOF) {
690 DEBUG_MSG(DEBUG_TOKEN_LEVEL, "token %s\n", "EOF");
692 return;
693 }
694
696 tval[0] = c;
697 tval[1] = 0;
698 DEBUG_MSG(DEBUG_TOKEN_LEVEL, "token char '%c'\n", c);
699}
700
701
703{
704 int i, err = 1;
705 CssValueType savedType = *type;
706
707 for (int j = 0; Css_property_info[prop].type[j] != CSS_TYPE_UNUSED; j++) {
708 *type = Css_property_info[prop].type[j];
709
710 switch (Css_property_info[prop].type[j]) {
711
712 case CSS_TYPE_ENUM:
713 if (ttype == CSS_TK_SYMBOL) {
714 for (i = 0; Css_property_info[prop].enum_symbols[i]; i++)
716 Css_property_info[prop].enum_symbols[i]) == 0)
717 return true;
718 }
719 break;
720
722 if (ttype == CSS_TK_SYMBOL) {
723 if (dStrAsciiCasecmp(tval, "none") == 0) {
724 return true;
725 } else {
726 for (i = 0; Css_property_info[prop].enum_symbols[i]; i++) {
728 Css_property_info[prop].enum_symbols[i]) == 0)
729 return true;
730 }
731 }
732 }
733 break;
734
736 if (ttype == CSS_TK_SYMBOL &&
737 (dStrAsciiCasecmp(tval, "center") == 0 ||
738 dStrAsciiCasecmp(tval, "left") == 0 ||
739 dStrAsciiCasecmp(tval, "right") == 0 ||
740 dStrAsciiCasecmp(tval, "top") == 0 ||
741 dStrAsciiCasecmp(tval, "bottom") == 0))
742 return true;
744 return true;
745 break;
748 case CSS_TYPE_LENGTH:
749 if (tval[0] == '-')
750 return false;
751 // Fall Through
754 return true;
755 break;
756
757 case CSS_TYPE_AUTO:
758 if (ttype == CSS_TK_SYMBOL && dStrAsciiCasecmp(tval, "auto") == 0)
759 return true;
760 break;
761
762 case CSS_TYPE_COLOR:
763 if ((ttype == CSS_TK_COLOR ||
764 ttype == CSS_TK_SYMBOL) &&
765 (dStrAsciiCasecmp(tval, "rgb") == 0 ||
766 a_Color_parse(tval, -1, &err) != -1))
767 return true;
768 break;
769
770 case CSS_TYPE_STRING:
771 if (ttype == CSS_TK_STRING)
772 return true;
773 break;
774
775 case CSS_TYPE_SYMBOL:
776 if (ttype == CSS_TK_SYMBOL ||
778 return true;
779 break;
780
782 if (ttype == CSS_TK_DECINT) {
783 i = strtol(tval, NULL, 10);
784 if (i >= 100 && i <= 900)
785 return true;
786 }
787 break;
788
789 case CSS_TYPE_URI:
790 if (ttype == CSS_TK_SYMBOL &&
791 (dStrAsciiCasecmp(tval, "url") == 0 ||
792 dStrAsciiCasecmp(tval, "none") == 0))
793 return true;
794 break;
795
796 case CSS_TYPE_INTEGER:
797 if (ttype == CSS_TK_DECINT)
798 return true;
799 break;
800
801 case CSS_TYPE_UNUSED:
802 default:
803 assert(false);
804 break;
805 }
806 }
807
808 *type = savedType;
809 return false;
810}
811
812bool CssParser::parseRgbColorComponent(int32_t *cc, int *percentage) {
813 if (ttype != CSS_TK_DECINT) {
814 MSG_CSS("expected integer not found in %s color\n", "rgb");
815 return false;
816 }
817
818 *cc = strtol(tval, NULL, 10);
819
820 nextToken();
821 if (ttype == CSS_TK_CHAR && tval[0] == '%') {
822 if (*percentage == 0) {
823 MSG_CSS("'%s' unexpected in rgb color\n", "%");
824 return false;
825 }
826 *percentage = 1;
827 *cc = *cc * 255 / 100;
828 nextToken();
829 } else {
830 if (*percentage == 1) {
831 MSG_CSS("expected '%s' not found in rgb color\n", "%");
832 return false;
833 }
834 *percentage = 0;
835 }
836
837 if (*cc > 255)
838 *cc = 255;
839 if (*cc < 0)
840 *cc = 0;
841
842 return true;
843}
844
845bool CssParser::parseRgbColor(int32_t *c) {
846 int32_t cc;
847 int percentage = -1;
848
849 *c = 0;
850
851 if (ttype != CSS_TK_CHAR || tval[0] != '(') {
852 MSG_CSS("expected '%s' not found in rgb color\n", "(");
853 return false;
854 }
855 nextToken();
856
857 if (!parseRgbColorComponent(&cc, &percentage))
858 return false;
859 *c |= cc << 16;
860
861 if (ttype != CSS_TK_CHAR || tval[0] != ',') {
862 MSG_CSS("expected '%s' not found in rgb color\n", ",");
863 return false;
864 }
865 nextToken();
866
867 if (!parseRgbColorComponent(&cc, &percentage))
868 return false;
869 *c |= cc << 8;
870
871 if (ttype != CSS_TK_CHAR || tval[0] != ',') {
872 MSG_CSS("expected '%s' not found in rgb color\n", ",");
873 return false;
874 }
875 nextToken();
876
877 if (!parseRgbColorComponent(&cc, &percentage))
878 return false;
879 *c |= cc;
880
881 if (ttype != CSS_TK_CHAR || tval[0] != ')') {
882 MSG_CSS("expected '%s' not found in rgb color\n", ")");
883 return false;
884 }
885
886 return true;
887}
888
890 CssValueType type,
891 CssPropertyValue *val)
892{
893 CssLengthType lentype;
894 bool found, ret = false;
895 float fval;
896 int i, ival, err = 1;
897 Dstr *dstr;
898
899 switch (type) {
900 case CSS_TYPE_ENUM:
901 if (ttype == CSS_TK_SYMBOL) {
902 for (i = 0; Css_property_info[prop].enum_symbols[i]; i++)
904 Css_property_info[prop].enum_symbols[i]) == 0) {
905 val->intVal = i;
906 ret = true;
907 break;
908 }
909 nextToken();
910 }
911 break;
912
914 val->intVal = 0;
915 ret = true;
916
917 while (ttype == CSS_TK_SYMBOL) {
918 if (dStrAsciiCasecmp(tval, "none") != 0) {
919 for (i = 0, found = false;
920 !found && Css_property_info[prop].enum_symbols[i]; i++) {
922 Css_property_info[prop].enum_symbols[i]) == 0)
923 val->intVal |= (1 << i);
924 }
925 }
926 nextToken();
927 }
928 break;
929
932 case CSS_TYPE_LENGTH:
934 if (ttype == CSS_TK_DECINT || ttype == CSS_TK_FLOAT) {
935 fval = atof(tval);
936 lentype = CSS_LENGTH_TYPE_NONE;
937
938 nextToken();
940 ret = true;
941
942 if (dStrAsciiCasecmp(tval, "px") == 0) {
943 lentype = CSS_LENGTH_TYPE_PX;
944 nextToken();
945 } else if (dStrAsciiCasecmp(tval, "mm") == 0) {
946 lentype = CSS_LENGTH_TYPE_MM;
947 nextToken();
948 } else if (dStrAsciiCasecmp(tval, "cm") == 0) {
949 lentype = CSS_LENGTH_TYPE_MM;
950 fval *= 10;
951 nextToken();
952 } else if (dStrAsciiCasecmp(tval, "in") == 0) {
953 lentype = CSS_LENGTH_TYPE_MM;
954 fval *= 25.4;
955 nextToken();
956 } else if (dStrAsciiCasecmp(tval, "pt") == 0) {
957 lentype = CSS_LENGTH_TYPE_MM;
958 fval *= (25.4 / 72);
959 nextToken();
960 } else if (dStrAsciiCasecmp(tval, "pc") == 0) {
961 lentype = CSS_LENGTH_TYPE_MM;
962 fval *= (25.4 / 6);
963 nextToken();
964 } else if (dStrAsciiCasecmp(tval, "em") == 0) {
965 lentype = CSS_LENGTH_TYPE_EM;
966 nextToken();
967 } else if (dStrAsciiCasecmp(tval, "ex") == 0) {
968 lentype = CSS_LENGTH_TYPE_EX;
969 nextToken();
970 } else {
971 ret = false;
972 }
973 } else if (!spaceSeparated &&
976 ttype == CSS_TK_CHAR &&
977 tval[0] == '%') {
978 fval /= 100;
980 ret = true;
981 nextToken();
982 }
983
984 /* Allow numbers without unit only for 0 or
985 * CSS_TYPE_LENGTH_PERCENTAGE_NUMBER
986 */
987 if (lentype == CSS_LENGTH_TYPE_NONE &&
988 (type == CSS_TYPE_LENGTH_PERCENTAGE_NUMBER || fval == 0.0))
989 ret = true;
990
991 val->intVal = CSS_CREATE_LENGTH(fval, lentype);
992 }
993 break;
994
995 case CSS_TYPE_AUTO:
996 assert (ttype == CSS_TK_SYMBOL && !dStrAsciiCasecmp(tval, "auto"));
997 ret = true;
999 nextToken();
1000 break;
1001
1002 case CSS_TYPE_COLOR:
1003 if (ttype == CSS_TK_COLOR) {
1004 val->intVal = a_Color_parse(tval, -1, &err);
1005 if (err)
1006 MSG_CSS("color is not in \"%s\" format\n", "#RRGGBB");
1007 else
1008 ret = true;
1009 nextToken();
1010 } else if (ttype == CSS_TK_SYMBOL) {
1011 if (dStrAsciiCasecmp(tval, "rgb") == 0) {
1012 nextToken();
1013 if (parseRgbColor(&val->intVal))
1014 ret = true;
1015 else
1016 MSG_CSS("Failed to parse %s color\n", "rgb(r,g,b)");
1017 } else {
1018 val->intVal = a_Color_parse(tval, -1, &err);
1019 if (err)
1020 MSG_CSS("color is not in \"%s\" format\n", "#RRGGBB");
1021 else
1022 ret = true;
1023 }
1024 nextToken();
1025 }
1026 break;
1027
1028 case CSS_TYPE_STRING:
1029 if (ttype == CSS_TK_STRING) {
1030 val->strVal = dStrdup(tval);
1031 ret = true;
1032 nextToken();
1033 }
1034 break;
1035
1036 case CSS_TYPE_SYMBOL:
1037 /* Read comma separated list of font family names */
1038 dstr = dStr_new("");
1039 while (ttype == CSS_TK_SYMBOL || ttype == CSS_TK_STRING ||
1040 (ttype == CSS_TK_CHAR && tval[0] == ',')) {
1041 if (spaceSeparated)
1042 dStr_append_c(dstr, ' ');
1043 dStr_append(dstr, tval);
1044 ret = true;
1045 nextToken();
1046 }
1047
1048 if (ret) {
1049 val->strVal = dStrstrip(dstr->str);
1050 dStr_free(dstr, 0);
1051 } else {
1052 dStr_free(dstr, 1);
1053 }
1054 break;
1055
1057 ival = 0;
1058 if (ttype == CSS_TK_DECINT) {
1059 ival = strtol(tval, NULL, 10);
1060 if (ival < 100 || ival > 900)
1061 /* invalid */
1062 ival = 0;
1063 }
1064
1065 if (ival != 0) {
1066 val->intVal = ival;
1067 ret = true;
1068 nextToken();
1069 }
1070 break;
1071
1072 case CSS_TYPE_URI:
1073 if (ttype == CSS_TK_SYMBOL) {
1074 if (dStrAsciiCasecmp(tval, "url") == 0) {
1075 val->strVal = parseUrl();
1076 if (val->strVal)
1077 ret = true;
1078 } else if (dStrAsciiCasecmp(tval, "none") == 0) {
1079 val->strVal = NULL;
1080 ret = true;
1081 }
1082 nextToken();
1083 }
1084 break;
1085
1087 // 'background-position' consists of one or two values: vertical and
1088 // horizontal position; in most cases in this order. However, as long it
1089 // is unambigous, the order can be switched: "10px left" and "left 10px"
1090 // are both possible and have the same effect. For this reason, all
1091 // possibilities are tested in parallel.
1092
1093 bool h[2], v[2];
1094 int pos[2];
1095 h[0] = v[0] = h[1] = v[1] = false;
1096
1097 // First: collect values in pos[0] and pos[1], and determine whether
1098 // they can be used for a horizontal (h[i]) or vertical (v[i]) position
1099 // (or both). When neither h[i] or v[i] is set, pos[i] is undefined.
1100 for (i = 0; i < 2; i++) {
1101 CssValueType typeTmp;
1102 // tokenMatchesProperty will, for CSS_PROPERTY_BACKGROUND_POSITION,
1103 // work on both parts, since they are exchangable.
1105 &typeTmp)) {
1106 h[i] = ttype != CSS_TK_SYMBOL ||
1107 (dStrAsciiCasecmp(tval, "top") != 0 &&
1108 dStrAsciiCasecmp(tval, "bottom") != 0);
1109 v[i] = ttype != CSS_TK_SYMBOL ||
1110 (dStrAsciiCasecmp(tval, "left") != 0 &&
1111 dStrAsciiCasecmp(tval, "right") != 0);
1112 } else
1113 // No match.
1114 h[i] = v[i] = false;
1115
1116 if (h[i] || v[i]) {
1117 // Calculate values.
1118 if (ttype == CSS_TK_SYMBOL) {
1119 if (dStrAsciiCasecmp(tval, "top") == 0 ||
1120 dStrAsciiCasecmp(tval, "left") == 0) {
1122 nextToken();
1123 } else if (dStrAsciiCasecmp(tval, "center") == 0) {
1125 nextToken();
1126 } else if (dStrAsciiCasecmp(tval, "bottom") == 0 ||
1127 dStrAsciiCasecmp(tval, "right") == 0) {
1129 nextToken();
1130 } else
1131 // tokenMatchesProperty should have returned "false" already.
1133 } else {
1134 // We can assume <length> or <percentage> here ...
1135 CssPropertyValue valTmp;
1136 if (parseValue(prop, CSS_TYPE_LENGTH_PERCENTAGE, &valTmp)) {
1137 pos[i] = valTmp.intVal;
1138 ret = true;
1139 } else if (parseValue(prop, CSS_TYPE_SIGNED_LENGTH, &valTmp)) {
1140 pos[i] = valTmp.intVal;
1141 ret = true;
1142 } else
1143 // ... but something may still fail.
1144 h[i] = v[i] = false;
1145 }
1146 }
1147
1148 // If the first value cannot be read, do not read the second.
1149 if (!h[i] && !v[i])
1150 break;
1151 }
1152
1153 // Second: Create the final value. Order will be determined here.
1154 if (v[0] || h[0]) {
1155 // If second value is not set, it is set to "center", i. e. 50%, (see
1156 // CSS specification), which is suitable for both dimensions.
1157 if (!h[1] && !v[1]) {
1159 h[1] = v[1] = true;
1160 }
1161
1162 // Only valid, when a combination h/v or v/h is possible.
1163 if ((h[0] && v[1]) || (v[0] && h[1])) {
1164 ret = true;
1166
1167 // Prefer combination h/v:
1168 if (h[0] && v[1]) {
1169 val->posVal->posX = pos[0];
1170 val->posVal->posY = pos[1];
1171 } else {
1172 // This should be v/h:
1173 val->posVal->posX = pos[1];
1174 val->posVal->posY = pos[0];
1175 }
1176 }
1177 }
1178 break;
1179
1180 case CSS_TYPE_INTEGER:
1181 if (ttype == CSS_TK_DECINT) {
1182 val->intVal = strtol(tval, NULL, 10);
1183 ret = true;
1184 nextToken();
1185 }
1186 break;
1187
1188 case CSS_TYPE_UNUSED:
1189 /* nothing */
1190 break;
1191
1192 default:
1193 assert(false); /* not reached */
1194 }
1195
1196 return ret;
1197}
1198
1200{
1201 if (ttype == CSS_TK_CHAR && tval[0] == '!') {
1202 nextToken();
1203 if (ttype == CSS_TK_SYMBOL &&
1204 dStrAsciiCasecmp(tval, "important") == 0) {
1205 nextToken();
1206 return true;
1207 }
1208 }
1209
1210 return false;
1211}
1212
1216static int Css_property_info_cmp(const void *a, const void *b)
1217{
1218 return dStrAsciiCasecmp(((CssPropertyInfo *) a)->symbol,
1219 ((CssPropertyInfo *) b)->symbol);
1220}
1221
1222
1226static int Css_shorthand_info_cmp(const void *a, const void *b)
1227{
1228 return dStrAsciiCasecmp(((CssShorthandInfo *) a)->symbol,
1229 ((CssShorthandInfo *) b)->symbol);
1230}
1231
1233 CssPropertyList *importantProps)
1234{
1235 CssPropertyInfo pi = {NULL, {CSS_TYPE_UNUSED}, NULL}, *pip;
1236 CssShorthandInfo *sip;
1238
1239 CssPropertyName prop;
1240 CssPropertyValue val, dir_vals[4];
1241 CssValueType dir_types[4];
1242 bool found, weight;
1243 int sh_index, i, j, n;
1244 int dir_set[4][4] = {
1245 /* 1 value */ {0, 0, 0, 0},
1246 /* 2 values */ {0, 0, 1, 1},
1247 /* 3 values */ {0, 2, 1, 1},
1248 /* 4 values */ {0, 2, 3, 1}
1249 };
1250
1251 if (ttype == CSS_TK_SYMBOL) {
1252 pi.symbol = tval;
1253 pip =
1254 (CssPropertyInfo *) bsearch(&pi, Css_property_info,
1256 sizeof(CssPropertyInfo),
1258 if (pip) {
1259 prop = (CssPropertyName) (pip - Css_property_info);
1260 nextToken();
1261 if (ttype == CSS_TK_CHAR && tval[0] == ':') {
1262 nextToken();
1263 if (tokenMatchesProperty (prop, &type) &&
1264 parseValue(prop, type, &val)) {
1265 weight = parseWeight();
1266 if (weight && importantProps)
1267 importantProps->set(prop, type, val);
1268 else
1269 props->set(prop, type, val);
1270 }
1271 }
1272 } else {
1273 /* Try shorthands. */
1274 sip =
1275 (CssShorthandInfo *) bsearch(&pi, Css_shorthand_info,
1277 sizeof(CssShorthandInfo),
1279 if (sip) {
1280 sh_index = sip - Css_shorthand_info;
1281 nextToken();
1282 if (ttype == CSS_TK_CHAR && tval[0] == ':') {
1283 nextToken();
1284
1285 switch (Css_shorthand_info[sh_index].type) {
1286
1287 case CssShorthandInfo::CSS_SHORTHAND_FONT:
1288 /* \todo Implement details. */
1289 case CssShorthandInfo::CSS_SHORTHAND_MULTIPLE:
1290 do {
1291 for (found = false, i = 0;
1292 !found &&
1293 Css_shorthand_info[sh_index].properties[i] !=
1295 i++)
1297 properties[i], &type)) {
1298 found = true;
1300 "will assign to '%s'\n",
1302 [Css_shorthand_info[sh_index]
1303 .properties[i]].symbol);
1304 if (parseValue(Css_shorthand_info[sh_index]
1305 .properties[i], type, &val)) {
1306 weight = parseWeight();
1307 if (weight && importantProps)
1308 importantProps->
1309 set(Css_shorthand_info[sh_index].
1310 properties[i], type, val);
1311 else
1312 props->set(Css_shorthand_info[sh_index].
1313 properties[i], type, val);
1314 }
1315 }
1316 } while (found);
1317 break;
1318
1319 case CssShorthandInfo::CSS_SHORTHAND_DIRECTIONS:
1320 n = 0;
1321 while (n < 4) {
1323 properties[0], &type) &&
1325 .properties[0], type, &val)) {
1326 dir_vals[n] = val;
1327 dir_types[n] = type;
1328 n++;
1329 } else
1330 break;
1331 }
1332
1333 weight = parseWeight();
1334 if (n > 0) {
1335 for (i = 0; i < 4; i++)
1336 if (weight && importantProps)
1337 importantProps->set(Css_shorthand_info[sh_index]
1338 .properties[i],
1339 dir_types[dir_set[n - 1][i]],
1340 dir_vals[dir_set[n - 1][i]]);
1341 else
1342 props->set(Css_shorthand_info[sh_index]
1343 .properties[i],
1344 dir_types[dir_set[n - 1][i]],
1345 dir_vals[dir_set[n - 1][i]]);
1346 } else
1347 MSG_CSS("no values for shorthand property '%s'\n",
1348 Css_shorthand_info[sh_index].symbol);
1349
1350 break;
1351
1352 case CssShorthandInfo::CSS_SHORTHAND_BORDER:
1353 do {
1354 for (found = false, i = 0;
1355 !found && i < 3;
1356 i++)
1358 properties[i], &type)) {
1359 found = true;
1360 if (parseValue(Css_shorthand_info[sh_index]
1361 .properties[i], type, &val)) {
1362 weight = parseWeight();
1363 for (j = 0; j < 4; j++)
1364 if (weight && importantProps)
1365 importantProps->
1366 set(Css_shorthand_info[sh_index].
1367 properties[j * 3 + i], type, val);
1368 else
1369 props->set(Css_shorthand_info[sh_index].
1370 properties[j * 3 + i], type, val);
1371 }
1372 }
1373 } while (found);
1374 break;
1375 }
1376 }
1377 }
1378 }
1379 }
1380
1381 /* Skip all tokens until the expected end. */
1382 while (!(ttype == CSS_TK_END ||
1383 (ttype == CSS_TK_CHAR &&
1384 (tval[0] == ';' || tval[0] == '}'))))
1385 nextToken();
1386
1387 if (ttype == CSS_TK_CHAR && tval[0] == ';')
1388 nextToken();
1389}
1390
1392{
1394
1395 if (ttype == CSS_TK_SYMBOL) {
1396 selector->setElement (a_Html_tag_index(tval));
1397 nextToken();
1398 if (spaceSeparated)
1399 return true;
1400 } else if (ttype == CSS_TK_CHAR && tval[0] == '*') {
1402 nextToken();
1403 if (spaceSeparated)
1404 return true;
1405 } else if (ttype == CSS_TK_CHAR &&
1406 (tval[0] == '#' ||
1407 tval[0] == '.' ||
1408 tval[0] == ':')) {
1409 // nothing to be done in this case
1410 } else {
1411 return false;
1412 }
1413
1414 do {
1415 selectType = CssSimpleSelector::SELECT_NONE;
1416 if (ttype == CSS_TK_CHAR) {
1417 switch (tval[0]) {
1418 case '#':
1419 selectType = CssSimpleSelector::SELECT_ID;
1420 break;
1421 case '.':
1423 break;
1424 case ':':
1426 if (selector->getPseudoClass ())
1427 // pseudo class has been set already.
1428 // As dillo currently only supports :link and :visisted, a
1429 // selector with more than one pseudo class will never match.
1430 // By returning false, the whole CssRule will be dropped.
1431 // \todo adapt this when supporting :hover, :active...
1432 return false;
1433 break;
1434 }
1435 }
1436
1437 if (selectType != CssSimpleSelector::SELECT_NONE) {
1438 nextToken();
1439 if (spaceSeparated)
1440 return false;
1441
1442 if (ttype == CSS_TK_SYMBOL) {
1443 selector->setSelect (selectType, tval);
1444 nextToken();
1445 } else {
1446 return false; // don't accept classes or id's starting with integer
1447 }
1448 if (spaceSeparated)
1449 return true;
1450 }
1451 } while (selectType != CssSimpleSelector::SELECT_NONE);
1452
1453 DEBUG_MSG(DEBUG_PARSE_LEVEL, "end of simple selector (%s, %s, %s, %d)\n",
1454 selector->id, selector->klass,
1455 selector->pseudo, selector->element);
1456
1457 return true;
1458}
1459
1461{
1462 CssSelector *selector = new CssSelector ();
1463
1464 while (true) {
1465 if (! parseSimpleSelector (selector->top ())) {
1466 delete selector;
1467 selector = NULL;
1468 break;
1469 }
1470
1471 if (ttype == CSS_TK_CHAR &&
1472 (tval[0] == ',' || tval[0] == '{')) {
1473 break;
1474 } else if (ttype == CSS_TK_CHAR && tval[0] == '>') {
1476 nextToken();
1477 } else if (ttype == CSS_TK_CHAR && tval[0] == '+') {
1479 nextToken();
1480 } else if (ttype != CSS_TK_END && spaceSeparated) {
1482 } else {
1483 delete selector;
1484 selector = NULL;
1485 break;
1486 }
1487 }
1488
1489 while (ttype != CSS_TK_END &&
1490 (ttype != CSS_TK_CHAR ||
1491 (tval[0] != ',' && tval[0] != '{')))
1492 nextToken();
1493
1494 return selector;
1495}
1496
1498{
1499 lout::misc::SimpleVector < CssSelector * >*list;
1500 CssPropertyList *props, *importantProps;
1501 CssSelector *selector;
1502
1503 list = new lout::misc::SimpleVector < CssSelector * >(1);
1504
1505 while (true) {
1506 selector = parseSelector();
1507
1508 if (selector) {
1509 selector->ref();
1510 list->increase();
1511 list->set(list->size() - 1, selector);
1512 }
1513
1514 // \todo dump whole ruleset in case of parse error as required by CSS 2.1
1515 // however make sure we don't dump it if only dillo fails to parse
1516 // valid CSS.
1517
1518 if (ttype == CSS_TK_CHAR && tval[0] == ',')
1519 /* To read the next token. */
1520 nextToken();
1521 else
1522 /* No more selectors. */
1523 break;
1524 }
1525
1526 DEBUG_MSG(DEBUG_PARSE_LEVEL, "end of %s\n", "selectors");
1527
1528 props = new CssPropertyList(true);
1529 props->ref();
1530 importantProps = new CssPropertyList(true);
1531 importantProps->ref();
1532
1533 /* Read block. ('{' has already been read.) */
1534 if (ttype != CSS_TK_END) {
1535 withinBlock = true;
1536 nextToken();
1537 do
1538 parseDeclaration(props, importantProps);
1539 while (!(ttype == CSS_TK_END ||
1540 (ttype == CSS_TK_CHAR && tval[0] == '}')));
1541 withinBlock = false;
1542 }
1543
1544 for (int i = 0; i < list->size(); i++) {
1545 CssSelector *s = list->get(i);
1546
1549 } else if (origin == CSS_ORIGIN_USER) {
1550 context->addRule(s, props, CSS_PRIMARY_USER);
1551 context->addRule(s, importantProps, CSS_PRIMARY_USER_IMPORTANT);
1552 } else if (origin == CSS_ORIGIN_AUTHOR) {
1554 context->addRule(s, importantProps, CSS_PRIMARY_AUTHOR_IMPORTANT);
1555 }
1556
1557 s->unref();
1558 }
1559
1560 props->unref();
1561 importantProps->unref();
1562
1563 delete list;
1564
1565 if (ttype == CSS_TK_CHAR && tval[0] == '}')
1566 nextToken();
1567}
1568
1570{
1571 Dstr *urlStr = NULL;
1572
1573 if (ttype != CSS_TK_SYMBOL ||
1574 dStrAsciiCasecmp(tval, "url") != 0)
1575 return NULL;
1576
1577 nextToken();
1578
1579 if (ttype != CSS_TK_CHAR || tval[0] != '(')
1580 return NULL;
1581
1582 nextToken();
1583
1584 if (ttype == CSS_TK_STRING) {
1585 urlStr = dStr_new(tval);
1586 nextToken();
1587 } else {
1588 urlStr = dStr_new("");
1589 while (ttype != CSS_TK_END &&
1590 (ttype != CSS_TK_CHAR || tval[0] != ')')) {
1591 dStr_append(urlStr, tval);
1592 nextToken();
1593 }
1594 }
1595
1596 if (ttype != CSS_TK_CHAR || tval[0] != ')') {
1597 dStr_free(urlStr, 1);
1598 urlStr = NULL;
1599 }
1600
1601 if (urlStr) {
1602 DilloUrl *dilloUrl = a_Url_new(urlStr->str, a_Url_str(this->baseUrl));
1603 char *url = dStrdup(a_Url_str(dilloUrl));
1604 a_Url_free(dilloUrl);
1605 dStr_free(urlStr, 1);
1606 return url;
1607 } else {
1608 return NULL;
1609 }
1610}
1611
1613{
1614 char *urlStr = NULL;
1615 bool importSyntaxIsOK = false;
1616 bool mediaSyntaxIsOK = true;
1617 bool mediaIsSelected = true;
1618
1619 nextToken();
1620
1621 if (ttype == CSS_TK_SYMBOL &&
1622 dStrAsciiCasecmp(tval, "url") == 0)
1623 urlStr = parseUrl();
1624 else if (ttype == CSS_TK_STRING)
1625 urlStr = dStrdup (tval);
1626
1627 nextToken();
1628
1629 /* parse a comma-separated list of media */
1630 if (ttype == CSS_TK_SYMBOL) {
1631 mediaSyntaxIsOK = false;
1632 mediaIsSelected = false;
1633 while (ttype == CSS_TK_SYMBOL) {
1634 if (dStrAsciiCasecmp(tval, "all") == 0 ||
1635 dStrAsciiCasecmp(tval, "screen") == 0)
1636 mediaIsSelected = true;
1637 nextToken();
1638 if (ttype == CSS_TK_CHAR && tval[0] == ',') {
1639 nextToken();
1640 } else {
1641 mediaSyntaxIsOK = true;
1642 break;
1643 }
1644 }
1645 }
1646
1647 if (mediaSyntaxIsOK &&
1648 ttype == CSS_TK_CHAR &&
1649 tval[0] == ';') {
1650 importSyntaxIsOK = true;
1651 nextToken();
1652 } else
1654
1655 if (urlStr) {
1656 if (importSyntaxIsOK && mediaIsSelected) {
1657 MSG("CssParser::parseImport(): @import %s\n", urlStr);
1658 DilloUrl *url = a_Html_url_new (html, urlStr, a_Url_str(this->baseUrl),
1659 this->baseUrl ? 1 : 0);
1660 a_Html_load_stylesheet(html, url);
1661 a_Url_free(url);
1662 }
1663 dFree (urlStr);
1664 }
1665}
1666
1668{
1669 bool mediaSyntaxIsOK = false;
1670 bool mediaIsSelected = false;
1671
1672 nextToken();
1673
1674 /* parse a comma-separated list of media */
1675 while (ttype == CSS_TK_SYMBOL) {
1676 if (dStrAsciiCasecmp(tval, "all") == 0 ||
1677 dStrAsciiCasecmp(tval, "screen") == 0)
1678 mediaIsSelected = true;
1679 nextToken();
1680 if (ttype == CSS_TK_CHAR && tval[0] == ',') {
1681 nextToken();
1682 } else {
1683 mediaSyntaxIsOK = true;
1684 break;
1685 }
1686 }
1687
1688 /* check that the syntax is OK so far */
1689 if (!(mediaSyntaxIsOK &&
1690 ttype == CSS_TK_CHAR &&
1691 tval[0] == '{')) {
1693 return;
1694 }
1695
1696 /* parse/ignore the block as required */
1697 if (mediaIsSelected) {
1698 nextToken();
1699 while (ttype != CSS_TK_END) {
1700 parseRuleset();
1701 if (ttype == CSS_TK_CHAR && tval[0] == '}') {
1702 nextToken();
1703 break;
1704 }
1705 }
1706 } else
1707 ignoreBlock();
1708}
1709
1711{
1712 return Css_property_info[name].symbol;
1713}
1714
1716{
1717 int depth = 0;
1718
1719 while (ttype != CSS_TK_END) {
1720 if (ttype == CSS_TK_CHAR) {
1721 if (tval[0] == '{') {
1722 depth++;
1723 } else if (tval[0] == '}') {
1724 depth--;
1725 if (depth == 0) {
1726 nextToken();
1727 return;
1728 }
1729 }
1730 }
1731 nextToken();
1732 }
1733}
1734
1736{
1737 while (ttype != CSS_TK_END) {
1738 if (ttype == CSS_TK_CHAR) {
1739 if (tval[0] == ';') {
1740 nextToken();
1741 return;
1742 } else if (tval[0] =='{') {
1743 ignoreBlock();
1744 return;
1745 }
1746 }
1747 nextToken();
1748 }
1749}
1750
1751void CssParser::parse(DilloHtml *html, const DilloUrl *baseUrl,
1752 CssContext *context,
1753 const char *buf,
1754 int buflen, CssOrigin origin)
1755{
1757 bool importsAreAllowed = true;
1758
1759 while (parser.ttype != CSS_TK_END) {
1760 if (parser.ttype == CSS_TK_CHAR &&
1761 parser.tval[0] == '@') {
1762 parser.nextToken();
1763 if (parser.ttype == CSS_TK_SYMBOL) {
1764 if (dStrAsciiCasecmp(parser.tval, "import") == 0 &&
1765 html != NULL &&
1766 importsAreAllowed) {
1767 parser.parseImport(html);
1768 } else if (dStrAsciiCasecmp(parser.tval, "media") == 0) {
1769 parser.parseMedia();
1770 } else {
1771 parser.ignoreStatement();
1772 }
1773 } else {
1774 parser.ignoreStatement();
1775 }
1776 } else {
1777 importsAreAllowed = false;
1778 parser.parseRuleset();
1779 }
1780 }
1781}
1782
1784 const char *buf, int buflen,
1785 CssPropertyList *props,
1786 CssPropertyList *propsImortant)
1787{
1788 CssParser parser (NULL, CSS_ORIGIN_AUTHOR, baseUrl, buf, buflen);
1789
1790 parser.withinBlock = true;
1791
1792 do
1793 parser.parseDeclaration(props, propsImortant);
1794 while (!(parser.ttype == CSS_TK_END ||
1795 (parser.ttype == CSS_TK_CHAR && parser.tval[0] == '}')));
1796}
#define MSG(...)
Definition bookmarks.c:46
A set of CssStyleSheets.
Definition css.hh:515
void addRule(CssSelector *sel, CssPropertyList *props, CssPrimaryOrder order)
Definition css.cc:529
void parseMedia()
CssContext * context
Definition cssparser.hh:16
void nextToken()
Definition cssparser.cc:521
bool parseValue(CssPropertyName prop, CssValueType type, CssPropertyValue *val)
Definition cssparser.cc:889
bool skipString(int c, const char *string)
Skip string str if it is found in the input buffer.
Definition cssparser.cc:505
bool tokenMatchesProperty(CssPropertyName prop, CssValueType *type)
Definition cssparser.cc:702
bool parseSimpleSelector(CssSimpleSelector *selector)
bool parseRgbColorComponent(int32_t *cc, int *percentage)
Definition cssparser.cc:812
void parseDeclaration(CssPropertyList *props, CssPropertyList *importantProps)
static void parseDeclarationBlock(const DilloUrl *baseUrl, const char *buf, int buflen, CssPropertyList *props, CssPropertyList *propsImortant)
char * parseUrl()
void parseImport(DilloHtml *html)
void ignoreBlock()
@ CSS_TK_DECINT
Definition cssparser.hh:11
@ CSS_TK_SYMBOL
Definition cssparser.hh:11
@ CSS_TK_STRING
Definition cssparser.hh:12
bool withinBlock
Definition cssparser.hh:25
bool parseRgbColor(int32_t *c)
Definition cssparser.cc:845
static const int maxStrLen
Definition cssparser.hh:15
void ungetChar()
Undoes the last getChar().
Definition cssparser.cc:494
bool spaceSeparated
Definition cssparser.hh:26
static void parse(DilloHtml *html, const DilloUrl *baseUrl, CssContext *context, const char *buf, int buflen, CssOrigin origin)
int getChar()
Gets the next character from the buffer, or EOF.
Definition cssparser.cc:476
CssOrigin origin
Definition cssparser.hh:17
static const char * propertyNameString(CssPropertyName name)
bool parseWeight()
char tval[maxStrLen]
Definition cssparser.hh:24
void parseRuleset()
CssTokenType ttype
Definition cssparser.hh:23
const char * buf
Definition cssparser.hh:20
const DilloUrl * baseUrl
Definition cssparser.hh:18
CssSelector * parseSelector()
CssParser(CssContext *context, CssOrigin origin, const DilloUrl *baseUrl, const char *buf, int buflen)
Definition cssparser.cc:457
void ignoreStatement()
A list of CssProperty objects.
Definition css.hh:328
void set(CssPropertyName name, CssValueType type, CssPropertyValue value)
Set property to a given name and type.
Definition css.cc:58
void unref()
Definition css.hh:349
void ref()
Definition css.hh:348
CSS selector class.
Definition css.hh:394
CssSimpleSelector * top()
Definition css.hh:419
void addSimpleSelector(Combinator c)
Definition css.cc:173
@ COMB_DESCENDANT
Definition css.hh:398
@ COMB_CHILD
Definition css.hh:399
@ COMB_ADJACENT_SIBLING
Definition css.hh:400
void ref()
Definition css.hh:438
void unref()
Definition css.hh:439
void setElement(int e)
Definition css.hh:373
char * pseudo
Definition css.hh:355
const char * getPseudoClass()
Definition css.hh:376
@ SELECT_PSEUDO_CLASS
Definition css.hh:367
void setSelect(SelectType t, const char *v)
Definition css.cc:244
lout::misc::SimpleVector< char * > klass
Definition css.hh:356
void increase()
Increase the vector size by one.
Definition misc.hh:161
void set(int i, T t)
Store an object in the vector.
Definition misc.hh:247
T get(int i) const
Return the one element, explicitly.
Definition misc.hh:202
int size() const
Return the number of elements put into this vector.
Definition misc.hh:142
int32_t a_Color_parse(const char *str, int32_t default_color, int *err)
Parse a color string.
Definition colors.c:258
CssPropertyName
Definition css.hh:161
@ CSS_PROPERTY_PADDING_TOP
Definition css.hh:226
@ CSS_PROPERTY_LIST_STYLE_TYPE
Definition css.hh:208
@ CSS_PROPERTY_MARGIN_BOTTOM
Definition css.hh:209
@ CSS_PROPERTY_BORDER_RIGHT_STYLE
Definition css.hh:176
@ CSS_PROPERTY_BORDER_BOTTOM_COLOR
Definition css.hh:168
@ CSS_PROPERTY_MARGIN_RIGHT
Definition css.hh:211
@ CSS_PROPERTY_BORDER_TOP_COLOR
Definition css.hh:179
@ CSS_PROPERTY_BORDER_LEFT_COLOR
Definition css.hh:172
@ CSS_PROPERTY_LIST_STYLE_POSITION
Definition css.hh:207
@ CSS_PROPERTY_END
Definition css.hh:162
@ CSS_PROPERTY_BORDER_RIGHT_WIDTH
Definition css.hh:177
@ CSS_PROPERTY_LAST
Definition css.hh:250
@ CSS_PROPERTY_BACKGROUND_REPEAT
Definition css.hh:167
@ CSS_PROPERTY_FONT_VARIANT
Definition css.hh:200
@ CSS_PROPERTY_BORDER_LEFT_WIDTH
Definition css.hh:174
@ CSS_PROPERTY_PADDING_BOTTOM
Definition css.hh:223
@ CSS_PROPERTY_BACKGROUND_ATTACHMENT
Definition css.hh:163
@ CSS_PROPERTY_OUTLINE_STYLE
Definition css.hh:220
@ CSS_PROPERTY_OUTLINE_WIDTH
Definition css.hh:221
@ CSS_PROPERTY_LIST_STYLE_IMAGE
Definition css.hh:206
@ CSS_PROPERTY_MARGIN_LEFT
Definition css.hh:210
@ CSS_PROPERTY_BORDER_RIGHT_COLOR
Definition css.hh:175
@ CSS_PROPERTY_OUTLINE_COLOR
Definition css.hh:219
@ CSS_PROPERTY_BORDER_TOP_WIDTH
Definition css.hh:181
@ CSS_PROPERTY_MARGIN_TOP
Definition css.hh:212
@ CSS_PROPERTY_PADDING_RIGHT
Definition css.hh:225
@ CSS_PROPERTY_PADDING_LEFT
Definition css.hh:224
@ CSS_PROPERTY_BORDER_LEFT_STYLE
Definition css.hh:173
@ CSS_PROPERTY_BACKGROUND_IMAGE
Definition css.hh:165
@ CSS_PROPERTY_BORDER_TOP_STYLE
Definition css.hh:180
@ CSS_PROPERTY_FONT_STYLE
Definition css.hh:199
@ CSS_PROPERTY_BACKGROUND_COLOR
Definition css.hh:164
@ CSS_PROPERTY_FONT_SIZE
Definition css.hh:196
@ CSS_PROPERTY_BORDER_BOTTOM_STYLE
Definition css.hh:169
@ CSS_PROPERTY_BORDER_BOTTOM_WIDTH
Definition css.hh:170
@ CSS_PROPERTY_BACKGROUND_POSITION
Definition css.hh:166
@ CSS_PROPERTY_FONT_FAMILY
Definition css.hh:195
@ CSS_PROPERTY_FONT_WEIGHT
Definition css.hh:201
CssValueType
Definition css.hh:36
@ CSS_TYPE_UNUSED
Not yet used.
Definition css.hh:65
@ CSS_TYPE_ENUM
Value is i, if represented by enum_symbols[i].
Definition css.hh:39
@ CSS_TYPE_INTEGER
This type is only used internally, for x-* properties.
Definition css.hh:37
@ CSS_TYPE_LENGTH_PERCENTAGE_NUMBER
Definition css.hh:52
@ CSS_TYPE_SIGNED_LENGTH
As CSS_TYPE_LENGTH but may be negative.
Definition css.hh:51
@ CSS_TYPE_MULTI_ENUM
For all enum_symbols[i], 1 << i are combined.
Definition css.hh:41
@ CSS_TYPE_URI
<uri>
Definition css.hh:63
@ CSS_TYPE_LENGTH_PERCENTAGE
<length> or <percentage>.
Definition css.hh:43
@ CSS_TYPE_LENGTH
<length>, represented as CssLength.
Definition css.hh:45
@ CSS_TYPE_STRING
<string>
Definition css.hh:58
@ CSS_TYPE_SYMBOL
Symbols, which are directly copied (as opposed to CSS_TYPE_ENUM and CSS_TYPE_MULTI_ENUM).
Definition css.hh:59
@ CSS_TYPE_FONT_WEIGHT
this very special and only used by 'font-weight'
Definition css.hh:56
@ CSS_TYPE_COLOR
Represented as integer.
Definition css.hh:55
@ CSS_TYPE_BACKGROUND_POSITION
Definition css.hh:64
@ CSS_TYPE_AUTO
Represented as CssLength of type CSS_LENGTH_TYPE_AUTO.
Definition css.hh:53
CssLength CSS_CREATE_LENGTH(float v, CssLengthType t)
Definition css.hh:106
@ CSS_PRIMARY_USER_IMPORTANT
Definition css.hh:26
@ CSS_PRIMARY_AUTHOR_IMPORTANT
Definition css.hh:25
@ CSS_PRIMARY_USER
Definition css.hh:23
@ CSS_PRIMARY_AUTHOR
Definition css.hh:24
@ CSS_PRIMARY_USER_AGENT
Definition css.hh:22
CssLengthType
Definition css.hh:93
@ CSS_LENGTH_TYPE_NONE
Definition css.hh:94
@ CSS_LENGTH_TYPE_EM
Definition css.hh:98
@ CSS_LENGTH_TYPE_MM
"cm", "in", "pt" and "pc" are converted into millimeters.
Definition css.hh:96
@ CSS_LENGTH_TYPE_PX
Definition css.hh:95
@ CSS_LENGTH_TYPE_EX
Definition css.hh:99
@ CSS_LENGTH_TYPE_PERCENTAGE
Definition css.hh:100
@ CSS_LENGTH_TYPE_AUTO
This can be used as a simple value.
Definition css.hh:103
CssOrigin
Definition css.hh:30
@ CSS_ORIGIN_USER
Definition css.hh:32
@ CSS_ORIGIN_AUTHOR
Definition css.hh:33
@ CSS_ORIGIN_USER_AGENT
Definition css.hh:31
static const char *const Css_border_width_enum_vals[]
Definition cssparser.cc:71
const CssPropertyName Css_font_properties[]
Definition cssparser.cc:410
static const char *const Css_background_repeat_enum_vals[]
Definition cssparser.cc:54
static const char *const Css_white_space_vals[]
Definition cssparser.cc:157
static const char *const Css_text_align_enum_vals[]
Definition cssparser.cc:140
static const CssShorthandInfo Css_shorthand_info[]
Definition cssparser.cc:419
static const char *const Css_list_style_type_enum_vals[]
Definition cssparser.cc:124
#define DEBUG_TOKEN_LEVEL
Definition cssparser.cc:32
const CssPropertyName Css_border_top_properties[]
Definition cssparser.cc:353
static const char *const Css_word_spacing_enum_vals[]
Definition cssparser.cc:161
static const char *const Css_text_transform_enum_vals[]
Definition cssparser.cc:148
#define DEBUG_PARSE_LEVEL
Definition cssparser.cc:33
static const char *const Css_overflow_enum_vals[]
Definition cssparser.cc:132
static const char *const Css_background_attachment_enum_vals[]
Definition cssparser.cc:50
const CssPropertyName Css_background_properties[]
Definition cssparser.cc:309
static const char *const Css_font_size_enum_vals[]
Definition cssparser.cc:95
static const char *const Css_vertical_align_vals[]
Definition cssparser.cc:152
static const char *const Css_font_variant_enum_vals[]
Definition cssparser.cc:104
static const char *const Css_cursor_enum_vals[]
Definition cssparser.cc:79
static const char *const Css_clear_enum_vals[]
Definition cssparser.cc:75
const CssPropertyName Css_padding_properties[]
Definition cssparser.cc:388
const CssPropertyInfo Css_property_info[CSS_PROPERTY_LAST]
Definition cssparser.cc:165
static const char *const Css_font_weight_enum_vals[]
Definition cssparser.cc:108
const CssPropertyName Css_outline_properties[]
Definition cssparser.cc:381
const CssPropertyName Css_border_properties[]
Definition cssparser.cc:395
static const char *const Css_display_enum_vals[]
Definition cssparser.cc:85
#define MSG_CSS(A,...)
Definition cssparser.cc:31
static int Css_property_info_cmp(const void *a, const void *b)
bsearch(3) compare function for searching properties
const CssPropertyName Css_border_right_properties[]
Definition cssparser.cc:339
const CssPropertyName Css_border_bottom_properties[]
Definition cssparser.cc:318
static const char *const Css_line_height_enum_vals[]
Definition cssparser.cc:120
const CssPropertyName Css_border_color_properties[4]
Definition cssparser.cc:325
static const char *const Css_position_enum_vals[]
Definition cssparser.cc:136
static const char *const Css_list_style_position_enum_vals[]
Definition cssparser.cc:116
const CssPropertyName Css_border_style_properties[]
Definition cssparser.cc:346
static int Css_shorthand_info_cmp(const void *a, const void *b)
bsearch(3) compare function for searching shorthands
#define CSS_SHORTHAND_NUM
Definition cssparser.cc:450
static const char *const Css_border_collapse_enum_vals[]
Definition cssparser.cc:58
static const char *const Css_text_decoration_enum_vals[]
Definition cssparser.cc:144
static const char *const Css_letter_spacing_enum_vals[]
Definition cssparser.cc:112
static const char *const Css_font_style_enum_vals[]
Definition cssparser.cc:100
const CssPropertyName Css_border_left_properties[]
Definition cssparser.cc:332
const CssPropertyName Css_margin_properties[]
Definition cssparser.cc:374
static const char *const Css_border_style_enum_vals[]
Definition cssparser.cc:66
const CssPropertyName Css_border_width_properties[]
Definition cssparser.cc:360
#define CSS_NUM_PARSED_PROPERTIES
Definition cssparser.cc:40
static const char *const Css_border_color_enum_vals[]
Definition cssparser.cc:62
const CssPropertyName Css_list_style_properties[]
Definition cssparser.cc:367
static const char *const Css_float_enum_vals[]
Definition cssparser.cc:91
#define DEBUG_MSG(level,...)
Definition debug.hh:29
void dFree(void *mem)
Definition dlib.c:68
int dStrAsciiCasecmp(const char *s1, const char *s2)
Definition dlib.c:203
char * dStrstrip(char *s)
Remove leading and trailing whitespace.
Definition dlib.c:122
void dStr_append(Dstr *ds, const char *s)
Append a C string to a Dstr.
Definition dlib.c:316
char * dStrdup(const char *s)
Definition dlib.c:77
void dStr_free(Dstr *ds, int all)
Free a dillo string.
Definition dlib.c:337
void dStr_append_c(Dstr *ds, int c)
Append one character.
Definition dlib.c:349
Dstr * dStr_new(const char *s)
Create a new string.
Definition dlib.c:325
#define dNew(type, count)
Definition dlib.h:49
DilloUrl * a_Html_url_new(DilloHtml *html, const char *url_str, const char *base_url, int use_base_url)
Wrapper for a_Url_new that adds an error detection message.
Definition html.cc:171
int a_Html_tag_index(const char *tag)
Get 'tag' index.
Definition html.cc:3609
void a_Html_load_stylesheet(DilloHtml *html, DilloUrl *url)
Tell cache to retrieve a stylesheet.
Definition html.cc:3246
Anything related to Dillo Widget styles is defined here.
Definition style.cc:34
void assertNotReached()
Definition misc.hh:36
Definition url.h:88
Definition dlib.h:102
Dstr_char_t * str
Definition dlib.h:105
CssBackgroundPosition * posVal
Definition css.hh:261
char * strVal
Definition css.hh:260
int32_t intVal
Definition css.hh:259
void a_Url_free(DilloUrl *url)
Free a DilloUrl.
Definition url.c:208
DilloUrl * a_Url_new(const char *url_str, const char *base_url)
Transform (and resolve) an URL string into the respective DilloURL.
Definition url.c:371
char * a_Url_str(const DilloUrl *u)
Return the url as a string.
Definition url.c:66