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