Mercurial > dillo_port1.3
changeset 774:c40b6d8a1e79
merge with CSS branch
author | Jorge Arellano Cid <jcid@dillo.org> |
---|---|
date | Fri, 16 Jan 2009 14:32:20 -0300 |
parents | e06bbc31cb4d (current diff) c1dd6bdfffe0 (diff) |
children | a0230b2a4a32 |
files | .hgtags |
diffstat | 69 files changed, 4038 insertions(+), 1624 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Fri Jan 16 14:20:49 2009 -0300 +++ b/.hgtags Fri Jan 16 14:32:20 2009 -0300 @@ -1,3 +1,4 @@ 009c4cf944331789ae47689d4dbefeb845900fb6 release-2_0 aa944fb43c5686ad5de0b759011883889df1fee2 start 96a14e974cfbca56647e2f503698f196a4b614b4 2.1-noCss +
--- a/ChangeLog Fri Jan 16 14:20:49 2009 -0300 +++ b/ChangeLog Fri Jan 16 14:32:20 2009 -0300 @@ -50,7 +50,8 @@ ? 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 @@ -59,6 +60,8 @@ Patch: place (AKA corvid) +- Cleaned up unused code in fltkviewbase. Patch: Johannes Hofmann ++- Added lout/msg.h and normalized debug messages to use it. + Patch: Jorge Arellano Cid -----------------------------------------------------------------------------
--- a/dillorc Fri Jan 16 14:20:49 2009 -0300 +++ b/dillorc Fri Jan 16 14:32:20 2009 -0300 @@ -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
--- a/dw/fltkimgbuf.cc Fri Jan 16 14:20:49 2009 -0300 +++ b/dw/fltkimgbuf.cc Fri Jan 16 14:32:20 2009 -0300 @@ -21,6 +21,7 @@ #include "fltkcore.hh" +#include "../lout/msg.h" #include "../lout/misc.hh" #include <fltk/draw.h> @@ -35,13 +36,13 @@ FltkImgbuf::FltkImgbuf (Type type, int width, int height) { - //printf("FltkImgbuf: new root %p\n", this); + _MSG("FltkImgbuf: new root %p\n", this); init (type, width, height, NULL); } FltkImgbuf::FltkImgbuf (Type type, int width, int height, FltkImgbuf *root) { - //printf("FltkImgbuf: new scaled %p, root is %p\n", this, root); + _MSG("FltkImgbuf: new scaled %p, root is %p\n", this, root); init (type, width, height, root); } @@ -58,8 +59,7 @@ case RGB: bpp = 3; break; default: bpp = 1; break; } - //fprintf(stderr,"FltkImgbuf::init width=%d height=%d bpp=%d\n", - // width, height, bpp); + _MSG("FltkImgbuf::init width=%d height=%d bpp=%d\n", width, height, bpp); rawdata = new uchar[bpp * width * height]; // Set light-gray as interim background color. memset(rawdata, 222, width*height*bpp); @@ -85,12 +85,7 @@ 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); + _MSG("~FltkImgbuf[%s %p] deleted\n", isRoot() ? "root":"scaled", this); if (!isRoot()) root->detachScaledBuf (this); @@ -110,8 +105,8 @@ { scaledBuffers->detachRef (scaledBuf); - //printf("FltkImgbuf[root %p]: scaled buffer %p is detached, %d left\n", - // this, scaledBuf, scaledBuffers->size ()); + _MSG("FltkImgbuf[root %p]: scaled buffer %p is detached, %d left\n", + this, scaledBuf, scaledBuffers->size ()); if (refCount == 0 && scaledBuffers->isEmpty () && deleteOnUnref) // If the root buffer is not used anymore, but this is the last scaled @@ -175,7 +170,7 @@ core::Imgbuf* FltkImgbuf::getScaledBuf (int width, int height) { - if (root) + if (!isRoot()) return root->getScaledBuf (width, height); if (width == this->width && height == this->height) { @@ -207,8 +202,8 @@ area->y = row; area->width = width; area->height = 1; - //fprintf(stderr,"::getRowArea: area x=%d y=%d width=%d height=%d\n", - // area->x, area->y, area->width, area->height); + _MSG("::getRowArea: area x=%d y=%d width=%d height=%d\n", + area->x, area->y, area->width, area->height); } else { // scaled buffer int sr1 = scaledY (row); @@ -218,8 +213,8 @@ area->y = sr1; area->width = width; area->height = sr2 - sr1; - //fprintf(stderr,"::getRowArea: area x=%d y=%d width=%d height=%d\n", - // area->x, area->y, area->width, area->height); + _MSG("::getRowArea: area x=%d y=%d width=%d height=%d\n", + area->x, area->y, area->width, area->height); } } @@ -238,28 +233,30 @@ refCount++; //if (root) - // printf("FltkImgbuf[scaled %p, root is %p]: ref() => %d\n", - // this, root, refCount); + // MSG("FltkImgbuf[scaled %p, root is %p]: ref() => %d\n", + // this, root, refCount); //else - // printf("FltkImgbuf[root %p]: ref() => %d\n", this, refCount); + // MSG("FltkImgbuf[root %p]: ref() => %d\n", this, refCount); } void FltkImgbuf::unref () { //if (root) - // printf("FltkImgbuf[scaled %p, root is %p]: ref() => %d\n", - // this, root, refCount - 1); + // MSG("FltkImgbuf[scaled %p, root is %p]: ref() => %d\n", + // this, root, refCount - 1); //else - // printf("FltkImgbuf[root %p]: ref() => %d\n", this, refCount - 1); + // MSG("FltkImgbuf[root %p]: ref() => %d\n", this, refCount - 1); if (--refCount == 0) { 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 { + _MSG("FltkImgbuf[root %p]: not deleted. numScaled=%d\n", + this, scaledBuffers->size ()); + } } else // Scaled buffer buffer, simply delete it. delete this; @@ -293,29 +290,15 @@ } 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 - // (and so has not to be passed at all). - -/* - setcolor (0); + // TODO: Clarify the question, whether "target" is the current widget + // (and so has not to be passed at all). - for (int row = y; row < y + height; row++) { - if (copiedRows->get (row)) { - ::fltk::Rectangle rect (x + xRoot, row + yRoot, width, 1); - fillrect (rect); - } - } -*/ + _MSG("::draw: xRoot=%d x=%d yRoot=%d y=%d width=%d height=%d\n" + " this->width=%d this->height=%d\n", + xRoot, x, yRoot, y, width, height, this->width, this->height); - //fprintf(stderr,"::draw: xRoot=%d x=%d yRoot=%d y=%d width=%d height=%d\n" - // " this->width=%d this->height=%d\n", - // xRoot, x, yRoot, y, width, height, this->width, this->height); - -//{ -#if 1 if (x > this->width || y > this->height) { return; } @@ -328,19 +311,10 @@ height = this->height - y; } - // almost OK for rows. For some unknown reason it trims the bottom and - // rightmost parts when scrolling. + // Draw ::fltk::Rectangle rect (xRoot + x, yRoot + y, width, height); PixelType ptype = (type == RGBA) ? ::fltk::RGBA : ::fltk::RGB; drawimage(rawdata+bpp*(y*this->width + x),ptype,rect,bpp*this->width); - -#else - // OK for full image. - ::fltk::Rectangle rect (xRoot, yRoot, this->width, this->height); - PixelType ptype = (type == RGBA) ? ::fltk::RGBA : ::fltk::RGB; - drawimage(rawdata,ptype,rect); -#endif -//} } } // namespace dw
--- a/dw/fltkplatform.cc Fri Jan 16 14:20:49 2009 -0300 +++ b/dw/fltkplatform.cc Fri Jan 16 14:32:20 2009 -0300 @@ -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,6 @@ font = ::fltk::font(name, fa); if(font == NULL) { - 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 +100,9 @@ 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 +120,10 @@ 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 +131,13 @@ 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 +297,16 @@ 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 +380,9 @@ return FltkFont::create (attrs); } -core::style::Color *FltkPlatform::createSimpleColor (int color) +core::style::Color *FltkPlatform::createColor (int color) { - return FltkColor::create (color, core::style::Color::TYPE_SIMPLE); -} - -core::style::Color *FltkPlatform::createShadedColor (int color) -{ - return FltkColor::create (color, core::style::Color::TYPE_SHADED); + return FltkColor::create (color); } void FltkPlatform::copySelection(const char *text)
--- a/dw/fltkplatform.hh Fri Jan 16 14:20:49 2009 -0300 +++ b/dw/fltkplatform.hh Fri Jan 16 14:32:20 2009 -0300 @@ -34,13 +34,13 @@ 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 @@ 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);
--- a/dw/fltkui.cc Fri Jan 16 14:20:49 2009 -0300 +++ b/dw/fltkui.cc Fri Jan 16 14:32:20 2009 -0300 @@ -23,6 +23,7 @@ #include "fltkcore.hh" #include "fltkflatview.hh" #include "fltkcomplexbutton.hh" +#include "../lout/msg.h" #include "../lout/misc.hh" #include <stdio.h> @@ -120,7 +121,7 @@ } } - fprintf (stderr, "FltkResource::detachView: View not found."); + MSG_WARN("FltkResource::detachView: View not found."); } void FltkResource::sizeAllocate (core::Allocation *allocation) @@ -444,9 +445,8 @@ } } - fprintf (stderr, - "FltkComplexButtonResourceResource::detachView: View not " - "found.\n"); + MSG_WARN("FltkComplexButtonResourceResource::detachView: " + "View not found.\n"); } void FltkComplexButtonResource::sizeAllocate (core::Allocation *allocation) @@ -597,7 +597,7 @@ * The Back or Forward, buttons, or the first click on a rendered * page. BUG: this must be investigated and reported to FLTK2 team */ - printf ("when = %d\n", widget->when ()); + MSG("when = %d\n", widget->when ()); if ((widget->when () & ::fltk::WHEN_ENTER_KEY_ALWAYS) && (::fltk::event_key() == ::fltk::ReturnKey)) ((FltkEntryResource*)data)->emitActivate (); @@ -648,11 +648,11 @@ // Check values. Upper bound check is left to the caller. if (numCols < 1) { - fprintf (stderr, "WARNING: numCols = %d is set to 1.\n", numCols); + MSG_WARN("numCols = %d is set to 1.\n", numCols); numCols = 1; } if (numRows < 1) { - fprintf (stderr, "WARNING: numRows = %d is set to 1.\n", numRows); + MSG_WARN("numRows = %d is set to 1.\n", numRows); numRows = 1; }
--- a/dw/fltkviewbase.cc Fri Jan 16 14:20:49 2009 -0300 +++ b/dw/fltkviewbase.cc Fri Jan 16 14:32:20 2009 -0300 @@ -30,6 +30,7 @@ #include <fltk/run.h> #include <stdio.h> +#include "../lout/msg.h" using namespace fltk; using namespace lout::object; @@ -203,7 +204,7 @@ translateViewXToCanvasX (event_x ()), translateViewYToCanvasY (event_y ()), getDwButtonState (), event_button ()); - //printf ("PUSH => %s\n", processed ? "true" : "false"); + _MSG("PUSH => %s\n", processed ? "true" : "false"); if (processed) { /* pressed dw content; give focus to the view */ ::fltk::focus(this); @@ -216,7 +217,7 @@ translateViewXToCanvasX (event_x ()), translateViewYToCanvasY (event_y ()), getDwButtonState (), event_button ()); - //printf ("RELEASE => %s\n", processed ? "true" : "false"); + _MSG("RELEASE => %s\n", processed ? "true" : "false"); return processed ? true : Group::handle (event); case MOVE: @@ -227,7 +228,7 @@ translateViewXToCanvasX (mouse_x), translateViewYToCanvasY (mouse_y), getDwButtonState ()); - //printf ("MOVE => %s\n", processed ? "true" : "false"); + _MSG("MOVE => %s\n", processed ? "true" : "false"); return processed ? true : Group::handle (event); case DRAG: @@ -236,7 +237,7 @@ translateViewXToCanvasX (event_x ()), translateViewYToCanvasY (event_y ()), getDwButtonState ()); - //printf ("DRAG => %s\n", processed ? "true" : "false"); + _MSG("DRAG => %s\n", processed ? "true" : "false"); return processed ? true : Group::handle (event); case ENTER: @@ -306,7 +307,7 @@ "CURSOR_HELP" }; - printf ("Cursor changes to '%s'.\n", cursorName[cursor]); + MSG("Cursor changes to '%s'.\n", cursorName[cursor]); */ /** \bug Does not work */
--- a/dw/fltkviewport.cc Fri Jan 16 14:20:49 2009 -0300 +++ b/dw/fltkviewport.cc Fri Jan 16 14:32:20 2009 -0300 @@ -27,6 +27,7 @@ #include <fltk/events.h> #include <stdio.h> +#include "../lout/msg.h" using namespace fltk; using namespace lout::object; @@ -211,7 +212,7 @@ int FltkViewport::handle (int event) { - //printf("FltkViewport::handle %d\n", event); + _MSG("FltkViewport::handle %d\n", event); if (hscrollbar->Rectangle::contains (event_x (), event_y ()) && !(event_state() & (SHIFT | CTRL | ALT)) &&
--- a/dw/image.cc Fri Jan 16 14:20:49 2009 -0300 +++ b/dw/image.cc Fri Jan 16 14:32:20 2009 -0300 @@ -21,6 +21,7 @@ #include "image.hh" +#include "../lout/msg.h" #include "../lout/misc.hh" namespace dw { @@ -197,15 +198,15 @@ dx = getStyle()->boxDiffWidth (); dy = getStyle()->boxDiffHeight (); #if 0 - printf("boxDiffHeight = %d + %d, buffer=%p\n", - getStyle()->boxOffsetY(), getStyle()->boxRestHeight(), buffer); - printf("getContentWidth() = allocation.width - style->boxDiffWidth ()" - " = %d - %d = %d\n", - this->allocation.width, getStyle()->boxDiffWidth(), - this->allocation.width - getStyle()->boxDiffWidth()); - printf("getContentHeight() = getHeight() - style->boxDiffHeight ()" - " = %d - %d = %d\n", this->getHeight(), getStyle()->boxDiffHeight(), - this->getHeight() - getStyle()->boxDiffHeight()); + MSG("boxDiffHeight = %d + %d, buffer=%p\n", + getStyle()->boxOffsetY(), getStyle()->boxRestHeight(), buffer); + MSG("getContentWidth() = allocation.width - style->boxDiffWidth ()" + " = %d - %d = %d\n", + this->allocation.width, getStyle()->boxDiffWidth(), + this->allocation.width - getStyle()->boxDiffWidth()); + MSG("getContentHeight() = getHeight() - style->boxDiffHeight ()" + " = %d - %d = %d\n", this->getHeight(), getStyle()->boxDiffHeight(), + this->getHeight() - getStyle()->boxDiffHeight()); #endif if (buffer && (getContentWidth () > 0 || getContentHeight () > 0)) { // Zero content size : simply wait...
--- a/dw/layout.cc Fri Jan 16 14:20:49 2009 -0300 +++ b/dw/layout.cc Fri Jan 16 14:32:20 2009 -0300 @@ -22,6 +22,7 @@ #include "core.hh" +#include "../lout/msg.h" #include "../lout/debug.hh" #include "../lout/misc.hh" @@ -128,7 +129,7 @@ void Layout::addWidget (Widget *widget) { if (topLevel) { - fprintf (stderr, "widget already set\n"); + MSG_WARN("widget already set\n"); return; } @@ -261,8 +262,8 @@ bool scrollingInterrupted) { if (usesViewport) { - //printf ("scrollTo (%d, %d, %s)\n", - // x, y, scrollingInterrupted ? "true" : "false"); + _MSG("scrollTo (%d, %d, %s)\n", + x, y, scrollingInterrupted ? "true" : "false"); scrollTargetHpos = hpos; scrollTargetVpos = vpos; @@ -353,7 +354,7 @@ canvasAscent + canvasDescent - (viewportHeight - hScrollbarThickness)); scrollY = misc::max (scrollY, 0); - //printf("adjustScrollPos: scrollX=%d scrollY=%d\n", scrollX, scrollY); + _MSG("adjustScrollPos: scrollX=%d scrollY=%d\n", scrollX, scrollY); } bool Layout::calcScrollInto (int requestedValue, int requestedSize, @@ -413,7 +414,7 @@ */ void Layout::setAnchor (const char *anchor) { - //printf ("setAnchor (%s)\n", anchor); + _MSG("setAnchor (%s)\n", anchor); if (requestedAnchor) delete requestedAnchor; @@ -523,7 +524,7 @@ void Layout::resizeIdle () { //static int calls = 0; - //printf(" Layout::resizeIdle calls = %d\n", ++calls); + //MSG(" Layout::resizeIdle calls = %d\n", ++calls); while (resizeIdleId != -1) { // Reset already here, since in this function, queueResize() may be @@ -739,8 +740,8 @@ */ Widget *Layout::getWidgetAtPoint (int x, int y) { - //_MSG ("------------------------------------------------------------\n"); - //_MSG ("widget at (%d, %d)\n", x, y); + _MSG ("------------------------------------------------------------\n"); + _MSG ("widget at (%d, %d)\n", x, y); if (topLevel) return topLevel->getWidgetAtPoint (x, y, 0); else @@ -879,8 +880,8 @@ */ void Layout::viewportSizeChanged (View *view, int width, int height) { - //printf("Layout::viewportSizeChanged w=%d h=%d new_w=%d new_h=%d\n", - // viewportWidth, viewportHeight, width, height); + _MSG("Layout::viewportSizeChanged w=%d h=%d new_w=%d new_h=%d\n", + viewportWidth, viewportHeight, width, height); /* If the width has become higher, we test again, whether the vertical * scrollbar (so to speak) can be hidden again. */
--- a/dw/layout.hh Fri Jan 16 14:20:49 2009 -0300 +++ b/dw/layout.hh Fri Jan 16 14:32:20 2009 -0300 @@ -216,19 +216,24 @@ return platform->prevGlyph (text, idx); } + inline float dpiX () + { + return platform->dpiX (); + } + + inline float dpiY () + { + return platform->dpiY (); + } + inline style::Font *createFont (style::FontAttrs *attrs, bool tryEverything) { return platform->createFont (attrs, tryEverything); } - inline style::Color *createSimpleColor (int color) + inline style::Color *createColor (int color) { - return platform->createSimpleColor (color); - } - - inline style::Color *createShadedColor (int color) - { - return platform->createShadedColor (color); + return platform->createColor (color); } inline Imgbuf *createImgbuf (Imgbuf::Type type, int width, int height)
--- a/dw/platform.hh Fri Jan 16 14:20:49 2009 -0300 +++ b/dw/platform.hh Fri Jan 16 14:32:20 2009 -0300 @@ -66,6 +66,16 @@ * \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 @@ 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; /* * --------------------
--- a/dw/style.cc Fri Jan 16 14:20:49 2009 -0300 +++ b/dw/style.cc Fri Jan 16 14:32:20 2009 -0300 @@ -26,6 +26,7 @@ #include <ctype.h> #include "core.hh" +#include "../lout/msg.h" namespace dw { namespace core { @@ -64,11 +65,9 @@ */ void StyleAttrs::resetValues () { - x_link = -1; x_img = -1; x_tooltip = NULL; - textAlign = TEXT_ALIGN_LEFT; /* ??? */ valign = VALIGN_MIDDLE; textAlignChar = '.'; backgroundColor = NULL; @@ -84,8 +83,6 @@ vBorderSpacing = 0; display = DISPLAY_INLINE; - whiteSpace = WHITE_SPACE_NORMAL; - cursor = CURSOR_DEFAULT; /** \todo Check CSS specification again. */ } /** @@ -328,7 +325,7 @@ } if (font == NULL) - fprintf (stderr, "Could not find any font.\n"); + MSG_WARN("Could not find any font.\n"); return font; } @@ -338,12 +335,12 @@ 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 +404,11 @@ } -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); } // ---------------------------------------------------------------------- @@ -464,11 +451,10 @@ points[3][1] = y1 + width; } - /* - printf ("drawPolygon: (%d, %d) .. (%d, %d) .. (%d, %d) .. (%d, %d)\n", - points[0][0], points[0][1], points[1][0], points[1][1], - points[2][0], points[2][1], points[3][0], points[3][1]); - */ + _MSG("drawPolygon: (%d, %d) .. (%d, %d) .. (%d, %d) .. (%d, %d)\n", + points[0][0], points[0][1], points[1][0], points[1][1], + points[2][0], points[2][1], points[3][0], points[3][1]); + view->drawPolygon (color, shading, true, points, 4); } } @@ -488,9 +474,6 @@ 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 @@ 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); }
--- a/dw/style.hh Fri Jan 16 14:20:49 2009 -0300 +++ b/dw/style.hh Fri Jan 16 14:32:20 2009 -0300 @@ -591,22 +591,16 @@ */ 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 @@ 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 @@ 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 ()
--- a/dw/table.cc Fri Jan 16 14:20:49 2009 -0300 +++ b/dw/table.cc Fri Jan 16 14:32:20 2009 -0300 @@ -21,6 +21,7 @@ //#define DBG #include "table.hh" +#include "../lout/msg.h" #include "../lout/misc.hh" #define MAX misc::max @@ -141,10 +142,8 @@ core::style::absLengthVal(getStyle()->width)); } -#ifdef DBG - printf(" Table::getExtremesImpl, {%d, %d} numCols=%d\n", - extremes->minWidth, extremes->maxWidth, numCols); -#endif + _MSG(" Table::getExtremesImpl, {%d, %d} numCols=%d\n", + extremes->minWidth, extremes->maxWidth, numCols); } void Table::sizeAllocateImpl (core::Allocation *allocation) @@ -203,9 +202,7 @@ { // If limitTextWidth is set, a queueResize may also be necessary. if (availWidth != width || limitTextWidth) { -#ifdef DBG - printf(" Table::setWidth %d\n", width); -#endif + _MSG(" Table::setWidth %d\n", width); availWidth = width; queueResize (0, false); } @@ -277,22 +274,22 @@ // We limit the values for colspan and rowspan to 50, to avoid // attacks by malicious web pages. if (colspan > 50 || colspan < 0) { - fprintf (stderr, "WARNING: colspan = %d is set to 50.\n", colspan); + MSG_WARN("colspan = %d is set to 50.\n", colspan); colspan = 50; } if (rowspan > 50 || rowspan <= 0) { - fprintf (stderr, "WARNING: rowspan = %d is set to 50.\n", rowspan); + MSG_WARN("rowspan = %d is set to 50.\n", rowspan); rowspan = 50; } if (numRows == 0) { // to prevent a crash - fprintf (stderr, "WARNING: Cell without row.\n"); + MSG_WARN("Cell without row.\n"); addRow (NULL); } if (rowClosed) { - fprintf (stderr, "WARNING: Last cell had colspan=0.\n"); + MSG_WARN("Last cell had colspan=0.\n"); addRow (NULL); } @@ -308,10 +305,9 @@ child->type == Child::SPAN_SPACE) curCol++; -#ifdef DBG - printf("Table::addCell numCols=%d,curCol=%d,colspan=%d,colspanEff=%d\n", - numCols, curCol, colspan, colspanEff); -#endif + _MSG("Table::addCell numCols=%d,curCol=%d,colspan=%d,colspanEff=%d\n", + numCols, curCol, colspan, colspanEff); + // Increase children array, when necessary. if (curRow + rowspan > numRows) reallocChildren (numCols, curRow + rowspan); @@ -351,18 +347,18 @@ for (int col = 0; col < numCols; col++) { int n = row * numCols + col; if (!(child = children->get (n))) { - printf("[null ] "); + MSG("[null ] "); } else if (children->get(n)->type == Child::CELL) { - printf("[CELL rs=%d] ", child->cell.rowspan); + MSG("[CELL rs=%d] ", child->cell.rowspan); } else if (children->get(n)->type == Child::SPAN_SPACE) { - printf("[SPAN rs=%d] ", child->cell.rowspan); + MSG("[SPAN rs=%d] ", child->cell.rowspan); } else { - printf("[Unk. ] "); + MSG("[Unk. ] "); } } - printf("\n"); + MSG("\n"); } - printf("\n"); + MSG("\n"); #endif } @@ -503,28 +499,28 @@ totalWidth = availWidth; forceTotalWidth = 0; } -#ifdef DBG - printf(" availWidth = %d\n", availWidth); - printf(" totalWidth1 = %d\n", totalWidth); -#endif + + _MSG(" availWidth = %d\n", availWidth); + _MSG(" totalWidth1 = %d\n", totalWidth); + if (totalWidth < extremes.minWidth) totalWidth = extremes.minWidth; totalWidth = totalWidth - (numCols + 1) * getStyle()->hBorderSpacing - getStyle()->boxDiffWidth (); -#ifdef DBG - printf(" totalWidth2 = %d curCol=%d\n", totalWidth,curCol); -#endif + + _MSG(" totalWidth2 = %d curCol=%d\n", totalWidth,curCol); + colWidths->setSize (numCols, 0); cumHeight->setSize (numRows + 1, 0); rowSpanCells->setSize (0); baseline->setSize (numRows); -#ifdef DBG - printf(" extremes = %d,%d\n", extremes.minWidth, extremes.maxWidth); - printf(" getStyle()->boxDiffWidth() = %d\n", getStyle()->boxDiffWidth()); - printf(" getStyle()->hBorderSpacing = %d\n", getStyle()->hBorderSpacing); -#endif + + _MSG(" extremes = %d,%d\n", extremes.minWidth, extremes.maxWidth); + _MSG(" getStyle()->boxDiffWidth() = %d\n", getStyle()->boxDiffWidth()); + _MSG(" getStyle()->hBorderSpacing = %d\n", getStyle()->hBorderSpacing); + apportion_percentages2 (totalWidth, forceTotalWidth); if (!hasColPercent) @@ -583,10 +579,9 @@ continue; // Cell size is too small. -#ifdef DBG - printf("Short cell %d, sumRows=%d spanHeight=%d\n", - n,sumRows,spanHeight); -#endif + _MSG("Short cell %d, sumRows=%d spanHeight=%d\n", + n,sumRows,spanHeight); + // Fill height array if (!rowHeight) { rowHeight = new int[numRows]; @@ -594,10 +589,10 @@ rowHeight[i] = cumHeight->get(i+1) - cumHeight->get(i); } #ifdef DBG - printf (" rowHeight { "); + MSG(" rowHeight { "); for (int i = 0; i < numRows; i++) - printf ("%d ", rowHeight[i]); - printf ("}\n"); + MSG("%d ", rowHeight[i]); + MSG("}\n"); #endif // Calc new row sizes for this span. @@ -607,12 +602,12 @@ sumRows == 0 ? (int)((float)(spanHeight-cumHnew_i)/(row+rs-i)) : (sumRows-cumh_i) <= 0 ? 0 : (int)((float)(spanHeight-cumHnew_i)*rowHeight[i]/(sumRows-cumh_i)); -#ifdef DBG - printf (" i=%-3d h=%d hnew_i=%d =%d*%d/%d cumh_i=%d cumHnew_i=%d\n", - i,rowHeight[i],hnew_i, - spanHeight-cumHnew_i,rowHeight[i],sumRows-cumh_i, - cumh_i, cumHnew_i); -#endif + + _MSG(" i=%-3d h=%d hnew_i=%d =%d*%d/%d cumh_i=%d cumHnew_i=%d\n", + i,rowHeight[i],hnew_i, + spanHeight-cumHnew_i,rowHeight[i],sumRows-cumh_i, + cumh_i, cumHnew_i); + cumHnew_i += hnew_i; cumh_i += rowHeight[i]; rowHeight[i] = hnew_i; @@ -642,9 +637,8 @@ */ void Table::forceCalcColumnExtremes () { -#ifdef DBG - printf(" Table::forceCalcColumnExtremes numCols=%d\n", numCols); -#endif + _MSG(" Table::forceCalcColumnExtremes numCols=%d\n", numCols); + if (numCols == 0) return; @@ -678,13 +672,13 @@ cellMinW = cellExtremes.minWidth; cellMaxW = cellExtremes.maxWidth; } -#ifdef DBG - printf("FCCE, col%d colMin,colMax,cellMin,cellMax = %d,%d,%d,%d\n", - col, - colExtremes->getRef(col)->minWidth, - colExtremes->getRef(col)->maxWidth, - cellMinW, cellMaxW); -#endif + + _MSG("FCCE, col%d colMin,colMax,cellMin,cellMax = %d,%d,%d,%d\n", + col, + colExtremes->getRef(col)->minWidth, + colExtremes->getRef(col)->maxWidth, + cellMinW, cellMaxW); + colExtremes->getRef(col)->minWidth = MAX (colExtremes->getRef(col)->minWidth, cellMinW); colExtremes->getRef(col)->maxWidth = @@ -737,10 +731,10 @@ minSumCols += colExtremes->getRef(col+i)->minWidth; maxSumCols += colExtremes->getRef(col+i)->maxWidth; } -#ifdef DBG - printf("cs=%d spanWidth=%d,%d sumCols=%d,%d\n", - cs,cellMinW,cellMaxW,minSumCols,maxSumCols); -#endif + + _MSG("cs=%d spanWidth=%d,%d sumCols=%d,%d\n", + cs,cellMinW,cellMaxW,minSumCols,maxSumCols); + if (minSumCols >= cellMinW && maxSumCols >= cellMaxW) continue; @@ -785,7 +779,7 @@ int d_a = colExtremes->getRef(i)->maxWidth; int d_w = curAppW > 0 ? (int)((float)curExtraW * d_a/curAppW) : 0; if (d_a < 0||d_w < 0) { - printf("d_a=%d d_w=%d\n",d_a,d_w); + MSG("d_a=%d d_w=%d\n",d_a,d_w); exit(1); } wMin = colExtremes->getRef(i)->minWidth + d_w; @@ -809,19 +803,19 @@ cumMaxWnew += wMax; cumMaxWold += colExtremes->getRef(i)->maxWidth; colExtremes->getRef(i)->maxWidth = wMax; -#ifdef DBG - printf ("i=%d, wMin=%d wMax=%d cumMaxWold=%d\n", - i,wMin,wMax,cumMaxWold); -#endif + + _MSG("i=%d, wMin=%d wMax=%d cumMaxWold=%d\n", + i,wMin,wMax,cumMaxWold); + } #ifdef DBG - printf ("col min,max: ["); + MSG("col min,max: ["); for (int i = 0; i < numCols; i++) - printf ("%d,%d ", - colExtremes->getRef(i)->minWidth, - colExtremes->getRef(i)->maxWidth); - printf ("]\n"); - printf ("getStyle()->hBorderSpacing = %d\n", getStyle()->hBorderSpacing); + MSG("%d,%d ", + colExtremes->getRef(i)->minWidth, + colExtremes->getRef(i)->maxWidth); + MSG("]\n"); + MSG("getStyle()->hBorderSpacing = %d\n", getStyle()->hBorderSpacing); #endif } } @@ -835,13 +829,13 @@ if (colExtremes->size() == 0) return; #ifdef DBG - printf("app2, availWidth=%d, totalWidth=%d, forceTotalWidth=%d\n", - availWidth, totalWidth, forceTotalWidth); - printf("app2, extremes: ( "); + MSG("app2, availWidth=%d, totalWidth=%d, forceTotalWidth=%d\n", + availWidth, totalWidth, forceTotalWidth); + MSG("app2, extremes: ( "); for (int i = 0; i < colExtremes->size (); i++) - printf("%d,%d ", - colExtremes->get(i).minWidth, colExtremes->get(i).maxWidth); - printf(")\n"); + MSG("%d,%d ", + colExtremes->get(i).minWidth, colExtremes->get(i).maxWidth); + MSG(")\n"); #endif int minAutoWidth = 0, maxAutoWidth = 0, availAutoWidth = totalWidth; for (int col = 0; col < numCols; col++) { @@ -871,10 +865,9 @@ int curMaxWidth = maxAutoWidth; int curNewWidth = minAutoWidth; for (int col = 0; col < numCols; col++) { -#ifdef DBG - printf("app2, col %d, minWidth=%d maxWidth=%d\n", - col,extremes->get(col).minWidth, colExtremes->get(col).maxWidth); -#endif + _MSG("app2, col %d, minWidth=%d maxWidth=%d\n", + col,extremes->get(col).minWidth, colExtremes->get(col).maxWidth); + if (colPercents->get(col) != LEN_AUTO) continue; @@ -882,19 +875,19 @@ int colMaxWidth = colExtremes->getRef(col)->maxWidth; int w = (curMaxWidth <= 0) ? 0 : (int)((float)curTargetWidth * colMaxWidth/curMaxWidth); -#ifdef DBG - printf("app2, curTargetWidth=%d colMaxWidth=%d curMaxWidth=%d " - "curNewWidth=%d ", - curTargetWidth, colMaxWidth,curMaxWidth,curNewWidth); - printf("w = %d, ", w); -#endif + + _MSG("app2, curTargetWidth=%d colMaxWidth=%d curMaxWidth=%d " + "curNewWidth=%d ", + curTargetWidth, colMaxWidth,curMaxWidth,curNewWidth); + _MSG("w = %d, ", w); + if (w <= colMinWidth) w = colMinWidth; else if (curNewWidth - colMinWidth + w > curTargetWidth) w = colMinWidth + curExtraWidth; -#ifdef DBG - printf("w = %d\n", w); -#endif + + _MSG("w = %d\n", w); + curNewWidth -= colMinWidth; curMaxWidth -= colMaxWidth; curExtraWidth -= (w - colMinWidth); @@ -902,10 +895,10 @@ setColWidth (col, w); } #ifdef DBG - printf("app2, result: ( "); + MSG("app2, result: ( "); for (int i = 0; i < colWidths->size (); i++) - printf("%d ", colWidths->get (i)); - printf(")\n"); + MSG("%d ", colWidths->get (i)); + MSG(")\n"); #endif } @@ -917,19 +910,17 @@ return; // If there's a table-wide percentage, totalWidth comes already scaled. -#ifdef DBG - printf("APP_P, availWidth=%d, totalWidth=%d, forceTotalWidth=%d\n", - availWidth, totalWidth, forceTotalWidth); -#endif + _MSG("APP_P, availWidth=%d, totalWidth=%d, forceTotalWidth=%d\n", + availWidth, totalWidth, forceTotalWidth); if (!hasColPercent) { #ifdef DBG - printf("APP_P, only a table-wide percentage\n"); - printf("APP_P, extremes = { "); + MSG("APP_P, only a table-wide percentage\n"); + MSG("APP_P, extremes = { "); for (int col = 0; col < numCols; col++) - printf("%d,%d ", colExtremes->getRef(col)->minWidth, - colExtremes->getRef(col)->maxWidth); - printf("}\n"); + MSG("%d,%d ", colExtremes->getRef(col)->minWidth, + colExtremes->getRef(col)->maxWidth); + MSG("}\n"); #endif // It has only a table-wide percentage. Apportion non-absolute widths. int sumMaxWidth = 0, perAvailWidth = totalWidth; @@ -939,10 +930,10 @@ else sumMaxWidth += colExtremes->getRef(col)->maxWidth; } -#ifdef DBG - printf("APP_P, perAvailWidth=%d, sumMaxWidth=%d\n", - perAvailWidth, sumMaxWidth); -#endif + + _MSG("APP_P, perAvailWidth=%d, sumMaxWidth=%d\n", + perAvailWidth, sumMaxWidth); + for (int col = 0; col < numCols; col++) { int max_wi = colExtremes->getRef(col)->maxWidth, new_wi; if (colPercents->get(col) != LEN_ABS) { @@ -954,17 +945,16 @@ } } #ifdef DBG - printf("APP_P, result = { "); + MSG("APP_P, result = { "); for (int col = 0; col < numCols; col++) - printf("%d ", result->get(col)); - printf("}\n"); + MSG("%d ", result->get(col)); + MSG("}\n"); #endif } else { // we'll have to apportion... -#ifdef DBG - printf("APP_P, we'll have to apportion...\n"); -#endif + _MSG("APP_P, we'll have to apportion...\n"); + // Calculate cumPercent and available space float cumPercent = 0.0f; int hasAutoCol = 0; @@ -979,11 +969,10 @@ } sumMinWidth += colExtremes->getRef(col)->minWidth; sumMaxWidth += colExtremes->getRef(col)->maxWidth; -#ifdef DBG - printf("APP_P, col %d minWidth=%d maxWidth=%d\n", col, - colExtremes->getRef(col)->minWidth, - colExtremes->getRef(col)->maxWidth); -#endif + + _MSG("APP_P, col %d minWidth=%d maxWidth=%d\n", col, + colExtremes->getRef(col)->minWidth, + colExtremes->getRef(col)->maxWidth); } int oldTotalWidth = totalWidth; if (!forceTotalWidth) { @@ -1011,11 +1000,11 @@ workingWidth = totalWidth; curPerWidth = sumMinWidth; } -#ifdef DBG - printf("APP_P, oldTotalWidth=%d totalWidth=%d" - " workingWidth=%d extraWidth=%d sumMinNonPer=%d\n", - oldTotalWidth,totalWidth,workingWidth,extraWidth,sumMinNonPer); -#endif + + _MSG("APP_P, oldTotalWidth=%d totalWidth=%d" + " workingWidth=%d extraWidth=%d sumMinNonPer=%d\n", + oldTotalWidth,totalWidth,workingWidth,extraWidth,sumMinNonPer); + for (int col = 0; col < numCols; col++) { int colMinWidth = colExtremes->getRef(col)->minWidth; if (colPercents->get(col) >= 0.0f) { @@ -1035,20 +1024,20 @@ if (cumPercent < 0.99f) { // Will have to apportion the other columns #ifdef DBG - printf("APP_P, extremes: ( "); + MSG("APP_P, extremes: ( "); for (int i = 0; i < colExtremes->size (); i++) - printf("%d,%d ", - colExtremes->get(i).minWidth, colExtremes->get(i).maxWidth); - printf(")\n"); + MSG("%d,%d ", + colExtremes->get(i).minWidth, colExtremes->get(i).maxWidth); + MSG(")\n"); #endif curPerWidth -= sumMinNonPer; int perWidth = (int)(curPerWidth/cumPercent); totalWidth = MAX (totalWidth, perWidth); totalWidth = misc::min (totalWidth, oldTotalWidth); -#ifdef DBG - printf("APP_P, curPerWidth=%d perWidth=%d, totalWidth=%d\n", - curPerWidth, perWidth, totalWidth); -#endif + + _MSG("APP_P, curPerWidth=%d perWidth=%d, totalWidth=%d\n", + curPerWidth, perWidth, totalWidth); + if (hasAutoCol == 0) { // Special case, cumPercent < 100% and no other columns to expand. // We'll honor totalWidth by expanding the percentage cols. @@ -1062,22 +1051,22 @@ } } #ifdef DBG - printf("APP_P, result ={ "); + MSG("APP_P, result ={ "); for (int col = 0; col < numCols; col++) - printf("%d ", colWidths->get(col)); - printf("}\n"); + MSG("%d ", colWidths->get(col)); + MSG("}\n"); #endif apportion2 (totalWidth, 2); #ifdef DBG - printf("APP_P, percent={"); + MSG("APP_P, percent={"); for (int col = 0; col < numCols; col++) - printf("%f ", colPercents->get(col)); - printf("}\n"); - printf("APP_P, result ={ "); + MSG("%f ", colPercents->get(col)); + MSG("}\n"); + MSG("APP_P, result ={ "); for (int col = 0; col < numCols; col++) - printf("%d ", colWidths->get(col)); - printf("}\n"); + MSG("%d ", colWidths->get(col)); + MSG("}\n"); #endif } }
--- a/dw/textblock.cc Fri Jan 16 14:20:49 2009 -0300 +++ b/dw/textblock.cc Fri Jan 16 14:32:20 2009 -0300 @@ -21,6 +21,7 @@ #include "textblock.hh" +#include "../lout/msg.h" #include "../lout/misc.hh" #include <stdio.h> @@ -260,8 +261,8 @@ extremes->minWidth = wordExtremes.minWidth; } - //printf("parMax = %d, wordMaxWidth=%d, prevWordSpace=%d\n", - // parMax, wordExtremes.maxWidth, prevWordSpace); + _MSG("parMax = %d, wordMaxWidth=%d, prevWordSpace=%d\n", + parMax, wordExtremes.maxWidth, prevWordSpace); if (word->content.type != core::Content::BREAK) parMax += prevWordSpace; parMax += wordExtremes.maxWidth; @@ -1077,8 +1078,8 @@ 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.) */ @@ -1417,7 +1418,7 @@ break; default: - fprintf (stderr, "BUG!!! at (%d, %d).\n", xWorld, yWorldBase + diff); + MSG_ERR("at (%d, %d).\n", xWorld, yWorldBase + diff); break; } @@ -1921,14 +1922,14 @@ 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 +1938,10 @@ 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;
--- a/dw/types.cc Fri Jan 16 14:20:49 2009 -0300 +++ b/dw/types.cc Fri Jan 16 14:32:20 2009 -0300 @@ -21,6 +21,7 @@ #include "core.hh" +#include "../lout/msg.h" namespace dw { namespace core { @@ -180,8 +181,8 @@ bool cross = linesCross0 (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2) && linesCross0 (bx1, by1, bx2, by2, ax1, ay1, ax2, ay2); - //printf ("(%d, %d) - (%d, %d) and (%d, %d) - (%d, %d) cross? %s.\n", - // ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, cross ? "Yes" : "No"); + _MSG("(%d, %d) - (%d, %d) and (%d, %d) - (%d, %d) cross? %s.\n", + ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, cross ? "Yes" : "No"); return cross; }
--- a/dw/widget.cc Fri Jan 16 14:20:49 2009 -0300 +++ b/dw/widget.cc Fri Jan 16 14:32:20 2009 -0300 @@ -22,6 +22,7 @@ #include "core.hh" +#include "../lout/msg.h" #include "../lout/debug.hh" using namespace lout::object; @@ -315,7 +316,7 @@ { /** \todo Maybe only the intersection? */ layout->queueDraw (x + allocation.x, y + allocation.y, width, height); - //printf("Widget::queueDrawArea x=%d y=%d w=%d h=%d\n", x, y, width, height); + _MSG("Widget::queueDrawArea x=%d y=%d w=%d h=%d\n", x, y, width, height); } /** @@ -547,7 +548,7 @@ widget = widget->parent; } - fprintf (stderr, "No background color found!\n"); + MSG_WARN("No background color found!\n"); return NULL; } @@ -692,7 +693,7 @@ /* Search upwards. */ while (widget1 != widget2) { if (widget1->parent == NULL) { - fprintf (stderr, "widgets in different trees\n"); + MSG_WARN("widgets in different trees\n"); return NULL; }
--- a/lout/Makefile.am Fri Jan 16 14:20:49 2009 -0300 +++ b/lout/Makefile.am Fri Jan 16 14:32:20 2009 -0300 @@ -11,4 +11,5 @@ object.cc \ object.hh \ signal.cc \ - signal.hh + signal.hh \ + msg.h
--- a/lout/misc.hh Fri Jan 16 14:20:49 2009 -0300 +++ b/lout/misc.hh Fri Jan 16 14:32:20 2009 -0300 @@ -112,6 +112,14 @@ 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)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lout/msg.h Fri Jan 16 14:32:20 2009 -0300 @@ -0,0 +1,43 @@ +#ifndef __MSG_H__ +#define __MSG_H__ + +#include <stdio.h> + +/*#include "prefs.h"*/ +#define prefs_show_msg 1 + +#define D_STMT_START do +#define D_STMT_END while (0) + +/* + * You can disable any MSG* macro by adding the '_' prefix. + */ +#define _MSG(...) +#define _MSG_WARN(...) +#define _MSG_HTTP(...) + + +#define MSG(...) \ + D_STMT_START { \ + if (prefs_show_msg){ \ + printf(__VA_ARGS__); \ + fflush (stdout); \ + } \ + } D_STMT_END + +#define MSG_WARN(...) \ + D_STMT_START { \ + if (prefs_show_msg) \ + printf("** WARNING **: " __VA_ARGS__); \ + } D_STMT_END + +#define MSG_ERR(...) \ + D_STMT_START { \ + if (prefs_show_msg) \ + printf("** ERROR **: " __VA_ARGS__); \ + } D_STMT_END + +#define MSG_HTTP(...) \ + printf("HTTP warning: " __VA_ARGS__) + +#endif /* __MSG_H__ */
--- a/src/Makefile.am Fri Jan 16 14:20:49 2009 -0300 +++ b/src/Makefile.am Fri Jan 16 14:32:20 2009 -0300 @@ -67,6 +67,13 @@ 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 @@ gif.c \ jpeg.c \ png.c \ + imgbuf.cc \ + imgbuf.hh \ image.cc \ image.hh \ menu.hh \
--- a/src/bw.c Fri Jan 16 14:20:49 2009 -0300 +++ b/src/bw.c Fri Jan 16 14:32:20 2009 -0300 @@ -63,6 +63,7 @@ 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 @@ /* Zero image-progress data */ bw->NumImages = 0; bw->NumImagesGot = 0; + + /* Zero stylesheet counter */ + bw->NumPendingStyleSheets = 0; } /*--------------------------------------------------------------------------*/
--- a/src/bw.h Fri Jan 16 14:20:49 2009 -0300 +++ b/src/bw.h Fri Jan 16 14:32:20 2009 -0300 @@ -38,6 +38,8 @@ 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 @@ * 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; };
--- a/src/cache.c Fri Jan 16 14:20:49 2009 -0300 +++ b/src/cache.c Fri Jan 16 14:32:20 2009 -0300 @@ -161,6 +161,7 @@ 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 @@ 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 @@ * 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); + + MSG("a_Cache_set_content_type {%s} {%s}\n", ctype, URL_STR(url)); 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; - - dFree(entry->TypeMeta); + 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 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 @@ 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 @@ 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); } } @@ -783,7 +773,7 @@ continue; if (N == 1 && (buf[i] == ' ' || buf[i] == '\t')) { /* unfold multiple-line header */ - MSG("Multiple-line header!\n"); + _MSG("Multiple-line header!\n"); dStr_erase(hdr, hdr->len - 1, 1); } N = (buf[i] == '\n') ? N + 1 : 0; @@ -812,15 +802,60 @@ 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 @@ 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 @@ 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");
--- a/src/cache.h Fri Jan 16 14:20:49 2009 -0300 +++ b/src/cache.h Fri Jan 16 14:32:20 2009 -0300 @@ -46,6 +46,7 @@ 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_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);
--- a/src/capi.c Fri Jan 16 14:20:49 2009 -0300 +++ b/src/capi.c Fri Jan 16 14:32:20 2009 -0300 @@ -421,10 +421,9 @@ /* * 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); } /*
--- a/src/capi.h Fri Jan 16 14:20:49 2009 -0300 +++ b/src/capi.h Fri Jan 16 14:32:20 2009 -0300 @@ -26,8 +26,7 @@ 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);
--- a/src/colors.c Fri Jan 16 14:20:49 2009 -0300 +++ b/src/colors.c Fri Jan 16 14:32:20 2009 -0300 @@ -204,7 +204,7 @@ #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 @@ 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;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/css.cc Fri Jan 16 14:32:20 2009 -0300 @@ -0,0 +1,412 @@ +/* + * 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 (); + selectorList->getRef (0)->notMatchingBefore = -1; + 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; + int *notMatchingBefore; + const DoctreeNode *n, *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; + notMatchingBefore = &selectorList->getRef (i + 1)->notMatchingBefore; + node = docTree->parent (node); + + if (node == NULL) + return false; + + switch (comb) { + case CHILD: + if (!sel->match (node)) + return false; + break; + case DESCENDENT: + n = node; + + while (true) { + if (node == NULL || node->num < *notMatchingBefore) { + *notMatchingBefore = n->num; + return false; + } + + if (sel->match (node)) + break; + + node = docTree->parent (node); + } + 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; + selectorList->getRef (selectorList->size () - 1)->notMatchingBefore = -1; + 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) { + 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++) + elementTable[i] = new RuleList (); + + idTable = new RuleMap (); + classTable = new RuleMap (); + anyTable = new RuleList (); +} + +CssStyleSheet::~CssStyleSheet () { + for (int i = 0; i < ntags; i++) + delete elementTable[i]; + delete idTable; + delete classTable; + delete anyTable; +} + +void CssStyleSheet::addRule (CssRule *rule) { + CssSimpleSelector *top = rule->selector->top (); + RuleList *ruleList = NULL; + lout::object::ConstString *string; + + if (top->id) { + string = new lout::object::ConstString (top->id); + ruleList = idTable->get (string); + if (ruleList == NULL) { + ruleList = new RuleList (); + idTable->put (string, ruleList); + } else { + delete string; + } + } else if (top->klass) { + string = new lout::object::ConstString (top->klass); + ruleList = classTable->get (string); + if (ruleList == NULL) { + ruleList = new RuleList; + classTable->put (string, ruleList); + } else { + delete string; + } + } else if (top->element >= 0 && top->element < ntags) { + ruleList = elementTable[top->element]; + } else if (top->element == CssSimpleSelector::ELEMENT_ANY) { + ruleList = anyTable; + } + + if (ruleList) { + ruleList->increase (); + *ruleList->getRef (ruleList->size() - 1) = rule; + } +} + +void CssStyleSheet::addRule (CssSelector *selector, CssPropertyList *props) { + CssRule *rule = new CssRule (selector, props); + addRule (rule); +} + +void CssStyleSheet::apply (CssPropertyList *props, Doctree *docTree) { + RuleList *ruleList[4] = {NULL, NULL, NULL, NULL}; + const DoctreeNode *top = docTree->top (); + + if (top->id) { + lout::object::String idString (top->id); + + ruleList[3] = idTable->get (&idString); + } + + if (top->klass) { + lout::object::String classString (top->klass); + + ruleList[2] = classTable->get (&classString); + } + + ruleList[1] = elementTable[docTree->top ()->element]; + ruleList[0] = anyTable; + +#if 0 + fprintf(stderr, "==> "); + for (int j = 0; j < 4; j++) + fprintf(stderr, "%d ", ruleList[j]?ruleList[j]->size():0); + fprintf(stderr, "\n"); +#endif + + for (int i = 0;; i++) { + int n = 0; + + for (int j = 0; j < 4; j++) { + if (ruleList[j] && ruleList[j]->size () > i) { + ruleList[j]->get (i)->apply (props, docTree); + n++; + } + } + + if (n == 0) + break; + } +} + +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}" + "li {margin-top: 0.1em}" + "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); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/css.hh Fri Jan 16 14:32:20 2009 -0300 @@ -0,0 +1,335 @@ +#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 { + int notMatchingBefore; // used for optimizing CSS selector matching + 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: + CssPropertyList *props; + + public: + CssSelector *selector; + + CssRule (CssSelector *selector, CssPropertyList *props); + ~CssRule (); + + void apply (CssPropertyList *props, Doctree *docTree); + void print (); +}; + +/** + * \brief A list of CssRules. + * In apply () all matching rules are applied. + */ +class CssStyleSheet { + private: + class RuleList : public lout::misc::SimpleVector <CssRule*>, + public lout::object::Object { + public: + RuleList () : lout::misc::SimpleVector <CssRule*> (1) {}; + ~RuleList () { + for (int i = 0; i < size (); i++) + delete get (i); + }; + + bool equals (lout::object::Object *other) { return this == other; }; + int hashValue () { return (intptr_t) this; }; + }; + + class RuleMap : public lout::container::typed::HashTable + <lout::object::ConstString, RuleList > { + public: + RuleMap () : lout::container::typed::HashTable + <lout::object::ConstString, RuleList > (true, true, 256) {}; + }; + + static const int ntags = 90; // \todo replace 90 + RuleList *elementTable[ntags]; + + RuleMap *idTable; + RuleMap *classTable; + RuleList *anyTable; + + 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cssparser.cc Fri Jan 16 14:32:20 2009 -0300 @@ -0,0 +1,1167 @@ +#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] == ':')) { + // nothing to be done in this case + } else { + 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 ())) { + delete selector; + selector = NULL; + break; + } + + if (parser->ttype == CSS_TK_CHAR && + (parser->tval[0] == ',' || parser->tval[0] == '{')) { + break; + } 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; + selector = NULL; + break; + } + } + + while (parser->ttype != CSS_TK_END && + (parser->ttype != CSS_TK_CHAR || + (parser->tval[0] != ',' && parser->tval[0] != '{'))) + Css_next_token(parser); + + 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); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cssparser.hh Fri Jan 16 14:32:20 2009 -0300 @@ -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__
--- a/src/dicache.c Fri Jan 16 14:20:49 2009 -0300 +++ b/src/dicache.c Fri Jan 16 14:32:20 2009 -0300 @@ -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 @@ 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 @@ 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 @@ } /* - * 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. + * 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. */ -DICacheEntry *a_Dicache_get_entry(const DilloUrl *Url) +DICacheEntry *a_Dicache_get_entry(const DilloUrl *Url, int version) { DICacheNode *node; - DICacheEntry *entry; + DICacheEntry *entry = NULL; + + dReturn_val_if_fail(version != 0, NULL); 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. - */ -static DICacheEntry *Dicache_get_entry_version(const DilloUrl *Url, - int version) -{ - DICacheNode *node; - DICacheEntry *entry; - - node = dList_find_sorted(CachedIMGs, Url, Dicache_node_by_url_cmp); - entry = (node) ? node->first : NULL; - - while (entry && entry->version != version) - entry = entry->next; - + 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 @@ 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 @@ { 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 *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 @@ /* * 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,6 +245,135 @@ /* ------------------------------------------------------------------------- */ /* + * Set image's width, height & type + * (By now, we'll use the image information despite the html tags --Jcid) + */ +void a_Dicache_set_parms(DilloUrl *url, int version, DilloImage *Image, + uint_t width, uint_t height, DilloImgType type) +{ + 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 = a_Dicache_get_entry(url, version); + dReturn_if_fail ( DicEntry != NULL ); + /* Parameters already set? */ + dReturn_if_fail ( DicEntry->State < DIC_SetParms ); + + _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_Imgbuf_new(Image->dw, I_RGB, width, height); + + DicEntry->TotalSize = width * height * 3; + DicEntry->width = width; + DicEntry->height = height; + DicEntry->type = type; + DicEntry->BitVec = a_Bitvec_new((int)height); + DicEntry->State = DIC_SetParms; + + dicache_size_total += DicEntry->TotalSize; +} + +/* + * Implement the set_cmap method for the Image + */ +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 = a_Dicache_get_entry(url, version); + + _MSG("a_Dicache_set_cmap\n"); + dReturn_if_fail ( DicEntry != NULL ); + + dFree(DicEntry->cmap); + DicEntry->cmap = dNew0(uchar_t, 3 * num_colors_max); + memcpy(DicEntry->cmap, cmap, 3 * num_colors); + if (bg_index >= 0 && (uint_t)bg_index < num_colors) { + DicEntry->cmap[bg_index * 3] = (Image->bg_color >> 16) & 0xff; + DicEntry->cmap[bg_index * 3 + 1] = (Image->bg_color >> 8) & 0xff; + DicEntry->cmap[bg_index * 3 + 2] = (Image->bg_color) & 0xff; + } + + DicEntry->State = DIC_SetCmap; +} + +/* + * Reset for a new scan from a multiple-scan image. + */ +void a_Dicache_new_scan(const DilloUrl *url, int version) +{ + DICacheEntry *DicEntry; + + _MSG("a_Dicache_new_scan\n"); + dReturn_if_fail ( url != NULL ); + 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++; +} + +/* + * Implement the write method + * (Write a scan line into the Dicache entry) + * buf: row buffer + * Y : row number + */ +void a_Dicache_write(DilloImage *Image, DilloUrl *url, int version, + const uchar_t *buf, uint_t Y) +{ + DICacheEntry *DicEntry; + + _MSG("a_Dicache_write\n"); + dReturn_if_fail ( Image != NULL ); + DicEntry = a_Dicache_get_entry(url, version); + dReturn_if_fail ( DicEntry != NULL ); + dReturn_if_fail ( DicEntry->width > 0 && DicEntry->height > 0 ); + + /* 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; +} + +/* + * Implement the close method of the decoding process + */ +void a_Dicache_close(DilloUrl *url, int version, CacheClient_t *Client) +{ + DilloWeb *Web = Client->Web; + DICacheEntry *DicEntry = a_Dicache_get_entry(url, version); + + dReturn_if_fail ( DicEntry != NULL ); + + /* 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) @@ -258,10 +381,27 @@ uint_t i; DilloWeb *Web = Client->Web; DilloImage *Image = Web->Image; - DICacheEntry *DicEntry = a_Dicache_get_entry(Web->url); + 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) { @@ -276,15 +416,13 @@ 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); + 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, DicEntry->v_imgbuf, - DicEntry->linebuf, i, FALSE); + a_Image_write(Image, i); } if (!a_Bitvec_get_bit(DicEntry->BitVec, (int)i)) a_Bitvec_clear_bit(Image->BitVec, (int)i); @@ -301,129 +439,6 @@ /* ------------------------------------------------------------------------- */ /* - * Set image's width, height & type - * (By now, we'll use the image information despite the html tags --Jcid) - */ -void a_Dicache_set_parms(DilloUrl *url, int version, DilloImage *Image, - uint_t width, uint_t height, DilloImgType type) -{ - DICacheEntry *DicEntry; - - dReturn_if_fail ( Image != NULL && width && height ); - /* Find the DicEntry for this Image */ - DicEntry = Dicache_get_entry_version(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 ); - - /* 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->TotalSize = width * height * 3; - DicEntry->width = width; - DicEntry->height = height; - DicEntry->type = type; - DicEntry->BitVec = a_Bitvec_new((int)height); - 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); -} - -/* - * Implement the set_cmap method for the Image - */ -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); - - dReturn_if_fail ( DicEntry != NULL ); - - dFree(DicEntry->cmap); - DicEntry->cmap = dNew0(uchar_t, 3 * num_colors_max); - memcpy(DicEntry->cmap, cmap, 3 * num_colors); - if (bg_index >= 0 && (uint_t)bg_index < num_colors) { - DicEntry->cmap[bg_index * 3] = (Image->bg_color >> 16) & 0xff; - DicEntry->cmap[bg_index * 3 + 1] = (Image->bg_color >> 8) & 0xff; - 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) -{ - DICacheEntry *DicEntry; - - dReturn_if_fail ( url != NULL ); - DicEntry = Dicache_get_entry_version(url, version); - dReturn_if_fail ( DicEntry != NULL ); - - a_Bitvec_clear(DicEntry->BitVec); - DicEntry->ScanNumber++; - a_Image_new_scan(image, DicEntry->v_imgbuf); -} - -/* - * Implement the write method - * (Write a scan line into the Dicache entry) - * buf: row buffer - * Y : row number - */ -void a_Dicache_write(DilloImage *Image, DilloUrl *url, int version, - const uchar_t *buf, uint_t Y) -{ - DICacheEntry *DicEntry; - - dReturn_if_fail ( Image != NULL ); - DicEntry = Dicache_get_entry_version(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); - DicEntry->Y = Y; - a_Bitvec_set_bit(DicEntry->BitVec, (int)Y); - DicEntry->State = DIC_Write; -} - -/* - * Implement the close method of the decoding process - */ -void a_Dicache_close(DilloUrl *url, int version, CacheClient_t *Client) -{ - DilloWeb *Web = Client->Web; - DICacheEntry *DicEntry = Dicache_get_entry_version(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_Bw_close_client(Web->bw, Client->Key); -} - -/* * Free the imgbuf (RGB data) of unused entries. */ void a_Dicache_cleanup(void) @@ -432,12 +447,13 @@ 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 @@ 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);
--- a/src/dicache.h Fri Jan 16 14:20:49 2009 -0300 +++ b/src/dicache.h Fri Jan 16 14:32:20 2009 -0300 @@ -10,6 +10,10 @@ #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 @@ 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 @@ 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);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/doctree.hh Fri Jan 16 14:32:20 2009 -0300 @@ -0,0 +1,21 @@ +#ifndef __DOCTREE_HH__ +#define __DOCTREE_HH__ + +class DoctreeNode { + public: + int num; // unique ascending id + 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
--- a/src/form.cc Fri Jan 16 14:20:49 2009 -0300 +++ b/src/form.cc Fri Jan 16 14:32:20 2009 -0300 @@ -294,7 +294,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ } 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 @@ 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,11 @@ 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); /* 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();
--- a/src/gif.c Fri Jan 16 14:20:49 2009 -0300 +++ b/src/gif.c Fri Jan 16 14:32:20 2009 -0300 @@ -157,7 +157,8 @@ /* * 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 @@ /* 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 @@ { int i; - _MSG("destroy gif %p\n", gif); + _MSG("Gif_close: destroy gif %p\n", gif); a_Dicache_close(gif->url, gif->version, Client);
--- a/src/html.cc Fri Jan 16 14:20:49 2009 -0300 +++ b/src/html.cc Fri Jan 16 14:32:20 2009 -0300 @@ -106,14 +106,10 @@ 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 @@ } /* - * 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 @@ /* 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 @@ * 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 @@ /* - * 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); - - DW2TB(html->dw)->addParbreak (space, style); - DW2TB(html->dw)->addWidget (textblock, style); - DW2TB(html->dw)->addParbreak (space, style); + Textblock *textblock = new Textblock (prefs.limit_text_width); + + 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ */ 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 @@ } delete (images); + delete styleEngine; + //a_Dw_image_map_list_free(&maps); } @@ -661,7 +564,15 @@ 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 @@ */ void DilloHtml::freeParseData() { - (stack->getRef(0)->style)->unref (); /* template style */ delete(stack); dStr_free(Stash, TRUE); @@ -1150,11 +1060,11 @@ 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 @@ 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 @@ 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 @@ 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 @@ } 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 ) */ Pword = a_Html_parse_entities(html, word, size); @@ -1261,7 +1171,7 @@ 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 @@ { 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 @@ * 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_force_push_tag(DilloHtml *html, int tag_idx) { + html->styleEngine->startElement (tag_idx); Html_push_tag(html, tag_idx); } @@ -1339,9 +1248,9 @@ { 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 @@ /* * 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 @@ 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 @@ end += 2; */ default: - l = createAbsLength ((int)v); + l = CSS_CREATE_LENGTH (v, CSS_LENGTH_TYPE_PX); break; } @@ -1455,24 +1364,24 @@ * 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 @@ * 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 @@ /* * 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_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 @@ { const char *attrbuf; Textblock *textblock; - StyleAttrs style_attrs; - Style *style; + CssPropertyList props; int32_t color; if (!(html->InFlags & IN_BODY)) @@ -1749,43 +1683,37 @@ 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, "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, "link"))) - html->link_color = a_Html_color_parse(html,attrbuf,prefs.link_color); - - if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "vlink"))) - html->visited_color = a_Html_color_parse(html, attrbuf, - prefs.visited_color); - - if (prefs.contrast_visited_color) { - /* get a color that has a "safe distance" from text, link and bg */ - html->visited_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); + 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, -1); + + 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 = 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_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 @@ char *src; DilloUrl *url; Textblock *textblock; - StyleAttrs style_attrs; - Style *link_style; Widget *bullet; + CssPropertyList props; textblock = DW2TB(html->dw); @@ -1841,46 +1771,41 @@ 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); - - link_style->unref (); + textblock->addParbreak (5, html->styleEngine->wordStyle ()); + dFree(src); } @@ -1892,9 +1817,9 @@ 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_h(DilloHtml *html, const char *tag, int tagsize) { - DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style); - - /* 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); + CssPropertyList props; + + + 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_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_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 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 - - S_TOP(html)->style = - Style::create (HT2LT(html), &style_attrs); - old_style->unref (); + if (color != -1) + props.set (CssProperty::CSS_PROPERTY_COLOR, color); } + +// \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); + + html->styleEngine->setNonCssHints (&props); } /* @@ -2005,52 +1912,11 @@ } /* - * <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_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 @@ */ 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 *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 @@ // 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,55 @@ /* 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); + Image = a_Image_new(0, 0, alt_ptr, 0); if (add) { - Html_add_widget(html, (Widget*)Image->dw, width_ptr, height_ptr, - style_attrs); + DW2TB(html->dw)->addWidget((Widget*)Image->dw, + html->styleEngine->style()); } + if (DW2TB(html->dw)->getBgColor()) + Image->bg_color = DW2TB(html->dw)->getBgColor()->getColor(); load_now = a_UIcmd_get_images_enabled(html->bw) || (a_Capi_get_flags(url) & CAPI_IsCached); @@ -2191,9 +2084,7 @@ 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 +2101,13 @@ /* 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 +2274,9 @@ */ 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 +2287,16 @@ 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 (); } - - 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 (); + + props.set(CssProperty::PROPERTY_X_LINK, Html_set_new_link(html, &url)); + html->styleEngine->setNonCssHints (&props); + + DW2TB(html->dw)->addText("[OBJECT]", html->styleEngine->wordStyle ()); } a_Url_free(base_url); } @@ -2476,7 +2330,7 @@ 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 +2347,8 @@ */ 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 +2363,24 @@ url = a_Html_url_new(html, attrbuf, NULL, 0); dReturn_if_fail ( url != NULL ); - old_style = S_TOP(html)->style; - style_attrs = *old_style; - if (a_Capi_get_flags(url) & CAPI_IsCached) { html->InVisitedLink = true; - style_attrs.color = Color::createSimple ( - HT2LT(html), - html->visited_color -/* - a_Color_vc(html->visited_color, - S_TOP(html)->style->color->getColor(), - html->link_color, - S_TOP(html)->current_bg_color), -*/ - ); + html->styleEngine->setPseudoVisited (); + if (html->visited_color != -1) + props.set (CssProperty::CSS_PROPERTY_COLOR, html->visited_color); } else { - style_attrs.color = Color::createSimple(HT2LT(html), - html->link_color); + html->styleEngine->setPseudoLink (); + if (html->link_color != -1) + props.set (CssProperty::CSS_PROPERTY_COLOR, html->link_color); } -// if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "title"))) -// style_attrs.x_tooltip = a_Dw_tooltip_new_no_ref(attrbuf); - - style_attrs.textDecoration |= TEXT_DECORATION_UNDERLINE; - style_attrs.x_link = Html_set_new_link(html, &url); - style_attrs.cursor = CURSOR_POINTER; - - S_TOP(html)->style = - Style::create (HT2LT(html), &style_attrs); - old_style->unref (); + props.set (CssProperty::PROPERTY_X_LINK, Html_set_new_link(html, &url)); + + 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 +2399,13 @@ } /* - * 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 +2419,7 @@ */ 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 +2430,7 @@ /* 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 +2441,9 @@ 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 +2454,15 @@ 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); + + 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 +2473,8 @@ */ 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, S_TOP(html)->style); - Html_add_indented(html, 40, 0, 9); - HTML_SET_TOP_ATTR(html, listStyleType, list_style_type); + DW2TB(html->dw)->addParbreak (9, html->styleEngine->wordStyle ()); + S_TOP(html)->list_type = HTML_LIST_UNORDERED; S_TOP(html)->list_number = 0; S_TOP(html)->ref_list_item = NULL; @@ -2712,28 +2497,30 @@ 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 +2537,16 @@ */ 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 +2555,33 @@ 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 (0, 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 (0, 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 +2601,50 @@ 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); - - DW2TB(html->dw)->addParbreak (5, S_TOP(html)->style); + + if (size > 0) { + CssLength size_top = CSS_CREATE_LENGTH ((size+1)/2, CSS_LENGTH_TYPE_PX); + CssLength size_bottom = CSS_CREATE_LENGTH (size / 2, CSS_LENGTH_TYPE_PX); + props.set (CssProperty::CSS_PROPERTY_BORDER_TOP_WIDTH, size_top); + props.set (CssProperty::CSS_PROPERTY_BORDER_LEFT_WIDTH, size_top); + props.set (CssProperty::CSS_PROPERTY_BORDER_BOTTOM_WIDTH, size_bottom); + props.set (CssProperty::CSS_PROPERTY_BORDER_RIGHT_WIDTH, size_bottom); + } + + DW2TB(html->dw)->addParbreak (5, html->styleEngine->wordStyle ()); + + 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 +2653,7 @@ 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 +2661,7 @@ */ 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 +2669,8 @@ */ 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 +2678,10 @@ */ 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 +2693,7 @@ 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 +2709,7 @@ /* 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 +2783,13 @@ } 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 +2797,97 @@ } /* + * 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 +2930,8 @@ } } -/* - * <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) +static void Html_tag_open_default(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) -{ - 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 +2939,11 @@ */ 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 +2951,7 @@ */ 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 +2966,7 @@ */ 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 +3005,30 @@ /* 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 +3043,17 @@ {"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 +3068,17 @@ /* 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 +3088,10 @@ /* 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 +3117,7 @@ * 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 +3148,17 @@ 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 +3255,7 @@ 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 +3268,7 @@ /* 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 +3281,11 @@ /* 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 +3307,9 @@ 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 +3343,8 @@ /* 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 +3356,9 @@ * 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 +3374,24 @@ 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 +3410,7 @@ (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 +3555,6 @@ } /* - * 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.
--- a/src/html_common.hh Fri Jan 16 14:20:49 2009 -0300 +++ b/src/html_common.hh Fri Jan 16 14:32:20 2009 -0300 @@ -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 _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 @@ char *content_type, *charset; bool stop_parser; + bool repush_after_head; + size_t CurrTagOfs; size_t OldTagOfs, OldTagLine; @@ -174,6 +181,7 @@ 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 @@ * 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 @@ 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 @@ 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__ */
--- a/src/image.cc Fri Jan 16 14:20:49 2009 -0300 +++ b/src/image.cc Fri Jan 16 14:32:20 2009 -0300 @@ -27,14 +27,7 @@ using namespace dw::core; // Image to Object-Image macro -#define OI(Image) ((dw::Image*)(Image->dw)) - - -/* - * Local data - */ -static size_t linebuf_size = 0; -static uchar_t *linebuf = NULL; +#define I2DW(Image) ((dw::Image*)(Image->dw)) /* @@ -51,8 +44,6 @@ Image->dw = (void*) new dw::Image(alt_text); Image->width = 0; Image->height = 0; - Image->cmap = NULL; - Image->in_type = DILLO_IMG_TYPE_NOTSET; Image->bg_color = bg_color; Image->ScanNumber = 0; Image->BitVec = NULL; @@ -92,37 +83,6 @@ } /* - * 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, @@ -132,17 +92,12 @@ _MSG("a_Image_set_parms: width=%d height=%d\n", width, height); bool resize = (Image->width != width || Image->height != height); - OI(Image)->setBuffer((Imgbuf*)v_imgbuf, resize); + I2DW(Image)->setBuffer((Imgbuf*)v_imgbuf, resize); if (!Image->BitVec) Image->BitVec = a_Bitvec_new(height); - 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,7 +106,7 @@ */ void a_Image_set_cmap(DilloImage *Image, const uchar_t *cmap) { - Image->cmap = cmap; + _MSG("a_Image_set_cmap\n"); Image->State = IMG_SetCmap; } @@ -160,6 +115,7 @@ */ 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 +124,15 @@ /* * 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); - } + /* Update the row in DwImage */ + I2DW(Image)->drawRow(y); a_Bitvec_set_bit(Image->BitVec, y); Image->State = IMG_Write; - - /* Update the row in DwImage */ - OI(Image)->drawRow(y); } /* @@ -192,46 +140,7 @@ */ 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; -} -
--- a/src/image.hh Fri Jan 16 14:20:49 2009 -0300 +++ b/src/image.hh Fri Jan 16 14:32:20 2009 -0300 @@ -38,10 +38,7 @@ uint_t width; uint_t height; - const uchar_t *cmap; /* Color map (only for indexed) */ - DilloImgType in_type; /* Image Type */ int32_t bg_color; /* Background color */ - bitvec_t *BitVec; /* Bit vector for decoded rows */ uint_t ScanNumber; /* Current decoding scan */ ImageState State; /* Processing status */ @@ -63,14 +60,9 @@ 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 }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/imgbuf.cc Fri Jan 16 14:32:20 2009 -0300 @@ -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); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/imgbuf.hh Fri Jan 16 14:32:20 2009 -0300 @@ -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__ */ +
--- a/src/jpeg.c Fri Jan 16 14:20:49 2009 -0300 +++ b/src/jpeg.c Fri Jan 16 14:32:20 2009 -0300 @@ -84,7 +84,6 @@ 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 @@ /* * 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 @@ /* 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 @@ */ 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 @@ 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 @@ /* 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; } }
--- a/src/nav.c Fri Jan 16 14:20:49 2009 -0300 +++ b/src/nav.c Fri Jan 16 14:32:20 2009 -0300 @@ -378,10 +378,14 @@ * 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); }
--- a/src/plain.cc Fri Jan 16 14:20:49 2009 -0300 +++ b/src/plain.cc Fri Jan 16 14:32:20 2009 -0300 @@ -108,9 +108,9 @@ 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 */
--- a/src/png.c Fri Jan 16 14:20:49 2009 -0300 +++ b/src/png.c Fri Jan 16 14:32:20 2009 -0300 @@ -231,8 +231,9 @@ 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 Png_close(DilloPng *png, CacheClient_t *Client) { + _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 */ - a_Dicache_close(png->url, png->version, Client); 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 @@ } /* - * 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 @@ /* 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); }
--- a/src/prefs.c Fri Jan 16 14:20:49 2009 -0300 +++ b/src/prefs.c Fri Jan 16 14:32:20 2009 -0300 @@ -74,6 +74,7 @@ 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, @@ -140,6 +141,7 @@ { "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 }, @@ -330,6 +332,9 @@ 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; @@ -457,6 +462,7 @@ 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);
--- a/src/prefs.h Fri Jan 16 14:20:49 2009 -0300 +++ b/src/prefs.h Fri Jan 16 14:32:20 2009 -0300 @@ -58,6 +58,7 @@ 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;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/styleengine.cc Fri Jan 16 14:32:20 2009 -0300 @@ -0,0 +1,432 @@ +/* + * 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 "prefs.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; + num = 0; + + 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 = (int) (12 * prefs.font_factor + 0.5); + font_attrs.weight = CssProperty::CSS_FONT_WEIGHT_NORMAL; + 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->num = num++; + 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->num = num++; + 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; + + attrs.valign = style ()->valign; + + 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); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/styleengine.hh Fri Jan 16 14:32:20 2009 -0300 @@ -0,0 +1,76 @@ +#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; + int num; + + 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
--- a/src/table.cc Fri Jan 16 14:20:49 2009 -0300 +++ b/src/table.cc Fri Jan 16 14:32:20 2009 -0300 @@ -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 @@ { #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 @@ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "cellpadding"))) cellpadding = strtol (attrbuf, NULL, 10); - /* The style for the table */ - style_attrs = *S_TOP(html)->style; + if (border != -1) { + cssLength = CSS_CREATE_LENGTH (border, CSS_LENGTH_TYPE_PX); + props.set (CssProperty::CSS_PROPERTY_BORDER_TOP_WIDTH, cssLength); + props.set (CssProperty::CSS_PROPERTY_BORDER_BOTTOM_WIDTH, cssLength); + props.set (CssProperty::CSS_PROPERTY_BORDER_LEFT_WIDTH, cssLength); + props.set (CssProperty::CSS_PROPERTY_BORDER_RIGHT_WIDTH, cssLength); + } - /* When dillo was started with the --debug-rendering option, there - * is always a border around the table. */ - if (dillo_dbg_rendering) - style_attrs.borderWidth.setVal (MIN (border, 1)); - else - style_attrs.borderWidth.setVal (border); - - style_attrs.setBorderColor ( - Color::createShaded(HT2LT(html), S_TOP(html)->current_bg_color)); - style_attrs.setBorderStyle (BORDER_OUTSET); - style_attrs.hBorderSpacing = cellspacing; - style_attrs.vBorderSpacing = cellspacing; + if (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); + } - 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 (); + 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 (); + + 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_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 @@ 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 @@ 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_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 @@ 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 @@ 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 @@ 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:
--- a/src/web.cc Fri Jan 16 14:20:49 2009 -0300 +++ b/src/web.cc Fri Jan 16 14:32:20 2009 -0300 @@ -80,9 +80,9 @@ 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 ();
--- a/test/dw_anchors_test.cc Fri Jan 16 14:20:49 2009 -0300 +++ b/test/dw_anchors_test.cc Fri Jan 16 14:32:20 2009 -0300 @@ -126,8 +126,8 @@ 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;
--- a/test/dw_border_test.cc Fri Jan 16 14:20:49 2009 -0300 +++ b/test/dw_border_test.cc Fri Jan 16 14:32:20 2009 -0300 @@ -49,7 +49,7 @@ 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 @@ 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);
--- a/test/dw_example.cc Fri Jan 16 14:20:49 2009 -0300 +++ b/test/dw_example.cc Fri Jan 16 14:32:20 2009 -0300 @@ -53,9 +53,9 @@ 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);
--- a/test/dw_find_test.cc Fri Jan 16 14:20:49 2009 -0300 +++ b/test/dw_find_test.cc Fri Jan 16 14:32:20 2009 -0300 @@ -99,8 +99,8 @@ 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);
--- a/test/dw_images_scaled.cc Fri Jan 16 14:20:49 2009 -0300 +++ b/test/dw_images_scaled.cc Fri Jan 16 14:32:20 2009 -0300 @@ -115,8 +115,8 @@ 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);
--- a/test/dw_images_scaled2.cc Fri Jan 16 14:20:49 2009 -0300 +++ b/test/dw_images_scaled2.cc Fri Jan 16 14:32:20 2009 -0300 @@ -90,8 +90,8 @@ 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 @@ 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;
--- a/test/dw_images_simple.cc Fri Jan 16 14:20:49 2009 -0300 +++ b/test/dw_images_simple.cc Fri Jan 16 14:32:20 2009 -0300 @@ -113,8 +113,8 @@ 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);
--- a/test/dw_links.cc Fri Jan 16 14:20:49 2009 -0300 +++ b/test/dw_links.cc Fri Jan 16 14:32:20 2009 -0300 @@ -91,8 +91,8 @@ 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 @@ 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;
--- a/test/dw_links2.cc Fri Jan 16 14:20:49 2009 -0300 +++ b/test/dw_links2.cc Fri Jan 16 14:32:20 2009 -0300 @@ -119,8 +119,8 @@ 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 @@ 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;
--- a/test/dw_lists.cc Fri Jan 16 14:20:49 2009 -0300 +++ b/test/dw_lists.cc Fri Jan 16 14:32:20 2009 -0300 @@ -56,8 +56,8 @@ 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 @@ 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);
--- a/test/dw_resource_test.cc Fri Jan 16 14:20:49 2009 -0300 +++ b/test/dw_resource_test.cc Fri Jan 16 14:32:20 2009 -0300 @@ -57,8 +57,8 @@ 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);
--- a/test/dw_table.cc Fri Jan 16 14:20:49 2009 -0300 +++ b/test/dw_table.cc Fri Jan 16 14:32:20 2009 -0300 @@ -51,9 +51,9 @@ 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;
--- a/test/dw_table_aligned.cc Fri Jan 16 14:20:49 2009 -0300 +++ b/test/dw_table_aligned.cc Fri Jan 16 14:32:20 2009 -0300 @@ -50,7 +50,7 @@ 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 @@ 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;
--- a/test/dw_ui_test.cc Fri Jan 16 14:20:49 2009 -0300 +++ b/test/dw_ui_test.cc Fri Jan 16 14:32:20 2009 -0300 @@ -53,8 +53,8 @@ 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";