dillo  3.0.5
About: dillo is a small, fast, extensible Web browser particularly suitable for older or smaller computers and embedded systems (but only limited or no support for frames, CSS, JavaScript, Java).
  Fossies Dox: dillo-3.0.5.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)  

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