summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am7
-rw-r--r--src/bw.c4
-rw-r--r--src/bw.h5
-rw-r--r--src/colors.c9
-rw-r--r--src/css.cc340
-rw-r--r--src/css.hh313
-rw-r--r--src/cssparser.cc1163
-rw-r--r--src/cssparser.hh63
-rw-r--r--src/doctree.hh20
-rw-r--r--src/form.cc31
-rw-r--r--src/html.cc850
-rw-r--r--src/html_common.hh20
-rw-r--r--src/nav.c1
-rw-r--r--src/plain.cc4
-rw-r--r--src/styleengine.cc424
-rw-r--r--src/styleengine.hh75
-rw-r--r--src/table.cc188
-rw-r--r--src/web.cc4
18 files changed, 2973 insertions, 548 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 8da631ea..e87c8d74 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -67,6 +67,13 @@ dillo_SOURCES = \
dicache.h \
capi.c \
capi.h \
+ css.cc \
+ css.hh \
+ cssparser.cc \
+ cssparser.hh \
+ doctree.hh \
+ styleengine.cc \
+ styleengine.hh \
plain.cc \
html.cc \
html.hh \
diff --git a/src/bw.c b/src/bw.c
index 27f3066c..d0c92086 100644
--- a/src/bw.c
+++ b/src/bw.c
@@ -63,6 +63,7 @@ BrowserWindow *a_Bw_new()
bw->ImageClients = dList_new(8);
bw->NumImages = 0;
bw->NumImagesGot = 0;
+ bw->NumPendingStyleSheets = 0;
bw->PageUrls = dList_new(8);
bw->Docs = dList_new(8);
@@ -253,6 +254,9 @@ void a_Bw_cleanup(BrowserWindow *bw)
/* Zero image-progress data */
bw->NumImages = 0;
bw->NumImagesGot = 0;
+
+ /* Zero stylesheet counter */
+ bw->NumPendingStyleSheets = 0;
}
/*--------------------------------------------------------------------------*/
diff --git a/src/bw.h b/src/bw.h
index 4345bf54..1dcf3a3a 100644
--- a/src/bw.h
+++ b/src/bw.h
@@ -38,6 +38,8 @@ struct _BrowserWindow
int NumImages;
/* Number of images already loaded */
int NumImagesGot;
+ /* Number of not yet arrived style sheets */
+ int NumPendingStyleSheets;
/* List of all Urls requested by this page (and its types) */
Dlist *PageUrls;
@@ -57,8 +59,7 @@ struct _BrowserWindow
* redirection loops (accounts for WEB_RootUrl only) */
int redirect_level;
- /* TODO: maybe this fits better in the linkblock.
- * Although having it here avoids having a signal for handling it. */
+ /* HTML-bugs detected at parse time */
int num_page_bugs;
Dstr *page_bugs;
};
diff --git a/src/colors.c b/src/colors.c
index 9a4c8c8e..6a684dde 100644
--- a/src/colors.c
+++ b/src/colors.c
@@ -204,7 +204,7 @@ static const struct key {
#define NCOLORS (sizeof(color_keyword) / sizeof(struct key))
/*
- * Parse a color in hex (RRGGBB)
+ * Parse a color in hex (RRGGBB) or (RGB)
*
* Return Value:
* parsed color if successful (err = 0),
@@ -219,7 +219,12 @@ static int32_t Color_parse_hex (const char *s, int32_t default_color, int *err)
ret_color = strtol(s, &tail, 16);
if (tail - s == 6)
*err = 0;
- else
+ else if (tail - s == 3) { /* #RGB as allowed by CSS */
+ *err = 0;
+ ret_color = ((ret_color & 0xf00) << 12) | ((ret_color & 0xf00) << 8) |
+ ((ret_color & 0x0f0) << 8) | ((ret_color & 0x0f0) << 4) |
+ ((ret_color & 0x00f) << 4) | ((ret_color & 0x00f) << 0);
+ } else
ret_color = default_color;
return ret_color;
diff --git a/src/css.cc b/src/css.cc
new file mode 100644
index 00000000..4982bc4b
--- /dev/null
+++ b/src/css.cc
@@ -0,0 +1,340 @@
+/*
+ * File: css.cc
+ *
+ * Copyright 2008 Jorge Arellano Cid <jcid@dillo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <stdio.h>
+#include <math.h>
+#include "../dlib/dlib.h"
+#include "prefs.h"
+#include "html_common.hh"
+#include "css.hh"
+#include "cssparser.hh"
+
+using namespace dw::core::style;
+
+void CssProperty::print () {
+ fprintf (stderr, "%s - %d\n", Css_property_info[name].symbol, value.intVal);
+}
+
+void CssPropertyList::set (CssProperty::Name name, CssProperty::Value value) {
+ for (int i = 0; i < size (); i++)
+ if (getRef (i)->name == name) {
+ getRef (i)->value = value;
+ return;
+ }
+
+ increase ();
+ getRef (size () - 1)->name = name;
+ getRef (size () - 1)->value = value;
+}
+
+void CssPropertyList::apply (CssPropertyList *props) {
+ for (int i = 0; i < size (); i++)
+ props->set (getRef (i)->name, getRef (i)->value);
+}
+
+void CssPropertyList::print () {
+ for (int i = 0; i < size (); i++)
+ getRef (i)->print ();
+}
+
+CssSelector::CssSelector (int element, const char *klass,
+ const char *pseudo, const char *id) {
+ refCount = 0;
+ selectorList = new lout::misc::SimpleVector
+ <struct CombinatorAndSelector> (1);
+ selectorList->increase ();
+ top ()->element = element;
+ top ()->klass = klass;
+ top ()->pseudo = pseudo;
+ top ()->id = id;
+};
+
+CssSelector::~CssSelector () {
+ delete selectorList;
+}
+
+bool CssSelector::match (Doctree *docTree) {
+ CssSimpleSelector *sel;
+ Combinator comb;
+ const DoctreeNode *node = docTree->top ();
+
+ assert (selectorList->size () > 0);
+
+ sel = top ();
+
+ if (! sel->match (node))
+ return false;
+
+ for (int i = selectorList->size () - 2; i >= 0; i--) {
+ sel = &selectorList->getRef (i)->selector;
+ comb = selectorList->getRef (i + 1)->combinator;
+ node = docTree->parent (node);
+
+ if (node == NULL)
+ return false;
+
+ switch (comb) {
+ case CHILD:
+ if (!sel->match (node))
+ return false;
+ break;
+ case DESCENDENT:
+ while (!sel->match (node)) {
+ node = docTree->parent (node);
+ if (node == NULL)
+ return false;
+ }
+ break;
+ default:
+ return false; // \todo implement other combinators
+ }
+ }
+
+ return true;
+}
+
+void CssSelector::addSimpleSelector (Combinator c, int element,
+ const char *klass, const char *pseudo,
+ const char *id) {
+ selectorList->increase ();
+
+ selectorList->getRef (selectorList->size () - 1)->combinator = c;
+ top ()->element = element;
+ top ()->klass = klass;
+ top ()->pseudo = pseudo;
+ top ()->id = id;
+
+}
+
+void CssSelector::print () {
+ for (int i = 0; i < selectorList->size () - 1; i++) {
+ selectorList->getRef (i)->selector.print ();
+
+ if (i < selectorList->size () - 2) {
+ switch (selectorList->getRef (i)->combinator) {
+ case CHILD:
+ fprintf (stderr, ">");
+ break;
+ case DESCENDENT:
+ fprintf (stderr, " ");
+ break;
+ default:
+ fprintf (stderr, "?");
+ break;
+ }
+ }
+ }
+
+ top ()->print ();
+ fprintf (stderr, "\n");
+}
+
+bool CssSimpleSelector::match (const DoctreeNode *n) {
+ if (element != ELEMENT_ANY && element != n->element)
+ return false;
+ if (klass != NULL &&
+ (n->klass == NULL || strcasecmp (klass, n->klass) != 0))
+ return false;
+ if (pseudo != NULL &&
+ (n->pseudo == NULL || strcasecmp (pseudo, n->pseudo) != 0))
+ return false;
+ if (id != NULL && (n->id == NULL || strcasecmp (id, n->id) != 0))
+ return false;
+
+ return true;
+}
+
+void CssSimpleSelector::print () {
+ fprintf (stderr, "Element %d, class %s, pseudo %s, id %s ",
+ element, klass, pseudo, id);
+}
+
+CssRule::CssRule (CssSelector *selector, CssPropertyList *props) {
+ refCount = 0;
+ this->selector = selector;
+ this->selector->ref ();
+ this->props = props;
+ this->props->ref ();
+};
+
+CssRule::~CssRule () {
+ selector->unref ();
+ props->unref ();
+};
+
+void CssRule::apply (CssPropertyList *props, Doctree *docTree) {
+ if (selector->match (docTree))
+ this->props->apply (props);
+}
+
+void CssRule::print () {
+ selector->print ();
+ props->print ();
+}
+
+CssStyleSheet::CssStyleSheet () {
+ for (int i = 0; i < ntags; i++)
+ ruleTable[i] = new lout::misc::SimpleVector <CssRule*> (1);
+}
+
+CssStyleSheet::~CssStyleSheet () {
+ for (int i = 0; i < ntags; i++) {
+ for (int j = 0; j < ruleTable[i]->size (); j++)
+ ruleTable[i]->get (j)->unref ();
+
+ delete ruleTable[i];
+ }
+}
+
+void CssStyleSheet::addRule (CssRule *rule) {
+ int topElement = rule->selector->top ()->element;
+
+ if (topElement == CssSimpleSelector::ELEMENT_ANY) {
+ for (int i = 0; i < ntags; i++) {
+ ruleTable[i]->increase ();
+ *ruleTable[i]->getRef (ruleTable[i]->size () - 1) = rule;
+ rule->ref ();
+ }
+ } else if (topElement >= 0 && topElement < ntags) {
+ ruleTable[topElement]->increase ();
+ *ruleTable[topElement]->getRef (ruleTable[topElement]->size()-1) = rule;
+ rule->ref ();
+ }
+}
+
+void CssStyleSheet::addRule (CssSelector *selector, CssPropertyList *props) {
+ CssRule *rule = new CssRule (selector, props);
+ addRule (rule);
+}
+
+void CssStyleSheet::apply (CssPropertyList *props, Doctree *docTree) {
+ lout::misc::SimpleVector <CssRule*> *ruleList;
+
+ ruleList = ruleTable[docTree->top ()->element];
+ for (int i = 0; i < ruleList->size (); i++)
+ ruleList->get (i)->apply (props, docTree);
+}
+
+CssStyleSheet *CssContext::userAgentStyle;
+CssStyleSheet *CssContext::userStyle;
+CssStyleSheet *CssContext::userImportantStyle;
+
+CssContext::CssContext () {
+ for (int o = CSS_PRIMARY_USER_AGENT; o < CSS_PRIMARY_LAST; o++)
+ sheet[o] = NULL;
+
+ if (userAgentStyle == NULL) {
+ userAgentStyle = new CssStyleSheet ();
+ userStyle = new CssStyleSheet ();
+ userImportantStyle = new CssStyleSheet ();
+
+ sheet[CSS_PRIMARY_USER_AGENT] = userAgentStyle;
+ sheet[CSS_PRIMARY_USER] = userStyle;
+ sheet[CSS_PRIMARY_USER_IMPORTANT] = userImportantStyle;
+
+ buildUserAgentStyle ();
+ buildUserStyle ();
+ }
+
+ sheet[CSS_PRIMARY_USER_AGENT] = userAgentStyle;
+ sheet[CSS_PRIMARY_USER] = userStyle;
+ sheet[CSS_PRIMARY_USER_IMPORTANT] = userImportantStyle;
+}
+
+CssContext::~CssContext () {
+ for (int o = CSS_PRIMARY_USER_AGENT; o < CSS_PRIMARY_LAST; o++)
+ if (sheet[o] != userAgentStyle && sheet[o] != userStyle &&
+ sheet[o] != userImportantStyle)
+ delete sheet[o];
+}
+
+void CssContext::apply (CssPropertyList *props, Doctree *docTree,
+ CssPropertyList *tagStyle, CssPropertyList *nonCssHints) {
+
+ for (int o = CSS_PRIMARY_USER_AGENT; o <= CSS_PRIMARY_USER; o++)
+ if (sheet[o])
+ sheet[o]->apply (props, docTree);
+
+ if (nonCssHints)
+ nonCssHints->apply (props);
+
+ for (int o = CSS_PRIMARY_AUTHOR; o <= CSS_PRIMARY_USER_IMPORTANT; o++)
+ if (sheet[o])
+ sheet[o]->apply (props, docTree);
+
+ if (tagStyle)
+ tagStyle->apply (props);
+}
+
+void CssContext::addRule (CssRule *rule, CssPrimaryOrder order) {
+ if (sheet[order] == NULL)
+ sheet[order] = new CssStyleSheet ();
+
+ sheet[order]->addRule (rule);
+
+// fprintf(stderr, "Adding Rule (%d)\n", order);
+// rule->print ();
+}
+
+void CssContext::buildUserAgentStyle () {
+ const char *cssBuf =
+ "body {background-color: #dcd1ba; font-family: helvetica; color: black;"
+ " margin: 5px; }"
+ "big { font-size: 1.17em }"
+ "blockquote, dd {margin-left: 40px; margin-right: 40px}"
+ "center { text-align: center }"
+ ":link {color: blue; text-decoration: underline; cursor: pointer; } "
+ ":visited {color: green; text-decoration: underline; cursor: pointer; } "
+ "h1, h2, h3, h4, h5, h6, b, strong {font-weight: bolder; } "
+ "i, em, cite, address {font-style: italic; } "
+ "img:link, img:visited {border: 1px solid } "
+ "frameset, ul, ol, dir {margin-left: 40px} "
+ "h1 {font-size: 2em; margin-top: .67em; margin-bottom: 0em;} "
+ "h2 {font-size: 1.5em; margin-top: .75em; margin-bottom: 0em;} "
+ "h3 {font-size: 1.17em; margin-top: .83em; margin-bottom: 0em;} "
+ "h4 {margin-top: 1.12em; margin-bottom: 0em;} "
+ "h5 {font-size: 0.83em; margin-top: 1.5em; margin-bottom: 0em;} "
+ "h6 {font-size: 0.75em; margin-top: 1.67em; margin-bottom: 0em;} "
+ "hr {width: 100%; border: 1px inset} "
+ "pre {white-space: pre} "
+ "u {text-decoration: underline } "
+ "small, sub, sup { font-size: 0.83em } "
+ "sub { vertical-align: sub } "
+ "sup { vertical-align: super } "
+ "s, strike, del { text-decoration: line-through }"
+ "table {border-style: outset; border-spacing: 1px} "
+ "td {border-style: inset; padding: 2px;} "
+ "thead, tbody, tfoot { vertical-align: middle }"
+ "th { font-weight: bolder; text-align: center }"
+ "code, tt, pre, samp, kbd {font-family: courier;} ";
+
+ a_Css_parse (this, cssBuf, strlen (cssBuf), 0, CSS_ORIGIN_USER_AGENT);
+}
+
+void CssContext::buildUserStyle () {
+ char buf[1024];
+ char *filename;
+
+ filename = dStrconcat(dGethomedir(), "/.dillo/style.css", NULL);
+ FILE *fp = fopen (filename, "r");
+ if (fp) {
+ Dstr *style = dStr_sized_new (1024);
+ size_t len;
+
+ while ((len = fread (buf, 1, sizeof (buf), fp)))
+ dStr_append_l (style, buf, len);
+
+ a_Css_parse (this, style->str, style->len, 0, CSS_ORIGIN_USER);
+ dStr_free (style, 1);
+ }
+
+ dFree (filename);
+}
diff --git a/src/css.hh b/src/css.hh
new file mode 100644
index 00000000..515831e9
--- /dev/null
+++ b/src/css.hh
@@ -0,0 +1,313 @@
+#ifndef __CSS_HH__
+#define __CSS_HH__
+
+#include "dw/core.hh"
+#include "doctree.hh"
+
+/* Origin and weight. Used only internally.*/
+typedef enum {
+ CSS_PRIMARY_USER_AGENT,
+ CSS_PRIMARY_USER,
+ CSS_PRIMARY_AUTHOR,
+ CSS_PRIMARY_AUTHOR_IMPORTANT,
+ CSS_PRIMARY_USER_IMPORTANT,
+ CSS_PRIMARY_LAST,
+} CssPrimaryOrder;
+
+/*
+ * Lengths are represented as int in the following way:
+ *
+ * +---+ - - - +---+---+- - - - - -+---+---+---+---+
+ * | integer part | decimal fraction | type |
+ * +---+ - - - +---+---+- - - - - -+---+---+---+---+
+ * n-1 19 18 3 2 1 0
+ *
+ * | <------ fixed point value ------> |
+ *
+ * where type is one of the CSS_LENGTH_TYPE_* values.
+ */
+
+typedef int CssLength;
+
+enum {
+ CSS_LENGTH_TYPE_PX,
+ CSS_LENGTH_TYPE_MM, /* "cm", "in", "pt" and "pc" are converted into
+ millimeters. */
+ CSS_LENGTH_TYPE_EM,
+ CSS_LENGTH_TYPE_EX,
+ CSS_LENGTH_TYPE_PERCENTAGE,
+ CSS_LENGTH_TYPE_RELATIVE, /* This does not exist in CSS but
+ is used in HTML */
+ CSS_LENGTH_TYPE_AUTO /* This can be used as a simple value. */
+};
+
+#define CSS_CREATE_LENGTH(v, t) ( ( (int)((v) * (1 << 19)) & ~7 ) | (t) )
+#define CSS_LENGTH_VALUE(l) ( ( (float)((l) & ~7) ) / (1 << 19) )
+#define CSS_LENGTH_TYPE(l) ((l) & 7)
+
+/**
+ * \brief This class holds a CSS property and value pair.
+ */
+class CssProperty {
+ public:
+ typedef union {
+ int intVal;
+ const char *strVal;
+ } Value;
+
+ typedef enum {
+ CSS_PROPERTY_BACKGROUND_ATTACHMENT,
+ CSS_PROPERTY_BACKGROUND_COLOR,
+ CSS_PROPERTY_BACKGROUND_IMAGE,
+ CSS_PROPERTY_BACKGROUND_POSITION,
+ CSS_PROPERTY_BACKGROUND_REPEAT,
+ CSS_PROPERTY_BORDER_BOTTOM_COLOR,
+ CSS_PROPERTY_BORDER_BOTTOM_STYLE,
+ CSS_PROPERTY_BORDER_BOTTOM_WIDTH,
+ CSS_PROPERTY_BORDER_COLLAPSE,
+ CSS_PROPERTY_BORDER_LEFT_COLOR,
+ CSS_PROPERTY_BORDER_LEFT_STYLE,
+ CSS_PROPERTY_BORDER_LEFT_WIDTH,
+ CSS_PROPERTY_BORDER_RIGHT_COLOR,
+ CSS_PROPERTY_BORDER_RIGHT_STYLE,
+ CSS_PROPERTY_BORDER_RIGHT_WIDTH,
+ CSS_PROPERTY_BORDER_SPACING,
+ CSS_PROPERTY_BORDER_TOP_COLOR,
+ CSS_PROPERTY_BORDER_TOP_STYLE,
+ CSS_PROPERTY_BORDER_TOP_WIDTH,
+ CSS_PROPERTY_BOTTOM,
+ CSS_PROPERTY_CAPTION_SIDE,
+ CSS_PROPERTY_CLEAR,
+ CSS_PROPERTY_CLIP,
+ CSS_PROPERTY_COLOR,
+ CSS_PROPERTY_CONTENT,
+ CSS_PROPERTY_COUNTER_INCREMENT,
+ CSS_PROPERTY_COUNTER_RESET,
+ CSS_PROPERTY_CURSOR,
+ CSS_PROPERTY_DIRECTION,
+ CSS_PROPERTY_DISPLAY,
+ CSS_PROPERTY_EMPTY_CELLS,
+ CSS_PROPERTY_FLOAT,
+ CSS_PROPERTY_FONT_FAMILY,
+ CSS_PROPERTY_FONT_SIZE,
+ CSS_PROPERTY_FONT_SIZE_ADJUST,
+ CSS_PROPERTY_FONT_STRETCH,
+ CSS_PROPERTY_FONT_STYLE,
+ CSS_PROPERTY_FONT_VARIANT,
+ CSS_PROPERTY_FONT_WEIGHT,
+ CSS_PROPERTY_HEIGHT,
+ CSS_PROPERTY_LEFT,
+ CSS_PROPERTY_LETTER_SPACING,
+ CSS_PROPERTY_LINE_HEIGHT,
+ CSS_PROPERTY_LIST_STYLE_IMAGE,
+ CSS_PROPERTY_LIST_STYLE_POSITION,
+ CSS_PROPERTY_LIST_STYLE_TYPE,
+ CSS_PROPERTY_MARGIN_BOTTOM,
+ CSS_PROPERTY_MARGIN_LEFT,
+ CSS_PROPERTY_MARGIN_RIGHT,
+ CSS_PROPERTY_MARGIN_TOP,
+ CSS_PROPERTY_MARKER_OFFSET,
+ CSS_PROPERTY_MARKS,
+ CSS_PROPERTY_MAX_HEIGHT,
+ CSS_PROPERTY_MAX_WIDTH,
+ CSS_PROPERTY_MIN_HEIGHT,
+ CSS_PROPERTY_MIN_WIDTH,
+ CSS_PROPERTY_OUTLINE_COLOR,
+ CSS_PROPERTY_OUTLINE_STYLE,
+ CSS_PROPERTY_OUTLINE_WIDTH,
+ CSS_PROPERTY_OVERFLOW,
+ CSS_PROPERTY_PADDING_BOTTOM,
+ CSS_PROPERTY_PADDING_LEFT,
+ CSS_PROPERTY_PADDING_RIGHT,
+ CSS_PROPERTY_PADDING_TOP,
+ CSS_PROPERTY_POSITION,
+ CSS_PROPERTY_QUOTES,
+ CSS_PROPERTY_RIGHT,
+ CSS_PROPERTY_TEXT_ALIGN,
+ CSS_PROPERTY_TEXT_DECORATION,
+ CSS_PROPERTY_TEXT_INDENT,
+ CSS_PROPERTY_TEXT_SHADOW,
+ CSS_PROPERTY_TEXT_TRANSFORM,
+ CSS_PROPERTY_TOP,
+ CSS_PROPERTY_UNICODE_BIDI,
+ CSS_PROPERTY_VERTICAL_ALIGN,
+ CSS_PROPERTY_VISIBILITY,
+ CSS_PROPERTY_WHITE_SPACE,
+ CSS_PROPERTY_WIDTH,
+ CSS_PROPERTY_WORD_SPACING,
+ CSS_PROPERTY_Z_INDEX,
+ CSS_PROPERTY_X_LINK,
+ CSS_PROPERTY_X_COLSPAN,
+ CSS_PROPERTY_X_ROWSPAN,
+ PROPERTY_X_LINK,
+ PROPERTY_X_IMG,
+ PROPERTY_X_TOOLTIP,
+ CSS_PROPERTY_LAST
+ } Name;
+
+ typedef enum {
+ CSS_FONT_WEIGHT_LIGHTER = -1,
+ CSS_FONT_WEIGHT_BOLDER = -2,
+ CSS_FONT_WEIGHT_STEP = 300,
+ /* Some special font weights. */
+ CSS_FONT_WEIGHT_LIGHT = 100,
+ CSS_FONT_WEIGHT_NORMAL = 400,
+ CSS_FONT_WEIGHT_BOLD = 700,
+ CSS_FONT_WEIGHT_MIN = 100,
+ CSS_FONT_WEIGHT_MAX = 900,
+ } FontWeightExtensions;
+
+ Name name;
+ Value value;
+
+ void print ();
+};
+
+/**
+ * \brief A list of CssProperty objects.
+ */
+class CssPropertyList : public lout::misc::SimpleVector <CssProperty> {
+ int refCount;
+
+ public:
+ CssPropertyList() : lout::misc::SimpleVector <CssProperty> (1) {
+ refCount = 0;
+ };
+ CssPropertyList(const CssPropertyList &p) :
+ lout::misc::SimpleVector <CssProperty> (p) {
+ refCount = 0;
+ };
+
+ void set (CssProperty::Name name, CssProperty::Value value);
+ void set (CssProperty::Name name, const char *value) {
+ CssProperty::Value v;
+ v.strVal = value;
+ set (name, v);
+ };
+ void set (CssProperty::Name name, int value) {
+ CssProperty::Value v;
+ v.intVal = value;
+ set (name, v);
+ };
+ void apply (CssPropertyList *props);
+ void print ();
+ inline void ref () { refCount++; }
+ inline void unref () { if(--refCount == 0) delete this; }
+};
+
+class CssSimpleSelector {
+ public:
+ enum {
+ ELEMENT_NONE = -1,
+ ELEMENT_ANY = -2,
+ };
+
+ int element;
+ const char *klass, *pseudo, *id;
+
+ bool match (const DoctreeNode *node);
+ void print ();
+};
+
+/**
+ * \brief CSS selector class.
+ * \todo Implement missing selector options.
+ */
+class CssSelector {
+ public:
+ typedef enum {
+ DESCENDENT,
+ CHILD,
+ ADJACENT_SIBLING,
+ } Combinator;
+
+ private:
+ struct CombinatorAndSelector {
+ Combinator combinator;
+ CssSimpleSelector selector;
+ };
+
+ int refCount;
+ lout::misc::SimpleVector <struct CombinatorAndSelector> *selectorList;
+
+ public:
+ CssSelector (int element = CssSimpleSelector::ELEMENT_ANY,
+ const char *klass = NULL,
+ const char *pseudo = NULL, const char *id = NULL);
+ ~CssSelector ();
+ void addSimpleSelector (Combinator c,
+ int element = CssSimpleSelector::ELEMENT_ANY,
+ const char *klass = NULL,
+ const char *pseudo = NULL, const char *id=NULL);
+ inline CssSimpleSelector *top () {
+ return &selectorList->getRef (selectorList->size () - 1)->selector;
+ };
+
+ bool match (Doctree *dt);
+ void print ();
+ inline void ref () { refCount++; }
+ inline void unref () { if(--refCount == 0) delete this; }
+};
+
+/**
+ * \brief A CssSelector CssPropertyList pair.
+ * The CssPropertyList is applied if the CssSelector matches.
+ */
+class CssRule {
+ private:
+ int refCount;
+ CssPropertyList *props;
+
+ public:
+ CssSelector *selector;
+
+ CssRule (CssSelector *selector, CssPropertyList *props);
+ ~CssRule ();
+
+ void apply (CssPropertyList *props, Doctree *docTree);
+ inline void ref () { refCount++; }
+ inline void unref () { if(--refCount == 0) delete this; }
+ void print ();
+};
+
+/**
+ * \brief A list of CssRules.
+ * In apply () all matching rules are applied.
+ */
+class CssStyleSheet {
+ private:
+ static const int ntags = 90; // \todo replace 90
+ lout::misc::SimpleVector <CssRule*> *ruleTable[ntags];
+
+ public:
+ CssStyleSheet();
+ ~CssStyleSheet();
+ void addRule (CssRule *rule);
+ void addRule (CssSelector *selector, CssPropertyList *props);
+ void apply (CssPropertyList *props, Doctree *docTree);
+};
+
+/**
+ * \brief A set of CssStyleSheets.
+ */
+class CssContext {
+ private:
+ static CssStyleSheet *userAgentStyle;
+ static CssStyleSheet *userStyle;
+ static CssStyleSheet *userImportantStyle;
+ CssStyleSheet *sheet[CSS_PRIMARY_USER_IMPORTANT + 1];
+
+ void buildUserAgentStyle ();
+ void buildUserStyle ();
+
+ public:
+ CssContext ();
+ ~CssContext ();
+
+ void addRule (CssRule *rule, CssPrimaryOrder order);
+ void apply (CssPropertyList *props,
+ Doctree *docTree,
+ CssPropertyList *tagStyle, CssPropertyList *nonCssHints);
+};
+
+#endif
diff --git a/src/cssparser.cc b/src/cssparser.cc
new file mode 100644
index 00000000..6bea06cb
--- /dev/null
+++ b/src/cssparser.cc
@@ -0,0 +1,1163 @@
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "msg.h"
+#include "colors.h"
+#include "html_common.hh"
+#include "css.hh"
+#include "cssparser.hh"
+
+using namespace dw::core::style;
+
+#define DEBUG_MSG(A, B, ...) _MSG(B, __VA_ARGS__)
+#define MSG_CSS(A, ...) MSG(A, __VA_ARGS__)
+#define DEBUG_TOKEN_LEVEL 0
+#define DEBUG_PARSE_LEVEL 0
+#define DEBUG_CREATE_LEVEL 0
+
+#define DEBUG_LEVEL 10
+
+/* Applies to symbol lengths and string literals. */
+#define MAX_STR_LEN 256
+
+static const char *Css_border_style_enum_vals[] = {
+ "none", "hidden", "dotted", "dashed", "solid", "double", "groove",
+ "ridge", "inset", "outset", NULL
+};
+
+static const char *Css_cursor_enum_vals[] = {
+ "crosshair", "default", "pointer", "move", "e_resize", "ne_resize",
+ "nw_resize", "n_resize", "se_resize", "sw_resize", "s_resize",
+ "w_resize", "text", "wait", "help", NULL
+};
+
+static const char *Css_display_enum_vals[DISPLAY_LAST + 1] = {
+ "block", "inline", "list-item", "table", "table-row-group",
+ "table-header-group", "table-footer-group", "table-row",
+ "table-cell", NULL
+};
+
+static const char *Css_font_style_enum_vals[] = {
+ "normal", "italic", "oblique", NULL
+};
+
+static const char *Css_list_style_type_enum_vals[] = {
+ "disc", "circle", "square", "decimal", "decimal-leading-zero",
+ "lower-roman", "upper-roman", "lower-greek", "lower-alpha",
+ "lower-latin", "upper-alpha", "upper-latin", "hebrew", "armenian",
+ "georgian", "cjk-ideographic", "hiragana", "katakana", "hiragana-iroha",
+ "katakana-iroha", "none", NULL
+};
+
+static const char *Css_text_align_enum_vals[] = {
+ "left", "right", "center", "justify", "string", NULL
+};
+
+static const char *Css_text_decoration_enum_vals[] = {
+ "underline", "overline", "line-through", "blink", NULL
+};
+
+static const char *Css_vertical_align_vals[] = {
+ "top", "bottom", "middle", "baseline", "sub", "super", NULL
+};
+
+static const char *Css_white_space_vals[] = {
+ "normal", "pre", "nowrap", NULL
+};
+
+CssPropertyInfo Css_property_info[CssProperty::CSS_PROPERTY_LAST] = {
+ {"background-attachment", CSS_TYPE_UNUSED, NULL},
+ {"background-color", CSS_TYPE_COLOR, NULL},
+ {"background-image", CSS_TYPE_UNUSED, NULL},
+ {"background-position", CSS_TYPE_UNUSED, NULL},
+ {"background-repeat", CSS_TYPE_UNUSED, NULL},
+ {"border-bottom-color", CSS_TYPE_COLOR, NULL},
+ {"border-bottom-style", CSS_TYPE_ENUM, Css_border_style_enum_vals},
+ {"border-bottom-width", CSS_TYPE_LENGTH, NULL},
+ {"border-collapse", CSS_TYPE_UNUSED, NULL},
+ {"border-left-color", CSS_TYPE_COLOR, NULL},
+ {"border-left-style", CSS_TYPE_ENUM, Css_border_style_enum_vals},
+ {"border-left-width", CSS_TYPE_LENGTH, NULL},
+ {"border-right-color", CSS_TYPE_COLOR, NULL},
+ {"border-right-style", CSS_TYPE_ENUM, Css_border_style_enum_vals},
+ {"border-right-width", CSS_TYPE_LENGTH, NULL},
+ {"border-spacing", CSS_TYPE_LENGTH, NULL},
+ {"border-top-color", CSS_TYPE_COLOR, NULL},
+ {"border-top-style", CSS_TYPE_ENUM, Css_border_style_enum_vals},
+ {"border-top-width", CSS_TYPE_LENGTH, NULL},
+ {"bottom", CSS_TYPE_UNUSED, NULL},
+ {"caption-side", CSS_TYPE_UNUSED, NULL},
+ {"clear", CSS_TYPE_UNUSED, NULL},
+ {"clip", CSS_TYPE_UNUSED, NULL},
+ {"color", CSS_TYPE_COLOR, NULL},
+ {"content", CSS_TYPE_STRING, NULL},
+ {"counter-increment", CSS_TYPE_UNUSED, NULL},
+ {"counter-reset", CSS_TYPE_UNUSED, NULL},
+ {"cursor", CSS_TYPE_ENUM, Css_cursor_enum_vals},
+ {"direction", CSS_TYPE_UNUSED, NULL},
+ {"display", CSS_TYPE_ENUM, Css_display_enum_vals},
+ {"empty-cells", CSS_TYPE_UNUSED, NULL},
+ {"float", CSS_TYPE_UNUSED, NULL},
+ {"font-family", CSS_TYPE_SYMBOL, NULL},
+ {"font-size", CSS_TYPE_LENGTH_PERCENTAGE, NULL},
+ {"font-size-adjust", CSS_TYPE_UNUSED, NULL},
+ {"font-stretch", CSS_TYPE_UNUSED, NULL},
+ {"font-style", CSS_TYPE_ENUM, Css_font_style_enum_vals},
+ {"font-variant", CSS_TYPE_UNUSED, NULL},
+ {"font-weight", CSS_TYPE_FONT_WEIGHT, NULL},
+ {"height", CSS_TYPE_LENGTH_PERCENTAGE, NULL},
+ {"left", CSS_TYPE_UNUSED, NULL},
+ {"letter-spacing", CSS_TYPE_UNUSED, NULL},
+ {"line-height", CSS_TYPE_UNUSED, NULL},
+ {"list-style-image", CSS_TYPE_UNUSED, NULL},
+ {"list-style-position", CSS_TYPE_UNUSED, NULL},
+ {"list-style-type", CSS_TYPE_ENUM, Css_list_style_type_enum_vals},
+ {"margin-bottom", CSS_TYPE_LENGTH, NULL},
+ {"margin-left", CSS_TYPE_LENGTH, NULL},
+ {"margin-right", CSS_TYPE_LENGTH, NULL},
+ {"margin-top", CSS_TYPE_LENGTH, NULL},
+ {"marker-offset", CSS_TYPE_UNUSED, NULL},
+ {"marks", CSS_TYPE_UNUSED, NULL},
+ {"max-height", CSS_TYPE_UNUSED, NULL},
+ {"max-width", CSS_TYPE_UNUSED, NULL},
+ {"min-height", CSS_TYPE_UNUSED, NULL},
+ {"min-width", CSS_TYPE_UNUSED, NULL},
+ {"outline-color", CSS_TYPE_UNUSED, NULL},
+ {"outline-style", CSS_TYPE_UNUSED, NULL},
+ {"outline-width", CSS_TYPE_UNUSED, NULL},
+ {"overflow", CSS_TYPE_UNUSED, NULL},
+ {"padding-bottom", CSS_TYPE_LENGTH, NULL},
+ {"padding-left", CSS_TYPE_LENGTH, NULL},
+ {"padding-right", CSS_TYPE_LENGTH, NULL},
+ {"padding-top", CSS_TYPE_LENGTH, NULL},
+ {"position", CSS_TYPE_UNUSED, NULL},
+ {"quotes", CSS_TYPE_UNUSED, NULL},
+ {"right", CSS_TYPE_UNUSED, NULL},
+ {"text-align", CSS_TYPE_ENUM, Css_text_align_enum_vals},
+ {"text-decoration", CSS_TYPE_MULTI_ENUM, Css_text_decoration_enum_vals},
+ {"text-indent", CSS_TYPE_UNUSED, NULL},
+ {"text-shadow", CSS_TYPE_UNUSED, NULL},
+ {"text-transform", CSS_TYPE_UNUSED, NULL},
+ {"top", CSS_TYPE_UNUSED, NULL},
+ {"unicode-bidi", CSS_TYPE_UNUSED, NULL},
+ {"vertical-align", CSS_TYPE_ENUM, Css_vertical_align_vals},
+ {"visibility", CSS_TYPE_UNUSED, NULL},
+ {"white-space", CSS_TYPE_ENUM, Css_white_space_vals},
+ {"width", CSS_TYPE_LENGTH_PERCENTAGE, NULL},
+ {"word-spacing", CSS_TYPE_UNUSED, NULL},
+ {"z-index", CSS_TYPE_UNUSED, NULL},
+
+ /* These are extensions, for internal used, and never parsed. */
+ {"x-link", CSS_TYPE_INTEGER, NULL},
+ {"x-colspan", CSS_TYPE_INTEGER, NULL},
+ {"x-rowspan", CSS_TYPE_INTEGER, NULL},
+
+ {"last", CSS_TYPE_UNUSED, NULL},
+};
+
+#define CSS_SHORTHAND_NUM 14
+
+typedef struct {
+ const char *symbol;
+ enum {
+ CSS_SHORTHAND_MULTIPLE, /* [ p1 || p2 || ...], the property pi is
+ * determined by the type */
+ CSS_SHORTHAND_DIRECTIONS, /* <t>{1,4} */
+ CSS_SHORTHAND_BORDER, /* special, used for 'border' */
+ CSS_SHORTHAND_FONT, /* special, used for 'font' */
+ } type;
+ CssProperty::Name * properties; /* CSS_SHORTHAND_MULTIPLE:
+ * must be terminated by -1
+ * CSS_SHORTHAND_DIRECTIONS:
+ * must have length 4
+ * CSS_SHORTHAND_BORDERS:
+ * must have length 12
+ * CSS_SHORTHAND_FONT:
+ * unused */
+} CssShorthandInfo;
+
+CssProperty::Name Css_background_properties[] = {
+ CssProperty::CSS_PROPERTY_BACKGROUND_COLOR,
+ CssProperty::CSS_PROPERTY_BACKGROUND_IMAGE,
+ CssProperty::CSS_PROPERTY_BACKGROUND_REPEAT,
+ CssProperty::CSS_PROPERTY_BACKGROUND_ATTACHMENT,
+ CssProperty::CSS_PROPERTY_BACKGROUND_POSITION,
+ (CssProperty::Name) - 1
+};
+
+CssProperty::Name Css_border_bottom_properties[] = {
+ CssProperty::CSS_PROPERTY_BORDER_BOTTOM_WIDTH,
+ CssProperty::CSS_PROPERTY_BORDER_BOTTOM_STYLE,
+ CssProperty::CSS_PROPERTY_BORDER_BOTTOM_COLOR,
+ (CssProperty::Name) - 1
+};
+
+CssProperty::Name Css_border_color_properties[4] = {
+ CssProperty::CSS_PROPERTY_BORDER_TOP_COLOR,
+ CssProperty::CSS_PROPERTY_BORDER_BOTTOM_COLOR,
+ CssProperty::CSS_PROPERTY_BORDER_LEFT_COLOR,
+ CssProperty::CSS_PROPERTY_BORDER_RIGHT_COLOR
+};
+
+CssProperty::Name Css_border_left_properties[] = {
+ CssProperty::CSS_PROPERTY_BORDER_LEFT_WIDTH,
+ CssProperty::CSS_PROPERTY_BORDER_LEFT_STYLE,
+ CssProperty::CSS_PROPERTY_BORDER_LEFT_COLOR,
+ (CssProperty::Name) - 1
+};
+
+CssProperty::Name Css_border_right_properties[] = {
+ CssProperty::CSS_PROPERTY_BORDER_RIGHT_WIDTH,
+ CssProperty::CSS_PROPERTY_BORDER_RIGHT_STYLE,
+ CssProperty::CSS_PROPERTY_BORDER_RIGHT_COLOR,
+ (CssProperty::Name) - 1
+};
+
+CssProperty::Name Css_border_style_properties[4] = {
+ CssProperty::CSS_PROPERTY_BORDER_TOP_STYLE,
+ CssProperty::CSS_PROPERTY_BORDER_BOTTOM_STYLE,
+ CssProperty::CSS_PROPERTY_BORDER_LEFT_STYLE,
+ CssProperty::CSS_PROPERTY_BORDER_RIGHT_STYLE
+};
+
+CssProperty::Name Css_border_top_properties[] = {
+ CssProperty::CSS_PROPERTY_BORDER_TOP_WIDTH,
+ CssProperty::CSS_PROPERTY_BORDER_TOP_STYLE,
+ CssProperty::CSS_PROPERTY_BORDER_TOP_COLOR,
+ (CssProperty::Name) - 1
+};
+
+CssProperty::Name Css_border_width_properties[4] = {
+ CssProperty::CSS_PROPERTY_BORDER_TOP_WIDTH,
+ CssProperty::CSS_PROPERTY_BORDER_BOTTOM_WIDTH,
+ CssProperty::CSS_PROPERTY_BORDER_LEFT_WIDTH,
+ CssProperty::CSS_PROPERTY_BORDER_RIGHT_WIDTH
+};
+
+CssProperty::Name Css_list_style_properties[] = {
+ CssProperty::CSS_PROPERTY_LIST_STYLE_TYPE,
+ CssProperty::CSS_PROPERTY_LIST_STYLE_POSITION,
+ CssProperty::CSS_PROPERTY_LIST_STYLE_IMAGE,
+ (CssProperty::Name) - 1
+};
+
+CssProperty::Name Css_margin_properties[4] = {
+ CssProperty::CSS_PROPERTY_MARGIN_TOP,
+ CssProperty::CSS_PROPERTY_MARGIN_BOTTOM,
+ CssProperty::CSS_PROPERTY_MARGIN_LEFT,
+ CssProperty::CSS_PROPERTY_MARGIN_RIGHT
+};
+
+CssProperty::Name Css_outline_properties[] = {
+ CssProperty::CSS_PROPERTY_OUTLINE_COLOR,
+ CssProperty::CSS_PROPERTY_OUTLINE_STYLE,
+ CssProperty::CSS_PROPERTY_OUTLINE_WIDTH,
+ (CssProperty::Name) - 1
+};
+
+CssProperty::Name Css_padding_properties[4] = {
+ CssProperty::CSS_PROPERTY_PADDING_TOP,
+ CssProperty::CSS_PROPERTY_PADDING_BOTTOM,
+ CssProperty::CSS_PROPERTY_PADDING_LEFT,
+ CssProperty::CSS_PROPERTY_PADDING_RIGHT
+};
+
+CssProperty::Name Css_border_properties[12] = {
+ CssProperty::CSS_PROPERTY_BORDER_TOP_WIDTH,
+ CssProperty::CSS_PROPERTY_BORDER_TOP_STYLE,
+ CssProperty::CSS_PROPERTY_BORDER_TOP_COLOR,
+ CssProperty::CSS_PROPERTY_BORDER_BOTTOM_WIDTH,
+ CssProperty::CSS_PROPERTY_BORDER_BOTTOM_STYLE,
+ CssProperty::CSS_PROPERTY_BORDER_BOTTOM_COLOR,
+ CssProperty::CSS_PROPERTY_BORDER_LEFT_WIDTH,
+ CssProperty::CSS_PROPERTY_BORDER_LEFT_STYLE,
+ CssProperty::CSS_PROPERTY_BORDER_LEFT_COLOR,
+ CssProperty::CSS_PROPERTY_BORDER_RIGHT_WIDTH,
+ CssProperty::CSS_PROPERTY_BORDER_RIGHT_STYLE,
+ CssProperty::CSS_PROPERTY_BORDER_RIGHT_COLOR
+};
+
+static CssShorthandInfo Css_shorthand_info[CSS_SHORTHAND_NUM] = {
+ {"background", CssShorthandInfo::CSS_SHORTHAND_MULTIPLE,
+ Css_background_properties},
+ {"border", CssShorthandInfo::CSS_SHORTHAND_BORDER,
+ Css_border_properties},
+ {"border-bottom", CssShorthandInfo::CSS_SHORTHAND_MULTIPLE,
+ Css_border_bottom_properties},
+ {"border-color", CssShorthandInfo::CSS_SHORTHAND_DIRECTIONS,
+ Css_border_color_properties},
+ {"border-left", CssShorthandInfo::CSS_SHORTHAND_MULTIPLE,
+ Css_border_left_properties},
+ {"border-right", CssShorthandInfo::CSS_SHORTHAND_MULTIPLE,
+ Css_border_right_properties},
+ {"border-style", CssShorthandInfo::CSS_SHORTHAND_DIRECTIONS,
+ Css_border_style_properties},
+ {"border-top", CssShorthandInfo::CSS_SHORTHAND_MULTIPLE,
+ Css_border_top_properties},
+ {"border-width", CssShorthandInfo::CSS_SHORTHAND_DIRECTIONS,
+ Css_border_width_properties},
+ {"font", CssShorthandInfo::CSS_SHORTHAND_FONT, NULL},
+ {"list-style", CssShorthandInfo::CSS_SHORTHAND_MULTIPLE,
+ Css_list_style_properties},
+ {"margin", CssShorthandInfo::CSS_SHORTHAND_DIRECTIONS,
+ Css_margin_properties},
+ {"outline", CssShorthandInfo::CSS_SHORTHAND_MULTIPLE,
+ Css_outline_properties},
+ {"padding", CssShorthandInfo::CSS_SHORTHAND_DIRECTIONS,
+ Css_padding_properties},
+};
+
+
+static const char *Css_primary_text[CSS_PRIMARY_LAST] = {
+ "user stylesheets, important", "author stylesheets, important",
+ "author stylesheets", "user stylesheets", "user-agent stylesheets"
+};
+
+static const char *Css_level_text[4] =
+ { "id", "class", "pseudo-class", "element" };
+
+
+/* ----------------------------------------------------------------------
+ * Initialization, Cleanup
+ * ---------------------------------------------------------------------- */
+
+static int values_num;
+
+void a_Css_init(void)
+{
+ values_num = 0;
+}
+
+void a_Css_freeall(void)
+{
+ if (values_num)
+ fprintf(stderr, "%d CSS values left", values_num);
+}
+
+/* ----------------------------------------------------------------------
+ * Parsing
+ * ---------------------------------------------------------------------- */
+
+typedef enum {
+ CSS_TK_DECINT, CSS_TK_FLOAT, CSS_TK_COLOR, CSS_TK_SYMBOL, CSS_TK_STRING,
+ CSS_TK_CHAR, CSS_TK_END
+} CssTokenType;
+
+typedef struct {
+ CssContext *context;
+ int order_count;
+ CssOrigin origin;
+
+ const char *buf;
+ int buflen, bufptr;
+
+ CssTokenType ttype;
+ char tval[MAX_STR_LEN];
+ bool within_block;
+ bool space_separated; /* used when parsing CSS selectors */
+} CssParser;
+
+/*
+ * Gets the next character from the buffer, or EOF.
+ */
+static int Css_getc(CssParser * parser)
+{
+ int c;
+
+ if (parser->bufptr >= parser->buflen)
+ c = EOF;
+ else
+ c = parser->buf[parser->bufptr];
+
+ /* The buffer pointer is increased in any case, so that Css_ungetc works
+ * correctly at the end of the buffer. */
+ parser->bufptr++;
+ return c;
+}
+
+/*
+ * Undoes the last Css_getc().
+ */
+static void Css_ungetc(CssParser * parser)
+{
+ parser->bufptr--;
+}
+
+static void Css_next_token(CssParser * parser)
+{
+ int c, c1, d, i, j;
+ bool point_allowed;
+ char hexbuf[5];
+ bool escaped;
+
+ parser->space_separated = false;
+
+ c = Css_getc(parser);
+
+ while (true) {
+ if (isspace(c)) { // ignore whitespace
+ parser->space_separated = true;
+ c = Css_getc(parser);
+ } else if (c == '/') { // ignore comments
+ d = Css_getc(parser);
+ if (d == '*') {
+ c = Css_getc(parser);
+ d = Css_getc(parser);
+ while (d != EOF && (c != '*' || d != '/')) {
+ c = d;
+ d = Css_getc(parser);
+ }
+ c = Css_getc(parser);
+ } else {
+ Css_ungetc(parser);
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+
+ if (isdigit(c)) {
+ parser->ttype = CSS_TK_DECINT;
+ point_allowed = true;
+
+ parser->tval[0] = c;
+ i = 1;
+ c = Css_getc(parser);
+ while (isdigit(c) || (point_allowed && c == '.')) {
+ if (c == '.') {
+ parser->ttype = CSS_TK_FLOAT;
+ point_allowed = false; /* Only one point read. */
+ }
+
+ if (i < MAX_STR_LEN - 1) {
+ parser->tval[i] = c;
+ i++;
+ }
+ /* else silently truncated */
+ c = Css_getc(parser);
+ }
+ parser->tval[i] = 0;
+ Css_ungetc(parser);
+
+ DEBUG_MSG(DEBUG_TOKEN_LEVEL, "token number %s\n", parser->tval);
+ return;
+ }
+
+ if (isalpha(c) || c == '_' || c == '-') {
+ parser->ttype = CSS_TK_SYMBOL;
+
+ parser->tval[0] = c;
+ i = 1;
+ c = Css_getc(parser);
+ while (isalnum(c) || c == '_' || c == '-') {
+ if (i < MAX_STR_LEN - 1) {
+ parser->tval[i] = c;
+ i++;
+ } /* else silently truncated */
+ c = Css_getc(parser);
+ }
+ parser->tval[i] = 0;
+ Css_ungetc(parser);
+ DEBUG_MSG(DEBUG_TOKEN_LEVEL, "token symbol '%s'\n", parser->tval);
+ return;
+ }
+
+ if (c == '"' || c == '\'') {
+ c1 = c;
+ parser->ttype = CSS_TK_STRING;
+
+ i = 0;
+ c = Css_getc(parser);
+ escaped = false;
+
+ while (c != EOF && (escaped || c != c1)) {
+ if (c == '\\') {
+ escaped = true;
+ d = Css_getc(parser);
+ if (isxdigit(d)) {
+ /* Read hex Unicode char. (Actually, strings are yet only 8
+ * bit.) */
+ hexbuf[0] = d;
+ j = 1;
+ d = Css_getc(parser);
+ while (j < 4 && isxdigit(d)) {
+ hexbuf[j] = d;
+ j++;
+ d = Css_getc(parser);
+ }
+ hexbuf[j] = 0;
+ Css_ungetc(parser);
+ c = strtol(hexbuf, NULL, 16);
+ } else
+ /* Take next character literally. */
+ c = Css_getc(parser);
+ } else
+ escaped = false;
+
+ if (i < MAX_STR_LEN - 1) {
+ parser->tval[i] = c;
+ i++;
+ } /* else silently truncated */
+ c = Css_getc(parser);
+ }
+ parser->tval[i] = 0;
+ /* No Css_ungetc(). */
+ DEBUG_MSG(DEBUG_TOKEN_LEVEL, "token string '%s'\n", parser->tval);
+ return;
+ }
+
+ /*
+ * Within blocks, '#' starts a color, outside, it is used in selectors.
+ */
+ if (c == '#' && parser->within_block) {
+ parser->ttype = CSS_TK_COLOR;
+
+ parser->tval[0] = c;
+ i = 1;
+ c = Css_getc(parser);
+ while (isxdigit(c)) {
+ if (i < MAX_STR_LEN - 1) {
+ parser->tval[i] = c;
+ i++;
+ } /* else silently truncated */
+ c = Css_getc(parser);
+ }
+ parser->tval[i] = 0;
+ Css_ungetc(parser);
+ DEBUG_MSG(DEBUG_TOKEN_LEVEL, "token color '%s'\n", parser->tval);
+ return;
+ }
+
+ if (c == EOF) {
+ DEBUG_MSG(DEBUG_TOKEN_LEVEL, "token %s\n", "EOF");
+ parser->ttype = CSS_TK_END;
+ return;
+ }
+
+ parser->ttype = CSS_TK_CHAR;
+ parser->tval[0] = c;
+ parser->tval[1] = 0;
+ DEBUG_MSG(DEBUG_TOKEN_LEVEL, "token char '%c'\n", c);
+}
+
+
+static bool Css_token_matches_property(CssParser * parser,
+ CssProperty::Name prop)
+{
+ int i, err = 1;
+
+ switch (Css_property_info[prop].type) {
+ case CSS_TYPE_ENUM:
+ if (parser->ttype == CSS_TK_SYMBOL) {
+ for (i = 0; Css_property_info[prop].enum_symbols[i]; i++)
+ if (strcmp(parser->tval,
+ Css_property_info[prop].enum_symbols[i]) == 0)
+ return true;
+ }
+ return false;
+
+ case CSS_TYPE_MULTI_ENUM:
+ if (parser->ttype == CSS_TK_SYMBOL) {
+ if (strcmp(parser->tval, "none") != 0)
+ return true;
+ else {
+ for (i = 0; Css_property_info[prop].enum_symbols[i]; i++) {
+ if (strcmp(parser->tval,
+ Css_property_info[prop].enum_symbols[i]) == 0)
+ return true;
+ }
+ }
+ }
+ return true;
+
+ case CSS_TYPE_LENGTH_PERCENTAGE:
+ case CSS_TYPE_LENGTH:
+ return parser->ttype == CSS_TK_DECINT ||
+ parser->ttype == CSS_TK_FLOAT || (parser->ttype == CSS_TK_SYMBOL
+ && strcmp(parser->tval,
+ "auto") == 0);
+
+ case CSS_TYPE_COLOR:
+ return (parser->ttype == CSS_TK_COLOR ||
+ parser->ttype == CSS_TK_SYMBOL) &&
+ a_Color_parse(parser->tval, -1, &err) != -1;
+
+ case CSS_TYPE_STRING:
+ return parser->ttype == CSS_TK_STRING;
+
+ case CSS_TYPE_SYMBOL:
+ return parser->ttype == CSS_TK_SYMBOL;
+
+ case CSS_TYPE_FONT_WEIGHT:
+ if (parser->ttype == CSS_TK_DECINT) {
+ i = atoi(parser->tval);
+ return i >= 100 && i <= 900;
+ } else
+ return (parser->ttype == CSS_TK_SYMBOL &&
+ (strcmp(parser->tval, "normal") == 0 ||
+ strcmp(parser->tval, "bold") == 0 ||
+ strcmp(parser->tval, "bolder") == 0 ||
+ strcmp(parser->tval, "lighter") == 0));
+ break;
+
+ case CSS_TYPE_UNUSED:
+ return false;
+
+ case CSS_TYPE_INTEGER:
+ /* Not used for parser values. */
+ default:
+ assert(false);
+ return false;
+ }
+}
+
+static bool Css_parse_value(CssParser * parser,
+ CssProperty::Name prop,
+ CssProperty::Value * val)
+{
+ int i, lentype;
+ bool found, ret = false;
+ float fval;
+ int ival, err = 1;
+
+ switch (Css_property_info[prop].type) {
+ case CSS_TYPE_ENUM:
+ if (parser->ttype == CSS_TK_SYMBOL) {
+ for (i = 0; Css_property_info[prop].enum_symbols[i]; i++)
+ if (strcmp(parser->tval,
+ Css_property_info[prop].enum_symbols[i]) == 0) {
+ val->intVal = i;
+ ret = true;
+ break;
+ }
+ Css_next_token(parser);
+ }
+ break;
+
+ case CSS_TYPE_MULTI_ENUM:
+ val->intVal = 0;
+ ret = true;
+
+ while (parser->ttype == CSS_TK_SYMBOL) {
+ if (strcmp(parser->tval, "none") != 0) {
+ for (i = 0, found = false;
+ !found && Css_property_info[prop].enum_symbols[i]; i++) {
+ if (strcmp(parser->tval,
+ Css_property_info[prop].enum_symbols[i]) == 0)
+ val->intVal |= (1 << i);
+ }
+ }
+ Css_next_token(parser);
+ }
+ break;
+
+ case CSS_TYPE_LENGTH_PERCENTAGE:
+ case CSS_TYPE_LENGTH:
+ if (parser->ttype == CSS_TK_DECINT || parser->ttype == CSS_TK_FLOAT) {
+ fval = atof(parser->tval);
+ lentype = CSS_LENGTH_TYPE_PX; /* Actually, there must be a unit,
+ * except for num == 0. */
+
+ ret = true;
+
+ Css_next_token(parser);
+ if (parser->ttype == CSS_TK_SYMBOL) {
+ if (strcmp(parser->tval, "px") == 0) {
+ lentype = CSS_LENGTH_TYPE_PX;
+ Css_next_token(parser);
+ } else if (strcmp(parser->tval, "mm") == 0) {
+ lentype = CSS_LENGTH_TYPE_MM;
+ Css_next_token(parser);
+ } else if (strcmp(parser->tval, "cm") == 0) {
+ lentype = CSS_LENGTH_TYPE_MM;
+ fval *= 10;
+ Css_next_token(parser);
+ } else if (strcmp(parser->tval, "in") == 0) {
+ lentype = CSS_LENGTH_TYPE_MM;
+ fval *= 25.4;
+ Css_next_token(parser);
+ } else if (strcmp(parser->tval, "pt") == 0) {
+ lentype = CSS_LENGTH_TYPE_MM;
+ fval *= (25.4 / 72);
+ Css_next_token(parser);
+ } else if (strcmp(parser->tval, "pc") == 0) {
+ lentype = CSS_LENGTH_TYPE_MM;
+ fval *= (25.4 / 6);
+ Css_next_token(parser);
+ } else if (strcmp(parser->tval, "em") == 0) {
+ lentype = CSS_LENGTH_TYPE_EM;
+ Css_next_token(parser);
+ } else if (strcmp(parser->tval, "ex") == 0) {
+ lentype = CSS_LENGTH_TYPE_EX;
+ Css_next_token(parser);
+ }
+ } else if (Css_property_info[prop].type ==
+ CSS_TYPE_LENGTH_PERCENTAGE &&
+ parser->ttype == CSS_TK_CHAR &&
+ parser->tval[0] == '%') {
+ fval /= 100;
+ lentype = CSS_LENGTH_TYPE_PERCENTAGE;
+ Css_next_token(parser);
+ }
+
+ val->intVal = CSS_CREATE_LENGTH(fval, lentype);
+ } else if (parser->ttype == CSS_TK_SYMBOL &&
+ strcmp(parser->tval, "auto") == 0) {
+ val->intVal = CSS_LENGTH_TYPE_AUTO;
+ }
+ break;
+
+ case CSS_TYPE_COLOR:
+ if (parser->ttype == CSS_TK_COLOR) {
+ val->intVal = a_Color_parse(parser->tval, -1, &err);
+ if (err)
+ MSG_CSS("color is not in \"%s\" format\n", "#RRGGBB");
+ else
+ ret = true;
+ Css_next_token(parser);
+ } else if (parser->ttype == CSS_TK_SYMBOL) {
+ val->intVal = a_Color_parse(parser->tval, -1, &err);
+ if (err)
+ MSG_CSS("color is not in \"%s\" format\n", "#RRGGBB");
+ else
+ ret = true;
+ Css_next_token(parser);
+ }
+ break;
+
+ case CSS_TYPE_STRING:
+ if (parser->ttype == CSS_TK_STRING) {
+ val->strVal = dStrdup(parser->tval);
+ Css_next_token(parser);
+ }
+ break;
+
+ case CSS_TYPE_SYMBOL:
+ if (parser->ttype == CSS_TK_SYMBOL) {
+ val->strVal = dStrdup(parser->tval);
+ ret = true;
+ Css_next_token(parser);
+ }
+ break;
+
+ case CSS_TYPE_FONT_WEIGHT:
+ ival = 0;
+ if (parser->ttype == CSS_TK_DECINT) {
+ ival = atoi(parser->tval);
+ if (ival < 100 || ival > 900)
+ /* invalid */
+ ival = 0;
+ } else if (parser->ttype == CSS_TK_SYMBOL) {
+ if (strcmp(parser->tval, "normal") == 0)
+ ival = CssProperty::CSS_FONT_WEIGHT_NORMAL;
+ if (strcmp(parser->tval, "bold") == 0)
+ ival = CssProperty::CSS_FONT_WEIGHT_BOLD;
+ if (strcmp(parser->tval, "bolder") == 0)
+ ival = CssProperty::CSS_FONT_WEIGHT_BOLDER;
+ if (strcmp(parser->tval, "lighter") == 0)
+ ival = CssProperty::CSS_FONT_WEIGHT_LIGHTER;
+ }
+
+ if (ival != 0) {
+ val->intVal = ival;
+ ret = true;
+ Css_next_token(parser);
+ }
+ break;
+
+ case CSS_TYPE_UNUSED:
+ /* nothing */
+ break;
+
+ case CSS_TYPE_INTEGER:
+ /* Not used for parser values. */
+ default:
+ assert(false); /* not reached */
+ }
+
+ return ret;
+}
+
+static bool Css_parse_weight(CssParser * parser)
+{
+ if (parser->ttype == CSS_TK_CHAR && parser->tval[0] == '!') {
+ Css_next_token(parser);
+ if (parser->ttype == CSS_TK_SYMBOL &&
+ strcmp(parser->tval, "important") == 0) {
+ Css_next_token(parser);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/*
+ * bsearch(3) compare function for searching properties
+ */
+static int Css_property_info_cmp(const void *a, const void *b)
+{
+ return strcmp(((CssPropertyInfo *) a)->symbol,
+ ((CssPropertyInfo *) b)->symbol);
+}
+
+
+/*
+ * bsearch(3) compare function for searching shorthands
+ */
+static int Css_shorthand_info_cmp(const void *a, const void *b)
+{
+ return strcmp(((CssShorthandInfo *) a)->symbol,
+ ((CssShorthandInfo *) b)->symbol);
+}
+
+static void Css_parse_declaration(CssParser * parser,
+ CssPropertyList * props,
+ CssPropertyList * importantProps)
+{
+ CssPropertyInfo pi, *pip;
+ CssShorthandInfo si, *sip;
+
+ CssProperty::Name prop;
+ CssProperty::Value val, dir_vals[4];
+ bool found, weight;
+ int sh_index, i, j, n;
+ int dir_set[4][4] = {
+ /* 1 value */ {0, 0, 0, 0},
+ /* 2 values */ {0, 0, 1, 1},
+ /* 3 values */ {0, 2, 1, 1},
+ /* 4 values */ {0, 2, 3, 1}
+ };
+
+ if (parser->ttype == CSS_TK_SYMBOL) {
+ pi.symbol = parser->tval;
+ pip =
+ (CssPropertyInfo *) bsearch(&pi, Css_property_info,
+ CSS_NUM_PARSED_PROPERTIES,
+ sizeof(CssPropertyInfo),
+ Css_property_info_cmp);
+ if (pip) {
+ prop = (CssProperty::Name) (pip - Css_property_info);
+ Css_next_token(parser);
+ if (parser->ttype == CSS_TK_CHAR && parser->tval[0] == ':') {
+ Css_next_token(parser);
+ if (Css_parse_value(parser, prop, &val)) {
+ weight = Css_parse_weight(parser);
+ if (weight)
+ importantProps->set(prop, val);
+ else
+ props->set(prop, val);
+ }
+ }
+ } else {
+ /* Try shorthands. */
+ si.symbol = parser->tval;
+ sip =
+ (CssShorthandInfo *) bsearch(&pi, Css_shorthand_info,
+ CSS_SHORTHAND_NUM,
+ sizeof(CssShorthandInfo),
+ Css_shorthand_info_cmp);
+ if (sip) {
+ sh_index = sip - Css_shorthand_info;
+ Css_next_token(parser);
+ if (parser->ttype == CSS_TK_CHAR && parser->tval[0] == ':') {
+ Css_next_token(parser);
+
+ switch (Css_shorthand_info[sh_index].type) {
+ case CssShorthandInfo::CSS_SHORTHAND_MULTIPLE:
+ do {
+ for (found = false, i = 0;
+ !found &&
+ Css_shorthand_info[sh_index].properties[i] != -1;
+ i++)
+ if (Css_token_matches_property(parser,
+ Css_shorthand_info
+ [sh_index].
+ properties[i])) {
+ found = true;
+ DEBUG_MSG(DEBUG_PARSE_LEVEL,
+ "will assign to '%s'\n",
+ Css_property_info
+ [Css_shorthand_info[sh_index]
+ .properties[i]].symbol);
+ if (Css_parse_value(parser,
+ Css_shorthand_info[sh_index]
+ .properties[i], &val)) {
+ weight = Css_parse_weight(parser);
+ if (weight)
+ importantProps->
+ set(Css_shorthand_info[sh_index].
+ properties[i], val);
+ else
+ props->set(Css_shorthand_info[sh_index].
+ properties[i], val);
+ }
+ }
+ } while (found);
+ break;
+
+ case CssShorthandInfo::CSS_SHORTHAND_DIRECTIONS:
+ n = 0;
+ while (n < 4) {
+ if (Css_token_matches_property(parser,
+ Css_shorthand_info
+ [sh_index].
+ properties[0]) &&
+ Css_parse_value(parser,
+ Css_shorthand_info[sh_index]
+ .properties[0], &val)) {
+ dir_vals[n] = val;
+ n++;
+ } else
+ break;
+ }
+
+ weight = Css_parse_weight(parser);
+ if (n > 0) {
+ for (i = 0; i < 4; i++)
+ if (weight)
+ importantProps->set(Css_shorthand_info[sh_index]
+ .properties[i],
+ dir_vals[dir_set[n - 1]
+ [i]]);
+ else
+ props->set(Css_shorthand_info[sh_index]
+ .properties[i],
+ dir_vals[dir_set[n - 1][i]]);
+ } else
+ MSG_CSS("no values for shorthand property '%s'\n",
+ Css_shorthand_info[sh_index].symbol);
+
+ break;
+
+ case CssShorthandInfo::CSS_SHORTHAND_BORDER:
+ do {
+ for (found = false, i = 0;
+ !found && i < 3;
+ i++)
+ if (Css_token_matches_property(parser,
+ Css_shorthand_info
+ [sh_index].
+ properties[i])) {
+ found = true;
+ if (Css_parse_value(parser,
+ Css_shorthand_info[sh_index]
+ .properties[i], &val)) {
+ weight = Css_parse_weight(parser);
+ for (j = 0; j < 4; j++)
+ if (weight)
+ importantProps->
+ set(Css_shorthand_info[sh_index].
+ properties[j * 3 + i], val);
+ else
+ props->set(Css_shorthand_info[sh_index].
+ properties[j * 3 + i], val);
+ }
+ }
+ } while (found);
+ break;
+
+ case CssShorthandInfo::CSS_SHORTHAND_FONT:
+ /* todo: Not yet implemented. */
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ /* Skip all tokens until the expected end. */
+ while (!(parser->ttype == CSS_TK_END ||
+ (parser->ttype == CSS_TK_CHAR &&
+ (parser->tval[0] == ';' || parser->tval[0] == '}'))))
+ Css_next_token(parser);
+
+ if (parser->ttype == CSS_TK_CHAR && parser->tval[0] == ';')
+ Css_next_token(parser);
+}
+
+static bool Css_parse_simple_selector(CssParser * parser,
+ CssSimpleSelector *selector) {
+ const char *p, **pp;
+
+ if (parser->ttype == CSS_TK_SYMBOL) {
+ selector->element = a_Html_tag_index(parser->tval);
+ Css_next_token(parser);
+ if (parser->space_separated)
+ return true;
+ } else if (parser->ttype == CSS_TK_CHAR && parser->tval[0] == '*') {
+ selector->element = CssSimpleSelector::ELEMENT_ANY;
+ Css_next_token(parser);
+ if (parser->space_separated)
+ return true;
+ } else if (parser->ttype == CSS_TK_CHAR && parser->tval[0] != '#' &&
+ parser->tval[0] != '.' && parser->tval[0] != ':') {
+ return false;
+ }
+
+ do {
+ pp = NULL;
+ if (parser->ttype == CSS_TK_CHAR) {
+ switch (parser->tval[0]) {
+ case '#':
+ pp = &selector->id;
+ break;
+ case '.':
+ pp = &selector->klass;
+ break;
+ case ':':
+ pp = &selector->pseudo;
+ break;
+ }
+ }
+
+ if (pp) {
+ Css_next_token(parser);
+ if (parser->space_separated)
+ return true;
+
+ if (parser->ttype == CSS_TK_SYMBOL ||
+ parser->ttype == CSS_TK_DECINT) {
+ if (*pp == NULL)
+ *pp = dStrdup(parser->tval);
+ Css_next_token(parser);
+ } else if (parser->ttype == CSS_TK_FLOAT) {
+ /* In this case, we are actually interested in three tokens:
+ * number, '.', number. Instead, we have a decimal fraction,
+ * which we split up again. */
+ p = strchr(parser->tval, '.');
+ if (*pp == NULL)
+ *pp = dStrndup(parser->tval, p - parser->tval);
+ if (selector->klass == NULL)
+ selector->klass = dStrdup(p + 1);
+ Css_next_token(parser);
+ }
+ if (parser->space_separated)
+ return true;
+ }
+ } while (pp);
+
+ DEBUG_MSG(DEBUG_PARSE_LEVEL, "end of simple selector (%s, %s, %s, %d)\n",
+ selector->id, selector->klass,
+ selector->pseudo, selector->element);
+
+ return true;
+}
+
+static CssSelector *Css_parse_selector(CssParser * parser) {
+ CssSelector *selector = new CssSelector ();
+
+ while (true) {
+ if (! Css_parse_simple_selector (parser, selector->top ()))
+ Css_next_token(parser); /* make sure we advance at least one token */
+
+ if (parser->ttype == CSS_TK_CHAR &&
+ (parser->tval[0] == ',' || parser->tval[0] == '{')) {
+ return selector;
+ } else if (parser->ttype == CSS_TK_CHAR && parser->tval[0] == '>') {
+ selector->addSimpleSelector (CssSelector::CHILD);
+ } else if (parser->ttype != CSS_TK_END && parser->space_separated) {
+ selector->addSimpleSelector (CssSelector::DESCENDENT);
+ } else {
+ delete selector;
+ return NULL;
+ }
+ }
+
+ return selector;
+}
+
+static void Css_parse_ruleset(CssParser * parser)
+{
+ lout::misc::SimpleVector < CssSelector * >*list;
+ CssPropertyList *props, *importantProps;
+ CssSelector *selector;
+
+ list = new lout::misc::SimpleVector < CssSelector * >(1);
+
+ while (true) {
+ selector = Css_parse_selector(parser);
+
+ if (selector) {
+ selector->ref();
+ list->increase();
+ list->set(list->size() - 1, selector);
+ }
+
+ if (parser->ttype == CSS_TK_CHAR && parser->tval[0] == ',')
+ /* To read the next token. */
+ Css_next_token(parser);
+ else
+ /* No more selectors. */
+ break;
+ }
+
+ DEBUG_MSG(DEBUG_PARSE_LEVEL, "end of %s\n", "selectors");
+
+ props = new CssPropertyList();
+ props->ref();
+ importantProps = new CssPropertyList();
+ importantProps->ref();
+
+ /* Read block. ('{' has already been read.) */
+ if (parser->ttype != CSS_TK_END) {
+ parser->within_block = true;
+ Css_next_token(parser);
+ do
+ Css_parse_declaration(parser, props, importantProps);
+ while (!(parser->ttype == CSS_TK_END ||
+ (parser->ttype == CSS_TK_CHAR && parser->tval[0] == '}')));
+ parser->within_block = false;
+ }
+
+ for (int i = 0; i < list->size(); i++) {
+ CssSelector *s = list->get(i);
+
+ if (parser->origin == CSS_ORIGIN_USER_AGENT) {
+ parser->context->addRule(new CssRule(s, props),
+ CSS_PRIMARY_USER_AGENT);
+ } else if (parser->origin == CSS_ORIGIN_USER) {
+ parser->context->addRule(new CssRule(s, props), CSS_PRIMARY_USER);
+ parser->context->addRule(new CssRule(s, importantProps),
+ CSS_PRIMARY_USER_IMPORTANT);
+ } else if (parser->origin == CSS_ORIGIN_AUTHOR) {
+ parser->context->addRule(new CssRule(s, props),
+ CSS_PRIMARY_AUTHOR);
+ parser->context->addRule(new CssRule(s, importantProps),
+ CSS_PRIMARY_AUTHOR_IMPORTANT);
+ }
+
+ s->unref();
+ }
+
+ props->unref();
+ importantProps->unref();
+
+ delete list;
+
+ if (parser->ttype == CSS_TK_CHAR && parser->tval[0] == '}')
+ Css_next_token(parser);
+}
+
+void a_Css_parse(CssContext * context,
+ const char *buf,
+ int buflen, int order_count, CssOrigin origin)
+{
+ CssParser parser;
+
+ parser.context = context;
+ parser.buf = buf;
+ parser.buflen = buflen;
+ parser.bufptr = 0;
+ parser.order_count = 0;
+ parser.origin = origin;
+ parser.within_block = false;
+ parser.space_separated = false;
+
+ Css_next_token(&parser);
+ while (parser.ttype != CSS_TK_END)
+ Css_parse_ruleset(&parser);
+}
diff --git a/src/cssparser.hh b/src/cssparser.hh
new file mode 100644
index 00000000..6638496d
--- /dev/null
+++ b/src/cssparser.hh
@@ -0,0 +1,63 @@
+#ifndef __CSSPARSER_HH__
+#define __CSSPARSER_HH__
+
+#include "css.hh"
+
+/* The last three ones are never parsed. */
+#define CSS_NUM_INTERNAL_PROPERTIES 3
+#define CSS_NUM_PARSED_PROPERTIES \
+ (CssProperty::CSS_PROPERTY_LAST - CSS_NUM_INTERNAL_PROPERTIES)
+
+
+typedef enum {
+ CSS_TYPE_INTEGER, /* This type is only used internally, for x-*
+ properties. */
+ CSS_TYPE_ENUM, /* Value is i, if represented by
+ enum_symbols[i]. */
+ CSS_TYPE_MULTI_ENUM, /* For all enum_symbols[i], 1 << i are
+ combined. */
+ CSS_TYPE_LENGTH_PERCENTAGE, /* <length> or <percentage>. Represented by
+ CssLength. */
+ CSS_TYPE_LENGTH, /* <length>, represented as CssLength.
+ Note: In some cases, CSS_TYPE_LENGTH is used
+ instead of CSS_TYPE_LENGTH_PERCENTAGE,
+ only because Dw cannot handle percentages
+ in this particular case (e.g.
+ 'margin-*-width'). */
+ CSS_TYPE_COLOR, /* Represented as integer. */
+ CSS_TYPE_FONT_WEIGHT, /* this very special and only used by
+ 'font-weight' */
+ CSS_TYPE_STRING, /* <string> */
+ CSS_TYPE_SYMBOL, /* Symbols, which are directly copied (as
+ opposed to CSS_TYPE_ENUM and
+ CSS_TYPE_MULTI_ENUM). Used for
+ 'font-family'. */
+ CSS_TYPE_UNUSED /* Not yet used. Will itself get unused some
+ day. */
+} CssValueType;
+
+typedef enum {
+ CSS_ORIGIN_USER_AGENT,
+ CSS_ORIGIN_USER,
+ CSS_ORIGIN_AUTHOR,
+} CssOrigin;
+
+typedef struct {
+ const char *symbol;
+ CssValueType type;
+ const char **enum_symbols;
+} CssPropertyInfo;
+
+
+void a_Css_init (void);
+void a_Css_freeall (void);
+
+void a_Css_parse (CssContext *context,
+ const char *buf,
+ int buflen,
+ int order_count,
+ CssOrigin origin);
+
+extern CssPropertyInfo Css_property_info[CssProperty::CSS_PROPERTY_LAST];
+
+#endif // __CSS_H__
diff --git a/src/doctree.hh b/src/doctree.hh
new file mode 100644
index 00000000..97686e40
--- /dev/null
+++ b/src/doctree.hh
@@ -0,0 +1,20 @@
+#ifndef __DOCTREE_HH__
+#define __DOCTREE_HH__
+
+class DoctreeNode {
+ public:
+ int depth;
+ int element;
+ const char *klass;
+ const char *pseudo;
+ const char *id;
+};
+
+class Doctree {
+ public:
+ virtual ~Doctree () {};
+ virtual const DoctreeNode *top () = 0;
+ virtual const DoctreeNode *parent (const DoctreeNode *node) = 0;
+};
+
+#endif
diff --git a/src/form.cc b/src/form.cc
index 76f2c32b..c442c017 100644
--- a/src/form.cc
+++ b/src/form.cc
@@ -287,7 +287,7 @@ void Html_tag_open_form(DilloHtml *html, const char *tag, int tagsize)
char *charset, *first;
const char *attrbuf;
- DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->wordStyle ());
if (html->InFlags & IN_FORM) {
BUG_MSG("nested forms\n");
@@ -545,10 +545,10 @@ void Html_tag_open_input(DilloHtml *html, const char *tag, int tagsize)
if (prefs.standard_widget_colors)
bg = NULL;
else
- bg = Color::createShaded(HT2LT(html), S_TOP(html)->current_bg_color);
+ bg = Color::create (HT2LT(html), S_TOP(html)->current_bg_color);
HTML_SET_TOP_ATTR(html, backgroundColor, bg);
- DW2TB(html->dw)->addWidget (embed, S_TOP(html)->style);
+ DW2TB(html->dw)->addWidget (embed, html->styleEngine->style ());
}
dFree(type);
dFree(name);
@@ -581,10 +581,10 @@ void Html_tag_open_isindex(DilloHtml *html, const char *tag, int tagsize)
html->charset);
html->InFlags |= IN_FORM;
- DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->wordStyle ());
if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "prompt")))
- DW2TB(html->dw)->addText(attrbuf, S_TOP(html)->style);
+ DW2TB(html->dw)->addText(attrbuf, html->styleEngine->wordStyle ());
ResourceFactory *factory = HT2LT(html)->getResourceFactory();
EntryResource *entryResource = factory->createEntryResource (20, false);
@@ -595,9 +595,9 @@ void Html_tag_open_isindex(DilloHtml *html, const char *tag, int tagsize)
if (prefs.standard_widget_colors)
bg = NULL;
else
- bg = Color::createShaded(HT2LT(html), S_TOP(html)->current_bg_color);
+ bg = Color::create (HT2LT(html), S_TOP(html)->current_bg_color);
HTML_SET_TOP_ATTR(html, backgroundColor, bg);
- DW2TB(html->dw)->addWidget (embed, S_TOP(html)->style);
+ DW2TB(html->dw)->addWidget (embed, html->styleEngine->style ());
a_Url_free(action);
html->InFlags &= ~IN_FORM;
@@ -663,10 +663,10 @@ void Html_tag_open_textarea(DilloHtml *html, const char *tag, int tagsize)
if (prefs.standard_widget_colors)
bg = NULL;
else
- bg = Color::createShaded(HT2LT(html), S_TOP(html)->current_bg_color);
+ bg = Color::create (HT2LT(html), S_TOP(html)->current_bg_color);
HTML_SET_TOP_ATTR(html, backgroundColor, bg);
- DW2TB(html->dw)->addWidget (embed, S_TOP(html)->style);
+ DW2TB(html->dw)->addWidget (embed, html->styleEngine->style ());
dFree(name);
}
@@ -747,7 +747,7 @@ void Html_tag_open_select(DilloHtml *html, const char *tag, int tagsize)
}
HTML_SET_TOP_ATTR(html, backgroundColor,
Color::createShaded (HT2LT(html), bg));
- DW2TB(html->dw)->addWidget (embed, S_TOP(html)->style);
+ DW2TB(html->dw)->addWidget (embed, html->styleEngine->style ());
// size = 0;
// if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "size")))
@@ -866,12 +866,12 @@ void Html_tag_open_button(DilloHtml *html, const char *tag, int tagsize)
Embed *embed;
char *name, *value;
- style_attrs = *S_TOP(html)->style;
+ style_attrs = *html->styleEngine->style ();
style_attrs.margin.setVal(0);
style_attrs.borderWidth.setVal(0);
style_attrs.padding.setVal(0);
style_attrs.backgroundColor =
- Color::createShaded(HT2LT(html), S_TOP(html)->current_bg_color);
+ Color::create (HT2LT(html), S_TOP(html)->current_bg_color);
style = Style::create (HT2LT(html), &style_attrs);
page = new Textblock (prefs.limit_text_width);
@@ -1917,14 +1917,13 @@ static Embed *Html_input_image(DilloHtml *html, const char *tag, int tagsize)
if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "src")) &&
(url = a_Html_url_new(html, attrbuf, NULL, 0))) {
- style_attrs = *S_TOP(html)->style;
+ style_attrs = *html->styleEngine->style ();
style_attrs.cursor = CURSOR_POINTER;
style_attrs.backgroundColor =
- style::Color::createShaded(HT2LT(html), S_TOP(html)->current_bg_color);
+ style::Color::create (HT2LT(html), S_TOP(html)->current_bg_color);
/* create new image and add it to the button */
- if ((Image = a_Html_add_new_image(html, tag, tagsize, url, &style_attrs,
- false))) {
+ if ((Image = a_Html_add_new_image(html, tag, tagsize, url, false))) {
Style *style = Style::create (HT2LT(html), &style_attrs);
IM2DW(Image)->setStyle (style);
ResourceFactory *factory = HT2LT(html)->getResourceFactory();
diff --git a/src/html.cc b/src/html.cc
index 1c3652ba..e3b961c5 100644
--- a/src/html.cc
+++ b/src/html.cc
@@ -106,14 +106,10 @@ static const char *Html_get_attr2(DilloHtml *html,
int tagsize,
const char *attrname,
int tag_parsing_flags);
-static void Html_add_widget(DilloHtml *html, Widget *widget,
- char *width_str, char *height_str,
- StyleAttrs *style_attrs);
static int Html_write_raw(DilloHtml *html, char *buf, int bufsize, int Eof);
static void Html_load_image(BrowserWindow *bw, DilloUrl *url,
DilloImage *image);
static void Html_callback(int Op, CacheClient_t *Client);
-static int Html_tag_index(const char *tag);
static void Html_tag_cleanup_at_close(DilloHtml *html, int TagIdx);
/*-----------------------------------------------------------------------------
@@ -305,9 +301,10 @@ static int Html_add_new_linkimage(DilloHtml *html,
void a_Html_set_top_font(DilloHtml *html, const char *name, int size,
int BI, int BImask)
{
+#if 0
FontAttrs font_attrs;
- font_attrs = *S_TOP(html)->style->font;
+ font_attrs = *html->styleEngine->style ()->font;
if (name)
font_attrs.name = name;
if (size)
@@ -319,6 +316,7 @@ void a_Html_set_top_font(DilloHtml *html, const char *name, int size,
HTML_SET_TOP_ATTR (html, font,
Font::create (HT2LT(html), &font_attrs));
+#endif
}
/*
@@ -326,25 +324,26 @@ void a_Html_set_top_font(DilloHtml *html, const char *name, int size,
* sets the style at the top of the stack.
*/
void a_Html_tag_set_align_attr(DilloHtml *html,
+ CssPropertyList *props,
const char *tag, int tagsize)
{
- const char *align, *charattr;
+ const char *align;
if ((align = a_Html_get_attr(html, tag, tagsize, "align"))) {
- Style *old_style = S_TOP(html)->style;
- StyleAttrs style_attrs = *old_style;
+ TextAlignType textAlignType = TEXT_ALIGN_LEFT;
if (dStrcasecmp (align, "left") == 0)
- style_attrs.textAlign = TEXT_ALIGN_LEFT;
+ textAlignType = TEXT_ALIGN_LEFT;
else if (dStrcasecmp (align, "right") == 0)
- style_attrs.textAlign = TEXT_ALIGN_RIGHT;
+ textAlignType = TEXT_ALIGN_RIGHT;
else if (dStrcasecmp (align, "center") == 0)
- style_attrs.textAlign = TEXT_ALIGN_CENTER;
+ textAlignType = TEXT_ALIGN_CENTER;
else if (dStrcasecmp (align, "justify") == 0)
- style_attrs.textAlign = TEXT_ALIGN_JUSTIFY;
+ textAlignType = TEXT_ALIGN_JUSTIFY;
+#if 0
else if (dStrcasecmp (align, "char") == 0) {
/* TODO: Actually not supported for <p> etc. */
- style_attrs.textAlign = TEXT_ALIGN_STRING;
+ v.textAlign = TEXT_ALIGN_STRING;
if ((charattr = a_Html_get_attr(html, tag, tagsize, "char"))) {
if (charattr[0] == 0)
/* TODO: ALIGN=" ", and even ALIGN="&32;" will reult in
@@ -358,8 +357,8 @@ void a_Html_tag_set_align_attr(DilloHtml *html,
/* TODO: Examine LANG attr of <html>. */
style_attrs.textAlignChar = '.';
}
- S_TOP(html)->style = Style::create (HT2LT(html), &style_attrs);
- old_style->unref ();
+#endif
+ props->set (CssProperty::CSS_PROPERTY_TEXT_ALIGN, textAlignType);
}
}
@@ -368,19 +367,22 @@ void a_Html_tag_set_align_attr(DilloHtml *html,
* sets the style in style_attrs. Returns true when set.
*/
bool a_Html_tag_set_valign_attr(DilloHtml *html, const char *tag,
- int tagsize, StyleAttrs *style_attrs)
+ int tagsize, CssPropertyList *props)
{
const char *attr;
+ VAlignType valign;
if ((attr = a_Html_get_attr(html, tag, tagsize, "valign"))) {
if (dStrcasecmp (attr, "top") == 0)
- style_attrs->valign = VALIGN_TOP;
+ valign = VALIGN_TOP;
else if (dStrcasecmp (attr, "bottom") == 0)
- style_attrs->valign = VALIGN_BOTTOM;
+ valign = VALIGN_BOTTOM;
else if (dStrcasecmp (attr, "baseline") == 0)
- style_attrs->valign = VALIGN_BASELINE;
+ valign = VALIGN_BASELINE;
else
- style_attrs->valign = VALIGN_MIDDLE;
+ valign = VALIGN_MIDDLE;
+
+ props->set (CssProperty::CSS_PROPERTY_VERTICAL_ALIGN, valign);
return true;
} else
return false;
@@ -388,55 +390,23 @@ bool a_Html_tag_set_valign_attr(DilloHtml *html, const char *tag,
/*
- * Add a new DwPage into the current DwPage, for indentation.
- * left and right are the horizontal indentation amounts, space is the
- * vertical space around the block.
+ * Create and add a new Textblock to the current Textblock
*/
-static void Html_add_indented_widget(DilloHtml *html, Widget *textblock,
- int left, int right, int space)
+static void Html_add_textblock(DilloHtml *html, int space)
{
- StyleAttrs style_attrs;
- Style *style;
-
- style_attrs = *S_TOP(html)->style;
-
- style_attrs.margin.setVal (0);
- style_attrs.borderWidth.setVal (0);
- style_attrs.padding.setVal(0);
-
- /* Activate this for debugging */
-#if 0
- style_attrs.borderWidth.setVal (1);
- style_attrs.setBorderColor (
- Color::createShaded (HT2LT(html), style_attrs.color->getColor());
- style_attrs.setBorderStyle (BORDER_DASHED);
-#endif
-
- style_attrs.margin.left = left;
- style_attrs.margin.right = right;
- style = Style::create (HT2LT(html), &style_attrs);
+ Textblock *textblock = new Textblock (prefs.limit_text_width);
- DW2TB(html->dw)->addParbreak (space, style);
- DW2TB(html->dw)->addWidget (textblock, style);
- DW2TB(html->dw)->addParbreak (space, style);
+ DW2TB(html->dw)->addParbreak (space, html->styleEngine->wordStyle ());
+ DW2TB(html->dw)->addWidget (textblock, html->styleEngine->style ());
+ DW2TB(html->dw)->addParbreak (space, html->styleEngine->wordStyle ());
S_TOP(html)->textblock = html->dw = textblock;
S_TOP(html)->hand_over_break = true;
- style->unref ();
/* Handle it when the user clicks on a link */
html->connectSignals(textblock);
}
/*
- * Create and add a new indented DwPage to the current DwPage
- */
-static void Html_add_indented(DilloHtml *html, int left, int right, int space)
-{
- Textblock *textblock = new Textblock (prefs.limit_text_width);
- Html_add_indented_widget (html, textblock, left, right, space);
-}
-
-/*
* Given a font_size, this will return the correct 'level'.
* (or the closest, if the exact level isn't found).
*/
@@ -497,6 +467,8 @@ DilloHtml::DilloHtml(BrowserWindow *p_bw, const DilloUrl *url,
a_Misc_parse_content_type(content_type, NULL, NULL, &charset);
stop_parser = false;
+ stop_parser_after_head = false;
+ repush_after_head = false;
CurrTagOfs = 0;
OldTagOfs = 0;
@@ -507,8 +479,7 @@ DilloHtml::DilloHtml(BrowserWindow *p_bw, const DilloUrl *url,
stack = new misc::SimpleVector <DilloHtmlState> (16);
stack->increase();
- stack->getRef(0)->style = NULL;
- stack->getRef(0)->table_cell_style = NULL;
+ stack->getRef(0)->table_cell_props = NULL;
stack->getRef(0)->parse_mode = DILLO_HTML_PARSE_MODE_INIT;
stack->getRef(0)->table_mode = DILLO_HTML_TABLE_MODE_NONE;
stack->getRef(0)->cell_text_align_set = false;
@@ -521,6 +492,8 @@ DilloHtml::DilloHtml(BrowserWindow *p_bw, const DilloUrl *url,
stack->getRef(0)->current_bg_color = prefs.bg_color;
stack->getRef(0)->hand_over_break = false;
+ styleEngine = new StyleEngine (HT2LT (this));
+
InFlags = IN_NONE;
Stash = dStr_new("");
@@ -548,8 +521,8 @@ DilloHtml::DilloHtml(BrowserWindow *p_bw, const DilloUrl *url,
images = new misc::SimpleVector <DilloLinkImage*> (16);
//a_Dw_image_map_list_init(&maps);
- link_color = prefs.link_color;
- visited_color = prefs.visited_color;
+ link_color = -1;
+ visited_color = -1;
/* Initialize the main widget */
initDw();
@@ -562,26 +535,12 @@ DilloHtml::DilloHtml(BrowserWindow *p_bw, const DilloUrl *url,
*/
void DilloHtml::initDw()
{
- StyleAttrs style_attrs;
- FontAttrs font_attrs;
-
dReturn_if_fail (dw == NULL);
/* Create the main widget */
dw = stack->getRef(0)->textblock = new Textblock (prefs.limit_text_width);
- /* Create a dummy font, attribute, and tag for the bottom of the stack. */
- font_attrs.name = prefs.vw_fontname;
- font_attrs.size = Html_level_to_fontsize(FontSizesBase);
- font_attrs.weight = 400;
- font_attrs.style = FONT_STYLE_NORMAL;
-
- style_attrs.initValues ();
- style_attrs.font = Font::create (HT2LT(this), &font_attrs);
- style_attrs.color = Color::createSimple (HT2LT(this), prefs.text_color);
- stack->getRef(0)->style = Style::create (HT2LT(this), &style_attrs);
-
- stack->getRef(0)->table_cell_style = NULL;
+ stack->getRef(0)->table_cell_props = NULL;
/* Handle it when the user clicks on a link */
connectSignals(dw);
@@ -627,6 +586,8 @@ DilloHtml::~DilloHtml()
}
delete (images);
+ delete styleEngine;
+
//a_Dw_image_map_list_free(&maps);
}
@@ -681,7 +642,6 @@ int DilloHtml::getCurTagLineNumber()
*/
void DilloHtml::freeParseData()
{
- (stack->getRef(0)->style)->unref (); /* template style */
delete(stack);
dStr_free(Stash, TRUE);
@@ -1137,11 +1097,11 @@ static void Html_process_space(DilloHtml *html, const char *space,
if (spaceCnt) {
spc = dStrnfill(spaceCnt, ' ');
- DW2TB(html->dw)->addText (spc, S_TOP(html)->style);
+ DW2TB(html->dw)->addText (spc, html->styleEngine->wordStyle ());
dFree(spc);
spaceCnt = 0;
}
- DW2TB(html->dw)->addLinebreak (S_TOP(html)->style);
+ DW2TB(html->dw)->addLinebreak (html->styleEngine->wordStyle ());
html->pre_column = 0;
}
html->PreFirstChar = false;
@@ -1169,7 +1129,7 @@ static void Html_process_space(DilloHtml *html, const char *space,
if (spaceCnt) {
spc = dStrnfill(spaceCnt, ' ');
- DW2TB(html->dw)->addText (spc, S_TOP(html)->style);
+ DW2TB(html->dw)->addText (spc, html->styleEngine->wordStyle ());
dFree(spc);
}
@@ -1177,7 +1137,7 @@ static void Html_process_space(DilloHtml *html, const char *space,
if (SGML_SPCDEL) {
/* SGML_SPCDEL ignores white space inmediately after an open tag */
} else if (!html->PrevWasSPC) {
- DW2TB(html->dw)->addSpace(S_TOP(html)->style);
+ DW2TB(html->dw)->addSpace(html->styleEngine->wordStyle ());
html->PrevWasSPC = true;
}
@@ -1230,7 +1190,7 @@ static void Html_process_word(DilloHtml *html, const char *word, int size)
while (Pword[++i] && !isspace(Pword[i])) ;
ch = Pword[i];
Pword[i] = 0;
- DW2TB(html->dw)->addText(Pword, S_TOP(html)->style);
+ DW2TB(html->dw)->addText(Pword, html->styleEngine->wordStyle ());
Pword[i] = ch;
html->pre_column += i - start;
html->PreFirstChar = false;
@@ -1240,7 +1200,7 @@ static void Html_process_word(DilloHtml *html, const char *word, int size)
} else {
if (!memchr(word,'&', size)) {
/* No entities */
- DW2TB(html->dw)->addText(word, S_TOP(html)->style);
+ DW2TB(html->dw)->addText(word, html->styleEngine->wordStyle ());
} else {
/* Collapse white-space entities inside the word (except &nbsp;) */
Pword = a_Html_parse_entities(html, word, size);
@@ -1248,7 +1208,7 @@ static void Html_process_word(DilloHtml *html, const char *word, int size)
if (strchr("\t\f\n\r", Pword[i]))
for (j = i; (Pword[j] = Pword[j+1]); ++j) ;
- DW2TB(html->dw)->addText(Pword, S_TOP(html)->style);
+ DW2TB(html->dw)->addText(Pword, html->styleEngine->wordStyle ());
dFree(Pword);
}
}
@@ -1284,7 +1244,7 @@ static void Html_eventually_pop_dw(DilloHtml *html, bool hand_over_break)
{
if (html->dw != S_TOP(html)->textblock) {
if (hand_over_break)
- DW2TB(html->dw)->handOverBreak (S_TOP(html)->style);
+ DW2TB(html->dw)->handOverBreak (html->styleEngine->style ());
DW2TB(html->dw)->flush ();
html->dw = S_TOP(html)->textblock;
}
@@ -1303,10 +1263,8 @@ static void Html_push_tag(DilloHtml *html, int tag_idx)
* instead of copying all fields except for tag. --Jcid */
*html->stack->getRef(n_items) = *html->stack->getRef(n_items - 1);
html->stack->getRef(n_items)->tag_idx = tag_idx;
- /* proper memory management, may be unref'd later */
- (S_TOP(html)->style)->ref ();
- if (S_TOP(html)->table_cell_style)
- (S_TOP(html)->table_cell_style)->ref ();
+ if (S_TOP(html)->table_cell_props)
+ S_TOP(html)->table_cell_props->ref ();
html->dw = S_TOP(html)->textblock;
}
@@ -1316,6 +1274,7 @@ static void Html_push_tag(DilloHtml *html, int tag_idx)
*/
static void Html_force_push_tag(DilloHtml *html, int tag_idx)
{
+ html->styleEngine->startElement (tag_idx);
Html_push_tag(html, tag_idx);
}
@@ -1326,9 +1285,9 @@ static void Html_real_pop_tag(DilloHtml *html)
{
bool hand_over_break;
- (S_TOP(html)->style)->unref ();
- if (S_TOP(html)->table_cell_style)
- (S_TOP(html)->table_cell_style)->unref ();
+ html->styleEngine->endElement (S_TOP(html)->tag_idx);
+ if (S_TOP(html)->table_cell_props)
+ S_TOP(html)->table_cell_props->unref ();
hand_over_break = S_TOP(html)->hand_over_break;
html->stack->setSize (html->stack->size() - 1);
Html_eventually_pop_dw(html, hand_over_break);
@@ -1403,10 +1362,10 @@ static void Html_tag_cleanup_at_close(DilloHtml *html, int TagIdx)
/*
* Used by a_Html_parse_length
*/
-static Length Html_parse_length_or_multi_length (const char *attr,
- char **endptr)
+static CssLength Html_parse_length_or_multi_length (const char *attr,
+ char **endptr)
{
- Length l;
+ CssLength l;
double v;
char *end;
@@ -1414,12 +1373,12 @@ static Length Html_parse_length_or_multi_length (const char *attr,
switch (*end) {
case '%':
end++;
- l = createPerLength (v / 100);
+ l = CSS_CREATE_LENGTH (v / 100, CSS_LENGTH_TYPE_PERCENTAGE);
break;
case '*':
end++;
- l = createRelLength (v);
+ l = CSS_CREATE_LENGTH (v, CSS_LENGTH_TYPE_RELATIVE);
break;
/*
The "px" suffix seems not allowed by HTML4.01 SPEC.
@@ -1428,7 +1387,7 @@ static Length Html_parse_length_or_multi_length (const char *attr,
end += 2;
*/
default:
- l = createAbsLength ((int)v);
+ l = CSS_CREATE_LENGTH (v, CSS_LENGTH_TYPE_PX);
break;
}
@@ -1442,24 +1401,24 @@ static Length Html_parse_length_or_multi_length (const char *attr,
* Returns a length or a percentage, or UNDEF_LENGTH in case
* of an error, or if attr is NULL.
*/
-Length a_Html_parse_length (DilloHtml *html, const char *attr)
+CssLength a_Html_parse_length (DilloHtml *html, const char *attr)
{
- Length l;
+ CssLength l;
char *end;
l = Html_parse_length_or_multi_length (attr, &end);
- if (isRelLength (l))
+ if (CSS_LENGTH_TYPE (l) == CSS_LENGTH_TYPE_RELATIVE)
/* not allowed as &Length; */
- return LENGTH_AUTO;
+ l = CSS_CREATE_LENGTH(0.0, CSS_LENGTH_TYPE_AUTO);
else {
/* allow only whitespaces */
if (*end && !isspace (*end)) {
BUG_MSG("Garbage after length: %s\n", attr);
- return LENGTH_AUTO;
+ l = CSS_CREATE_LENGTH(0.0, CSS_LENGTH_TYPE_AUTO);
}
}
- _MSG("a_Html_parse_length: \"%s\" %d\n", attr, absLengthVal(l));
+ _MSG("a_Html_parse_length: \"%s\" %d\n", attr, CSS_LENGTH_VALUE(l));
return l;
}
@@ -1636,14 +1595,22 @@ static void Html_tag_open_head(DilloHtml *html, const char *tag, int tagsize)
* Handle close HEAD element
* Note: as a side effect of Html_test_section() this function is called
* twice when the head element is closed implicitly.
+ * Note2: HEAD is parsed once completely got. This asserts that a
+ * linked stylesheet will always arrive after HEAD contents.
*/
static void Html_tag_close_head(DilloHtml *html, int TagIdx)
{
if (html->InFlags & IN_HEAD) {
+ MSG("Closing HEAD section\n");
if (html->Num_TITLE == 0)
BUG_MSG("HEAD section lacks the TITLE element\n");
-
+
html->InFlags &= ~IN_HEAD;
+
+ if (html->stop_parser_after_head)
+ html->stop_parser = true;
+ if (html->repush_after_head)
+ a_Nav_repush(html->bw);
}
}
@@ -1693,11 +1660,27 @@ static void Html_tag_close_script(DilloHtml *html, int TagIdx)
/*
* Handle open STYLE
- * store the contents to the stash where (in the future) the style
- * sheet interpreter can get it.
+ * Store contents in the stash where the style sheet interpreter can get it.
*/
static void Html_tag_open_style(DilloHtml *html, const char *tag, int tagsize)
{
+ const char *attrbuf;
+
+ if (!(attrbuf = a_Html_get_attr(html, tag, tagsize, "type"))) {
+ BUG_MSG("type attribute is required for <style>\n");
+ } else if (dStrcasecmp(attrbuf, "text/css")) {
+ MSG("Shouldn't be applying <style type=\"%s\">\n", attrbuf);
+ /* We need to inform close_style() */
+ }
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "media")) &&
+ dStrcasecmp(attrbuf, "all") && !dStristr(attrbuf, "screen")) {
+ /* HTML 4.01 sec. 6.13 says that media descriptors are case-sensitive,
+ * but sec. 14.2.3 says that the attribute is case-insensitive.
+ * TODO can be a comma-separated list.
+ * TODO handheld.
+ */
+ MSG("Shouldn't be applying <style media=\"%s\">\n", attrbuf);
+ }
a_Html_stash_init(html);
S_TOP(html)->parse_mode = DILLO_HTML_PARSE_MODE_VERBATIM;
}
@@ -1707,7 +1690,8 @@ static void Html_tag_open_style(DilloHtml *html, const char *tag, int tagsize)
*/
static void Html_tag_close_style(DilloHtml *html, int TagIdx)
{
- /* eventually the stash will be sent to an interpreter for parsing */
+ html->styleEngine->parse(html->Stash->str, html->Stash->len,
+ 0, CSS_ORIGIN_AUTHOR);
}
/*
@@ -1717,8 +1701,7 @@ static void Html_tag_open_body(DilloHtml *html, const char *tag, int tagsize)
{
const char *attrbuf;
Textblock *textblock;
- StyleAttrs style_attrs;
- Style *style;
+ CssPropertyList props;
int32_t color;
if (!(html->InFlags & IN_BODY))
@@ -1736,43 +1719,37 @@ static void Html_tag_open_body(DilloHtml *html, const char *tag, int tagsize)
textblock = DW2TB(html->dw);
- if (!prefs.force_my_colors) {
- if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "bgcolor"))) {
- color = a_Html_color_parse(html, attrbuf, prefs.bg_color);
- if (color == 0xffffff && !prefs.allow_white_bg)
- color = prefs.bg_color;
-
- style_attrs = *html->dw->getStyle ();
- style_attrs.backgroundColor = Color::createShaded(HT2LT(html), color);
- style = Style::create (HT2LT(html), &style_attrs);
- html->dw->setStyle (style);
- style->unref ();
- S_TOP(html)->current_bg_color = color;
- }
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "bgcolor"))) {
+ color = a_Html_color_parse(html, attrbuf, prefs.bg_color);
+ if (color == 0xffffff && !prefs.allow_white_bg)
+ color = prefs.bg_color;
+ S_TOP(html)->current_bg_color = color;
+ props.set (CssProperty::CSS_PROPERTY_BACKGROUND_COLOR, color);
+ }
- if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "text"))) {
- color = a_Html_color_parse(html, attrbuf, prefs.text_color);
- HTML_SET_TOP_ATTR (html, color,
- Color::createSimple (HT2LT(html),color));
- }
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "text"))) {
+ color = a_Html_color_parse(html, attrbuf, prefs.text_color);
+ props.set (CssProperty::CSS_PROPERTY_COLOR, color);
+ }
- if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "link")))
- html->link_color = a_Html_color_parse(html,attrbuf,prefs.link_color);
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "link")))
+ html->link_color = a_Html_color_parse(html, attrbuf, -1);
- if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "vlink")))
- html->visited_color = a_Html_color_parse(html, attrbuf,
- prefs.visited_color);
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "vlink")))
+ html->visited_color = a_Html_color_parse(html, attrbuf, -1);
- if (prefs.contrast_visited_color) {
- /* get a color that has a "safe distance" from text, link and bg */
- html->visited_color =
+ if (prefs.contrast_visited_color) {
+ /* get a color that has a "safe distance" from text, link and bg */
+ html->visited_color =
a_Color_vc(html->visited_color,
- S_TOP(html)->style->color->getColor(),
+ html->styleEngine->style ()->color->getColor(),
html->link_color,
S_TOP(html)->current_bg_color);
- }
}
+ html->styleEngine->setNonCssHints (&props);
+ html->dw->setStyle (html->styleEngine->style ());
+
S_TOP(html)->parse_mode = DILLO_HTML_PARSE_MODE_BODY;
}
@@ -1794,13 +1771,16 @@ static void Html_tag_close_body(DilloHtml *html, int TagIdx)
*/
static void Html_tag_open_p(DilloHtml *html, const char *tag, int tagsize)
{
+ CssPropertyList props;
+
if ((html->InFlags & IN_LI) && !html->WordAfterLI) {
/* ignore first parbreak after an empty <LI> */
html->WordAfterLI = true;
} else {
- DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->wordStyle ());
}
- a_Html_tag_set_align_attr (html, tag, tagsize);
+ a_Html_tag_set_align_attr (html, &props, tag, tagsize);
+ html->styleEngine->setNonCssHints (&props);
}
/*
@@ -1828,27 +1808,27 @@ static void Html_tag_open_frame (DilloHtml *html, const char *tag, int tagsize)
src = dStrdup(attrbuf);
- style_attrs = *(S_TOP(html)->style);
+ style_attrs = *(html->styleEngine->style ());
if (a_Capi_get_flags(url) & CAPI_IsCached) { /* visited frame */
style_attrs.color =
- Color::createSimple (HT2LT(html), html->visited_color);
+ Color::create (HT2LT(html), html->visited_color);
} else { /* unvisited frame */
- style_attrs.color = Color::createSimple (HT2LT(html), html->link_color);
+ style_attrs.color = Color::create (HT2LT(html), html->link_color);
}
style_attrs.textDecoration |= TEXT_DECORATION_UNDERLINE;
style_attrs.x_link = Html_set_new_link(html, &url);
style_attrs.cursor = CURSOR_POINTER;
link_style = Style::create (HT2LT(html), &style_attrs);
- textblock->addParbreak (5, S_TOP(html)->style);
+ textblock->addParbreak (5, html->styleEngine->wordStyle ());
/* The bullet will be assigned the current list style, which should
* be "disc" by default, but may in very weird pages be different.
* Anyway, there should be no harm. */
bullet = new Bullet();
- textblock->addWidget(bullet, S_TOP(html)->style);
- textblock->addSpace(S_TOP(html)->style);
+ textblock->addWidget(bullet, html->styleEngine->style ());
+ textblock->addSpace(html->styleEngine->wordStyle ());
if (tolower(tag[1]) == 'i') {
/* IFRAME usually comes with very long advertising/spying URLS,
@@ -1865,7 +1845,7 @@ static void Html_tag_open_frame (DilloHtml *html, const char *tag, int tagsize)
}
}
- textblock->addParbreak (5, S_TOP(html)->style);
+ textblock->addParbreak (5, html->styleEngine->wordStyle ());
link_style->unref ();
dFree(src);
@@ -1879,9 +1859,9 @@ static void Html_tag_open_frame (DilloHtml *html, const char *tag, int tagsize)
static void Html_tag_open_frameset (DilloHtml *html,
const char *tag, int tagsize)
{
- DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
- DW2TB(html->dw)->addText("--FRAME--", S_TOP(html)->style);
- Html_add_indented(html, 40, 0, 5);
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->wordStyle ());
+ DW2TB(html->dw)->addText("--FRAME--", html->styleEngine->wordStyle ());
+ Html_add_textblock(html, 5);
}
/*
@@ -1889,18 +1869,19 @@ static void Html_tag_open_frameset (DilloHtml *html,
*/
static void Html_tag_open_h(DilloHtml *html, const char *tag, int tagsize)
{
- DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
+ CssPropertyList props;
- /* TODO: combining these two would be slightly faster */
- a_Html_set_top_font(html, prefs.vw_fontname,
- Html_level_to_fontsize(FontSizesNum - (tag[2] - '0')),
- 1, 3);
- a_Html_tag_set_align_attr (html, tag, tagsize);
+
+ html->styleEngine->inheritBackgroundColor ();
+ a_Html_tag_set_align_attr (html, &props, tag, tagsize);
+ html->styleEngine->setNonCssHints (&props);
+
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->wordStyle ());
/* First finalize unclosed H tags (we test if already named anyway) */
a_Menu_pagemarks_set_text(html->bw, html->Stash->str);
a_Menu_pagemarks_add(html->bw, DW2TB(html->dw),
- S_TOP(html)->style, (tag[2] - '0'));
+ html->styleEngine->style (), (tag[2] - '0'));
a_Html_stash_init(html);
S_TOP(html)->parse_mode =
DILLO_HTML_PARSE_MODE_STASH_AND_BODY;
@@ -1912,7 +1893,7 @@ static void Html_tag_open_h(DilloHtml *html, const char *tag, int tagsize)
static void Html_tag_close_h(DilloHtml *html, int TagIdx)
{
a_Menu_pagemarks_set_text(html->bw, html->Stash->str);
- DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->wordStyle ());
}
/*
@@ -1921,20 +1902,21 @@ static void Html_tag_close_h(DilloHtml *html, int TagIdx)
static void Html_tag_open_big_small(DilloHtml *html,
const char *tag, int tagsize)
{
- int level;
+}
- level =
- Html_fontsize_to_level(S_TOP(html)->style->font->size) +
- ((dStrncasecmp(tag+1, "big", 3)) ? -1 : 1);
- a_Html_set_top_font(html, NULL, Html_level_to_fontsize(level), 0, 0);
+static void Html_tag_open_span(DilloHtml *html,
+ const char *tag, int tagsize)
+{
+ html->styleEngine->inheritBackgroundColor();
}
+
/*
* <BR>
*/
static void Html_tag_open_br(DilloHtml *html, const char *tag, int tagsize)
{
- DW2TB(html->dw)->addLinebreak (S_TOP(html)->style);
+ DW2TB(html->dw)->addLinebreak (html->styleEngine->wordStyle ());
}
/*
@@ -1942,39 +1924,27 @@ static void Html_tag_open_br(DilloHtml *html, const char *tag, int tagsize)
*/
static void Html_tag_open_font(DilloHtml *html, const char *tag, int tagsize)
{
- StyleAttrs style_attrs;
- Style *old_style;
/*Font font;*/
const char *attrbuf;
int32_t color;
-
- if (!prefs.force_my_colors) {
- old_style = S_TOP(html)->style;
- style_attrs = *old_style;
-
- if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "color"))) {
- if (prefs.contrast_visited_color && html->InVisitedLink) {
- color = html->visited_color;
- } else {
- /* use the tag-specified color */
- color = a_Html_color_parse(html, attrbuf,
- style_attrs.color->getColor());
- style_attrs.color = Color::createSimple (HT2LT(html), color);
- }
+ CssPropertyList props;
+
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "color"))) {
+ if (prefs.contrast_visited_color && html->InVisitedLink) {
+ color = html->visited_color;
+ } else {
+ /* use the tag-specified color */
+ color = a_Html_color_parse(html, attrbuf, -1);
}
+ if (color != -1)
+ props.set (CssProperty::CSS_PROPERTY_COLOR, color);
+ }
-#if 0
- //if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "face"))) {
- // font = *( style_attrs.font );
- // font.name = attrbuf;
- // style_attrs.font = a_Dw_style_font_new_from_list (&font);
- //}
-#endif
+// \todo reenable font face handling when font selection is implemented
+// if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "face")))
+// props.set (CssProperty::CSS_PROPERTY_FONT_FAMILY, attrbuf);
- S_TOP(html)->style =
- Style::create (HT2LT(html), &style_attrs);
- old_style->unref ();
- }
+ html->styleEngine->setNonCssHints (&props);
}
/*
@@ -1996,7 +1966,6 @@ static void Html_tag_open_abbr(DilloHtml *html, const char *tag, int tagsize)
*/
static void Html_tag_open_b(DilloHtml *html, const char *tag, int tagsize)
{
- a_Html_set_top_font(html, NULL, 0, 1, 1);
}
/*
@@ -2004,7 +1973,6 @@ static void Html_tag_open_b(DilloHtml *html, const char *tag, int tagsize)
*/
static void Html_tag_open_strong(DilloHtml *html, const char *tag, int tagsize)
{
- a_Html_set_top_font(html, NULL, 0, 1, 1);
}
/*
@@ -2012,7 +1980,6 @@ static void Html_tag_open_strong(DilloHtml *html, const char *tag, int tagsize)
*/
static void Html_tag_open_i(DilloHtml *html, const char *tag, int tagsize)
{
- a_Html_set_top_font(html, NULL, 0, 2, 2);
}
/*
@@ -2020,7 +1987,6 @@ static void Html_tag_open_i(DilloHtml *html, const char *tag, int tagsize)
*/
static void Html_tag_open_em(DilloHtml *html, const char *tag, int tagsize)
{
- a_Html_set_top_font(html, NULL, 0, 2, 2);
}
/*
@@ -2028,7 +1994,6 @@ static void Html_tag_open_em(DilloHtml *html, const char *tag, int tagsize)
*/
static void Html_tag_open_cite(DilloHtml *html, const char *tag, int tagsize)
{
- a_Html_set_top_font(html, NULL, 0, 2, 2);
}
/*
@@ -2036,8 +2001,7 @@ static void Html_tag_open_cite(DilloHtml *html, const char *tag, int tagsize)
*/
static void Html_tag_open_center(DilloHtml *html, const char *tag, int tagsize)
{
- DW2TB(html->dw)->addParbreak (0, S_TOP(html)->style);
- HTML_SET_TOP_ATTR(html, textAlign, TEXT_ALIGN_CENTER);
+ DW2TB(html->dw)->addParbreak (0, html->styleEngine->wordStyle ());
}
/*
@@ -2046,8 +2010,7 @@ static void Html_tag_open_center(DilloHtml *html, const char *tag, int tagsize)
static void Html_tag_open_address(DilloHtml *html,
const char *tag, int tagsize)
{
- DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
- a_Html_set_top_font(html, NULL, 0, 2, 2);
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->wordStyle ());
}
/*
@@ -2055,7 +2018,6 @@ static void Html_tag_open_address(DilloHtml *html,
*/
static void Html_tag_open_tt(DilloHtml *html, const char *tag, int tagsize)
{
- a_Html_set_top_font(html, prefs.fw_fontname, 0, 0, 0);
}
/*
@@ -2064,7 +2026,6 @@ static void Html_tag_open_tt(DilloHtml *html, const char *tag, int tagsize)
*/
DilloImage *a_Html_add_new_image(DilloHtml *html, const char *tag,
int tagsize, DilloUrl *url,
- dw::core::style::StyleAttrs *style_attrs,
bool add)
{
const int MAX_W = 6000, MAX_H = 6000;
@@ -2073,8 +2034,9 @@ DilloImage *a_Html_add_new_image(DilloHtml *html, const char *tag,
char *width_ptr, *height_ptr, *alt_ptr;
const char *attrbuf;
Length l_w, l_h;
- int space, w = 0, h = 0;
+ int space, border, w = 0, h = 0;
bool load_now;
+ CssPropertyList props;
// if (prefs.show_tooltip &&
// (attrbuf = a_Html_get_attr(html, tag, tagsize, "title")))
@@ -2091,17 +2053,24 @@ DilloImage *a_Html_add_new_image(DilloHtml *html, const char *tag,
// TODO: the same for percentage and relative lengths.
if (width_ptr) {
l_w = a_Html_parse_length (html, width_ptr);
- w = isAbsLength(l_w) ? absLengthVal(l_w) : 0;
+ w = (int) CSS_LENGTH_TYPE(l_w) == CSS_LENGTH_TYPE_PX ?
+ CSS_LENGTH_VALUE(l_w) : 0;
}
if (height_ptr) {
l_h = a_Html_parse_length (html, height_ptr);
- h = isAbsLength(l_h) ? absLengthVal(l_h) : 0;
+ h = (int) CSS_LENGTH_TYPE(l_h) == CSS_LENGTH_TYPE_PX ?
+ CSS_LENGTH_VALUE(l_h) : 0;
}
if (w < 0 || h < 0 || abs(w*h) > MAX_W * MAX_H) {
dFree(width_ptr);
dFree(height_ptr);
width_ptr = height_ptr = NULL;
MSG("a_Html_add_new_image: suspicious image size request %dx%d\n", w, h);
+ } else {
+ if (width_ptr)
+ props.set (CssProperty::CSS_PROPERTY_WIDTH, l_w);
+ if (height_ptr)
+ props.set (CssProperty::CSS_PROPERTY_HEIGHT, l_h);
}
/* TODO: we should scale the image respecting its ratio.
@@ -2114,27 +2083,52 @@ DilloImage *a_Html_add_new_image(DilloHtml *html, const char *tag,
/* Spacing to the left and right */
if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "hspace"))) {
space = strtol(attrbuf, NULL, 10);
- if (space > 0)
- style_attrs->margin.left = style_attrs->margin.right = space;
+ if (space > 0) {
+ space = CSS_CREATE_LENGTH(space, CSS_LENGTH_TYPE_PX);
+ props.set (CssProperty::CSS_PROPERTY_MARGIN_LEFT, space);
+ props.set (CssProperty::CSS_PROPERTY_MARGIN_RIGHT, space);
+ }
}
/* Spacing at the top and bottom */
if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "vspace"))) {
space = strtol(attrbuf, NULL, 10);
- if (space > 0)
- style_attrs->margin.top = style_attrs->margin.bottom = space;
+ if (space > 0) {
+ space = CSS_CREATE_LENGTH(space, CSS_LENGTH_TYPE_PX);
+ props.set (CssProperty::CSS_PROPERTY_MARGIN_TOP, space);
+ props.set (CssProperty::CSS_PROPERTY_MARGIN_BOTTOM, space);
+ }
+ }
+
+ /* Border */
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "border"))) {
+ border = strtol(attrbuf, NULL, 10);
+ if (border >= 0) {
+ border = CSS_CREATE_LENGTH(border, CSS_LENGTH_TYPE_PX);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_TOP_WIDTH, border);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_BOTTOM_WIDTH, border);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_LEFT_WIDTH, border);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_RIGHT_WIDTH, border);
+
+ props.set (CssProperty::CSS_PROPERTY_BORDER_TOP_STYLE, BORDER_SOLID);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_BOTTOM_STYLE,
+ BORDER_SOLID);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_LEFT_STYLE, BORDER_SOLID);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_RIGHT_STYLE,BORDER_SOLID);
+ }
}
/* x_img is an index to a list of {url,image} pairs.
* We know Html_add_new_linkimage() will use size() as its next index */
- style_attrs->x_img = html->images->size();
+ props.set (CssProperty::PROPERTY_X_IMG, html->images->size());
+
+ html->styleEngine->setNonCssHints(&props);
/* Add a new image widget to this page */
Image = a_Image_new(0, 0, alt_ptr, S_TOP(html)->current_bg_color);
- if (add) {
- Html_add_widget(html, (Widget*)Image->dw, width_ptr, height_ptr,
- style_attrs);
- }
+ if (add)
+ DW2TB(html->dw)->addWidget((Widget*)Image->dw,
+ html->styleEngine->style());
load_now = a_UIcmd_get_images_enabled(html->bw) ||
(a_Capi_get_flags(url) & CAPI_IsCached);
@@ -2178,9 +2172,7 @@ static void Html_tag_open_img(DilloHtml *html, const char *tag, int tagsize)
DilloImage *Image;
DilloUrl *url, *usemap_url;
Textblock *textblock;
- StyleAttrs style_attrs;
const char *attrbuf;
- int border;
/* This avoids loading images. Useful for viewing suspicious HTML email. */
if (URL_FLAGS(html->base_url) & URL_SpamSafe)
@@ -2197,34 +2189,13 @@ static void Html_tag_open_img(DilloHtml *html, const char *tag, int tagsize)
/* TODO: usemap URLs outside of the document are not used. */
usemap_url = a_Html_url_new(html, attrbuf, NULL, 0);
- /* Set the style attributes for this image */
- style_attrs = *S_TOP(html)->style;
- if (S_TOP(html)->style->x_link != -1 ||
- usemap_url != NULL) {
- /* Images within links */
- border = 1;
- if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "border")))
- border = strtol (attrbuf, NULL, 10);
-
- if (S_TOP(html)->style->x_link != -1) {
- /* In this case we can use the text color */
- style_attrs.setBorderColor (
- Color::createShaded (HT2LT(html), style_attrs.color->getColor()));
- } else {
- style_attrs.setBorderColor (
- Color::createShaded (HT2LT(html), html->link_color));
- }
- style_attrs.setBorderStyle (BORDER_SOLID);
- style_attrs.borderWidth.setVal (border);
- }
-
- Image = a_Html_add_new_image(html, tag, tagsize, url, &style_attrs, true);
+ Image = a_Html_add_new_image(html, tag, tagsize, url, true);
/* Image maps */
if (a_Html_get_attr(html, tag, tagsize, "ismap")) {
((::dw::Image*)Image->dw)->setIsMap();
_MSG(" Html_tag_open_img: server-side map (ISMAP)\n");
- } else if (S_TOP(html)->style->x_link != -1 &&
+ } else if (html->styleEngine->style ()->x_link != -1 &&
usemap_url == NULL) {
/* For simple links, we have to suppress the "image_pressed" signal.
* This is overridden for USEMAP images. */
@@ -2405,22 +2376,22 @@ static void Html_tag_open_object(DilloHtml *html, const char *tag, int tagsize)
URL_STR(base_url), (base_url != NULL));
dReturn_if_fail ( url != NULL );
- style_attrs = *S_TOP(html)->style;
+ style_attrs = *html->styleEngine->style ();
if (a_Capi_get_flags(url) & CAPI_IsCached) {
- style_attrs.color = Color::createSimple (
+ style_attrs.color = Color::create (
HT2LT(html),
html->visited_color
/*
a_Color_vc(html->visited_color,
- S_TOP(html)->style->color->getColor(),
+ html->styleEngine->style()->color->getColor(),
html->link_color,
- S_TOP(html)->style->backgroundColor->getColor()),
+ html->styleEngine->style()->backgroundColor->getColor()
+ );
*/
);
} else {
- style_attrs.color = Color::createSimple(HT2LT(html),
- html->link_color);
+ style_attrs.color = Color::create (HT2LT(html), html->link_color);
}
style_attrs.textDecoration |= TEXT_DECORATION_UNDERLINE;
@@ -2463,7 +2434,7 @@ static const char* Html_get_javascript_link(DilloHtml *html)
static void Html_add_anchor(DilloHtml *html, const char *name)
{
_MSG("Registering ANCHOR: %s\n", name);
- if (!DW2TB(html->dw)->addAnchor (name, S_TOP(html)->style))
+ if (!DW2TB(html->dw)->addAnchor (name, html->styleEngine->style ()))
BUG_MSG("Anchor names must be unique within the document\n");
/*
* According to Sec. 12.2.1 of the HTML 4.01 spec, "anchor names that
@@ -2480,9 +2451,8 @@ static void Html_add_anchor(DilloHtml *html, const char *name)
*/
static void Html_tag_open_a(DilloHtml *html, const char *tag, int tagsize)
{
- StyleAttrs style_attrs;
- Style *old_style;
DilloUrl *url;
+ CssPropertyList props;
const char *attrbuf;
/* TODO: add support for MAP with A HREF */
@@ -2497,38 +2467,24 @@ static void Html_tag_open_a(DilloHtml *html, const char *tag, int tagsize)
url = a_Html_url_new(html, attrbuf, NULL, 0);
dReturn_if_fail ( url != NULL );
- old_style = S_TOP(html)->style;
- style_attrs = *old_style;
-
if (a_Capi_get_flags(url) & CAPI_IsCached) {
html->InVisitedLink = true;
- style_attrs.color = Color::createSimple (
- HT2LT(html),
- html->visited_color
-/*
- a_Color_vc(html->visited_color,
- S_TOP(html)->style->color->getColor(),
- html->link_color,
- S_TOP(html)->current_bg_color),
-*/
- );
+ html->styleEngine->setPseudoVisited ();
+ if (html->visited_color != -1)
+ props.set (CssProperty::CSS_PROPERTY_COLOR, html->visited_color);
} else {
- style_attrs.color = Color::createSimple(HT2LT(html),
- html->link_color);
+ html->styleEngine->setPseudoLink ();
+ if (html->link_color != -1)
+ props.set (CssProperty::CSS_PROPERTY_COLOR, html->link_color);
}
-// if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "title")))
-// style_attrs.x_tooltip = a_Dw_tooltip_new_no_ref(attrbuf);
-
- style_attrs.textDecoration |= TEXT_DECORATION_UNDERLINE;
- style_attrs.x_link = Html_set_new_link(html, &url);
- style_attrs.cursor = CURSOR_POINTER;
+ props.set (CssProperty::PROPERTY_X_LINK, Html_set_new_link(html, &url));
- S_TOP(html)->style =
- Style::create (HT2LT(html), &style_attrs);
- old_style->unref ();
+ html->styleEngine->setNonCssHints (&props);
}
+ html->styleEngine->inheritBackgroundColor ();
+
if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "name"))) {
if (prefs.show_extra_warnings)
Html_check_name_val(html, attrbuf, "name");
@@ -2551,15 +2507,6 @@ static void Html_tag_close_a(DilloHtml *html, int TagIdx)
*/
static void Html_tag_open_u(DilloHtml *html, const char *tag, int tagsize)
{
- Style *style;
- StyleAttrs style_attrs;
-
- style = S_TOP(html)->style;
- style_attrs = *style;
- style_attrs.textDecoration |= TEXT_DECORATION_UNDERLINE;
- S_TOP(html)->style =
- Style::create (HT2LT(html), &style_attrs);
- style->unref ();
}
/*
@@ -2567,15 +2514,6 @@ static void Html_tag_open_u(DilloHtml *html, const char *tag, int tagsize)
*/
static void Html_tag_open_strike(DilloHtml *html, const char *tag, int tagsize)
{
- Style *style;
- StyleAttrs style_attrs;
-
- style = S_TOP(html)->style;
- style_attrs = *style;
- style_attrs.textDecoration |= TEXT_DECORATION_LINE_THROUGH;
- S_TOP(html)->style =
- Style::create (HT2LT(html), &style_attrs);
- style->unref ();
}
/*
@@ -2584,8 +2522,8 @@ static void Html_tag_open_strike(DilloHtml *html, const char *tag, int tagsize)
static void Html_tag_open_blockquote(DilloHtml *html,
const char *tag, int tagsize)
{
- DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
- Html_add_indented(html, 40, 40, 9);
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->wordStyle ());
+ Html_add_textblock(html, 9);
}
/*
@@ -2599,7 +2537,7 @@ static void Html_tag_open_q(DilloHtml *html, const char *tag, int tagsize)
*/
const char *U201C = "\xe2\x80\x9c";
- DW2TB(html->dw)->addText (U201C, S_TOP(html)->style);
+ DW2TB(html->dw)->addText (U201C, html->styleEngine->wordStyle ());
}
/*
@@ -2610,7 +2548,7 @@ static void Html_tag_close_q(DilloHtml *html, int TagIdx)
/* Right Double Quotation Mark */
const char *U201D = "\xe2\x80\x9d";
- DW2TB(html->dw)->addText (U201D, S_TOP(html)->style);
+ DW2TB(html->dw)->addText (U201D, html->styleEngine->wordStyle ());
}
/*
@@ -2621,8 +2559,8 @@ static void Html_tag_open_ul(DilloHtml *html, const char *tag, int tagsize)
const char *attrbuf;
ListStyleType list_style_type;
- DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
- Html_add_indented(html, 40, 0, 9);
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->wordStyle ());
+ Html_add_textblock(html, 9);
if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "type"))) {
/* list_style_type explicitly defined */
@@ -2641,7 +2579,7 @@ static void Html_tag_open_ul(DilloHtml *html, const char *tag, int tagsize)
/* --EG :: I changed the behavior here : types are cycling instead of
* being forced to square. It's easier for mixed lists level counting.
*/
- switch (S_TOP(html)->style->listStyleType) {
+ switch (html->styleEngine->style ()->listStyleType) {
case LIST_STYLE_TYPE_DISC:
list_style_type = LIST_STYLE_TYPE_CIRCLE;
break;
@@ -2672,11 +2610,8 @@ static void Html_tag_open_ul(DilloHtml *html, const char *tag, int tagsize)
*/
static void Html_tag_open_dir(DilloHtml *html, const char *tag, int tagsize)
{
- ListStyleType list_style_type = LIST_STYLE_TYPE_DISC;
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->wordStyle ());
- DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
- Html_add_indented(html, 40, 0, 9);
- HTML_SET_TOP_ATTR(html, listStyleType, list_style_type);
S_TOP(html)->list_type = HTML_LIST_UNORDERED;
S_TOP(html)->list_number = 0;
S_TOP(html)->ref_list_item = NULL;
@@ -2699,28 +2634,30 @@ static void Html_tag_open_menu(DilloHtml *html, const char *tag, int tagsize)
static void Html_tag_open_ol(DilloHtml *html, const char *tag, int tagsize)
{
const char *attrbuf;
- ListStyleType list_style_type;
int n = 1;
- DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
- Html_add_indented(html, 40, 0, 9);
-
- list_style_type = LIST_STYLE_TYPE_DECIMAL;
-
if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "type"))) {
+ CssPropertyList props;
+ ListStyleType listStyleType = LIST_STYLE_TYPE_DECIMAL;
+
if (*attrbuf == '1')
- list_style_type = LIST_STYLE_TYPE_DECIMAL;
+ listStyleType = LIST_STYLE_TYPE_DECIMAL;
else if (*attrbuf == 'a')
- list_style_type = LIST_STYLE_TYPE_LOWER_ALPHA;
+ listStyleType = LIST_STYLE_TYPE_LOWER_ALPHA;
else if (*attrbuf == 'A')
- list_style_type = LIST_STYLE_TYPE_UPPER_ALPHA;
+ listStyleType = LIST_STYLE_TYPE_UPPER_ALPHA;
else if (*attrbuf == 'i')
- list_style_type = LIST_STYLE_TYPE_LOWER_ROMAN;
+ listStyleType = LIST_STYLE_TYPE_LOWER_ROMAN;
else if (*attrbuf == 'I')
- list_style_type = LIST_STYLE_TYPE_UPPER_ROMAN;
+ listStyleType = LIST_STYLE_TYPE_UPPER_ROMAN;
+
+ props.set (CssProperty::CSS_PROPERTY_LIST_STYLE_TYPE, listStyleType);
+ html->styleEngine->setNonCssHints (&props);
}
- HTML_SET_TOP_ATTR(html, listStyleType, list_style_type);
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->wordStyle ());
+ Html_add_textblock(html, 9);
+
S_TOP(html)->list_type = HTML_LIST_ORDERED;
if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "start")) &&
@@ -2753,7 +2690,7 @@ static void Html_tag_open_li(DilloHtml *html, const char *tag, int tagsize)
ref_list_item = &html->stack->getRef(html->stack->size()-2)->ref_list_item;
/* set the item style */
- word_style = S_TOP(html)->style;
+ word_style = html->styleEngine->wordStyle ();
style_attrs = *word_style;
//style_attrs.backgroundColor = Color::createShaded (HT2LT(html), 0xffff40);
//style_attrs.setBorderColor (Color::createSimple (HT2LT(html), 0x000000));
@@ -2779,7 +2716,8 @@ static void Html_tag_open_li(DilloHtml *html, const char *tag, int tagsize)
BUG_MSG("illegal negative LIST VALUE attribute; Starting from 0\n");
*list_number = 0;
}
- numtostr((*list_number)++, buf, 16, S_TOP(html)->style->listStyleType);
+ numtostr((*list_number)++, buf, 16,
+ html->styleEngine->style ()->listStyleType);
list_item->initWithText (dStrdup(buf), word_style);
list_item->addSpace (word_style);
html->PrevWasSPC = true;
@@ -2809,58 +2747,50 @@ static void Html_tag_close_li(DilloHtml *html, int TagIdx)
static void Html_tag_open_hr(DilloHtml *html, const char *tag, int tagsize)
{
Widget *hruler;
- StyleAttrs style_attrs;
- Style *style;
+ CssPropertyList props;
char *width_ptr;
const char *attrbuf;
int32_t size = 0;
- style_attrs = *S_TOP(html)->style;
-
- width_ptr = a_Html_get_attr_wdef(html, tag, tagsize, "width", "100%");
- style_attrs.width = a_Html_parse_length (html, width_ptr);
- dFree(width_ptr);
+ width_ptr = a_Html_get_attr_wdef(html, tag, tagsize, "width", NULL);
+ if (width_ptr) {
+ props.set (CssProperty::CSS_PROPERTY_WIDTH,
+ a_Html_parse_length (html, width_ptr));
+ dFree(width_ptr);
+ }
if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "size")))
size = strtol(attrbuf, NULL, 10);
-
- if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "align"))) {
- if (dStrcasecmp (attrbuf, "left") == 0)
- style_attrs.textAlign = TEXT_ALIGN_LEFT;
- else if (dStrcasecmp (attrbuf, "right") == 0)
- style_attrs.textAlign = TEXT_ALIGN_RIGHT;
- else if (dStrcasecmp (attrbuf, "center") == 0)
- style_attrs.textAlign = TEXT_ALIGN_CENTER;
- }
+
+ a_Html_tag_set_align_attr(html, &props, tag, tagsize);
/* TODO: evaluate attribute */
if (a_Html_get_attr(html, tag, tagsize, "noshade")) {
- style_attrs.setBorderStyle (BORDER_SOLID);
- style_attrs.setBorderColor (
- Color::createShaded (HT2LT(html), style_attrs.color->getColor()));
- if (size < 1)
+ props.set (CssProperty::CSS_PROPERTY_BORDER_TOP_STYLE, BORDER_SOLID);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_BOTTOM_STYLE, BORDER_SOLID);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_LEFT_STYLE, BORDER_SOLID);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_RIGHT_STYLE, BORDER_SOLID);
+
+ if (size <= 0)
size = 1;
- } else {
- style_attrs.setBorderStyle (BORDER_INSET);
- style_attrs.setBorderColor
- (Color::createShaded (HT2LT(html),
- S_TOP(html)->current_bg_color));
- if (size < 2)
- size = 2;
}
-
- style_attrs.borderWidth.top =
- style_attrs.borderWidth.left = (size + 1) / 2;
- style_attrs.borderWidth.bottom =
- style_attrs.borderWidth.right = size / 2;
- style = Style::create (HT2LT(html), &style_attrs);
+
+ if (size > 0) {
+ CssLength size_top = CSS_CREATE_LENGTH ((size+1)/2, CSS_LENGTH_TYPE_PX);
+ CssLength size_bottom = CSS_CREATE_LENGTH (size / 2, CSS_LENGTH_TYPE_PX);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_TOP_WIDTH, size_top);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_LEFT_WIDTH, size_top);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_BOTTOM_WIDTH, size_bottom);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_RIGHT_WIDTH, size_bottom);
+ }
+
+ DW2TB(html->dw)->addParbreak (5, html->styleEngine->wordStyle ());
- DW2TB(html->dw)->addParbreak (5, S_TOP(html)->style);
+ html->styleEngine->setNonCssHints (&props);
hruler = new Ruler();
- hruler->setStyle (style);
- DW2TB(html->dw)->addWidget (hruler, style);
- style->unref ();
- DW2TB(html->dw)->addParbreak (5, S_TOP(html)->style);
+ hruler->setStyle (html->styleEngine->style ());
+ DW2TB(html->dw)->addWidget (hruler, html->styleEngine->style ());
+ DW2TB(html->dw)->addParbreak (5, html->styleEngine->wordStyle ());
}
/*
@@ -2869,7 +2799,7 @@ static void Html_tag_open_hr(DilloHtml *html, const char *tag, int tagsize)
static void Html_tag_open_dl(DilloHtml *html, const char *tag, int tagsize)
{
/* may want to actually do some stuff here. */
- DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->wordStyle ());
}
/*
@@ -2877,7 +2807,7 @@ static void Html_tag_open_dl(DilloHtml *html, const char *tag, int tagsize)
*/
static void Html_tag_open_dt(DilloHtml *html, const char *tag, int tagsize)
{
- DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->wordStyle ());
a_Html_set_top_font(html, NULL, 0, 1, 1);
}
@@ -2886,8 +2816,8 @@ static void Html_tag_open_dt(DilloHtml *html, const char *tag, int tagsize)
*/
static void Html_tag_open_dd(DilloHtml *html, const char *tag, int tagsize)
{
- DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
- Html_add_indented(html, 40, 40, 9);
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->wordStyle ());
+ Html_add_textblock(html, 9);
}
/*
@@ -2895,12 +2825,10 @@ static void Html_tag_open_dd(DilloHtml *html, const char *tag, int tagsize)
*/
static void Html_tag_open_pre(DilloHtml *html, const char *tag, int tagsize)
{
- DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
- a_Html_set_top_font(html, prefs.fw_fontname, 0, 0, 0);
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->wordStyle ());
/* Is the placement of this statement right? */
S_TOP(html)->parse_mode = DILLO_HTML_PARSE_MODE_PRE;
- HTML_SET_TOP_ATTR (html, whiteSpace, WHITE_SPACE_PRE);
html->pre_column = 0;
html->PreFirstChar = true;
html->InFlags |= IN_PRE;
@@ -2912,7 +2840,7 @@ static void Html_tag_open_pre(DilloHtml *html, const char *tag, int tagsize)
static void Html_tag_close_pre(DilloHtml *html, int TagIdx)
{
html->InFlags &= ~IN_PRE;
- DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->wordStyle ());
}
/*
@@ -2928,7 +2856,7 @@ static int Html_tag_pre_excludes(int tag_idx)
/* initialize array */
if (!ei_set[0])
for (i = 0; es_set[i]; ++i)
- ei_set[i] = Html_tag_index(es_set[i]);
+ ei_set[i] = a_Html_tag_index(es_set[i]);
for (i = 0; ei_set[i]; ++i)
if (tag_idx == ei_set[i])
@@ -3009,8 +2937,8 @@ static void Html_tag_open_meta(DilloHtml *html, const char *tag, int tagsize)
* this code in another bw might have already changed it for us.
*/
if (a_Misc_content_type_cmp(html->content_type, new_content)) {
- a_Nav_repush(html->bw);
- html->stop_parser = true;
+ html->stop_parser_after_head = true;
+ html->repush_after_head = true;
}
}
}
@@ -3018,6 +2946,94 @@ static void Html_tag_open_meta(DilloHtml *html, const char *tag, int tagsize)
}
/*
+ * Called by the network engine when a stylesheet has new data.
+ */
+static void Html_css_load_callback(int Op, CacheClient_t *Client)
+{
+ _MSG("Css_callback: Op=%d\n", Op);
+ if (Op) { /* EOF */
+ BrowserWindow *bw = ((DilloWeb *)Client->Web)->bw;
+ /* Repush when we've got them all */
+ if (--bw->NumPendingStyleSheets == 0)
+ a_Nav_repush(bw);
+ }
+}
+
+/*
+ * Tell cache to retrieve a stylesheet
+ */
+static void Html_load_stylesheet(DilloHtml *html, DilloUrl *url)
+{
+ char *data;
+ int len;
+ if (a_Nav_get_buf(url, &data, &len)) {
+ /* Haven't looked into what origin_count is */
+ if (a_Capi_get_flags(url) & CAPI_Completed)
+ html->styleEngine->parse(data, len, 0, CSS_ORIGIN_AUTHOR);
+ a_Nav_unref_buf(url);
+ } else if (!html->repush_after_head) {
+ /* Fill a Web structure for the cache query */
+ int ClientKey;
+ DilloWeb *Web = a_Web_new(url);
+ Web->bw = html->bw;
+ //Web->flags |= WEB_Stylesheet;
+ if ((ClientKey = a_Capi_open_url(Web, Html_css_load_callback, NULL))) {
+ ++html->bw->NumPendingStyleSheets;
+ a_Bw_add_client(html->bw, ClientKey, 0);
+ a_Bw_add_url(html->bw, url);
+ MSG("Html_load_stylesheet: NumPendingStyleSheets=%d\n",
+ html->bw->NumPendingStyleSheets);
+ }
+ }
+}
+
+/*
+ * Parse the LINK element (Only CSS stylesheets by now).
+ * (If it either hits or misses, is not relevant here; that's up to the
+ * cache functions)
+ */
+static void Html_tag_open_link(DilloHtml *html, const char *tag, int tagsize)
+{
+ DilloUrl *url;
+ const char *attrbuf;
+
+ //char *tag_str = dStrndup(tag, tagsize);
+ //MSG("Html_tag_open_link(): %s\n", tag_str);
+ //dFree(tag_str);
+
+ /* When viewing suspicious HTML email, don't load LINK */
+ if (URL_FLAGS(html->base_url) & URL_SpamSafe)
+ return;
+ /* Ignore LINK outside HEAD */
+ if (!(html->InFlags & IN_HEAD)) {
+ BUG_MSG("the LINK element must be inside the HEAD section\n");
+ return;
+ }
+
+ /* TODO: How will we know when to use "handheld"? Ask the html->bw->ui for
+ screen dimensions, or a dillorc preference. */
+
+ /* CSS stylesheet link */
+ if ((!(attrbuf = a_Html_get_attr(html, tag, tagsize, "rel")) ||
+ dStrcasecmp(attrbuf, "stylesheet")) ||
+ (!(attrbuf = a_Html_get_attr(html, tag, tagsize, "href")) ||
+ !(url = a_Html_url_new(html, attrbuf, NULL, 0))))
+ return;
+ /* IMPLIED attributes? */
+ if (((attrbuf = a_Html_get_attr(html, tag, tagsize, "type")) &&
+ dStrcasecmp(attrbuf, "text/css")) ||
+ ((attrbuf = a_Html_get_attr(html, tag, tagsize, "media")) &&
+ !dStristr(attrbuf, "screen") && dStrcasecmp(attrbuf, "all")))
+ return;
+
+ MSG(" Html_tag_open_link(): URL=%s\n", URL_STR(url));
+ MSG(" repush after HEAD=%d\n", html->repush_after_head);
+
+ Html_load_stylesheet(html, url);
+ a_Url_free(url);
+}
+
+/*
* Set the history of the menu to be consistent with the active menuitem.
*/
//static void Html_select_set_history(DilloHtmlInput *input)
@@ -3065,7 +3081,6 @@ static void Html_tag_open_base(DilloHtml *html, const char *tag, int tagsize)
*/
static void Html_tag_open_code(DilloHtml *html, const char *tag, int tagsize)
{
- a_Html_set_top_font(html, prefs.fw_fontname, 0, 0, 0);
}
/*
@@ -3081,7 +3096,6 @@ static void Html_tag_open_dfn(DilloHtml *html, const char *tag, int tagsize)
*/
static void Html_tag_open_kbd(DilloHtml *html, const char *tag, int tagsize)
{
- a_Html_set_top_font(html, prefs.fw_fontname, 0, 0, 0);
}
/*
@@ -3089,7 +3103,6 @@ static void Html_tag_open_kbd(DilloHtml *html, const char *tag, int tagsize)
*/
static void Html_tag_open_samp(DilloHtml *html, const char *tag, int tagsize)
{
- a_Html_set_top_font(html, prefs.fw_fontname, 0, 0, 0);
}
/*
@@ -3105,7 +3118,6 @@ static void Html_tag_open_var(DilloHtml *html, const char *tag, int tagsize)
*/
static void Html_tag_open_sub(DilloHtml *html, const char *tag, int tagsize)
{
- HTML_SET_TOP_ATTR (html, valign, VALIGN_SUB);
}
/*
@@ -3113,7 +3125,6 @@ static void Html_tag_open_sub(DilloHtml *html, const char *tag, int tagsize)
*/
static void Html_tag_open_sup(DilloHtml *html, const char *tag, int tagsize)
{
- HTML_SET_TOP_ATTR (html, valign, VALIGN_SUPER);
}
/*
@@ -3121,8 +3132,11 @@ static void Html_tag_open_sup(DilloHtml *html, const char *tag, int tagsize)
*/
static void Html_tag_open_div(DilloHtml *html, const char *tag, int tagsize)
{
- DW2TB(html->dw)->addParbreak (0, S_TOP(html)->style);
- a_Html_tag_set_align_attr (html, tag, tagsize);
+ CssPropertyList props;
+
+ a_Html_tag_set_align_attr (html, &props, tag, tagsize);
+ html->styleEngine->setNonCssHints (&props);
+ Html_add_textblock(html, 0);
}
/*
@@ -3130,7 +3144,7 @@ static void Html_tag_open_div(DilloHtml *html, const char *tag, int tagsize)
*/
static void Html_tag_close_div(DilloHtml *html, int TagIdx)
{
- DW2TB(html->dw)->addParbreak (0, S_TOP(html)->style);
+ DW2TB(html->dw)->addParbreak (0, html->styleEngine->wordStyle ());
}
/*
@@ -3145,7 +3159,7 @@ static void Html_tag_close_default(DilloHtml *html, int TagIdx)
*/
static void Html_tag_close_par(DilloHtml *html, int TagIdx)
{
- DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->wordStyle ());
}
@@ -3232,7 +3246,7 @@ const TagInfo Tags[] = {
/* label 010101 */
/* legend 01?? */
{"li", B8(011110),'O',1, Html_tag_open_li, Html_tag_close_li},
- /* link 100000 'F' */
+ {"link", B8(100001),'F',0, Html_tag_open_link, Html_tag_close_default},
{"map", B8(011001),'R',2, Html_tag_open_map, Html_tag_close_map},
/* menu 1010 -- TODO: not exactly 1010, it can contain LI and inline */
{"menu", B8(011010),'R',2, Html_tag_open_menu, Html_tag_close_par},
@@ -3252,7 +3266,7 @@ const TagInfo Tags[] = {
{"script", B8(111001),'R',2, Html_tag_open_script, Html_tag_close_script},
{"select", B8(010101),'R',2, Html_tag_open_select, Html_tag_close_select},
{"small", B8(010101),'R',2, Html_tag_open_big_small, Html_tag_close_default},
- /* span 0101 */
+ {"span", B8(010101),'R',2, Html_tag_open_span, Html_tag_close_default},
{"strike", B8(010101),'R',2, Html_tag_open_strike, Html_tag_close_default},
{"strong", B8(010101),'R',2, Html_tag_open_strong, Html_tag_close_default},
{"style", B8(100101),'R',2, Html_tag_open_style, Html_tag_close_style},
@@ -3296,7 +3310,7 @@ static int Html_tag_compare(const char *p1, const char *p2)
* Get 'tag' index
* return -1 if tag is not handled yet
*/
-static int Html_tag_index(const char *tag)
+int a_Html_tag_index(const char *tag)
{
int low, high, mid, cond;
@@ -3327,17 +3341,17 @@ static int Html_needs_optional_close(int old_idx, int cur_idx)
if (i_P == -1) {
/* initialize the indexes of elements with optional close */
- i_P = Html_tag_index("p"),
- i_LI = Html_tag_index("li"),
- i_TD = Html_tag_index("td"),
- i_TR = Html_tag_index("tr"),
- i_TH = Html_tag_index("th"),
- i_DD = Html_tag_index("dd"),
- i_DT = Html_tag_index("dt"),
- i_OPTION = Html_tag_index("option");
- // i_THEAD = Html_tag_index("thead");
- // i_TFOOT = Html_tag_index("tfoot");
- // i_COLGROUP = Html_tag_index("colgroup");
+ i_P = a_Html_tag_index("p"),
+ i_LI = a_Html_tag_index("li"),
+ i_TD = a_Html_tag_index("td"),
+ i_TR = a_Html_tag_index("tr"),
+ i_TH = a_Html_tag_index("th"),
+ i_DD = a_Html_tag_index("dd"),
+ i_DT = a_Html_tag_index("dt"),
+ i_OPTION = a_Html_tag_index("option");
+ // i_THEAD = a_Html_tag_index("thead");
+ // i_TFOOT = a_Html_tag_index("tfoot");
+ // i_COLGROUP = a_Html_tag_index("colgroup");
}
if (old_idx == i_P || old_idx == i_DT) {
@@ -3434,7 +3448,7 @@ static void Html_test_section(DilloHtml *html, int new_idx, int IsCloseTag)
if (!(html->InFlags & IN_HTML)) {
tag = "<html>";
- tag_idx = Html_tag_index(tag + 1);
+ tag_idx = a_Html_tag_index(tag + 1);
if (tag_idx != new_idx || IsCloseTag) {
/* implicit open */
Html_force_push_tag(html, tag_idx);
@@ -3447,7 +3461,7 @@ static void Html_test_section(DilloHtml *html, int new_idx, int IsCloseTag)
/* head element */
if (!(html->InFlags & IN_HEAD)) {
tag = "<head>";
- tag_idx = Html_tag_index(tag + 1);
+ tag_idx = a_Html_tag_index(tag + 1);
if (tag_idx != new_idx || IsCloseTag) {
/* implicit open of the head element */
Html_force_push_tag(html, tag_idx);
@@ -3460,11 +3474,11 @@ static void Html_test_section(DilloHtml *html, int new_idx, int IsCloseTag)
/* body element */
if (html->InFlags & IN_HEAD) {
tag = "</head>";
- tag_idx = Html_tag_index(tag + 2);
+ tag_idx = a_Html_tag_index(tag + 2);
Html_tag_cleanup_at_close(html, tag_idx);
}
tag = "<body>";
- tag_idx = Html_tag_index(tag + 1);
+ tag_idx = a_Html_tag_index(tag + 1);
if (tag_idx != new_idx || IsCloseTag) {
/* implicit open */
Html_force_push_tag(html, tag_idx);
@@ -3486,7 +3500,7 @@ static void Html_process_tag(DilloHtml *html, char *tag, int tagsize)
char *start = tag + 1; /* discard the '<' */
int IsCloseTag = (*start == '/');
- ni = Html_tag_index(start + IsCloseTag);
+ ni = a_Html_tag_index(start + IsCloseTag);
if (ni == -1) {
/* TODO: doctype parsing is a bit fuzzy, but enough for the time being */
if (!(html->InFlags & IN_HTML)) {
@@ -3520,11 +3534,8 @@ static void Html_process_tag(DilloHtml *html, char *tag, int tagsize)
/* Push the tag into the stack */
Html_push_tag(html, ni);
- /* Call the open function for this tag */
+ html->styleEngine->startElement (ni);
_MSG("Open : %*s%s\n", html->stack->size(), " ", Tags[ni].name);
- Tags[ni].open (html, tag, tagsize);
- if (html->stop_parser)
- break;
/* Now parse attributes that can appear on any tag */
if (tagsize >= 8 && /* length of "<t id=i>" */
@@ -3536,6 +3547,9 @@ static void Html_process_tag(DilloHtml *html, char *tag, int tagsize)
* spec states in Sec. 7.5.2 that anchor ids are case-sensitive.
* So we don't do it and hope for better specs in the future ...
*/
+ if (attrbuf)
+ html->styleEngine->setId (attrbuf);
+
Html_check_name_val(html, attrbuf, "id");
/* We compare the "id" value with the url-decoded "name" value */
if (!html->NameVal || strcmp(html->NameVal, attrbuf)) {
@@ -3551,6 +3565,25 @@ static void Html_process_tag(DilloHtml *html, char *tag, int tagsize)
html->NameVal = NULL;
}
+ if (tagsize >= 10) { /* length of "<t class=i>" */
+ attrbuf = Html_get_attr2(html, tag, tagsize, "class",
+ HTML_LeftTrim | HTML_RightTrim);
+ if (attrbuf)
+ html->styleEngine->setClass (attrbuf);
+ }
+
+ if (tagsize >= 11) { /* length of "<t style=i>" */
+ attrbuf = Html_get_attr2(html, tag, tagsize, "style",
+ HTML_LeftTrim | HTML_RightTrim);
+ if (attrbuf)
+ html->styleEngine->setStyle (attrbuf);
+ }
+
+ /* Call the open function for this tag */
+ Tags[ni].open (html, tag, tagsize);
+ if (html->stop_parser)
+ break;
+
/* Request inmediate close for elements with forbidden close tag. */
/* TODO: XHTML always requires close tags. A simple implementation
* of the commented clause below will make it work. */
@@ -3713,29 +3746,6 @@ char *a_Html_get_attr_wdef(DilloHtml *html,
}
/*
- * Add a widget to the page.
- */
-static void Html_add_widget(DilloHtml *html,
- Widget *widget,
- char *width_str,
- char *height_str,
- StyleAttrs *style_attrs)
-{
- StyleAttrs new_style_attrs;
- Style *style;
-
- new_style_attrs = *style_attrs;
- new_style_attrs.width = width_str ?
- a_Html_parse_length (html, width_str) : LENGTH_AUTO;
- new_style_attrs.height = height_str ?
- a_Html_parse_length (html, height_str) : LENGTH_AUTO;
- style = Style::create (HT2LT(html), &new_style_attrs);
- DW2TB(html->dw)->addWidget (widget, style);
- style->unref ();
-}
-
-
-/*
* Dispatch the apropriate function for 'Op'
* This function is a Cache client and gets called whenever new data arrives
* Op : operation to perform.
diff --git a/src/html_common.hh b/src/html_common.hh
index 302d9ece..4c6f40c5 100644
--- a/src/html_common.hh
+++ b/src/html_common.hh
@@ -13,6 +13,8 @@
#include "form.hh"
+#include "styleengine.hh"
+
/*
* Macros
*/
@@ -36,6 +38,7 @@
* Change one toplevel attribute. var should be an identifier. val is
* only evaluated once, so you can safely use a function call for it.
*/
+#if 0
#define HTML_SET_TOP_ATTR(html, var, val) \
do { \
StyleAttrs style_attrs; \
@@ -48,7 +51,9 @@
Style::create (HT2LT(html), &style_attrs); \
old_style->unref (); \
} while (FALSE)
-
+#else
+#define HTML_SET_TOP_ATTR(html, var, val)
+#endif
/*
* Typedefs
*/
@@ -109,7 +114,7 @@ struct _DilloLinkImage {
};
struct _DilloHtmlState {
- dw::core::style::Style *style, *table_cell_style;
+ CssPropertyList *table_cell_props;
DilloHtmlParseMode parse_mode;
DilloHtmlTableMode table_mode;
bool cell_text_align_set;
@@ -167,6 +172,9 @@ public: //BUG: for now everything is public
char *content_type, *charset;
bool stop_parser;
+ bool stop_parser_after_head;
+ bool repush_after_head;
+
size_t CurrTagOfs;
size_t OldTagOfs, OldTagLine;
@@ -174,6 +182,7 @@ public: //BUG: for now everything is public
float DocTypeVersion; /* HTML or XHTML version number */
lout::misc::SimpleVector<DilloHtmlState> *stack;
+ StyleEngine *styleEngine;
int InFlags; /* tracks which elements we are in */
@@ -232,6 +241,8 @@ public:
* Parser functions
*/
+int a_Html_tag_index(const char *tag);
+
const char *a_Html_get_attr(DilloHtml *html,
const char *tag,
int tagsize,
@@ -249,7 +260,6 @@ DilloUrl *a_Html_url_new(DilloHtml *html,
DilloImage *a_Html_add_new_image(DilloHtml *html, const char *tag,
int tagsize, DilloUrl *url,
- dw::core::style::StyleAttrs *style_attrs,
bool add);
char *a_Html_parse_entities(DilloHtml *html, const char *token, int toksize);
@@ -259,11 +269,11 @@ int32_t a_Html_color_parse(DilloHtml *html,
const char *subtag, int32_t default_color);
dw::core::style::Length a_Html_parse_length (DilloHtml *html,
const char *attr);
-void a_Html_tag_set_align_attr(DilloHtml *html,
+void a_Html_tag_set_align_attr(DilloHtml *html, CssPropertyList *props,
const char *tag, int tagsize);
bool a_Html_tag_set_valign_attr(DilloHtml *html,
const char *tag, int tagsize,
- dw::core::style::StyleAttrs *style_attrs);
+ CssPropertyList *props);
void a_Html_set_top_font(DilloHtml *html, const char *name, int size,
int BI, int BImask);
diff --git a/src/nav.c b/src/nav.c
index 8acf9130..d6293143 100644
--- a/src/nav.c
+++ b/src/nav.c
@@ -382,6 +382,7 @@ static void Nav_repush_callback(void *data)
void a_Nav_repush(BrowserWindow *bw)
{
dReturn_if_fail (bw != NULL);
+ MSG(">>> a_Nav_repush <<<<\n");
a_Timeout_add(0.0, Nav_repush_callback, (void*)bw);
}
diff --git a/src/plain.cc b/src/plain.cc
index b75dbea5..8826dafe 100644
--- a/src/plain.cc
+++ b/src/plain.cc
@@ -108,9 +108,9 @@ DilloPlain::DilloPlain(BrowserWindow *p_bw, const DilloUrl *p_url)
styleAttrs.initValues ();
styleAttrs.margin.setVal (5);
styleAttrs.font = style::Font::create (layout, &fontAttrs);
- styleAttrs.color = style::Color::createSimple (layout, prefs.text_color);
+ styleAttrs.color = style::Color::create (layout, prefs.text_color);
styleAttrs.backgroundColor =
- style::Color::createSimple (layout, prefs.bg_color);
+ style::Color::create (layout, prefs.bg_color);
widgetStyle = style::Style::create (layout, &styleAttrs);
/* The context menu */
diff --git a/src/styleengine.cc b/src/styleengine.cc
new file mode 100644
index 00000000..fec34eb3
--- /dev/null
+++ b/src/styleengine.cc
@@ -0,0 +1,424 @@
+/*
+ * File: styleengine.cc
+ *
+ * Copyright 2008 Jorge Arellano Cid <jcid@dillo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <stdio.h>
+#include <math.h>
+#include "../dlib/dlib.h"
+#include "styleengine.hh"
+
+using namespace dw::core::style;
+
+StyleEngine::StyleEngine (dw::core::Layout *layout) {
+ StyleAttrs style_attrs;
+ FontAttrs font_attrs;
+
+ stack = new lout::misc::SimpleVector <Node> (1);
+ cssContext = new CssContext ();
+ this->layout = layout;
+
+ stack->increase ();
+ Node *n = stack->getRef (stack->size () - 1);
+
+ /* Create a dummy font, attribute, and tag for the bottom of the stack. */
+ font_attrs.name = "helvetica";
+ font_attrs.size = 12;
+ font_attrs.weight = 400;
+ font_attrs.style = FONT_STYLE_NORMAL;
+
+ style_attrs.initValues ();
+ style_attrs.font = Font::create (layout, &font_attrs);
+ style_attrs.color = Color::create (layout, 0);
+ style_attrs.backgroundColor = Color::create (layout, 0xffffff);
+
+ n->style = Style::create (layout, &style_attrs);
+ n->wordStyle = NULL;
+ n->pseudo = NULL;
+}
+
+StyleEngine::~StyleEngine () {
+ /* \todo clear stack if not empty */
+ delete stack;
+ delete cssContext;
+}
+
+/**
+ * \brief tell the styleEngine that a new html element has started.
+ */
+void StyleEngine::startElement (int element) {
+// fprintf(stderr, "===> START %d\n", element);
+
+ if (stack->getRef (stack->size () - 1)->style == NULL)
+ style0 ();
+
+ stack->increase ();
+ Node *n = stack->getRef (stack->size () - 1);
+ n->style = NULL;
+ n->wordStyle = NULL;
+ n->depth = stack->size () - 1;
+ n->element = element;
+ n->id = NULL;
+ n->klass = NULL;
+ n->pseudo = stack->getRef (stack->size () - 2)->pseudo; // inherit pseudo
+ n->styleAttribute = NULL;
+ n->inheritBackgroundColor = false;
+}
+
+void StyleEngine::setId (const char *id) {
+ Node *n = stack->getRef (stack->size () - 1);
+ assert (n->id == NULL);
+ n->id = dStrdup (id);
+};
+
+void StyleEngine::setClass (const char *klass) {
+ Node *n = stack->getRef (stack->size () - 1);
+ assert (n->klass == NULL);
+ n->klass = dStrdup (klass);
+};
+
+void StyleEngine::setStyle (const char *style) {
+ Node *n = stack->getRef (stack->size () - 1);
+ assert (n->styleAttribute == NULL);
+ n->styleAttribute = dStrdup (style);
+};
+
+/**
+ * \brief set properties that were definded using (mostly deprecated) HTML
+ * attributes (e.g. bgColor).
+ */
+void StyleEngine::setNonCssHints (CssPropertyList *nonCssHints) {
+ if (stack->getRef (stack->size () - 1)->style)
+ stack->getRef (stack->size () - 1)->style->unref ();
+ style0 (nonCssHints); // evaluate now, so caller can free nonCssHints
+}
+
+/**
+ * \brief Use of the background color of the parent style as default.
+ * This is only used in table code to allow for colors specified for
+ * table rows as table rows are currently no widgets and therefore
+ * don't draw any background.
+ */
+void StyleEngine::inheritBackgroundColor () {
+ stack->getRef (stack->size () - 1)->inheritBackgroundColor = true;
+}
+
+/**
+ * \brief set the CSS pseudo class :link.
+ */
+void StyleEngine::setPseudoLink () {
+ Node *n = stack->getRef (stack->size () - 1);
+ n->pseudo = "link";
+}
+
+/**
+ * \brief set the CSS pseudo class :visited.
+ */
+void StyleEngine::setPseudoVisited () {
+ Node *n = stack->getRef (stack->size () - 1);
+ n->pseudo = "visited";
+}
+
+/**
+ * \brief tell the styleEngine that a html element has ended.
+ */
+void StyleEngine::endElement (int element) {
+// fprintf(stderr, "===> END %d\n", element);
+ assert (stack->size () > 1);
+ assert (element == stack->getRef (stack->size () - 1)->element);
+
+ Node *n = stack->getRef (stack->size () - 1);
+
+ if (n->style)
+ n->style->unref ();
+ if (n->wordStyle)
+ n->wordStyle->unref ();
+ if (n->id)
+ dFree ((void*) n->id);
+ if (n->klass)
+ dFree ((void*) n->klass);
+ if (n->styleAttribute)
+ dFree ((void*) n->styleAttribute);
+
+ stack->setSize (stack->size () - 1);
+}
+
+/**
+ * \brief Make changes to StyleAttrs attrs according to CssPropertyList props.
+ */
+void StyleEngine::apply (StyleAttrs *attrs, CssPropertyList *props) {
+ FontAttrs fontAttrs = *attrs->font;
+ Font *parentFont;
+
+ /* Determine font first so it can be used to resolve relative lenths.
+ * \todo Things should be rearranged so that just one pass is necessary.
+ */
+ for (int i = 0; i < props->size (); i++) {
+ CssProperty *p = props->getRef (i);
+
+ switch (p->name) {
+ case CssProperty::CSS_PROPERTY_FONT_FAMILY:
+ fontAttrs.name = p->value.strVal;
+ break;
+ case CssProperty::CSS_PROPERTY_FONT_SIZE:
+ parentFont = stack->get (stack->size () - 2).style->font;
+ computeValue (&fontAttrs.size, p->value.intVal, parentFont,
+ parentFont->size);
+ break;
+ case CssProperty::CSS_PROPERTY_FONT_STYLE:
+ fontAttrs.style = (FontStyle) p->value.intVal;
+ break;
+ case CssProperty::CSS_PROPERTY_FONT_WEIGHT:
+ switch (p->value.intVal) {
+ case CssProperty::CSS_FONT_WEIGHT_LIGHTER:
+ fontAttrs.weight -= CssProperty::CSS_FONT_WEIGHT_STEP;
+ break;
+ case CssProperty::CSS_FONT_WEIGHT_BOLDER:
+ fontAttrs.weight += CssProperty::CSS_FONT_WEIGHT_STEP;
+ break;
+ default:
+ fontAttrs.weight = p->value.intVal;
+ break;
+ }
+ if (fontAttrs.weight < CssProperty::CSS_FONT_WEIGHT_MIN)
+ fontAttrs.weight = CssProperty::CSS_FONT_WEIGHT_MIN;
+ if (fontAttrs.weight > CssProperty::CSS_FONT_WEIGHT_MAX)
+ fontAttrs.weight = CssProperty::CSS_FONT_WEIGHT_MAX;
+ break;
+ default:
+ break;
+ }
+ }
+
+ attrs->font = Font::create (layout, &fontAttrs);
+
+ for (int i = 0; i < props->size (); i++) {
+ CssProperty *p = props->getRef (i);
+
+ switch (p->name) {
+ /* \todo missing cases */
+ case CssProperty::CSS_PROPERTY_BACKGROUND_COLOR:
+ attrs->backgroundColor =
+ Color::create (layout, p->value.intVal);
+ break;
+ case CssProperty::CSS_PROPERTY_BORDER_TOP_COLOR:
+ attrs->borderColor.top =
+ Color::create (layout, p->value.intVal);
+ break;
+ case CssProperty::CSS_PROPERTY_BORDER_BOTTOM_COLOR:
+ attrs->borderColor.bottom =
+ Color::create (layout, p->value.intVal);
+ break;
+ case CssProperty::CSS_PROPERTY_BORDER_LEFT_COLOR:
+ attrs->borderColor.left =
+ Color::create (layout, p->value.intVal);
+ break;
+ case CssProperty::CSS_PROPERTY_BORDER_RIGHT_COLOR:
+ attrs->borderColor.right =
+ Color::create (layout, p->value.intVal);
+ break;
+ case CssProperty::CSS_PROPERTY_BORDER_BOTTOM_STYLE:
+ attrs->borderStyle.bottom = (BorderStyle) p->value.intVal;
+ break;
+ case CssProperty::CSS_PROPERTY_BORDER_LEFT_STYLE:
+ attrs->borderStyle.left = (BorderStyle) p->value.intVal;
+ break;
+ case CssProperty::CSS_PROPERTY_BORDER_RIGHT_STYLE:
+ attrs->borderStyle.right = (BorderStyle) p->value.intVal;
+ break;
+ case CssProperty::CSS_PROPERTY_BORDER_TOP_STYLE:
+ attrs->borderStyle.top = (BorderStyle) p->value.intVal;
+ break;
+ case CssProperty::CSS_PROPERTY_BORDER_BOTTOM_WIDTH:
+ computeValue (&attrs->borderWidth.bottom, p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_BORDER_LEFT_WIDTH:
+ computeValue (&attrs->borderWidth.left, p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_BORDER_RIGHT_WIDTH:
+ computeValue (&attrs->borderWidth.right, p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_BORDER_TOP_WIDTH:
+ computeValue (&attrs->borderWidth.top, p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_BORDER_SPACING:
+ computeValue (&attrs->hBorderSpacing, p->value.intVal, attrs->font);
+ computeValue (&attrs->vBorderSpacing, p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_COLOR:
+ attrs->color = Color::create (layout, p->value.intVal);
+ break;
+ case CssProperty::CSS_PROPERTY_CURSOR:
+ attrs->cursor = (Cursor) p->value.intVal;
+ break;
+ case CssProperty::CSS_PROPERTY_LIST_STYLE_TYPE:
+ attrs->listStyleType = (ListStyleType) p->value.intVal;
+ break;
+ case CssProperty::CSS_PROPERTY_MARGIN_BOTTOM:
+ computeValue (&attrs->margin.bottom, p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_MARGIN_LEFT:
+ computeValue (&attrs->margin.left, p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_MARGIN_RIGHT:
+ computeValue (&attrs->margin.right, p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_MARGIN_TOP:
+ computeValue (&attrs->margin.top, p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_PADDING_TOP:
+ computeValue (&attrs->padding.top, p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_PADDING_BOTTOM:
+ computeValue (&attrs->padding.bottom, p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_PADDING_LEFT:
+ computeValue (&attrs->padding.left, p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_PADDING_RIGHT:
+ computeValue (&attrs->padding.right, p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_TEXT_ALIGN:
+ attrs->textAlign = (TextAlignType) p->value.intVal;
+ break;
+ case CssProperty::CSS_PROPERTY_TEXT_DECORATION:
+ attrs->textDecoration |= p->value.intVal;
+ break;
+ case CssProperty::CSS_PROPERTY_VERTICAL_ALIGN:
+ attrs->valign = (VAlignType) p->value.intVal;
+ break;
+ case CssProperty::CSS_PROPERTY_WHITE_SPACE:
+ attrs->whiteSpace = (WhiteSpace) p->value.intVal;
+ break;
+ case CssProperty::CSS_PROPERTY_WIDTH:
+ computeLength (&attrs->width, p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_HEIGHT:
+ computeLength (&attrs->height, p->value.intVal, attrs->font);
+ break;
+ case CssProperty::PROPERTY_X_LINK:
+ attrs->x_link = p->value.intVal;
+ break;
+ case CssProperty::PROPERTY_X_IMG:
+ attrs->x_img = p->value.intVal;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /* make sure border colors are set */
+ if (attrs->borderColor.top == NULL)
+ attrs->borderColor.top = attrs->color;
+ if (attrs->borderColor.bottom == NULL)
+ attrs->borderColor.bottom = attrs->color;
+ if (attrs->borderColor.left == NULL)
+ attrs->borderColor.left = attrs->color;
+ if (attrs->borderColor.right == NULL)
+ attrs->borderColor.right = attrs->color;
+
+}
+
+/**
+ * \brief Resolve relative lengths to absolute values.
+ */
+bool StyleEngine::computeValue (int *dest, CssLength value, Font *font) {
+ static float dpmm;
+
+ if (dpmm == 0.0)
+ dpmm = layout->dpiX () / 25.4; /* assume dpiX == dpiY */
+
+ switch (CSS_LENGTH_TYPE (value)) {
+ case CSS_LENGTH_TYPE_PX:
+ *dest = (int) CSS_LENGTH_VALUE (value);
+ return true;
+ case CSS_LENGTH_TYPE_MM:
+ *dest = (int) (CSS_LENGTH_VALUE (value) * dpmm);
+ return true;
+ case CSS_LENGTH_TYPE_EM:
+ *dest = (int) (CSS_LENGTH_VALUE (value) * font->size);
+ return true;
+ case CSS_LENGTH_TYPE_EX:
+ *dest = (int) (CSS_LENGTH_VALUE(value) * font->xHeight);
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+}
+
+bool StyleEngine::computeValue (int *dest, CssLength value, Font *font,
+ int percentageBase) {
+ if (CSS_LENGTH_TYPE (value) == CSS_LENGTH_TYPE_PERCENTAGE) {
+ *dest = (int) (CSS_LENGTH_VALUE (value) * percentageBase);
+ return true;
+ } else
+ return computeValue (dest, value, font);
+}
+
+bool StyleEngine::computeLength (dw::core::style::Length *dest,
+ CssLength value, Font *font) {
+ int v;
+
+ if (CSS_LENGTH_TYPE (value) == CSS_LENGTH_TYPE_PERCENTAGE) {
+ *dest = createPerLength (CSS_LENGTH_VALUE (value));
+ return true;
+ } else if (computeValue (&v, value, font)) {
+ *dest = createAbsLength (v);
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * \brief Create a new style object based on the previously opened / closed
+ * HTML elements and the nonCssProperties that have been set.
+ * This method is private. Call style() to get a current style object.
+ */
+Style * StyleEngine::style0 (CssPropertyList *nonCssProperties) {
+ CssPropertyList props;
+ CssPropertyList *tagStyleProps = NULL; /** \todo implementation */
+
+ // get previous style from the stack
+ StyleAttrs attrs = *stack->getRef (stack->size () - 2)->style;
+ // reset values that are not inherited according to CSS
+ attrs.resetValues ();
+
+ if (stack->getRef (stack->size () - 2)->inheritBackgroundColor)
+ attrs.backgroundColor =
+ stack->getRef (stack->size () - 2)->style->backgroundColor;
+
+ cssContext->apply (&props, this, tagStyleProps, nonCssProperties);
+
+ apply (&attrs, &props);
+
+ stack->getRef (stack->size () - 1)->style = Style::create (layout, &attrs);
+
+ return stack->getRef (stack->size () - 1)->style;
+}
+
+Style * StyleEngine::wordStyle0 (CssPropertyList *nonCssProperties) {
+ StyleAttrs attrs = *style ();
+ attrs.resetValues ();
+
+ if (stack->getRef (stack->size () - 1)->inheritBackgroundColor)
+ attrs.backgroundColor = style ()->backgroundColor;
+
+ stack->getRef (stack->size () - 1)->wordStyle = Style::create (layout, &attrs);
+ return stack->getRef (stack->size () - 1)->wordStyle;
+}
+
+void StyleEngine::parse (const char *buf, int buflen,
+ int order_count, CssOrigin origin) {
+
+ a_Css_parse (cssContext, buf, buflen, order_count, origin);
+}
diff --git a/src/styleengine.hh b/src/styleengine.hh
new file mode 100644
index 00000000..d063fb27
--- /dev/null
+++ b/src/styleengine.hh
@@ -0,0 +1,75 @@
+#ifndef __STYLEENGINE_HH__
+#define __STYLEENGINE_HH__
+
+#include "dw/core.hh"
+#include "doctree.hh"
+#include "css.hh"
+#include "cssparser.hh"
+
+class StyleEngine : public Doctree {
+ private:
+ class Node : public DoctreeNode {
+ public:
+ dw::core::style::Style *style;
+ dw::core::style::Style *wordStyle;
+ const char *styleAttribute;
+ bool inheritBackgroundColor;
+ };
+
+ dw::core::Layout *layout;
+ lout::misc::SimpleVector <Node> *stack;
+ CssContext *cssContext;
+
+ dw::core::style::Style *style0 (CssPropertyList *nonCssHints = NULL);
+ dw::core::style::Style *wordStyle0 (CssPropertyList *nonCssHints = NULL);
+ void apply (dw::core::style::StyleAttrs *attrs, CssPropertyList *props);
+ bool computeValue (int *dest, CssLength value, dw::core::style::Font *font);
+ bool computeValue (int *dest, CssLength value, dw::core::style::Font *font,
+ int percentageBase);
+ bool computeLength (dw::core::style::Length *dest, CssLength value, dw::core::style::Font *font);
+
+ public:
+ StyleEngine (dw::core::Layout *layout);
+ ~StyleEngine ();
+
+ /* Doctree interface */
+ inline const DoctreeNode *top () {
+ return stack->getRef (stack->size () - 1);
+ };
+
+ inline const DoctreeNode *parent (const DoctreeNode *n) {
+ if (n->depth > 1)
+ return stack->getRef (n->depth - 1);
+ else
+ return NULL;
+ };
+
+ void parse (const char *buf, int buflen, int order_count, CssOrigin origin);
+ void startElement (int tag);
+ void setId (const char *id);
+ void setClass (const char *klass);
+ void setStyle (const char *style);
+ void endElement (int tag);
+ void setPseudoLink ();
+ void setPseudoVisited ();
+ void setNonCssHints (CssPropertyList *nonCssHints);
+ void inheritBackgroundColor (); /* \todo get rid of this somehow */
+
+ inline dw::core::style::Style *style () {
+ dw::core::style::Style *s = stack->getRef (stack->size () - 1)->style;
+ if (s)
+ return s;
+ else
+ return style0 ();
+ };
+ inline dw::core::style::Style *wordStyle () {
+ dw::core::style::Style *s = stack->getRef (stack->size () - 1)->wordStyle;
+ if (s)
+ return s;
+ else
+ return wordStyle0 ();
+ };
+
+};
+
+#endif
diff --git a/src/table.cc b/src/table.cc
index a72411d6..e06849a5 100644
--- a/src/table.cc
+++ b/src/table.cc
@@ -18,12 +18,11 @@
#include "prefs.h"
#include "msg.h"
+#include "css.hh"
/* Undefine if you want to unroll tables. For instance for PDAs */
#define USE_TABLES
-#define dillo_dbg_rendering 0
-
using namespace dw;
using namespace dw::core;
using namespace dw::core::style;
@@ -43,13 +42,13 @@ void Html_tag_open_table(DilloHtml *html, const char *tag, int tagsize)
{
#ifdef USE_TABLES
dw::core::Widget *table;
- dw::core::style::StyleAttrs style_attrs;
- dw::core::style::Style *cell_style, *old_style;
+ CssPropertyList props, *table_cell_props;
const char *attrbuf;
- int32_t border = 0, cellspacing = 1, cellpadding = 2, bgcolor;
+ int32_t border = -1, cellspacing = -1, cellpadding = -1, bgcolor = -1;
+ int cssLength;
#endif
- DW2TB(html->dw)->addParbreak (0, S_TOP(html)->style);
+ DW2TB(html->dw)->addParbreak (0, html->styleEngine->wordStyle ());
#ifdef USE_TABLES
if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "border")))
@@ -59,68 +58,70 @@ void Html_tag_open_table(DilloHtml *html, const char *tag, int tagsize)
if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "cellpadding")))
cellpadding = strtol (attrbuf, NULL, 10);
- /* The style for the table */
- style_attrs = *S_TOP(html)->style;
-
- /* When dillo was started with the --debug-rendering option, there
- * is always a border around the table. */
- if (dillo_dbg_rendering)
- style_attrs.borderWidth.setVal (MIN (border, 1));
- else
- style_attrs.borderWidth.setVal (border);
+ if (border != -1) {
+ cssLength = CSS_CREATE_LENGTH (border, CSS_LENGTH_TYPE_PX);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_TOP_WIDTH, cssLength);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_BOTTOM_WIDTH, cssLength);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_LEFT_WIDTH, cssLength);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_RIGHT_WIDTH, cssLength);
+ }
- style_attrs.setBorderColor (
- Color::createShaded(HT2LT(html), S_TOP(html)->current_bg_color));
- style_attrs.setBorderStyle (BORDER_OUTSET);
- style_attrs.hBorderSpacing = cellspacing;
- style_attrs.vBorderSpacing = cellspacing;
+ if (cellspacing != -1) {
+ cssLength = CSS_CREATE_LENGTH (cellspacing, CSS_LENGTH_TYPE_PX);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_SPACING, cssLength);
+ }
if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "width")))
- style_attrs.width = a_Html_parse_length (html, attrbuf);
+ props.set (CssProperty::CSS_PROPERTY_WIDTH,
+ a_Html_parse_length (html, attrbuf));
if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "align"))) {
if (dStrcasecmp (attrbuf, "left") == 0)
- style_attrs.textAlign = dw::core::style::TEXT_ALIGN_LEFT;
+ props.set (CssProperty::CSS_PROPERTY_TEXT_ALIGN, TEXT_ALIGN_LEFT);
else if (dStrcasecmp (attrbuf, "right") == 0)
- style_attrs.textAlign = dw::core::style::TEXT_ALIGN_RIGHT;
+ props.set (CssProperty::CSS_PROPERTY_TEXT_ALIGN, TEXT_ALIGN_RIGHT);
else if (dStrcasecmp (attrbuf, "center") == 0)
- style_attrs.textAlign = dw::core::style::TEXT_ALIGN_CENTER;
+ props.set (CssProperty::CSS_PROPERTY_TEXT_ALIGN, TEXT_ALIGN_CENTER);
}
- if (!prefs.force_my_colors &&
- (attrbuf = a_Html_get_attr(html, tag, tagsize, "bgcolor"))) {
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "bgcolor"))) {
bgcolor = a_Html_color_parse(html, attrbuf, -1);
if (bgcolor != -1) {
if (bgcolor == 0xffffff && !prefs.allow_white_bg)
bgcolor = prefs.bg_color;
S_TOP(html)->current_bg_color = bgcolor;
- style_attrs.backgroundColor =
- Color::createShaded (HT2LT(html), bgcolor);
+ props.set (CssProperty::CSS_PROPERTY_BACKGROUND_COLOR, bgcolor);
}
}
+ html->styleEngine->setNonCssHints (&props);
+
/* The style for the cells */
- cell_style = Style::create (HT2LT(html), &style_attrs);
- style_attrs = *S_TOP(html)->style;
- /* When dillo was started with the --debug-rendering option, there
- * is always a border around the cells. */
- if (dillo_dbg_rendering)
- style_attrs.borderWidth.setVal (1);
- else
- style_attrs.borderWidth.setVal (border ? 1 : 0);
- style_attrs.padding.setVal(cellpadding);
- style_attrs.setBorderColor (cell_style->borderColor.top);
- style_attrs.setBorderStyle (BORDER_INSET);
+ table_cell_props = new CssPropertyList ();
+ if (border > 0) {
+ cssLength = CSS_CREATE_LENGTH (1, CSS_LENGTH_TYPE_PX);
+ table_cell_props->set (CssProperty::CSS_PROPERTY_BORDER_TOP_WIDTH, cssLength);
+ table_cell_props->set (CssProperty::CSS_PROPERTY_BORDER_BOTTOM_WIDTH, cssLength);
+ table_cell_props->set (CssProperty::CSS_PROPERTY_BORDER_LEFT_WIDTH, cssLength);
+ table_cell_props->set (CssProperty::CSS_PROPERTY_BORDER_RIGHT_WIDTH, cssLength);
+ }
+
+ if (cellpadding != -1) {
+ cssLength = CSS_CREATE_LENGTH (cellpadding, CSS_LENGTH_TYPE_PX);
+ table_cell_props->set (CssProperty::CSS_PROPERTY_PADDING_TOP, cssLength);
+ table_cell_props->set (CssProperty::CSS_PROPERTY_PADDING_BOTTOM, cssLength);
+ table_cell_props->set (CssProperty::CSS_PROPERTY_PADDING_LEFT, cssLength);
+ table_cell_props->set (CssProperty::CSS_PROPERTY_PADDING_RIGHT, cssLength);
+ }
+
+ if (S_TOP(html)->table_cell_props)
+ S_TOP(html)->table_cell_props->unref ();
- old_style = S_TOP(html)->table_cell_style;
- S_TOP(html)->table_cell_style =
- Style::create (HT2LT(html), &style_attrs);
- if (old_style)
- old_style->unref ();
+ S_TOP(html)->table_cell_props = table_cell_props;
+ S_TOP(html)->table_cell_props->ref ();
table = new dw::Table(prefs.limit_text_width);
- DW2TB(html->dw)->addWidget (table, cell_style);
- cell_style->unref ();
+ DW2TB(html->dw)->addWidget (table, html->styleEngine->style ());
S_TOP(html)->table_mode = DILLO_HTML_TABLE_MODE_TOP;
S_TOP(html)->cell_text_align_set = FALSE;
@@ -134,10 +135,9 @@ void Html_tag_open_table(DilloHtml *html, const char *tag, int tagsize)
void Html_tag_open_tr(DilloHtml *html, const char *tag, int tagsize)
{
const char *attrbuf;
- dw::core::style::StyleAttrs style_attrs;
- dw::core::style::Style *style, *old_style;
int32_t bgcolor = -1;
bool new_style = false;
+ CssPropertyList props, *table_cell_props;
#ifdef USE_TABLES
switch (S_TOP(html)->table_mode) {
@@ -148,44 +148,41 @@ void Html_tag_open_tr(DilloHtml *html, const char *tag, int tagsize)
case DILLO_HTML_TABLE_MODE_TOP:
case DILLO_HTML_TABLE_MODE_TR:
case DILLO_HTML_TABLE_MODE_TD:
- style = NULL;
- if (!prefs.force_my_colors &&
- (attrbuf = a_Html_get_attr(html, tag, tagsize, "bgcolor"))) {
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "bgcolor"))) {
bgcolor = a_Html_color_parse(html, attrbuf, -1);
if (bgcolor != -1) {
if (bgcolor == 0xffffff && !prefs.allow_white_bg)
bgcolor = prefs.bg_color;
-
- style_attrs = *S_TOP(html)->style;
- style_attrs.backgroundColor =
- Color::createShaded (HT2LT(html), bgcolor);
- style = Style::create (HT2LT(html), &style_attrs);
+ props.set (CssProperty::CSS_PROPERTY_BACKGROUND_COLOR, bgcolor);
S_TOP(html)->current_bg_color = bgcolor;
}
}
- ((dw::Table*)S_TOP(html)->table)->addRow (style);
- if (style)
- style->unref ();
+ html->styleEngine->inheritBackgroundColor ();
+ html->styleEngine->setNonCssHints (&props);
+
+ ((dw::Table*)S_TOP(html)->table)->addRow (html->styleEngine->style ());
if (a_Html_get_attr (html, tag, tagsize, "align")) {
S_TOP(html)->cell_text_align_set = TRUE;
- a_Html_tag_set_align_attr (html, tag, tagsize);
+ a_Html_tag_set_align_attr (html, &props, tag, tagsize);
+ html->styleEngine->setNonCssHints (&props);
}
- style_attrs = *S_TOP(html)->table_cell_style;
+ table_cell_props = new CssPropertyList (*S_TOP(html)->table_cell_props);
if (bgcolor != -1) {
- style_attrs.backgroundColor =Color::createShaded(HT2LT(html),bgcolor);
+ table_cell_props->set (CssProperty::CSS_PROPERTY_BACKGROUND_COLOR, bgcolor);
new_style = true;
}
- if (a_Html_tag_set_valign_attr (html, tag, tagsize, &style_attrs))
+ if (a_Html_tag_set_valign_attr (html, tag, tagsize, table_cell_props))
new_style = true;
if (new_style) {
- old_style = S_TOP(html)->table_cell_style;
- S_TOP(html)->table_cell_style =
- Style::create (HT2LT(html), &style_attrs);
- old_style->unref ();
+ S_TOP(html)->table_cell_props->unref ();
+ S_TOP(html)->table_cell_props = table_cell_props;
+ S_TOP(html)->table_cell_props->ref ();
+ } else {
+ delete table_cell_props;
}
break;
default:
@@ -194,7 +191,7 @@ void Html_tag_open_tr(DilloHtml *html, const char *tag, int tagsize)
S_TOP(html)->table_mode = DILLO_HTML_TABLE_MODE_TR;
#else
- DW2TB(html->dw)->addParbreak (0, S_TOP(html)->style);
+ DW2TB(html->dw)->addParbreak (0, html->styleEngine->wordStyle ());
#endif
}
@@ -232,10 +229,15 @@ static void Html_tag_open_table_cell(DilloHtml *html,
Widget *col_tb;
int colspan = 1, rowspan = 1;
const char *attrbuf;
- dw::core::style::StyleAttrs style_attrs;
- dw::core::style::Style *style, *old_style;
int32_t bgcolor;
bool_t new_style;
+ CssPropertyList *props;
+
+ // \todo any shorter way to do this?
+ if (S_TOP(html)->table_cell_props != NULL)
+ props = new CssPropertyList (*S_TOP(html)->table_cell_props);
+ else
+ props = new CssPropertyList ();
switch (S_TOP(html)->table_mode) {
case DILLO_HTML_TABLE_MODE_NONE:
@@ -259,47 +261,39 @@ static void Html_tag_open_table_cell(DilloHtml *html,
rowspan = MAX(1, strtol (attrbuf, NULL, 10));
/* text style */
- old_style = S_TOP(html)->style;
- style_attrs = *old_style;
- if (!S_TOP(html)->cell_text_align_set)
- style_attrs.textAlign = text_align;
+ if (!S_TOP(html)->cell_text_align_set) {
+ props->set (CssProperty::CSS_PROPERTY_TEXT_ALIGN, text_align);
+ }
if (a_Html_get_attr(html, tag, tagsize, "nowrap"))
- style_attrs.whiteSpace = WHITE_SPACE_NOWRAP;
+ props->set (CssProperty::CSS_PROPERTY_WHITE_SPACE, WHITE_SPACE_NOWRAP);
else
- style_attrs.whiteSpace = WHITE_SPACE_NORMAL;
+ props->set (CssProperty::CSS_PROPERTY_WHITE_SPACE, WHITE_SPACE_NORMAL);
- S_TOP(html)->style =
- Style::create (HT2LT(html), &style_attrs);
- old_style->unref ();
- a_Html_tag_set_align_attr (html, tag, tagsize);
-
- /* cell style */
- style_attrs = *S_TOP(html)->table_cell_style;
- new_style = FALSE;
+ a_Html_tag_set_align_attr (html, props, tag, tagsize);
if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "width"))) {
- style_attrs.width = a_Html_parse_length (html, attrbuf);
- new_style = TRUE;
+ props->set (CssProperty::CSS_PROPERTY_WIDTH,
+ a_Html_parse_length (html, attrbuf));
}
- if (a_Html_tag_set_valign_attr (html, tag, tagsize, &style_attrs))
+ if (a_Html_tag_set_valign_attr (html, tag, tagsize, props))
new_style = TRUE;
- if (!prefs.force_my_colors &&
- (attrbuf = a_Html_get_attr(html, tag, tagsize, "bgcolor"))) {
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "bgcolor"))) {
bgcolor = a_Html_color_parse(html, attrbuf, -1);
if (bgcolor != -1) {
if (bgcolor == 0xffffff && !prefs.allow_white_bg)
bgcolor = prefs.bg_color;
- new_style = TRUE;
- style_attrs.backgroundColor =
- Color::createShaded (HT2LT(html), bgcolor);
+ props->set (CssProperty::CSS_PROPERTY_BACKGROUND_COLOR, bgcolor);
S_TOP(html)->current_bg_color = bgcolor;
}
}
- if (S_TOP(html)->style->textAlign
+ html->styleEngine->setNonCssHints (props);
+ delete props;
+
+ if (html->styleEngine->style ()->textAlign
== TEXT_ALIGN_STRING)
col_tb = new dw::TableCell (
((dw::Table*)S_TOP(html)->table)->getCellRef (),
@@ -307,18 +301,14 @@ static void Html_tag_open_table_cell(DilloHtml *html,
else
col_tb = new Textblock (prefs.limit_text_width);
- if (new_style) {
- style = dw::core::style::Style::create (HT2LT(html), &style_attrs);
- col_tb->setStyle (style);
- style->unref ();
- } else
- col_tb->setStyle (S_TOP(html)->table_cell_style);
+ col_tb->setStyle (html->styleEngine->style ());
((dw::Table*)S_TOP(html)->table)->addCell (col_tb, colspan, rowspan);
S_TOP(html)->textblock = html->dw = col_tb;
/* Handle it when the user clicks on a link */
html->connectSignals(col_tb);
+
break;
default:
diff --git a/src/web.cc b/src/web.cc
index b9141913..ba5d90a1 100644
--- a/src/web.cc
+++ b/src/web.cc
@@ -80,9 +80,9 @@ int a_Web_dispatch_by_type (const char *Type, DilloWeb *Web,
styleAttrs.initValues ();
styleAttrs.margin.setVal (5);
styleAttrs.font = style::Font::create (layout, &fontAttrs);
- styleAttrs.color = style::Color::createSimple (layout, 0xff0000);
+ styleAttrs.color = style::Color::create (layout, 0xff0000);
styleAttrs.backgroundColor =
- style::Color::createSimple (layout, prefs.bg_color);
+ style::Color::create (layout, prefs.bg_color);
widgetStyle = style::Style::create (layout, &styleAttrs);
dw->setStyle (widgetStyle);
widgetStyle->unref ();