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