aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog3
-rw-r--r--dillorc2
-rw-r--r--dw/fltkimgbuf.cc18
-rw-r--r--dw/fltkplatform.cc43
-rw-r--r--dw/fltkplatform.hh9
-rw-r--r--dw/layout.hh17
-rw-r--r--dw/platform.hh20
-rw-r--r--dw/style.cc58
-rw-r--r--dw/style.hh23
-rw-r--r--dw/textblock.cc18
-rw-r--r--lout/misc.hh8
-rw-r--r--src/Makefile.am9
-rw-r--r--src/bw.c4
-rw-r--r--src/bw.h5
-rw-r--r--src/cache.c162
-rw-r--r--src/cache.h4
-rw-r--r--src/capi.c5
-rw-r--r--src/capi.h3
-rw-r--r--src/colors.c9
-rw-r--r--src/css.cc345
-rw-r--r--src/css.hh313
-rw-r--r--src/cssparser.cc1154
-rw-r--r--src/cssparser.hh63
-rw-r--r--src/dicache.c249
-rw-r--r--src/dicache.h15
-rw-r--r--src/doctree.hh20
-rw-r--r--src/form.cc31
-rw-r--r--src/gif.c21
-rw-r--r--src/html.cc1175
-rw-r--r--src/html_common.hh21
-rw-r--r--src/image.cc101
-rw-r--r--src/image.hh7
-rw-r--r--src/imgbuf.cc117
-rw-r--r--src/imgbuf.hh30
-rw-r--r--src/jpeg.c25
-rw-r--r--src/nav.c4
-rw-r--r--src/plain.cc4
-rw-r--r--src/png.c30
-rw-r--r--src/prefs.c6
-rw-r--r--src/prefs.h1
-rw-r--r--src/styleengine.cc426
-rw-r--r--src/styleengine.hh75
-rw-r--r--src/table.cc189
-rw-r--r--src/web.cc4
-rw-r--r--test/dw_anchors_test.cc4
-rw-r--r--test/dw_border_test.cc10
-rw-r--r--test/dw_example.cc4
-rw-r--r--test/dw_find_test.cc4
-rw-r--r--test/dw_images_scaled.cc4
-rw-r--r--test/dw_images_scaled2.cc6
-rw-r--r--test/dw_images_simple.cc4
-rw-r--r--test/dw_links.cc6
-rw-r--r--test/dw_links2.cc6
-rw-r--r--test/dw_lists.cc8
-rw-r--r--test/dw_resource_test.cc4
-rw-r--r--test/dw_table.cc6
-rw-r--r--test/dw_table_aligned.cc6
-rw-r--r--test/dw_ui_test.cc4
58 files changed, 3606 insertions, 1316 deletions
diff --git a/ChangeLog b/ChangeLog
index 4a7f4e94..da4aeb6f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -49,7 +49,8 @@ dillo-2.1
? Trying a new iconv() test in configure.in.
- Allowed the rc parser to skip whitespace around the equal sign.
- Fixed the parser not to call Html_tag_close_* functions twice.
-!- Started code cleanup of the image code mainly in dicache.c.
+ - Implemented CSS Stylesheet loading.
+ - Made a big cleanup of cache.c WRT charset decoding (fixes bugs).
Patches: Jorge Arellano Cid
dw
diff --git a/dillorc b/dillorc
index 0b22d74f..215cdfdf 100644
--- a/dillorc
+++ b/dillorc
@@ -18,6 +18,8 @@
# (there's a toggle button near the bug meter to change this on-the-fly)
#load_images=YES
+# Change this if you want to disable loading of CSS stylesheets.
+#load_stylesheets=YES
# Change the buffering scheme for drawing
# 0 no double buffering - useful for debugging
diff --git a/dw/fltkimgbuf.cc b/dw/fltkimgbuf.cc
index b8beb1cb..571a8abd 100644
--- a/dw/fltkimgbuf.cc
+++ b/dw/fltkimgbuf.cc
@@ -85,12 +85,7 @@ void FltkImgbuf::init (Type type, int width, int height, FltkImgbuf *root)
FltkImgbuf::~FltkImgbuf ()
{
- //printf ("FltkImgbuf::~FltkImgbuf (%s)\n", isRoot() ? "root" : "scaled");
-
- //if (root)
- // printf("FltkImgbuf[scaled %p, root is %p]: deleted\n", this, root);
- //else
- // printf("FltkImgbuf[root %p]: deleted\n", this);
+ //printf("~FltkImgbuf[%s %p] deleted\n", isRoot() ? "root":"scaled", this);
if (!isRoot())
root->detachScaledBuf (this);
@@ -175,7 +170,7 @@ void FltkImgbuf::newScan ()
core::Imgbuf* FltkImgbuf::getScaledBuf (int width, int height)
{
- if (root)
+ if (!isRoot())
return root->getScaledBuf (width, height);
if (width == this->width && height == this->height) {
@@ -256,10 +251,11 @@ void FltkImgbuf::unref ()
if (isRoot ()) {
// Root buffer, it must be ensured that no scaled buffers are left.
// See also FltkImgbuf::detachScaledBuf().
- if (scaledBuffers->isEmpty () && deleteOnUnref)
+ if (scaledBuffers->isEmpty () && deleteOnUnref) {
delete this;
- else
- printf("FltkImgbuf[root %p]: not deleted\n", this);
+ } else
+ printf("FltkImgbuf[root %p]: not deleted. numScaled=%d\n",
+ this, scaledBuffers->size ());
} else
// Scaled buffer buffer, simply delete it.
delete this;
@@ -293,7 +289,7 @@ int FltkImgbuf::scaledY(int ySrc)
}
void FltkImgbuf::draw (::fltk::Widget *target, int xRoot, int yRoot,
- int x, int y, int width, int height)
+ int x, int y, int width, int height)
{
// TODO (i): Implementation.
// TODO (ii): Clarify the question, whether "target" is the current widget
diff --git a/dw/fltkplatform.cc b/dw/fltkplatform.cc
index 1dc1c860..e35027d4 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>
@@ -54,7 +55,7 @@ FltkFont::FltkFont (core::style::FontAttrs *attrs)
font = ::fltk::font(name, fa);
if(font == NULL) {
- fprintf(stderr, "No font '%s', using default sans-serif font.\n", name);
+ //fprintf(stderr, "No font '%s', using default sans-serif font.\n",name);
/*
* If using xft, fltk::HELVETICA just means sans, fltk::COURIER
* means mono, and fltk::TIMES means serif.
@@ -100,11 +101,9 @@ container::typed::HashTable <dw::core::style::ColorAttrs,
new container::typed::HashTable <dw::core::style::ColorAttrs,
FltkColor> (false, false);
-FltkColor::FltkColor (int color, core::style::Color::Type type):
- Color (color, type)
+FltkColor::FltkColor (int color): Color (color)
{
this->color = color;
- this->type = type;
/*
* fltk/setcolor.cxx:
@@ -122,13 +121,10 @@ FltkColor::FltkColor (int color, core::style::Color::Type type):
colors[SHADING_NORMAL] = ::fltk::BLACK;
if (!(colors[SHADING_INVERSE] = shadeColor (color, SHADING_INVERSE) << 8))
colors[SHADING_INVERSE] = ::fltk::BLACK;
-
- if(type == core::style::Color::TYPE_SHADED) {
- if (!(colors[SHADING_DARK] = shadeColor (color, SHADING_DARK) << 8))
- colors[SHADING_DARK] = ::fltk::BLACK;
- if (!(colors[SHADING_LIGHT] = shadeColor (color, SHADING_LIGHT) << 8))
- colors[SHADING_LIGHT] = ::fltk::BLACK;
- }
+ if (!(colors[SHADING_DARK] = shadeColor (color, SHADING_DARK) << 8))
+ colors[SHADING_DARK] = ::fltk::BLACK;
+ if (!(colors[SHADING_LIGHT] = shadeColor (color, SHADING_LIGHT) << 8))
+ colors[SHADING_LIGHT] = ::fltk::BLACK;
}
FltkColor::~FltkColor ()
@@ -136,13 +132,13 @@ FltkColor::~FltkColor ()
colorsTable->remove (this);
}
-FltkColor * FltkColor::create (int col, core::style::Color::Type type)
+FltkColor * FltkColor::create (int col)
{
- ColorAttrs attrs(col, type);
+ ColorAttrs attrs(col);
FltkColor *color = colorsTable->get (&attrs);
if (color == NULL) {
- color = new FltkColor (col, type);
+ color = new FltkColor (col);
colorsTable->put (color, color);
}
@@ -302,6 +298,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();
@@ -375,14 +381,9 @@ core::style::Font *FltkPlatform::createFont (core::style::FontAttrs
return FltkFont::create (attrs);
}
-core::style::Color *FltkPlatform::createSimpleColor (int color)
-{
- return FltkColor::create (color, core::style::Color::TYPE_SIMPLE);
-}
-
-core::style::Color *FltkPlatform::createShadedColor (int color)
+core::style::Color *FltkPlatform::createColor (int color)
{
- return FltkColor::create (color, core::style::Color::TYPE_SHADED);
+ return FltkColor::create (color);
}
void FltkPlatform::copySelection(const char *text)
diff --git a/dw/fltkplatform.hh b/dw/fltkplatform.hh
index 7f430ee3..776204a6 100644
--- a/dw/fltkplatform.hh
+++ b/dw/fltkplatform.hh
@@ -34,13 +34,13 @@ class FltkColor: public core::style::Color
static lout::container::typed::HashTable <dw::core::style::ColorAttrs,
FltkColor> *colorsTable;
- FltkColor (int color, core::style::Color::Type type);
+ FltkColor (int color);
~FltkColor ();
public:
int colors[SHADING_NUM];
- static FltkColor *create(int color, core::style::Color::Type type);
+ static FltkColor *create(int color);
};
@@ -126,14 +126,15 @@ 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);
core::style::Font *createFont (core::style::FontAttrs *attrs,
bool tryEverything);
- core::style::Color *createSimpleColor (int color);
- core::style::Color *createShadedColor (int color);
+ core::style::Color *createColor (int color);
core::Imgbuf *createImgbuf (core::Imgbuf::Type type, int width, int height);
diff --git a/dw/layout.hh b/dw/layout.hh
index 13b8f312..ce9786f1 100644
--- a/dw/layout.hh
+++ b/dw/layout.hh
@@ -216,19 +216,24 @@ public:
return platform->prevGlyph (text, idx);
}
- inline style::Font *createFont (style::FontAttrs *attrs, bool tryEverything)
+ inline float dpiX ()
{
- return platform->createFont (attrs, tryEverything);
+ return platform->dpiX ();
}
- inline style::Color *createSimpleColor (int color)
+ inline float dpiY ()
{
- return platform->createSimpleColor (color);
+ return platform->dpiY ();
+ }
+
+ inline style::Font *createFont (style::FontAttrs *attrs, bool tryEverything)
+ {
+ return platform->createFont (attrs, tryEverything);
}
- inline style::Color *createShadedColor (int color)
+ inline style::Color *createColor (int color)
{
- return platform->createShadedColor (color);
+ return platform->createColor (color);
}
inline Imgbuf *createImgbuf (Imgbuf::Type type, int width, int height)
diff --git a/dw/platform.hh b/dw/platform.hh
index 0ae5d508..156a602a 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;
/*
* ---------------------------------------------------------
@@ -110,15 +120,9 @@ public:
bool tryEverything) = 0;
/**
- * \brief Create a simple color resource for a given 0xrrggbb value.
+ * \brief Create a color resource for a given 0xrrggbb value.
*/
- virtual style::Color *createSimpleColor (int color) = 0;
-
- /**
- * \brief Create a shaded color resource for a given 0xrrggbb value.
- */
- virtual style::Color *createShadedColor (int color) = 0;
-
+ virtual style::Color *createColor (int color) = 0;
/*
* --------------------
diff --git a/dw/style.cc b/dw/style.cc
index 52092593..106f2592 100644
--- a/dw/style.cc
+++ b/dw/style.cc
@@ -64,11 +64,9 @@ void StyleAttrs::initValues ()
*/
void StyleAttrs::resetValues ()
{
- x_link = -1;
x_img = -1;
x_tooltip = NULL;
- textAlign = TEXT_ALIGN_LEFT; /* ??? */
valign = VALIGN_MIDDLE;
textAlignChar = '.';
backgroundColor = NULL;
@@ -84,8 +82,6 @@ void StyleAttrs::resetValues ()
vBorderSpacing = 0;
display = DISPLAY_INLINE;
- whiteSpace = WHITE_SPACE_NORMAL;
- cursor = CURSOR_DEFAULT; /** \todo Check CSS specification again. */
}
/**
@@ -338,12 +334,12 @@ Font *Font::createFromList (Layout *layout, FontAttrs *attrs,
bool ColorAttrs::equals(object::Object *other)
{
ColorAttrs *oc = (ColorAttrs*)other;
- return this == oc || (color == oc->color && type == oc->type);
+ return this == oc || (color == oc->color);
}
int ColorAttrs::hashValue()
{
- return color ^ type;
+ return color;
}
Color::~Color ()
@@ -407,21 +403,11 @@ int Color::shadeColor (int color, Shading shading)
}
-Color *Color::create (Layout *layout, int col, Type type)
+Color *Color::create (Layout *layout, int col)
{
- ColorAttrs attrs(col, type);
- Color *color = NULL;
+ ColorAttrs attrs(col);
- switch (type) {
- case TYPE_SIMPLE:
- color = layout->createSimpleColor (col);
- break;
- case TYPE_SHADED:
- color = layout->createShadedColor (col);
- break;
- }
-
- return color;
+ return layout->createColor (col);
}
// ----------------------------------------------------------------------
@@ -488,9 +474,6 @@ void drawBorder (View *view, Rectangle *area,
Color::Shading top, right, bottom, left;
int xb1, yb1, xb2, yb2, xp1, yp1, xp2, yp2;
- if (style->borderStyle.top == BORDER_NONE)
- return;
-
xb1 = x + style->margin.left;
yb1 = y + style->margin.top;
xb2 = xb1 + width - style->margin.left - style->margin.right;
@@ -521,18 +504,25 @@ void drawBorder (View *view, Rectangle *area,
break;
}
- drawPolygon (view, style->borderColor.top, top, xb1, yb1, xb2, yb1,
- style->borderWidth.top, style->borderWidth.left,
- - style->borderWidth.right);
- drawPolygon (view, style->borderColor.right, right, xb2, yb1, xb2, yb2,
- - style->borderWidth.right, style->borderWidth.top,
- - style->borderWidth.bottom);
- drawPolygon (view, style->borderColor.bottom, bottom, xb1, yb2, xb2, yb2,
- - style->borderWidth.bottom, style->borderWidth.left,
- - style->borderWidth.right);
- drawPolygon (view, style->borderColor.left, left, xb1, yb1, xb1, yb2,
- style->borderWidth.left, style->borderWidth.top,
- - style->borderWidth.bottom);
+ if (style->borderStyle.top != BORDER_NONE && style->borderColor.top)
+ drawPolygon (view, style->borderColor.top, top, xb1, yb1, xb2, yb1,
+ style->borderWidth.top, style->borderWidth.left,
+ - style->borderWidth.right);
+
+ if (style->borderStyle.right != BORDER_NONE && style->borderColor.right)
+ drawPolygon (view, style->borderColor.right, right, xb2, yb1, xb2, yb2,
+ - style->borderWidth.right, style->borderWidth.top,
+ - style->borderWidth.bottom);
+
+ if (style->borderStyle.bottom != BORDER_NONE && style->borderColor.bottom)
+ drawPolygon (view, style->borderColor.bottom, bottom, xb1, yb2, xb2, yb2,
+ - style->borderWidth.bottom, style->borderWidth.left,
+ - style->borderWidth.right);
+
+ if (style->borderStyle.left != BORDER_NONE && style->borderColor.left)
+ drawPolygon (view, style->borderColor.left, left, xb1, yb1, xb1, yb2,
+ style->borderWidth.left, style->borderWidth.top,
+ - style->borderWidth.bottom);
}
diff --git a/dw/style.hh b/dw/style.hh
index 0dd7fbd4..9e6672bb 100644
--- a/dw/style.hh
+++ b/dw/style.hh
@@ -591,22 +591,16 @@ public:
*/
class ColorAttrs: public object::Object
{
-public:
- enum Type { TYPE_SIMPLE, TYPE_SHADED };
-
protected:
int color;
- Type type;
public:
- inline ColorAttrs(int color, Type type)
+ inline ColorAttrs(int color)
{
this->color = color;
- this->type = type;
}
inline int getColor () { return color; }
- inline Type getType () { return type; }
bool equals(object::Object *other);
int hashValue();
@@ -621,12 +615,11 @@ class Color: public ColorAttrs
private:
int refCount;
- static Color *create (Layout *layout, int color, Type type);
void remove(dw::core::Layout *layout);
- int shadeColor (int color, int d);
+ int shadeColor (int color, int d);
protected:
- inline Color (int color, Type type): ColorAttrs (color, type) {
+ inline Color (int color): ColorAttrs (color) {
refCount = 0; }
virtual ~Color ();
@@ -638,15 +631,7 @@ protected:
int shadeColor (int color, Shading shading);
public:
- inline static Color *createSimple (Layout *layout, int color)
- {
- return create (layout, color, TYPE_SIMPLE);
- }
-
- inline static Color *createShaded (Layout *layout, int color)
- {
- return create (layout, color, TYPE_SHADED);
- }
+ static Color *create (Layout *layout, int color);
inline void ref () { refCount++; }
inline void unref ()
diff --git a/dw/textblock.cc b/dw/textblock.cc
index d80a7ad4..2f5c66ae 100644
--- a/dw/textblock.cc
+++ b/dw/textblock.cc
@@ -1077,8 +1077,8 @@ void Textblock::calcWidgetSize (core::Widget *widget, core::Requisition *size)
widget->setAscent (availAscent);
widget->setDescent (availDescent);
widget->sizeRequest (size);
- size->ascent -= widget->getStyle()->margin.top;
- size->descent -= widget->getStyle()->margin.bottom;
+// size->ascent -= widget->getStyle()->margin.top;
+// size->descent -= widget->getStyle()->margin.bottom;
} else {
/* TODO: Use margin.{top|bottom} here, like above.
* (No harm for the next future.) */
@@ -1921,14 +1921,14 @@ void Textblock::changeLinkColor (int link, int newColor)
case core::Content::TEXT:
{ core::style::Style *old_style = word->style;
styleAttrs = *old_style;
- styleAttrs.color = core::style::Color::createSimple (layout,
- newColor);
+ styleAttrs.color = core::style::Color::create (layout,
+ newColor);
word->style = core::style::Style::create (layout, &styleAttrs);
old_style->unref();
old_style = word->spaceStyle;
styleAttrs = *old_style;
- styleAttrs.color = core::style::Color::createSimple (layout,
- newColor);
+ styleAttrs.color = core::style::Color::create (layout,
+ newColor);
word->spaceStyle =
core::style::Style::create(layout, &styleAttrs);
old_style->unref();
@@ -1937,10 +1937,10 @@ void Textblock::changeLinkColor (int link, int newColor)
case core::Content::WIDGET:
{ core::Widget *widget = word->content.widget;
styleAttrs = *widget->getStyle();
- styleAttrs.color = core::style::Color::createSimple (layout,
- newColor);
+ styleAttrs.color = core::style::Color::create (layout,
+ newColor);
styleAttrs.setBorderColor(
- core::style::Color::createShaded(layout, newColor));
+ core::style::Color::create (layout, newColor));
widget->setStyle(
core::style::Style::create (layout, &styleAttrs));
break;
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 8da631ea..e944fb98 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -67,6 +67,13 @@ dillo_SOURCES = \
dicache.h \
capi.c \
capi.h \
+ css.cc \
+ css.hh \
+ cssparser.cc \
+ cssparser.hh \
+ doctree.hh \
+ styleengine.cc \
+ styleengine.hh \
plain.cc \
html.cc \
html.hh \
@@ -82,6 +89,8 @@ dillo_SOURCES = \
gif.c \
jpeg.c \
png.c \
+ imgbuf.cc \
+ imgbuf.hh \
image.cc \
image.hh \
menu.hh \
diff --git a/src/bw.c b/src/bw.c
index 27f3066c..d0c92086 100644
--- a/src/bw.c
+++ b/src/bw.c
@@ -63,6 +63,7 @@ BrowserWindow *a_Bw_new()
bw->ImageClients = dList_new(8);
bw->NumImages = 0;
bw->NumImagesGot = 0;
+ bw->NumPendingStyleSheets = 0;
bw->PageUrls = dList_new(8);
bw->Docs = dList_new(8);
@@ -253,6 +254,9 @@ void a_Bw_cleanup(BrowserWindow *bw)
/* Zero image-progress data */
bw->NumImages = 0;
bw->NumImagesGot = 0;
+
+ /* Zero stylesheet counter */
+ bw->NumPendingStyleSheets = 0;
}
/*--------------------------------------------------------------------------*/
diff --git a/src/bw.h b/src/bw.h
index 4345bf54..1dcf3a3a 100644
--- a/src/bw.h
+++ b/src/bw.h
@@ -38,6 +38,8 @@ struct _BrowserWindow
int NumImages;
/* Number of images already loaded */
int NumImagesGot;
+ /* Number of not yet arrived style sheets */
+ int NumPendingStyleSheets;
/* List of all Urls requested by this page (and its types) */
Dlist *PageUrls;
@@ -57,8 +59,7 @@ struct _BrowserWindow
* redirection loops (accounts for WEB_RootUrl only) */
int redirect_level;
- /* TODO: maybe this fits better in the linkblock.
- * Although having it here avoids having a signal for handling it. */
+ /* HTML-bugs detected at parse time */
int num_page_bugs;
Dstr *page_bugs;
};
diff --git a/src/cache.c b/src/cache.c
index 831ad411..9cdcdfb4 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -161,6 +161,7 @@ static int Cache_client_enqueue(const DilloUrl *Url, DilloWeb *Web,
ClientKey = Cache_client_make_key();
NewClient->Key = ClientKey;
NewClient->Url = Url;
+ NewClient->Version = 0;
NewClient->Buf = NULL;
NewClient->Callback = Callback;
NewClient->CbData = CbData;
@@ -424,6 +425,7 @@ static void Cache_ref_data(CacheEntry_t *entry)
entry->DataRefcount++;
_MSG("DataRefcount++: %d\n", entry->DataRefcount);
if (entry->CharsetDecoder && entry->DataRefcount == 1) {
+ dStr_free(entry->UTF8Data, 1);
entry->UTF8Data = a_Decode_process(entry->CharsetDecoder,
entry->Data->str,
entry->Data->len);
@@ -483,40 +485,33 @@ static Dstr *Cache_data(CacheEntry_t *entry)
* Change Content-Type for cache entry found by url.
* Return new content type.
*/
-const char *a_Cache_set_content_type(const DilloUrl *url, const char *ctype,
- bool_t force)
+const char *a_Cache_set_content_type(const DilloUrl *url, const char *ctype)
{
+ char *charset;
const char *curr;
CacheEntry_t *entry = Cache_entry_search_with_redirect(url);
- if (!entry)
- return NULL;
+ dReturn_val_if_fail (entry != NULL, NULL);
- curr = Cache_current_content_type(entry);
- if (entry->TypeMeta && (force == FALSE)) {
- /* it's already been set */
- return curr;
- }
-
- if (a_Misc_content_type_cmp(curr, ctype)) {
- char *charset;
+ MSG("a_Cache_set_content_type {%s} {%s}\n", ctype, URL_STR(url));
- dFree(entry->TypeMeta);
+ curr = Cache_current_content_type(entry);
+ if (entry->TypeMeta) {
+ /* Type is already been set. Do nothing.
+ * Multiple META elements? */
+ } else if (a_Misc_content_type_cmp(curr, ctype)) {
+ /* TypeMeta not set, and META gives one different from default */
curr = entry->TypeMeta = dStrdup(ctype);
-
if (entry->CharsetDecoder)
a_Decode_free(entry->CharsetDecoder);
a_Misc_parse_content_type(ctype, NULL, NULL, &charset);
entry->CharsetDecoder = a_Decode_charset_init(charset);
dFree(charset);
+ /* Invalidate UTF8Data */
dStr_free(entry->UTF8Data, 1);
- if (entry->CharsetDecoder && entry->DataRefcount > 0)
- entry->UTF8Data = a_Decode_process(entry->CharsetDecoder,
- entry->Data->str,
- entry->Data->len);
- else
- entry->UTF8Data = NULL;
+ entry->UTF8Data = NULL;
+
}
return curr;
@@ -632,7 +627,7 @@ static Dlist *Cache_parse_multiple_fields(const char *header,
static void Cache_parse_header(CacheEntry_t *entry)
{
char *header = entry->Header->str;
- char *Length, *Type, *location_str, *encoding, *charset;
+ char *Length, *Type, *location_str, *encoding;
#ifndef DISABLE_COOKIES
Dlist *Cookies;
#endif
@@ -641,6 +636,8 @@ static void Cache_parse_header(CacheEntry_t *entry)
void *data;
int i;
+ MSG("Cache_parse_header\n");
+
if (entry->Header->len > 12) {
if (header[9] == '1' && header[10] == '0' && header[11] == '0') {
/* 100: Continue. The "real" header has not come yet. */
@@ -751,18 +748,11 @@ static void Cache_parse_header(CacheEntry_t *entry)
MSG_HTTP("Server didn't send Content-Type in header.\n");
}
} else {
+ /* This HTTP Content-Type is not trusted. It's checked against real data
+ * in Cache_process_queue(); only then CA_GotContentType becomes true. */
entry->TypeHdr = Type;
- _MSG("Content-Type {%s} {%s}\n", Type, URL_STR(entry->Url));
- /* This Content-Type is not trusted. It's checked against real data
- * in Cache_process_queue(); only then CA_GotContentType becomes true.
- */
- a_Misc_parse_content_type(Type, NULL, NULL, &charset);
- if (charset) {
- entry->CharsetDecoder = a_Decode_charset_init(charset);
- if (entry->CharsetDecoder)
- entry->UTF8Data = dStr_new("");
- dFree(charset);
- }
+ MSG("TypeHdr {%s} {%s}\n", Type, URL_STR(entry->Url));
+ MSG("TypeMeta {%s}\n", entry->TypeMeta);
}
}
@@ -812,15 +802,60 @@ static int Cache_get_header(CacheEntry_t *entry,
void a_Cache_process_dbuf(int Op, const char *buf, size_t buf_size,
const DilloUrl *Url)
{
- int offset = 0;
- int len;
+ int offset, len;
const char *str;
+ Dstr *dstr1, *dstr2, *dstr3;
CacheEntry_t *entry = Cache_entry_search(Url);
/* Assert a valid entry (not aborted) */
dReturn_if_fail (entry != NULL);
- if (Op == IOClose) {
+ MSG("__a_Cache_process_dbuf__\n");
+
+ if (Op == IORead) {
+ /*
+ * Cache_get_header() will set CA_GotHeader if it has a full header, and
+ * Cache_parse_header() will unset it if the header ends being
+ * merely an informational response from the server (i.e., 100 Continue)
+ */
+ for (offset = 0; !(entry->Flags & CA_GotHeader) &&
+ (len = Cache_get_header(entry, buf + offset, buf_size - offset));
+ Cache_parse_header(entry) ) {
+ offset += len;
+ }
+
+ if (entry->Flags & CA_GotHeader) {
+ str = buf + offset;
+ len = buf_size - offset;
+ entry->TransferSize += len;
+ dstr1 = dstr2 = dstr3 = NULL;
+
+ /* Decode arrived data (<= 3 stages) */
+ if (entry->TransferDecoder) {
+ dstr1 = a_Decode_process(entry->TransferDecoder, str, len);
+ str = dstr1->str;
+ len = dstr1->len;
+ }
+ if (entry->ContentDecoder) {
+ dstr2 = a_Decode_process(entry->ContentDecoder, str, len);
+ str = dstr2->str;
+ len = dstr2->len;
+ }
+ dStr_append_l(entry->Data, str, len);
+ if (entry->CharsetDecoder && entry->UTF8Data) {
+ dstr3 = a_Decode_process(entry->CharsetDecoder, str, len);
+ dStr_append_l(entry->UTF8Data, dstr3->str, dstr3->len);
+ }
+ dStr_free(dstr1, 1);
+ dStr_free(dstr2, 1);
+ dStr_free(dstr3, 1);
+
+ if (entry->Data->len)
+ entry->Flags &= ~CA_IsEmpty;
+
+ Cache_process_queue(entry);
+ }
+ } else if (Op == IOClose) {
if ((entry->Flags & CA_GotLength) &&
(entry->ExpectedSize != entry->TransferSize)) {
MSG_HTTP("Content-Length does NOT match message body,\n"
@@ -843,61 +878,11 @@ void a_Cache_process_dbuf(int Op, const char *buf, size_t buf_size,
if (entry->Flags & CA_GotHeader) {
Cache_unref_data(entry);
}
- return;
+
} else if (Op == IOAbort) {
/* unused */
MSG("a_Cache_process_dbuf Op = IOAbort; not implemented!\n");
- return;
- }
-
- /*
- * Cache_get_header() will set CA_GotHeader if it has a full header, and
- * Cache_parse_header() will unset it if the header turns out to have been
- * merely an informational response from the server (i.e., 100 Continue)
- */
- while (!(entry->Flags & CA_GotHeader) &&
- (len = Cache_get_header(entry, buf + offset, buf_size - offset))) {
- offset += len;
- /* Let's scan, allocate, and set things according to header info */
- Cache_parse_header(entry);
- }
-
- if (!(entry->Flags & CA_GotHeader))
- return;
-
- str = buf + offset;
- len = buf_size - offset;
- entry->TransferSize += len;
-
- if (entry->TransferDecoder) {
- Dstr *dbuf = a_Decode_process(entry->TransferDecoder, str, len);
- str = dbuf->str;
- len = dbuf->len;
- dStr_free(dbuf, 0);
- }
- if (entry->ContentDecoder) {
- Dstr *dbuf = a_Decode_process(entry->ContentDecoder, str, len);
- if (entry->TransferDecoder)
- dFree((char *)str);
- str = dbuf->str;
- len = dbuf->len;
- dStr_free(dbuf, 0);
- }
- dStr_append_l(entry->Data, str, len);
-
- if (entry->UTF8Data) {
- Dstr *dbuf = a_Decode_process(entry->CharsetDecoder, str, len);
- dStr_append_l(entry->UTF8Data, dbuf->str, dbuf->len);
- dStr_free(dbuf, 1);
}
-
- if (entry->TransferDecoder || entry->ContentDecoder)
- dFree((char *)str);
-
- if (entry->Data->len)
- entry->Flags &= ~CA_IsEmpty;
-
- Cache_process_queue(entry);
}
/*
@@ -1258,9 +1243,14 @@ CacheClient_t *a_Cache_client_get_if_unique(int Key)
void a_Cache_stop_client(int Key)
{
CacheClient_t *Client;
+ DICacheEntry *DicEntry;
if ((Client = dList_find_custom(ClientQueue, INT2VOIDP(Key),
Cache_client_by_key_cmp))) {
+ DicEntry = a_Dicache_get_entry(Client->Url, Client->Version);
+ if (DicEntry) {
+ a_Dicache_unref(Client->Url, Client->Version);
+ }
Cache_client_dequeue(Client, NULLKey);
} else {
_MSG("WARNING: Cache_stop_client, nonexistent client\n");
diff --git a/src/cache.h b/src/cache.h
index 6099447c..81b9c1ec 100644
--- a/src/cache.h
+++ b/src/cache.h
@@ -46,6 +46,7 @@ typedef void (*CA_Callback_t)(int Op, CacheClient_t *Client);
struct _CacheClient {
int Key; /* Primary Key for this client */
const DilloUrl *Url; /* Pointer to a cache entry Url */
+ int Version; /* Dicache version of this Url (0 if not used) */
void *Buf; /* Pointer to cache-data */
uint_t BufSize; /* Valid size of cache-data */
CA_Callback_t Callback; /* Client function */
@@ -61,8 +62,7 @@ int a_Cache_open_url(void *Web, CA_Callback_t Call, void *CbData);
int a_Cache_get_buf(const DilloUrl *Url, char **PBuf, int *BufSize);
void a_Cache_unref_buf(const DilloUrl *Url);
const char *a_Cache_get_content_type(const DilloUrl *url);
-const char *a_Cache_set_content_type(const DilloUrl *url, const char *ctype,
- bool_t force);
+const char *a_Cache_set_content_type(const DilloUrl *url, const char *ctype);
uint_t a_Cache_get_flags(const DilloUrl *url);
void a_Cache_process_dbuf(int Op, const char *buf, size_t buf_size,
const DilloUrl *Url);
diff --git a/src/capi.c b/src/capi.c
index efa2cd93..cfd059f5 100644
--- a/src/capi.c
+++ b/src/capi.c
@@ -421,10 +421,9 @@ const char *a_Capi_get_content_type(const DilloUrl *url)
/*
* Set the Content-Type for the URL.
*/
-const char *a_Capi_set_content_type(const DilloUrl *url, const char *ctype,
- bool_t force)
+const char *a_Capi_set_content_type(const DilloUrl *url, const char *ctype)
{
- return a_Cache_set_content_type(url, ctype, force);
+ return a_Cache_set_content_type(url, ctype);
}
/*
diff --git a/src/capi.h b/src/capi.h
index c30dc6cf..fe1cacdf 100644
--- a/src/capi.h
+++ b/src/capi.h
@@ -26,8 +26,7 @@ int a_Capi_open_url(DilloWeb *web, CA_Callback_t Call, void *CbData);
int a_Capi_get_buf(const DilloUrl *Url, char **PBuf, int *BufSize);
void a_Capi_unref_buf(const DilloUrl *Url);
const char *a_Capi_get_content_type(const DilloUrl *url);
-const char *a_Capi_set_content_type(const DilloUrl *url, const char *ctype,
- bool_t force);
+const char *a_Capi_set_content_type(const DilloUrl *url, const char *ctype);
int a_Capi_get_flags(const DilloUrl *Url);
int a_Capi_dpi_send_cmd(DilloUrl *url, void *bw, char *cmd, char *server,
int flags);
diff --git a/src/colors.c b/src/colors.c
index 9a4c8c8e..6a684dde 100644
--- a/src/colors.c
+++ b/src/colors.c
@@ -204,7 +204,7 @@ static const struct key {
#define NCOLORS (sizeof(color_keyword) / sizeof(struct key))
/*
- * Parse a color in hex (RRGGBB)
+ * Parse a color in hex (RRGGBB) or (RGB)
*
* Return Value:
* parsed color if successful (err = 0),
@@ -219,7 +219,12 @@ static int32_t Color_parse_hex (const char *s, int32_t default_color, int *err)
ret_color = strtol(s, &tail, 16);
if (tail - s == 6)
*err = 0;
- else
+ else if (tail - s == 3) { /* #RGB as allowed by CSS */
+ *err = 0;
+ ret_color = ((ret_color & 0xf00) << 12) | ((ret_color & 0xf00) << 8) |
+ ((ret_color & 0x0f0) << 8) | ((ret_color & 0x0f0) << 4) |
+ ((ret_color & 0x00f) << 4) | ((ret_color & 0x00f) << 0);
+ } else
ret_color = default_color;
return ret_color;
diff --git a/src/css.cc b/src/css.cc
new file mode 100644
index 00000000..578ccfb7
--- /dev/null
+++ b/src/css.cc
@@ -0,0 +1,345 @@
+/*
+ * File: css.cc
+ *
+ * Copyright 2008 Jorge Arellano Cid <jcid@dillo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <stdio.h>
+#include <math.h>
+#include "../dlib/dlib.h"
+#include "prefs.h"
+#include "html_common.hh"
+#include "css.hh"
+#include "cssparser.hh"
+
+using namespace dw::core::style;
+
+void CssProperty::print () {
+ fprintf (stderr, "%s - %d\n", Css_property_info[name].symbol, value.intVal);
+}
+
+void CssPropertyList::set (CssProperty::Name name, CssProperty::Value value) {
+ for (int i = 0; i < size (); i++)
+ if (getRef (i)->name == name) {
+ getRef (i)->value = value;
+ return;
+ }
+
+ increase ();
+ getRef (size () - 1)->name = name;
+ getRef (size () - 1)->value = value;
+}
+
+void CssPropertyList::apply (CssPropertyList *props) {
+ for (int i = 0; i < size (); i++)
+ props->set (getRef (i)->name, getRef (i)->value);
+}
+
+void CssPropertyList::print () {
+ for (int i = 0; i < size (); i++)
+ getRef (i)->print ();
+}
+
+CssSelector::CssSelector (int element, const char *klass,
+ const char *pseudo, const char *id) {
+ refCount = 0;
+ selectorList = new lout::misc::SimpleVector
+ <struct CombinatorAndSelector> (1);
+ selectorList->increase ();
+ top ()->element = element;
+ top ()->klass = klass;
+ top ()->pseudo = pseudo;
+ top ()->id = id;
+};
+
+CssSelector::~CssSelector () {
+ delete selectorList;
+}
+
+bool CssSelector::match (Doctree *docTree) {
+ CssSimpleSelector *sel;
+ Combinator comb;
+ const DoctreeNode *node = docTree->top ();
+
+ assert (selectorList->size () > 0);
+
+ sel = top ();
+
+ if (! sel->match (node))
+ return false;
+
+ for (int i = selectorList->size () - 2; i >= 0; i--) {
+ sel = &selectorList->getRef (i)->selector;
+ comb = selectorList->getRef (i + 1)->combinator;
+ node = docTree->parent (node);
+
+ if (node == NULL)
+ return false;
+
+ switch (comb) {
+ case CHILD:
+ if (!sel->match (node))
+ return false;
+ break;
+ case DESCENDENT:
+ while (!sel->match (node)) {
+ node = docTree->parent (node);
+ if (node == NULL)
+ return false;
+ }
+ break;
+ default:
+ return false; // \todo implement other combinators
+ }
+ }
+
+ return true;
+}
+
+void CssSelector::addSimpleSelector (Combinator c, int element,
+ const char *klass, const char *pseudo,
+ const char *id) {
+ selectorList->increase ();
+
+ selectorList->getRef (selectorList->size () - 1)->combinator = c;
+ top ()->element = element;
+ top ()->klass = klass;
+ top ()->pseudo = pseudo;
+ top ()->id = id;
+
+}
+
+void CssSelector::print () {
+ for (int i = 0; i < selectorList->size (); i++) {
+ selectorList->getRef (i)->selector.print ();
+
+ if (i < selectorList->size () - 1) {
+ switch (selectorList->getRef (i + 1)->combinator) {
+ case CHILD:
+ fprintf (stderr, "> ");
+ break;
+ case DESCENDENT:
+ fprintf (stderr, "\" \" ");
+ break;
+ default:
+ fprintf (stderr, "? ");
+ break;
+ }
+ }
+ }
+
+ fprintf (stderr, "\n");
+}
+
+bool CssSimpleSelector::match (const DoctreeNode *n) {
+ if (element != ELEMENT_ANY && element != n->element)
+ return false;
+ if (klass != NULL &&
+ (n->klass == NULL || strcasecmp (klass, n->klass) != 0))
+ return false;
+ if (pseudo != NULL &&
+ (n->pseudo == NULL || strcasecmp (pseudo, n->pseudo) != 0))
+ return false;
+ if (id != NULL && (n->id == NULL || strcasecmp (id, n->id) != 0))
+ return false;
+
+ return true;
+}
+
+void CssSimpleSelector::print () {
+ fprintf (stderr, "Element %d, class %s, pseudo %s, id %s ",
+ element, klass, pseudo, id);
+}
+
+CssRule::CssRule (CssSelector *selector, CssPropertyList *props) {
+ refCount = 0;
+ this->selector = selector;
+ this->selector->ref ();
+ this->props = props;
+ this->props->ref ();
+};
+
+CssRule::~CssRule () {
+ selector->unref ();
+ props->unref ();
+};
+
+void CssRule::apply (CssPropertyList *props, Doctree *docTree) {
+ if (selector->match (docTree))
+ this->props->apply (props);
+}
+
+void CssRule::print () {
+ selector->print ();
+ props->print ();
+}
+
+CssStyleSheet::CssStyleSheet () {
+ for (int i = 0; i < ntags; i++)
+ ruleTable[i] = new lout::misc::SimpleVector <CssRule*> (1);
+}
+
+CssStyleSheet::~CssStyleSheet () {
+ for (int i = 0; i < ntags; i++) {
+ for (int j = 0; j < ruleTable[i]->size (); j++)
+ ruleTable[i]->get (j)->unref ();
+
+ delete ruleTable[i];
+ }
+}
+
+void CssStyleSheet::addRule (CssRule *rule) {
+ int topElement = rule->selector->top ()->element;
+
+ if (topElement == CssSimpleSelector::ELEMENT_ANY) {
+ for (int i = 0; i < ntags; i++) {
+ ruleTable[i]->increase ();
+ *ruleTable[i]->getRef (ruleTable[i]->size () - 1) = rule;
+ rule->ref ();
+ }
+ } else if (topElement >= 0 && topElement < ntags) {
+ ruleTable[topElement]->increase ();
+ *ruleTable[topElement]->getRef (ruleTable[topElement]->size()-1) = rule;
+ rule->ref ();
+ }
+}
+
+void CssStyleSheet::addRule (CssSelector *selector, CssPropertyList *props) {
+ CssRule *rule = new CssRule (selector, props);
+ addRule (rule);
+}
+
+void CssStyleSheet::apply (CssPropertyList *props, Doctree *docTree) {
+ lout::misc::SimpleVector <CssRule*> *ruleList;
+
+ ruleList = ruleTable[docTree->top ()->element];
+ for (int i = 0; i < ruleList->size (); i++)
+ ruleList->get (i)->apply (props, docTree);
+}
+
+CssStyleSheet *CssContext::userAgentStyle;
+CssStyleSheet *CssContext::userStyle;
+CssStyleSheet *CssContext::userImportantStyle;
+
+CssContext::CssContext () {
+ for (int o = CSS_PRIMARY_USER_AGENT; o < CSS_PRIMARY_LAST; o++)
+ sheet[o] = NULL;
+
+ if (userAgentStyle == NULL) {
+ userAgentStyle = new CssStyleSheet ();
+ userStyle = new CssStyleSheet ();
+ userImportantStyle = new CssStyleSheet ();
+
+ sheet[CSS_PRIMARY_USER_AGENT] = userAgentStyle;
+ sheet[CSS_PRIMARY_USER] = userStyle;
+ sheet[CSS_PRIMARY_USER_IMPORTANT] = userImportantStyle;
+
+ buildUserAgentStyle ();
+ buildUserStyle ();
+ }
+
+ sheet[CSS_PRIMARY_USER_AGENT] = userAgentStyle;
+ sheet[CSS_PRIMARY_USER] = userStyle;
+ sheet[CSS_PRIMARY_USER_IMPORTANT] = userImportantStyle;
+}
+
+CssContext::~CssContext () {
+ for (int o = CSS_PRIMARY_USER_AGENT; o < CSS_PRIMARY_LAST; o++)
+ if (sheet[o] != userAgentStyle && sheet[o] != userStyle &&
+ sheet[o] != userImportantStyle)
+ delete sheet[o];
+}
+
+void CssContext::apply (CssPropertyList *props, Doctree *docTree,
+ CssPropertyList *tagStyle, CssPropertyList *nonCssHints) {
+
+ for (int o = CSS_PRIMARY_USER_AGENT; o <= CSS_PRIMARY_USER; o++)
+ if (sheet[o])
+ sheet[o]->apply (props, docTree);
+
+ if (nonCssHints)
+ nonCssHints->apply (props);
+
+ for (int o = CSS_PRIMARY_AUTHOR; o <= CSS_PRIMARY_USER_IMPORTANT; o++)
+ if (sheet[o])
+ sheet[o]->apply (props, docTree);
+
+ if (tagStyle)
+ tagStyle->apply (props);
+}
+
+void CssContext::addRule (CssRule *rule, CssPrimaryOrder order) {
+ if (sheet[order] == NULL)
+ sheet[order] = new CssStyleSheet ();
+
+ sheet[order]->addRule (rule);
+
+// fprintf(stderr, "Adding Rule (%d)\n", order);
+// rule->print ();
+}
+
+void CssContext::buildUserAgentStyle () {
+ const char *cssBuf =
+ "body {background-color: #dcd1ba; font-family: helvetica; color: black;"
+ " margin: 5px}"
+ "big {font-size: 1.17em}"
+ "blockquote, dd {margin-left: 40px; margin-right: 40px}"
+ "center {text-align: center}"
+ "dt {font-weight: bolder}"
+ ":link {color: blue; text-decoration: underline; cursor: pointer}"
+ ":visited {color: green; text-decoration: underline; cursor: pointer}"
+ "h1, h2, h3, h4, h5, h6, b, strong {font-weight: bolder}"
+ "i, em, cite, address {font-style: italic}"
+ "img:link, img:visited {border: 1px solid}"
+ "frameset, ul, ol, dir {margin-left: 40px}"
+ "h1 {font-size: 2em; margin-top: .67em; margin-bottom: 0}"
+ "h2 {font-size: 1.5em; margin-top: .75em; margin-bottom: 0}"
+ "h3 {font-size: 1.17em; margin-top: .83em; margin-bottom: 0}"
+ "h4 {margin-top: 1.12em; margin-bottom: 0}"
+ "h5 {font-size: 0.83em; margin-top: 1.5em; margin-bottom: 0}"
+ "h6 {font-size: 0.75em; margin-top: 1.67em; margin-bottom: 0}"
+ "hr {width: 100%; border: 1px inset}"
+ "pre {white-space: pre}"
+ "ol {list-style-type: decimal}"
+ "ul {list-style-type: disc}"
+ "ul > ul {list-style-type: circle}"
+ "ul > ul > ul {list-style-type: square}"
+ "ul > ul > ul > ul {list-style-type: disc}"
+ "u {text-decoration: underline}"
+ "small, sub, sup { font-size: 0.83em}"
+ "sub { vertical-align: sub}"
+ "sup { vertical-align: super}"
+ "s, strike, del { text-decoration: line-through}"
+ "table {border-style: outset; border-spacing: 1px}"
+ "td {border-style: inset; padding: 2px}"
+ "thead, tbody, tfoot { vertical-align: middle}"
+ "th { font-weight: bolder; text-align: center}"
+ "code, tt, pre, samp, kbd {font-family: courier}";
+
+ a_Css_parse (this, cssBuf, strlen (cssBuf), 0, CSS_ORIGIN_USER_AGENT);
+}
+
+void CssContext::buildUserStyle () {
+ char buf[1024];
+ char *filename;
+
+ filename = dStrconcat(dGethomedir(), "/.dillo/style.css", NULL);
+ FILE *fp = fopen (filename, "r");
+ if (fp) {
+ Dstr *style = dStr_sized_new (1024);
+ size_t len;
+
+ while ((len = fread (buf, 1, sizeof (buf), fp)))
+ dStr_append_l (style, buf, len);
+
+ a_Css_parse (this, style->str, style->len, 0, CSS_ORIGIN_USER);
+ dStr_free (style, 1);
+ }
+
+ dFree (filename);
+}
diff --git a/src/css.hh b/src/css.hh
new file mode 100644
index 00000000..515831e9
--- /dev/null
+++ b/src/css.hh
@@ -0,0 +1,313 @@
+#ifndef __CSS_HH__
+#define __CSS_HH__
+
+#include "dw/core.hh"
+#include "doctree.hh"
+
+/* Origin and weight. Used only internally.*/
+typedef enum {
+ CSS_PRIMARY_USER_AGENT,
+ CSS_PRIMARY_USER,
+ CSS_PRIMARY_AUTHOR,
+ CSS_PRIMARY_AUTHOR_IMPORTANT,
+ CSS_PRIMARY_USER_IMPORTANT,
+ CSS_PRIMARY_LAST,
+} CssPrimaryOrder;
+
+/*
+ * Lengths are represented as int in the following way:
+ *
+ * +---+ - - - +---+---+- - - - - -+---+---+---+---+
+ * | integer part | decimal fraction | type |
+ * +---+ - - - +---+---+- - - - - -+---+---+---+---+
+ * n-1 19 18 3 2 1 0
+ *
+ * | <------ fixed point value ------> |
+ *
+ * where type is one of the CSS_LENGTH_TYPE_* values.
+ */
+
+typedef int CssLength;
+
+enum {
+ CSS_LENGTH_TYPE_PX,
+ CSS_LENGTH_TYPE_MM, /* "cm", "in", "pt" and "pc" are converted into
+ millimeters. */
+ CSS_LENGTH_TYPE_EM,
+ CSS_LENGTH_TYPE_EX,
+ CSS_LENGTH_TYPE_PERCENTAGE,
+ CSS_LENGTH_TYPE_RELATIVE, /* This does not exist in CSS but
+ is used in HTML */
+ CSS_LENGTH_TYPE_AUTO /* This can be used as a simple value. */
+};
+
+#define CSS_CREATE_LENGTH(v, t) ( ( (int)((v) * (1 << 19)) & ~7 ) | (t) )
+#define CSS_LENGTH_VALUE(l) ( ( (float)((l) & ~7) ) / (1 << 19) )
+#define CSS_LENGTH_TYPE(l) ((l) & 7)
+
+/**
+ * \brief This class holds a CSS property and value pair.
+ */
+class CssProperty {
+ public:
+ typedef union {
+ int intVal;
+ const char *strVal;
+ } Value;
+
+ typedef enum {
+ CSS_PROPERTY_BACKGROUND_ATTACHMENT,
+ CSS_PROPERTY_BACKGROUND_COLOR,
+ CSS_PROPERTY_BACKGROUND_IMAGE,
+ CSS_PROPERTY_BACKGROUND_POSITION,
+ CSS_PROPERTY_BACKGROUND_REPEAT,
+ CSS_PROPERTY_BORDER_BOTTOM_COLOR,
+ CSS_PROPERTY_BORDER_BOTTOM_STYLE,
+ CSS_PROPERTY_BORDER_BOTTOM_WIDTH,
+ CSS_PROPERTY_BORDER_COLLAPSE,
+ CSS_PROPERTY_BORDER_LEFT_COLOR,
+ CSS_PROPERTY_BORDER_LEFT_STYLE,
+ CSS_PROPERTY_BORDER_LEFT_WIDTH,
+ CSS_PROPERTY_BORDER_RIGHT_COLOR,
+ CSS_PROPERTY_BORDER_RIGHT_STYLE,
+ CSS_PROPERTY_BORDER_RIGHT_WIDTH,
+ CSS_PROPERTY_BORDER_SPACING,
+ CSS_PROPERTY_BORDER_TOP_COLOR,
+ CSS_PROPERTY_BORDER_TOP_STYLE,
+ CSS_PROPERTY_BORDER_TOP_WIDTH,
+ CSS_PROPERTY_BOTTOM,
+ CSS_PROPERTY_CAPTION_SIDE,
+ CSS_PROPERTY_CLEAR,
+ CSS_PROPERTY_CLIP,
+ CSS_PROPERTY_COLOR,
+ CSS_PROPERTY_CONTENT,
+ CSS_PROPERTY_COUNTER_INCREMENT,
+ CSS_PROPERTY_COUNTER_RESET,
+ CSS_PROPERTY_CURSOR,
+ CSS_PROPERTY_DIRECTION,
+ CSS_PROPERTY_DISPLAY,
+ CSS_PROPERTY_EMPTY_CELLS,
+ CSS_PROPERTY_FLOAT,
+ CSS_PROPERTY_FONT_FAMILY,
+ CSS_PROPERTY_FONT_SIZE,
+ CSS_PROPERTY_FONT_SIZE_ADJUST,
+ CSS_PROPERTY_FONT_STRETCH,
+ CSS_PROPERTY_FONT_STYLE,
+ CSS_PROPERTY_FONT_VARIANT,
+ CSS_PROPERTY_FONT_WEIGHT,
+ CSS_PROPERTY_HEIGHT,
+ CSS_PROPERTY_LEFT,
+ CSS_PROPERTY_LETTER_SPACING,
+ CSS_PROPERTY_LINE_HEIGHT,
+ CSS_PROPERTY_LIST_STYLE_IMAGE,
+ CSS_PROPERTY_LIST_STYLE_POSITION,
+ CSS_PROPERTY_LIST_STYLE_TYPE,
+ CSS_PROPERTY_MARGIN_BOTTOM,
+ CSS_PROPERTY_MARGIN_LEFT,
+ CSS_PROPERTY_MARGIN_RIGHT,
+ CSS_PROPERTY_MARGIN_TOP,
+ CSS_PROPERTY_MARKER_OFFSET,
+ CSS_PROPERTY_MARKS,
+ CSS_PROPERTY_MAX_HEIGHT,
+ CSS_PROPERTY_MAX_WIDTH,
+ CSS_PROPERTY_MIN_HEIGHT,
+ CSS_PROPERTY_MIN_WIDTH,
+ CSS_PROPERTY_OUTLINE_COLOR,
+ CSS_PROPERTY_OUTLINE_STYLE,
+ CSS_PROPERTY_OUTLINE_WIDTH,
+ CSS_PROPERTY_OVERFLOW,
+ CSS_PROPERTY_PADDING_BOTTOM,
+ CSS_PROPERTY_PADDING_LEFT,
+ CSS_PROPERTY_PADDING_RIGHT,
+ CSS_PROPERTY_PADDING_TOP,
+ CSS_PROPERTY_POSITION,
+ CSS_PROPERTY_QUOTES,
+ CSS_PROPERTY_RIGHT,
+ CSS_PROPERTY_TEXT_ALIGN,
+ CSS_PROPERTY_TEXT_DECORATION,
+ CSS_PROPERTY_TEXT_INDENT,
+ CSS_PROPERTY_TEXT_SHADOW,
+ CSS_PROPERTY_TEXT_TRANSFORM,
+ CSS_PROPERTY_TOP,
+ CSS_PROPERTY_UNICODE_BIDI,
+ CSS_PROPERTY_VERTICAL_ALIGN,
+ CSS_PROPERTY_VISIBILITY,
+ CSS_PROPERTY_WHITE_SPACE,
+ CSS_PROPERTY_WIDTH,
+ CSS_PROPERTY_WORD_SPACING,
+ CSS_PROPERTY_Z_INDEX,
+ CSS_PROPERTY_X_LINK,
+ CSS_PROPERTY_X_COLSPAN,
+ CSS_PROPERTY_X_ROWSPAN,
+ PROPERTY_X_LINK,
+ PROPERTY_X_IMG,
+ PROPERTY_X_TOOLTIP,
+ CSS_PROPERTY_LAST
+ } Name;
+
+ typedef enum {
+ CSS_FONT_WEIGHT_LIGHTER = -1,
+ CSS_FONT_WEIGHT_BOLDER = -2,
+ CSS_FONT_WEIGHT_STEP = 300,
+ /* Some special font weights. */
+ CSS_FONT_WEIGHT_LIGHT = 100,
+ CSS_FONT_WEIGHT_NORMAL = 400,
+ CSS_FONT_WEIGHT_BOLD = 700,
+ CSS_FONT_WEIGHT_MIN = 100,
+ CSS_FONT_WEIGHT_MAX = 900,
+ } FontWeightExtensions;
+
+ Name name;
+ Value value;
+
+ void print ();
+};
+
+/**
+ * \brief A list of CssProperty objects.
+ */
+class CssPropertyList : public lout::misc::SimpleVector <CssProperty> {
+ int refCount;
+
+ public:
+ CssPropertyList() : lout::misc::SimpleVector <CssProperty> (1) {
+ refCount = 0;
+ };
+ CssPropertyList(const CssPropertyList &p) :
+ lout::misc::SimpleVector <CssProperty> (p) {
+ refCount = 0;
+ };
+
+ void set (CssProperty::Name name, CssProperty::Value value);
+ void set (CssProperty::Name name, const char *value) {
+ CssProperty::Value v;
+ v.strVal = value;
+ set (name, v);
+ };
+ void set (CssProperty::Name name, int value) {
+ CssProperty::Value v;
+ v.intVal = value;
+ set (name, v);
+ };
+ void apply (CssPropertyList *props);
+ void print ();
+ inline void ref () { refCount++; }
+ inline void unref () { if(--refCount == 0) delete this; }
+};
+
+class CssSimpleSelector {
+ public:
+ enum {
+ ELEMENT_NONE = -1,
+ ELEMENT_ANY = -2,
+ };
+
+ int element;
+ const char *klass, *pseudo, *id;
+
+ bool match (const DoctreeNode *node);
+ void print ();
+};
+
+/**
+ * \brief CSS selector class.
+ * \todo Implement missing selector options.
+ */
+class CssSelector {
+ public:
+ typedef enum {
+ DESCENDENT,
+ CHILD,
+ ADJACENT_SIBLING,
+ } Combinator;
+
+ private:
+ struct CombinatorAndSelector {
+ Combinator combinator;
+ CssSimpleSelector selector;
+ };
+
+ int refCount;
+ lout::misc::SimpleVector <struct CombinatorAndSelector> *selectorList;
+
+ public:
+ CssSelector (int element = CssSimpleSelector::ELEMENT_ANY,
+ const char *klass = NULL,
+ const char *pseudo = NULL, const char *id = NULL);
+ ~CssSelector ();
+ void addSimpleSelector (Combinator c,
+ int element = CssSimpleSelector::ELEMENT_ANY,
+ const char *klass = NULL,
+ const char *pseudo = NULL, const char *id=NULL);
+ inline CssSimpleSelector *top () {
+ return &selectorList->getRef (selectorList->size () - 1)->selector;
+ };
+
+ bool match (Doctree *dt);
+ void print ();
+ inline void ref () { refCount++; }
+ inline void unref () { if(--refCount == 0) delete this; }
+};
+
+/**
+ * \brief A CssSelector CssPropertyList pair.
+ * The CssPropertyList is applied if the CssSelector matches.
+ */
+class CssRule {
+ private:
+ int refCount;
+ CssPropertyList *props;
+
+ public:
+ CssSelector *selector;
+
+ CssRule (CssSelector *selector, CssPropertyList *props);
+ ~CssRule ();
+
+ void apply (CssPropertyList *props, Doctree *docTree);
+ inline void ref () { refCount++; }
+ inline void unref () { if(--refCount == 0) delete this; }
+ void print ();
+};
+
+/**
+ * \brief A list of CssRules.
+ * In apply () all matching rules are applied.
+ */
+class CssStyleSheet {
+ private:
+ static const int ntags = 90; // \todo replace 90
+ lout::misc::SimpleVector <CssRule*> *ruleTable[ntags];
+
+ public:
+ CssStyleSheet();
+ ~CssStyleSheet();
+ void addRule (CssRule *rule);
+ void addRule (CssSelector *selector, CssPropertyList *props);
+ void apply (CssPropertyList *props, Doctree *docTree);
+};
+
+/**
+ * \brief A set of CssStyleSheets.
+ */
+class CssContext {
+ private:
+ static CssStyleSheet *userAgentStyle;
+ static CssStyleSheet *userStyle;
+ static CssStyleSheet *userImportantStyle;
+ CssStyleSheet *sheet[CSS_PRIMARY_USER_IMPORTANT + 1];
+
+ void buildUserAgentStyle ();
+ void buildUserStyle ();
+
+ public:
+ CssContext ();
+ ~CssContext ();
+
+ void addRule (CssRule *rule, CssPrimaryOrder order);
+ void apply (CssPropertyList *props,
+ Doctree *docTree,
+ CssPropertyList *tagStyle, CssPropertyList *nonCssHints);
+};
+
+#endif
diff --git a/src/cssparser.cc b/src/cssparser.cc
new file mode 100644
index 00000000..809f6a0b
--- /dev/null
+++ b/src/cssparser.cc
@@ -0,0 +1,1154 @@
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "msg.h"
+#include "colors.h"
+#include "html_common.hh"
+#include "css.hh"
+#include "cssparser.hh"
+
+using namespace dw::core::style;
+
+#define DEBUG_MSG(A, B, ...) _MSG(B, __VA_ARGS__)
+#define MSG_CSS(A, ...) MSG(A, __VA_ARGS__)
+#define DEBUG_TOKEN_LEVEL 0
+#define DEBUG_PARSE_LEVEL 0
+#define DEBUG_CREATE_LEVEL 0
+
+#define DEBUG_LEVEL 10
+
+/* Applies to symbol lengths and string literals. */
+#define MAX_STR_LEN 256
+
+static const char *Css_border_style_enum_vals[] = {
+ "none", "hidden", "dotted", "dashed", "solid", "double", "groove",
+ "ridge", "inset", "outset", NULL
+};
+
+static const char *Css_cursor_enum_vals[] = {
+ "crosshair", "default", "pointer", "move", "e_resize", "ne_resize",
+ "nw_resize", "n_resize", "se_resize", "sw_resize", "s_resize",
+ "w_resize", "text", "wait", "help", NULL
+};
+
+static const char *Css_display_enum_vals[DISPLAY_LAST + 1] = {
+ "block", "inline", "list-item", "table", "table-row-group",
+ "table-header-group", "table-footer-group", "table-row",
+ "table-cell", NULL
+};
+
+static const char *Css_font_style_enum_vals[] = {
+ "normal", "italic", "oblique", NULL
+};
+
+static const char *Css_list_style_type_enum_vals[] = {
+ "disc", "circle", "square", "decimal", "decimal-leading-zero",
+ "lower-roman", "upper-roman", "lower-greek", "lower-alpha",
+ "lower-latin", "upper-alpha", "upper-latin", "hebrew", "armenian",
+ "georgian", "cjk-ideographic", "hiragana", "katakana", "hiragana-iroha",
+ "katakana-iroha", "none", NULL
+};
+
+static const char *Css_text_align_enum_vals[] = {
+ "left", "right", "center", "justify", "string", NULL
+};
+
+static const char *Css_text_decoration_enum_vals[] = {
+ "underline", "overline", "line-through", "blink", NULL
+};
+
+static const char *Css_vertical_align_vals[] = {
+ "top", "bottom", "middle", "baseline", "sub", "super", NULL
+};
+
+static const char *Css_white_space_vals[] = {
+ "normal", "pre", "nowrap", NULL
+};
+
+CssPropertyInfo Css_property_info[CssProperty::CSS_PROPERTY_LAST] = {
+ {"background-attachment", CSS_TYPE_UNUSED, NULL},
+ {"background-color", CSS_TYPE_COLOR, NULL},
+ {"background-image", CSS_TYPE_UNUSED, NULL},
+ {"background-position", CSS_TYPE_UNUSED, NULL},
+ {"background-repeat", CSS_TYPE_UNUSED, NULL},
+ {"border-bottom-color", CSS_TYPE_COLOR, NULL},
+ {"border-bottom-style", CSS_TYPE_ENUM, Css_border_style_enum_vals},
+ {"border-bottom-width", CSS_TYPE_LENGTH, NULL},
+ {"border-collapse", CSS_TYPE_UNUSED, NULL},
+ {"border-left-color", CSS_TYPE_COLOR, NULL},
+ {"border-left-style", CSS_TYPE_ENUM, Css_border_style_enum_vals},
+ {"border-left-width", CSS_TYPE_LENGTH, NULL},
+ {"border-right-color", CSS_TYPE_COLOR, NULL},
+ {"border-right-style", CSS_TYPE_ENUM, Css_border_style_enum_vals},
+ {"border-right-width", CSS_TYPE_LENGTH, NULL},
+ {"border-spacing", CSS_TYPE_LENGTH, NULL},
+ {"border-top-color", CSS_TYPE_COLOR, NULL},
+ {"border-top-style", CSS_TYPE_ENUM, Css_border_style_enum_vals},
+ {"border-top-width", CSS_TYPE_LENGTH, NULL},
+ {"bottom", CSS_TYPE_UNUSED, NULL},
+ {"caption-side", CSS_TYPE_UNUSED, NULL},
+ {"clear", CSS_TYPE_UNUSED, NULL},
+ {"clip", CSS_TYPE_UNUSED, NULL},
+ {"color", CSS_TYPE_COLOR, NULL},
+ {"content", CSS_TYPE_STRING, NULL},
+ {"counter-increment", CSS_TYPE_UNUSED, NULL},
+ {"counter-reset", CSS_TYPE_UNUSED, NULL},
+ {"cursor", CSS_TYPE_ENUM, Css_cursor_enum_vals},
+ {"direction", CSS_TYPE_UNUSED, NULL},
+ {"display", CSS_TYPE_ENUM, Css_display_enum_vals},
+ {"empty-cells", CSS_TYPE_UNUSED, NULL},
+ {"float", CSS_TYPE_UNUSED, NULL},
+ {"font-family", CSS_TYPE_SYMBOL, NULL},
+ {"font-size", CSS_TYPE_LENGTH_PERCENTAGE, NULL},
+ {"font-size-adjust", CSS_TYPE_UNUSED, NULL},
+ {"font-stretch", CSS_TYPE_UNUSED, NULL},
+ {"font-style", CSS_TYPE_ENUM, Css_font_style_enum_vals},
+ {"font-variant", CSS_TYPE_UNUSED, NULL},
+ {"font-weight", CSS_TYPE_FONT_WEIGHT, NULL},
+ {"height", CSS_TYPE_LENGTH_PERCENTAGE, NULL},
+ {"left", CSS_TYPE_UNUSED, NULL},
+ {"letter-spacing", CSS_TYPE_UNUSED, NULL},
+ {"line-height", CSS_TYPE_UNUSED, NULL},
+ {"list-style-image", CSS_TYPE_UNUSED, NULL},
+ {"list-style-position", CSS_TYPE_UNUSED, NULL},
+ {"list-style-type", CSS_TYPE_ENUM, Css_list_style_type_enum_vals},
+ {"margin-bottom", CSS_TYPE_LENGTH, NULL},
+ {"margin-left", CSS_TYPE_LENGTH, NULL},
+ {"margin-right", CSS_TYPE_LENGTH, NULL},
+ {"margin-top", CSS_TYPE_LENGTH, NULL},
+ {"marker-offset", CSS_TYPE_UNUSED, NULL},
+ {"marks", CSS_TYPE_UNUSED, NULL},
+ {"max-height", CSS_TYPE_UNUSED, NULL},
+ {"max-width", CSS_TYPE_UNUSED, NULL},
+ {"min-height", CSS_TYPE_UNUSED, NULL},
+ {"min-width", CSS_TYPE_UNUSED, NULL},
+ {"outline-color", CSS_TYPE_UNUSED, NULL},
+ {"outline-style", CSS_TYPE_UNUSED, NULL},
+ {"outline-width", CSS_TYPE_UNUSED, NULL},
+ {"overflow", CSS_TYPE_UNUSED, NULL},
+ {"padding-bottom", CSS_TYPE_LENGTH, NULL},
+ {"padding-left", CSS_TYPE_LENGTH, NULL},
+ {"padding-right", CSS_TYPE_LENGTH, NULL},
+ {"padding-top", CSS_TYPE_LENGTH, NULL},
+ {"position", CSS_TYPE_UNUSED, NULL},
+ {"quotes", CSS_TYPE_UNUSED, NULL},
+ {"right", CSS_TYPE_UNUSED, NULL},
+ {"text-align", CSS_TYPE_ENUM, Css_text_align_enum_vals},
+ {"text-decoration", CSS_TYPE_MULTI_ENUM, Css_text_decoration_enum_vals},
+ {"text-indent", CSS_TYPE_UNUSED, NULL},
+ {"text-shadow", CSS_TYPE_UNUSED, NULL},
+ {"text-transform", CSS_TYPE_UNUSED, NULL},
+ {"top", CSS_TYPE_UNUSED, NULL},
+ {"unicode-bidi", CSS_TYPE_UNUSED, NULL},
+ {"vertical-align", CSS_TYPE_ENUM, Css_vertical_align_vals},
+ {"visibility", CSS_TYPE_UNUSED, NULL},
+ {"white-space", CSS_TYPE_ENUM, Css_white_space_vals},
+ {"width", CSS_TYPE_LENGTH_PERCENTAGE, NULL},
+ {"word-spacing", CSS_TYPE_UNUSED, NULL},
+ {"z-index", CSS_TYPE_UNUSED, NULL},
+
+ /* These are extensions, for internal used, and never parsed. */
+ {"x-link", CSS_TYPE_INTEGER, NULL},
+ {"x-colspan", CSS_TYPE_INTEGER, NULL},
+ {"x-rowspan", CSS_TYPE_INTEGER, NULL},
+
+ {"last", CSS_TYPE_UNUSED, NULL},
+};
+
+#define CSS_SHORTHAND_NUM 14
+
+typedef struct {
+ const char *symbol;
+ enum {
+ CSS_SHORTHAND_MULTIPLE, /* [ p1 || p2 || ...], the property pi is
+ * determined by the type */
+ CSS_SHORTHAND_DIRECTIONS, /* <t>{1,4} */
+ CSS_SHORTHAND_BORDER, /* special, used for 'border' */
+ CSS_SHORTHAND_FONT, /* special, used for 'font' */
+ } type;
+ CssProperty::Name * properties; /* CSS_SHORTHAND_MULTIPLE:
+ * must be terminated by -1
+ * CSS_SHORTHAND_DIRECTIONS:
+ * must have length 4
+ * CSS_SHORTHAND_BORDERS:
+ * must have length 12
+ * CSS_SHORTHAND_FONT:
+ * unused */
+} CssShorthandInfo;
+
+CssProperty::Name Css_background_properties[] = {
+ CssProperty::CSS_PROPERTY_BACKGROUND_COLOR,
+ CssProperty::CSS_PROPERTY_BACKGROUND_IMAGE,
+ CssProperty::CSS_PROPERTY_BACKGROUND_REPEAT,
+ CssProperty::CSS_PROPERTY_BACKGROUND_ATTACHMENT,
+ CssProperty::CSS_PROPERTY_BACKGROUND_POSITION,
+ (CssProperty::Name) - 1
+};
+
+CssProperty::Name Css_border_bottom_properties[] = {
+ CssProperty::CSS_PROPERTY_BORDER_BOTTOM_WIDTH,
+ CssProperty::CSS_PROPERTY_BORDER_BOTTOM_STYLE,
+ CssProperty::CSS_PROPERTY_BORDER_BOTTOM_COLOR,
+ (CssProperty::Name) - 1
+};
+
+CssProperty::Name Css_border_color_properties[4] = {
+ CssProperty::CSS_PROPERTY_BORDER_TOP_COLOR,
+ CssProperty::CSS_PROPERTY_BORDER_BOTTOM_COLOR,
+ CssProperty::CSS_PROPERTY_BORDER_LEFT_COLOR,
+ CssProperty::CSS_PROPERTY_BORDER_RIGHT_COLOR
+};
+
+CssProperty::Name Css_border_left_properties[] = {
+ CssProperty::CSS_PROPERTY_BORDER_LEFT_WIDTH,
+ CssProperty::CSS_PROPERTY_BORDER_LEFT_STYLE,
+ CssProperty::CSS_PROPERTY_BORDER_LEFT_COLOR,
+ (CssProperty::Name) - 1
+};
+
+CssProperty::Name Css_border_right_properties[] = {
+ CssProperty::CSS_PROPERTY_BORDER_RIGHT_WIDTH,
+ CssProperty::CSS_PROPERTY_BORDER_RIGHT_STYLE,
+ CssProperty::CSS_PROPERTY_BORDER_RIGHT_COLOR,
+ (CssProperty::Name) - 1
+};
+
+CssProperty::Name Css_border_style_properties[4] = {
+ CssProperty::CSS_PROPERTY_BORDER_TOP_STYLE,
+ CssProperty::CSS_PROPERTY_BORDER_BOTTOM_STYLE,
+ CssProperty::CSS_PROPERTY_BORDER_LEFT_STYLE,
+ CssProperty::CSS_PROPERTY_BORDER_RIGHT_STYLE
+};
+
+CssProperty::Name Css_border_top_properties[] = {
+ CssProperty::CSS_PROPERTY_BORDER_TOP_WIDTH,
+ CssProperty::CSS_PROPERTY_BORDER_TOP_STYLE,
+ CssProperty::CSS_PROPERTY_BORDER_TOP_COLOR,
+ (CssProperty::Name) - 1
+};
+
+CssProperty::Name Css_border_width_properties[4] = {
+ CssProperty::CSS_PROPERTY_BORDER_TOP_WIDTH,
+ CssProperty::CSS_PROPERTY_BORDER_BOTTOM_WIDTH,
+ CssProperty::CSS_PROPERTY_BORDER_LEFT_WIDTH,
+ CssProperty::CSS_PROPERTY_BORDER_RIGHT_WIDTH
+};
+
+CssProperty::Name Css_list_style_properties[] = {
+ CssProperty::CSS_PROPERTY_LIST_STYLE_TYPE,
+ CssProperty::CSS_PROPERTY_LIST_STYLE_POSITION,
+ CssProperty::CSS_PROPERTY_LIST_STYLE_IMAGE,
+ (CssProperty::Name) - 1
+};
+
+CssProperty::Name Css_margin_properties[4] = {
+ CssProperty::CSS_PROPERTY_MARGIN_TOP,
+ CssProperty::CSS_PROPERTY_MARGIN_BOTTOM,
+ CssProperty::CSS_PROPERTY_MARGIN_LEFT,
+ CssProperty::CSS_PROPERTY_MARGIN_RIGHT
+};
+
+CssProperty::Name Css_outline_properties[] = {
+ CssProperty::CSS_PROPERTY_OUTLINE_COLOR,
+ CssProperty::CSS_PROPERTY_OUTLINE_STYLE,
+ CssProperty::CSS_PROPERTY_OUTLINE_WIDTH,
+ (CssProperty::Name) - 1
+};
+
+CssProperty::Name Css_padding_properties[4] = {
+ CssProperty::CSS_PROPERTY_PADDING_TOP,
+ CssProperty::CSS_PROPERTY_PADDING_BOTTOM,
+ CssProperty::CSS_PROPERTY_PADDING_LEFT,
+ CssProperty::CSS_PROPERTY_PADDING_RIGHT
+};
+
+CssProperty::Name Css_border_properties[12] = {
+ CssProperty::CSS_PROPERTY_BORDER_TOP_WIDTH,
+ CssProperty::CSS_PROPERTY_BORDER_TOP_STYLE,
+ CssProperty::CSS_PROPERTY_BORDER_TOP_COLOR,
+ CssProperty::CSS_PROPERTY_BORDER_BOTTOM_WIDTH,
+ CssProperty::CSS_PROPERTY_BORDER_BOTTOM_STYLE,
+ CssProperty::CSS_PROPERTY_BORDER_BOTTOM_COLOR,
+ CssProperty::CSS_PROPERTY_BORDER_LEFT_WIDTH,
+ CssProperty::CSS_PROPERTY_BORDER_LEFT_STYLE,
+ CssProperty::CSS_PROPERTY_BORDER_LEFT_COLOR,
+ CssProperty::CSS_PROPERTY_BORDER_RIGHT_WIDTH,
+ CssProperty::CSS_PROPERTY_BORDER_RIGHT_STYLE,
+ CssProperty::CSS_PROPERTY_BORDER_RIGHT_COLOR
+};
+
+static CssShorthandInfo Css_shorthand_info[CSS_SHORTHAND_NUM] = {
+ {"background", CssShorthandInfo::CSS_SHORTHAND_MULTIPLE,
+ Css_background_properties},
+ {"border", CssShorthandInfo::CSS_SHORTHAND_BORDER,
+ Css_border_properties},
+ {"border-bottom", CssShorthandInfo::CSS_SHORTHAND_MULTIPLE,
+ Css_border_bottom_properties},
+ {"border-color", CssShorthandInfo::CSS_SHORTHAND_DIRECTIONS,
+ Css_border_color_properties},
+ {"border-left", CssShorthandInfo::CSS_SHORTHAND_MULTIPLE,
+ Css_border_left_properties},
+ {"border-right", CssShorthandInfo::CSS_SHORTHAND_MULTIPLE,
+ Css_border_right_properties},
+ {"border-style", CssShorthandInfo::CSS_SHORTHAND_DIRECTIONS,
+ Css_border_style_properties},
+ {"border-top", CssShorthandInfo::CSS_SHORTHAND_MULTIPLE,
+ Css_border_top_properties},
+ {"border-width", CssShorthandInfo::CSS_SHORTHAND_DIRECTIONS,
+ Css_border_width_properties},
+ {"font", CssShorthandInfo::CSS_SHORTHAND_FONT, NULL},
+ {"list-style", CssShorthandInfo::CSS_SHORTHAND_MULTIPLE,
+ Css_list_style_properties},
+ {"margin", CssShorthandInfo::CSS_SHORTHAND_DIRECTIONS,
+ Css_margin_properties},
+ {"outline", CssShorthandInfo::CSS_SHORTHAND_MULTIPLE,
+ Css_outline_properties},
+ {"padding", CssShorthandInfo::CSS_SHORTHAND_DIRECTIONS,
+ Css_padding_properties},
+};
+
+/* ----------------------------------------------------------------------
+ * Initialization, Cleanup
+ * ---------------------------------------------------------------------- */
+
+static int values_num;
+
+void a_Css_init(void)
+{
+ values_num = 0;
+}
+
+void a_Css_freeall(void)
+{
+ if (values_num)
+ fprintf(stderr, "%d CSS values left", values_num);
+}
+
+/* ----------------------------------------------------------------------
+ * Parsing
+ * ---------------------------------------------------------------------- */
+
+typedef enum {
+ CSS_TK_DECINT, CSS_TK_FLOAT, CSS_TK_COLOR, CSS_TK_SYMBOL, CSS_TK_STRING,
+ CSS_TK_CHAR, CSS_TK_END
+} CssTokenType;
+
+typedef struct {
+ CssContext *context;
+ int order_count;
+ CssOrigin origin;
+
+ const char *buf;
+ int buflen, bufptr;
+
+ CssTokenType ttype;
+ char tval[MAX_STR_LEN];
+ bool within_block;
+ bool space_separated; /* used when parsing CSS selectors */
+} CssParser;
+
+/*
+ * Gets the next character from the buffer, or EOF.
+ */
+static int Css_getc(CssParser * parser)
+{
+ int c;
+
+ if (parser->bufptr >= parser->buflen)
+ c = EOF;
+ else
+ c = parser->buf[parser->bufptr];
+
+ /* The buffer pointer is increased in any case, so that Css_ungetc works
+ * correctly at the end of the buffer. */
+ parser->bufptr++;
+ return c;
+}
+
+/*
+ * Undoes the last Css_getc().
+ */
+static void Css_ungetc(CssParser * parser)
+{
+ parser->bufptr--;
+}
+
+static void Css_next_token(CssParser * parser)
+{
+ int c, c1, d, i, j;
+ bool point_allowed;
+ char hexbuf[5];
+ bool escaped;
+
+ parser->space_separated = false;
+
+ c = Css_getc(parser);
+
+ while (true) {
+ if (isspace(c)) { // ignore whitespace
+ parser->space_separated = true;
+ c = Css_getc(parser);
+ } else if (c == '/') { // ignore comments
+ d = Css_getc(parser);
+ if (d == '*') {
+ c = Css_getc(parser);
+ d = Css_getc(parser);
+ while (d != EOF && (c != '*' || d != '/')) {
+ c = d;
+ d = Css_getc(parser);
+ }
+ c = Css_getc(parser);
+ } else {
+ Css_ungetc(parser);
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+
+ if (isdigit(c)) {
+ parser->ttype = CSS_TK_DECINT;
+ point_allowed = true;
+
+ parser->tval[0] = c;
+ i = 1;
+ c = Css_getc(parser);
+ while (isdigit(c) || (point_allowed && c == '.')) {
+ if (c == '.') {
+ parser->ttype = CSS_TK_FLOAT;
+ point_allowed = false; /* Only one point read. */
+ }
+
+ if (i < MAX_STR_LEN - 1) {
+ parser->tval[i] = c;
+ i++;
+ }
+ /* else silently truncated */
+ c = Css_getc(parser);
+ }
+ parser->tval[i] = 0;
+ Css_ungetc(parser);
+
+ DEBUG_MSG(DEBUG_TOKEN_LEVEL, "token number %s\n", parser->tval);
+ return;
+ }
+
+ if (isalpha(c) || c == '_' || c == '-') {
+ parser->ttype = CSS_TK_SYMBOL;
+
+ parser->tval[0] = c;
+ i = 1;
+ c = Css_getc(parser);
+ while (isalnum(c) || c == '_' || c == '-') {
+ if (i < MAX_STR_LEN - 1) {
+ parser->tval[i] = c;
+ i++;
+ } /* else silently truncated */
+ c = Css_getc(parser);
+ }
+ parser->tval[i] = 0;
+ Css_ungetc(parser);
+ DEBUG_MSG(DEBUG_TOKEN_LEVEL, "token symbol '%s'\n", parser->tval);
+ return;
+ }
+
+ if (c == '"' || c == '\'') {
+ c1 = c;
+ parser->ttype = CSS_TK_STRING;
+
+ i = 0;
+ c = Css_getc(parser);
+ escaped = false;
+
+ while (c != EOF && (escaped || c != c1)) {
+ if (c == '\\') {
+ escaped = true;
+ d = Css_getc(parser);
+ if (isxdigit(d)) {
+ /* Read hex Unicode char. (Actually, strings are yet only 8
+ * bit.) */
+ hexbuf[0] = d;
+ j = 1;
+ d = Css_getc(parser);
+ while (j < 4 && isxdigit(d)) {
+ hexbuf[j] = d;
+ j++;
+ d = Css_getc(parser);
+ }
+ hexbuf[j] = 0;
+ Css_ungetc(parser);
+ c = strtol(hexbuf, NULL, 16);
+ } else
+ /* Take next character literally. */
+ c = Css_getc(parser);
+ } else
+ escaped = false;
+
+ if (i < MAX_STR_LEN - 1) {
+ parser->tval[i] = c;
+ i++;
+ } /* else silently truncated */
+ c = Css_getc(parser);
+ }
+ parser->tval[i] = 0;
+ /* No Css_ungetc(). */
+ DEBUG_MSG(DEBUG_TOKEN_LEVEL, "token string '%s'\n", parser->tval);
+ return;
+ }
+
+ /*
+ * Within blocks, '#' starts a color, outside, it is used in selectors.
+ */
+ if (c == '#' && parser->within_block) {
+ parser->ttype = CSS_TK_COLOR;
+
+ parser->tval[0] = c;
+ i = 1;
+ c = Css_getc(parser);
+ while (isxdigit(c)) {
+ if (i < MAX_STR_LEN - 1) {
+ parser->tval[i] = c;
+ i++;
+ } /* else silently truncated */
+ c = Css_getc(parser);
+ }
+ parser->tval[i] = 0;
+ Css_ungetc(parser);
+ DEBUG_MSG(DEBUG_TOKEN_LEVEL, "token color '%s'\n", parser->tval);
+ return;
+ }
+
+ if (c == EOF) {
+ DEBUG_MSG(DEBUG_TOKEN_LEVEL, "token %s\n", "EOF");
+ parser->ttype = CSS_TK_END;
+ return;
+ }
+
+ parser->ttype = CSS_TK_CHAR;
+ parser->tval[0] = c;
+ parser->tval[1] = 0;
+ DEBUG_MSG(DEBUG_TOKEN_LEVEL, "token char '%c'\n", c);
+}
+
+
+static bool Css_token_matches_property(CssParser * parser,
+ CssProperty::Name prop)
+{
+ int i, err = 1;
+
+ switch (Css_property_info[prop].type) {
+ case CSS_TYPE_ENUM:
+ if (parser->ttype == CSS_TK_SYMBOL) {
+ for (i = 0; Css_property_info[prop].enum_symbols[i]; i++)
+ if (strcmp(parser->tval,
+ Css_property_info[prop].enum_symbols[i]) == 0)
+ return true;
+ }
+ return false;
+
+ case CSS_TYPE_MULTI_ENUM:
+ if (parser->ttype == CSS_TK_SYMBOL) {
+ if (strcmp(parser->tval, "none") != 0)
+ return true;
+ else {
+ for (i = 0; Css_property_info[prop].enum_symbols[i]; i++) {
+ if (strcmp(parser->tval,
+ Css_property_info[prop].enum_symbols[i]) == 0)
+ return true;
+ }
+ }
+ }
+ return true;
+
+ case CSS_TYPE_LENGTH_PERCENTAGE:
+ case CSS_TYPE_LENGTH:
+ return parser->ttype == CSS_TK_DECINT ||
+ parser->ttype == CSS_TK_FLOAT || (parser->ttype == CSS_TK_SYMBOL
+ && strcmp(parser->tval,
+ "auto") == 0);
+
+ case CSS_TYPE_COLOR:
+ return (parser->ttype == CSS_TK_COLOR ||
+ parser->ttype == CSS_TK_SYMBOL) &&
+ a_Color_parse(parser->tval, -1, &err) != -1;
+
+ case CSS_TYPE_STRING:
+ return parser->ttype == CSS_TK_STRING;
+
+ case CSS_TYPE_SYMBOL:
+ return parser->ttype == CSS_TK_SYMBOL;
+
+ case CSS_TYPE_FONT_WEIGHT:
+ if (parser->ttype == CSS_TK_DECINT) {
+ i = atoi(parser->tval);
+ return i >= 100 && i <= 900;
+ } else
+ return (parser->ttype == CSS_TK_SYMBOL &&
+ (strcmp(parser->tval, "normal") == 0 ||
+ strcmp(parser->tval, "bold") == 0 ||
+ strcmp(parser->tval, "bolder") == 0 ||
+ strcmp(parser->tval, "lighter") == 0));
+ break;
+
+ case CSS_TYPE_UNUSED:
+ return false;
+
+ case CSS_TYPE_INTEGER:
+ /* Not used for parser values. */
+ default:
+ assert(false);
+ return false;
+ }
+}
+
+static bool Css_parse_value(CssParser * parser,
+ CssProperty::Name prop,
+ CssProperty::Value * val)
+{
+ int i, lentype;
+ bool found, ret = false;
+ float fval;
+ int ival, err = 1;
+
+ switch (Css_property_info[prop].type) {
+ case CSS_TYPE_ENUM:
+ if (parser->ttype == CSS_TK_SYMBOL) {
+ for (i = 0; Css_property_info[prop].enum_symbols[i]; i++)
+ if (strcmp(parser->tval,
+ Css_property_info[prop].enum_symbols[i]) == 0) {
+ val->intVal = i;
+ ret = true;
+ break;
+ }
+ Css_next_token(parser);
+ }
+ break;
+
+ case CSS_TYPE_MULTI_ENUM:
+ val->intVal = 0;
+ ret = true;
+
+ while (parser->ttype == CSS_TK_SYMBOL) {
+ if (strcmp(parser->tval, "none") != 0) {
+ for (i = 0, found = false;
+ !found && Css_property_info[prop].enum_symbols[i]; i++) {
+ if (strcmp(parser->tval,
+ Css_property_info[prop].enum_symbols[i]) == 0)
+ val->intVal |= (1 << i);
+ }
+ }
+ Css_next_token(parser);
+ }
+ break;
+
+ case CSS_TYPE_LENGTH_PERCENTAGE:
+ case CSS_TYPE_LENGTH:
+ if (parser->ttype == CSS_TK_DECINT || parser->ttype == CSS_TK_FLOAT) {
+ fval = atof(parser->tval);
+ lentype = CSS_LENGTH_TYPE_PX; /* Actually, there must be a unit,
+ * except for num == 0. */
+
+ ret = true;
+
+ Css_next_token(parser);
+ if (parser->ttype == CSS_TK_SYMBOL) {
+ if (strcmp(parser->tval, "px") == 0) {
+ lentype = CSS_LENGTH_TYPE_PX;
+ Css_next_token(parser);
+ } else if (strcmp(parser->tval, "mm") == 0) {
+ lentype = CSS_LENGTH_TYPE_MM;
+ Css_next_token(parser);
+ } else if (strcmp(parser->tval, "cm") == 0) {
+ lentype = CSS_LENGTH_TYPE_MM;
+ fval *= 10;
+ Css_next_token(parser);
+ } else if (strcmp(parser->tval, "in") == 0) {
+ lentype = CSS_LENGTH_TYPE_MM;
+ fval *= 25.4;
+ Css_next_token(parser);
+ } else if (strcmp(parser->tval, "pt") == 0) {
+ lentype = CSS_LENGTH_TYPE_MM;
+ fval *= (25.4 / 72);
+ Css_next_token(parser);
+ } else if (strcmp(parser->tval, "pc") == 0) {
+ lentype = CSS_LENGTH_TYPE_MM;
+ fval *= (25.4 / 6);
+ Css_next_token(parser);
+ } else if (strcmp(parser->tval, "em") == 0) {
+ lentype = CSS_LENGTH_TYPE_EM;
+ Css_next_token(parser);
+ } else if (strcmp(parser->tval, "ex") == 0) {
+ lentype = CSS_LENGTH_TYPE_EX;
+ Css_next_token(parser);
+ }
+ } else if (Css_property_info[prop].type ==
+ CSS_TYPE_LENGTH_PERCENTAGE &&
+ parser->ttype == CSS_TK_CHAR &&
+ parser->tval[0] == '%') {
+ fval /= 100;
+ lentype = CSS_LENGTH_TYPE_PERCENTAGE;
+ Css_next_token(parser);
+ }
+
+ val->intVal = CSS_CREATE_LENGTH(fval, lentype);
+ } else if (parser->ttype == CSS_TK_SYMBOL &&
+ strcmp(parser->tval, "auto") == 0) {
+ val->intVal = CSS_LENGTH_TYPE_AUTO;
+ }
+ break;
+
+ case CSS_TYPE_COLOR:
+ if (parser->ttype == CSS_TK_COLOR) {
+ val->intVal = a_Color_parse(parser->tval, -1, &err);
+ if (err)
+ MSG_CSS("color is not in \"%s\" format\n", "#RRGGBB");
+ else
+ ret = true;
+ Css_next_token(parser);
+ } else if (parser->ttype == CSS_TK_SYMBOL) {
+ val->intVal = a_Color_parse(parser->tval, -1, &err);
+ if (err)
+ MSG_CSS("color is not in \"%s\" format\n", "#RRGGBB");
+ else
+ ret = true;
+ Css_next_token(parser);
+ }
+ break;
+
+ case CSS_TYPE_STRING:
+ if (parser->ttype == CSS_TK_STRING) {
+ val->strVal = dStrdup(parser->tval);
+ Css_next_token(parser);
+ }
+ break;
+
+ case CSS_TYPE_SYMBOL:
+ if (parser->ttype == CSS_TK_SYMBOL) {
+ val->strVal = dStrdup(parser->tval);
+ ret = true;
+ Css_next_token(parser);
+ }
+ break;
+
+ case CSS_TYPE_FONT_WEIGHT:
+ ival = 0;
+ if (parser->ttype == CSS_TK_DECINT) {
+ ival = atoi(parser->tval);
+ if (ival < 100 || ival > 900)
+ /* invalid */
+ ival = 0;
+ } else if (parser->ttype == CSS_TK_SYMBOL) {
+ if (strcmp(parser->tval, "normal") == 0)
+ ival = CssProperty::CSS_FONT_WEIGHT_NORMAL;
+ if (strcmp(parser->tval, "bold") == 0)
+ ival = CssProperty::CSS_FONT_WEIGHT_BOLD;
+ if (strcmp(parser->tval, "bolder") == 0)
+ ival = CssProperty::CSS_FONT_WEIGHT_BOLDER;
+ if (strcmp(parser->tval, "lighter") == 0)
+ ival = CssProperty::CSS_FONT_WEIGHT_LIGHTER;
+ }
+
+ if (ival != 0) {
+ val->intVal = ival;
+ ret = true;
+ Css_next_token(parser);
+ }
+ break;
+
+ case CSS_TYPE_UNUSED:
+ /* nothing */
+ break;
+
+ case CSS_TYPE_INTEGER:
+ /* Not used for parser values. */
+ default:
+ assert(false); /* not reached */
+ }
+
+ return ret;
+}
+
+static bool Css_parse_weight(CssParser * parser)
+{
+ if (parser->ttype == CSS_TK_CHAR && parser->tval[0] == '!') {
+ Css_next_token(parser);
+ if (parser->ttype == CSS_TK_SYMBOL &&
+ strcmp(parser->tval, "important") == 0) {
+ Css_next_token(parser);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/*
+ * bsearch(3) compare function for searching properties
+ */
+static int Css_property_info_cmp(const void *a, const void *b)
+{
+ return strcmp(((CssPropertyInfo *) a)->symbol,
+ ((CssPropertyInfo *) b)->symbol);
+}
+
+
+/*
+ * bsearch(3) compare function for searching shorthands
+ */
+static int Css_shorthand_info_cmp(const void *a, const void *b)
+{
+ return strcmp(((CssShorthandInfo *) a)->symbol,
+ ((CssShorthandInfo *) b)->symbol);
+}
+
+static void Css_parse_declaration(CssParser * parser,
+ CssPropertyList * props,
+ CssPropertyList * importantProps)
+{
+ CssPropertyInfo pi, *pip;
+ CssShorthandInfo si, *sip;
+
+ CssProperty::Name prop;
+ CssProperty::Value val, dir_vals[4];
+ bool found, weight;
+ int sh_index, i, j, n;
+ int dir_set[4][4] = {
+ /* 1 value */ {0, 0, 0, 0},
+ /* 2 values */ {0, 0, 1, 1},
+ /* 3 values */ {0, 2, 1, 1},
+ /* 4 values */ {0, 2, 3, 1}
+ };
+
+ if (parser->ttype == CSS_TK_SYMBOL) {
+ pi.symbol = parser->tval;
+ pip =
+ (CssPropertyInfo *) bsearch(&pi, Css_property_info,
+ CSS_NUM_PARSED_PROPERTIES,
+ sizeof(CssPropertyInfo),
+ Css_property_info_cmp);
+ if (pip) {
+ prop = (CssProperty::Name) (pip - Css_property_info);
+ Css_next_token(parser);
+ if (parser->ttype == CSS_TK_CHAR && parser->tval[0] == ':') {
+ Css_next_token(parser);
+ if (Css_parse_value(parser, prop, &val)) {
+ weight = Css_parse_weight(parser);
+ if (weight)
+ importantProps->set(prop, val);
+ else
+ props->set(prop, val);
+ }
+ }
+ } else {
+ /* Try shorthands. */
+ si.symbol = parser->tval;
+ sip =
+ (CssShorthandInfo *) bsearch(&pi, Css_shorthand_info,
+ CSS_SHORTHAND_NUM,
+ sizeof(CssShorthandInfo),
+ Css_shorthand_info_cmp);
+ if (sip) {
+ sh_index = sip - Css_shorthand_info;
+ Css_next_token(parser);
+ if (parser->ttype == CSS_TK_CHAR && parser->tval[0] == ':') {
+ Css_next_token(parser);
+
+ switch (Css_shorthand_info[sh_index].type) {
+ case CssShorthandInfo::CSS_SHORTHAND_MULTIPLE:
+ do {
+ for (found = false, i = 0;
+ !found &&
+ Css_shorthand_info[sh_index].properties[i] != -1;
+ i++)
+ if (Css_token_matches_property(parser,
+ Css_shorthand_info
+ [sh_index].
+ properties[i])) {
+ found = true;
+ DEBUG_MSG(DEBUG_PARSE_LEVEL,
+ "will assign to '%s'\n",
+ Css_property_info
+ [Css_shorthand_info[sh_index]
+ .properties[i]].symbol);
+ if (Css_parse_value(parser,
+ Css_shorthand_info[sh_index]
+ .properties[i], &val)) {
+ weight = Css_parse_weight(parser);
+ if (weight)
+ importantProps->
+ set(Css_shorthand_info[sh_index].
+ properties[i], val);
+ else
+ props->set(Css_shorthand_info[sh_index].
+ properties[i], val);
+ }
+ }
+ } while (found);
+ break;
+
+ case CssShorthandInfo::CSS_SHORTHAND_DIRECTIONS:
+ n = 0;
+ while (n < 4) {
+ if (Css_token_matches_property(parser,
+ Css_shorthand_info
+ [sh_index].
+ properties[0]) &&
+ Css_parse_value(parser,
+ Css_shorthand_info[sh_index]
+ .properties[0], &val)) {
+ dir_vals[n] = val;
+ n++;
+ } else
+ break;
+ }
+
+ weight = Css_parse_weight(parser);
+ if (n > 0) {
+ for (i = 0; i < 4; i++)
+ if (weight)
+ importantProps->set(Css_shorthand_info[sh_index]
+ .properties[i],
+ dir_vals[dir_set[n - 1]
+ [i]]);
+ else
+ props->set(Css_shorthand_info[sh_index]
+ .properties[i],
+ dir_vals[dir_set[n - 1][i]]);
+ } else
+ MSG_CSS("no values for shorthand property '%s'\n",
+ Css_shorthand_info[sh_index].symbol);
+
+ break;
+
+ case CssShorthandInfo::CSS_SHORTHAND_BORDER:
+ do {
+ for (found = false, i = 0;
+ !found && i < 3;
+ i++)
+ if (Css_token_matches_property(parser,
+ Css_shorthand_info
+ [sh_index].
+ properties[i])) {
+ found = true;
+ if (Css_parse_value(parser,
+ Css_shorthand_info[sh_index]
+ .properties[i], &val)) {
+ weight = Css_parse_weight(parser);
+ for (j = 0; j < 4; j++)
+ if (weight)
+ importantProps->
+ set(Css_shorthand_info[sh_index].
+ properties[j * 3 + i], val);
+ else
+ props->set(Css_shorthand_info[sh_index].
+ properties[j * 3 + i], val);
+ }
+ }
+ } while (found);
+ break;
+
+ case CssShorthandInfo::CSS_SHORTHAND_FONT:
+ /* todo: Not yet implemented. */
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ /* Skip all tokens until the expected end. */
+ while (!(parser->ttype == CSS_TK_END ||
+ (parser->ttype == CSS_TK_CHAR &&
+ (parser->tval[0] == ';' || parser->tval[0] == '}'))))
+ Css_next_token(parser);
+
+ if (parser->ttype == CSS_TK_CHAR && parser->tval[0] == ';')
+ Css_next_token(parser);
+}
+
+static bool Css_parse_simple_selector(CssParser * parser,
+ CssSimpleSelector *selector) {
+ const char *p, **pp;
+
+ if (parser->ttype == CSS_TK_SYMBOL) {
+ selector->element = a_Html_tag_index(parser->tval);
+ Css_next_token(parser);
+ if (parser->space_separated)
+ return true;
+ } else if (parser->ttype == CSS_TK_CHAR && parser->tval[0] == '*') {
+ selector->element = CssSimpleSelector::ELEMENT_ANY;
+ Css_next_token(parser);
+ if (parser->space_separated)
+ return true;
+ } else if (parser->ttype == CSS_TK_CHAR && parser->tval[0] != '#' &&
+ parser->tval[0] != '.' && parser->tval[0] != ':') {
+ return false;
+ }
+
+ do {
+ pp = NULL;
+ if (parser->ttype == CSS_TK_CHAR) {
+ switch (parser->tval[0]) {
+ case '#':
+ pp = &selector->id;
+ break;
+ case '.':
+ pp = &selector->klass;
+ break;
+ case ':':
+ pp = &selector->pseudo;
+ break;
+ }
+ }
+
+ if (pp) {
+ Css_next_token(parser);
+ if (parser->space_separated)
+ return true;
+
+ if (parser->ttype == CSS_TK_SYMBOL ||
+ parser->ttype == CSS_TK_DECINT) {
+ if (*pp == NULL)
+ *pp = dStrdup(parser->tval);
+ Css_next_token(parser);
+ } else if (parser->ttype == CSS_TK_FLOAT) {
+ /* In this case, we are actually interested in three tokens:
+ * number, '.', number. Instead, we have a decimal fraction,
+ * which we split up again. */
+ p = strchr(parser->tval, '.');
+ if (*pp == NULL)
+ *pp = dStrndup(parser->tval, p - parser->tval);
+ if (selector->klass == NULL)
+ selector->klass = dStrdup(p + 1);
+ Css_next_token(parser);
+ }
+ if (parser->space_separated)
+ return true;
+ }
+ } while (pp);
+
+ DEBUG_MSG(DEBUG_PARSE_LEVEL, "end of simple selector (%s, %s, %s, %d)\n",
+ selector->id, selector->klass,
+ selector->pseudo, selector->element);
+
+ return true;
+}
+
+static CssSelector *Css_parse_selector(CssParser * parser) {
+ CssSelector *selector = new CssSelector ();
+
+ while (true) {
+ if (! Css_parse_simple_selector (parser, selector->top ()))
+ Css_next_token(parser); /* make sure we advance at least one token */
+
+ if (parser->ttype == CSS_TK_CHAR &&
+ (parser->tval[0] == ',' || parser->tval[0] == '{')) {
+ return selector;
+ } else if (parser->ttype == CSS_TK_CHAR && parser->tval[0] == '>') {
+ selector->addSimpleSelector (CssSelector::CHILD);
+ Css_next_token(parser);
+ } else if (parser->ttype != CSS_TK_END && parser->space_separated) {
+ selector->addSimpleSelector (CssSelector::DESCENDENT);
+ } else {
+ delete selector;
+ return NULL;
+ }
+ }
+
+ return selector;
+}
+
+static void Css_parse_ruleset(CssParser * parser)
+{
+ lout::misc::SimpleVector < CssSelector * >*list;
+ CssPropertyList *props, *importantProps;
+ CssSelector *selector;
+
+ list = new lout::misc::SimpleVector < CssSelector * >(1);
+
+ while (true) {
+ selector = Css_parse_selector(parser);
+
+ if (selector) {
+ selector->ref();
+ list->increase();
+ list->set(list->size() - 1, selector);
+ }
+
+ if (parser->ttype == CSS_TK_CHAR && parser->tval[0] == ',')
+ /* To read the next token. */
+ Css_next_token(parser);
+ else
+ /* No more selectors. */
+ break;
+ }
+
+ DEBUG_MSG(DEBUG_PARSE_LEVEL, "end of %s\n", "selectors");
+
+ props = new CssPropertyList();
+ props->ref();
+ importantProps = new CssPropertyList();
+ importantProps->ref();
+
+ /* Read block. ('{' has already been read.) */
+ if (parser->ttype != CSS_TK_END) {
+ parser->within_block = true;
+ Css_next_token(parser);
+ do
+ Css_parse_declaration(parser, props, importantProps);
+ while (!(parser->ttype == CSS_TK_END ||
+ (parser->ttype == CSS_TK_CHAR && parser->tval[0] == '}')));
+ parser->within_block = false;
+ }
+
+ for (int i = 0; i < list->size(); i++) {
+ CssSelector *s = list->get(i);
+
+ if (parser->origin == CSS_ORIGIN_USER_AGENT) {
+ parser->context->addRule(new CssRule(s, props),
+ CSS_PRIMARY_USER_AGENT);
+ } else if (parser->origin == CSS_ORIGIN_USER) {
+ parser->context->addRule(new CssRule(s, props), CSS_PRIMARY_USER);
+ parser->context->addRule(new CssRule(s, importantProps),
+ CSS_PRIMARY_USER_IMPORTANT);
+ } else if (parser->origin == CSS_ORIGIN_AUTHOR) {
+ parser->context->addRule(new CssRule(s, props),
+ CSS_PRIMARY_AUTHOR);
+ parser->context->addRule(new CssRule(s, importantProps),
+ CSS_PRIMARY_AUTHOR_IMPORTANT);
+ }
+
+ s->unref();
+ }
+
+ props->unref();
+ importantProps->unref();
+
+ delete list;
+
+ if (parser->ttype == CSS_TK_CHAR && parser->tval[0] == '}')
+ Css_next_token(parser);
+}
+
+void a_Css_parse(CssContext * context,
+ const char *buf,
+ int buflen, int order_count, CssOrigin origin)
+{
+ CssParser parser;
+
+ parser.context = context;
+ parser.buf = buf;
+ parser.buflen = buflen;
+ parser.bufptr = 0;
+ parser.order_count = 0;
+ parser.origin = origin;
+ parser.within_block = false;
+ parser.space_separated = false;
+
+ Css_next_token(&parser);
+ while (parser.ttype != CSS_TK_END)
+ Css_parse_ruleset(&parser);
+}
diff --git a/src/cssparser.hh b/src/cssparser.hh
new file mode 100644
index 00000000..6638496d
--- /dev/null
+++ b/src/cssparser.hh
@@ -0,0 +1,63 @@
+#ifndef __CSSPARSER_HH__
+#define __CSSPARSER_HH__
+
+#include "css.hh"
+
+/* The last three ones are never parsed. */
+#define CSS_NUM_INTERNAL_PROPERTIES 3
+#define CSS_NUM_PARSED_PROPERTIES \
+ (CssProperty::CSS_PROPERTY_LAST - CSS_NUM_INTERNAL_PROPERTIES)
+
+
+typedef enum {
+ CSS_TYPE_INTEGER, /* This type is only used internally, for x-*
+ properties. */
+ CSS_TYPE_ENUM, /* Value is i, if represented by
+ enum_symbols[i]. */
+ CSS_TYPE_MULTI_ENUM, /* For all enum_symbols[i], 1 << i are
+ combined. */
+ CSS_TYPE_LENGTH_PERCENTAGE, /* <length> or <percentage>. Represented by
+ CssLength. */
+ CSS_TYPE_LENGTH, /* <length>, represented as CssLength.
+ Note: In some cases, CSS_TYPE_LENGTH is used
+ instead of CSS_TYPE_LENGTH_PERCENTAGE,
+ only because Dw cannot handle percentages
+ in this particular case (e.g.
+ 'margin-*-width'). */
+ CSS_TYPE_COLOR, /* Represented as integer. */
+ CSS_TYPE_FONT_WEIGHT, /* this very special and only used by
+ 'font-weight' */
+ CSS_TYPE_STRING, /* <string> */
+ CSS_TYPE_SYMBOL, /* Symbols, which are directly copied (as
+ opposed to CSS_TYPE_ENUM and
+ CSS_TYPE_MULTI_ENUM). Used for
+ 'font-family'. */
+ CSS_TYPE_UNUSED /* Not yet used. Will itself get unused some
+ day. */
+} CssValueType;
+
+typedef enum {
+ CSS_ORIGIN_USER_AGENT,
+ CSS_ORIGIN_USER,
+ CSS_ORIGIN_AUTHOR,
+} CssOrigin;
+
+typedef struct {
+ const char *symbol;
+ CssValueType type;
+ const char **enum_symbols;
+} CssPropertyInfo;
+
+
+void a_Css_init (void);
+void a_Css_freeall (void);
+
+void a_Css_parse (CssContext *context,
+ const char *buf,
+ int buflen,
+ int order_count,
+ CssOrigin origin);
+
+extern CssPropertyInfo Css_property_info[CssProperty::CSS_PROPERTY_LAST];
+
+#endif // __CSS_H__
diff --git a/src/dicache.c b/src/dicache.c
index fb1a0c8c..424fc87f 100644
--- a/src/dicache.c
+++ b/src/dicache.c
@@ -14,7 +14,9 @@
#include <stdio.h>
#include <stdlib.h>
+#include "msg.h"
#include "image.hh"
+#include "imgbuf.hh"
#include "web.hh"
#include "dicache.h"
#include "cache.h"
@@ -78,7 +80,6 @@ static DICacheEntry *Dicache_entry_new(void)
entry->height = 0;
entry->type = DILLO_IMG_TYPE_NOTSET;
entry->cmap = NULL;
- entry->linebuf = NULL;
entry->v_imgbuf = NULL;
entry->RefCount = 1;
entry->TotalSize = 0;
@@ -86,7 +87,11 @@ static DICacheEntry *Dicache_entry_new(void)
entry->ScanNumber = 0;
entry->BitVec = NULL;
entry->State = DIC_Empty;
- entry->version = 0;
+ entry->version = 1;
+
+ entry->Decoder = NULL;
+ entry->DecoderData = NULL;
+ entry->DecodedSize = 0;
entry->next = NULL;
@@ -128,41 +133,31 @@ DICacheEntry *a_Dicache_add_entry(const DilloUrl *Url)
}
/*
- * Search an entry in the dicache (given the Url).
- * Return value: a pointer to the entry of the _newest_ (i.e. highest)
- * version if found; NULL otherwise.
- */
-DICacheEntry *a_Dicache_get_entry(const DilloUrl *Url)
-{
- DICacheNode *node;
- DICacheEntry *entry;
-
- node = dList_find_sorted(CachedIMGs, Url, Dicache_node_by_url_cmp);
-
- if (!node || !node->valid)
- return NULL;
-
- for (entry = node->first; (entry && entry->next); entry = entry->next);
-
- return entry;
-}
-
-/*
* Search a particular version of a URL in the Dicache.
* Return value: a pointer to the entry if found; NULL otherwise.
+ *
+ * Notes: DIC_Last means last version of the image.
+ * version zero is not allowed.
*/
-static DICacheEntry *Dicache_get_entry_version(const DilloUrl *Url,
- int version)
+DICacheEntry *a_Dicache_get_entry(const DilloUrl *Url, int version)
{
DICacheNode *node;
- DICacheEntry *entry;
+ DICacheEntry *entry = NULL;
- node = dList_find_sorted(CachedIMGs, Url, Dicache_node_by_url_cmp);
- entry = (node) ? node->first : NULL;
-
- while (entry && entry->version != version)
- entry = entry->next;
+ dReturn_val_if_fail(version != 0, NULL);
+ node = dList_find_sorted(CachedIMGs, Url, Dicache_node_by_url_cmp);
+ if (node) {
+ if (version == DIC_Last) {
+ if (node->valid) {
+ entry = node->first;
+ for ( ; (entry && entry->next); entry = entry->next);
+ }
+ } else {
+ entry = node->first;
+ for ( ; entry && entry->version != version; entry = entry->next) ;
+ }
+ }
return entry;
}
@@ -185,9 +180,8 @@ static void Dicache_remove(const DilloUrl *Url, int version)
if (entry) {
/* Eliminate this dicache entry */
dFree(entry->cmap);
- dFree(entry->linebuf);
a_Bitvec_free(entry->BitVec);
- a_Image_imgbuf_unref(entry->v_imgbuf);
+ a_Imgbuf_unref(entry->v_imgbuf);
dicache_size_total -= entry->TotalSize;
if (node->first == entry) {
@@ -213,8 +207,7 @@ void a_Dicache_unref(const DilloUrl *Url, int version)
{
DICacheEntry *entry;
- if ((entry = Dicache_get_entry_version(Url, version))) {
- /*if (--entry->RefCount == 0 && (entry->next || !prefs.use_dicache)) {*/
+ if ((entry = a_Dicache_get_entry(Url, version))) {
if (--entry->RefCount == 0) {
Dicache_remove(Url, version);
}
@@ -228,7 +221,7 @@ DICacheEntry* a_Dicache_ref(const DilloUrl *Url, int version)
{
DICacheEntry *entry;
- if ((entry = Dicache_get_entry_version(Url, version))) {
+ if ((entry = a_Dicache_get_entry(Url, version))) {
++entry->RefCount;
}
return entry;
@@ -236,7 +229,8 @@ DICacheEntry* a_Dicache_ref(const DilloUrl *Url, int version)
/*
* Invalidate this entry. This is used for the reloading mechanism.
- * Can't erase current versions, but a_Dicache_get_entry must return NULL.
+ * Can't erase current versions, but a_Dicache_get_entry(url, DIC_Last)
+ * must return NULL.
*/
void a_Dicache_invalidate_entry(const DilloUrl *Url)
{
@@ -251,56 +245,6 @@ void a_Dicache_invalidate_entry(const DilloUrl *Url)
/* ------------------------------------------------------------------------- */
/*
- * This function is a cache client; (but feeds its clients from dicache)
- */
-void a_Dicache_callback(int Op, CacheClient_t *Client)
-{
- uint_t i;
- DilloWeb *Web = Client->Web;
- DilloImage *Image = Web->Image;
- DICacheEntry *DicEntry = a_Dicache_get_entry(Web->url);
-
- dReturn_if_fail ( DicEntry != NULL );
-
- /* when the data stream is not an image 'v_imgbuf' remains NULL */
- if (Op == CA_Send && DicEntry->v_imgbuf) {
- if (Image->height == 0 && DicEntry->State >= DIC_SetParms) {
- /* Set parms */
- a_Image_set_parms(
- Image, DicEntry->v_imgbuf, DicEntry->url,
- DicEntry->version, DicEntry->width, DicEntry->height,
- DicEntry->type);
- }
- if (DicEntry->State == DIC_Write) {
- if (DicEntry->ScanNumber == Image->ScanNumber) {
- for (i = 0; i < DicEntry->height; ++i)
- if (a_Bitvec_get_bit(DicEntry->BitVec, (int)i) &&
- !a_Bitvec_get_bit(Image->BitVec, (int)i) )
- a_Image_write(Image, DicEntry->v_imgbuf,
- DicEntry->linebuf, i, FALSE);
- } else {
- for (i = 0; i < DicEntry->height; ++i) {
- if (a_Bitvec_get_bit(DicEntry->BitVec, (int)i) ||
- !a_Bitvec_get_bit(Image->BitVec, (int)i) ||
- DicEntry->ScanNumber > Image->ScanNumber + 1) {
- a_Image_write(Image, DicEntry->v_imgbuf,
- DicEntry->linebuf, i, FALSE);
- }
- if (!a_Bitvec_get_bit(DicEntry->BitVec, (int)i))
- a_Bitvec_clear_bit(Image->BitVec, (int)i);
- }
- Image->ScanNumber = DicEntry->ScanNumber;
- }
- }
- } else if (Op == CA_Close || Op == CA_Abort) {
- a_Image_close(Image);
- a_Bw_close_client(Web->bw, Client->Key);
- }
-}
-
-/* ------------------------------------------------------------------------- */
-
-/*
* Set image's width, height & type
* (By now, we'll use the image information despite the html tags --Jcid)
*/
@@ -309,24 +253,19 @@ void a_Dicache_set_parms(DilloUrl *url, int version, DilloImage *Image,
{
DICacheEntry *DicEntry;
+ _MSG("a_Dicache_set_parms (%s)\n", URL_STR(url));
dReturn_if_fail ( Image != NULL && width && height );
/* Find the DicEntry for this Image */
- DicEntry = Dicache_get_entry_version(url, version);
+ DicEntry = a_Dicache_get_entry(url, version);
dReturn_if_fail ( DicEntry != NULL );
/* Parameters already set? */
dReturn_if_fail ( DicEntry->State < DIC_SetParms );
- /* Initialize the DicEntry */
- DicEntry->linebuf = dNew(uchar_t, width * 3);
- dReturn_if_fail ( DicEntry->linebuf != NULL );
+ _MSG(" RefCount=%d version=%d\n", DicEntry->RefCount, DicEntry->version);
/* BUG: there's just one image-type now */
#define I_RGB 0
- DicEntry->v_imgbuf = a_Image_imgbuf_new(Image->dw, I_RGB, width, height);
-
- /* This extra reference activates the dicache ALWAYS.
- * Extra code is necessary in Imgbuf to be able to free it */
- //a_Image_imgbuf_ref(DicEntry->v_imgbuf);
+ DicEntry->v_imgbuf = a_Imgbuf_new(Image->dw, I_RGB, width, height);
DicEntry->TotalSize = width * height * 3;
DicEntry->width = width;
@@ -336,10 +275,6 @@ void a_Dicache_set_parms(DilloUrl *url, int version, DilloImage *Image,
DicEntry->State = DIC_SetParms;
dicache_size_total += DicEntry->TotalSize;
-
- /* Allocate and initialize this image */
- a_Image_set_parms(Image, DicEntry->v_imgbuf, url, version,
- width, height, type);
}
/*
@@ -349,8 +284,9 @@ void a_Dicache_set_cmap(DilloUrl *url, int version, DilloImage *Image,
const uchar_t *cmap, uint_t num_colors,
int num_colors_max, int bg_index)
{
- DICacheEntry *DicEntry = Dicache_get_entry_version(url, version);
+ DICacheEntry *DicEntry = a_Dicache_get_entry(url, version);
+ _MSG("a_Dicache_set_cmap\n");
dReturn_if_fail ( DicEntry != NULL );
dFree(DicEntry->cmap);
@@ -362,24 +298,26 @@ void a_Dicache_set_cmap(DilloUrl *url, int version, DilloImage *Image,
DicEntry->cmap[bg_index * 3 + 2] = (Image->bg_color) & 0xff;
}
- a_Image_set_cmap(Image, DicEntry->cmap);
DicEntry->State = DIC_SetCmap;
}
/*
* Reset for a new scan from a multiple-scan image.
*/
-void a_Dicache_new_scan(DilloImage *image, const DilloUrl *url, int version)
+void a_Dicache_new_scan(const DilloUrl *url, int version)
{
DICacheEntry *DicEntry;
+ _MSG("a_Dicache_new_scan\n");
dReturn_if_fail ( url != NULL );
- DicEntry = Dicache_get_entry_version(url, version);
+ DicEntry = a_Dicache_get_entry(url, version);
dReturn_if_fail ( DicEntry != NULL );
-
+ if (DicEntry->State < DIC_SetParms) {
+ MSG("a_Dicache_new_scan before DIC_SetParms\n");
+ exit(-1);
+ }
a_Bitvec_clear(DicEntry->BitVec);
DicEntry->ScanNumber++;
- a_Image_new_scan(image, DicEntry->v_imgbuf);
}
/*
@@ -393,12 +331,16 @@ void a_Dicache_write(DilloImage *Image, DilloUrl *url, int version,
{
DICacheEntry *DicEntry;
+ _MSG("a_Dicache_write\n");
dReturn_if_fail ( Image != NULL );
- DicEntry = Dicache_get_entry_version(url, version);
+ DicEntry = a_Dicache_get_entry(url, version);
dReturn_if_fail ( DicEntry != NULL );
dReturn_if_fail ( DicEntry->width > 0 && DicEntry->height > 0 );
- a_Image_write(Image, DicEntry->v_imgbuf, buf, Y, TRUE);
+ /* update the common buffer in the imgbuf */
+ a_Imgbuf_update(DicEntry->v_imgbuf, buf, DicEntry->type,
+ DicEntry->cmap, DicEntry->width, DicEntry->height, Y);
+
DicEntry->Y = Y;
a_Bitvec_set_bit(DicEntry->BitVec, (int)Y);
DicEntry->State = DIC_Write;
@@ -410,19 +352,92 @@ void a_Dicache_write(DilloImage *Image, DilloUrl *url, int version,
void a_Dicache_close(DilloUrl *url, int version, CacheClient_t *Client)
{
DilloWeb *Web = Client->Web;
- DICacheEntry *DicEntry = Dicache_get_entry_version(url, version);
+ DICacheEntry *DicEntry = a_Dicache_get_entry(url, version);
dReturn_if_fail ( DicEntry != NULL );
- DicEntry->State = DIC_Close;
- dFree(DicEntry->cmap);
- DicEntry->cmap = NULL;
- dFree(DicEntry->linebuf);
- DicEntry->linebuf = NULL;
- a_Image_close(Web->Image);
+ /* a_Dicache_unref() may free DicEntry */
+ MSG("a_Dicache_close RefCount=%d\n", DicEntry->RefCount - 1);
+
+ if (DicEntry->State < DIC_Close) {
+ DicEntry->State = DIC_Close;
+ dFree(DicEntry->cmap);
+ DicEntry->cmap = NULL;
+ DicEntry->Decoder = NULL;
+ DicEntry->DecoderData = NULL;
+ }
+ a_Dicache_unref(url, version);
+
a_Bw_close_client(Web->bw, Client->Key);
}
+/* ------------------------------------------------------------------------- */
+
+/*
+ * This function is a cache client; (but feeds its clients from dicache)
+ */
+void a_Dicache_callback(int Op, CacheClient_t *Client)
+{
+ uint_t i;
+ DilloWeb *Web = Client->Web;
+ DilloImage *Image = Web->Image;
+ DICacheEntry *DicEntry = a_Dicache_get_entry(Web->url, DIC_Last);
+
+ dReturn_if_fail ( DicEntry != NULL );
+
+ /* Copy the version number in the Client */
+ if (Client->Version == 0)
+ Client->Version = DicEntry->version;
+
+ /* Only call the decoder when necessary */
+ if (Op == CA_Send && DicEntry->State < DIC_Close &&
+ DicEntry->DecodedSize < Client->BufSize) {
+ DicEntry->Decoder(Op, Client);
+ DicEntry->DecodedSize = Client->BufSize;
+ } else if (Op == CA_Close || Op == CA_Abort) {
+ if (DicEntry->State < DIC_Close) {
+ DicEntry->Decoder(Op, Client);
+ } else {
+ a_Dicache_close(DicEntry->url, DicEntry->version, Client);
+ }
+ }
+
+ /* when the data stream is not an image 'v_imgbuf' remains NULL */
+ if (Op == CA_Send && DicEntry->v_imgbuf) {
+ if (Image->height == 0 && DicEntry->State >= DIC_SetParms) {
+ /* Set parms */
+ a_Image_set_parms(
+ Image, DicEntry->v_imgbuf, DicEntry->url,
+ DicEntry->version, DicEntry->width, DicEntry->height,
+ DicEntry->type);
+ }
+ if (DicEntry->State == DIC_Write) {
+ if (DicEntry->ScanNumber == Image->ScanNumber) {
+ for (i = 0; i < DicEntry->height; ++i)
+ if (a_Bitvec_get_bit(DicEntry->BitVec, (int)i) &&
+ !a_Bitvec_get_bit(Image->BitVec, (int)i) )
+ a_Image_write(Image, i);
+ } else {
+ for (i = 0; i < DicEntry->height; ++i) {
+ if (a_Bitvec_get_bit(DicEntry->BitVec, (int)i) ||
+ !a_Bitvec_get_bit(Image->BitVec, (int)i) ||
+ DicEntry->ScanNumber > Image->ScanNumber + 1) {
+ a_Image_write(Image, i);
+ }
+ if (!a_Bitvec_get_bit(DicEntry->BitVec, (int)i))
+ a_Bitvec_clear_bit(Image->BitVec, (int)i);
+ }
+ Image->ScanNumber = DicEntry->ScanNumber;
+ }
+ }
+ } else if (Op == CA_Close || Op == CA_Abort) {
+ a_Image_close(Image);
+ a_Bw_close_client(Web->bw, Client->Key);
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
/*
* Free the imgbuf (RGB data) of unused entries.
*/
@@ -432,12 +447,13 @@ void a_Dicache_cleanup(void)
DICacheNode *node;
DICacheEntry *entry;
+ _MSG("a_Dicache_cleanup\n");
for (i = 0; i < dList_length(CachedIMGs); ++i) {
node = dList_nth_data(CachedIMGs, i);
/* iterate each entry of this node */
for (entry = node->first; entry; entry = entry->next) {
if (entry->v_imgbuf &&
- a_Image_imgbuf_last_reference(entry->v_imgbuf)) {
+ a_Imgbuf_last_reference(entry->v_imgbuf)) {
/* free this unused entry */
if (entry->next) {
Dicache_remove(node->url, entry->version);
@@ -467,9 +483,8 @@ void a_Dicache_freeall(void)
while ((entry = node->first)) {
node->first = entry->next;
dFree(entry->cmap);
- dFree(entry->linebuf);
a_Bitvec_free(entry->BitVec);
- a_Image_imgbuf_unref(entry->v_imgbuf);
+ a_Imgbuf_unref(entry->v_imgbuf);
dicache_size_total -= entry->TotalSize;
}
dList_remove(CachedIMGs, node);
diff --git a/src/dicache.h b/src/dicache.h
index c78d0953..51d67de2 100644
--- a/src/dicache.h
+++ b/src/dicache.h
@@ -10,6 +10,10 @@ extern "C" {
#include "image.hh"
#include "cache.h"
+/* Symbolic name to request the last version of an image */
+#define DIC_Last -1
+
+
/* These will reflect the entry's "state" */
typedef enum {
DIC_Empty, /* Just created the entry */
@@ -27,7 +31,6 @@ struct _DICacheEntry {
uint_t width, height; /* As taken from image data */
DilloImgType type; /* Image type */
uchar_t *cmap; /* Color map */
- uchar_t *linebuf; /* Decompressed RGB buffer for one line */
void *v_imgbuf; /* Void pointer to an Imgbuf object */
uint_t TotalSize; /* Amount of memory the image takes up */
int Y; /* Current decoding row */
@@ -37,23 +40,29 @@ struct _DICacheEntry {
int RefCount; /* Reference Counter */
int version; /* Version number, used for different
versions of the same URL image */
+
+ CA_Callback_t Decoder; /* Client function */
+ void *DecoderData; /* Client function data */
+ uint_t DecodedSize; /* Size of already decoded data */
+
DICacheEntry *next; /* Link to the next "newer" version */
};
void a_Dicache_init (void);
-DICacheEntry *a_Dicache_get_entry(const DilloUrl *Url);
+DICacheEntry *a_Dicache_get_entry(const DilloUrl *Url, int version);
DICacheEntry *a_Dicache_add_entry(const DilloUrl *Url);
void a_Dicache_callback(int Op, CacheClient_t *Client);
+void a_Dicache_callback2(int Op, CacheClient_t *Client);
void a_Dicache_set_parms(DilloUrl *url, int version, DilloImage *Image,
uint_t width, uint_t height, DilloImgType type);
void a_Dicache_set_cmap(DilloUrl *url, int version, DilloImage *Image,
const uchar_t *cmap, uint_t num_colors,
int num_colors_max, int bg_index);
-void a_Dicache_new_scan(DilloImage *image, const DilloUrl *url, int version);
+void a_Dicache_new_scan(const DilloUrl *url, int version);
void a_Dicache_write(DilloImage *Image, DilloUrl *url, int version,
const uchar_t *buf, uint_t Y);
void a_Dicache_close(DilloUrl *url, int version, CacheClient_t *Client);
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 b20e5a95..2f8b320a 100644
--- a/src/form.cc
+++ b/src/form.cc
@@ -294,7 +294,7 @@ void Html_tag_open_form(DilloHtml *html, const char *tag, int tagsize)
char *charset, *first;
const char *attrbuf;
- DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->wordStyle ());
if (html->InFlags & IN_FORM) {
BUG_MSG("nested forms\n");
@@ -558,10 +558,10 @@ void Html_tag_open_input(DilloHtml *html, const char *tag, int tagsize)
if (prefs.standard_widget_colors)
bg = NULL;
else
- bg = Color::createShaded(HT2LT(html), S_TOP(html)->current_bg_color);
+ bg = Color::create (HT2LT(html), S_TOP(html)->current_bg_color);
HTML_SET_TOP_ATTR(html, backgroundColor, bg);
- DW2TB(html->dw)->addWidget (embed, S_TOP(html)->style);
+ DW2TB(html->dw)->addWidget (embed, html->styleEngine->style ());
}
dFree(type);
dFree(name);
@@ -594,10 +594,10 @@ void Html_tag_open_isindex(DilloHtml *html, const char *tag, int tagsize)
html->charset);
html->InFlags |= IN_FORM;
- DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->wordStyle ());
if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "prompt")))
- DW2TB(html->dw)->addText(attrbuf, S_TOP(html)->style);
+ DW2TB(html->dw)->addText(attrbuf, html->styleEngine->wordStyle ());
ResourceFactory *factory = HT2LT(html)->getResourceFactory();
EntryResource *entryResource = factory->createEntryResource (20,false,NULL);
@@ -608,9 +608,9 @@ void Html_tag_open_isindex(DilloHtml *html, const char *tag, int tagsize)
if (prefs.standard_widget_colors)
bg = NULL;
else
- bg = Color::createShaded(HT2LT(html), S_TOP(html)->current_bg_color);
+ bg = Color::create (HT2LT(html), S_TOP(html)->current_bg_color);
HTML_SET_TOP_ATTR(html, backgroundColor, bg);
- DW2TB(html->dw)->addWidget (embed, S_TOP(html)->style);
+ DW2TB(html->dw)->addWidget (embed, html->styleEngine->style ());
a_Url_free(action);
html->InFlags &= ~IN_FORM;
@@ -676,10 +676,10 @@ void Html_tag_open_textarea(DilloHtml *html, const char *tag, int tagsize)
if (prefs.standard_widget_colors)
bg = NULL;
else
- bg = Color::createShaded(HT2LT(html), S_TOP(html)->current_bg_color);
+ bg = Color::create (HT2LT(html), S_TOP(html)->current_bg_color);
HTML_SET_TOP_ATTR(html, backgroundColor, bg);
- DW2TB(html->dw)->addWidget (embed, S_TOP(html)->style);
+ DW2TB(html->dw)->addWidget (embed, html->styleEngine->style ());
dFree(name);
}
@@ -760,7 +760,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")))
@@ -879,12 +879,12 @@ void Html_tag_open_button(DilloHtml *html, const char *tag, int tagsize)
Embed *embed;
char *name, *value;
- style_attrs = *S_TOP(html)->style;
+ style_attrs = *html->styleEngine->style ();
style_attrs.margin.setVal(0);
style_attrs.borderWidth.setVal(0);
style_attrs.padding.setVal(0);
style_attrs.backgroundColor =
- Color::createShaded(HT2LT(html), S_TOP(html)->current_bg_color);
+ Color::create (HT2LT(html), S_TOP(html)->current_bg_color);
style = Style::create (HT2LT(html), &style_attrs);
page = new Textblock (prefs.limit_text_width);
@@ -1945,14 +1945,13 @@ static Embed *Html_input_image(DilloHtml *html, const char *tag, int tagsize)
if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "src")) &&
(url = a_Html_url_new(html, attrbuf, NULL, 0))) {
- style_attrs = *S_TOP(html)->style;
+ style_attrs = *html->styleEngine->style ();
style_attrs.cursor = CURSOR_POINTER;
style_attrs.backgroundColor =
- style::Color::createShaded(HT2LT(html), S_TOP(html)->current_bg_color);
+ style::Color::create (HT2LT(html), S_TOP(html)->current_bg_color);
/* create new image and add it to the button */
- if ((Image = a_Html_add_new_image(html, tag, tagsize, url, &style_attrs,
- false))) {
+ if ((Image = a_Html_add_new_image(html, tag, tagsize, url, false))) {
Style *style = Style::create (HT2LT(html), &style_attrs);
IM2DW(Image)->setStyle (style);
ResourceFactory *factory = HT2LT(html)->getResourceFactory();
diff --git a/src/gif.c b/src/gif.c
index 6ea23561..ea6990b3 100644
--- a/src/gif.c
+++ b/src/gif.c
@@ -157,7 +157,8 @@ void *a_Gif_image(const char *Type, void *Ptr, CA_Callback_t *Call,
/*
* MIME handler for "image/gif" type
- * (Sets Gif_callback as cache-client)
+ * Sets a_Dicache_callback as the cache-client,
+ * and Gif_callback as the image decoder.
*/
void *a_Gif_image(const char *Type, void *Ptr, CA_Callback_t *Call,
void **Data)
@@ -172,20 +173,20 @@ void *a_Gif_image(const char *Type, void *Ptr, CA_Callback_t *Call,
/* Add an extra reference to the Image (for dicache usage) */
a_Image_ref(web->Image);
- DicEntry = a_Dicache_get_entry(web->url);
+ DicEntry = a_Dicache_get_entry(web->url, DIC_Last);
if (!DicEntry) {
/* Let's create an entry for this image... */
DicEntry = a_Dicache_add_entry(web->url);
-
- /* ... and let the decoder feed it! */
- *Data = Gif_new(web->Image, DicEntry->url, DicEntry->version);
- *Call = (CA_Callback_t) Gif_callback;
+ DicEntry->DecoderData =
+ Gif_new(web->Image, DicEntry->url, DicEntry->version);
} else {
- /* Let's feed our client from the dicache */
+ /* Repeated image */
a_Dicache_ref(DicEntry->url, DicEntry->version);
- *Data = web->Image;
- *Call = (CA_Callback_t) a_Dicache_callback;
}
+ DicEntry->Decoder = Gif_callback;
+ *Data = DicEntry->DecoderData;
+ *Call = (CA_Callback_t) a_Dicache_callback;
+
return (web->Image->dw);
}
@@ -261,7 +262,7 @@ static void Gif_close(DilloGif *gif, CacheClient_t *Client)
{
int i;
- _MSG("destroy gif %p\n", gif);
+ MSG("Gif_close: destroy gif %p\n", gif);
a_Dicache_close(gif->url, gif->version, Client);
diff --git a/src/html.cc b/src/html.cc
index 77128927..2c348fc8 100644
--- a/src/html.cc
+++ b/src/html.cc
@@ -106,14 +106,10 @@ static const char *Html_get_attr2(DilloHtml *html,
int tagsize,
const char *attrname,
int tag_parsing_flags);
-static void Html_add_widget(DilloHtml *html, Widget *widget,
- char *width_str, char *height_str,
- StyleAttrs *style_attrs);
static int Html_write_raw(DilloHtml *html, char *buf, int bufsize, int Eof);
static void Html_load_image(BrowserWindow *bw, DilloUrl *url,
DilloImage *image);
static void Html_callback(int Op, CacheClient_t *Client);
-static int Html_tag_index(const char *tag);
static void Html_tag_cleanup_at_close(DilloHtml *html, int TagIdx);
/*-----------------------------------------------------------------------------
@@ -312,52 +308,30 @@ static int Html_add_new_linkimage(DilloHtml *html,
}
/*
- * Set the font at the top of the stack. BImask specifies which
- * attributes in BI should be changed.
- */
-void a_Html_set_top_font(DilloHtml *html, const char *name, int size,
- int BI, int BImask)
-{
- FontAttrs font_attrs;
-
- font_attrs = *S_TOP(html)->style->font;
- if (name)
- font_attrs.name = name;
- if (size)
- font_attrs.size = size;
- if (BImask & 1)
- font_attrs.weight = (BI & 1) ? 700 : 400;
- if (BImask & 2)
- font_attrs.style = (BI & 2) ? FONT_STYLE_ITALIC : FONT_STYLE_NORMAL;
-
- HTML_SET_TOP_ATTR (html, font,
- Font::create (HT2LT(html), &font_attrs));
-}
-
-/*
* Evaluates the ALIGN attribute (left|center|right|justify) and
* 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
@@ -371,8 +345,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);
}
}
@@ -381,19 +355,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;
@@ -401,87 +378,23 @@ bool a_Html_tag_set_valign_attr(DilloHtml *html, const char *tag,
/*
- * Add a new DwPage into the current DwPage, for indentation.
- * left and right are the horizontal indentation amounts, space is the
- * vertical space around the block.
+ * Create and add a new Textblock to the current Textblock
*/
-static void Html_add_indented_widget(DilloHtml *html, Widget *textblock,
- int left, int right, int space)
+static void Html_add_textblock(DilloHtml *html, int space)
{
- StyleAttrs style_attrs;
- Style *style;
-
- style_attrs = *S_TOP(html)->style;
-
- style_attrs.margin.setVal (0);
- style_attrs.borderWidth.setVal (0);
- style_attrs.padding.setVal(0);
-
- /* Activate this for debugging */
-#if 0
- style_attrs.borderWidth.setVal (1);
- style_attrs.setBorderColor (
- Color::createShaded (HT2LT(html), style_attrs.color->getColor());
- style_attrs.setBorderStyle (BORDER_DASHED);
-#endif
-
- style_attrs.margin.left = left;
- style_attrs.margin.right = right;
- style = Style::create (HT2LT(html), &style_attrs);
+ Textblock *textblock = new Textblock (prefs.limit_text_width);
- DW2TB(html->dw)->addParbreak (space, style);
- DW2TB(html->dw)->addWidget (textblock, style);
- DW2TB(html->dw)->addParbreak (space, style);
+ DW2TB(html->dw)->addParbreak (space, html->styleEngine->wordStyle ());
+ DW2TB(html->dw)->addWidget (textblock, html->styleEngine->style ());
+ DW2TB(html->dw)->addParbreak (space, html->styleEngine->wordStyle ());
S_TOP(html)->textblock = html->dw = textblock;
S_TOP(html)->hand_over_break = true;
- style->unref ();
/* Handle it when the user clicks on a link */
html->connectSignals(textblock);
}
/*
- * Create and add a new indented DwPage to the current DwPage
- */
-static void Html_add_indented(DilloHtml *html, int left, int right, int space)
-{
- Textblock *textblock = new Textblock (prefs.limit_text_width);
- Html_add_indented_widget (html, textblock, left, right, space);
-}
-
-/*
- * Given a font_size, this will return the correct 'level'.
- * (or the closest, if the exact level isn't found).
- */
-static int Html_fontsize_to_level(int fontsize)
-{
- int i, level;
- double normalized_size = fontsize / prefs.font_factor,
- approximation = FontSizes[FontSizesNum-1] + 1;
-
- for (i = level = 0; i < FontSizesNum; i++)
- if (approximation >= fabs(normalized_size - FontSizes[i])) {
- approximation = fabs(normalized_size - FontSizes[i]);
- level = i;
- } else {
- break;
- }
-
- return level;
-}
-
-/*
- * Given a level of a font, this will return the correct 'size'.
- */
-static int Html_level_to_fontsize(int level)
-{
- level = MAX(0, level);
- level = MIN(FontSizesNum - 1, level);
-
- return (int)rint(FontSizes[level]*prefs.font_factor);
-}
-
-/*
* Create and initialize a new DilloHtml class
*/
DilloHtml::DilloHtml(BrowserWindow *p_bw, const DilloUrl *url,
@@ -510,6 +423,7 @@ DilloHtml::DilloHtml(BrowserWindow *p_bw, const DilloUrl *url,
a_Misc_parse_content_type(content_type, NULL, NULL, &charset);
stop_parser = false;
+ repush_after_head = false;
CurrTagOfs = 0;
OldTagOfs = 0;
@@ -520,8 +434,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;
@@ -534,6 +447,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("");
@@ -561,8 +476,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();
@@ -575,26 +490,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);
@@ -640,6 +541,8 @@ DilloHtml::~DilloHtml()
}
delete (images);
+ delete styleEngine;
+
//a_Dw_image_map_list_free(&maps);
}
@@ -661,7 +564,15 @@ void DilloHtml::write(char *Buf, int BufSize, int Eof)
char *buf = Buf + Start_Ofs;
int bufsize = BufSize - Start_Ofs;
+ MSG("DilloHtml::write BufSize=%d Start_Ofs=%d\n", BufSize, Start_Ofs);
+#if 0
+ char *aux = dStrndup(Buf, BufSize);
+ MSG(" {%s}\n", aux);
+ dFree(aux);
+#endif
+
dReturn_if_fail (dw != NULL);
+ dReturn_if_fail (stop_parser == FALSE);
Start_Buf = Buf;
token_start = Html_write_raw(this, buf, bufsize, Eof);
@@ -694,7 +605,6 @@ int DilloHtml::getCurTagLineNumber()
*/
void DilloHtml::freeParseData()
{
- (stack->getRef(0)->style)->unref (); /* template style */
delete(stack);
dStr_free(Stash, TRUE);
@@ -1150,11 +1060,11 @@ static void Html_process_space(DilloHtml *html, const char *space,
if (spaceCnt) {
spc = dStrnfill(spaceCnt, ' ');
- DW2TB(html->dw)->addText (spc, S_TOP(html)->style);
+ DW2TB(html->dw)->addText (spc, html->styleEngine->wordStyle ());
dFree(spc);
spaceCnt = 0;
}
- DW2TB(html->dw)->addLinebreak (S_TOP(html)->style);
+ DW2TB(html->dw)->addLinebreak (html->styleEngine->wordStyle ());
html->pre_column = 0;
}
html->PreFirstChar = false;
@@ -1182,7 +1092,7 @@ static void Html_process_space(DilloHtml *html, const char *space,
if (spaceCnt) {
spc = dStrnfill(spaceCnt, ' ');
- DW2TB(html->dw)->addText (spc, S_TOP(html)->style);
+ DW2TB(html->dw)->addText (spc, html->styleEngine->wordStyle ());
dFree(spc);
}
@@ -1190,7 +1100,7 @@ static void Html_process_space(DilloHtml *html, const char *space,
if (SGML_SPCDEL) {
/* SGML_SPCDEL ignores white space inmediately after an open tag */
} else if (!html->PrevWasSPC) {
- DW2TB(html->dw)->addSpace(S_TOP(html)->style);
+ DW2TB(html->dw)->addSpace(html->styleEngine->wordStyle ());
html->PrevWasSPC = true;
}
@@ -1243,7 +1153,7 @@ static void Html_process_word(DilloHtml *html, const char *word, int size)
while (Pword[++i] && !isspace(Pword[i])) ;
ch = Pword[i];
Pword[i] = 0;
- DW2TB(html->dw)->addText(Pword, S_TOP(html)->style);
+ DW2TB(html->dw)->addText(Pword, html->styleEngine->wordStyle ());
Pword[i] = ch;
html->pre_column += i - start;
html->PreFirstChar = false;
@@ -1253,7 +1163,7 @@ static void Html_process_word(DilloHtml *html, const char *word, int size)
} else {
if (!memchr(word,'&', size)) {
/* No entities */
- DW2TB(html->dw)->addText(word, S_TOP(html)->style);
+ DW2TB(html->dw)->addText(word, html->styleEngine->wordStyle ());
} else {
/* Collapse white-space entities inside the word (except &nbsp;) */
Pword = a_Html_parse_entities(html, word, size);
@@ -1261,7 +1171,7 @@ static void Html_process_word(DilloHtml *html, const char *word, int size)
if (strchr("\t\f\n\r", Pword[i]))
for (j = i; (Pword[j] = Pword[j+1]); ++j) ;
- DW2TB(html->dw)->addText(Pword, S_TOP(html)->style);
+ DW2TB(html->dw)->addText(Pword, html->styleEngine->wordStyle ());
dFree(Pword);
}
}
@@ -1297,7 +1207,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;
}
@@ -1316,10 +1226,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;
}
@@ -1329,6 +1237,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);
}
@@ -1339,9 +1248,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);
@@ -1416,10 +1325,10 @@ static void Html_tag_cleanup_at_close(DilloHtml *html, int TagIdx)
/*
* Used by a_Html_parse_length
*/
-static Length Html_parse_length_or_multi_length (const char *attr,
- char **endptr)
+static CssLength Html_parse_length_or_multi_length (const char *attr,
+ char **endptr)
{
- Length l;
+ CssLength l;
double v;
char *end;
@@ -1427,12 +1336,12 @@ static Length Html_parse_length_or_multi_length (const char *attr,
switch (*end) {
case '%':
end++;
- l = createPerLength (v / 100);
+ l = CSS_CREATE_LENGTH (v / 100, CSS_LENGTH_TYPE_PERCENTAGE);
break;
case '*':
end++;
- l = createRelLength (v);
+ l = CSS_CREATE_LENGTH (v, CSS_LENGTH_TYPE_RELATIVE);
break;
/*
The "px" suffix seems not allowed by HTML4.01 SPEC.
@@ -1441,7 +1350,7 @@ static Length Html_parse_length_or_multi_length (const char *attr,
end += 2;
*/
default:
- l = createAbsLength ((int)v);
+ l = CSS_CREATE_LENGTH (v, CSS_LENGTH_TYPE_PX);
break;
}
@@ -1455,24 +1364,24 @@ static Length Html_parse_length_or_multi_length (const char *attr,
* Returns a length or a percentage, or UNDEF_LENGTH in case
* of an error, or if attr is NULL.
*/
-Length a_Html_parse_length (DilloHtml *html, const char *attr)
+CssLength a_Html_parse_length (DilloHtml *html, const char *attr)
{
- Length l;
+ CssLength l;
char *end;
l = Html_parse_length_or_multi_length (attr, &end);
- if (isRelLength (l))
+ if (CSS_LENGTH_TYPE (l) == CSS_LENGTH_TYPE_RELATIVE)
/* not allowed as &Length; */
- return LENGTH_AUTO;
+ l = CSS_CREATE_LENGTH(0.0, CSS_LENGTH_TYPE_AUTO);
else {
/* allow only whitespaces */
if (*end && !isspace (*end)) {
BUG_MSG("Garbage after length: %s\n", attr);
- return LENGTH_AUTO;
+ l = CSS_CREATE_LENGTH(0.0, CSS_LENGTH_TYPE_AUTO);
}
}
- _MSG("a_Html_parse_length: \"%s\" %d\n", attr, absLengthVal(l));
+ _MSG("a_Html_parse_length: \"%s\" %d\n", attr, CSS_LENGTH_VALUE(l));
return l;
}
@@ -1649,14 +1558,23 @@ static void Html_tag_open_head(DilloHtml *html, const char *tag, int tagsize)
* Handle close HEAD element
* Note: as a side effect of Html_test_section() this function is called
* twice when the head element is closed implicitly.
+ * Note2: HEAD is parsed once completely got. This asserts that a
+ * linked stylesheet will always arrive after HEAD contents.
*/
static void Html_tag_close_head(DilloHtml *html, int TagIdx)
{
if (html->InFlags & IN_HEAD) {
+ _MSG("Closing HEAD section\n");
if (html->Num_TITLE == 0)
BUG_MSG("HEAD section lacks the TITLE element\n");
-
+
html->InFlags &= ~IN_HEAD;
+
+ if (html->repush_after_head) {
+ html->stop_parser = true;
+ MSG(" [html->stop_parser = true]\n");
+ a_Nav_repush(html->bw);
+ }
}
}
@@ -1706,11 +1624,27 @@ static void Html_tag_close_script(DilloHtml *html, int TagIdx)
/*
* Handle open STYLE
- * store the contents to the stash where (in the future) the style
- * sheet interpreter can get it.
+ * Store contents in the stash where the style sheet interpreter can get it.
*/
static void Html_tag_open_style(DilloHtml *html, const char *tag, int tagsize)
{
+ const char *attrbuf;
+
+ if (!(attrbuf = a_Html_get_attr(html, tag, tagsize, "type"))) {
+ BUG_MSG("type attribute is required for <style>\n");
+ } else if (dStrcasecmp(attrbuf, "text/css")) {
+ MSG("Shouldn't be applying <style type=\"%s\">\n", attrbuf);
+ /* We need to inform close_style() */
+ }
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "media")) &&
+ dStrcasecmp(attrbuf, "all") && !dStristr(attrbuf, "screen")) {
+ /* HTML 4.01 sec. 6.13 says that media descriptors are case-sensitive,
+ * but sec. 14.2.3 says that the attribute is case-insensitive.
+ * TODO can be a comma-separated list.
+ * TODO handheld.
+ */
+ MSG("Shouldn't be applying <style media=\"%s\">\n", attrbuf);
+ }
a_Html_stash_init(html);
S_TOP(html)->parse_mode = DILLO_HTML_PARSE_MODE_VERBATIM;
}
@@ -1720,7 +1654,8 @@ static void Html_tag_open_style(DilloHtml *html, const char *tag, int tagsize)
*/
static void Html_tag_close_style(DilloHtml *html, int TagIdx)
{
- /* eventually the stash will be sent to an interpreter for parsing */
+ html->styleEngine->parse(html->Stash->str, html->Stash->len,
+ 0, CSS_ORIGIN_AUTHOR);
}
/*
@@ -1730,8 +1665,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))
@@ -1749,43 +1683,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;
}
@@ -1807,13 +1735,16 @@ static void Html_tag_close_body(DilloHtml *html, int TagIdx)
*/
static void Html_tag_open_p(DilloHtml *html, const char *tag, int tagsize)
{
+ CssPropertyList props;
+
if ((html->InFlags & IN_LI) && !html->WordAfterLI) {
/* ignore first parbreak after an empty <LI> */
html->WordAfterLI = true;
} else {
- DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->wordStyle ());
}
- a_Html_tag_set_align_attr (html, tag, tagsize);
+ a_Html_tag_set_align_attr (html, &props, tag, tagsize);
+ html->styleEngine->setNonCssHints (&props);
}
/*
@@ -1827,9 +1758,8 @@ static void Html_tag_open_frame (DilloHtml *html, const char *tag, int tagsize)
char *src;
DilloUrl *url;
Textblock *textblock;
- StyleAttrs style_attrs;
- Style *link_style;
Widget *bullet;
+ CssPropertyList props;
textblock = DW2TB(html->dw);
@@ -1841,46 +1771,41 @@ static void Html_tag_open_frame (DilloHtml *html, const char *tag, int tagsize)
src = dStrdup(attrbuf);
- style_attrs = *(S_TOP(html)->style);
-
if (a_Capi_get_flags(url) & CAPI_IsCached) { /* visited frame */
- style_attrs.color =
- Color::createSimple (HT2LT(html), html->visited_color);
+ html->styleEngine->setPseudoVisited ();
} else { /* unvisited frame */
- style_attrs.color = Color::createSimple (HT2LT(html), html->link_color);
+ html->styleEngine->setPseudoLink ();
}
- style_attrs.textDecoration |= TEXT_DECORATION_UNDERLINE;
- style_attrs.x_link = Html_set_new_link(html, &url);
- style_attrs.cursor = CURSOR_POINTER;
- link_style = Style::create (HT2LT(html), &style_attrs);
- textblock->addParbreak (5, S_TOP(html)->style);
+ props.set (CssProperty::PROPERTY_X_LINK, Html_set_new_link(html, &url));
+ html->styleEngine->setNonCssHints (&props);
+
+ textblock->addParbreak (5, html->styleEngine->wordStyle ());
/* The bullet will be assigned the current list style, which should
* be "disc" by default, but may in very weird pages be different.
* Anyway, there should be no harm. */
bullet = new Bullet();
- textblock->addWidget(bullet, S_TOP(html)->style);
- textblock->addSpace(S_TOP(html)->style);
+ textblock->addWidget(bullet, html->styleEngine->style ());
+ textblock->addSpace(html->styleEngine->wordStyle ());
if (tolower(tag[1]) == 'i') {
/* IFRAME usually comes with very long advertising/spying URLS,
* to not break rendering we will force name="IFRAME" */
- textblock->addText ("IFRAME", link_style);
+ textblock->addText ("IFRAME", html->styleEngine->wordStyle ());
} else {
/* FRAME:
* If 'name' tag is present use it, if not use 'src' value */
if (!(attrbuf = a_Html_get_attr(html, tag, tagsize, "name"))) {
- textblock->addText (src, link_style);
+ textblock->addText (src, html->styleEngine->wordStyle ());
} else {
- textblock->addText (attrbuf, link_style);
+ textblock->addText (attrbuf, html->styleEngine->wordStyle ());
}
}
- textblock->addParbreak (5, S_TOP(html)->style);
+ textblock->addParbreak (5, html->styleEngine->wordStyle ());
- link_style->unref ();
dFree(src);
}
@@ -1892,9 +1817,9 @@ static void Html_tag_open_frame (DilloHtml *html, const char *tag, int tagsize)
static void Html_tag_open_frameset (DilloHtml *html,
const char *tag, int tagsize)
{
- DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
- DW2TB(html->dw)->addText("--FRAME--", S_TOP(html)->style);
- Html_add_indented(html, 40, 0, 5);
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->wordStyle ());
+ DW2TB(html->dw)->addText("--FRAME--", html->styleEngine->wordStyle ());
+ Html_add_textblock(html, 5);
}
/*
@@ -1902,18 +1827,19 @@ static void Html_tag_open_frameset (DilloHtml *html,
*/
static void Html_tag_open_h(DilloHtml *html, const char *tag, int tagsize)
{
- DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
+ CssPropertyList props;
- /* TODO: combining these two would be slightly faster */
- a_Html_set_top_font(html, prefs.vw_fontname,
- Html_level_to_fontsize(FontSizesNum - (tag[2] - '0')),
- 1, 3);
- a_Html_tag_set_align_attr (html, tag, tagsize);
+
+ html->styleEngine->inheritBackgroundColor ();
+ a_Html_tag_set_align_attr (html, &props, tag, tagsize);
+ html->styleEngine->setNonCssHints (&props);
+
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->wordStyle ());
/* First finalize unclosed H tags (we test if already named anyway) */
a_Menu_pagemarks_set_text(html->bw, html->Stash->str);
a_Menu_pagemarks_add(html->bw, DW2TB(html->dw),
- S_TOP(html)->style, (tag[2] - '0'));
+ html->styleEngine->style (), (tag[2] - '0'));
a_Html_stash_init(html);
S_TOP(html)->parse_mode =
DILLO_HTML_PARSE_MODE_STASH_AND_BODY;
@@ -1925,29 +1851,22 @@ static void Html_tag_open_h(DilloHtml *html, const char *tag, int tagsize)
static void Html_tag_close_h(DilloHtml *html, int TagIdx)
{
a_Menu_pagemarks_set_text(html->bw, html->Stash->str);
- DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->wordStyle ());
}
-/*
- * <BIG> | <SMALL>
- */
-static void Html_tag_open_big_small(DilloHtml *html,
- const char *tag, int tagsize)
+static void Html_tag_open_span(DilloHtml *html,
+ const char *tag, int tagsize)
{
- int level;
-
- level =
- Html_fontsize_to_level(S_TOP(html)->style->font->size) +
- ((dStrncasecmp(tag+1, "big", 3)) ? -1 : 1);
- a_Html_set_top_font(html, NULL, Html_level_to_fontsize(level), 0, 0);
+ html->styleEngine->inheritBackgroundColor();
}
+
/*
* <BR>
*/
static void Html_tag_open_br(DilloHtml *html, const char *tag, int tagsize)
{
- DW2TB(html->dw)->addLinebreak (S_TOP(html)->style);
+ DW2TB(html->dw)->addLinebreak (html->styleEngine->wordStyle ());
}
/*
@@ -1955,39 +1874,27 @@ static void Html_tag_open_br(DilloHtml *html, const char *tag, int tagsize)
*/
static void Html_tag_open_font(DilloHtml *html, const char *tag, int tagsize)
{
- StyleAttrs style_attrs;
- Style *old_style;
/*Font font;*/
const char *attrbuf;
int32_t color;
-
- if (!prefs.force_my_colors) {
- old_style = S_TOP(html)->style;
- style_attrs = *old_style;
-
- if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "color"))) {
- if (prefs.contrast_visited_color && html->InVisitedLink) {
- color = html->visited_color;
- } else {
- /* use the tag-specified color */
- color = a_Html_color_parse(html, attrbuf,
- style_attrs.color->getColor());
- style_attrs.color = Color::createSimple (HT2LT(html), color);
- }
+ CssPropertyList props;
+
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "color"))) {
+ if (prefs.contrast_visited_color && html->InVisitedLink) {
+ color = html->visited_color;
+ } else {
+ /* use the tag-specified color */
+ color = a_Html_color_parse(html, attrbuf, -1);
}
+ if (color != -1)
+ props.set (CssProperty::CSS_PROPERTY_COLOR, color);
+ }
-#if 0
- //if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "face"))) {
- // font = *( style_attrs.font );
- // font.name = attrbuf;
- // style_attrs.font = a_Dw_style_font_new_from_list (&font);
- //}
-#endif
+// \todo reenable font face handling when font selection is implemented
+// if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "face")))
+// props.set (CssProperty::CSS_PROPERTY_FONT_FAMILY, attrbuf);
- S_TOP(html)->style =
- Style::create (HT2LT(html), &style_attrs);
- old_style->unref ();
- }
+ html->styleEngine->setNonCssHints (&props);
}
/*
@@ -2005,52 +1912,11 @@ static void Html_tag_open_abbr(DilloHtml *html, const char *tag, int tagsize)
}
/*
- * <B>
- */
-static void Html_tag_open_b(DilloHtml *html, const char *tag, int tagsize)
-{
- a_Html_set_top_font(html, NULL, 0, 1, 1);
-}
-
-/*
- * <STRONG>
- */
-static void Html_tag_open_strong(DilloHtml *html, const char *tag, int tagsize)
-{
- a_Html_set_top_font(html, NULL, 0, 1, 1);
-}
-
-/*
- * <I>
- */
-static void Html_tag_open_i(DilloHtml *html, const char *tag, int tagsize)
-{
- a_Html_set_top_font(html, NULL, 0, 2, 2);
-}
-
-/*
- * <EM>
- */
-static void Html_tag_open_em(DilloHtml *html, const char *tag, int tagsize)
-{
- a_Html_set_top_font(html, NULL, 0, 2, 2);
-}
-
-/*
- * <CITE>
- */
-static void Html_tag_open_cite(DilloHtml *html, const char *tag, int tagsize)
-{
- a_Html_set_top_font(html, NULL, 0, 2, 2);
-}
-
-/*
* <CENTER>
*/
static void Html_tag_open_center(DilloHtml *html, const char *tag, int tagsize)
{
- DW2TB(html->dw)->addParbreak (0, S_TOP(html)->style);
- HTML_SET_TOP_ATTR(html, textAlign, TEXT_ALIGN_CENTER);
+ DW2TB(html->dw)->addParbreak (0, html->styleEngine->wordStyle ());
}
/*
@@ -2059,16 +1925,7 @@ static void Html_tag_open_center(DilloHtml *html, const char *tag, int tagsize)
static void Html_tag_open_address(DilloHtml *html,
const char *tag, int tagsize)
{
- DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
- a_Html_set_top_font(html, NULL, 0, 2, 2);
-}
-
-/*
- * <TT>
- */
-static void Html_tag_open_tt(DilloHtml *html, const char *tag, int tagsize)
-{
- a_Html_set_top_font(html, prefs.fw_fontname, 0, 0, 0);
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->wordStyle ());
}
/*
@@ -2077,7 +1934,6 @@ static void Html_tag_open_tt(DilloHtml *html, const char *tag, int tagsize)
*/
DilloImage *a_Html_add_new_image(DilloHtml *html, const char *tag,
int tagsize, DilloUrl *url,
- dw::core::style::StyleAttrs *style_attrs,
bool add)
{
const int MAX_W = 6000, MAX_H = 6000;
@@ -2085,9 +1941,11 @@ DilloImage *a_Html_add_new_image(DilloHtml *html, const char *tag,
DilloImage *Image;
char *width_ptr, *height_ptr, *alt_ptr;
const char *attrbuf;
- Length l_w, l_h;
- int space, w = 0, h = 0;
+ Length l_w = CSS_CREATE_LENGTH(0.0, CSS_LENGTH_TYPE_AUTO);
+ Length l_h = CSS_CREATE_LENGTH(0.0, CSS_LENGTH_TYPE_AUTO);
+ int space, border, w = 0, h = 0;
bool load_now;
+ CssPropertyList props;
// if (prefs.show_tooltip &&
// (attrbuf = a_Html_get_attr(html, tag, tagsize, "title")))
@@ -2104,17 +1962,24 @@ DilloImage *a_Html_add_new_image(DilloHtml *html, const char *tag,
// TODO: the same for percentage and relative lengths.
if (width_ptr) {
l_w = a_Html_parse_length (html, width_ptr);
- w = isAbsLength(l_w) ? absLengthVal(l_w) : 0;
+ w = (int) (CSS_LENGTH_TYPE(l_w) == CSS_LENGTH_TYPE_PX ?
+ CSS_LENGTH_VALUE(l_w) : 0);
}
if (height_ptr) {
l_h = a_Html_parse_length (html, height_ptr);
- h = isAbsLength(l_h) ? absLengthVal(l_h) : 0;
+ h = (int) (CSS_LENGTH_TYPE(l_h) == CSS_LENGTH_TYPE_PX ?
+ CSS_LENGTH_VALUE(l_h) : 0);
}
if (w < 0 || h < 0 || abs(w*h) > MAX_W * MAX_H) {
dFree(width_ptr);
dFree(height_ptr);
width_ptr = height_ptr = NULL;
MSG("a_Html_add_new_image: suspicious image size request %dx%d\n", w, h);
+ } else {
+ if (CSS_LENGTH_TYPE(l_w) != CSS_LENGTH_TYPE_AUTO)
+ props.set (CssProperty::CSS_PROPERTY_WIDTH, l_w);
+ if (CSS_LENGTH_TYPE(l_h) != CSS_LENGTH_TYPE_AUTO)
+ props.set (CssProperty::CSS_PROPERTY_HEIGHT, l_h);
}
/* TODO: we should scale the image respecting its ratio.
@@ -2127,27 +1992,52 @@ DilloImage *a_Html_add_new_image(DilloHtml *html, const char *tag,
/* Spacing to the left and right */
if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "hspace"))) {
space = strtol(attrbuf, NULL, 10);
- if (space > 0)
- style_attrs->margin.left = style_attrs->margin.right = space;
+ if (space > 0) {
+ space = CSS_CREATE_LENGTH(space, CSS_LENGTH_TYPE_PX);
+ props.set (CssProperty::CSS_PROPERTY_MARGIN_LEFT, space);
+ props.set (CssProperty::CSS_PROPERTY_MARGIN_RIGHT, space);
+ }
}
/* Spacing at the top and bottom */
if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "vspace"))) {
space = strtol(attrbuf, NULL, 10);
- if (space > 0)
- style_attrs->margin.top = style_attrs->margin.bottom = space;
+ if (space > 0) {
+ space = CSS_CREATE_LENGTH(space, CSS_LENGTH_TYPE_PX);
+ props.set (CssProperty::CSS_PROPERTY_MARGIN_TOP, space);
+ props.set (CssProperty::CSS_PROPERTY_MARGIN_BOTTOM, space);
+ }
+ }
+
+ /* Border */
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "border"))) {
+ border = strtol(attrbuf, NULL, 10);
+ if (border >= 0) {
+ border = CSS_CREATE_LENGTH(border, CSS_LENGTH_TYPE_PX);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_TOP_WIDTH, border);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_BOTTOM_WIDTH, border);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_LEFT_WIDTH, border);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_RIGHT_WIDTH, border);
+
+ props.set (CssProperty::CSS_PROPERTY_BORDER_TOP_STYLE, BORDER_SOLID);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_BOTTOM_STYLE,
+ BORDER_SOLID);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_LEFT_STYLE, BORDER_SOLID);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_RIGHT_STYLE,BORDER_SOLID);
+ }
}
/* x_img is an index to a list of {url,image} pairs.
* We know Html_add_new_linkimage() will use size() as its next index */
- style_attrs->x_img = html->images->size();
+ props.set (CssProperty::PROPERTY_X_IMG, html->images->size());
+
+ html->styleEngine->setNonCssHints(&props);
/* Add a new image widget to this page */
Image = a_Image_new(0, 0, alt_ptr, S_TOP(html)->current_bg_color);
- if (add) {
- Html_add_widget(html, (Widget*)Image->dw, width_ptr, height_ptr,
- style_attrs);
- }
+ if (add)
+ DW2TB(html->dw)->addWidget((Widget*)Image->dw,
+ html->styleEngine->style());
load_now = a_UIcmd_get_images_enabled(html->bw) ||
(a_Capi_get_flags(url) & CAPI_IsCached);
@@ -2191,9 +2081,7 @@ static void Html_tag_open_img(DilloHtml *html, const char *tag, int tagsize)
DilloImage *Image;
DilloUrl *url, *usemap_url;
Textblock *textblock;
- StyleAttrs style_attrs;
const char *attrbuf;
- int border;
/* This avoids loading images. Useful for viewing suspicious HTML email. */
if (URL_FLAGS(html->base_url) & URL_SpamSafe)
@@ -2210,34 +2098,13 @@ static void Html_tag_open_img(DilloHtml *html, const char *tag, int tagsize)
/* TODO: usemap URLs outside of the document are not used. */
usemap_url = a_Html_url_new(html, attrbuf, NULL, 0);
- /* Set the style attributes for this image */
- style_attrs = *S_TOP(html)->style;
- if (S_TOP(html)->style->x_link != -1 ||
- usemap_url != NULL) {
- /* Images within links */
- border = 1;
- if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "border")))
- border = strtol (attrbuf, NULL, 10);
-
- if (S_TOP(html)->style->x_link != -1) {
- /* In this case we can use the text color */
- style_attrs.setBorderColor (
- Color::createShaded (HT2LT(html), style_attrs.color->getColor()));
- } else {
- style_attrs.setBorderColor (
- Color::createShaded (HT2LT(html), html->link_color));
- }
- style_attrs.setBorderStyle (BORDER_SOLID);
- style_attrs.borderWidth.setVal (border);
- }
-
- Image = a_Html_add_new_image(html, tag, tagsize, url, &style_attrs, true);
+ Image = a_Html_add_new_image(html, tag, tagsize, url, true);
/* Image maps */
if (a_Html_get_attr(html, tag, tagsize, "ismap")) {
((::dw::Image*)Image->dw)->setIsMap();
_MSG(" Html_tag_open_img: server-side map (ISMAP)\n");
- } else if (S_TOP(html)->style->x_link != -1 &&
+ } else if (html->styleEngine->style ()->x_link != -1 &&
usemap_url == NULL) {
/* For simple links, we have to suppress the "image_pressed" signal.
* This is overridden for USEMAP images. */
@@ -2404,10 +2271,9 @@ static void Html_tag_open_area(DilloHtml *html, const char *tag, int tagsize)
*/
static void Html_tag_open_object(DilloHtml *html, const char *tag, int tagsize)
{
- StyleAttrs style_attrs;
- Style *style;
DilloUrl *url, *base_url = NULL;
const char *attrbuf;
+ CssPropertyList props;
if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "codebase"))) {
base_url = a_Html_url_new(html, attrbuf, NULL, 0);
@@ -2418,31 +2284,16 @@ 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;
-
if (a_Capi_get_flags(url) & CAPI_IsCached) {
- 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)->style->backgroundColor->getColor()),
-*/
- );
+ html->styleEngine->setPseudoVisited ();
} else {
- style_attrs.color = Color::createSimple(HT2LT(html),
- html->link_color);
+ html->styleEngine->setPseudoLink ();
}
+
+ props.set(CssProperty::PROPERTY_X_LINK, Html_set_new_link(html, &url));
+ html->styleEngine->setNonCssHints (&props);
- style_attrs.textDecoration |= TEXT_DECORATION_UNDERLINE;
- style_attrs.x_link = Html_set_new_link(html, &url);
- style_attrs.cursor = CURSOR_POINTER;
-
- style = Style::create (HT2LT(html), &style_attrs);
- DW2TB(html->dw)->addText("[OBJECT]", style);
- style->unref ();
+ DW2TB(html->dw)->addText("[OBJECT]", html->styleEngine->wordStyle ());
}
a_Url_free(base_url);
}
@@ -2476,7 +2327,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
@@ -2493,9 +2344,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 */
@@ -2510,38 +2360,24 @@ static void Html_tag_open_a(DilloHtml *html, const char *tag, int tagsize)
url = a_Html_url_new(html, attrbuf, NULL, 0);
dReturn_if_fail ( url != NULL );
- old_style = S_TOP(html)->style;
- style_attrs = *old_style;
-
if (a_Capi_get_flags(url) & CAPI_IsCached) {
html->InVisitedLink = true;
- style_attrs.color = Color::createSimple (
- HT2LT(html),
- html->visited_color
-/*
- a_Color_vc(html->visited_color,
- S_TOP(html)->style->color->getColor(),
- html->link_color,
- S_TOP(html)->current_bg_color),
-*/
- );
+ html->styleEngine->setPseudoVisited ();
+ if (html->visited_color != -1)
+ props.set (CssProperty::CSS_PROPERTY_COLOR, html->visited_color);
} else {
- style_attrs.color = Color::createSimple(HT2LT(html),
- html->link_color);
+ html->styleEngine->setPseudoLink ();
+ if (html->link_color != -1)
+ props.set (CssProperty::CSS_PROPERTY_COLOR, html->link_color);
}
-// if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "title")))
-// style_attrs.x_tooltip = a_Dw_tooltip_new_no_ref(attrbuf);
+ props.set (CssProperty::PROPERTY_X_LINK, Html_set_new_link(html, &url));
- style_attrs.textDecoration |= TEXT_DECORATION_UNDERLINE;
- style_attrs.x_link = Html_set_new_link(html, &url);
- style_attrs.cursor = CURSOR_POINTER;
-
- S_TOP(html)->style =
- Style::create (HT2LT(html), &style_attrs);
- old_style->unref ();
+ html->styleEngine->setNonCssHints (&props);
}
+ html->styleEngine->inheritBackgroundColor ();
+
if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "name"))) {
if (prefs.show_extra_warnings)
Html_check_name_val(html, attrbuf, "name");
@@ -2560,45 +2396,13 @@ static void Html_tag_close_a(DilloHtml *html, int TagIdx)
}
/*
- * Insert underlined text in the page.
- */
-static void Html_tag_open_u(DilloHtml *html, const char *tag, int tagsize)
-{
- Style *style;
- StyleAttrs style_attrs;
-
- style = S_TOP(html)->style;
- style_attrs = *style;
- style_attrs.textDecoration |= TEXT_DECORATION_UNDERLINE;
- S_TOP(html)->style =
- Style::create (HT2LT(html), &style_attrs);
- style->unref ();
-}
-
-/*
- * Insert strike-through text. Used by <S>, <STRIKE> and <DEL>.
- */
-static void Html_tag_open_strike(DilloHtml *html, const char *tag, int tagsize)
-{
- Style *style;
- StyleAttrs style_attrs;
-
- style = S_TOP(html)->style;
- style_attrs = *style;
- style_attrs.textDecoration |= TEXT_DECORATION_LINE_THROUGH;
- S_TOP(html)->style =
- Style::create (HT2LT(html), &style_attrs);
- style->unref ();
-}
-
-/*
* <BLOCKQUOTE>
*/
static void Html_tag_open_blockquote(DilloHtml *html,
const char *tag, int tagsize)
{
- DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
- Html_add_indented(html, 40, 40, 9);
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->wordStyle ());
+ Html_add_textblock(html, 9);
}
/*
@@ -2612,7 +2416,7 @@ static void Html_tag_open_q(DilloHtml *html, const char *tag, int tagsize)
*/
const char *U201C = "\xe2\x80\x9c";
- DW2TB(html->dw)->addText (U201C, S_TOP(html)->style);
+ DW2TB(html->dw)->addText (U201C, html->styleEngine->wordStyle ());
}
/*
@@ -2623,7 +2427,7 @@ static void Html_tag_close_q(DilloHtml *html, int TagIdx)
/* Right Double Quotation Mark */
const char *U201D = "\xe2\x80\x9d";
- DW2TB(html->dw)->addText (U201D, S_TOP(html)->style);
+ DW2TB(html->dw)->addText (U201D, html->styleEngine->wordStyle ());
}
/*
@@ -2634,10 +2438,9 @@ static void Html_tag_open_ul(DilloHtml *html, const char *tag, int tagsize)
const char *attrbuf;
ListStyleType list_style_type;
- DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
- Html_add_indented(html, 40, 0, 9);
-
if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "type"))) {
+ CssPropertyList props;
+
/* list_style_type explicitly defined */
if (dStrncasecmp(attrbuf, "disc", 4) == 0)
list_style_type = LIST_STYLE_TYPE_DISC;
@@ -2648,33 +2451,15 @@ static void Html_tag_open_ul(DilloHtml *html, const char *tag, int tagsize)
else
/* invalid value */
list_style_type = LIST_STYLE_TYPE_DISC;
- } else {
- if (S_TOP(html)->list_type == HTML_LIST_UNORDERED) {
- /* Nested <UL>'s. */
- /* --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) {
- case LIST_STYLE_TYPE_DISC:
- list_style_type = LIST_STYLE_TYPE_CIRCLE;
- break;
- case LIST_STYLE_TYPE_CIRCLE:
- list_style_type = LIST_STYLE_TYPE_SQUARE;
- break;
- case LIST_STYLE_TYPE_SQUARE:
- default: /* this is actually a bug */
- list_style_type = LIST_STYLE_TYPE_DISC;
- break;
- }
- } else {
- /* Either first <UL>, or a <OL> before. */
- list_style_type = LIST_STYLE_TYPE_DISC;
- }
- }
- HTML_SET_TOP_ATTR(html, listStyleType, list_style_type);
- S_TOP(html)->list_type = HTML_LIST_UNORDERED;
+ props.set(CssProperty::CSS_PROPERTY_LIST_STYLE_TYPE, list_style_type);
+ html->styleEngine->setNonCssHints (&props);
+ }
+
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->wordStyle ());
+ Html_add_textblock(html, 9);
+ S_TOP(html)->list_type = HTML_LIST_UNORDERED;
S_TOP(html)->list_number = 0;
S_TOP(html)->ref_list_item = NULL;
}
@@ -2685,11 +2470,8 @@ static void Html_tag_open_ul(DilloHtml *html, const char *tag, int tagsize)
*/
static void Html_tag_open_dir(DilloHtml *html, const char *tag, int tagsize)
{
- ListStyleType list_style_type = LIST_STYLE_TYPE_DISC;
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->wordStyle ());
- DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
- Html_add_indented(html, 40, 0, 9);
- HTML_SET_TOP_ATTR(html, listStyleType, list_style_type);
S_TOP(html)->list_type = HTML_LIST_UNORDERED;
S_TOP(html)->list_number = 0;
S_TOP(html)->ref_list_item = NULL;
@@ -2712,28 +2494,30 @@ static void Html_tag_open_menu(DilloHtml *html, const char *tag, int tagsize)
static void Html_tag_open_ol(DilloHtml *html, const char *tag, int tagsize)
{
const char *attrbuf;
- ListStyleType list_style_type;
int n = 1;
- DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
- Html_add_indented(html, 40, 0, 9);
-
- list_style_type = LIST_STYLE_TYPE_DECIMAL;
-
if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "type"))) {
+ CssPropertyList props;
+ ListStyleType listStyleType = LIST_STYLE_TYPE_DECIMAL;
+
if (*attrbuf == '1')
- list_style_type = LIST_STYLE_TYPE_DECIMAL;
+ listStyleType = LIST_STYLE_TYPE_DECIMAL;
else if (*attrbuf == 'a')
- list_style_type = LIST_STYLE_TYPE_LOWER_ALPHA;
+ listStyleType = LIST_STYLE_TYPE_LOWER_ALPHA;
else if (*attrbuf == 'A')
- list_style_type = LIST_STYLE_TYPE_UPPER_ALPHA;
+ listStyleType = LIST_STYLE_TYPE_UPPER_ALPHA;
else if (*attrbuf == 'i')
- list_style_type = LIST_STYLE_TYPE_LOWER_ROMAN;
+ listStyleType = LIST_STYLE_TYPE_LOWER_ROMAN;
else if (*attrbuf == 'I')
- list_style_type = LIST_STYLE_TYPE_UPPER_ROMAN;
+ listStyleType = LIST_STYLE_TYPE_UPPER_ROMAN;
+
+ props.set (CssProperty::CSS_PROPERTY_LIST_STYLE_TYPE, listStyleType);
+ html->styleEngine->setNonCssHints (&props);
}
- HTML_SET_TOP_ATTR(html, listStyleType, list_style_type);
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->wordStyle ());
+ Html_add_textblock(html, 9);
+
S_TOP(html)->list_type = HTML_LIST_ORDERED;
if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "start")) &&
@@ -2750,13 +2534,16 @@ static void Html_tag_open_ol(DilloHtml *html, const char *tag, int tagsize)
*/
static void Html_tag_open_li(DilloHtml *html, const char *tag, int tagsize)
{
- StyleAttrs style_attrs;
- Style *item_style, *word_style;
+ Style *style = html->styleEngine->style ();
+ Style *wordStyle = html->styleEngine->wordStyle ();
Widget **ref_list_item;
ListItem *list_item;
int *list_number;
const char *attrbuf;
char buf[16];
+
+ if (S_TOP(html)->list_type == HTML_LIST_NONE)
+ BUG_MSG("<li> outside <ul> or <ol>\n");
html->InFlags |= IN_LI;
html->WordAfterLI = false;
@@ -2765,44 +2552,33 @@ static void Html_tag_open_li(DilloHtml *html, const char *tag, int tagsize)
list_number = &html->stack->getRef(html->stack->size()-2)->list_number;
ref_list_item = &html->stack->getRef(html->stack->size()-2)->ref_list_item;
- /* set the item style */
- word_style = S_TOP(html)->style;
- style_attrs = *word_style;
- //style_attrs.backgroundColor = Color::createShaded (HT2LT(html), 0xffff40);
- //style_attrs.setBorderColor (Color::createSimple (HT2LT(html), 0x000000));
- //style_attrs.setBorderStyle (BORDER_SOLID);
- //style_attrs.borderWidth.setVal (1);
- item_style = Style::create (HT2LT(html), &style_attrs);
-
- DW2TB(html->dw)->addParbreak (2, word_style);
+ DW2TB(html->dw)->addParbreak (2, wordStyle);
list_item = new ListItem ((ListItem*)*ref_list_item,prefs.limit_text_width);
- DW2TB(html->dw)->addWidget (list_item, item_style);
- DW2TB(html->dw)->addParbreak (2, word_style);
+ DW2TB(html->dw)->addWidget (list_item, style);
+ DW2TB(html->dw)->addParbreak (2, wordStyle);
*ref_list_item = list_item;
S_TOP(html)->textblock = html->dw = list_item;
- item_style->unref();
/* Handle it when the user clicks on a link */
html->connectSignals(list_item);
- switch (S_TOP(html)->list_type) {
- case HTML_LIST_ORDERED:
+ if (style->listStyleType == LIST_STYLE_TYPE_NONE) {
+ // none
+ } else if (style->listStyleType >= LIST_STYLE_TYPE_DECIMAL) {
+ // ordered
if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "value")) &&
(*list_number = strtol(attrbuf, NULL, 10)) < 0) {
BUG_MSG("illegal negative LIST VALUE attribute; Starting from 0\n");
*list_number = 0;
}
- numtostr((*list_number)++, buf, 16, S_TOP(html)->style->listStyleType);
- list_item->initWithText (dStrdup(buf), word_style);
- list_item->addSpace (word_style);
+ numtostr((*list_number)++, buf, 16, style->listStyleType);
+ list_item->initWithText (dStrdup(buf), wordStyle);
+ list_item->addSpace (wordStyle);
html->PrevWasSPC = true;
- break;
- case HTML_LIST_NONE:
- BUG_MSG("<li> outside <ul> or <ol>\n");
- default:
- list_item->initWithWidget (new Bullet(), word_style);
- list_item->addSpace (word_style);
- break;
+ } else {
+ // unordered
+ list_item->initWithWidget (new Bullet(), wordStyle);
+ list_item->addSpace (wordStyle);
}
}
@@ -2822,58 +2598,50 @@ static void Html_tag_close_li(DilloHtml *html, int TagIdx)
static void Html_tag_open_hr(DilloHtml *html, const char *tag, int tagsize)
{
Widget *hruler;
- StyleAttrs style_attrs;
- Style *style;
+ CssPropertyList props;
char *width_ptr;
const char *attrbuf;
int32_t size = 0;
- style_attrs = *S_TOP(html)->style;
-
- width_ptr = a_Html_get_attr_wdef(html, tag, tagsize, "width", "100%");
- style_attrs.width = a_Html_parse_length (html, width_ptr);
- dFree(width_ptr);
+ width_ptr = a_Html_get_attr_wdef(html, tag, tagsize, "width", NULL);
+ if (width_ptr) {
+ props.set (CssProperty::CSS_PROPERTY_WIDTH,
+ a_Html_parse_length (html, width_ptr));
+ dFree(width_ptr);
+ }
if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "size")))
size = strtol(attrbuf, NULL, 10);
-
- if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "align"))) {
- if (dStrcasecmp (attrbuf, "left") == 0)
- style_attrs.textAlign = TEXT_ALIGN_LEFT;
- else if (dStrcasecmp (attrbuf, "right") == 0)
- style_attrs.textAlign = TEXT_ALIGN_RIGHT;
- else if (dStrcasecmp (attrbuf, "center") == 0)
- style_attrs.textAlign = TEXT_ALIGN_CENTER;
- }
+
+ a_Html_tag_set_align_attr(html, &props, tag, tagsize);
/* TODO: evaluate attribute */
if (a_Html_get_attr(html, tag, tagsize, "noshade")) {
- style_attrs.setBorderStyle (BORDER_SOLID);
- style_attrs.setBorderColor (
- Color::createShaded (HT2LT(html), style_attrs.color->getColor()));
- if (size < 1)
+ props.set (CssProperty::CSS_PROPERTY_BORDER_TOP_STYLE, BORDER_SOLID);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_BOTTOM_STYLE, BORDER_SOLID);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_LEFT_STYLE, BORDER_SOLID);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_RIGHT_STYLE, BORDER_SOLID);
+
+ if (size <= 0)
size = 1;
- } else {
- style_attrs.setBorderStyle (BORDER_INSET);
- style_attrs.setBorderColor
- (Color::createShaded (HT2LT(html),
- S_TOP(html)->current_bg_color));
- if (size < 2)
- size = 2;
}
-
- style_attrs.borderWidth.top =
- style_attrs.borderWidth.left = (size + 1) / 2;
- style_attrs.borderWidth.bottom =
- style_attrs.borderWidth.right = size / 2;
- style = Style::create (HT2LT(html), &style_attrs);
+
+ if (size > 0) {
+ CssLength size_top = CSS_CREATE_LENGTH ((size+1)/2, CSS_LENGTH_TYPE_PX);
+ CssLength size_bottom = CSS_CREATE_LENGTH (size / 2, CSS_LENGTH_TYPE_PX);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_TOP_WIDTH, size_top);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_LEFT_WIDTH, size_top);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_BOTTOM_WIDTH, size_bottom);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_RIGHT_WIDTH, size_bottom);
+ }
- DW2TB(html->dw)->addParbreak (5, S_TOP(html)->style);
+ DW2TB(html->dw)->addParbreak (5, html->styleEngine->wordStyle ());
+
+ html->styleEngine->setNonCssHints (&props);
hruler = new Ruler();
- hruler->setStyle (style);
- DW2TB(html->dw)->addWidget (hruler, style);
- style->unref ();
- DW2TB(html->dw)->addParbreak (5, S_TOP(html)->style);
+ hruler->setStyle (html->styleEngine->style ());
+ DW2TB(html->dw)->addWidget (hruler, html->styleEngine->style ());
+ DW2TB(html->dw)->addParbreak (5, html->styleEngine->wordStyle ());
}
/*
@@ -2882,7 +2650,7 @@ static void Html_tag_open_hr(DilloHtml *html, const char *tag, int tagsize)
static void Html_tag_open_dl(DilloHtml *html, const char *tag, int tagsize)
{
/* may want to actually do some stuff here. */
- DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->wordStyle ());
}
/*
@@ -2890,8 +2658,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);
- a_Html_set_top_font(html, NULL, 0, 1, 1);
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->wordStyle ());
}
/*
@@ -2899,8 +2666,8 @@ static void Html_tag_open_dt(DilloHtml *html, const char *tag, int tagsize)
*/
static void Html_tag_open_dd(DilloHtml *html, const char *tag, int tagsize)
{
- DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
- Html_add_indented(html, 40, 40, 9);
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->wordStyle ());
+ Html_add_textblock(html, 9);
}
/*
@@ -2908,12 +2675,10 @@ static void Html_tag_open_dd(DilloHtml *html, const char *tag, int tagsize)
*/
static void Html_tag_open_pre(DilloHtml *html, const char *tag, int tagsize)
{
- DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
- a_Html_set_top_font(html, prefs.fw_fontname, 0, 0, 0);
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->wordStyle ());
/* Is the placement of this statement right? */
S_TOP(html)->parse_mode = DILLO_HTML_PARSE_MODE_PRE;
- HTML_SET_TOP_ATTR (html, whiteSpace, WHITE_SPACE_PRE);
html->pre_column = 0;
html->PreFirstChar = true;
html->InFlags |= IN_PRE;
@@ -2925,7 +2690,7 @@ static void Html_tag_open_pre(DilloHtml *html, const char *tag, int tagsize)
static void Html_tag_close_pre(DilloHtml *html, int TagIdx)
{
html->InFlags &= ~IN_PRE;
- DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->wordStyle ());
}
/*
@@ -2941,7 +2706,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])
@@ -3015,15 +2780,13 @@ static void Html_tag_open_meta(DilloHtml *html, const char *tag, int tagsize)
} else if (!dStrcasecmp(equiv, "content-type") &&
(content = a_Html_get_attr(html, tag, tagsize, "content"))) {
if (a_Misc_content_type_cmp(html->content_type, content)) {
- const bool_t force = FALSE;
const char *new_content =
- a_Capi_set_content_type(html->page_url, content, force);
+ a_Capi_set_content_type(html->page_url, content);
/* Cannot ask cache whether the content type was changed, as
* this code in another bw might have already changed it for us.
*/
if (a_Misc_content_type_cmp(html->content_type, new_content)) {
- a_Nav_repush(html->bw);
- html->stop_parser = true;
+ html->repush_after_head = true;
}
}
}
@@ -3031,6 +2794,97 @@ static void Html_tag_open_meta(DilloHtml *html, const char *tag, int tagsize)
}
/*
+ * Called by the network engine when a stylesheet has new data.
+ */
+static void Html_css_load_callback(int Op, CacheClient_t *Client)
+{
+ _MSG("Css_callback: Op=%d\n", Op);
+ if (Op) { /* EOF */
+ BrowserWindow *bw = ((DilloWeb *)Client->Web)->bw;
+ /* Repush when we've got them all */
+ if (--bw->NumPendingStyleSheets == 0)
+ a_Nav_repush(bw);
+ }
+}
+
+/*
+ * Tell cache to retrieve a stylesheet
+ */
+static void Html_load_stylesheet(DilloHtml *html, DilloUrl *url)
+{
+ char *data;
+ int len;
+ if (a_Nav_get_buf(url, &data, &len)) {
+ /* Haven't looked into what origin_count is */
+ if (a_Capi_get_flags(url) & CAPI_Completed)
+ html->styleEngine->parse(data, len, 0, CSS_ORIGIN_AUTHOR);
+ a_Nav_unref_buf(url);
+ } else if (!html->repush_after_head) {
+ /* Fill a Web structure for the cache query */
+ int ClientKey;
+ DilloWeb *Web = a_Web_new(url);
+ Web->bw = html->bw;
+ //Web->flags |= WEB_Stylesheet;
+ if ((ClientKey = a_Capi_open_url(Web, Html_css_load_callback, NULL))) {
+ ++html->bw->NumPendingStyleSheets;
+ a_Bw_add_client(html->bw, ClientKey, 0);
+ a_Bw_add_url(html->bw, url);
+ MSG("Html_load_stylesheet: NumPendingStyleSheets=%d\n",
+ html->bw->NumPendingStyleSheets);
+ }
+ }
+}
+
+/*
+ * Parse the LINK element (Only CSS stylesheets by now).
+ * (If it either hits or misses, is not relevant here; that's up to the
+ * cache functions)
+ */
+static void Html_tag_open_link(DilloHtml *html, const char *tag, int tagsize)
+{
+ DilloUrl *url;
+ const char *attrbuf;
+
+ //char *tag_str = dStrndup(tag, tagsize);
+ //MSG("Html_tag_open_link(): %s\n", tag_str);
+ //dFree(tag_str);
+
+ /* When viewing suspicious HTML email, don't load LINK */
+ if (URL_FLAGS(html->base_url) & URL_SpamSafe)
+ return;
+ /* Ignore LINK outside HEAD */
+ if (!(html->InFlags & IN_HEAD)) {
+ BUG_MSG("the LINK element must be inside the HEAD section\n");
+ return;
+ }
+
+ /* TODO: How will we know when to use "handheld"? Ask the html->bw->ui for
+ screen dimensions, or a dillorc preference. */
+
+ if (!prefs.load_stylesheets)
+ return;
+
+ /* CSS stylesheet link */
+ if ((!(attrbuf = a_Html_get_attr(html, tag, tagsize, "rel")) ||
+ dStrcasecmp(attrbuf, "stylesheet")) ||
+ (!(attrbuf = a_Html_get_attr(html, tag, tagsize, "href")) ||
+ !(url = a_Html_url_new(html, attrbuf, NULL, 0))))
+ return;
+ /* IMPLIED attributes? */
+ if (((attrbuf = a_Html_get_attr(html, tag, tagsize, "type")) &&
+ dStrcasecmp(attrbuf, "text/css")) ||
+ ((attrbuf = a_Html_get_attr(html, tag, tagsize, "media")) &&
+ !dStristr(attrbuf, "screen") && dStrcasecmp(attrbuf, "all")))
+ return;
+
+ MSG(" Html_tag_open_link(): URL=%s\n", URL_STR(url));
+ _MSG(" repush after HEAD=%d\n", html->repush_after_head);
+
+ Html_load_stylesheet(html, url);
+ a_Url_free(url);
+}
+
+/*
* Set the history of the menu to be consistent with the active menuitem.
*/
//static void Html_select_set_history(DilloHtmlInput *input)
@@ -3073,60 +2927,8 @@ static void Html_tag_open_base(DilloHtml *html, const char *tag, int tagsize)
}
}
-/*
- * <CODE>
- */
-static void Html_tag_open_code(DilloHtml *html, const char *tag, int tagsize)
-{
- a_Html_set_top_font(html, prefs.fw_fontname, 0, 0, 0);
-}
-
-/*
- * <DFN>
- */
-static void Html_tag_open_dfn(DilloHtml *html, const char *tag, int tagsize)
-{
- a_Html_set_top_font(html, NULL, 0, 2, 3);
-}
-
-/*
- * <KBD>
- */
-static void Html_tag_open_kbd(DilloHtml *html, const char *tag, int tagsize)
-{
- a_Html_set_top_font(html, prefs.fw_fontname, 0, 0, 0);
-}
-
-/*
- * <SAMP>
- */
-static void Html_tag_open_samp(DilloHtml *html, const char *tag, int tagsize)
-{
- a_Html_set_top_font(html, prefs.fw_fontname, 0, 0, 0);
-}
-
-/*
- * <VAR>
- */
-static void Html_tag_open_var(DilloHtml *html, const char *tag, int tagsize)
-{
- a_Html_set_top_font(html, NULL, 0, 2, 2);
-}
-
-/*
- * <SUB>
- */
-static void Html_tag_open_sub(DilloHtml *html, const char *tag, int tagsize)
+static void Html_tag_open_default(DilloHtml *html,const char *tag,int tagsize)
{
- HTML_SET_TOP_ATTR (html, valign, VALIGN_SUB);
-}
-
-/*
- * <SUP>
- */
-static void Html_tag_open_sup(DilloHtml *html, const char *tag, int tagsize)
-{
- HTML_SET_TOP_ATTR (html, valign, VALIGN_SUPER);
}
/*
@@ -3134,8 +2936,11 @@ static void Html_tag_open_sup(DilloHtml *html, const char *tag, int tagsize)
*/
static void Html_tag_open_div(DilloHtml *html, const char *tag, int tagsize)
{
- DW2TB(html->dw)->addParbreak (0, S_TOP(html)->style);
- a_Html_tag_set_align_attr (html, tag, tagsize);
+ CssPropertyList props;
+
+ a_Html_tag_set_align_attr (html, &props, tag, tagsize);
+ html->styleEngine->setNonCssHints (&props);
+ Html_add_textblock(html, 0);
}
/*
@@ -3143,7 +2948,7 @@ static void Html_tag_open_div(DilloHtml *html, const char *tag, int tagsize)
*/
static void Html_tag_close_div(DilloHtml *html, int TagIdx)
{
- DW2TB(html->dw)->addParbreak (0, S_TOP(html)->style);
+ DW2TB(html->dw)->addParbreak (0, html->styleEngine->wordStyle ());
}
/*
@@ -3158,7 +2963,7 @@ static void Html_tag_close_default(DilloHtml *html, int TagIdx)
*/
static void Html_tag_close_par(DilloHtml *html, int TagIdx)
{
- DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
+ DW2TB(html->dw)->addParbreak (9, html->styleEngine->wordStyle ());
}
@@ -3197,30 +3002,30 @@ const TagInfo Tags[] = {
/* acronym 010101 */
{"address", B8(010110),'R',2, Html_tag_open_address, Html_tag_close_par},
{"area", B8(010001),'F',0, Html_tag_open_area, Html_tag_close_default},
- {"b", B8(010101),'R',2, Html_tag_open_b, Html_tag_close_default},
+ {"b", B8(010101),'R',2, Html_tag_open_default, Html_tag_close_default},
{"base", B8(100001),'F',0, Html_tag_open_base, Html_tag_close_default},
/* basefont 010001 */
/* bdo 010101 */
- {"big", B8(010101),'R',2, Html_tag_open_big_small, Html_tag_close_default},
+ {"big", B8(010101),'R',2, Html_tag_open_default, Html_tag_close_default},
{"blockquote", B8(011110),'R',2,Html_tag_open_blockquote,Html_tag_close_par},
{"body", B8(011110),'O',1, Html_tag_open_body, Html_tag_close_body},
{"br", B8(010001),'F',0, Html_tag_open_br, Html_tag_close_default},
{"button", B8(011101),'R',2, Html_tag_open_button, Html_tag_close_button},
/* caption */
{"center", B8(011110),'R',2, Html_tag_open_center, Html_tag_close_div},
- {"cite", B8(010101),'R',2, Html_tag_open_cite, Html_tag_close_default},
- {"code", B8(010101),'R',2, Html_tag_open_code, Html_tag_close_default},
+ {"cite", B8(010101),'R',2, Html_tag_open_default, Html_tag_close_default},
+ {"code", B8(010101),'R',2, Html_tag_open_default, Html_tag_close_default},
/* col 010010 'F' */
/* colgroup */
{"dd", B8(011110),'O',1, Html_tag_open_dd, Html_tag_close_par},
- {"del", B8(011101),'R',2, Html_tag_open_strike, Html_tag_close_default},
- {"dfn", B8(010101),'R',2, Html_tag_open_dfn, Html_tag_close_default},
+ {"del", B8(011101),'R',2, Html_tag_open_default, Html_tag_close_default},
+ {"dfn", B8(010101),'R',2, Html_tag_open_default, Html_tag_close_default},
{"dir", B8(011010),'R',2, Html_tag_open_dir, Html_tag_close_par},
/* TODO: complete <div> support! */
{"div", B8(011110),'R',2, Html_tag_open_div, Html_tag_close_div},
{"dl", B8(011010),'R',2, Html_tag_open_dl, Html_tag_close_par},
{"dt", B8(010110),'O',1, Html_tag_open_dt, Html_tag_close_par},
- {"em", B8(010101),'R',2, Html_tag_open_em, Html_tag_close_default},
+ {"em", B8(010101),'R',2, Html_tag_open_default, Html_tag_close_default},
/* fieldset */
{"font", B8(010101),'R',2, Html_tag_open_font, Html_tag_close_default},
{"form", B8(011110),'R',2, Html_tag_open_form, Html_tag_close_form},
@@ -3235,17 +3040,17 @@ const TagInfo Tags[] = {
{"head", B8(101101),'O',1, Html_tag_open_head, Html_tag_close_head},
{"hr", B8(010010),'F',0, Html_tag_open_hr, Html_tag_close_default},
{"html", B8(001110),'O',1, Html_tag_open_html, Html_tag_close_html},
- {"i", B8(010101),'R',2, Html_tag_open_i, Html_tag_close_default},
+ {"i", B8(010101),'R',2, Html_tag_open_default, Html_tag_close_default},
{"iframe", B8(011110),'R',2, Html_tag_open_frame, Html_tag_close_default},
{"img", B8(010001),'F',0, Html_tag_open_img, Html_tag_close_default},
{"input", B8(010001),'F',0, Html_tag_open_input, Html_tag_close_default},
/* ins */
{"isindex", B8(110001),'F',0, Html_tag_open_isindex, Html_tag_close_default},
- {"kbd", B8(010101),'R',2, Html_tag_open_kbd, Html_tag_close_default},
+ {"kbd", B8(010101),'R',2, Html_tag_open_default, Html_tag_close_default},
/* label 010101 */
/* legend 01?? */
{"li", B8(011110),'O',1, Html_tag_open_li, Html_tag_close_li},
- /* link 100000 'F' */
+ {"link", B8(100001),'F',0, Html_tag_open_link, Html_tag_close_default},
{"map", B8(011001),'R',2, Html_tag_open_map, Html_tag_close_map},
/* menu 1010 -- TODO: not exactly 1010, it can contain LI and inline */
{"menu", B8(011010),'R',2, Html_tag_open_menu, Html_tag_close_par},
@@ -3260,17 +3065,17 @@ const TagInfo Tags[] = {
/* param 010001 'F' */
{"pre", B8(010110),'R',2, Html_tag_open_pre, Html_tag_close_pre},
{"q", B8(010101),'R',2, Html_tag_open_q, Html_tag_close_q},
- {"s", B8(010101),'R',2, Html_tag_open_strike, Html_tag_close_default},
- {"samp", B8(010101),'R',2, Html_tag_open_samp, Html_tag_close_default},
+ {"s", B8(010101),'R',2, Html_tag_open_default, Html_tag_close_default},
+ {"samp", B8(010101),'R',2, Html_tag_open_default, Html_tag_close_default},
{"script", B8(111001),'R',2, Html_tag_open_script, Html_tag_close_script},
{"select", B8(010101),'R',2, Html_tag_open_select, Html_tag_close_select},
- {"small", B8(010101),'R',2, Html_tag_open_big_small, Html_tag_close_default},
- /* span 0101 */
- {"strike", B8(010101),'R',2, Html_tag_open_strike, Html_tag_close_default},
- {"strong", B8(010101),'R',2, Html_tag_open_strong, Html_tag_close_default},
+ {"small", B8(010101),'R',2, Html_tag_open_default, Html_tag_close_default},
+ {"span", B8(010101),'R',2, Html_tag_open_span, Html_tag_close_default},
+ {"strike", B8(010101),'R',2, Html_tag_open_default, Html_tag_close_default},
+ {"strong", B8(010101),'R',2, Html_tag_open_default, Html_tag_close_default},
{"style", B8(100101),'R',2, Html_tag_open_style, Html_tag_close_style},
- {"sub", B8(010101),'R',2, Html_tag_open_sub, Html_tag_close_default},
- {"sup", B8(010101),'R',2, Html_tag_open_sup, Html_tag_close_default},
+ {"sub", B8(010101),'R',2, Html_tag_open_default, Html_tag_close_default},
+ {"sup", B8(010101),'R',2, Html_tag_open_default, Html_tag_close_default},
{"table", B8(011010),'R',5, Html_tag_open_table, Html_tag_close_div},
/* tbody */
{"td", B8(011110),'O',3, Html_tag_open_td, Html_tag_close_default},
@@ -3280,10 +3085,10 @@ const TagInfo Tags[] = {
/* thead */
{"title", B8(100101),'R',2, Html_tag_open_title, Html_tag_close_title},
{"tr", B8(011010),'O',4, Html_tag_open_tr, Html_tag_close_default},
- {"tt", B8(010101),'R',2, Html_tag_open_tt, Html_tag_close_default},
- {"u", B8(010101),'R',2, Html_tag_open_u, Html_tag_close_default},
+ {"tt", B8(010101),'R',2, Html_tag_open_default, Html_tag_close_default},
+ {"u", B8(010101),'R',2, Html_tag_open_default, Html_tag_close_default},
{"ul", B8(011010),'R',2, Html_tag_open_ul, Html_tag_close_par},
- {"var", B8(010101),'R',2, Html_tag_open_var, Html_tag_close_default}
+ {"var", B8(010101),'R',2, Html_tag_open_default, Html_tag_close_default}
};
#define NTAGS (sizeof(Tags)/sizeof(Tags[0]))
@@ -3309,7 +3114,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;
@@ -3340,17 +3145,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) {
@@ -3447,7 +3252,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);
@@ -3460,7 +3265,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);
@@ -3473,11 +3278,11 @@ static void Html_test_section(DilloHtml *html, int new_idx, int IsCloseTag)
/* body element */
if (html->InFlags & IN_HEAD) {
tag = "</head>";
- tag_idx = Html_tag_index(tag + 2);
+ tag_idx = a_Html_tag_index(tag + 2);
Html_tag_cleanup_at_close(html, tag_idx);
}
tag = "<body>";
- tag_idx = Html_tag_index(tag + 1);
+ tag_idx = a_Html_tag_index(tag + 1);
if (tag_idx != new_idx || IsCloseTag) {
/* implicit open */
Html_force_push_tag(html, tag_idx);
@@ -3499,7 +3304,9 @@ 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);
+ dReturn_if_fail ( html->stop_parser == false );
+
+ 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)) {
@@ -3533,11 +3340,8 @@ static void Html_process_tag(DilloHtml *html, char *tag, int tagsize)
/* Push the tag into the stack */
Html_push_tag(html, ni);
- /* Call the open function for this tag */
+ html->styleEngine->startElement (ni);
_MSG("Open : %*s%s\n", html->stack->size(), " ", Tags[ni].name);
- Tags[ni].open (html, tag, tagsize);
- if (html->stop_parser)
- break;
/* Now parse attributes that can appear on any tag */
if (tagsize >= 8 && /* length of "<t id=i>" */
@@ -3549,6 +3353,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)) {
@@ -3564,6 +3371,24 @@ 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 */
+ _MSG("Open : %s\n", Tags[ni].name);
+ Tags[ni].open (html, tag, tagsize);
+
/* Request inmediate close for elements with forbidden close tag. */
/* TODO: XHTML always requires close tags. A simple implementation
* of the commented clause below will make it work. */
@@ -3582,6 +3407,7 @@ static void Html_process_tag(DilloHtml *html, char *tag, int tagsize)
(strchr(" \"'", tag[tagsize-3]) || /* [ "']/> */
(size_t)tagsize == strlen(Tags[ni].name) + 3))) { /* <x/> */
+ _MSG("Close: %s\n", Tags[ni].name);
Html_tag_cleanup_at_close(html, ni);
/* This was a close tag */
html->ReqTagClose = false;
@@ -3726,29 +3552,6 @@ char *a_Html_get_attr_wdef(DilloHtml *html,
}
/*
- * Add a widget to the page.
- */
-static void Html_add_widget(DilloHtml *html,
- Widget *widget,
- char *width_str,
- char *height_str,
- StyleAttrs *style_attrs)
-{
- StyleAttrs new_style_attrs;
- Style *style;
-
- new_style_attrs = *style_attrs;
- new_style_attrs.width = width_str ?
- a_Html_parse_length (html, width_str) : LENGTH_AUTO;
- new_style_attrs.height = height_str ?
- a_Html_parse_length (html, height_str) : LENGTH_AUTO;
- style = Style::create (HT2LT(html), &new_style_attrs);
- DW2TB(html->dw)->addWidget (widget, style);
- style->unref ();
-}
-
-
-/*
* Dispatch the apropriate function for 'Op'
* This function is a Cache client and gets called whenever new data arrives
* Op : operation to perform.
diff --git a/src/html_common.hh b/src/html_common.hh
index 302d9ece..aaab4861 100644
--- a/src/html_common.hh
+++ b/src/html_common.hh
@@ -13,6 +13,8 @@
#include "form.hh"
+#include "styleengine.hh"
+
/*
* Macros
*/
@@ -36,6 +38,7 @@
* Change one toplevel attribute. var should be an identifier. val is
* only evaluated once, so you can safely use a function call for it.
*/
+#if 0
#define HTML_SET_TOP_ATTR(html, var, val) \
do { \
StyleAttrs style_attrs; \
@@ -48,7 +51,9 @@
Style::create (HT2LT(html), &style_attrs); \
old_style->unref (); \
} while (FALSE)
-
+#else
+#define HTML_SET_TOP_ATTR(html, var, val)
+#endif
/*
* Typedefs
*/
@@ -109,7 +114,7 @@ struct _DilloLinkImage {
};
struct _DilloHtmlState {
- dw::core::style::Style *style, *table_cell_style;
+ CssPropertyList *table_cell_props;
DilloHtmlParseMode parse_mode;
DilloHtmlTableMode table_mode;
bool cell_text_align_set;
@@ -167,6 +172,8 @@ public: //BUG: for now everything is public
char *content_type, *charset;
bool stop_parser;
+ bool repush_after_head;
+
size_t CurrTagOfs;
size_t OldTagOfs, OldTagLine;
@@ -174,6 +181,7 @@ public: //BUG: for now everything is public
float DocTypeVersion; /* HTML or XHTML version number */
lout::misc::SimpleVector<DilloHtmlState> *stack;
+ StyleEngine *styleEngine;
int InFlags; /* tracks which elements we are in */
@@ -232,6 +240,8 @@ public:
* Parser functions
*/
+int a_Html_tag_index(const char *tag);
+
const char *a_Html_get_attr(DilloHtml *html,
const char *tag,
int tagsize,
@@ -249,7 +259,6 @@ DilloUrl *a_Html_url_new(DilloHtml *html,
DilloImage *a_Html_add_new_image(DilloHtml *html, const char *tag,
int tagsize, DilloUrl *url,
- dw::core::style::StyleAttrs *style_attrs,
bool add);
char *a_Html_parse_entities(DilloHtml *html, const char *token, int toksize);
@@ -259,12 +268,10 @@ 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);
-void a_Html_set_top_font(DilloHtml *html, const char *name, int size,
- int BI, int BImask);
+ CssPropertyList *props);
#endif /* __HTML_COMMON_HH__ */
diff --git a/src/image.cc b/src/image.cc
index 462ec90c..fa4f5516 100644
--- a/src/image.cc
+++ b/src/image.cc
@@ -31,13 +31,6 @@ using namespace dw::core;
/*
- * Local data
- */
-static size_t linebuf_size = 0;
-static uchar_t *linebuf = NULL;
-
-
-/*
* Create and initialize a new image structure.
*/
DilloImage *a_Image_new(int width,
@@ -92,37 +85,6 @@ void a_Image_ref(DilloImage *Image)
}
/*
- * Decode 'buf' (an image line) into RGB format.
- */
-static uchar_t *
- Image_line(DilloImage *Image, const uchar_t *buf, const uchar_t *cmap, int y)
-{
- uint_t x;
-
- switch (Image->in_type) {
- case DILLO_IMG_TYPE_INDEXED:
- if (cmap) {
- for (x = 0; x < Image->width; x++)
- memcpy(linebuf + x * 3, cmap + buf[x] * 3, 3);
- } else {
- MSG("Gif:: WARNING, image lacks a color map\n");
- }
- break;
- case DILLO_IMG_TYPE_GRAY:
- for (x = 0; x < Image->width; x++)
- memset(linebuf + x * 3, buf[x], 3);
- break;
- case DILLO_IMG_TYPE_RGB:
- /* avoid a memcpy here! --Jcid */
- return (uchar_t *)buf;
- case DILLO_IMG_TYPE_NOTSET:
- MSG_ERR("Image_line: type not set...\n");
- break;
- }
- return linebuf;
-}
-
-/*
* Set initial parameters of the image
*/
void a_Image_set_parms(DilloImage *Image, void *v_imgbuf, DilloUrl *url,
@@ -139,10 +101,6 @@ void a_Image_set_parms(DilloImage *Image, void *v_imgbuf, DilloUrl *url,
Image->in_type = type;
Image->width = width;
Image->height = height;
- if (3 * width > linebuf_size) {
- linebuf_size = 3 * width;
- linebuf = (uchar_t*) dRealloc(linebuf, linebuf_size);
- }
Image->State = IMG_SetParms;
}
@@ -151,6 +109,7 @@ void a_Image_set_parms(DilloImage *Image, void *v_imgbuf, DilloUrl *url,
*/
void a_Image_set_cmap(DilloImage *Image, const uchar_t *cmap)
{
+ _MSG("a_Image_set_cmap\n");
Image->cmap = cmap;
Image->State = IMG_SetCmap;
}
@@ -160,6 +119,7 @@ void a_Image_set_cmap(DilloImage *Image, const uchar_t *cmap)
*/
void a_Image_new_scan(DilloImage *Image, void *v_imgbuf)
{
+ _MSG("a_Image_new_scan\n");
a_Bitvec_clear(Image->BitVec);
Image->ScanNumber++;
((Imgbuf*)v_imgbuf)->newScan();
@@ -168,23 +128,15 @@ void a_Image_new_scan(DilloImage *Image, void *v_imgbuf)
/*
* Implement the write method
*/
-void a_Image_write(DilloImage *Image, void *v_imgbuf,
- const uchar_t *buf, uint_t y, int decode)
+void a_Image_write(DilloImage *Image, uint_t y)
{
- const uchar_t *newbuf;
-
+ _MSG("a_Image_write\n");
dReturn_if_fail ( y < Image->height );
- if (decode) {
- /* Decode 'buf' and copy it into the DicEntry buffer */
- newbuf = Image_line(Image, buf, Image->cmap, y);
- ((Imgbuf*)v_imgbuf)->copyRow(y, (byte *)newbuf);
- }
- a_Bitvec_set_bit(Image->BitVec, y);
- Image->State = IMG_Write;
-
/* Update the row in DwImage */
OI(Image)->drawRow(y);
+ a_Bitvec_set_bit(Image->BitVec, y);
+ Image->State = IMG_Write;
}
/*
@@ -192,46 +144,7 @@ void a_Image_write(DilloImage *Image, void *v_imgbuf,
*/
void a_Image_close(DilloImage *Image)
{
+ MSG("a_Image_close\n");
a_Image_unref(Image);
}
-
-// Wrappers for Imgbuf -------------------------------------------------------
-
-/*
- * Increment reference count for an Imgbuf
- */
-void a_Image_imgbuf_ref(void *v_imgbuf)
-{
- ((Imgbuf*)v_imgbuf)->ref();
-}
-
-/*
- * Decrement reference count for an Imgbuf
- */
-void a_Image_imgbuf_unref(void *v_imgbuf)
-{
- ((Imgbuf*)v_imgbuf)->unref();
-}
-
-/*
- * Create a new Imgbuf
- */
-void *a_Image_imgbuf_new(void *v_dw, int img_type, int width, int height)
-{
- Layout *layout = ((Widget*)v_dw)->getLayout();
- if (!layout) {
- MSG_ERR("a_Image_imgbuf_new: layout is NULL.\n");
- exit(1);
- }
- return (void*)layout->createImgbuf(Imgbuf::RGB, width, height);
-}
-
-/*
- * Last reference for this Imgbuf?
- */
-int a_Image_imgbuf_last_reference(void *v_imgbuf)
-{
- return ((Imgbuf*)v_imgbuf)->lastReference () ? 1 : 0;
-}
-
diff --git a/src/image.hh b/src/image.hh
index ce906c74..d4525ba2 100644
--- a/src/image.hh
+++ b/src/image.hh
@@ -63,14 +63,9 @@ void a_Image_set_parms(DilloImage *Image, void *v_imgbuf, DilloUrl *url,
DilloImgType type);
void a_Image_set_cmap(DilloImage *Image, const uchar_t *cmap);
void a_Image_new_scan(DilloImage *image, void *v_imgbuf);
-void a_Image_write(DilloImage *Image, void *v_imgbuf,
- const uchar_t *buf, uint_t y, int decode);
+void a_Image_write(DilloImage *Image, uint_t y);
void a_Image_close(DilloImage *Image);
-void a_Image_imgbuf_ref(void *v_imgbuf);
-void a_Image_imgbuf_unref(void *v_imgbuf);
-void *a_Image_imgbuf_new(void *v_dw, int img_type, int width, int height) ;
-int a_Image_imgbuf_last_reference(void *v_imgbuf);
#ifdef __cplusplus
}
diff --git a/src/imgbuf.cc b/src/imgbuf.cc
new file mode 100644
index 00000000..ee8f918a
--- /dev/null
+++ b/src/imgbuf.cc
@@ -0,0 +1,117 @@
+/*
+ * File: imgbuf.cc
+ *
+ * Copyright (C) 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 "msg.h"
+#include "imgbuf.hh"
+#include "dw/core.hh"
+#include "dw/image.hh"
+
+using namespace dw::core;
+
+/*
+ * Local data
+ */
+static size_t linebuf_size = 0;
+static uchar_t *linebuf = NULL;
+
+
+/*
+ * Decode 'buf' (an image line) into RGB format.
+ */
+static uchar_t *Imgbuf_rgb_line(const uchar_t *buf,
+ DilloImgType type, uchar_t *cmap,
+ uint_t width, uint_t y)
+{
+ uint_t x;
+
+ switch (type) {
+ case DILLO_IMG_TYPE_INDEXED:
+ if (cmap) {
+ for (x = 0; x < width; x++)
+ memcpy(linebuf + x * 3, cmap + buf[x] * 3, 3);
+ } else {
+ MSG("Gif:: WARNING, image lacks a color map\n");
+ }
+ break;
+ case DILLO_IMG_TYPE_GRAY:
+ for (x = 0; x < width; x++)
+ memset(linebuf + x * 3, buf[x], 3);
+ break;
+ case DILLO_IMG_TYPE_RGB:
+ /* avoid a memcpy here! --Jcid */
+ return (uchar_t *)buf;
+ case DILLO_IMG_TYPE_NOTSET:
+ MSG_ERR("Imgbuf_rgb_line: type not set...\n");
+ break;
+ }
+ return linebuf;
+}
+
+// Wrappers for Imgbuf -------------------------------------------------------
+
+/*
+ * Increment reference count for an Imgbuf
+ */
+void a_Imgbuf_ref(void *v_imgbuf)
+{
+ ((Imgbuf*)v_imgbuf)->ref();
+}
+
+/*
+ * Decrement reference count for an Imgbuf
+ */
+void a_Imgbuf_unref(void *v_imgbuf)
+{
+ if (v_imgbuf)
+ ((Imgbuf*)v_imgbuf)->unref();
+}
+
+/*
+ * Create a new Imgbuf
+ */
+void *a_Imgbuf_new(void *v_dw, int img_type, uint_t width, uint_t height)
+{
+ Layout *layout = ((Widget*)v_dw)->getLayout();
+ if (!layout) {
+ MSG_ERR("a_Imgbuf_new: layout is NULL.\n");
+ exit(1);
+ }
+ // Assert linebuf is wide enough.
+ if (3 * width > linebuf_size) {
+ linebuf_size = 3 * width;
+ linebuf = (uchar_t*) dRealloc(linebuf, linebuf_size);
+ }
+
+ return (void*)layout->createImgbuf(Imgbuf::RGB, width, height);
+}
+
+/*
+ * Last reference for this Imgbuf?
+ */
+int a_Imgbuf_last_reference(void *v_imgbuf)
+{
+ return ((Imgbuf*)v_imgbuf)->lastReference () ? 1 : 0;
+}
+
+/*
+ * Update the root buffer of an imgbuf.
+ */
+void a_Imgbuf_update(void *v_imgbuf, const uchar_t *buf, DilloImgType type,
+ uchar_t *cmap, uint_t width, uint_t height, uint_t y)
+
+{
+ dReturn_if_fail ( y < height );
+
+ /* Decode 'buf' and copy it into the imgbuf */
+ uchar_t *newbuf = Imgbuf_rgb_line(buf, type, cmap, width, y);
+ ((Imgbuf*)v_imgbuf)->copyRow(y, (byte *)newbuf);
+}
+
diff --git a/src/imgbuf.hh b/src/imgbuf.hh
new file mode 100644
index 00000000..3cab68a0
--- /dev/null
+++ b/src/imgbuf.hh
@@ -0,0 +1,30 @@
+#ifndef __IMGBUF_HH__
+#define __IMGBUF_HH__
+
+// Imgbuf wrappers
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#include "image.hh"
+
+/*
+ * Function prototypes
+ */
+void a_Imgbuf_ref(void *v_imgbuf);
+void a_Imgbuf_unref(void *v_imgbuf);
+void *a_Imgbuf_new(void *v_dw, int img_type, uint_t width, uint_t height);
+int a_Imgbuf_last_reference(void *v_imgbuf);
+void a_Imgbuf_update(void *v_imgbuf, const uchar_t *buf, DilloImgType type,
+ uchar_t *cmap, uint_t width, uint_t height, uint_t y);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __IMGBUF_HH__ */
+
diff --git a/src/jpeg.c b/src/jpeg.c
index 9e548a7c..4da2d39e 100644
--- a/src/jpeg.c
+++ b/src/jpeg.c
@@ -84,7 +84,6 @@ typedef struct DilloJpeg {
static DilloJpeg *Jpeg_new(DilloImage *Image, DilloUrl *url, int version);
static void Jpeg_callback(int Op, CacheClient_t *Client);
static void Jpeg_write(DilloJpeg *jpeg, void *Buf, uint_t BufSize);
-static void Jpeg_close(DilloJpeg *jpeg, CacheClient_t *Client);
METHODDEF(void) Jpeg_errorexit (j_common_ptr cinfo);
/* exported function */
@@ -103,7 +102,8 @@ METHODDEF(void) Jpeg_errorexit (j_common_ptr cinfo)
/*
* MIME handler for "image/jpeg" type
- * (Sets Jpeg_callback or a_Dicache_callback as the cache-client)
+ * Sets a_Dicache_callback as the cache-client,
+ * and Jpeg_callback as the image decoder.
*/
void *a_Jpeg_image(const char *Type, void *P, CA_Callback_t *Call,
void **Data)
@@ -117,20 +117,20 @@ void *a_Jpeg_image(const char *Type, void *P, CA_Callback_t *Call,
/* Add an extra reference to the Image (for dicache usage) */
a_Image_ref(web->Image);
- DicEntry = a_Dicache_get_entry(web->url);
+ DicEntry = a_Dicache_get_entry(web->url, DIC_Last);
if (!DicEntry) {
/* Let's create an entry for this image... */
DicEntry = a_Dicache_add_entry(web->url);
-
- /* ... and let the decoder feed it! */
- *Data = Jpeg_new(web->Image, DicEntry->url, DicEntry->version);
- *Call = (CA_Callback_t) Jpeg_callback;
+ DicEntry->DecoderData =
+ Jpeg_new(web->Image, DicEntry->url, DicEntry->version);
} else {
- /* Let's feed our client from the dicache */
+ /* Repeated image */
a_Dicache_ref(DicEntry->url, DicEntry->version);
- *Data = web->Image;
- *Call = (CA_Callback_t) a_Dicache_callback;
}
+ DicEntry->Decoder = Jpeg_callback;
+ *Data = DicEntry->DecoderData;
+ *Call = (CA_Callback_t) a_Dicache_callback;
+
return (web->Image->dw);
}
@@ -139,6 +139,7 @@ void *a_Jpeg_image(const char *Type, void *P, CA_Callback_t *Call,
*/
static void Jpeg_close(DilloJpeg *jpeg, CacheClient_t *Client)
{
+ MSG("Jpeg_close\n");
a_Dicache_close(jpeg->url, jpeg->version, Client);
jpeg_destroy_decompress(&(jpeg->cinfo));
dFree(jpeg);
@@ -330,7 +331,7 @@ static void Jpeg_write(DilloJpeg *jpeg, void *Buf, uint_t BufSize)
if (jpeg->state == DILLO_JPEG_READ_BEGIN_SCAN) {
if (jpeg_start_output(&jpeg->cinfo, jpeg->cinfo.input_scan_number)) {
- a_Dicache_new_scan(jpeg->Image, jpeg->url, jpeg->version);
+ a_Dicache_new_scan(jpeg->url, jpeg->version);
jpeg->state = DILLO_JPEG_READ_IN_SCAN;
}
}
@@ -389,7 +390,7 @@ static void Jpeg_write(DilloJpeg *jpeg, void *Buf, uint_t BufSize)
/* out of input */
break;
}
- a_Dicache_new_scan(jpeg->Image, jpeg->url, jpeg->version);
+ a_Dicache_new_scan(jpeg->url, jpeg->version);
jpeg->state = DILLO_JPEG_READ_IN_SCAN;
}
}
diff --git a/src/nav.c b/src/nav.c
index 8acf9130..ad8eb43b 100644
--- a/src/nav.c
+++ b/src/nav.c
@@ -378,10 +378,14 @@ static void Nav_repush_callback(void *data)
* Repush current URL: not an end-to-end reload but from cache.
* - Currently used to switch to a charset decoder given by the META element.
* - Delayed to let dillo finish the call flow into a known state.
+ *
+ * There's no need to stop the parser before calling this function:
+ * When the timeout activates, a_Bw_stop_clients will stop the data feed.
*/
void a_Nav_repush(BrowserWindow *bw)
{
dReturn_if_fail (bw != NULL);
+ MSG(">>> a_Nav_repush <<<<\n");
a_Timeout_add(0.0, Nav_repush_callback, (void*)bw);
}
diff --git a/src/plain.cc b/src/plain.cc
index b75dbea5..8826dafe 100644
--- a/src/plain.cc
+++ b/src/plain.cc
@@ -108,9 +108,9 @@ DilloPlain::DilloPlain(BrowserWindow *p_bw, const DilloUrl *p_url)
styleAttrs.initValues ();
styleAttrs.margin.setVal (5);
styleAttrs.font = style::Font::create (layout, &fontAttrs);
- styleAttrs.color = style::Color::createSimple (layout, prefs.text_color);
+ styleAttrs.color = style::Color::create (layout, prefs.text_color);
styleAttrs.backgroundColor =
- style::Color::createSimple (layout, prefs.bg_color);
+ style::Color::create (layout, prefs.bg_color);
widgetStyle = style::Style::create (layout, &styleAttrs);
/* The context menu */
diff --git a/src/png.c b/src/png.c
index e9b0b843..f7e2de8d 100644
--- a/src/png.c
+++ b/src/png.c
@@ -231,8 +231,9 @@ static void
png_progressive_combine_row(png_ptr, png->row_pointers[row_num], new_row);
+ _MSG("png: row_num=%u previous_row=%u\n", row_num, png->previous_row);
if (row_num < png->previous_row) {
- a_Dicache_new_scan(png->Image, png->url, png->version);
+ a_Dicache_new_scan(png->url, png->version);
}
png->previous_row = row_num;
@@ -303,12 +304,14 @@ static void
*/
static void Png_close(DilloPng *png, CacheClient_t *Client)
{
- /* Free up the resources for this image */
+ MSG("Png_close\n");
+ /* Let dicache know decoding is over */
a_Dicache_close(png->url, png->version, Client);
+
+ /* Free up the resources for this image */
dFree(png->image_data);
dFree(png->row_pointers);
dFree(png->linebuf);
-
if (setjmp(png->jmpbuf))
MSG_WARN("PNG: can't destroy read structure\n");
else if (png->png_ptr)
@@ -443,8 +446,9 @@ static DilloPng *Png_new(DilloImage *Image, DilloUrl *url, int version)
}
/*
- * MIME handler for "image/png" type
- * (Sets Png_callback or a_Dicache_callback as the cache-client)
+ * MIME handler for "image/png" type.
+ * Sets a_Dicache_callback as the cache-client,
+ * and Png_callback as the image decoder.
*
* Parameters:
* Type: MIME type
@@ -464,20 +468,20 @@ void *a_Png_image(const char *Type, void *Ptr, CA_Callback_t *Call,
/* Add an extra reference to the Image (for dicache usage) */
a_Image_ref(web->Image);
- DicEntry = a_Dicache_get_entry(web->url);
+ DicEntry = a_Dicache_get_entry(web->url, DIC_Last);
if (!DicEntry) {
/* Let's create an entry for this image... */
DicEntry = a_Dicache_add_entry(web->url);
-
- /* ... and let the decoder feed it! */
- *Data = Png_new(web->Image, DicEntry->url, DicEntry->version);
- *Call = (CA_Callback_t) Png_callback;
+ DicEntry->DecoderData =
+ Png_new(web->Image, DicEntry->url, DicEntry->version);
} else {
- /* Let's feed our client from the dicache */
+ /* Repeated image */
a_Dicache_ref(DicEntry->url, DicEntry->version);
- *Data = web->Image;
- *Call = (CA_Callback_t) a_Dicache_callback;
}
+ DicEntry->Decoder = Png_callback;
+ *Data = DicEntry->DecoderData;
+ *Call = (CA_Callback_t) a_Dicache_callback;
+
return (web->Image->dw);
}
diff --git a/src/prefs.c b/src/prefs.c
index d7042924..2c8ec5df 100644
--- a/src/prefs.c
+++ b/src/prefs.c
@@ -73,6 +73,7 @@ typedef enum {
DRC_TOKEN_LIMIT_TEXT_WIDTH,
DRC_TOKEN_LINK_COLOR,
DRC_TOKEN_LOAD_IMAGES,
+ DRC_TOKEN_LOAD_STYLESHEETS,
DRC_TOKEN_BUFFERED_DRAWING,
DRC_TOKEN_MIDDLE_CLICK_OPENS_NEW_TAB,
DRC_TOKEN_NOPROXY,
@@ -138,6 +139,7 @@ static const SymNode_t symbols[] = {
{ "limit_text_width", DRC_TOKEN_LIMIT_TEXT_WIDTH },
{ "link_color", DRC_TOKEN_LINK_COLOR },
{ "load_images", DRC_TOKEN_LOAD_IMAGES },
+ { "load_stylesheets", DRC_TOKEN_LOAD_STYLESHEETS },
{ "middle_click_drags_page", DRC_TOKEN_MIDDLE_CLICK_DRAGS_PAGE },
{ "middle_click_opens_new_tab", DRC_TOKEN_MIDDLE_CLICK_OPENS_NEW_TAB },
{ "no_proxy", DRC_TOKEN_NOPROXY },
@@ -324,6 +326,9 @@ static int Prefs_parse_pair(char *name, char *value)
case DRC_TOKEN_LOAD_IMAGES:
prefs.load_images = (strcmp(value, "YES") == 0);
break;
+ case DRC_TOKEN_LOAD_STYLESHEETS:
+ prefs.load_stylesheets = (strcmp(value, "YES") == 0);
+ break;
case DRC_TOKEN_BUFFERED_DRAWING:
prefs.buffered_drawing = atoi(value);
break;
@@ -450,6 +455,7 @@ void a_Prefs_init(void)
prefs.show_progress_box=TRUE;
prefs.fullwindow_start=FALSE;
prefs.load_images=TRUE;
+ prefs.load_stylesheets=TRUE;
prefs.buffered_drawing=1;
prefs.vw_fontname = dStrdup(D_VW_FONTNAME);
prefs.fw_fontname = dStrdup(D_FW_FONTNAME);
diff --git a/src/prefs.h b/src/prefs.h
index a12e5a37..67607533 100644
--- a/src/prefs.h
+++ b/src/prefs.h
@@ -57,6 +57,7 @@ struct _DilloPrefs {
bool_t show_progress_box;
bool_t fullwindow_start;
bool_t load_images;
+ bool_t load_stylesheets;
int32_t buffered_drawing;
char *vw_fontname;
char *fw_fontname;
diff --git a/src/styleengine.cc b/src/styleengine.cc
new file mode 100644
index 00000000..bd5c60ed
--- /dev/null
+++ b/src/styleengine.cc
@@ -0,0 +1,426 @@
+/*
+ * File: styleengine.cc
+ *
+ * Copyright 2008 Jorge Arellano Cid <jcid@dillo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <stdio.h>
+#include <math.h>
+#include "../dlib/dlib.h"
+#include "styleengine.hh"
+
+using namespace dw::core::style;
+
+StyleEngine::StyleEngine (dw::core::Layout *layout) {
+ StyleAttrs style_attrs;
+ FontAttrs font_attrs;
+
+ stack = new lout::misc::SimpleVector <Node> (1);
+ cssContext = new CssContext ();
+ this->layout = layout;
+
+ stack->increase ();
+ Node *n = stack->getRef (stack->size () - 1);
+
+ /* Create a dummy font, attribute, and tag for the bottom of the stack. */
+ font_attrs.name = "helvetica";
+ font_attrs.size = 12;
+ font_attrs.weight = 400;
+ font_attrs.style = FONT_STYLE_NORMAL;
+
+ style_attrs.initValues ();
+ style_attrs.font = Font::create (layout, &font_attrs);
+ style_attrs.color = Color::create (layout, 0);
+ style_attrs.backgroundColor = Color::create (layout, 0xffffff);
+
+ n->style = Style::create (layout, &style_attrs);
+ n->wordStyle = NULL;
+ n->pseudo = NULL;
+ n->styleAttribute = NULL;
+ n->inheritBackgroundColor = false;
+}
+
+StyleEngine::~StyleEngine () {
+ /* \todo clear stack if not empty */
+ delete stack;
+ delete cssContext;
+}
+
+/**
+ * \brief tell the styleEngine that a new html element has started.
+ */
+void StyleEngine::startElement (int element) {
+// fprintf(stderr, "===> START %d\n", element);
+
+ if (stack->getRef (stack->size () - 1)->style == NULL)
+ style0 ();
+
+ stack->increase ();
+ Node *n = stack->getRef (stack->size () - 1);
+ n->style = NULL;
+ n->wordStyle = NULL;
+ n->depth = stack->size () - 1;
+ n->element = element;
+ n->id = NULL;
+ n->klass = NULL;
+ n->pseudo = NULL;
+ n->styleAttribute = NULL;
+ n->inheritBackgroundColor = false;
+}
+
+void StyleEngine::setId (const char *id) {
+ Node *n = stack->getRef (stack->size () - 1);
+ assert (n->id == NULL);
+ n->id = dStrdup (id);
+};
+
+void StyleEngine::setClass (const char *klass) {
+ Node *n = stack->getRef (stack->size () - 1);
+ assert (n->klass == NULL);
+ n->klass = dStrdup (klass);
+};
+
+void StyleEngine::setStyle (const char *style) {
+ Node *n = stack->getRef (stack->size () - 1);
+ assert (n->styleAttribute == NULL);
+ n->styleAttribute = dStrdup (style);
+};
+
+/**
+ * \brief set properties that were definded using (mostly deprecated) HTML
+ * attributes (e.g. bgColor).
+ */
+void StyleEngine::setNonCssHints (CssPropertyList *nonCssHints) {
+ if (stack->getRef (stack->size () - 1)->style)
+ stack->getRef (stack->size () - 1)->style->unref ();
+ style0 (nonCssHints); // evaluate now, so caller can free nonCssHints
+}
+
+/**
+ * \brief Use of the background color of the parent style as default.
+ * This is only used in table code to allow for colors specified for
+ * table rows as table rows are currently no widgets and therefore
+ * don't draw any background.
+ */
+void StyleEngine::inheritBackgroundColor () {
+ stack->getRef (stack->size () - 1)->inheritBackgroundColor = true;
+}
+
+/**
+ * \brief set the CSS pseudo class :link.
+ */
+void StyleEngine::setPseudoLink () {
+ Node *n = stack->getRef (stack->size () - 1);
+ n->pseudo = "link";
+}
+
+/**
+ * \brief set the CSS pseudo class :visited.
+ */
+void StyleEngine::setPseudoVisited () {
+ Node *n = stack->getRef (stack->size () - 1);
+ n->pseudo = "visited";
+}
+
+/**
+ * \brief tell the styleEngine that a html element has ended.
+ */
+void StyleEngine::endElement (int element) {
+// fprintf(stderr, "===> END %d\n", element);
+ assert (stack->size () > 1);
+ assert (element == stack->getRef (stack->size () - 1)->element);
+
+ Node *n = stack->getRef (stack->size () - 1);
+
+ if (n->style)
+ n->style->unref ();
+ if (n->wordStyle)
+ n->wordStyle->unref ();
+ if (n->id)
+ dFree ((void*) n->id);
+ if (n->klass)
+ dFree ((void*) n->klass);
+ if (n->styleAttribute)
+ dFree ((void*) n->styleAttribute);
+
+ stack->setSize (stack->size () - 1);
+}
+
+/**
+ * \brief Make changes to StyleAttrs attrs according to CssPropertyList props.
+ */
+void StyleEngine::apply (StyleAttrs *attrs, CssPropertyList *props) {
+ FontAttrs fontAttrs = *attrs->font;
+ Font *parentFont;
+
+ /* Determine font first so it can be used to resolve relative lenths.
+ * \todo Things should be rearranged so that just one pass is necessary.
+ */
+ for (int i = 0; i < props->size (); i++) {
+ CssProperty *p = props->getRef (i);
+
+ switch (p->name) {
+ case CssProperty::CSS_PROPERTY_FONT_FAMILY:
+ fontAttrs.name = p->value.strVal;
+ break;
+ case CssProperty::CSS_PROPERTY_FONT_SIZE:
+ parentFont = stack->get (stack->size () - 2).style->font;
+ computeValue (&fontAttrs.size, p->value.intVal, parentFont,
+ parentFont->size);
+ break;
+ case CssProperty::CSS_PROPERTY_FONT_STYLE:
+ fontAttrs.style = (FontStyle) p->value.intVal;
+ break;
+ case CssProperty::CSS_PROPERTY_FONT_WEIGHT:
+ switch (p->value.intVal) {
+ case CssProperty::CSS_FONT_WEIGHT_LIGHTER:
+ fontAttrs.weight -= CssProperty::CSS_FONT_WEIGHT_STEP;
+ break;
+ case CssProperty::CSS_FONT_WEIGHT_BOLDER:
+ fontAttrs.weight += CssProperty::CSS_FONT_WEIGHT_STEP;
+ break;
+ default:
+ fontAttrs.weight = p->value.intVal;
+ break;
+ }
+ if (fontAttrs.weight < CssProperty::CSS_FONT_WEIGHT_MIN)
+ fontAttrs.weight = CssProperty::CSS_FONT_WEIGHT_MIN;
+ if (fontAttrs.weight > CssProperty::CSS_FONT_WEIGHT_MAX)
+ fontAttrs.weight = CssProperty::CSS_FONT_WEIGHT_MAX;
+ break;
+ default:
+ break;
+ }
+ }
+
+ attrs->font = Font::create (layout, &fontAttrs);
+
+ for (int i = 0; i < props->size (); i++) {
+ CssProperty *p = props->getRef (i);
+
+ switch (p->name) {
+ /* \todo missing cases */
+ case CssProperty::CSS_PROPERTY_BACKGROUND_COLOR:
+ attrs->backgroundColor =
+ Color::create (layout, p->value.intVal);
+ break;
+ case CssProperty::CSS_PROPERTY_BORDER_TOP_COLOR:
+ attrs->borderColor.top =
+ Color::create (layout, p->value.intVal);
+ break;
+ case CssProperty::CSS_PROPERTY_BORDER_BOTTOM_COLOR:
+ attrs->borderColor.bottom =
+ Color::create (layout, p->value.intVal);
+ break;
+ case CssProperty::CSS_PROPERTY_BORDER_LEFT_COLOR:
+ attrs->borderColor.left =
+ Color::create (layout, p->value.intVal);
+ break;
+ case CssProperty::CSS_PROPERTY_BORDER_RIGHT_COLOR:
+ attrs->borderColor.right =
+ Color::create (layout, p->value.intVal);
+ break;
+ case CssProperty::CSS_PROPERTY_BORDER_BOTTOM_STYLE:
+ attrs->borderStyle.bottom = (BorderStyle) p->value.intVal;
+ break;
+ case CssProperty::CSS_PROPERTY_BORDER_LEFT_STYLE:
+ attrs->borderStyle.left = (BorderStyle) p->value.intVal;
+ break;
+ case CssProperty::CSS_PROPERTY_BORDER_RIGHT_STYLE:
+ attrs->borderStyle.right = (BorderStyle) p->value.intVal;
+ break;
+ case CssProperty::CSS_PROPERTY_BORDER_TOP_STYLE:
+ attrs->borderStyle.top = (BorderStyle) p->value.intVal;
+ break;
+ case CssProperty::CSS_PROPERTY_BORDER_BOTTOM_WIDTH:
+ computeValue (&attrs->borderWidth.bottom, p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_BORDER_LEFT_WIDTH:
+ computeValue (&attrs->borderWidth.left, p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_BORDER_RIGHT_WIDTH:
+ computeValue (&attrs->borderWidth.right, p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_BORDER_TOP_WIDTH:
+ computeValue (&attrs->borderWidth.top, p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_BORDER_SPACING:
+ computeValue (&attrs->hBorderSpacing, p->value.intVal, attrs->font);
+ computeValue (&attrs->vBorderSpacing, p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_COLOR:
+ attrs->color = Color::create (layout, p->value.intVal);
+ break;
+ case CssProperty::CSS_PROPERTY_CURSOR:
+ attrs->cursor = (Cursor) p->value.intVal;
+ break;
+ case CssProperty::CSS_PROPERTY_LIST_STYLE_TYPE:
+ attrs->listStyleType = (ListStyleType) p->value.intVal;
+ break;
+ case CssProperty::CSS_PROPERTY_MARGIN_BOTTOM:
+ computeValue (&attrs->margin.bottom, p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_MARGIN_LEFT:
+ computeValue (&attrs->margin.left, p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_MARGIN_RIGHT:
+ computeValue (&attrs->margin.right, p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_MARGIN_TOP:
+ computeValue (&attrs->margin.top, p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_PADDING_TOP:
+ computeValue (&attrs->padding.top, p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_PADDING_BOTTOM:
+ computeValue (&attrs->padding.bottom, p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_PADDING_LEFT:
+ computeValue (&attrs->padding.left, p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_PADDING_RIGHT:
+ computeValue (&attrs->padding.right, p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_TEXT_ALIGN:
+ attrs->textAlign = (TextAlignType) p->value.intVal;
+ break;
+ case CssProperty::CSS_PROPERTY_TEXT_DECORATION:
+ attrs->textDecoration |= p->value.intVal;
+ break;
+ case CssProperty::CSS_PROPERTY_VERTICAL_ALIGN:
+ attrs->valign = (VAlignType) p->value.intVal;
+ break;
+ case CssProperty::CSS_PROPERTY_WHITE_SPACE:
+ attrs->whiteSpace = (WhiteSpace) p->value.intVal;
+ break;
+ case CssProperty::CSS_PROPERTY_WIDTH:
+ computeLength (&attrs->width, p->value.intVal, attrs->font);
+ break;
+ case CssProperty::CSS_PROPERTY_HEIGHT:
+ computeLength (&attrs->height, p->value.intVal, attrs->font);
+ break;
+ case CssProperty::PROPERTY_X_LINK:
+ attrs->x_link = p->value.intVal;
+ break;
+ case CssProperty::PROPERTY_X_IMG:
+ attrs->x_img = p->value.intVal;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /* make sure border colors are set */
+ if (attrs->borderColor.top == NULL)
+ attrs->borderColor.top = attrs->color;
+ if (attrs->borderColor.bottom == NULL)
+ attrs->borderColor.bottom = attrs->color;
+ if (attrs->borderColor.left == NULL)
+ attrs->borderColor.left = attrs->color;
+ if (attrs->borderColor.right == NULL)
+ attrs->borderColor.right = attrs->color;
+
+}
+
+/**
+ * \brief Resolve relative lengths to absolute values.
+ */
+bool StyleEngine::computeValue (int *dest, CssLength value, Font *font) {
+ static float dpmm;
+
+ if (dpmm == 0.0)
+ dpmm = layout->dpiX () / 25.4; /* assume dpiX == dpiY */
+
+ switch (CSS_LENGTH_TYPE (value)) {
+ case CSS_LENGTH_TYPE_PX:
+ *dest = (int) CSS_LENGTH_VALUE (value);
+ return true;
+ case CSS_LENGTH_TYPE_MM:
+ *dest = (int) (CSS_LENGTH_VALUE (value) * dpmm + 0.5);
+ return true;
+ case CSS_LENGTH_TYPE_EM:
+ *dest = (int) (CSS_LENGTH_VALUE (value) * font->size + 0.5);
+ return true;
+ case CSS_LENGTH_TYPE_EX:
+ *dest = (int) (CSS_LENGTH_VALUE(value) * font->xHeight + 0.5);
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+}
+
+bool StyleEngine::computeValue (int *dest, CssLength value, Font *font,
+ int percentageBase) {
+ if (CSS_LENGTH_TYPE (value) == CSS_LENGTH_TYPE_PERCENTAGE) {
+ *dest = (int) (CSS_LENGTH_VALUE (value) * percentageBase + 0.5);
+ return true;
+ } else
+ return computeValue (dest, value, font);
+}
+
+bool StyleEngine::computeLength (dw::core::style::Length *dest,
+ CssLength value, Font *font) {
+ int v;
+
+ if (CSS_LENGTH_TYPE (value) == CSS_LENGTH_TYPE_PERCENTAGE) {
+ *dest = createPerLength (CSS_LENGTH_VALUE (value));
+ return true;
+ } else if (computeValue (&v, value, font)) {
+ *dest = createAbsLength (v);
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * \brief Create a new style object based on the previously opened / closed
+ * HTML elements and the nonCssProperties that have been set.
+ * This method is private. Call style() to get a current style object.
+ */
+Style * StyleEngine::style0 (CssPropertyList *nonCssProperties) {
+ CssPropertyList props;
+ CssPropertyList *tagStyleProps = NULL; /** \todo implementation */
+
+ // get previous style from the stack
+ StyleAttrs attrs = *stack->getRef (stack->size () - 2)->style;
+ // reset values that are not inherited according to CSS
+ attrs.resetValues ();
+
+ if (stack->getRef (stack->size () - 2)->inheritBackgroundColor)
+ attrs.backgroundColor =
+ stack->getRef (stack->size () - 2)->style->backgroundColor;
+
+ cssContext->apply (&props, this, tagStyleProps, nonCssProperties);
+
+ apply (&attrs, &props);
+
+ stack->getRef (stack->size () - 1)->style = Style::create (layout, &attrs);
+
+ return stack->getRef (stack->size () - 1)->style;
+}
+
+Style * StyleEngine::wordStyle0 (CssPropertyList *nonCssProperties) {
+ StyleAttrs attrs = *style ();
+ attrs.resetValues ();
+
+ if (stack->getRef (stack->size () - 1)->inheritBackgroundColor)
+ attrs.backgroundColor = style ()->backgroundColor;
+
+ stack->getRef (stack->size () - 1)->wordStyle = Style::create (layout, &attrs);
+ return stack->getRef (stack->size () - 1)->wordStyle;
+}
+
+void StyleEngine::parse (const char *buf, int buflen,
+ int order_count, CssOrigin origin) {
+
+ a_Css_parse (cssContext, buf, buflen, order_count, origin);
+}
diff --git a/src/styleengine.hh b/src/styleengine.hh
new file mode 100644
index 00000000..d063fb27
--- /dev/null
+++ b/src/styleengine.hh
@@ -0,0 +1,75 @@
+#ifndef __STYLEENGINE_HH__
+#define __STYLEENGINE_HH__
+
+#include "dw/core.hh"
+#include "doctree.hh"
+#include "css.hh"
+#include "cssparser.hh"
+
+class StyleEngine : public Doctree {
+ private:
+ class Node : public DoctreeNode {
+ public:
+ dw::core::style::Style *style;
+ dw::core::style::Style *wordStyle;
+ const char *styleAttribute;
+ bool inheritBackgroundColor;
+ };
+
+ dw::core::Layout *layout;
+ lout::misc::SimpleVector <Node> *stack;
+ CssContext *cssContext;
+
+ dw::core::style::Style *style0 (CssPropertyList *nonCssHints = NULL);
+ dw::core::style::Style *wordStyle0 (CssPropertyList *nonCssHints = NULL);
+ void apply (dw::core::style::StyleAttrs *attrs, CssPropertyList *props);
+ bool computeValue (int *dest, CssLength value, dw::core::style::Font *font);
+ bool computeValue (int *dest, CssLength value, dw::core::style::Font *font,
+ int percentageBase);
+ bool computeLength (dw::core::style::Length *dest, CssLength value, dw::core::style::Font *font);
+
+ public:
+ StyleEngine (dw::core::Layout *layout);
+ ~StyleEngine ();
+
+ /* Doctree interface */
+ inline const DoctreeNode *top () {
+ return stack->getRef (stack->size () - 1);
+ };
+
+ inline const DoctreeNode *parent (const DoctreeNode *n) {
+ if (n->depth > 1)
+ return stack->getRef (n->depth - 1);
+ else
+ return NULL;
+ };
+
+ void parse (const char *buf, int buflen, int order_count, CssOrigin origin);
+ void startElement (int tag);
+ void setId (const char *id);
+ void setClass (const char *klass);
+ void setStyle (const char *style);
+ void endElement (int tag);
+ void setPseudoLink ();
+ void setPseudoVisited ();
+ void setNonCssHints (CssPropertyList *nonCssHints);
+ void inheritBackgroundColor (); /* \todo get rid of this somehow */
+
+ inline dw::core::style::Style *style () {
+ dw::core::style::Style *s = stack->getRef (stack->size () - 1)->style;
+ if (s)
+ return s;
+ else
+ return style0 ();
+ };
+ inline dw::core::style::Style *wordStyle () {
+ dw::core::style::Style *s = stack->getRef (stack->size () - 1)->wordStyle;
+ if (s)
+ return s;
+ else
+ return wordStyle0 ();
+ };
+
+};
+
+#endif
diff --git a/src/table.cc b/src/table.cc
index a72411d6..1bae2a4b 100644
--- a/src/table.cc
+++ b/src/table.cc
@@ -18,12 +18,11 @@
#include "prefs.h"
#include "msg.h"
+#include "css.hh"
/* Undefine if you want to unroll tables. For instance for PDAs */
#define USE_TABLES
-#define dillo_dbg_rendering 0
-
using namespace dw;
using namespace dw::core;
using namespace dw::core::style;
@@ -43,13 +42,13 @@ void Html_tag_open_table(DilloHtml *html, const char *tag, int tagsize)
{
#ifdef USE_TABLES
dw::core::Widget *table;
- dw::core::style::StyleAttrs style_attrs;
- dw::core::style::Style *cell_style, *old_style;
+ CssPropertyList props, *table_cell_props;
const char *attrbuf;
- int32_t border = 0, cellspacing = 1, cellpadding = 2, bgcolor;
+ int32_t border = -1, cellspacing = -1, cellpadding = -1, bgcolor = -1;
+ int cssLength;
#endif
- DW2TB(html->dw)->addParbreak (0, S_TOP(html)->style);
+ DW2TB(html->dw)->addParbreak (0, html->styleEngine->wordStyle ());
#ifdef USE_TABLES
if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "border")))
@@ -59,68 +58,70 @@ void Html_tag_open_table(DilloHtml *html, const char *tag, int tagsize)
if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "cellpadding")))
cellpadding = strtol (attrbuf, NULL, 10);
- /* The style for the table */
- style_attrs = *S_TOP(html)->style;
-
- /* When dillo was started with the --debug-rendering option, there
- * is always a border around the table. */
- if (dillo_dbg_rendering)
- style_attrs.borderWidth.setVal (MIN (border, 1));
- else
- style_attrs.borderWidth.setVal (border);
+ if (border != -1) {
+ cssLength = CSS_CREATE_LENGTH (border, CSS_LENGTH_TYPE_PX);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_TOP_WIDTH, cssLength);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_BOTTOM_WIDTH, cssLength);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_LEFT_WIDTH, cssLength);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_RIGHT_WIDTH, cssLength);
+ }
- style_attrs.setBorderColor (
- Color::createShaded(HT2LT(html), S_TOP(html)->current_bg_color));
- style_attrs.setBorderStyle (BORDER_OUTSET);
- style_attrs.hBorderSpacing = cellspacing;
- style_attrs.vBorderSpacing = cellspacing;
+ if (cellspacing != -1) {
+ cssLength = CSS_CREATE_LENGTH (cellspacing, CSS_LENGTH_TYPE_PX);
+ props.set (CssProperty::CSS_PROPERTY_BORDER_SPACING, cssLength);
+ }
if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "width")))
- style_attrs.width = a_Html_parse_length (html, attrbuf);
+ props.set (CssProperty::CSS_PROPERTY_WIDTH,
+ a_Html_parse_length (html, attrbuf));
if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "align"))) {
if (dStrcasecmp (attrbuf, "left") == 0)
- style_attrs.textAlign = dw::core::style::TEXT_ALIGN_LEFT;
+ props.set (CssProperty::CSS_PROPERTY_TEXT_ALIGN, TEXT_ALIGN_LEFT);
else if (dStrcasecmp (attrbuf, "right") == 0)
- style_attrs.textAlign = dw::core::style::TEXT_ALIGN_RIGHT;
+ props.set (CssProperty::CSS_PROPERTY_TEXT_ALIGN, TEXT_ALIGN_RIGHT);
else if (dStrcasecmp (attrbuf, "center") == 0)
- style_attrs.textAlign = dw::core::style::TEXT_ALIGN_CENTER;
+ props.set (CssProperty::CSS_PROPERTY_TEXT_ALIGN, TEXT_ALIGN_CENTER);
}
- if (!prefs.force_my_colors &&
- (attrbuf = a_Html_get_attr(html, tag, tagsize, "bgcolor"))) {
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "bgcolor"))) {
bgcolor = a_Html_color_parse(html, attrbuf, -1);
if (bgcolor != -1) {
if (bgcolor == 0xffffff && !prefs.allow_white_bg)
bgcolor = prefs.bg_color;
S_TOP(html)->current_bg_color = bgcolor;
- style_attrs.backgroundColor =
- Color::createShaded (HT2LT(html), bgcolor);
+ props.set (CssProperty::CSS_PROPERTY_BACKGROUND_COLOR, bgcolor);
}
}
+ html->styleEngine->setNonCssHints (&props);
+
/* The style for the cells */
- cell_style = Style::create (HT2LT(html), &style_attrs);
- style_attrs = *S_TOP(html)->style;
- /* When dillo was started with the --debug-rendering option, there
- * is always a border around the cells. */
- if (dillo_dbg_rendering)
- style_attrs.borderWidth.setVal (1);
- else
- style_attrs.borderWidth.setVal (border ? 1 : 0);
- style_attrs.padding.setVal(cellpadding);
- style_attrs.setBorderColor (cell_style->borderColor.top);
- style_attrs.setBorderStyle (BORDER_INSET);
+ table_cell_props = new CssPropertyList ();
+ if (border > 0) {
+ cssLength = CSS_CREATE_LENGTH (1, CSS_LENGTH_TYPE_PX);
+ table_cell_props->set (CssProperty::CSS_PROPERTY_BORDER_TOP_WIDTH, cssLength);
+ table_cell_props->set (CssProperty::CSS_PROPERTY_BORDER_BOTTOM_WIDTH, cssLength);
+ table_cell_props->set (CssProperty::CSS_PROPERTY_BORDER_LEFT_WIDTH, cssLength);
+ table_cell_props->set (CssProperty::CSS_PROPERTY_BORDER_RIGHT_WIDTH, cssLength);
+ }
+
+ if (cellpadding != -1) {
+ cssLength = CSS_CREATE_LENGTH (cellpadding, CSS_LENGTH_TYPE_PX);
+ table_cell_props->set (CssProperty::CSS_PROPERTY_PADDING_TOP, cssLength);
+ table_cell_props->set (CssProperty::CSS_PROPERTY_PADDING_BOTTOM, cssLength);
+ table_cell_props->set (CssProperty::CSS_PROPERTY_PADDING_LEFT, cssLength);
+ table_cell_props->set (CssProperty::CSS_PROPERTY_PADDING_RIGHT, cssLength);
+ }
+
+ if (S_TOP(html)->table_cell_props)
+ S_TOP(html)->table_cell_props->unref ();
- old_style = S_TOP(html)->table_cell_style;
- S_TOP(html)->table_cell_style =
- Style::create (HT2LT(html), &style_attrs);
- if (old_style)
- old_style->unref ();
+ S_TOP(html)->table_cell_props = table_cell_props;
+ S_TOP(html)->table_cell_props->ref ();
table = new dw::Table(prefs.limit_text_width);
- DW2TB(html->dw)->addWidget (table, cell_style);
- cell_style->unref ();
+ DW2TB(html->dw)->addWidget (table, html->styleEngine->style ());
S_TOP(html)->table_mode = DILLO_HTML_TABLE_MODE_TOP;
S_TOP(html)->cell_text_align_set = FALSE;
@@ -134,10 +135,9 @@ void Html_tag_open_table(DilloHtml *html, const char *tag, int tagsize)
void Html_tag_open_tr(DilloHtml *html, const char *tag, int tagsize)
{
const char *attrbuf;
- dw::core::style::StyleAttrs style_attrs;
- dw::core::style::Style *style, *old_style;
int32_t bgcolor = -1;
bool new_style = false;
+ CssPropertyList props, *table_cell_props;
#ifdef USE_TABLES
switch (S_TOP(html)->table_mode) {
@@ -148,44 +148,41 @@ void Html_tag_open_tr(DilloHtml *html, const char *tag, int tagsize)
case DILLO_HTML_TABLE_MODE_TOP:
case DILLO_HTML_TABLE_MODE_TR:
case DILLO_HTML_TABLE_MODE_TD:
- style = NULL;
- if (!prefs.force_my_colors &&
- (attrbuf = a_Html_get_attr(html, tag, tagsize, "bgcolor"))) {
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "bgcolor"))) {
bgcolor = a_Html_color_parse(html, attrbuf, -1);
if (bgcolor != -1) {
if (bgcolor == 0xffffff && !prefs.allow_white_bg)
bgcolor = prefs.bg_color;
-
- style_attrs = *S_TOP(html)->style;
- style_attrs.backgroundColor =
- Color::createShaded (HT2LT(html), bgcolor);
- style = Style::create (HT2LT(html), &style_attrs);
+ props.set (CssProperty::CSS_PROPERTY_BACKGROUND_COLOR, bgcolor);
S_TOP(html)->current_bg_color = bgcolor;
}
}
- ((dw::Table*)S_TOP(html)->table)->addRow (style);
- if (style)
- style->unref ();
+ html->styleEngine->inheritBackgroundColor ();
+ html->styleEngine->setNonCssHints (&props);
+
+ ((dw::Table*)S_TOP(html)->table)->addRow (html->styleEngine->style ());
if (a_Html_get_attr (html, tag, tagsize, "align")) {
S_TOP(html)->cell_text_align_set = TRUE;
- a_Html_tag_set_align_attr (html, tag, tagsize);
+ a_Html_tag_set_align_attr (html, &props, tag, tagsize);
+ html->styleEngine->setNonCssHints (&props);
}
- style_attrs = *S_TOP(html)->table_cell_style;
+ table_cell_props = new CssPropertyList (*S_TOP(html)->table_cell_props);
if (bgcolor != -1) {
- style_attrs.backgroundColor =Color::createShaded(HT2LT(html),bgcolor);
+ table_cell_props->set (CssProperty::CSS_PROPERTY_BACKGROUND_COLOR, bgcolor);
new_style = true;
}
- if (a_Html_tag_set_valign_attr (html, tag, tagsize, &style_attrs))
+ if (a_Html_tag_set_valign_attr (html, tag, tagsize, table_cell_props))
new_style = true;
if (new_style) {
- old_style = S_TOP(html)->table_cell_style;
- S_TOP(html)->table_cell_style =
- Style::create (HT2LT(html), &style_attrs);
- old_style->unref ();
+ S_TOP(html)->table_cell_props->unref ();
+ S_TOP(html)->table_cell_props = table_cell_props;
+ S_TOP(html)->table_cell_props->ref ();
+ } else {
+ delete table_cell_props;
}
break;
default:
@@ -194,7 +191,7 @@ void Html_tag_open_tr(DilloHtml *html, const char *tag, int tagsize)
S_TOP(html)->table_mode = DILLO_HTML_TABLE_MODE_TR;
#else
- DW2TB(html->dw)->addParbreak (0, S_TOP(html)->style);
+ DW2TB(html->dw)->addParbreak (0, html->styleEngine->wordStyle ());
#endif
}
@@ -212,7 +209,6 @@ void Html_tag_open_td(DilloHtml *html, const char *tag, int tagsize)
*/
void Html_tag_open_th(DilloHtml *html, const char *tag, int tagsize)
{
- a_Html_set_top_font(html, NULL, 0, 1, 1);
Html_tag_open_table_cell (html, tag, tagsize,
dw::core::style::TEXT_ALIGN_CENTER);
}
@@ -232,10 +228,15 @@ static void Html_tag_open_table_cell(DilloHtml *html,
Widget *col_tb;
int colspan = 1, rowspan = 1;
const char *attrbuf;
- dw::core::style::StyleAttrs style_attrs;
- dw::core::style::Style *style, *old_style;
int32_t bgcolor;
bool_t new_style;
+ CssPropertyList *props;
+
+ // \todo any shorter way to do this?
+ if (S_TOP(html)->table_cell_props != NULL)
+ props = new CssPropertyList (*S_TOP(html)->table_cell_props);
+ else
+ props = new CssPropertyList ();
switch (S_TOP(html)->table_mode) {
case DILLO_HTML_TABLE_MODE_NONE:
@@ -259,47 +260,39 @@ static void Html_tag_open_table_cell(DilloHtml *html,
rowspan = MAX(1, strtol (attrbuf, NULL, 10));
/* text style */
- old_style = S_TOP(html)->style;
- style_attrs = *old_style;
- if (!S_TOP(html)->cell_text_align_set)
- style_attrs.textAlign = text_align;
+ if (!S_TOP(html)->cell_text_align_set) {
+ props->set (CssProperty::CSS_PROPERTY_TEXT_ALIGN, text_align);
+ }
if (a_Html_get_attr(html, tag, tagsize, "nowrap"))
- style_attrs.whiteSpace = WHITE_SPACE_NOWRAP;
+ props->set (CssProperty::CSS_PROPERTY_WHITE_SPACE, WHITE_SPACE_NOWRAP);
else
- style_attrs.whiteSpace = WHITE_SPACE_NORMAL;
+ props->set (CssProperty::CSS_PROPERTY_WHITE_SPACE, WHITE_SPACE_NORMAL);
- S_TOP(html)->style =
- Style::create (HT2LT(html), &style_attrs);
- old_style->unref ();
- a_Html_tag_set_align_attr (html, tag, tagsize);
-
- /* cell style */
- style_attrs = *S_TOP(html)->table_cell_style;
- new_style = FALSE;
+ a_Html_tag_set_align_attr (html, props, tag, tagsize);
if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "width"))) {
- style_attrs.width = a_Html_parse_length (html, attrbuf);
- new_style = TRUE;
+ props->set (CssProperty::CSS_PROPERTY_WIDTH,
+ a_Html_parse_length (html, attrbuf));
}
- if (a_Html_tag_set_valign_attr (html, tag, tagsize, &style_attrs))
+ if (a_Html_tag_set_valign_attr (html, tag, tagsize, props))
new_style = TRUE;
- if (!prefs.force_my_colors &&
- (attrbuf = a_Html_get_attr(html, tag, tagsize, "bgcolor"))) {
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "bgcolor"))) {
bgcolor = a_Html_color_parse(html, attrbuf, -1);
if (bgcolor != -1) {
if (bgcolor == 0xffffff && !prefs.allow_white_bg)
bgcolor = prefs.bg_color;
- new_style = TRUE;
- style_attrs.backgroundColor =
- Color::createShaded (HT2LT(html), bgcolor);
+ props->set (CssProperty::CSS_PROPERTY_BACKGROUND_COLOR, bgcolor);
S_TOP(html)->current_bg_color = bgcolor;
}
}
- if (S_TOP(html)->style->textAlign
+ html->styleEngine->setNonCssHints (props);
+ delete props;
+
+ if (html->styleEngine->style ()->textAlign
== TEXT_ALIGN_STRING)
col_tb = new dw::TableCell (
((dw::Table*)S_TOP(html)->table)->getCellRef (),
@@ -307,18 +300,14 @@ static void Html_tag_open_table_cell(DilloHtml *html,
else
col_tb = new Textblock (prefs.limit_text_width);
- if (new_style) {
- style = dw::core::style::Style::create (HT2LT(html), &style_attrs);
- col_tb->setStyle (style);
- style->unref ();
- } else
- col_tb->setStyle (S_TOP(html)->table_cell_style);
+ col_tb->setStyle (html->styleEngine->style ());
((dw::Table*)S_TOP(html)->table)->addCell (col_tb, colspan, rowspan);
S_TOP(html)->textblock = html->dw = col_tb;
/* Handle it when the user clicks on a link */
html->connectSignals(col_tb);
+
break;
default:
diff --git a/src/web.cc b/src/web.cc
index b9141913..ba5d90a1 100644
--- a/src/web.cc
+++ b/src/web.cc
@@ -80,9 +80,9 @@ int a_Web_dispatch_by_type (const char *Type, DilloWeb *Web,
styleAttrs.initValues ();
styleAttrs.margin.setVal (5);
styleAttrs.font = style::Font::create (layout, &fontAttrs);
- styleAttrs.color = style::Color::createSimple (layout, 0xff0000);
+ styleAttrs.color = style::Color::create (layout, 0xff0000);
styleAttrs.backgroundColor =
- style::Color::createSimple (layout, prefs.bg_color);
+ style::Color::create (layout, prefs.bg_color);
widgetStyle = style::Style::create (layout, &styleAttrs);
dw->setStyle (widgetStyle);
widgetStyle->unref ();
diff --git a/test/dw_anchors_test.cc b/test/dw_anchors_test.cc
index 8615439e..97ed3fb4 100644
--- a/test/dw_anchors_test.cc
+++ b/test/dw_anchors_test.cc
@@ -126,8 +126,8 @@ int main(int argc, char **argv)
styleAttrs.initValues ();
styleAttrs.font = Font::create (layout, &fontAttrs);
styleAttrs.margin.setVal (5);
- styleAttrs.color = Color::createSimple (layout, 0x000000);
- styleAttrs.backgroundColor = Color::createSimple (layout, 0xffffff);
+ styleAttrs.color = Color::create (layout, 0x000000);
+ styleAttrs.backgroundColor = Color::create (layout, 0xffffff);
topWidgetStyle = Style::create (layout, &styleAttrs);
styleAttrs.margin.left = 20;
diff --git a/test/dw_border_test.cc b/test/dw_border_test.cc
index 0c2b7783..f45c1a07 100644
--- a/test/dw_border_test.cc
+++ b/test/dw_border_test.cc
@@ -49,7 +49,7 @@ int main(int argc, char **argv)
styleAttrs.initValues ();
styleAttrs.margin.setVal (5);
styleAttrs.borderWidth.setVal (2);
- styleAttrs.setBorderColor (Color::createShaded (layout, 0xffffff));
+ styleAttrs.setBorderColor (Color::create (layout, 0xffffff));
styleAttrs.setBorderStyle (BORDER_INSET);
styleAttrs.padding.setVal (5);
@@ -60,15 +60,15 @@ int main(int argc, char **argv)
fontAttrs.style = FONT_STYLE_NORMAL;
styleAttrs.font = Font::create (layout, &fontAttrs);
- styleAttrs.color = Color::createSimple (layout, 0x000000);
- styleAttrs.backgroundColor = Color::createSimple (layout, 0xffffff);
+ styleAttrs.color = Color::create (layout, 0x000000);
+ styleAttrs.backgroundColor = Color::create (layout, 0xffffff);
Style *widgetStyle1 = Style::create (layout, &styleAttrs);
- styleAttrs.backgroundColor = Color::createSimple (layout, 0xffff80);
+ styleAttrs.backgroundColor = Color::create (layout, 0xffff80);
styleAttrs.margin.setVal (0);
styleAttrs.borderWidth.setVal (1);
- styleAttrs.setBorderColor (Color::createSimple (layout, 0x4040ff));
+ styleAttrs.setBorderColor (Color::create (layout, 0x4040ff));
styleAttrs.setBorderStyle (BORDER_SOLID);
styleAttrs.padding.setVal (1);
diff --git a/test/dw_example.cc b/test/dw_example.cc
index 75b891e2..ad570924 100644
--- a/test/dw_example.cc
+++ b/test/dw_example.cc
@@ -53,9 +53,9 @@ int main(int argc, char **argv)
styleAttrs.font = dw::core::style::Font::create (layout, &fontAttrs);
styleAttrs.color =
- dw::core::style::Color::createSimple (layout, 0x000000);
+ dw::core::style::Color::create (layout, 0x000000);
styleAttrs.backgroundColor =
- dw::core::style::Color::createSimple (layout, 0xffffff);
+ dw::core::style::Color::create (layout, 0xffffff);
dw::core::style::Style *widgetStyle =
dw::core::style::Style::create (layout, &styleAttrs);
diff --git a/test/dw_find_test.cc b/test/dw_find_test.cc
index a43b4e59..651ca653 100644
--- a/test/dw_find_test.cc
+++ b/test/dw_find_test.cc
@@ -99,8 +99,8 @@ int main(int argc, char **argv)
styleAttrs.initValues ();
styleAttrs.font = Font::create (layout, &fontAttrs);
styleAttrs.margin.setVal (10);
- styleAttrs.color = Color::createSimple (layout, 0x000000);
- styleAttrs.backgroundColor = Color::createSimple (layout, 0xffffff);
+ styleAttrs.color = Color::create (layout, 0x000000);
+ styleAttrs.backgroundColor = Color::create (layout, 0xffffff);
Style *topWidgetStyle = Style::create (layout, &styleAttrs);
styleAttrs.margin.setVal (0);
diff --git a/test/dw_images_scaled.cc b/test/dw_images_scaled.cc
index dfaf57b9..da53a6fd 100644
--- a/test/dw_images_scaled.cc
+++ b/test/dw_images_scaled.cc
@@ -115,8 +115,8 @@ int main(int argc, char **argv)
fontAttrs.style = FONT_STYLE_NORMAL;
styleAttrs.font = Font::create (layout, &fontAttrs);
- styleAttrs.color = Color::createSimple (layout, 0x000000);
- styleAttrs.backgroundColor = Color::createSimple (layout, 0xffffff);
+ styleAttrs.color = Color::create (layout, 0x000000);
+ styleAttrs.backgroundColor = Color::create (layout, 0xffffff);
Style *widgetStyle = Style::create (layout, &styleAttrs);
diff --git a/test/dw_images_scaled2.cc b/test/dw_images_scaled2.cc
index 39c55046..aea724f0 100644
--- a/test/dw_images_scaled2.cc
+++ b/test/dw_images_scaled2.cc
@@ -90,8 +90,8 @@ int main(int argc, char **argv)
fontAttrs.style = FONT_STYLE_NORMAL;
styleAttrs.font = Font::create (layout, &fontAttrs);
- styleAttrs.color = Color::createSimple (layout, 0x000000);
- styleAttrs.backgroundColor = Color::createSimple (layout, 0xffffff);
+ styleAttrs.color = Color::create (layout, 0x000000);
+ styleAttrs.backgroundColor = Color::create (layout, 0xffffff);
Style *widgetStyle = Style::create (layout, &styleAttrs);
@@ -109,7 +109,7 @@ int main(int argc, char **argv)
Style *wordStyle = Style::create (layout, &styleAttrs);
styleAttrs.borderWidth.setVal (1);
- styleAttrs.setBorderColor (Color::createShaded (layout, 0x000080));
+ styleAttrs.setBorderColor (Color::create (layout, 0x000080));
styleAttrs.setBorderStyle (BORDER_SOLID);
styleAttrs.padding.setVal (1);
styleAttrs.backgroundColor = NULL;
diff --git a/test/dw_images_simple.cc b/test/dw_images_simple.cc
index 78629d55..62f25cf7 100644
--- a/test/dw_images_simple.cc
+++ b/test/dw_images_simple.cc
@@ -113,8 +113,8 @@ int main(int argc, char **argv)
fontAttrs.style = FONT_STYLE_NORMAL;
styleAttrs.font = Font::create (layout, &fontAttrs);
- styleAttrs.color = Color::createSimple (layout, 0x000000);
- styleAttrs.backgroundColor = Color::createSimple (layout, 0xffffff);
+ styleAttrs.color = Color::create (layout, 0x000000);
+ styleAttrs.backgroundColor = Color::create (layout, 0xffffff);
Style *widgetStyle = Style::create (layout, &styleAttrs);
diff --git a/test/dw_links.cc b/test/dw_links.cc
index 4d15d520..08428e88 100644
--- a/test/dw_links.cc
+++ b/test/dw_links.cc
@@ -91,8 +91,8 @@ int main(int argc, char **argv)
fontAttrs.style = FONT_STYLE_NORMAL;
styleAttrs.font = Font::create (layout, &fontAttrs);
- styleAttrs.color = Color::createSimple (layout, 0x000000);
- styleAttrs.backgroundColor = Color::createSimple (layout, 0xffffff);
+ styleAttrs.color = Color::create (layout, 0x000000);
+ styleAttrs.backgroundColor = Color::create (layout, 0xffffff);
Style *widgetStyle = Style::create (layout, &styleAttrs);
@@ -110,7 +110,7 @@ int main(int argc, char **argv)
Style *wordStyle = Style::create (layout, &styleAttrs);
- styleAttrs.color = Color::createSimple (layout, 0x0000ff);
+ styleAttrs.color = Color::create (layout, 0x0000ff);
styleAttrs.textDecoration = TEXT_DECORATION_UNDERLINE;
styleAttrs.cursor = CURSOR_POINTER;
diff --git a/test/dw_links2.cc b/test/dw_links2.cc
index e1db9011..ea2d4d40 100644
--- a/test/dw_links2.cc
+++ b/test/dw_links2.cc
@@ -119,8 +119,8 @@ int main(int argc, char **argv)
fontAttrs.style = FONT_STYLE_NORMAL;
styleAttrs.font = Font::create (layout, &fontAttrs);
- styleAttrs.color = Color::createSimple (layout, 0x000000);
- styleAttrs.backgroundColor = Color::createSimple (layout, 0xffffff);
+ styleAttrs.color = Color::create (layout, 0x000000);
+ styleAttrs.backgroundColor = Color::create (layout, 0xffffff);
Style *widgetStyle = Style::create (layout, &styleAttrs);
@@ -138,7 +138,7 @@ int main(int argc, char **argv)
Style *wordStyle = Style::create (layout, &styleAttrs);
- styleAttrs.color = Color::createSimple (layout, 0x0000ff);
+ styleAttrs.color = Color::create (layout, 0x0000ff);
styleAttrs.textDecoration = TEXT_DECORATION_UNDERLINE;
styleAttrs.cursor = CURSOR_POINTER;
diff --git a/test/dw_lists.cc b/test/dw_lists.cc
index 99e78149..2d546f63 100644
--- a/test/dw_lists.cc
+++ b/test/dw_lists.cc
@@ -56,8 +56,8 @@ int main(int argc, char **argv)
fontAttrs.style = FONT_STYLE_NORMAL;
styleAttrs.font = Font::create (layout, &fontAttrs);
- styleAttrs.color = Color::createSimple (layout, 0x000000);
- styleAttrs.backgroundColor = Color::createSimple (layout, 0xffffff);
+ styleAttrs.color = Color::create (layout, 0x000000);
+ styleAttrs.backgroundColor = Color::create (layout, 0xffffff);
Style *widgetStyle = Style::create (layout, &styleAttrs);
@@ -75,8 +75,8 @@ int main(int argc, char **argv)
styleAttrs.margin.setVal (5);
styleAttrs.padding.setVal (5);
- styleAttrs.backgroundColor = Color::createSimple (layout, 0xffff40);
- styleAttrs.setBorderColor (Color::createSimple (layout, 0x000000));
+ styleAttrs.backgroundColor = Color::create (layout, 0xffff40);
+ styleAttrs.setBorderColor (Color::create (layout, 0x000000));
styleAttrs.setBorderStyle (BORDER_SOLID);
styleAttrs.borderWidth.setVal (1);
diff --git a/test/dw_resource_test.cc b/test/dw_resource_test.cc
index fc825836..2c90d3ce 100644
--- a/test/dw_resource_test.cc
+++ b/test/dw_resource_test.cc
@@ -57,8 +57,8 @@ int main(int argc, char **argv)
fontAttrs.style = FONT_STYLE_NORMAL;
styleAttrs.font = Font::create (layout, &fontAttrs);
- styleAttrs.color = Color::createSimple (layout, 0x000000);
- styleAttrs.backgroundColor = Color::createSimple (layout, 0xffffff);
+ styleAttrs.color = Color::create (layout, 0x000000);
+ styleAttrs.backgroundColor = Color::create (layout, 0xffffff);
Style *widgetStyle = Style::create (layout, &styleAttrs);
diff --git a/test/dw_table.cc b/test/dw_table.cc
index d269d551..87ed8360 100644
--- a/test/dw_table.cc
+++ b/test/dw_table.cc
@@ -51,9 +51,9 @@ int main(int argc, char **argv)
styleAttrs.padding.setVal (0);
styleAttrs.borderWidth.setVal (1);
styleAttrs.setBorderStyle (BORDER_OUTSET);
- styleAttrs.setBorderColor (Color::createShaded (layout, 0xffffff));
- styleAttrs.color = Color::createSimple (layout, 0x000000);
- styleAttrs.backgroundColor = Color::createSimple (layout, 0xffffff);
+ styleAttrs.setBorderColor (Color::create (layout, 0xffffff));
+ styleAttrs.color = Color::create (layout, 0x000000);
+ styleAttrs.backgroundColor = Color::create (layout, 0xffffff);
styleAttrs.hBorderSpacing = 5;
styleAttrs.vBorderSpacing = 5;
diff --git a/test/dw_table_aligned.cc b/test/dw_table_aligned.cc
index beb8525d..5fa94874 100644
--- a/test/dw_table_aligned.cc
+++ b/test/dw_table_aligned.cc
@@ -50,7 +50,7 @@ int main(int argc, char **argv)
styleAttrs.margin.setVal (5);
styleAttrs.borderWidth.setVal (1);
styleAttrs.setBorderStyle (BORDER_OUTSET);
- styleAttrs.setBorderColor (Color::createShaded (layout, 0x808080));
+ styleAttrs.setBorderColor (Color::create (layout, 0x808080));
FontAttrs fontAttrs;
fontAttrs.name = "Bitstream Charter";
@@ -59,8 +59,8 @@ int main(int argc, char **argv)
fontAttrs.style = FONT_STYLE_NORMAL;
styleAttrs.font = Font::create (layout, &fontAttrs);
- styleAttrs.color = Color::createSimple (layout, 0x000000);
- styleAttrs.backgroundColor = Color::createSimple (layout, 0xa0a0a0);
+ styleAttrs.color = Color::create (layout, 0x000000);
+ styleAttrs.backgroundColor = Color::create (layout, 0xa0a0a0);
styleAttrs.hBorderSpacing = 5;
styleAttrs.vBorderSpacing = 5;
diff --git a/test/dw_ui_test.cc b/test/dw_ui_test.cc
index 3815a868..88595a76 100644
--- a/test/dw_ui_test.cc
+++ b/test/dw_ui_test.cc
@@ -53,8 +53,8 @@ int main(int argc, char **argv)
StyleAttrs styleAttrs;
styleAttrs.initValues ();
styleAttrs.margin.setVal (5);
- styleAttrs.color = Color::createSimple (layout, 0x000000);
- styleAttrs.backgroundColor = Color::createSimple (layout, 0xffffff);
+ styleAttrs.color = Color::create (layout, 0x000000);
+ styleAttrs.backgroundColor = Color::create (layout, 0xffffff);
FontAttrs fontAttrs;
fontAttrs.name = "Helvetica";