aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dw/fltkplatform.cc11
-rw-r--r--dw/fltkplatform.hh2
-rw-r--r--dw/layout.hh10
-rw-r--r--dw/platform.hh10
-rw-r--r--dw/style.cc2
-rw-r--r--lout/misc.hh8
-rw-r--r--src/Makefile.am7
-rw-r--r--src/css.cc228
-rw-r--r--src/css.hh269
-rw-r--r--src/cssparser.cc1116
-rw-r--r--src/cssparser.hh73
-rw-r--r--src/doctree.hh20
-rw-r--r--src/form.cc18
-rw-r--r--src/html.cc441
-rw-r--r--src/html_common.hh16
-rw-r--r--src/styleengine.cc348
-rw-r--r--src/styleengine.hh57
-rw-r--r--src/table.cc206
18 files changed, 2498 insertions, 344 deletions
diff --git a/dw/fltkplatform.cc b/dw/fltkplatform.cc
index 337f4dba..1d83dbb8 100644
--- a/dw/fltkplatform.cc
+++ b/dw/fltkplatform.cc
@@ -25,6 +25,7 @@
#include <fltk/draw.h>
#include <fltk/run.h>
#include <fltk/events.h>
+#include <fltk/Monitor.h>
#include <fltk/utf.h>
#include <stdio.h>
@@ -301,6 +302,16 @@ int FltkPlatform::prevGlyph (const char *text, int idx)
return utf8back (&text[idx - 1], text, &text[strlen (text)]) - text;
}
+float FltkPlatform::dpiX ()
+{
+ return ::fltk::Monitor::all ().dpi_x ();
+}
+
+float FltkPlatform::dpiY ()
+{
+ return ::fltk::Monitor::all ().dpi_y ();
+}
+
void FltkPlatform::generalStaticIdle (void *data)
{
((FltkPlatform*)data)->generalIdle();
diff --git a/dw/fltkplatform.hh b/dw/fltkplatform.hh
index 7b3d3e73..e7493fba 100644
--- a/dw/fltkplatform.hh
+++ b/dw/fltkplatform.hh
@@ -125,6 +125,8 @@ public:
int textWidth (core::style::Font *font, const char *text, int len);
int nextGlyph (const char *text, int idx);
int prevGlyph (const char *text, int idx);
+ float dpiX ();
+ float dpiY ();
int addIdle (void (core::Layout::*func) ());
void removeIdle (int idleId);
diff --git a/dw/layout.hh b/dw/layout.hh
index 13b8f312..292024a2 100644
--- a/dw/layout.hh
+++ b/dw/layout.hh
@@ -216,6 +216,16 @@ public:
return platform->prevGlyph (text, idx);
}
+ inline float dpiX ()
+ {
+ return platform->dpiX ();
+ }
+
+ inline float dpiY ()
+ {
+ return platform->dpiY ();
+ }
+
inline style::Font *createFont (style::FontAttrs *attrs, bool tryEverything)
{
return platform->createFont (attrs, tryEverything);
diff --git a/dw/platform.hh b/dw/platform.hh
index 0ae5d508..4dcb2681 100644
--- a/dw/platform.hh
+++ b/dw/platform.hh
@@ -66,6 +66,16 @@ public:
* \brief Return the index of the previous glyph in string text.
*/
virtual int prevGlyph (const char *text, int idx) = 0;
+
+ /**
+ * \brief Return screen resolution in x-direction.
+ */
+ virtual float dpiX () = 0;
+
+ /**
+ * \brief Return screen resolution in y-direction.
+ */
+ virtual float dpiY () = 0;
/*
* ---------------------------------------------------------
diff --git a/dw/style.cc b/dw/style.cc
index bdb04f25..d989c21c 100644
--- a/dw/style.cc
+++ b/dw/style.cc
@@ -64,7 +64,6 @@ void StyleAttrs::initValues ()
*/
void StyleAttrs::resetValues ()
{
- x_link = -1;
x_img = -1;
x_tooltip = NULL;
@@ -85,7 +84,6 @@ void StyleAttrs::resetValues ()
display = DISPLAY_INLINE;
whiteSpace = WHITE_SPACE_NORMAL;
- cursor = CURSOR_DEFAULT; /** \todo Check CSS specification again. */
}
/**
diff --git a/lout/misc.hh b/lout/misc.hh
index a3f5b3d3..730a47a4 100644
--- a/lout/misc.hh
+++ b/lout/misc.hh
@@ -112,6 +112,14 @@ public:
this->array = NULL;
}
+ inline SimpleVector (const SimpleVector &o) {
+ this->array = NULL;
+ this->num = o.num;
+ this->numAlloc = o.numAlloc;
+ resize ();
+ memcpy (this->array, o.array, sizeof (T) * num);
+ }
+
inline ~SimpleVector ()
{
if (this->array)
diff --git a/src/Makefile.am b/src/Makefile.am
index d4d03eea..7629aaef 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -65,6 +65,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/css.cc b/src/css.cc
new file mode 100644
index 00000000..8ecad167
--- /dev/null
+++ b/src/css.cc
@@ -0,0 +1,228 @@
+/*
+ * 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;
+ this->element = element;
+ this->klass = klass;
+ this->pseudo = pseudo;
+ this->id = id;
+};
+
+/** \todo implement all selection option CSS offers */
+bool CssSelector::match (Doctree *docTree) {
+ const DoctreeNode *n = docTree-> top ();
+
+ if (element >= 0 && 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 CssSelector::print () {
+ fprintf (stderr, "Element %d, class %s, pseudo %s, id %s\n",
+ element, klass, pseudo, id);
+}
+
+CssRule::CssRule (CssSelector *selector, CssPropertyList *props) {
+ this->selector = selector;
+ this->selector->ref ();
+ this->props = props;
+ this->props->ref ();
+};
+
+CssRule::~CssRule () {
+ this->selector->unref ();
+ this->props->unref ();
+};
+
+void CssRule::apply (CssPropertyList *props, Doctree *docTree) {
+ if (selector->match (docTree))
+ this->props->apply (props);
+}
+
+void CssRule::print () {
+ selector->print ();
+ props->print ();
+}
+
+void CssStyleSheet::addRule (CssRule *rule) {
+ increase ();
+ set (size () - 1, rule);
+}
+
+void CssStyleSheet::addRule (CssSelector *selector, CssPropertyList *props) {
+ CssRule *rule = new CssRule (selector, props);
+ addRule (rule);
+}
+
+void CssStyleSheet::apply (CssPropertyList *props, Doctree *docTree) {
+ for (int i = 0; i < size (); i++)
+ get (i)->apply (props, docTree);
+}
+
+CssStyleSheet::~CssStyleSheet () {
+ for (int i = 0; i < size (); i++)
+ delete get (i);
+}
+
+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 }"
+ ":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 {font-style: italic; } "
+ "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;} "
+ "small, sub, sup { font-size: 0.83em } "
+ "sub { vertical-align: sub } "
+ "sup { vertical-align: super } "
+ "s, strike, del { text-decoration: line-through }"
+ "table {border-top-style: outset; border-spacing: 1px} "
+ "td {border-top-style: inset; padding: 2px;} "
+ "thead, tbody, tfoot { vertical-align: middle }"
+ "tt, pre {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..552fd457
--- /dev/null
+++ b/src/css.hh
@@ -0,0 +1,269 @@
+#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_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_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_TEXT_INDENT,
+ 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; }
+};
+
+/**
+ * \brief CSS selector class.
+ * \todo Implement missing selector options.
+ */
+class CssSelector {
+ private:
+ int refCount;
+
+ public:
+ int element;
+ const char *klass, *pseudo, *id;
+
+ CssSelector (int element = -1, const char *klass = NULL,
+ const char *pseudo = NULL, const char *id = NULL);
+ 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:
+ CssSelector *selector;
+ CssPropertyList *props;
+
+ public:
+ CssRule (CssSelector *selector, CssPropertyList *props);
+ ~CssRule ();
+
+ void apply (CssPropertyList *props, Doctree *docTree);
+ void print ();
+};
+
+/**
+ * \brief A list of CssRules.
+ * In apply () all matching rules are applied.
+ */
+class CssStyleSheet : lout::misc::SimpleVector <CssRule*> {
+ public:
+ CssStyleSheet() : lout::misc::SimpleVector <CssRule*> (1) {};
+ ~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..cf6fc341
--- /dev/null
+++ b/src/cssparser.cc
@@ -0,0 +1,1116 @@
+#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-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},
+ {"text-indent", CSS_TYPE_UNUSED, NULL},
+ {"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:
+ * unused
+ * 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
+};
+
+static CssShorthandInfo Css_shorthand_info[CSS_SHORTHAND_NUM] = {
+ {"background", CssShorthandInfo::CSS_SHORTHAND_MULTIPLE,
+ Css_background_properties},
+ {"border", CssShorthandInfo::CSS_SHORTHAND_BORDER, NULL},
+ {"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;
+} 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;
+
+ do
+ c = Css_getc(parser);
+ while (isspace(c));
+
+ 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 (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, 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:
+ /* todo: Not yet implemented. */
+ 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 void Css_parse_ruleset(CssParser * parser)
+{
+ lout::misc::SimpleVector < CssSelector * >*list;
+ CssPropertyList *props, *importantProps;
+ CssSelector *selector;
+ const char *p, **pp;
+
+ list = new lout::misc::SimpleVector < CssSelector * >(1);
+
+ while (true) {
+ selector = NULL;
+
+ if (parser->ttype == CSS_TK_SYMBOL) {
+ int element = a_Html_tag_index(parser->tval);
+ if (element != -1)
+ selector = new CssSelector(element);
+ Css_next_token(parser);
+ } else if (parser->ttype == CSS_TK_CHAR && parser->tval[0] == '*') {
+ selector = new CssSelector();
+ Css_next_token(parser);
+ } else if (parser->ttype == CSS_TK_CHAR &&
+ (parser->tval[0] == '.' || parser->tval[0] == ':' ||
+ parser->tval[0] == '#')) {
+ selector = new CssSelector();
+ /* But no next token. */
+ }
+
+ if (selector) {
+ selector->ref();
+ selector->id = selector->klass = selector->pseudo = NULL;
+
+ 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->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);
+ }
+ }
+ } while (pp);
+ }
+
+ /* Skip all tokens which may "belong" to this selector. */
+ while (!(parser->ttype == CSS_TK_END ||
+ (parser->ttype == CSS_TK_CHAR &&
+ (parser->tval[0] == ',' || parser->tval[0] == '{'))))
+ Css_next_token(parser);
+
+ if (selector)
+ DEBUG_MSG(DEBUG_PARSE_LEVEL, "end of selector (%s, %s, %s, %d)\n",
+ selector->id, selector->klass, selector->pseudo,
+ selector->element);
+ else
+ DEBUG_MSG(DEBUG_PARSE_LEVEL, "not a %s\n", "selector");
+
+ if (selector) {
+ 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;
+
+ Css_next_token(&parser);
+ while (parser.ttype != CSS_TK_END)
+ Css_parse_ruleset(&parser);
+}
+
+#if 0
+void p_Css_parse_element_style(CssContext * context,
+ char *id,
+ char *klass,
+ char *pseudo,
+ char *element,
+ const char *buf,
+ int buflen,
+ int order_count, CssOrigin origin)
+{
+ CssParser parser;
+ CssSelector *selector;
+ GSList *list;
+
+ parser.context = context;
+ parser.buf = buf;
+ parser.buflen = buflen;
+ parser.bufptr = 0;
+ parser.order_count = 0;
+ parser.origin = origin;
+ parser.within_block = true;
+
+ selector = g_new(CssSelector, 1);
+ selector->id = id;
+ selector->klass = klass;
+ selector->pseudo = pseudo;
+ selector->element = element;
+ list = g_slist_append(NULL, selector);
+
+ Css_next_token(&parser);
+ while (parser.ttype != CSS_TK_END)
+ Css_parse_declaration(&parser, list);
+
+ dFree(selector);
+ g_slist_free(list);
+}
+#endif
diff --git a/src/cssparser.hh b/src/cssparser.hh
new file mode 100644
index 00000000..2446e4a9
--- /dev/null
+++ b/src/cssparser.hh
@@ -0,0 +1,73 @@
+#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);
+
+void p_Css_parse_element_style (CssContext *context,
+ char *id,
+ char *klass,
+ char *pseudo,
+ char *element,
+ 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 6f7979be..bf706ebf 100644
--- a/src/form.cc
+++ b/src/form.cc
@@ -277,7 +277,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->style ());
if (html->InFlags & IN_FORM) {
BUG_MSG("nested forms\n");
@@ -540,7 +540,7 @@ void Html_tag_open_input(DilloHtml *html, const char *tag, int tagsize)
bg = Color::createShaded(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);
@@ -573,10 +573,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->style ());
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->style ());
ResourceFactory *factory = HT2LT(html)->getResourceFactory();
EntryResource *entryResource = factory->createEntryResource (20, false);
@@ -589,7 +589,7 @@ void Html_tag_open_isindex(DilloHtml *html, const char *tag, int tagsize)
else
bg = Color::createShaded(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;
@@ -658,7 +658,7 @@ void Html_tag_open_textarea(DilloHtml *html, const char *tag, int tagsize)
bg = Color::createShaded(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);
}
@@ -740,7 +740,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")))
@@ -861,7 +861,7 @@ 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);
@@ -1904,7 +1904,7 @@ 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);
diff --git a/src/html.cc b/src/html.cc
index 88607395..3edd59a4 100644
--- a/src/html.cc
+++ b/src/html.cc
@@ -113,7 +113,6 @@ 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);
/*-----------------------------------------------------------------------------
@@ -266,9 +265,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)
@@ -280,6 +280,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
}
/*
@@ -287,25 +288,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
@@ -319,8 +321,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);
}
}
@@ -329,19 +331,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;
@@ -359,7 +364,7 @@ static void Html_add_indented_widget(DilloHtml *html, Widget *textblock,
StyleAttrs style_attrs;
Style *style;
- style_attrs = *S_TOP(html)->style;
+ style_attrs = *html->styleEngine->style ();
style_attrs.margin.setVal (0);
style_attrs.borderWidth.setVal (0);
@@ -468,8 +473,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;
@@ -482,6 +486,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("");
@@ -511,8 +517,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();
@@ -525,26 +531,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);
@@ -644,7 +636,7 @@ int DilloHtml::getCurTagLineNumber()
*/
void DilloHtml::freeParseData()
{
- (stack->getRef(0)->style)->unref (); /* template style */
+// (stack->getRef(0)->style)->unref (); /* template style */
delete(stack);
dStr_free(Stash, TRUE);
@@ -1100,11 +1092,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->style ());
dFree(spc);
spaceCnt = 0;
}
- DW2TB(html->dw)->addLinebreak (S_TOP(html)->style);
+ DW2TB(html->dw)->addLinebreak (html->styleEngine->style ());
html->pre_column = 0;
}
html->PreFirstChar = false;
@@ -1132,7 +1124,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->style ());
dFree(spc);
}
@@ -1140,7 +1132,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->style ());
html->PrevWasSPC = true;
}
@@ -1193,7 +1185,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->style ());
Pword[i] = ch;
html->pre_column += i - start;
html->PreFirstChar = false;
@@ -1203,7 +1195,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->style ());
} else {
/* Collapse white-space entities inside the word (except &nbsp;) */
Pword = a_Html_parse_entities(html, word, size);
@@ -1211,7 +1203,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->style ());
dFree(Pword);
}
}
@@ -1248,7 +1240,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;
}
@@ -1267,10 +1259,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;
}
@@ -1280,6 +1270,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);
}
@@ -1290,9 +1281,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);
@@ -1699,8 +1690,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))
@@ -1718,43 +1708,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;
}
@@ -1777,13 +1761,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->style ());
}
- a_Html_tag_set_align_attr (html, tag, tagsize);
+ a_Html_tag_set_align_attr (html, &props, tag, tagsize);
+ html->styleEngine->setNonCssHints (&props);
}
/*
@@ -1811,7 +1798,7 @@ 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 =
@@ -1824,14 +1811,14 @@ static void Html_tag_open_frame (DilloHtml *html, const char *tag, int tagsize)
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->style ());
/* 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->style ());
if (tolower(tag[1]) == 'i') {
/* IFRAME usually comes with very long advertising/spying URLS,
@@ -1848,7 +1835,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->style ());
link_style->unref ();
dFree(src);
@@ -1862,8 +1849,8 @@ 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);
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->style ());
+ DW2TB(html->dw)->addText("--FRAME--", html->styleEngine->style ());
Html_add_indented(html, 40, 0, 5);
}
@@ -1872,18 +1859,17 @@ 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);
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->style ());
+
+ a_Html_tag_set_align_attr (html, &props, tag, tagsize);
+ html->styleEngine->setNonCssHints (&props);
/* 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;
@@ -1895,7 +1881,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->style ());
a_Html_pop_tag(html, TagIdx);
}
@@ -1908,7 +1894,7 @@ static void Html_tag_open_big_small(DilloHtml *html,
int level;
level =
- Html_fontsize_to_level(S_TOP(html)->style->font->size) +
+ Html_fontsize_to_level(html->styleEngine->style ()->font->size) +
((dStrncasecmp(tag+1, "big", 3)) ? -1 : 1);
a_Html_set_top_font(html, NULL, Html_level_to_fontsize(level), 0, 0);
}
@@ -1918,7 +1904,7 @@ static void Html_tag_open_big_small(DilloHtml *html,
*/
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->style ());
}
/*
@@ -1926,39 +1912,26 @@ 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
+ 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);
}
/*
@@ -1980,7 +1953,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);
}
/*
@@ -1988,7 +1960,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);
}
/*
@@ -1996,7 +1967,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);
}
/*
@@ -2004,7 +1974,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);
}
/*
@@ -2012,7 +1981,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);
}
/*
@@ -2020,7 +1988,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);
+ DW2TB(html->dw)->addParbreak (0, html->styleEngine->style ());
HTML_SET_TOP_ATTR(html, textAlign, TEXT_ALIGN_CENTER);
}
@@ -2030,7 +1998,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);
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->style ());
a_Html_set_top_font(html, NULL, 0, 2, 2);
}
@@ -2182,15 +2150,15 @@ static void Html_tag_open_img(DilloHtml *html, const char *tag, int tagsize)
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 ||
+ style_attrs = *html->styleEngine->style ();
+ if (html->styleEngine->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) {
+ if (html->styleEngine->style ()->x_link != -1) {
/* In this case we can use the text color */
style_attrs.setBorderColor (
Color::createShaded (HT2LT(html), style_attrs.color->getColor()));
@@ -2208,7 +2176,7 @@ static void Html_tag_open_img(DilloHtml *html, const char *tag, int tagsize)
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. */
@@ -2390,7 +2358,7 @@ 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 (
@@ -2398,9 +2366,10 @@ static void Html_tag_open_object(DilloHtml *html, const char *tag, int tagsize)
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 {
@@ -2448,7 +2417,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
@@ -2465,9 +2434,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 */
@@ -2482,36 +2450,20 @@ 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->setPseudo ("visited");
+ 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->setPseudo ("link");
+ 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);
}
if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "name"))) {
@@ -2540,12 +2492,12 @@ static void Html_tag_open_u(DilloHtml *html, const char *tag, int tagsize)
Style *style;
StyleAttrs style_attrs;
- style = S_TOP(html)->style;
+ style = html->styleEngine->style ();
style_attrs = *style;
style_attrs.textDecoration |= TEXT_DECORATION_UNDERLINE;
- S_TOP(html)->style =
- Style::create (HT2LT(html), &style_attrs);
- style->unref ();
+// html->styleEngine->style () =
+// Style::create (HT2LT(html), &style_attrs);
+// style->unref ();
}
/*
@@ -2556,12 +2508,12 @@ static void Html_tag_open_strike(DilloHtml *html, const char *tag, int tagsize)
Style *style;
StyleAttrs style_attrs;
- style = S_TOP(html)->style;
+ style = html->styleEngine->style ();
style_attrs = *style;
style_attrs.textDecoration |= TEXT_DECORATION_LINE_THROUGH;
- S_TOP(html)->style =
- Style::create (HT2LT(html), &style_attrs);
- style->unref ();
+// html->styleEngine->style () =
+// Style::create (HT2LT(html), &style_attrs);
+// style->unref ();
}
/*
@@ -2570,7 +2522,7 @@ 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);
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->style ());
Html_add_indented(html, 40, 40, 9);
}
@@ -2582,7 +2534,7 @@ 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);
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->style ());
Html_add_indented(html, 40, 0, 9);
if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "type"))) {
@@ -2602,7 +2554,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;
@@ -2633,11 +2585,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->style ());
- 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;
@@ -2660,28 +2609,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->style ());
+ Html_add_indented(html, 40, 0, 9);
+
S_TOP(html)->list_type = HTML_LIST_ORDERED;
if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "start")) &&
@@ -2714,7 +2665,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->style ();
style_attrs = *word_style;
//style_attrs.backgroundColor = Color::createShaded (HT2LT(html), 0xffff40);
//style_attrs.setBorderColor (Color::createSimple (HT2LT(html), 0x000000));
@@ -2740,7 +2691,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;
@@ -2777,7 +2729,7 @@ static void Html_tag_open_hr(DilloHtml *html, const char *tag, int tagsize)
const char *attrbuf;
int32_t size = 0;
- style_attrs = *S_TOP(html)->style;
+ style_attrs = *html->styleEngine->style ();
width_ptr = a_Html_get_attr_wdef(html, tag, tagsize, "width", "100%");
style_attrs.width = a_Html_parse_length (html, width_ptr);
@@ -2817,12 +2769,12 @@ static void Html_tag_open_hr(DilloHtml *html, const char *tag, int tagsize)
style_attrs.borderWidth.right = size / 2;
style = Style::create (HT2LT(html), &style_attrs);
- DW2TB(html->dw)->addParbreak (5, S_TOP(html)->style);
+ DW2TB(html->dw)->addParbreak (5, html->styleEngine->style ());
hruler = new Ruler();
hruler->setStyle (style);
DW2TB(html->dw)->addWidget (hruler, style);
style->unref ();
- DW2TB(html->dw)->addParbreak (5, S_TOP(html)->style);
+ DW2TB(html->dw)->addParbreak (5, html->styleEngine->style ());
}
/*
@@ -2831,7 +2783,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->style ());
}
/*
@@ -2839,7 +2791,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->style ());
a_Html_set_top_font(html, NULL, 0, 1, 1);
}
@@ -2848,7 +2800,7 @@ 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);
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->style ());
Html_add_indented(html, 40, 40, 9);
}
@@ -2857,7 +2809,7 @@ 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);
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->style ());
a_Html_set_top_font(html, prefs.fw_fontname, 0, 0, 0);
/* Is the placement of this statement right? */
@@ -2874,7 +2826,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->style ());
a_Html_pop_tag(html, TagIdx);
}
@@ -2891,7 +2843,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])
@@ -3084,8 +3036,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;
+
+ DW2TB(html->dw)->addParbreak (0, html->styleEngine->style ());
+ a_Html_tag_set_align_attr (html, &props, tag, tagsize);
+ html->styleEngine->setNonCssHints (&props);
}
/*
@@ -3093,7 +3048,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->style ());
a_Html_pop_tag(html, TagIdx);
}
@@ -3110,7 +3065,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->style ());
a_Html_pop_tag(html, TagIdx);
}
@@ -3262,7 +3217,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;
@@ -3293,17 +3248,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) {
@@ -3400,7 +3355,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);
@@ -3412,7 +3367,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);
@@ -3424,11 +3379,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);
Tags[tag_idx].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);
@@ -3449,7 +3404,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)) {
@@ -3483,10 +3438,7 @@ 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 */
- Tags[ni].open (html, tag, tagsize);
- if (html->stop_parser)
- break;
+ html->styleEngine->startElement (ni);
/* Now parse attributes that can appear on any tag */
if (tagsize >= 8 && /* length of "<t id=i>" */
@@ -3498,6 +3450,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)) {
@@ -3513,6 +3468,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;
+
/* let the parser know this was an open tag */
html->PrevWasOpenTag = true;
@@ -3535,6 +3509,7 @@ static void Html_process_tag(DilloHtml *html, char *tag, int tagsize)
(size_t)tagsize == strlen(Tags[ni].name) + 3))) { /* <x/> */
Tags[ni].close (html, ni);
+// html->styleEngine->endElement (ni);
/* This was a close tag */
html->PrevWasOpenTag = false;
html->ReqTagClose = false;
diff --git a/src/html_common.hh b/src/html_common.hh
index c694123e..3468ba89 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;
@@ -174,6 +179,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 */
@@ -233,6 +239,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,
@@ -260,11 +268,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/styleengine.cc b/src/styleengine.cc
new file mode 100644
index 00000000..7b151469
--- /dev/null
+++ b/src/styleengine.cc
@@ -0,0 +1,348 @@
+/*
+ * 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::createSimple (layout, 0);
+ style_attrs.backgroundColor = Color::createSimple (layout, 0xffffff);
+
+ n->style = Style::create (layout, &style_attrs);
+}
+
+StyleEngine::~StyleEngine () {
+ 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->depth = stack->size ();
+ n->element = element;
+ n->id = NULL;
+ n->klass = NULL;
+ n->pseudo = NULL;
+ n->styleAttribute = NULL;
+}
+
+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 set the CSS pseudo class (e.g. "link", "visited").
+ */
+void StyleEngine::setPseudo (const char *pseudo) {
+ Node *n = stack->getRef (stack->size () - 1);
+ assert (n->pseudo == NULL);
+ n->pseudo = dStrdup (pseudo);
+}
+
+/**
+ * \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->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;
+ if (CSS_LENGTH_TYPE (p->value.intVal) == CSS_LENGTH_TYPE_PERCENTAGE)
+ fontAttrs.size = (int) (CSS_LENGTH_VALUE (p->value.intVal) *
+ parentFont->size);
+ else
+ fontAttrs.size = computeValue (p->value.intVal, parentFont);
+ 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::createSimple (layout, p->value.intVal);
+ break;
+ case CssProperty::CSS_PROPERTY_BORDER_TOP_COLOR:
+ attrs->borderColor.top =
+ Color::createSimple (layout, p->value.intVal);
+ break;
+ case CssProperty::CSS_PROPERTY_BORDER_BOTTOM_COLOR:
+ attrs->borderColor.bottom =
+ Color::createSimple (layout, p->value.intVal);
+ break;
+ case CssProperty::CSS_PROPERTY_BORDER_LEFT_COLOR:
+ attrs->borderColor.left =
+ Color::createSimple (layout, p->value.intVal);
+ break;
+ case CssProperty::CSS_PROPERTY_BORDER_RIGHT_COLOR:
+ attrs->borderColor.right =
+ Color::createSimple (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:
+ attrs->borderWidth.bottom = computeValue (p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_BORDER_LEFT_WIDTH:
+ attrs->borderWidth.left = computeValue (p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_BORDER_RIGHT_WIDTH:
+ attrs->borderWidth.right = computeValue (p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_BORDER_TOP_WIDTH:
+ attrs->borderWidth.top = computeValue (p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_BORDER_SPACING:
+ attrs->hBorderSpacing = computeValue (p->value.intVal, attrs->font);
+ attrs->vBorderSpacing = attrs->hBorderSpacing;
+ break;
+ case CssProperty::CSS_PROPERTY_COLOR:
+ attrs->color = Color::createSimple (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:
+ attrs->margin.bottom = computeValue (p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_MARGIN_LEFT:
+ attrs->margin.left = computeValue (p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_MARGIN_RIGHT:
+ attrs->margin.right = computeValue (p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_MARGIN_TOP:
+ attrs->margin.top = computeValue (p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_PADDING_TOP:
+ attrs->padding.top = computeValue (p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_PADDING_BOTTOM:
+ attrs->padding.bottom = computeValue (p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_PADDING_LEFT:
+ attrs->padding.left = computeValue (p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_PADDING_RIGHT:
+ attrs->padding.right = computeValue (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;
+ /* \todo proper conversion from CssLength to dw::core::style::Length */
+ case CssProperty::CSS_PROPERTY_WIDTH:
+ attrs->width = p->value.intVal;
+ break;
+ case CssProperty::CSS_PROPERTY_HEIGHT:
+ attrs->height = p->value.intVal;
+ 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;
+ }
+ }
+}
+
+/**
+ * \brief Resolve relative lengths to absolute values.
+ */
+
+int StyleEngine::computeValue (CssLength value, Font *font) {
+ int ret;
+ 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:
+ ret = (int) CSS_LENGTH_VALUE (value);
+ break;
+ case CSS_LENGTH_TYPE_MM:
+ ret = (int) (CSS_LENGTH_VALUE (value) * dpmm);
+ break;
+ case CSS_LENGTH_TYPE_EM:
+ ret = (int) (CSS_LENGTH_VALUE (value) * font->size);
+ break;
+ case CSS_LENGTH_TYPE_EX:
+ ret = (int) (CSS_LENGTH_VALUE(value) * font->xHeight);
+ break;
+ default:
+ ret = value;
+ break;
+ }
+ return ret;
+}
+
+
+/**
+ * \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 ();
+
+ 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;
+}
diff --git a/src/styleengine.hh b/src/styleengine.hh
new file mode 100644
index 00000000..60b044b8
--- /dev/null
+++ b/src/styleengine.hh
@@ -0,0 +1,57 @@
+#ifndef __STYLEENGINE_HH__
+#define __STYLEENGINE_HH__
+
+#include "dw/core.hh"
+#include "doctree.hh"
+#include "css.hh"
+
+class StyleEngine : public Doctree {
+ private:
+ class Node : public DoctreeNode {
+ public:
+ dw::core::style::Style *style;
+ const char *styleAttribute;
+ };
+
+ dw::core::Layout *layout;
+ lout::misc::SimpleVector <Node> *stack;
+ CssContext *cssContext;
+
+ dw::core::style::Style *style0 (CssPropertyList *nonCssHints = NULL);
+ void apply (dw::core::style::StyleAttrs *attrs, CssPropertyList *props);
+ int computeValue (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 > 0)
+ return stack->getRef (n->depth - 1);
+ else
+ return NULL;
+ };
+
+ void startElement (int tag);
+ void setId (const char *id);
+ void setClass (const char *klass);
+ void setStyle (const char *style);
+ void endElement (int tag);
+ void setPseudo (const char *pseudo);
+ void setNonCssHints (CssPropertyList *nonCssHints);
+
+ inline dw::core::style::Style *style () {
+ dw::core::style::Style *s = stack->getRef (stack->size () - 1)->style;
+ if (s)
+ return s;
+ else
+ return style0 ();
+ };
+};
+
+#endif
diff --git a/src/table.cc b/src/table.cc
index a72411d6..994dcbbd 100644
--- a/src/table.cc
+++ b/src/table.cc
@@ -18,6 +18,7 @@
#include "prefs.h"
#include "msg.h"
+#include "css.hh"
/* Undefine if you want to unroll tables. For instance for PDAs */
#define USE_TABLES
@@ -43,13 +44,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->style ());
#ifdef USE_TABLES
if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "border")))
@@ -59,68 +60,100 @@ 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;
+ 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);
+ }
+
+ if (cellspacing != -1) {
+ cssLength = CSS_CREATE_LENGTH (cellspacing, CSS_LENGTH_TYPE_PX);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_SPACING, cssLength);
+ }
/* 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);
-
- 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 (dillo_dbg_rendering && border < 1) {
+ cssLength = CSS_CREATE_LENGTH (1, 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);
+ }
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"))) {
+ /** \todo figure out how to handle shaded colors with CSS */
+ props.set (CssProperty::CSS_PROPERTY_BORDER_TOP_COLOR, 0x000000);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_BOTTOM_COLOR, 0x000000);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_LEFT_COLOR, 0x000000);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_RIGHT_COLOR, 0x000000);
+
+ 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);
-
- 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 ();
+ table_cell_props = new CssPropertyList ();
+ if (border != -1) {
+ cssLength = CSS_CREATE_LENGTH (border, 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 (dillo_dbg_rendering && border < 1) {
+ 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);
+ }
+
+ /** \todo figure out how to handle shaded colors with CSS */
+ table_cell_props->set (CssProperty::CSS_PROPERTY_BORDER_TOP_COLOR, 0x000000);
+ table_cell_props->set (CssProperty::CSS_PROPERTY_BORDER_BOTTOM_COLOR, 0x000000);
+ table_cell_props->set (CssProperty::CSS_PROPERTY_BORDER_LEFT_COLOR, 0x000000);
+ table_cell_props->set (CssProperty::CSS_PROPERTY_BORDER_RIGHT_COLOR, 0x000000);
+
+ if (S_TOP(html)->table_cell_props)
+ S_TOP(html)->table_cell_props->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 +167,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 +180,40 @@ 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->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 +222,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->style ());
#endif
}
@@ -232,10 +260,9 @@ 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 (*S_TOP(html)->table_cell_props);
switch (S_TOP(html)->table_mode) {
case DILLO_HTML_TABLE_MODE_NONE:
@@ -259,47 +286,38 @@ 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;
-
- S_TOP(html)->style =
- Style::create (HT2LT(html), &style_attrs);
- old_style->unref ();
- a_Html_tag_set_align_attr (html, tag, tagsize);
+ props.set (CssProperty::CSS_PROPERTY_WHITE_SPACE, WHITE_SPACE_NORMAL);
- /* 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);
+
+ if (html->styleEngine->style ()->textAlign
== TEXT_ALIGN_STRING)
col_tb = new dw::TableCell (
((dw::Table*)S_TOP(html)->table)->getCellRef (),
@@ -307,18 +325,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: