summaryrefslogtreecommitdiff
path: root/src/cssparser.cc
diff options
context:
space:
mode:
authorJohannes Hofmann <Johannes.Hofmann@gmx.de>2011-05-28 20:48:21 +0200
committerJohannes Hofmann <Johannes.Hofmann@gmx.de>2011-05-28 20:48:21 +0200
commitb0b0cddaff10b4cff371b8bb7aa21e045f8e3915 (patch)
tree10f178f4d8cb6ad5b80cba3590d9dc0107027655 /src/cssparser.cc
parent1351b8d80044b898f92557e7ff90096deee5f5bc (diff)
parentb99998a37d3ab1336d0ce82ddc60d0c406a2fd1b (diff)
merge
Diffstat (limited to 'src/cssparser.cc')
-rw-r--r--src/cssparser.cc205
1 files changed, 170 insertions, 35 deletions
diff --git a/src/cssparser.cc b/src/cssparser.cc
index 9d141293..7b522c8c 100644
--- a/src/cssparser.cc
+++ b/src/cssparser.cc
@@ -47,6 +47,14 @@ typedef struct {
const char *const *enum_symbols;
} CssPropertyInfo;
+static const char *const Css_border_collapse_enum_vals[] = {
+ "separate", "collapse", NULL
+};
+
+static const char *const Css_border_color_enum_vals[] = {
+ "transparent", NULL
+};
+
static const char *const Css_border_style_enum_vals[] = {
"none", "hidden", "dotted", "dashed", "solid", "double", "groove",
"ridge", "inset", "outset", NULL
@@ -81,6 +89,10 @@ static const char *const Css_font_style_enum_vals[] = {
"normal", "italic", "oblique", NULL
};
+static const char *const Css_font_variant_enum_vals[] = {
+ "normal", "small-caps", NULL
+};
+
static const char *const Css_font_weight_enum_vals[] = {
"bold", "bolder", "light", "lighter", "normal", NULL
};
@@ -132,24 +144,29 @@ const CssPropertyInfo Css_property_info[CSS_PROPERTY_LAST] = {
{"background-image", {CSS_TYPE_UNUSED}, NULL},
{"background-position", {CSS_TYPE_UNUSED}, NULL},
{"background-repeat", {CSS_TYPE_UNUSED}, NULL},
- {"border-bottom-color", {CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, NULL},
+ {"border-bottom-color", {CSS_TYPE_ENUM, CSS_TYPE_COLOR, CSS_TYPE_UNUSED},
+ Css_border_color_enum_vals},
{"border-bottom-style", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED},
Css_border_style_enum_vals},
{"border-bottom-width", {CSS_TYPE_ENUM, CSS_TYPE_LENGTH, CSS_TYPE_UNUSED},
Css_border_width_enum_vals},
- {"border-collapse", {CSS_TYPE_UNUSED}, NULL},
- {"border-left-color", {CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, NULL},
+ {"border-collapse", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED},
+ Css_border_collapse_enum_vals},
+ {"border-left-color", {CSS_TYPE_ENUM, CSS_TYPE_COLOR, CSS_TYPE_UNUSED},
+ Css_border_color_enum_vals},
{"border-left-style", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED},
Css_border_style_enum_vals},
{"border-left-width", {CSS_TYPE_ENUM, CSS_TYPE_LENGTH, CSS_TYPE_UNUSED},
Css_border_width_enum_vals},
- {"border-right-color", {CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, NULL},
+ {"border-right-color", {CSS_TYPE_ENUM, CSS_TYPE_COLOR, CSS_TYPE_UNUSED},
+ Css_border_color_enum_vals},
{"border-right-style", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED},
Css_border_style_enum_vals},
{"border-rigth-width", {CSS_TYPE_ENUM, CSS_TYPE_LENGTH, CSS_TYPE_UNUSED},
Css_border_width_enum_vals},
{"border-spacing", {CSS_TYPE_LENGTH, CSS_TYPE_UNUSED}, NULL},
- {"border-top-color", {CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, NULL},
+ {"border-top-color", {CSS_TYPE_ENUM, CSS_TYPE_COLOR, CSS_TYPE_UNUSED},
+ Css_border_color_enum_vals},
{"border-top-style", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED},
Css_border_style_enum_vals},
{"border-top-width", {CSS_TYPE_ENUM, CSS_TYPE_LENGTH, CSS_TYPE_UNUSED},
@@ -173,7 +190,8 @@ const CssPropertyInfo Css_property_info[CSS_PROPERTY_LAST] = {
{"font-size-adjust", {CSS_TYPE_UNUSED}, NULL},
{"font-stretch", {CSS_TYPE_UNUSED}, NULL},
{"font-style", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED}, Css_font_style_enum_vals},
- {"font-variant", {CSS_TYPE_UNUSED}, NULL},
+ {"font-variant", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED},
+ Css_font_variant_enum_vals},
{"font-weight", {CSS_TYPE_ENUM, CSS_TYPE_FONT_WEIGHT, CSS_TYPE_UNUSED},
Css_font_weight_enum_vals},
{"height", {CSS_TYPE_LENGTH_PERCENTAGE, CSS_TYPE_UNUSED}, NULL},
@@ -212,7 +230,7 @@ const CssPropertyInfo Css_property_info[CSS_PROPERTY_LAST] = {
{"text-align", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED}, Css_text_align_enum_vals},
{"text-decoration", {CSS_TYPE_MULTI_ENUM, CSS_TYPE_UNUSED},
Css_text_decoration_enum_vals},
- {"text-indent", {CSS_TYPE_UNUSED}, NULL},
+ {"text-indent", {CSS_TYPE_LENGTH_PERCENTAGE, CSS_TYPE_UNUSED}, NULL},
{"text-shadow", {CSS_TYPE_UNUSED}, NULL},
{"text-transform", {CSS_TYPE_UNUSED}, NULL},
{"top", {CSS_TYPE_UNUSED}, NULL},
@@ -441,21 +459,21 @@ void CssParser::ungetChar()
/*
* Skip string str if it is found in the input buffer.
+ * If string is found leave bufptr pointing to last matched char.
* If not wind back. The first char is passed as parameter c
* to avoid unnecessary getChar() / ungetChar() calls.
*/
inline bool CssParser::skipString(int c, const char *str)
{
- int n = 0;
+ for (int n = 0; str[n]; n++) {
+ if (n > 0)
+ c = getChar();
- while (str[n]) {
if (str[n] != c) {
while (n--)
ungetChar();
return false;
}
- c = getChar();
- n++;
}
return true;
@@ -663,9 +681,9 @@ bool CssParser::tokenMatchesProperty(CssPropertyName prop, CssValueType *type)
case CSS_TYPE_MULTI_ENUM:
if (ttype == CSS_TK_SYMBOL) {
- if (dStrcasecmp(tval, "none") == 0)
- return true;
- else {
+ if (dStrcasecmp(tval, "none") == 0) {
+ return true;
+ } else {
for (i = 0; Css_property_info[prop].enum_symbols[i]; i++) {
if (dStrcasecmp(tval,
Css_property_info[prop].enum_symbols[i]) == 0)
@@ -1409,54 +1427,171 @@ char * CssParser::parseUrl()
void CssParser::parseImport(DilloHtml *html, DilloUrl *baseUrl)
{
char *urlStr = NULL;
+ bool importSyntaxIsOK = false;
+ bool mediaSyntaxIsOK = true;
+ bool mediaIsSelected = true;
- if (html != NULL &&
- ttype == CSS_TK_SYMBOL &&
- dStrcasecmp(tval, "import") == 0) {
- nextToken();
+ nextToken();
- if (ttype == CSS_TK_SYMBOL &&
- dStrcasecmp(tval, "url") == 0)
- urlStr = parseUrl();
- else if (ttype == CSS_TK_STRING)
- urlStr = dStrdup (tval);
+ if (ttype == CSS_TK_SYMBOL &&
+ dStrcasecmp(tval, "url") == 0)
+ urlStr = parseUrl();
+ else if (ttype == CSS_TK_STRING)
+ urlStr = dStrdup (tval);
- /* Skip all tokens until the expected end. */
- while (!(ttype == CSS_TK_END ||
- (ttype == CSS_TK_CHAR && (tval[0] == ';'))))
+ nextToken();
+
+ /* parse a comma-separated list of media */
+ if (ttype == CSS_TK_SYMBOL) {
+ mediaSyntaxIsOK = false;
+ mediaIsSelected = false;
+ while (ttype == CSS_TK_SYMBOL) {
+ if (dStrcasecmp(tval, "all") == 0 ||
+ dStrcasecmp(tval, "screen") == 0)
+ mediaIsSelected = true;
nextToken();
+ if (ttype == CSS_TK_CHAR && tval[0] == ',') {
+ nextToken();
+ } else {
+ mediaSyntaxIsOK = true;
+ break;
+ }
+ }
+ }
+ if (mediaSyntaxIsOK &&
+ ttype == CSS_TK_CHAR &&
+ tval[0] == ';') {
+ importSyntaxIsOK = true;
nextToken();
+ } else
+ ignoreStatement();
- if (urlStr) {
+ if (urlStr) {
+ if (importSyntaxIsOK && mediaIsSelected) {
MSG("CssParser::parseImport(): @import %s\n", urlStr);
DilloUrl *url = a_Html_url_new (html, urlStr, a_Url_str(baseUrl),
baseUrl ? 1 : 0);
a_Html_load_stylesheet(html, url);
a_Url_free(url);
- dFree (urlStr);
+ }
+ dFree (urlStr);
+ }
+}
+
+void CssParser::parseMedia()
+{
+ bool mediaSyntaxIsOK = false;
+ bool mediaIsSelected = false;
+
+ nextToken();
+
+ /* parse a comma-separated list of media */
+ while (ttype == CSS_TK_SYMBOL) {
+ if (dStrcasecmp(tval, "all") == 0 ||
+ dStrcasecmp(tval, "screen") == 0)
+ mediaIsSelected = true;
+ nextToken();
+ if (ttype == CSS_TK_CHAR && tval[0] == ',') {
+ nextToken();
+ } else {
+ mediaSyntaxIsOK = true;
+ break;
}
}
+
+ /* check that the syntax is OK so far */
+ if (!(mediaSyntaxIsOK &&
+ ttype == CSS_TK_CHAR &&
+ tval[0] == '{')) {
+ ignoreStatement();
+ return;
+ }
+
+ /* parse/ignore the block as required */
+ if (mediaIsSelected) {
+ nextToken();
+ while (ttype != CSS_TK_END) {
+ parseRuleset();
+ if (ttype == CSS_TK_CHAR && tval[0] == '}') {
+ nextToken();
+ break;
+ }
+ }
+ } else
+ ignoreBlock();
}
const char * CssParser::propertyNameString(CssPropertyName name)
{
return Css_property_info[name].symbol;
}
+
+void CssParser::ignoreBlock()
+{
+ int depth = 0;
+
+ while (ttype != CSS_TK_END) {
+ if (ttype == CSS_TK_CHAR) {
+ if (tval[0] == '{') {
+ depth++;
+ } else if (tval[0] == '}') {
+ depth--;
+ if (depth == 0) {
+ nextToken();
+ return;
+ }
+ }
+ }
+ nextToken();
+ }
+}
+
+void CssParser::ignoreStatement()
+{
+ while (ttype != CSS_TK_END) {
+ if (ttype == CSS_TK_CHAR) {
+ if (tval[0] == ';') {
+ nextToken();
+ return;
+ } else if (tval[0] =='{') {
+ ignoreBlock();
+ return;
+ }
+ }
+ nextToken();
+ }
+}
void CssParser::parse(DilloHtml *html, DilloUrl *url, CssContext * context,
const char *buf,
int buflen, CssOrigin origin)
{
CssParser parser (context, origin, buf, buflen);
-
- while (parser.ttype == CSS_TK_CHAR && parser.tval[0] == '@') {
- parser.nextToken();
- parser.parseImport(html, url);
+ bool importsAreAllowed = true;
+
+ while (parser.ttype != CSS_TK_END) {
+ if (parser.ttype == CSS_TK_CHAR &&
+ parser.tval[0] == '@') {
+ parser.nextToken();
+ if (parser.ttype == CSS_TK_SYMBOL) {
+ if (dStrcasecmp(parser.tval, "import") == 0 &&
+ html != NULL &&
+ importsAreAllowed) {
+ parser.parseImport(html, url);
+ } else if (dStrcasecmp(parser.tval, "media") == 0) {
+ parser.parseMedia();
+ } else {
+ parser.ignoreStatement();
+ }
+ } else {
+ parser.ignoreStatement();
+ }
+ } else {
+ importsAreAllowed = false;
+ parser.parseRuleset();
+ }
}
-
- while (parser.ttype != CSS_TK_END)
- parser.parseRuleset();
}
CssPropertyList *CssParser::parseDeclarationBlock(const char *buf, int buflen)