diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/IO/Makefile.am | 4 | ||||
-rw-r--r-- | src/IO/mime.c | 1 | ||||
-rw-r--r-- | src/cache.c | 14 | ||||
-rw-r--r-- | src/capi.c | 14 | ||||
-rw-r--r-- | src/cookies.h | 1 | ||||
-rw-r--r-- | src/css.cc | 34 | ||||
-rw-r--r-- | src/css.hh | 22 | ||||
-rw-r--r-- | src/cssparser.cc | 205 | ||||
-rw-r--r-- | src/cssparser.hh | 3 | ||||
-rw-r--r-- | src/dillo.cc | 1 | ||||
-rw-r--r-- | src/form.cc | 9 | ||||
-rw-r--r-- | src/gif.c | 14 | ||||
-rw-r--r-- | src/html.cc | 355 | ||||
-rw-r--r-- | src/html_common.hh | 14 | ||||
-rw-r--r-- | src/jpeg.c | 3 | ||||
-rw-r--r-- | src/misc.c | 7 | ||||
-rw-r--r-- | src/nav.c | 4 | ||||
-rw-r--r-- | src/png.c | 22 | ||||
-rw-r--r-- | src/prefs.c | 1 | ||||
-rw-r--r-- | src/prefs.h | 1 | ||||
-rw-r--r-- | src/prefsparser.cc | 7 | ||||
-rw-r--r-- | src/styleengine.cc | 290 | ||||
-rw-r--r-- | src/styleengine.hh | 49 | ||||
-rw-r--r-- | src/table.cc | 249 | ||||
-rw-r--r-- | src/uicmd.cc | 12 | ||||
-rw-r--r-- | src/url.c | 1 | ||||
-rw-r--r-- | src/url.h | 1 | ||||
-rw-r--r-- | src/web.cc | 15 |
28 files changed, 868 insertions, 485 deletions
diff --git a/src/IO/Makefile.am b/src/IO/Makefile.am index b168073c..c889dae8 100644 --- a/src/IO/Makefile.am +++ b/src/IO/Makefile.am @@ -1,4 +1,6 @@ -AM_CPPFLAGS=-DDILLO_BINDIR='"$(bindir)/"' +AM_CPPFLAGS = \ + -I$(top_srcdir) \ + -DDILLO_BINDIR='"$(bindir)/"' AM_CFLAGS = @LIBFLTK_CFLAGS@ AM_CXXFLAGS = @LIBFLTK_CXXFLAGS@ diff --git a/src/IO/mime.c b/src/IO/mime.c index 9bffd619..19dc601a 100644 --- a/src/IO/mime.c +++ b/src/IO/mime.c @@ -108,6 +108,7 @@ void a_Mime_init() Mime_add_minor_type("image/x-png", a_Dicache_png_image); /* deprecated */ #endif Mime_add_minor_type("text/html", a_Html_text); + Mime_add_minor_type("application/xhtml+xml", a_Html_text); /* Add a major type to handle all the text stuff */ Mime_add_major_type("text", a_Plain_text); diff --git a/src/cache.c b/src/cache.c index fcd27a05..d26ae610 100644 --- a/src/cache.c +++ b/src/cache.c @@ -311,6 +311,10 @@ static void Cache_entry_free(CacheEntry_t *entry) dStr_free(entry->UTF8Data, 1); if (entry->CharsetDecoder) a_Decode_free(entry->CharsetDecoder); + if (entry->TransferDecoder) + a_Decode_free(entry->TransferDecoder); + if (entry->ContentDecoder) + a_Decode_free(entry->ContentDecoder); dFree(entry); } @@ -516,6 +520,10 @@ const char *a_Cache_set_content_type(const DilloUrl *url, const char *ctype, ((!major || !*major) && (!minor || !*minor))) { /* META only gives charset; use detected MIME type too */ entry->TypeNorm = dStrconcat(entry->TypeDet, ctype, NULL); + } else if (*from == 'm' && + !dStrncasecmp(ctype, "text/xhtml", 10)) { + /* WORKAROUND: doxygen uses "text/xhtml" in META */ + entry->TypeNorm = dStrdup(entry->TypeDet); } if (charset) { if (entry->CharsetDecoder) @@ -932,7 +940,7 @@ static int Cache_redirect(CacheEntry_t *entry, int Flags, BrowserWindow *bw) (entry->Flags & CA_ForceRedirect || entry->Flags & CA_TempRedirect || !entry->Data->len || entry->Data->len < 1024)) { - _MSG(">>>Redirect from: %s\n to %s\n", + _MSG(">>>> Redirect from: %s\n to %s <<<<\n", URL_STR_(entry->Url), URL_STR_(entry->Location)); _MSG("%s", entry->Header->str); @@ -946,9 +954,9 @@ static int Cache_redirect(CacheEntry_t *entry, int Flags, BrowserWindow *bw) } else { /* Sub entity redirection (most probably an image) */ if (!entry->Data->len) { - _MSG(">>>Image redirection without entity-content<<<\n"); + _MSG(">>>> Image redirection without entity-content <<<<\n"); } else { - _MSG(">>>Image redirection with entity-content<<<\n"); + _MSG(">>>> Image redirection with entity-content <<<<\n"); } } } @@ -362,9 +362,9 @@ static void Capi_dpi_send_source(BrowserWindow *bw, DilloUrl *url) * For a user request, the action will be permitted. * For an automatic request, permission to load depends on the filter set * by the user. - */ -static bool_t Capi_filters_allow(const DilloUrl *wanted, - const DilloUrl *requester) + */ +static bool_t Capi_filters_test(const DilloUrl *wanted, + const DilloUrl *requester) { bool_t ret; @@ -392,8 +392,8 @@ static bool_t Capi_filters_allow(const DilloUrl *wanted, ret = dStrcasecmp(req_suffix, want_suffix) == 0; } - MSG("Capi_filters_allow: from %s to %s: %s\n", req_host, want_host, - ret ? "ALLOWED" : "DENIED"); + MSG("Capi_filters_test: %s from '%s' to '%s'\n", + ret ? "ALLOW" : "DENY", req_host, want_host); break; } case PREFS_FILTER_ALLOW_ALL: @@ -422,7 +422,7 @@ int a_Capi_open_url(DilloWeb *web, CA_Callback_t Call, void *CbData) int safe = 0, ret = 0, use_cache = 0; dReturn_val_if_fail((a_Capi_get_flags(web->url) & CAPI_IsCached) || - Capi_filters_allow(web->url, web->requester), 0); + Capi_filters_test(web->url, web->requester), 0); /* reload test */ reload = (!(a_Capi_get_flags(web->url) & CAPI_IsCached) || @@ -480,7 +480,7 @@ int a_Capi_open_url(DilloWeb *web, CA_Callback_t Call, void *CbData) /* create a new connection and start the CCC operations */ conn = Capi_conn_new(web->url, web->bw, "http", "none"); /* start the reception branch before the query one because the DNS - * may callback immediatly. This may avoid a race condition. */ + * may callback immediately. This may avoid a race condition. */ a_Capi_ccc(OpStart, 2, BCK, a_Chain_new(), conn, "http"); a_Capi_ccc(OpStart, 1, BCK, a_Chain_new(), conn, web); } diff --git a/src/cookies.h b/src/cookies.h index 482aa5ae..d6ee1ccd 100644 --- a/src/cookies.h +++ b/src/cookies.h @@ -8,6 +8,7 @@ extern "C" { #ifdef DISABLE_COOKIES # define a_Cookies_get_query(url) dStrdup("") +# define a_Cookies_set() ; # define a_Cookies_init() ; # define a_Cookies_freeall() ; #else @@ -25,6 +25,28 @@ void CssProperty::print () { (int)value.intVal); } +CssPropertyList::CssPropertyList (const CssPropertyList &p, bool deep) : + lout::misc::SimpleVector <CssProperty> (p) +{ + refCount = 0; + if (deep) { + for (int i = 0; i < size (); i++) { + CssProperty *p = getRef(i); + switch (p->type) { + case CSS_TYPE_STRING: + case CSS_TYPE_SYMBOL: + p->value.strVal = dStrdup (p->value.strVal); + break; + default: + break; + } + } + ownerOfStrings = true; + } else { + ownerOfStrings = false; + } +}; + CssPropertyList::~CssPropertyList () { if (ownerOfStrings) for (int i = 0; i < size (); i++) @@ -428,7 +450,7 @@ void CssStyleSheet::apply (CssPropertyList *props, } } - ruleList[numLists] = elementTable[docTree->top ()->element]; + ruleList[numLists] = elementTable[node->element]; if (ruleList[numLists]) numLists++; @@ -512,9 +534,8 @@ CssContext::~CssContext () { * This allows e.g. user styles to overwrite author styles. */ void CssContext::apply (CssPropertyList *props, Doctree *docTree, + DoctreeNode *node, CssPropertyList *tagStyle, CssPropertyList *nonCssHints) { - const DoctreeNode *node = docTree->top (); - if (sheet[CSS_PRIMARY_USER_AGENT]) sheet[CSS_PRIMARY_USER_AGENT]->apply (props, docTree, node); @@ -558,8 +579,7 @@ void CssContext::addRule (CssSelector *sel, CssPropertyList *props, */ void CssContext::buildUserAgentStyle () { const char *cssBuf = - "body {background-color: #e0e0a3; font-family: sans-serif; color: black;" - " margin: 5px}" + "body {margin: 5px}" "big {font-size: 1.17em}" "blockquote, dd {margin-left: 40px; margin-right: 40px}" "center {text-align: center}" @@ -589,8 +609,8 @@ void CssContext::buildUserAgentStyle () { "sub {vertical-align: sub}" "sup {vertical-align: super}" "s, strike, del {text-decoration: line-through}" - "table {border-style: outset; border-spacing: 1px}" - "td, th {border-style: inset; padding: 2px}" + "table {border-spacing: 2px}" + "td, th {padding: 2px}" "thead, tbody, tfoot {vertical-align: middle}" "th {font-weight: bolder; text-align: center}" "code, tt, pre, samp, kbd {font-family: monospace}" @@ -90,7 +90,7 @@ inline CssLength CSS_CREATE_LENGTH (float v, CssLengthType t) { switch (t) { case CSS_LENGTH_TYPE_PX: - iv = (int) (v + 0.5); + iv = lout::misc::roundInt(v); if (iv > CSS_LENGTH_INT_MAX) iv = CSS_LENGTH_INT_MAX; else if (iv < -CSS_LENGTH_INT_MAX) @@ -304,25 +304,11 @@ class CssPropertyList : public lout::misc::SimpleVector <CssProperty> { refCount = 0; this->ownerOfStrings = ownerOfStrings; }; - inline CssPropertyList(const CssPropertyList &p) : - lout::misc::SimpleVector <CssProperty> (p) { - refCount = 0; - ownerOfStrings = false; - }; + CssPropertyList(const CssPropertyList &p, bool deep = false); ~CssPropertyList (); void set (CssPropertyName name, CssValueType type, CssPropertyValue value); - inline void set (CssPropertyName name, CssValueType type, char *value) { - CssPropertyValue v; - v.strVal = value; - set (name, type, v); - }; - inline void set (CssPropertyName name, CssValueType type, int value) { - CssPropertyValue v; - v.intVal = value; - set (name, type, v); - }; void apply (CssPropertyList *props); void print (); inline void ref () { refCount++; } @@ -476,7 +462,7 @@ class CssContext { static CssStyleSheet *userStyle; static CssStyleSheet *userImportantStyle; CssStyleSheet *sheet[CSS_PRIMARY_USER_IMPORTANT + 1]; - int pos; + int pos; void buildUserAgentStyle (); void buildUserStyle (); @@ -488,7 +474,7 @@ class CssContext { void addRule (CssSelector *sel, CssPropertyList *props, CssPrimaryOrder order); void apply (CssPropertyList *props, - Doctree *docTree, + Doctree *docTree, DoctreeNode *node, CssPropertyList *tagStyle, CssPropertyList *nonCssHints); }; diff --git a/src/cssparser.cc b/src/cssparser.cc index 9d141293..7b522c8c 100644 --- a/src/cssparser.cc +++ b/src/cssparser.cc @@ -47,6 +47,14 @@ typedef struct { const char *const *enum_symbols; } CssPropertyInfo; +static const char *const Css_border_collapse_enum_vals[] = { + "separate", "collapse", NULL +}; + +static const char *const Css_border_color_enum_vals[] = { + "transparent", NULL +}; + static const char *const Css_border_style_enum_vals[] = { "none", "hidden", "dotted", "dashed", "solid", "double", "groove", "ridge", "inset", "outset", NULL @@ -81,6 +89,10 @@ static const char *const Css_font_style_enum_vals[] = { "normal", "italic", "oblique", NULL }; +static const char *const Css_font_variant_enum_vals[] = { + "normal", "small-caps", NULL +}; + static const char *const Css_font_weight_enum_vals[] = { "bold", "bolder", "light", "lighter", "normal", NULL }; @@ -132,24 +144,29 @@ const CssPropertyInfo Css_property_info[CSS_PROPERTY_LAST] = { {"background-image", {CSS_TYPE_UNUSED}, NULL}, {"background-position", {CSS_TYPE_UNUSED}, NULL}, {"background-repeat", {CSS_TYPE_UNUSED}, NULL}, - {"border-bottom-color", {CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, NULL}, + {"border-bottom-color", {CSS_TYPE_ENUM, CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, + Css_border_color_enum_vals}, {"border-bottom-style", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED}, Css_border_style_enum_vals}, {"border-bottom-width", {CSS_TYPE_ENUM, CSS_TYPE_LENGTH, CSS_TYPE_UNUSED}, Css_border_width_enum_vals}, - {"border-collapse", {CSS_TYPE_UNUSED}, NULL}, - {"border-left-color", {CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, NULL}, + {"border-collapse", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED}, + Css_border_collapse_enum_vals}, + {"border-left-color", {CSS_TYPE_ENUM, CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, + Css_border_color_enum_vals}, {"border-left-style", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED}, Css_border_style_enum_vals}, {"border-left-width", {CSS_TYPE_ENUM, CSS_TYPE_LENGTH, CSS_TYPE_UNUSED}, Css_border_width_enum_vals}, - {"border-right-color", {CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, NULL}, + {"border-right-color", {CSS_TYPE_ENUM, CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, + Css_border_color_enum_vals}, {"border-right-style", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED}, Css_border_style_enum_vals}, {"border-rigth-width", {CSS_TYPE_ENUM, CSS_TYPE_LENGTH, CSS_TYPE_UNUSED}, Css_border_width_enum_vals}, {"border-spacing", {CSS_TYPE_LENGTH, CSS_TYPE_UNUSED}, NULL}, - {"border-top-color", {CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, NULL}, + {"border-top-color", {CSS_TYPE_ENUM, CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, + Css_border_color_enum_vals}, {"border-top-style", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED}, Css_border_style_enum_vals}, {"border-top-width", {CSS_TYPE_ENUM, CSS_TYPE_LENGTH, CSS_TYPE_UNUSED}, @@ -173,7 +190,8 @@ const CssPropertyInfo Css_property_info[CSS_PROPERTY_LAST] = { {"font-size-adjust", {CSS_TYPE_UNUSED}, NULL}, {"font-stretch", {CSS_TYPE_UNUSED}, NULL}, {"font-style", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED}, Css_font_style_enum_vals}, - {"font-variant", {CSS_TYPE_UNUSED}, NULL}, + {"font-variant", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED}, + Css_font_variant_enum_vals}, {"font-weight", {CSS_TYPE_ENUM, CSS_TYPE_FONT_WEIGHT, CSS_TYPE_UNUSED}, Css_font_weight_enum_vals}, {"height", {CSS_TYPE_LENGTH_PERCENTAGE, CSS_TYPE_UNUSED}, NULL}, @@ -212,7 +230,7 @@ const CssPropertyInfo Css_property_info[CSS_PROPERTY_LAST] = { {"text-align", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED}, Css_text_align_enum_vals}, {"text-decoration", {CSS_TYPE_MULTI_ENUM, CSS_TYPE_UNUSED}, Css_text_decoration_enum_vals}, - {"text-indent", {CSS_TYPE_UNUSED}, NULL}, + {"text-indent", {CSS_TYPE_LENGTH_PERCENTAGE, CSS_TYPE_UNUSED}, NULL}, {"text-shadow", {CSS_TYPE_UNUSED}, NULL}, {"text-transform", {CSS_TYPE_UNUSED}, NULL}, {"top", {CSS_TYPE_UNUSED}, NULL}, @@ -441,21 +459,21 @@ void CssParser::ungetChar() /* * Skip string str if it is found in the input buffer. + * If string is found leave bufptr pointing to last matched char. * If not wind back. The first char is passed as parameter c * to avoid unnecessary getChar() / ungetChar() calls. */ inline bool CssParser::skipString(int c, const char *str) { - int n = 0; + for (int n = 0; str[n]; n++) { + if (n > 0) + c = getChar(); - while (str[n]) { if (str[n] != c) { while (n--) ungetChar(); return false; } - c = getChar(); - n++; } return true; @@ -663,9 +681,9 @@ bool CssParser::tokenMatchesProperty(CssPropertyName prop, CssValueType *type) case CSS_TYPE_MULTI_ENUM: if (ttype == CSS_TK_SYMBOL) { - if (dStrcasecmp(tval, "none") == 0) - return true; - else { + if (dStrcasecmp(tval, "none") == 0) { + return true; + } else { for (i = 0; Css_property_info[prop].enum_symbols[i]; i++) { if (dStrcasecmp(tval, Css_property_info[prop].enum_symbols[i]) == 0) @@ -1409,54 +1427,171 @@ char * CssParser::parseUrl() void CssParser::parseImport(DilloHtml *html, DilloUrl *baseUrl) { char *urlStr = NULL; + bool importSyntaxIsOK = false; + bool mediaSyntaxIsOK = true; + bool mediaIsSelected = true; - if (html != NULL && - ttype == CSS_TK_SYMBOL && - dStrcasecmp(tval, "import") == 0) { - nextToken(); + nextToken(); - if (ttype == CSS_TK_SYMBOL && - dStrcasecmp(tval, "url") == 0) - urlStr = parseUrl(); - else if (ttype == CSS_TK_STRING) - urlStr = dStrdup (tval); + if (ttype == CSS_TK_SYMBOL && + dStrcasecmp(tval, "url") == 0) + urlStr = parseUrl(); + else if (ttype == CSS_TK_STRING) + urlStr = dStrdup (tval); - /* Skip all tokens until the expected end. */ - while (!(ttype == CSS_TK_END || - (ttype == CSS_TK_CHAR && (tval[0] == ';')))) + nextToken(); + + /* parse a comma-separated list of media */ + if (ttype == CSS_TK_SYMBOL) { + mediaSyntaxIsOK = false; + mediaIsSelected = false; + while (ttype == CSS_TK_SYMBOL) { + if (dStrcasecmp(tval, "all") == 0 || + dStrcasecmp(tval, "screen") == 0) + mediaIsSelected = true; nextToken(); + if (ttype == CSS_TK_CHAR && tval[0] == ',') { + nextToken(); + } else { + mediaSyntaxIsOK = true; + break; + } + } + } + if (mediaSyntaxIsOK && + ttype == CSS_TK_CHAR && + tval[0] == ';') { + importSyntaxIsOK = true; nextToken(); + } else + ignoreStatement(); - if (urlStr) { + if (urlStr) { + if (importSyntaxIsOK && mediaIsSelected) { MSG("CssParser::parseImport(): @import %s\n", urlStr); DilloUrl *url = a_Html_url_new (html, urlStr, a_Url_str(baseUrl), baseUrl ? 1 : 0); a_Html_load_stylesheet(html, url); a_Url_free(url); - dFree (urlStr); + } + dFree (urlStr); + } +} + +void CssParser::parseMedia() +{ + bool mediaSyntaxIsOK = false; + bool mediaIsSelected = false; + + nextToken(); + + /* parse a comma-separated list of media */ + while (ttype == CSS_TK_SYMBOL) { + if (dStrcasecmp(tval, "all") == 0 || + dStrcasecmp(tval, "screen") == 0) + mediaIsSelected = true; + nextToken(); + if (ttype == CSS_TK_CHAR && tval[0] == ',') { + nextToken(); + } else { + mediaSyntaxIsOK = true; + break; } } + + /* check that the syntax is OK so far */ + if (!(mediaSyntaxIsOK && + ttype == CSS_TK_CHAR && + tval[0] == '{')) { + ignoreStatement(); + return; + } + + /* parse/ignore the block as required */ + if (mediaIsSelected) { + nextToken(); + while (ttype != CSS_TK_END) { + parseRuleset(); + if (ttype == CSS_TK_CHAR && tval[0] == '}') { + nextToken(); + break; + } + } + } else + ignoreBlock(); } const char * CssParser::propertyNameString(CssPropertyName name) { return Css_property_info[name].symbol; } + +void CssParser::ignoreBlock() +{ + int depth = 0; + + while (ttype != CSS_TK_END) { + if (ttype == CSS_TK_CHAR) { + if (tval[0] == '{') { + depth++; + } else if (tval[0] == '}') { + depth--; + if (depth == 0) { + nextToken(); + return; + } + } + } + nextToken(); + } +} + +void CssParser::ignoreStatement() +{ + while (ttype != CSS_TK_END) { + if (ttype == CSS_TK_CHAR) { + if (tval[0] == ';') { + nextToken(); + return; + } else if (tval[0] =='{') { + ignoreBlock(); + return; + } + } + nextToken(); + } +} void CssParser::parse(DilloHtml *html, DilloUrl *url, CssContext * context, const char *buf, int buflen, CssOrigin origin) { CssParser parser (context, origin, buf, buflen); - - while (parser.ttype == CSS_TK_CHAR && parser.tval[0] == '@') { - parser.nextToken(); - parser.parseImport(html, url); + bool importsAreAllowed = true; + + while (parser.ttype != CSS_TK_END) { + if (parser.ttype == CSS_TK_CHAR && + parser.tval[0] == '@') { + parser.nextToken(); + if (parser.ttype == CSS_TK_SYMBOL) { + if (dStrcasecmp(parser.tval, "import") == 0 && + html != NULL && + importsAreAllowed) { + parser.parseImport(html, url); + } else if (dStrcasecmp(parser.tval, "media") == 0) { + parser.parseMedia(); + } else { + parser.ignoreStatement(); + } + } else { + parser.ignoreStatement(); + } + } else { + importsAreAllowed = false; + parser.parseRuleset(); + } } - - while (parser.ttype != CSS_TK_END) - parser.parseRuleset(); } CssPropertyList *CssParser::parseDeclarationBlock(const char *buf, int buflen) diff --git a/src/cssparser.hh b/src/cssparser.hh index 1e471c68..1542405d 100644 --- a/src/cssparser.hh +++ b/src/cssparser.hh @@ -40,8 +40,11 @@ class CssParser { bool parseSimpleSelector(CssSimpleSelector *selector); char *parseUrl(); void parseImport(DilloHtml *html, DilloUrl *url); + void parseMedia(); CssSelector *parseSelector(); void parseRuleset(); + void ignoreBlock(); + void ignoreStatement(); public: static CssPropertyList *parseDeclarationBlock(const char *buf, diff --git a/src/dillo.cc b/src/dillo.cc index a42b0dab..3159674e 100644 --- a/src/dillo.cc +++ b/src/dillo.cc @@ -22,6 +22,7 @@ #include <stdlib.h> #include <time.h> #include <signal.h> +#include <locale.h> #include <fltk/Window.h> #include <fltk/TabGroup.h> diff --git a/src/form.cc b/src/form.cc index 38afea8f..18441fb8 100644 --- a/src/form.cc +++ b/src/form.cc @@ -554,12 +554,9 @@ void Html_tag_open_input(DilloHtml *html, const char *tag, int tagsize) } if (prefs.show_tooltip && (attrbuf = a_Html_get_attr(html, tag, tagsize, "title"))) { - CssPropertyList props; - char *tooltip_str = dStrdup(attrbuf); - props.set (PROPERTY_X_TOOLTIP, CSS_TYPE_STRING, tooltip_str); - html->styleEngine->setNonCssHints (&props); - dFree(tooltip_str); + html->styleEngine->setNonCssHint (PROPERTY_X_TOOLTIP, CSS_TYPE_STRING, + attrbuf); } HT2TB(html)->addWidget (embed, html->styleEngine->backgroundStyle()); } @@ -930,7 +927,7 @@ DilloHtmlForm::~DilloHtmlForm () void DilloHtmlForm::eventHandler(Resource *resource, EventButton *event) { - MSG("DilloHtmlForm::eventHandler\n"); + _MSG("DilloHtmlForm::eventHandler\n"); if (event && (event->button == 3)) { a_UIcmd_form_popup(html->bw, html->page_url, this, showing_hiddens); } else { @@ -351,8 +351,6 @@ static size_t Gif_do_extension(DilloGif *gif, uint_t Label, return Gif_data_blocks(buf, BSize); case Txt_Ext: /* Plain text Extension */ - /* This extension allows (rcm thinks) the image to be rendered as text. - */ case App_Ext: /* Application Extension */ default: return Gif_do_generic_ext(buf, BSize); /*Ignore Extension */ @@ -428,16 +426,6 @@ static void Gif_emit_line(DilloGif *gif, const uchar_t *linebuf) } /* - * I apologize for the large size of this routine and the goto error - * construct - I almost _never_ do that. I offer the excuse of - * optimizing for speed. - * - * RCM -- busted these down into smaller subroutines... still very hard to - * read. - */ - - -/* * Decode the packetized lwz bytes */ static void Gif_literal(DilloGif *gif, uint_t code) @@ -816,7 +804,7 @@ static size_t Gif_do_img_desc(DilloGif *gif, void *Buf, /* check max image size */ if (gif->Width <= 0 || gif->Height <= 0 || gif->Width > IMAGE_MAX_AREA / gif->Height) { - MSG("Gif_do_img_desc: suspicious image size request %ux%u\n", + MSG("Gif_do_img_desc: suspicious image size request %u x %u\n", gif->Width, gif->Height); gif->state = 999; return 0; diff --git a/src/html.cc b/src/html.cc index 25942514..bcefe14b 100644 --- a/src/html.cc +++ b/src/html.cc @@ -68,9 +68,8 @@ using namespace dw::core::style; * Typedefs *---------------------------------------------------------------------------*/ class DilloHtml; -typedef void (*TagOpenFunct) (DilloHtml *Html, const char *Tag, int Tagsize); -typedef void (*TagCloseFunct) (DilloHtml *Html, int TagIdx); -typedef struct _DilloHtmlClass DilloHtmlClass; +typedef void (*TagOpenFunct) (DilloHtml *html, const char *tag, int tagsize); +typedef void (*TagCloseFunct) (DilloHtml *html, int TagIdx); typedef enum { SEEK_ATTR_START, @@ -305,9 +304,7 @@ static void Html_add_new_htmlimage(DilloHtml *html, * 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) +void a_Html_tag_set_align_attr(DilloHtml *html, const char *tag, int tagsize) { const char *align; @@ -340,7 +337,8 @@ void a_Html_tag_set_align_attr(DilloHtml *html, style_attrs.textAlignChar = '.'; } #endif - props->set (CSS_PROPERTY_TEXT_ALIGN, CSS_TYPE_ENUM, textAlignType); + html->styleEngine->setNonCssHint(CSS_PROPERTY_TEXT_ALIGN, CSS_TYPE_ENUM, + textAlignType); } } @@ -348,8 +346,7 @@ void a_Html_tag_set_align_attr(DilloHtml *html, * Evaluates the VALIGN attribute (top|bottom|middle|baseline) and * sets the style in style_attrs. Returns true when set. */ -bool a_Html_tag_set_valign_attr(DilloHtml *html, const char *tag, - int tagsize, CssPropertyList *props) +bool a_Html_tag_set_valign_attr(DilloHtml *html, const char *tag, int tagsize) { const char *attr; VAlignType valign; @@ -364,7 +361,8 @@ bool a_Html_tag_set_valign_attr(DilloHtml *html, const char *tag, else valign = VALIGN_MIDDLE; - props->set (CSS_PROPERTY_VERTICAL_ALIGN, CSS_TYPE_ENUM, valign); + html->styleEngine->setNonCssHint (CSS_PROPERTY_VERTICAL_ALIGN, + CSS_TYPE_ENUM, valign); return true; } else return false; @@ -433,9 +431,9 @@ DilloHtml::DilloHtml(BrowserWindow *p_bw, const DilloUrl *url, stack = new misc::SimpleVector <DilloHtmlState> (16); stack->increase(); - 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)->table_border_mode = DILLO_HTML_TABLE_BORDER_SEPARATE; stack->getRef(0)->cell_text_align_set = false; stack->getRef(0)->list_type = HTML_LIST_NONE; stack->getRef(0)->list_number = 0; @@ -586,9 +584,6 @@ int DilloHtml::getCurTagLineNumber() */ void DilloHtml::freeParseData() { - for (int i = stack->size () - 1; i >= 0; i--) - if (stack->getRef (i)->table_cell_props) - stack->getRef (i)->table_cell_props->unref (); delete(stack); dStr_free(Stash, TRUE); @@ -1189,13 +1184,13 @@ static void Html_process_word(DilloHtml *html, const char *word, int size) dFree(Pword); } else { - const char *word2, *word2_end; + const char *word2, *beyond_word2; Pword = NULL; if (!memchr(word,'&', size)) { /* No entities */ word2 = word; - word2_end = word + size - 1; + beyond_word2 = word + size; } else { /* Collapse white-space entities inside the word (except ) */ Pword = a_Html_parse_entities(html, word, size); @@ -1210,7 +1205,7 @@ static void Html_process_word(DilloHtml *html, const char *word, int size) } } word2 = Pword; - word2_end = word2 + strlen(word2) - 1; + beyond_word2 = word2 + strlen(word2); } for (start = i = 0; word2[i]; start = i) { int len; @@ -1220,7 +1215,7 @@ static void Html_process_word(DilloHtml *html, const char *word, int size) Html_process_space(html, word2 + start, i - start); } else if (!strncmp(word2+i, utf8_zero_width_space, 3)) { i += 3; - } else if (a_Utf8_ideographic(word2+i, word2_end, &len)) { + } else if (a_Utf8_ideographic(word2+i, beyond_word2, &len)) { i += len; HT2TB(html)->addText(word2 + start, i - start, html->styleEngine->wordStyle ()); @@ -1229,7 +1224,7 @@ static void Html_process_word(DilloHtml *html, const char *word, int size) i += len; } while (word2[i] && !isspace(word2[i]) && strncmp(word2+i, utf8_zero_width_space, 3) && - (!a_Utf8_ideographic(word2+i, word2_end, &len))); + (!a_Utf8_ideographic(word2+i, beyond_word2, &len))); HT2TB(html)->addText(word2 + start, i - start, html->styleEngine->wordStyle ()); } @@ -1284,8 +1279,6 @@ static void Html_push_tag(DilloHtml *html, int tag_idx) * instead of copying all fields except for tag. --Jcid */ *html->stack->getRef(n_items) = *html->stack->getRef(n_items - 1); html->stack->getRef(n_items)->tag_idx = tag_idx; - if (S_TOP(html)->table_cell_props) - S_TOP(html)->table_cell_props->ref (); html->dw = S_TOP(html)->textblock; } @@ -1307,8 +1300,6 @@ static void Html_real_pop_tag(DilloHtml *html) bool hand_over_break; 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); @@ -1505,7 +1496,8 @@ static int */ static void Html_parse_doctype(DilloHtml *html, const char *tag, int tagsize) { - static const char HTML_sig [] = "<!DOCTYPE HTML PUBLIC "; + static const char HTML_SGML_sig [] = "<!DOCTYPE HTML PUBLIC "; + static const char HTML5_sig [] = "<!DOCTYPE html>"; static const char HTML20 [] = "-//IETF//DTD HTML 2.0"; static const char HTML32 [] = "-//W3C//DTD HTML 3.2"; static const char HTML40 [] = "-//W3C//DTD HTML 4.0"; @@ -1541,8 +1533,8 @@ static void Html_parse_doctype(DilloHtml *html, const char *tag, int tagsize) _MSG("New: {%s}\n", ntag); /* The default DT_NONE type is TagSoup */ - if (!dStrncasecmp(ntag, HTML_sig, strlen(HTML_sig))) { - p = ntag + strlen(HTML_sig) + 1; + if (!dStrncasecmp(ntag, HTML_SGML_sig, strlen(HTML_SGML_sig))) { + p = ntag + strlen(HTML_SGML_sig) + 1; if (!strncmp(p, HTML401, strlen(HTML401)) && dStristr(p + strlen(HTML401), HTML401_url)) { html->DocType = DT_HTML; @@ -1565,6 +1557,10 @@ static void Html_parse_doctype(DilloHtml *html, const char *tag, int tagsize) html->DocType = DT_HTML; html->DocTypeVersion = 2.0f; } + } else if (!dStrcasecmp(ntag, HTML5_sig)) { + BUG_MSG("Document follows HTML5 working draft; treating as HTML4.\n"); + html->DocType = DT_HTML; + html->DocTypeVersion = 5.0f; } dFree(ntag); @@ -1728,9 +1724,9 @@ static void Html_tag_open_body(DilloHtml *html, const char *tag, int tagsize) { const char *attrbuf; Textblock *textblock; - CssPropertyList props; int32_t color; int tag_index_a = a_Html_tag_index ("a"); + style::Color *bgColor; if (!(html->InFlags & IN_BODY)) html->InFlags |= IN_BODY; @@ -1750,24 +1746,32 @@ static void Html_tag_open_body(DilloHtml *html, const char *tag, int tagsize) if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "bgcolor"))) { color = a_Html_color_parse(html, attrbuf, -1); if (color != -1) - props.set (CSS_PROPERTY_BACKGROUND_COLOR, CSS_TYPE_COLOR, color); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BACKGROUND_COLOR, + CSS_TYPE_COLOR, color); } if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "text"))) { color = a_Html_color_parse(html, attrbuf, -1); if (color != -1) - props.set (CSS_PROPERTY_COLOR, CSS_TYPE_COLOR, color); + html->styleEngine->setNonCssHint (CSS_PROPERTY_COLOR, + CSS_TYPE_COLOR, color); } + html->styleEngine->restyle (); + if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "link"))) html->non_css_link_color = a_Html_color_parse(html, attrbuf, -1); if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "vlink"))) html->non_css_visited_color = a_Html_color_parse(html, attrbuf, -1); - html->styleEngine->setNonCssHints (&props); html->dw->setStyle (html->styleEngine->style ()); + bgColor = html->styleEngine->backgroundColor (); + + if (bgColor) + HT2LT(html)->setBgColor(bgColor); + /* Determine a color for visited links. * This color is computed once per page and used for immediate feedback * when clicking a link. @@ -1777,10 +1781,8 @@ static void Html_tag_open_body(DilloHtml *html, const char *tag, int tagsize) html->styleEngine->startElement (tag_index_a); html->styleEngine->setPseudoVisited (); if (html->non_css_visited_color != -1) { - CssPropertyList vprops; - vprops.set (CSS_PROPERTY_COLOR, CSS_TYPE_COLOR, - html->non_css_visited_color); - html->styleEngine->setNonCssHints (&vprops); + html->styleEngine->setNonCssHint (CSS_PROPERTY_COLOR, CSS_TYPE_COLOR, + html->non_css_visited_color); } html->visited_color = html->styleEngine->style ()->color->getColor (); html->styleEngine->endElement (tag_index_a); @@ -1794,6 +1796,7 @@ static void Html_tag_open_body(DilloHtml *html, const char *tag, int tagsize) html->styleEngine->backgroundStyle()->backgroundColor->getColor()); } + S_TOP(html)->parse_mode = DILLO_HTML_PARSE_MODE_BODY; } @@ -1817,9 +1820,8 @@ static void Html_tag_open_p(DilloHtml *html, const char *tag, int tagsize) { CssPropertyList props; - a_Html_tag_set_align_attr (html, &props, tag, tagsize); + a_Html_tag_set_align_attr (html, tag, tagsize); html->styleEngine->inheritBackgroundColor (); - html->styleEngine->setNonCssHints (&props); HT2TB(html)->addParbreak (9, html->styleEngine->wordStyle ()); } @@ -1855,8 +1857,8 @@ static void Html_tag_open_frame (DilloHtml *html, const char *tag, int tagsize) html->styleEngine->setPseudoLink (); } - props.set (PROPERTY_X_LINK, CSS_TYPE_INTEGER, Html_set_new_link(html,&url)); - html->styleEngine->setNonCssHints (&props); + html->styleEngine->setNonCssHint (PROPERTY_X_LINK, CSS_TYPE_INTEGER, + Html_set_new_link(html,&url)); textblock->addParbreak (5, html->styleEngine->wordStyle ()); @@ -1902,12 +1904,8 @@ static void Html_tag_open_frameset (DilloHtml *html, */ static void Html_tag_open_h(DilloHtml *html, const char *tag, int tagsize) { - CssPropertyList props; - - html->styleEngine->inheritBackgroundColor (); - a_Html_tag_set_align_attr (html, &props, tag, tagsize); - html->styleEngine->setNonCssHints (&props); + a_Html_tag_set_align_attr (html, tag, tagsize); HT2TB(html)->addParbreak (9, html->styleEngine->wordStyle ()); @@ -1932,7 +1930,6 @@ static void Html_tag_open_font(DilloHtml *html, const char *tag, int tagsize) const char *attrbuf; char *fontFamily = NULL; int32_t color; - CssPropertyList props; if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "color"))) { if (prefs.contrast_visited_color && html->InVisitedLink) { @@ -1942,15 +1939,16 @@ static void Html_tag_open_font(DilloHtml *html, const char *tag, int tagsize) color = a_Html_color_parse(html, attrbuf, -1); } if (color != -1) - props.set (CSS_PROPERTY_COLOR, CSS_TYPE_COLOR, color); + html->styleEngine->setNonCssHint (CSS_PROPERTY_COLOR, + CSS_TYPE_COLOR, color); } if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "face"))) { fontFamily = dStrdup(attrbuf); - props.set (CSS_PROPERTY_FONT_FAMILY, CSS_TYPE_SYMBOL, fontFamily); + html->styleEngine->setNonCssHint (CSS_PROPERTY_FONT_FAMILY, + CSS_TYPE_SYMBOL, fontFamily); } - html->styleEngine->setNonCssHints (&props); dFree(fontFamily); } @@ -1961,14 +1959,13 @@ static void Html_tag_open_abbr(DilloHtml *html, const char *tag, int tagsize) { const char *attrbuf; + html->styleEngine->inheritBackgroundColor (); + if (prefs.show_tooltip && (attrbuf = a_Html_get_attr(html, tag, tagsize, "title"))) { - CssPropertyList props; - char *tooltip_str = dStrdup(attrbuf); - props.set (PROPERTY_X_TOOLTIP, CSS_TYPE_STRING, tooltip_str); - html->styleEngine->setNonCssHints (&props); - dFree(tooltip_str); + html->styleEngine->setNonCssHint (PROPERTY_X_TOOLTIP, CSS_TYPE_STRING, + attrbuf); } } @@ -1977,6 +1974,7 @@ static void Html_tag_open_abbr(DilloHtml *html, const char *tag, int tagsize) */ static void Html_tag_open_center(DilloHtml *html, const char *tag, int tagsize) { + html->styleEngine->inheritBackgroundColor (); HT2TB(html)->addParbreak (0, html->styleEngine->wordStyle ()); } @@ -1994,6 +1992,7 @@ static void Html_tag_close_center(DilloHtml *html, int TagIdx) static void Html_tag_open_address(DilloHtml *html, const char *tag, int tagsize) { + html->styleEngine->inheritBackgroundColor (); HT2TB(html)->addParbreak (9, html->styleEngine->wordStyle ()); } @@ -2010,13 +2009,11 @@ DilloImage *a_Html_image_new(DilloHtml *html, const char *tag, CssLength l_h = CSS_CREATE_LENGTH(0.0, CSS_LENGTH_TYPE_AUTO); int space, border, w = 0, h = 0; bool load_now; - CssPropertyList props; - char *tooltip_str = NULL; if (prefs.show_tooltip && (attrbuf = a_Html_get_attr(html, tag, tagsize, "title"))) { - tooltip_str = dStrdup(attrbuf); - props.set (PROPERTY_X_TOOLTIP, CSS_TYPE_STRING, tooltip_str); + html->styleEngine->setNonCssHint(PROPERTY_X_TOOLTIP, CSS_TYPE_STRING, + attrbuf); } alt_ptr = a_Html_get_attr_wdef(html, tag, tagsize, "alt", NULL); if ((!alt_ptr || !*alt_ptr) && !prefs.load_images) { @@ -2052,12 +2049,14 @@ DilloImage *a_Html_image_new(DilloHtml *html, const char *tag, dFree(width_ptr); dFree(height_ptr); width_ptr = height_ptr = NULL; - MSG("a_Html_image_new: suspicious image size request %dx%d\n", w, h); + MSG("a_Html_image_new: suspicious image size request %d x %d\n", w, h); } else { if (CSS_LENGTH_TYPE(l_w) != CSS_LENGTH_TYPE_AUTO) - props.set (CSS_PROPERTY_WIDTH, CSS_TYPE_LENGTH_PERCENTAGE, l_w); + html->styleEngine->setNonCssHint (CSS_PROPERTY_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, l_w); if (CSS_LENGTH_TYPE(l_h) != CSS_LENGTH_TYPE_AUTO) - props.set (CSS_PROPERTY_HEIGHT, CSS_TYPE_LENGTH_PERCENTAGE, l_h); + html->styleEngine->setNonCssHint (CSS_PROPERTY_HEIGHT, + CSS_TYPE_LENGTH_PERCENTAGE, l_h); } /* TODO: we should scale the image respecting its ratio. @@ -2072,10 +2071,10 @@ DilloImage *a_Html_image_new(DilloHtml *html, const char *tag, space = strtol(attrbuf, NULL, 10); if (space > 0) { space = CSS_CREATE_LENGTH(space, CSS_LENGTH_TYPE_PX); - props.set (CSS_PROPERTY_MARGIN_LEFT, CSS_TYPE_LENGTH_PERCENTAGE, - space); - props.set (CSS_PROPERTY_MARGIN_RIGHT, CSS_TYPE_LENGTH_PERCENTAGE, - space); + html->styleEngine->setNonCssHint (CSS_PROPERTY_MARGIN_LEFT, + CSS_TYPE_LENGTH_PERCENTAGE, space); + html->styleEngine->setNonCssHint (CSS_PROPERTY_MARGIN_RIGHT, + CSS_TYPE_LENGTH_PERCENTAGE, space); } } @@ -2084,10 +2083,10 @@ DilloImage *a_Html_image_new(DilloHtml *html, const char *tag, space = strtol(attrbuf, NULL, 10); if (space > 0) { space = CSS_CREATE_LENGTH(space, CSS_LENGTH_TYPE_PX); - props.set (CSS_PROPERTY_MARGIN_TOP, CSS_TYPE_LENGTH_PERCENTAGE, - space); - props.set (CSS_PROPERTY_MARGIN_BOTTOM, CSS_TYPE_LENGTH_PERCENTAGE, - space); + html->styleEngine->setNonCssHint (CSS_PROPERTY_MARGIN_TOP, + CSS_TYPE_LENGTH_PERCENTAGE, space); + html->styleEngine->setNonCssHint (CSS_PROPERTY_MARGIN_BOTTOM, + CSS_TYPE_LENGTH_PERCENTAGE, space); } } @@ -2096,31 +2095,30 @@ DilloImage *a_Html_image_new(DilloHtml *html, const char *tag, border = strtol(attrbuf, NULL, 10); if (border >= 0) { border = CSS_CREATE_LENGTH(border, CSS_LENGTH_TYPE_PX); - props.set (CSS_PROPERTY_BORDER_TOP_WIDTH, CSS_TYPE_LENGTH_PERCENTAGE, - border); - props.set (CSS_PROPERTY_BORDER_BOTTOM_WIDTH, - CSS_TYPE_LENGTH_PERCENTAGE, border); - props.set (CSS_PROPERTY_BORDER_LEFT_WIDTH, - CSS_TYPE_LENGTH_PERCENTAGE, border); - props.set (CSS_PROPERTY_BORDER_RIGHT_WIDTH, - CSS_TYPE_LENGTH_PERCENTAGE, border); - - props.set (CSS_PROPERTY_BORDER_TOP_STYLE, CSS_TYPE_ENUM, - BORDER_SOLID); - props.set (CSS_PROPERTY_BORDER_BOTTOM_STYLE, CSS_TYPE_ENUM, - BORDER_SOLID); - props.set (CSS_PROPERTY_BORDER_LEFT_STYLE, CSS_TYPE_ENUM, - BORDER_SOLID); - props.set (CSS_PROPERTY_BORDER_RIGHT_STYLE, CSS_TYPE_ENUM, - BORDER_SOLID); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_TOP_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, border); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_BOTTOM_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, border); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_LEFT_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, border); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_RIGHT_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, border); + + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_TOP_STYLE, + CSS_TYPE_ENUM, BORDER_SOLID); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_BOTTOM_STYLE, + CSS_TYPE_ENUM, BORDER_SOLID); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_LEFT_STYLE, + CSS_TYPE_ENUM, BORDER_SOLID); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_RIGHT_STYLE, + CSS_TYPE_ENUM, BORDER_SOLID); } } /* x_img is an index to a list of {url,image} pairs. * We know Html_add_new_htmlimage() will use size() as its next index */ - props.set (PROPERTY_X_IMG, CSS_TYPE_INTEGER, html->images->size()); - - html->styleEngine->setNonCssHints(&props); + html->styleEngine->setNonCssHint (PROPERTY_X_IMG, CSS_TYPE_INTEGER, + html->images->size()); /* Add a new image widget to this page */ Image = a_Image_new(alt_ptr, 0); @@ -2135,7 +2133,6 @@ DilloImage *a_Html_image_new(DilloHtml *html, const char *tag, loading = Html_load_image(html->bw, url, html->page_url, Image); Html_add_new_htmlimage(html, &url, loading ? NULL : Image); - dFree(tooltip_str); dFree(width_ptr); dFree(height_ptr); dFree(alt_ptr); @@ -2279,7 +2276,7 @@ misc::SimpleVector<int> *Html_read_coords(DilloHtml *html, const char *str) if (!*newtail) break; if (*newtail != ',') { - BUG_MSG("usemap coords MUST be separated by commas.\n"); + BUG_MSG("area coords must be integers separated by commas.\n"); } tail = newtail + 1; } @@ -2347,10 +2344,6 @@ static void Html_tag_open_area(DilloHtml *html, const char *tag, int tagsize) shape = poly = new Polygon(); for (i = 0; i < (coords->size() / 2); i++) poly->addPoint(coords->get(2*i), coords->get(2*i + 1)); - if (i) { - /* be sure to close it */ - poly->addPoint(coords->get(0), coords->get(1)); - } } delete(coords); } @@ -2379,7 +2372,6 @@ static void Html_tag_open_object(DilloHtml *html, const char *tag, int tagsize) { 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); @@ -2396,9 +2388,8 @@ static void Html_tag_open_object(DilloHtml *html, const char *tag, int tagsize) html->styleEngine->setPseudoLink (); } - props.set(PROPERTY_X_LINK, CSS_TYPE_INTEGER, - Html_set_new_link(html, &url)); - html->styleEngine->setNonCssHints (&props); + html->styleEngine->setNonCssHint(PROPERTY_X_LINK, CSS_TYPE_INTEGER, + Html_set_new_link(html, &url)); HT2TB(html)->addText("[OBJECT]", html->styleEngine->wordStyle ()); } @@ -2452,8 +2443,6 @@ static void Html_add_anchor(DilloHtml *html, const char *name) static void Html_tag_open_a(DilloHtml *html, const char *tag, int tagsize) { DilloUrl *url; - char *tooltip_str = NULL; - CssPropertyList props; const char *attrbuf; /* TODO: add support for MAP with A HREF */ @@ -2472,25 +2461,23 @@ static void Html_tag_open_a(DilloHtml *html, const char *tag, int tagsize) html->InVisitedLink = true; html->styleEngine->setPseudoVisited (); if (html->non_css_visited_color != -1) - props.set (CSS_PROPERTY_COLOR, CSS_TYPE_COLOR, - html->non_css_visited_color); + html->styleEngine->setNonCssHint(CSS_PROPERTY_COLOR, CSS_TYPE_COLOR, + html->non_css_visited_color); } else { html->styleEngine->setPseudoLink (); if (html->non_css_link_color != -1) - props.set (CSS_PROPERTY_COLOR, CSS_TYPE_COLOR, - html->non_css_link_color); + html->styleEngine->setNonCssHint(CSS_PROPERTY_COLOR, CSS_TYPE_COLOR, + html->non_css_link_color); } - props.set (PROPERTY_X_LINK, CSS_TYPE_INTEGER, - Html_set_new_link(html, &url)); + html->styleEngine->setNonCssHint (PROPERTY_X_LINK, CSS_TYPE_INTEGER, + Html_set_new_link(html, &url)); } if (prefs.show_tooltip && (attrbuf = a_Html_get_attr(html, tag, tagsize, "title"))) { - tooltip_str = dStrdup(attrbuf); - props.set (PROPERTY_X_TOOLTIP, CSS_TYPE_STRING, tooltip_str); + html->styleEngine->setNonCssHint (PROPERTY_X_TOOLTIP, CSS_TYPE_STRING, + attrbuf); } - html->styleEngine->setNonCssHints (&props); - dFree(tooltip_str); html->styleEngine->inheritBackgroundColor (); @@ -2538,13 +2525,14 @@ static void Html_tag_open_blockquote(DilloHtml *html, */ static void Html_tag_open_q(DilloHtml *html, const char *tag, int tagsize) { - /* - * Left Double Quotation Mark, which is wrong in many cases, but - * should at least be widely recognized. - */ - const char *U201C = "\xe2\x80\x9c"; + /* + * Left Double Quotation Mark, which is wrong in many cases, but + * should at least be widely recognized. + */ + const char *U201C = "\xe2\x80\x9c"; - HT2TB(html)->addText (U201C, html->styleEngine->wordStyle ()); + html->styleEngine->inheritBackgroundColor (); + HT2TB(html)->addText (U201C, html->styleEngine->wordStyle ()); } /* @@ -2567,7 +2555,6 @@ static void Html_tag_open_ul(DilloHtml *html, const char *tag, int tagsize) ListStyleType list_style_type; if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "type"))) { - CssPropertyList props; /* list_style_type explicitly defined */ if (dStrcasecmp(attrbuf, "disc") == 0) @@ -2580,8 +2567,8 @@ static void Html_tag_open_ul(DilloHtml *html, const char *tag, int tagsize) /* invalid value */ list_style_type = LIST_STYLE_TYPE_DISC; - props.set(CSS_PROPERTY_LIST_STYLE_TYPE, CSS_TYPE_ENUM, list_style_type); - html->styleEngine->setNonCssHints (&props); + html->styleEngine->setNonCssHint (CSS_PROPERTY_LIST_STYLE_TYPE, + CSS_TYPE_ENUM, list_style_type); } Html_add_textblock(html, 9); @@ -2597,6 +2584,7 @@ static void Html_tag_open_ul(DilloHtml *html, const char *tag, int tagsize) */ static void Html_tag_open_dir(DilloHtml *html, const char *tag, int tagsize) { + html->styleEngine->inheritBackgroundColor (); HT2TB(html)->addParbreak (9, html->styleEngine->wordStyle ()); S_TOP(html)->list_type = HTML_LIST_UNORDERED; @@ -2624,7 +2612,6 @@ static void Html_tag_open_ol(DilloHtml *html, const char *tag, int tagsize) int n = 1; if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "type"))) { - CssPropertyList props; ListStyleType listStyleType = LIST_STYLE_TYPE_DECIMAL; if (*attrbuf == '1') @@ -2638,8 +2625,8 @@ static void Html_tag_open_ol(DilloHtml *html, const char *tag, int tagsize) else if (*attrbuf == 'I') listStyleType = LIST_STYLE_TYPE_UPPER_ROMAN; - props.set (CSS_PROPERTY_LIST_STYLE_TYPE, CSS_TYPE_ENUM, listStyleType); - html->styleEngine->setNonCssHints (&props); + html->styleEngine->setNonCssHint (CSS_PROPERTY_LIST_STYLE_TYPE, + CSS_TYPE_ENUM, listStyleType); } Html_add_textblock(html, 9); @@ -2717,29 +2704,33 @@ static void Html_tag_close_li(DilloHtml *html, int TagIdx) static void Html_tag_open_hr(DilloHtml *html, const char *tag, int tagsize) { Widget *hruler; - CssPropertyList props; char *width_ptr; const char *attrbuf; int32_t size = 0; width_ptr = a_Html_get_attr_wdef(html, tag, tagsize, "width", NULL); if (width_ptr) { - props.set (CSS_PROPERTY_WIDTH, CSS_TYPE_LENGTH_PERCENTAGE, - a_Html_parse_length (html, width_ptr)); + html->styleEngine->setNonCssHint (CSS_PROPERTY_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, + 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); - a_Html_tag_set_align_attr(html, &props, tag, tagsize); + a_Html_tag_set_align_attr(html, tag, tagsize); /* TODO: evaluate attribute */ if (a_Html_get_attr(html, tag, tagsize, "noshade")) { - props.set (CSS_PROPERTY_BORDER_TOP_STYLE, CSS_TYPE_ENUM, BORDER_SOLID); - props.set (CSS_PROPERTY_BORDER_BOTTOM_STYLE,CSS_TYPE_ENUM,BORDER_SOLID); - props.set (CSS_PROPERTY_BORDER_LEFT_STYLE, CSS_TYPE_ENUM, BORDER_SOLID); - props.set (CSS_PROPERTY_BORDER_RIGHT_STYLE, CSS_TYPE_ENUM, BORDER_SOLID); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_TOP_STYLE, + CSS_TYPE_ENUM, BORDER_SOLID); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_BOTTOM_STYLE, + CSS_TYPE_ENUM, BORDER_SOLID); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_LEFT_STYLE, + CSS_TYPE_ENUM, BORDER_SOLID); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_RIGHT_STYLE, + CSS_TYPE_ENUM, BORDER_SOLID); if (size <= 0) size = 1; @@ -2748,18 +2739,16 @@ static void Html_tag_open_hr(DilloHtml *html, const char *tag, int tagsize) 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 (CSS_PROPERTY_BORDER_TOP_WIDTH, CSS_TYPE_LENGTH_PERCENTAGE, - size_top); - props.set (CSS_PROPERTY_BORDER_LEFT_WIDTH, CSS_TYPE_LENGTH_PERCENTAGE, - size_top); - props.set (CSS_PROPERTY_BORDER_BOTTOM_WIDTH, CSS_TYPE_LENGTH_PERCENTAGE, - size_bottom); - props.set (CSS_PROPERTY_BORDER_RIGHT_WIDTH, CSS_TYPE_LENGTH_PERCENTAGE, - size_bottom); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_TOP_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, size_top); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_LEFT_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, size_top); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_BOTTOM_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, size_bottom); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_RIGHT_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, size_bottom); } - html->styleEngine->setNonCssHints (&props); - HT2TB(html)->addParbreak (5, html->styleEngine->wordStyle ()); hruler = new Ruler(); @@ -2774,6 +2763,7 @@ static void Html_tag_open_hr(DilloHtml *html, const char *tag, int tagsize) static void Html_tag_open_dl(DilloHtml *html, const char *tag, int tagsize) { /* may want to actually do some stuff here. */ + html->styleEngine->inheritBackgroundColor (); HT2TB(html)->addParbreak (9, html->styleEngine->wordStyle ()); } @@ -2782,6 +2772,7 @@ static void Html_tag_open_dl(DilloHtml *html, const char *tag, int tagsize) */ static void Html_tag_open_dt(DilloHtml *html, const char *tag, int tagsize) { + html->styleEngine->inheritBackgroundColor (); HT2TB(html)->addParbreak (9, html->styleEngine->wordStyle ()); } @@ -2798,6 +2789,7 @@ static void Html_tag_open_dd(DilloHtml *html, const char *tag, int tagsize) */ static void Html_tag_open_pre(DilloHtml *html, const char *tag, int tagsize) { + html->styleEngine->inheritBackgroundColor (); HT2TB(html)->addParbreak (9, html->styleEngine->wordStyle ()); html->InFlags |= IN_PRE; @@ -2879,41 +2871,44 @@ static void Html_tag_open_meta(DilloHtml *html, const char *tag, int tagsize) } /* Skip to anything after "URL=" */ while (*content && *(content++) != '=') ; - /* Handle the case of a quoted URL */ - if (*content == '"' || *content == '\'') { - if ((p = strchr(content + 1, *content))) - mr_url = dStrndup(content + 1, p - content - 1); - else - mr_url = dStrdup(content + 1); - } else { - mr_url = dStrdup(content); - } + if (*content) { - if (delay == 0) { - /* zero-delay redirection */ - html->stop_parser = true; - DilloUrl *new_url = a_Url_new(mr_url, URL_STR(html->base_url)); - if (a_Capi_dpi_verify_request(html->bw, new_url)) - a_UIcmd_redirection0((void*)html->bw, new_url); - a_Url_free(new_url); - } else { - /* Send a custom HTML message. - * TODO: This is a hairy hack, - * It'd be much better to build a widget. */ - Dstr *ds_msg = dStr_sized_new(256); - dStr_sprintf(ds_msg, meta_template, mr_url, delay_str); - { - int o_InFlags = html->InFlags; - int o_TagSoup = html->TagSoup; - html->InFlags = IN_BODY; - html->TagSoup = false; - Html_write_raw(html, ds_msg->str, ds_msg->len, 0); - html->TagSoup = o_TagSoup; - html->InFlags = o_InFlags; + /* Handle the case of a quoted URL */ + if (*content == '"' || *content == '\'') { + if ((p = strchr(content + 1, *content))) + mr_url = dStrndup(content + 1, p - content - 1); + else + mr_url = dStrdup(content + 1); + } else { + mr_url = dStrdup(content); + } + + if (delay == 0) { + /* zero-delay redirection */ + html->stop_parser = true; + DilloUrl *new_url = a_Url_new(mr_url, URL_STR(html->base_url)); + if (a_Capi_dpi_verify_request(html->bw, new_url)) + a_UIcmd_redirection0((void*)html->bw, new_url); + a_Url_free(new_url); + } else { + /* Send a custom HTML message. + * TODO: This is a hairy hack, + * It'd be much better to build a widget. */ + Dstr *ds_msg = dStr_sized_new(256); + dStr_sprintf(ds_msg, meta_template, mr_url, delay_str); + { + int o_InFlags = html->InFlags; + int o_TagSoup = html->TagSoup; + html->InFlags = IN_BODY; + html->TagSoup = false; + Html_write_raw(html, ds_msg->str, ds_msg->len, 0); + html->TagSoup = o_TagSoup; + html->InFlags = o_InFlags; + } + dStr_free(ds_msg, 1); } - dStr_free(ds_msg, 1); + dFree(mr_url); } - dFree(mr_url); } else if (!dStrcasecmp(equiv, "content-type") && (content = a_Html_get_attr(html, tag, tagsize, "content"))) { @@ -3095,10 +3090,7 @@ static void Html_tag_open_default(DilloHtml *html,const char *tag,int tagsize) */ static void Html_tag_open_div(DilloHtml *html, const char *tag, int tagsize) { - CssPropertyList props; - - a_Html_tag_set_align_attr (html, &props, tag, tagsize); - html->styleEngine->setNonCssHints (&props); + a_Html_tag_set_align_attr (html, tag, tagsize); Html_add_textblock(html, 0); } @@ -3137,14 +3129,6 @@ static void Html_tag_close_par(DilloHtml *html, int TagIdx) * - Empty elements have both inline and block container clear. * (flow have both set) */ -struct _TagInfo{ - const char *name; - unsigned char Flags; - char EndTag; - uchar_t TagLevel; - TagOpenFunct open; - TagCloseFunct close; -}; const TagInfo Tags[] = { @@ -3739,11 +3723,8 @@ static void Html_callback(int Op, CacheClient_t *Client) static int Html_write_raw(DilloHtml *html, char *buf, int bufsize, int Eof) { char ch = 0, *p, *text; - Textblock *textblock; int token_start, buf_index; - dReturn_val_if_fail ((textblock = HT2TB(html)) != NULL, 0); - /* Now, 'buf' and 'bufsize' define a buffer aligned to start at a token * boundary. Iterate through tokens until end of buffer is reached. */ buf_index = 0; @@ -3862,7 +3843,7 @@ static int Html_write_raw(DilloHtml *html, char *buf, int bufsize, int Eof) } }/*while*/ - textblock->flush (); + HT2TB(html)->flush (); return token_start; } diff --git a/src/html_common.hh b/src/html_common.hh index 3cca82de..cf5c8114 100644 --- a/src/html_common.hh +++ b/src/html_common.hh @@ -64,6 +64,11 @@ typedef enum { } DilloHtmlTableMode; typedef enum { + DILLO_HTML_TABLE_BORDER_SEPARATE, + DILLO_HTML_TABLE_BORDER_COLLAPSE +} DilloHtmlTableBorderMode; + +typedef enum { HTML_LIST_NONE, HTML_LIST_UNORDERED, HTML_LIST_ORDERED @@ -94,10 +99,11 @@ struct _DilloHtmlImage { }; struct _DilloHtmlState { - CssPropertyList *table_cell_props; DilloHtmlParseMode parse_mode; DilloHtmlTableMode table_mode; + DilloHtmlTableBorderMode table_border_mode; bool cell_text_align_set; + DilloHtmlListMode list_type; int list_number; @@ -242,11 +248,9 @@ int32_t a_Html_color_parse(DilloHtml *html, const char *subtag, int32_t default_color); dw::core::style::Length a_Html_parse_length (DilloHtml *html, const char *attr); -void a_Html_tag_set_align_attr(DilloHtml *html, CssPropertyList *props, - const char *tag, int tagsize); +void a_Html_tag_set_align_attr(DilloHtml *html, const char *tag, int tagsize); bool a_Html_tag_set_valign_attr(DilloHtml *html, - const char *tag, int tagsize, - CssPropertyList *props); + const char *tag, int tagsize); void a_Html_load_stylesheet(DilloHtml *html, DilloUrl *url); @@ -1,7 +1,6 @@ /* * File: jpeg.c * - * Copyright (C) 1997 Raph Levien <raph@acm.org> * Copyright (C) 2000-2007 Jorge Arellano Cid <jcid@dillo.org> * * This program is free software; you can redistribute it and/or modify @@ -292,7 +291,7 @@ static void Jpeg_write(DilloJpeg *jpeg, void *Buf, uint_t BufSize) if (jpeg->cinfo.image_width <= 0 || jpeg->cinfo.image_height <= 0 || jpeg->cinfo.image_width > IMAGE_MAX_AREA / jpeg->cinfo.image_height) { - MSG("Jpeg_write: suspicious image size request %ux%u\n", + MSG("Jpeg_write: suspicious image size request %u x %u\n", (uint_t)jpeg->cinfo.image_width, (uint_t)jpeg->cinfo.image_height); jpeg->state = DILLO_JPEG_ERROR; @@ -1,7 +1,6 @@ /* * File: misc.c * - * Copyright (C) 2000 Jörgen Viksell <vsksga@hotmail.com> * Copyright (C) 2000-2007 Jorge Arellano Cid <jcid@dillo.org>, * * This program is free software; you can redistribute it and/or modify @@ -105,6 +104,7 @@ typedef struct ContentType_ { static const ContentType_t MimeTypes[] = { { "application/octet-stream", 24 }, + { "application/xhtml+xml", 21 }, { "text/html", 9 }, { "text/plain", 10 }, { "image/gif", 9 }, @@ -342,7 +342,12 @@ int a_Misc_content_type_check(const char *EntryType, const char *DetectedType) dStrncasecmp(DetectedType, "application/", 12)) { /* Not an application sent as text */ st = 0; + } else if (dStrncasecmp(EntryType, "application/xhtml+xml", 21) && + dStrncasecmp(DetectedType, "text/html", 9)) { + /* XML version of HTML */ + st = 0; } + _MSG("Type check: %s\n", st == 0 ? "MATCH" : "MISMATCH"); return st; } @@ -395,7 +395,7 @@ static void Nav_repush_callback(void *data) void a_Nav_repush(BrowserWindow *bw) { dReturn_if_fail (bw != NULL); - MSG(">>> a_Nav_repush <<<<\n"); + MSG(">>>> a_Nav_repush <<<<\n"); a_Timeout_add(0.0, Nav_repush_callback, (void*)bw); } @@ -424,7 +424,7 @@ static void Nav_redirection0_callback(void *data) void a_Nav_redirection0(BrowserWindow *bw, const DilloUrl *new_url) { dReturn_if_fail (bw != NULL); - _MSG(">>> a_Nav_redirection0 <<<<\n"); + _MSG(">>>> a_Nav_redirection0 <<<<\n"); a_Url_free(bw->meta_refresh_url); bw->meta_refresh_url = a_Url_dup(new_url); @@ -65,8 +65,8 @@ struct _DilloPng { int version; /* Secondary Key for the dicache */ double display_exponent; /* gamma correction */ - ulong_t width; /* png image width */ - ulong_t height; /* png image height */ + png_uint_32 width; /* png image width */ + png_uint_32 height; /* png image height */ png_structp png_ptr; /* libpng private data */ png_infop info_ptr; /* libpng private info */ uchar_t *image_data; /* decoded image data */ @@ -135,17 +135,17 @@ Png_datainfo_callback(png_structp png_ptr, png_infop info_ptr) &bit_depth, &color_type, &interlace_type, NULL, NULL); /* check max image size */ - if (png->width <= 0 || png->height <= 0 || + if (png->width == 0 || png->height == 0 || png->width > IMAGE_MAX_AREA / png->height) { - MSG("Png_datainfo_callback: suspicious image size request %ldx%ld\n", - png->width, png->height); + MSG("Png_datainfo_callback: suspicious image size request %lu x %lu\n", + (ulong_t) png->width, (ulong_t) png->height); Png_error_handling(png_ptr, "Aborting..."); return; /* not reached */ } - _MSG("Png_datainfo_callback: png->width = %ld\n" - "Png_datainfo_callback: png->height = %ld\n", - png->width, png->height); + _MSG("Png_datainfo_callback: png->width = %lu\n" + "Png_datainfo_callback: png->height = %lu\n", + (ulong_t) png->width, (ulong_t) png->height); /* we need RGB/RGBA in the end */ if (color_type == PNG_COLOR_TYPE_PALETTE && bit_depth <= 8) { @@ -193,9 +193,9 @@ Png_datainfo_callback(png_structp png_ptr, png_infop info_ptr) /* init Dillo specifics */ _MSG("Png_datainfo_callback: rowbytes = %d\n" - "Png_datainfo_callback: width = %ld\n" - "Png_datainfo_callback: height = %ld\n", - png->rowbytes, png->width, png->height); + "Png_datainfo_callback: width = %lu\n" + "Png_datainfo_callback: height = %lu\n", + png->rowbytes, (ulong_t) png->width, (ulong_t) png->height); png->image_data = (uchar_t *) dMalloc(png->rowbytes * png->height); png->row_pointers = (uchar_t **) dMalloc(png->height * sizeof(uchar_t *)); diff --git a/src/prefs.c b/src/prefs.c index 5514c01a..f968710a 100644 --- a/src/prefs.c +++ b/src/prefs.c @@ -36,6 +36,7 @@ DilloPrefs prefs; void a_Prefs_init(void) { prefs.allow_white_bg = TRUE; + prefs.bg_color = 0xdcd1ba; prefs.buffered_drawing = 1; prefs.contrast_visited_color = TRUE; prefs.enterpress_forces_submit = FALSE; diff --git a/src/prefs.h b/src/prefs.h index 684262ed..4009925c 100644 --- a/src/prefs.h +++ b/src/prefs.h @@ -46,6 +46,7 @@ struct _DilloPrefs { DilloUrl *start_page; DilloUrl *home; bool_t allow_white_bg; + int32_t bg_color; bool_t contrast_visited_color; bool_t show_tooltip; int panel_size; diff --git a/src/prefsparser.cc b/src/prefsparser.cc index 78cade0b..95f98c16 100644 --- a/src/prefsparser.cc +++ b/src/prefsparser.cc @@ -16,11 +16,13 @@ #include "prefs.h" #include "misc.h" #include "msg.h" +#include "colors.h" #include "prefsparser.hh" typedef enum { PREFS_BOOL, + PREFS_COLOR, PREFS_STRING, PREFS_URL, PREFS_INT32, @@ -43,10 +45,12 @@ int PrefsParser::parseOption(char *name, char *value) { const SymNode_t *node; uint_t i; + int st; /* Symbol array, sorted alphabetically */ const SymNode_t symbols[] = { { "allow_white_bg", &prefs.allow_white_bg, PREFS_BOOL }, + { "bg_color", &prefs.bg_color, PREFS_COLOR }, { "buffered_drawing", &prefs.buffered_drawing, PREFS_INT32 }, { "contrast_visited_color", &prefs.contrast_visited_color, PREFS_BOOL }, { "enterpress_forces_submit", &prefs.enterpress_forces_submit, @@ -122,6 +126,9 @@ int PrefsParser::parseOption(char *name, char *value) *(bool_t *)node->pref = (!dStrcasecmp(value, "yes") || !dStrcasecmp(value, "true")); break; + case PREFS_COLOR: + *(int32_t *)node->pref = a_Color_parse(value, *(int32_t*)node->pref,&st); + break; case PREFS_STRING: dFree(*(char **)node->pref); *(char **)node->pref = dStrdup(value); diff --git a/src/styleengine.cc b/src/styleengine.cc index b861e717..776c1694 100644 --- a/src/styleengine.cc +++ b/src/styleengine.cc @@ -15,6 +15,7 @@ #include "html_common.hh" #include "styleengine.hh" +using namespace lout::misc; using namespace dw::core::style; StyleEngine::StyleEngine (dw::core::Layout *layout) { @@ -32,7 +33,7 @@ StyleEngine::StyleEngine (dw::core::Layout *layout) { /* Create a dummy font, attribute, and tag for the bottom of the stack. */ font_attrs.name = prefs.font_sans_serif; - font_attrs.size = (int) (14 * prefs.font_factor + 0.5); + font_attrs.size = roundInt(14 * prefs.font_factor); if (font_attrs.size < prefs.font_min_size) font_attrs.size = prefs.font_min_size; if (font_attrs.size > prefs.font_max_size) @@ -40,6 +41,7 @@ StyleEngine::StyleEngine (dw::core::Layout *layout) { font_attrs.weight = 400; font_attrs.style = FONT_STYLE_NORMAL; font_attrs.letterSpacing = 0; + font_attrs.fontVariant = FONT_VARIANT_NORMAL; style_attrs.initValues (); style_attrs.font = Font::create (layout, &font_attrs); @@ -48,13 +50,23 @@ StyleEngine::StyleEngine (dw::core::Layout *layout) { n->style = Style::create (layout, &style_attrs); n->wordStyle = NULL; - n->styleAttribute = NULL; + n->backgroundStyle = NULL; + n->styleAttrProperties = NULL; + n->nonCssProperties = NULL; n->inheritBackgroundColor = false; } StyleEngine::~StyleEngine () { while (doctree->top ()) endElement (doctree->top ()->element); + assert (stack->size () == 1); // dummy node on the bottom of the stack + Node *n = stack->getRef (stack->size () - 1); + if (n->style) + n->style->unref (); + if (n->wordStyle) + n->wordStyle->unref (); + if (n->backgroundStyle) + n->backgroundStyle->unref (); delete stack; delete doctree; delete cssContext; @@ -65,17 +77,20 @@ StyleEngine::~StyleEngine () { */ void StyleEngine::startElement (int element) { if (stack->getRef (stack->size () - 1)->style == NULL) - style0 (); + style0 (stack->size () - 1); stack->increase (); Node *n = stack->getRef (stack->size () - 1); + n->styleAttrProperties = NULL; + n->nonCssProperties = NULL; n->style = NULL; n->wordStyle = NULL; - n->styleAttribute = NULL; + n->backgroundStyle = NULL; n->inheritBackgroundColor = false; DoctreeNode *dn = doctree->push (); dn->element = element; + n->doctreeNode = dn; } void StyleEngine::startElement (const char *tagname) { @@ -119,20 +134,36 @@ void StyleEngine::setClass (const char *klass) { dn->klass = splitStr (klass, ' '); }; -void StyleEngine::setStyle (const char *style) { +void StyleEngine::setStyle (const char *styleAttr) { Node *n = stack->getRef (stack->size () - 1); - assert (n->styleAttribute == NULL); - n->styleAttribute = dStrdup (style); + assert (n->styleAttrProperties == NULL); + // parse style information from style="" attribute, if it exists + if (styleAttr && prefs.parse_embedded_css) + n->styleAttrProperties = + CssParser::parseDeclarationBlock (styleAttr, + strlen (styleAttr)); }; /** - * \brief set properties that were definded using (mostly deprecated) HTML - * attributes (e.g. bgColor). + * \brief Instruct StyleEngine to use the nonCssHints from parent element + * This is only used for tables where nonCssHints on the TABLE-element + * (e.g. border=1) also affect child elements like TD. */ -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 +void StyleEngine::inheritNonCssHints () { + Node *pn = stack->getRef (stack->size () - 2); + Node *n = stack->getRef (stack->size () - 1); + + if (pn->nonCssProperties) + n->nonCssProperties = new CssPropertyList (*pn->nonCssProperties, true); +} + +void StyleEngine::clearNonCssHints () { + Node *n = stack->getRef (stack->size () - 1); + + if (n->nonCssProperties) { + delete n->nonCssProperties; + n->nonCssProperties = NULL; + } } /** @@ -145,6 +176,17 @@ void StyleEngine::inheritBackgroundColor () { stack->getRef (stack->size () - 1)->inheritBackgroundColor = true; } +dw::core::style::Color *StyleEngine::backgroundColor () { + for (int i = 1; i < stack->size (); i++) { + Node *n = stack->getRef (i); + + if (n->style && n->style->backgroundColor) + return n->style->backgroundColor; + } + + return NULL; +} + /** * \brief set the CSS pseudo class :link. */ @@ -165,32 +207,80 @@ void StyleEngine::setPseudoVisited () { * \brief tell the styleEngine that a html element has ended. */ void StyleEngine::endElement (int element) { - assert (stack->size () > 0); assert (element == doctree->top ()->element); Node *n = stack->getRef (stack->size () - 1); + if (n->styleAttrProperties) + delete n->styleAttrProperties; + if (n->nonCssProperties) + delete n->nonCssProperties; if (n->style) n->style->unref (); if (n->wordStyle) n->wordStyle->unref (); - if (n->styleAttribute) - dFree ((void*) n->styleAttribute); + if (n->backgroundStyle) + n->backgroundStyle->unref (); doctree->pop (); stack->setSize (stack->size () - 1); } +void StyleEngine::preprocessAttrs (dw::core::style::StyleAttrs *attrs) { + /* workaround for styling of inline elements */ + if (stack->getRef (stack->size () - 2)->inheritBackgroundColor) { + attrs->backgroundColor = + stack->getRef (stack->size () - 2)->style->backgroundColor; + + attrs->valign = stack->getRef (stack->size () - 2)->style->valign; + } + attrs->borderColor.top = (Color *) -1; + attrs->borderColor.bottom = (Color *) -1; + attrs->borderColor.left = (Color *) -1; + attrs->borderColor.right = (Color *) -1; + /* initial value of border-width is 'medium' */ + attrs->borderWidth.top = 2; + attrs->borderWidth.bottom = 2; + attrs->borderWidth.left = 2; + attrs->borderWidth.right = 2; +} + +void StyleEngine::postprocessAttrs (dw::core::style::StyleAttrs *attrs) { + /* if border-color is not specified, use color as computed value */ + if (attrs->borderColor.top == (Color *) -1) + attrs->borderColor.top = attrs->color; + if (attrs->borderColor.bottom == (Color *) -1) + attrs->borderColor.bottom = attrs->color; + if (attrs->borderColor.left == (Color *) -1) + attrs->borderColor.left = attrs->color; + if (attrs->borderColor.right == (Color *) -1) + attrs->borderColor.right = attrs->color; + /* computed value of border-width is 0 if border-style + is 'none' or 'hidden' */ + if (attrs->borderStyle.top == BORDER_NONE || + attrs->borderStyle.top == BORDER_HIDDEN) + attrs->borderWidth.top = 0; + if (attrs->borderStyle.bottom == BORDER_NONE || + attrs->borderStyle.bottom == BORDER_HIDDEN) + attrs->borderWidth.bottom = 0; + if (attrs->borderStyle.left == BORDER_NONE || + attrs->borderStyle.left == BORDER_HIDDEN) + attrs->borderWidth.left = 0; + if (attrs->borderStyle.right == BORDER_NONE || + attrs->borderStyle.right == BORDER_HIDDEN) + attrs->borderWidth.right = 0; +} + /** * \brief Make changes to StyleAttrs attrs according to CssPropertyList props. */ -void StyleEngine::apply (StyleAttrs *attrs, CssPropertyList *props) { +void StyleEngine::apply (int i, StyleAttrs *attrs, CssPropertyList *props) { FontAttrs fontAttrs = *attrs->font; - Font *parentFont = stack->get (stack->size () - 2).style->font; + Font *parentFont = stack->get (i - 1).style->font; char *c, *fontName; int lineHeight; - /* Determine font first so it can be used to resolve relative lenths. */ + /* Determine font first so it can be used to resolve relative lengths. */ for (int i = 0; i < props->size (); i++) { CssProperty *p = props->getRef (i); @@ -233,31 +323,30 @@ void StyleEngine::apply (StyleAttrs *attrs, CssPropertyList *props) { if (p->type == CSS_TYPE_ENUM) { switch (p->value.intVal) { case CSS_FONT_SIZE_XX_SMALL: - fontAttrs.size = (int) (11.0 * prefs.font_factor + 0.5); + fontAttrs.size = roundInt(11.0 * prefs.font_factor); break; case CSS_FONT_SIZE_X_SMALL: - fontAttrs.size = (int) (12.0 * prefs.font_factor + 0.5); + fontAttrs.size = roundInt(12.0 * prefs.font_factor); break; case CSS_FONT_SIZE_SMALL: - fontAttrs.size = (int) (13.0 * prefs.font_factor + 0.5); + fontAttrs.size = roundInt(13.0 * prefs.font_factor); break; case CSS_FONT_SIZE_MEDIUM: - fontAttrs.size = (int) (14.0 * prefs.font_factor + 0.5); + fontAttrs.size = roundInt(14.0 * prefs.font_factor); break; case CSS_FONT_SIZE_LARGE: - fontAttrs.size = (int) (15.0 * prefs.font_factor + 0.5); break; case CSS_FONT_SIZE_X_LARGE: - fontAttrs.size = (int) (16.0 * prefs.font_factor + 0.5); + fontAttrs.size = roundInt(16.0 * prefs.font_factor); break; case CSS_FONT_SIZE_XX_LARGE: - fontAttrs.size = (int) (17.0 * prefs.font_factor + 0.5); + fontAttrs.size = roundInt(17.0 * prefs.font_factor); break; case CSS_FONT_SIZE_SMALLER: - fontAttrs.size -= (int) (1.0 * prefs.font_factor + 0.5); + fontAttrs.size -= roundInt(1.0 * prefs.font_factor); break; case CSS_FONT_SIZE_LARGER: - fontAttrs.size += (int) (1.0 * prefs.font_factor + 0.5); + fontAttrs.size += roundInt(1.0 * prefs.font_factor); break; default: assert(false); // invalid font-size enum @@ -327,6 +416,9 @@ void StyleEngine::apply (StyleAttrs *attrs, CssPropertyList *props) { else if (fontAttrs.letterSpacing < -1000) fontAttrs.letterSpacing = -1000; break; + case CSS_PROPERTY_FONT_VARIANT: + fontAttrs.fontVariant = (FontVariant) p->value.intVal; + break; default: break; } @@ -346,21 +438,24 @@ void StyleEngine::apply (StyleAttrs *attrs, CssPropertyList *props) { //attrs->backgroundColor = Color::create(layout, 0xdcd1ba); attrs->backgroundColor = Color::create(layout, 0xe0e0a3); break; + case CSS_PROPERTY_BORDER_COLLAPSE: + attrs->borderCollapse = (BorderCollapse) p->value.intVal; + break; case CSS_PROPERTY_BORDER_TOP_COLOR: - attrs->borderColor.top = - Color::create (layout, p->value.intVal); + attrs->borderColor.top = (p->type == CSS_TYPE_ENUM) ? NULL : + Color::create (layout, p->value.intVal); break; case CSS_PROPERTY_BORDER_BOTTOM_COLOR: - attrs->borderColor.bottom = - Color::create (layout, p->value.intVal); + attrs->borderColor.bottom = (p->type == CSS_TYPE_ENUM) ? NULL : + Color::create (layout, p->value.intVal); break; case CSS_PROPERTY_BORDER_LEFT_COLOR: - attrs->borderColor.left = - Color::create (layout, p->value.intVal); + attrs->borderColor.left = (p->type == CSS_TYPE_ENUM) ? NULL : + Color::create (layout, p->value.intVal); break; case CSS_PROPERTY_BORDER_RIGHT_COLOR: - attrs->borderColor.right = - Color::create (layout, p->value.intVal); + attrs->borderColor.right = (p->type == CSS_TYPE_ENUM) ? NULL : + Color::create (layout, p->value.intVal); break; case CSS_PROPERTY_BORDER_BOTTOM_STYLE: attrs->borderStyle.bottom = (BorderStyle) p->value.intVal; @@ -409,9 +504,8 @@ void StyleEngine::apply (StyleAttrs *attrs, CssPropertyList *props) { if (CSS_LENGTH_TYPE (p->value.intVal) == CSS_LENGTH_TYPE_NONE) { attrs->lineHeight = createPerLength(CSS_LENGTH_VALUE(p->value.intVal)); - } else { - computeValue (&lineHeight, p->value.intVal, attrs->font, - attrs->font->size); + } else if (computeValue (&lineHeight, p->value.intVal, + attrs->font, attrs->font->size)) { attrs->lineHeight = createAbsLength(lineHeight); } } @@ -460,6 +554,9 @@ void StyleEngine::apply (StyleAttrs *attrs, CssPropertyList *props) { case CSS_PROPERTY_TEXT_DECORATION: attrs->textDecoration |= p->value.intVal; break; + case CSS_PROPERTY_TEXT_INDENT: + computeLength (&attrs->textIndent, p->value.intVal, attrs->font); + break; case CSS_PROPERTY_VERTICAL_ALIGN: attrs->valign = (VAlignType) p->value.intVal; break; @@ -501,16 +598,6 @@ void StyleEngine::apply (StyleAttrs *attrs, CssPropertyList *props) { } } - /* 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; - } /** @@ -527,14 +614,21 @@ bool StyleEngine::computeValue (int *dest, CssLength value, Font *font) { *dest = (int) CSS_LENGTH_VALUE (value); return true; case CSS_LENGTH_TYPE_MM: - *dest = (int) (CSS_LENGTH_VALUE (value) * dpmm + 0.5); - return true; + *dest = roundInt (CSS_LENGTH_VALUE (value) * dpmm); + return true; case CSS_LENGTH_TYPE_EM: - *dest = (int) (CSS_LENGTH_VALUE (value) * font->size + 0.5); - return true; + *dest = roundInt (CSS_LENGTH_VALUE (value) * font->size); + return true; case CSS_LENGTH_TYPE_EX: - *dest = (int) (CSS_LENGTH_VALUE(value) * font->xHeight + 0.5); - return true; + *dest = roundInt (CSS_LENGTH_VALUE(value) * font->xHeight); + return true; + case CSS_LENGTH_TYPE_NONE: + // length values other than 0 without unit are only allowed + // in special cases (line-height) and have to be handled + // separately. + assert ((int) CSS_LENGTH_VALUE (value) == 0); + *dest = 0; + return true; default: break; } @@ -545,7 +639,7 @@ bool StyleEngine::computeValue (int *dest, CssLength value, Font *font) { 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); + *dest = roundInt (CSS_LENGTH_VALUE (value) * percentageBase); return true; } else return computeValue (dest, value, font); @@ -596,13 +690,17 @@ void StyleEngine::computeBorderWidth (int *dest, CssProperty *p, * background. This method ensures that backgroundColor is set. */ Style * StyleEngine::backgroundStyle () { - StyleAttrs attrs = *style (); + if (!stack->getRef (stack->size () - 1)->backgroundStyle) { + StyleAttrs attrs = *style (); - for (int i = stack->size () - 1; i >= 0 && ! attrs.backgroundColor; i--) - attrs.backgroundColor = stack->getRef (i)->style->backgroundColor; + for (int i = stack->size () - 1; i >= 0 && ! attrs.backgroundColor; i--) + attrs.backgroundColor = stack->getRef (i)->style->backgroundColor; - assert (attrs.backgroundColor); - return Style::create (layout, &attrs); + assert (attrs.backgroundColor); + stack->getRef (stack->size () - 1)->backgroundStyle = + Style::create (layout, &attrs); + } + return stack->getRef (stack->size () - 1)->backgroundStyle; } /** @@ -610,56 +708,45 @@ Style * StyleEngine::backgroundStyle () { * 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, *styleAttributeProps = NULL; - const char *styleAttribute = - stack->getRef (stack->size () - 1)->styleAttribute; +Style * StyleEngine::style0 (int i) { + CssPropertyList props, *styleAttrProperties, *nonCssProperties; // get previous style from the stack - StyleAttrs attrs = *stack->getRef (stack->size () - 2)->style; + StyleAttrs attrs = *stack->getRef (i - 1)->style; // Ensure that StyleEngine::style0() has not been called before for // this element. // Style computation is expensive so limit it as much as possible. // If this assertion is hit, you need to rearrange the code that is - // doing styleEngine calls to call setNonCssHints() before calling + // doing styleEngine calls to call setNonCssHint() before calling // style() or wordStyle() for each new element. - assert (stack->getRef (stack->size () - 1)->style == NULL); + assert (stack->getRef (i)->style == NULL); // reset values that are not inherited according to CSS attrs.resetValues (); + preprocessAttrs (&attrs); - if (stack->getRef (stack->size () - 2)->inheritBackgroundColor) { - attrs.backgroundColor = - stack->getRef (stack->size () - 2)->style->backgroundColor; - - attrs.valign = stack->getRef (stack->size () - 2)->style->valign; - } - - // parse style information from style="" attribute, if it exists - if (styleAttribute && prefs.parse_embedded_css) - styleAttributeProps = - CssParser::parseDeclarationBlock (styleAttribute, - strlen (styleAttribute)); + styleAttrProperties = stack->getRef (i)->styleAttrProperties; + nonCssProperties = stack->getRef (i)->nonCssProperties; // merge style information - cssContext->apply (&props, doctree, styleAttributeProps, nonCssProperties); + cssContext->apply (&props, doctree, stack->getRef(i)->doctreeNode, + styleAttrProperties, nonCssProperties); // apply style - apply (&attrs, &props); + apply (i, &attrs, &props); - stack->getRef (stack->size () - 1)->style = Style::create (layout, &attrs); + postprocessAttrs (&attrs); - if (styleAttributeProps) - delete styleAttributeProps; + stack->getRef (i)->style = Style::create (layout, &attrs); - return stack->getRef (stack->size () - 1)->style; + return stack->getRef (i)->style; } -Style * StyleEngine::wordStyle0 (CssPropertyList *nonCssProperties) { +Style * StyleEngine::wordStyle0 () { StyleAttrs attrs = *style (); attrs.resetValues (); - if (stack->getRef (stack->size () - 1)->inheritBackgroundColor) + if (stack->getRef (stack->size() - 1)->inheritBackgroundColor) attrs.backgroundColor = style ()->backgroundColor; attrs.valign = style ()->valign; @@ -668,6 +755,33 @@ Style * StyleEngine::wordStyle0 (CssPropertyList *nonCssProperties) { return stack->getRef (stack->size () - 1)->wordStyle; } +/** + * \brief Recompute all style information from scratch + * This is used to take into account CSS styles for the HTML-element. + * The CSS data is only completely available after parsing the HEAD-section + * and thereby after the HTML-element has been opened. + * Note that restyle() does not change any styles in the widget tree. + */ +void StyleEngine::restyle () { + for (int i = 1; i < stack->size (); i++) { + Node *n = stack->getRef (i); + if (n->style) { + n->style->unref (); + n->style = NULL; + } + if (n->wordStyle) { + n->wordStyle->unref (); + n->wordStyle = NULL; + } + if (n->backgroundStyle) { + n->backgroundStyle->unref (); + n->backgroundStyle = NULL; + } + + style0 (i); + } +} + void StyleEngine::parse (DilloHtml *html, DilloUrl *url, const char *buf, int buflen, CssOrigin origin) { if (importDepth > 10) { // avoid looping with recursive @import directives diff --git a/src/styleengine.hh b/src/styleengine.hh index 66f28cee..e37aeed1 100644 --- a/src/styleengine.hh +++ b/src/styleengine.hh @@ -19,12 +19,14 @@ class StyleEngine; */ class StyleEngine { private: - class Node { - public: - dw::core::style::Style *style; - dw::core::style::Style *wordStyle; - const char *styleAttribute; - bool inheritBackgroundColor; + struct Node { + CssPropertyList *styleAttrProperties; + CssPropertyList *nonCssProperties; + dw::core::style::Style *style; + dw::core::style::Style *wordStyle; + dw::core::style::Style *backgroundStyle; + bool inheritBackgroundColor; + DoctreeNode *doctreeNode; }; dw::core::Layout *layout; @@ -33,9 +35,19 @@ class StyleEngine { Doctree *doctree; int importDepth; - 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); + dw::core::style::Style *style0 (int i); + dw::core::style::Style *wordStyle0 (); + inline void setNonCssHint(CssPropertyName name, CssValueType type, + CssPropertyValue value) { + Node *n = stack->getRef (stack->size () - 1); + + if (!n->nonCssProperties) + n->nonCssProperties = new CssPropertyList (true); + n->nonCssProperties->set(name, type, value); + } + void preprocessAttrs (dw::core::style::StyleAttrs *attrs); + void postprocessAttrs (dw::core::style::StyleAttrs *attrs); + void apply (int i, dw::core::style::StyleAttrs *attrs, CssPropertyList *props); bool computeValue (int *dest, CssLength value, dw::core::style::Font *font); bool computeValue (int *dest, CssLength value, @@ -60,16 +72,31 @@ class StyleEngine { void endElement (int tag); void setPseudoLink (); void setPseudoVisited (); - void setNonCssHints (CssPropertyList *nonCssHints); + inline void setNonCssHint(CssPropertyName name, CssValueType type, + int value) { + CssPropertyValue v; + v.intVal = value; + setNonCssHint (name, type, v); + } + inline void setNonCssHint(CssPropertyName name, CssValueType type, + const char *value) { + CssPropertyValue v; + v.strVal = dStrdup(value); + setNonCssHint (name, type, v); + } + void inheritNonCssHints (); + void clearNonCssHints (); + void restyle (); void inheritBackgroundColor (); /* \todo get rid of this somehow */ dw::core::style::Style *backgroundStyle (); + dw::core::style::Color *backgroundColor (); inline dw::core::style::Style *style () { dw::core::style::Style *s = stack->getRef (stack->size () - 1)->style; if (s) return s; else - return style0 (); + return style0 (stack->size () - 1); }; inline dw::core::style::Style *wordStyle () { diff --git a/src/table.cc b/src/table.cc index 43304206..58cdf22e 100644 --- a/src/table.cc +++ b/src/table.cc @@ -38,7 +38,6 @@ static void Html_tag_open_table_cell(DilloHtml *html, void Html_tag_open_table(DilloHtml *html, const char *tag, int tagsize) { dw::core::Widget *table; - CssPropertyList props, *table_cell_props; const char *attrbuf; int32_t border = -1, cellspacing = -1, cellpadding = -1, bgcolor = -1; CssLength cssLength; @@ -52,81 +51,95 @@ void Html_tag_open_table(DilloHtml *html, const char *tag, int tagsize) if (border != -1) { cssLength = CSS_CREATE_LENGTH (border, CSS_LENGTH_TYPE_PX); - props.set (CSS_PROPERTY_BORDER_TOP_WIDTH, CSS_TYPE_LENGTH_PERCENTAGE, - cssLength); - props.set (CSS_PROPERTY_BORDER_BOTTOM_WIDTH, CSS_TYPE_LENGTH_PERCENTAGE, - cssLength); - props.set (CSS_PROPERTY_BORDER_LEFT_WIDTH, CSS_TYPE_LENGTH_PERCENTAGE, - cssLength); - props.set (CSS_PROPERTY_BORDER_RIGHT_WIDTH, CSS_TYPE_LENGTH_PERCENTAGE, - cssLength); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_TOP_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, cssLength); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_BOTTOM_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, cssLength); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_LEFT_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, cssLength); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_RIGHT_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, cssLength); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_TOP_STYLE, + CSS_TYPE_ENUM, BORDER_OUTSET); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_BOTTOM_STYLE, + CSS_TYPE_ENUM, BORDER_OUTSET); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_LEFT_STYLE, + CSS_TYPE_ENUM, BORDER_OUTSET); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_RIGHT_STYLE, + CSS_TYPE_ENUM, BORDER_OUTSET); } if (cellspacing != -1) { cssLength = CSS_CREATE_LENGTH (cellspacing, CSS_LENGTH_TYPE_PX); - props.set (CSS_PROPERTY_BORDER_SPACING, CSS_TYPE_LENGTH_PERCENTAGE, - cssLength); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_SPACING, + CSS_TYPE_LENGTH_PERCENTAGE, cssLength); } if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "width"))) - props.set (CSS_PROPERTY_WIDTH, CSS_TYPE_LENGTH_PERCENTAGE, - a_Html_parse_length (html, attrbuf)); + html->styleEngine->setNonCssHint (CSS_PROPERTY_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, + a_Html_parse_length (html, attrbuf)); if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "align"))) { if (dStrcasecmp (attrbuf, "left") == 0) - props.set (CSS_PROPERTY_TEXT_ALIGN, CSS_TYPE_ENUM, TEXT_ALIGN_LEFT); + html->styleEngine->setNonCssHint (CSS_PROPERTY_TEXT_ALIGN, + CSS_TYPE_ENUM, TEXT_ALIGN_LEFT); else if (dStrcasecmp (attrbuf, "right") == 0) - props.set (CSS_PROPERTY_TEXT_ALIGN, CSS_TYPE_ENUM, TEXT_ALIGN_RIGHT); + html->styleEngine->setNonCssHint (CSS_PROPERTY_TEXT_ALIGN, + CSS_TYPE_ENUM, TEXT_ALIGN_RIGHT); else if (dStrcasecmp (attrbuf, "center") == 0) - props.set (CSS_PROPERTY_TEXT_ALIGN, CSS_TYPE_ENUM, TEXT_ALIGN_CENTER); + html->styleEngine->setNonCssHint (CSS_PROPERTY_TEXT_ALIGN, + CSS_TYPE_ENUM, TEXT_ALIGN_CENTER); } if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "bgcolor"))) { bgcolor = a_Html_color_parse(html, attrbuf, -1); if (bgcolor != -1) - props.set (CSS_PROPERTY_BACKGROUND_COLOR, CSS_TYPE_COLOR, bgcolor); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BACKGROUND_COLOR, + CSS_TYPE_COLOR, bgcolor); } - html->styleEngine->setNonCssHints (&props); - HT2TB(html)->addParbreak (0, html->styleEngine->wordStyle ()); /* The style for the cells */ - table_cell_props = new CssPropertyList (); + html->styleEngine->clearNonCssHints (); if (border > 0) { cssLength = CSS_CREATE_LENGTH (1, CSS_LENGTH_TYPE_PX); - table_cell_props->set (CSS_PROPERTY_BORDER_TOP_WIDTH, - CSS_TYPE_LENGTH_PERCENTAGE, cssLength); - table_cell_props->set (CSS_PROPERTY_BORDER_BOTTOM_WIDTH, - CSS_TYPE_LENGTH_PERCENTAGE, cssLength); - table_cell_props->set (CSS_PROPERTY_BORDER_LEFT_WIDTH, - CSS_TYPE_LENGTH_PERCENTAGE, cssLength); - table_cell_props->set (CSS_PROPERTY_BORDER_RIGHT_WIDTH, - CSS_TYPE_LENGTH_PERCENTAGE, cssLength); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_TOP_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, cssLength); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_BOTTOM_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, cssLength); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_LEFT_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, cssLength); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_RIGHT_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, cssLength); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_TOP_STYLE, + CSS_TYPE_ENUM, BORDER_INSET); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_BOTTOM_STYLE, + CSS_TYPE_ENUM, BORDER_INSET); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_LEFT_STYLE, + CSS_TYPE_ENUM, BORDER_INSET); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_RIGHT_STYLE, + CSS_TYPE_ENUM, BORDER_INSET); } if (cellpadding != -1) { cssLength = CSS_CREATE_LENGTH (cellpadding, CSS_LENGTH_TYPE_PX); - table_cell_props->set (CSS_PROPERTY_PADDING_TOP, - CSS_TYPE_LENGTH_PERCENTAGE, cssLength); - table_cell_props->set (CSS_PROPERTY_PADDING_BOTTOM, - CSS_TYPE_LENGTH_PERCENTAGE, cssLength); - table_cell_props->set (CSS_PROPERTY_PADDING_LEFT, - CSS_TYPE_LENGTH_PERCENTAGE, cssLength); - table_cell_props->set (CSS_PROPERTY_PADDING_RIGHT, - CSS_TYPE_LENGTH_PERCENTAGE, cssLength); + html->styleEngine->setNonCssHint (CSS_PROPERTY_PADDING_TOP, + CSS_TYPE_LENGTH_PERCENTAGE, cssLength); + html->styleEngine->setNonCssHint (CSS_PROPERTY_PADDING_BOTTOM, + CSS_TYPE_LENGTH_PERCENTAGE, cssLength); + html->styleEngine->setNonCssHint (CSS_PROPERTY_PADDING_LEFT, + CSS_TYPE_LENGTH_PERCENTAGE, cssLength); + html->styleEngine->setNonCssHint (CSS_PROPERTY_PADDING_RIGHT, + CSS_TYPE_LENGTH_PERCENTAGE, 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); HT2TB(html)->addWidget (table, html->styleEngine->style ()); S_TOP(html)->table_mode = DILLO_HTML_TABLE_MODE_TOP; + S_TOP(html)->table_border_mode = DILLO_HTML_TABLE_BORDER_SEPARATE; S_TOP(html)->cell_text_align_set = FALSE; S_TOP(html)->table = table; } @@ -139,7 +152,8 @@ void Html_tag_open_tr(DilloHtml *html, const char *tag, int tagsize) const char *attrbuf; int32_t bgcolor = -1; bool new_style = false; - CssPropertyList props, *table_cell_props; + + html->styleEngine->inheritNonCssHints (); switch (S_TOP(html)->table_mode) { case DILLO_HTML_TABLE_MODE_NONE: @@ -153,34 +167,26 @@ void Html_tag_open_tr(DilloHtml *html, const char *tag, int tagsize) if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "bgcolor"))) { bgcolor = a_Html_color_parse(html, attrbuf, -1); if (bgcolor != -1) - props.set (CSS_PROPERTY_BACKGROUND_COLOR, CSS_TYPE_COLOR, bgcolor); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BACKGROUND_COLOR, + CSS_TYPE_COLOR, bgcolor); } if (a_Html_get_attr (html, tag, tagsize, "align")) { S_TOP(html)->cell_text_align_set = TRUE; - a_Html_tag_set_align_attr (html, &props, tag, tagsize); + a_Html_tag_set_align_attr (html, tag, tagsize); } html->styleEngine->inheritBackgroundColor (); - html->styleEngine->setNonCssHints (&props); ((dw::Table*)S_TOP(html)->table)->addRow (html->styleEngine->style ()); - table_cell_props = new CssPropertyList (*S_TOP(html)->table_cell_props); if (bgcolor != -1) { - table_cell_props->set (CSS_PROPERTY_BACKGROUND_COLOR, - CSS_TYPE_COLOR, bgcolor); + html->styleEngine->setNonCssHint(CSS_PROPERTY_BACKGROUND_COLOR, + CSS_TYPE_COLOR, bgcolor); new_style = true; } - if (a_Html_tag_set_valign_attr (html, tag, tagsize, table_cell_props)) + if (a_Html_tag_set_valign_attr (html, tag, tagsize)) new_style = true; - if (new_style) { - 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: break; @@ -212,6 +218,96 @@ void Html_tag_open_th(DilloHtml *html, const char *tag, int tagsize) */ /* + * The table border model is stored in the table's stack item + */ +static int Html_table_get_border_model(DilloHtml *html) +{ + static int i_TABLE = -1; + if (i_TABLE == -1) + i_TABLE = a_Html_tag_index("table"); + + int s_idx = html->stack->size(); + while (--s_idx > 0 && html->stack->getRef(s_idx)->tag_idx != i_TABLE) + ; + return html->stack->getRef(s_idx)->table_border_mode; +} + +/* + * Set current table's border model + */ +static void Html_table_set_border_model(DilloHtml *html, + DilloHtmlTableBorderMode mode) +{ + int s_idx = html->stack->size(), i_TABLE = a_Html_tag_index("table"); + + while (--s_idx > 0 && html->stack->getRef(s_idx)->tag_idx != i_TABLE) ; + if (s_idx > 0) + html->stack->getRef(s_idx)->table_border_mode = mode; +} + +/* WORKAROUND: collapsing border model requires moving rendering code from + * the cell to the table, and making table-code aware of each + * cell style. + * This workaround mimics collapsing model within separate model. This is not + * a complete emulation but should be enough for most cases. + */ +static void Html_set_collapsing_border_model(DilloHtml *html, Widget *col_tb) +{ + dw::core::style::Style *collapseStyle, *tableStyle; + dw::core::style::StyleAttrs collapseCellAttrs, collapseTableAttrs; + int borderWidth, marginWidth; + + tableStyle = ((dw::Table*)S_TOP(html)->table)->getStyle (); + borderWidth = html->styleEngine->style ()->borderWidth.top; + marginWidth = tableStyle->margin.top; + + collapseCellAttrs = *(html->styleEngine->style ()); + collapseCellAttrs.margin.setVal (0); + collapseCellAttrs.borderWidth.left = 0; + collapseCellAttrs.borderWidth.top = 0; + collapseCellAttrs.borderWidth.right = borderWidth; + collapseCellAttrs.borderWidth.bottom = borderWidth; + collapseCellAttrs.hBorderSpacing = 0; + collapseCellAttrs.vBorderSpacing = 0; + collapseStyle = Style::create(HT2LT(html), &collapseCellAttrs); + col_tb->setStyle (collapseStyle); + + if (Html_table_get_border_model(html) != DILLO_HTML_TABLE_BORDER_COLLAPSE) { + Html_table_set_border_model(html, DILLO_HTML_TABLE_BORDER_COLLAPSE); + collapseTableAttrs = *tableStyle; + collapseTableAttrs.margin.setVal (marginWidth); + collapseTableAttrs.borderWidth.left = borderWidth; + collapseTableAttrs.borderWidth.top = borderWidth; + collapseTableAttrs.borderWidth.right = 0; + collapseTableAttrs.borderWidth.bottom = 0; + collapseTableAttrs.hBorderSpacing = 0; + collapseTableAttrs.vBorderSpacing = 0; + collapseTableAttrs.borderColor = collapseCellAttrs.borderColor; + collapseTableAttrs.borderStyle = collapseCellAttrs.borderStyle; + /* CSS2 17.6.2: table does not have padding (in collapsing mode) */ + collapseTableAttrs.padding.setVal (0); + collapseStyle = Style::create(HT2LT(html), &collapseTableAttrs); + ((dw::Table*)S_TOP(html)->table)->setStyle (collapseStyle); + } +} + +/* + * Adjust style for separate border model. + * (Dw uses this model internally). + */ +static void Html_set_separate_border_model(DilloHtml *html, Widget *col_tb) +{ + dw::core::style::Style *separateStyle; + dw::core::style::StyleAttrs separateCellAttrs; + + separateCellAttrs = *(html->styleEngine->style ()); + /* CSS2 17.5: Internal table elements do not have margins */ + separateCellAttrs.margin.setVal (0); + separateStyle = Style::create(HT2LT(html), &separateCellAttrs); + col_tb->setStyle (separateStyle); +} + +/* * used by <TD> and <TH> */ static void Html_tag_open_table_cell(DilloHtml *html, @@ -224,6 +320,8 @@ static void Html_tag_open_table_cell(DilloHtml *html, int32_t bgcolor; bool_t new_style; + html->styleEngine->inheritNonCssHints (); + switch (S_TOP(html)->table_mode) { case DILLO_HTML_TABLE_MODE_NONE: BUG_MSG("<td> or <th> outside <table>\n"); @@ -245,41 +343,36 @@ static void Html_tag_open_table_cell(DilloHtml *html, if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "rowspan"))) rowspan = MAX(1, strtol (attrbuf, NULL, 10)); - 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 (); - /* text style */ if (!S_TOP(html)->cell_text_align_set) { - props->set (CSS_PROPERTY_TEXT_ALIGN, CSS_TYPE_ENUM, text_align); + html->styleEngine->setNonCssHint (CSS_PROPERTY_TEXT_ALIGN, + CSS_TYPE_ENUM, text_align); } if (a_Html_get_attr(html, tag, tagsize, "nowrap")) - props->set(CSS_PROPERTY_WHITE_SPACE,CSS_TYPE_ENUM,WHITE_SPACE_NOWRAP); + html->styleEngine->setNonCssHint(CSS_PROPERTY_WHITE_SPACE, + CSS_TYPE_ENUM, WHITE_SPACE_NOWRAP); else - props->set(CSS_PROPERTY_WHITE_SPACE,CSS_TYPE_ENUM,WHITE_SPACE_NORMAL); + html->styleEngine->setNonCssHint(CSS_PROPERTY_WHITE_SPACE, + CSS_TYPE_ENUM, WHITE_SPACE_NORMAL); - a_Html_tag_set_align_attr (html, props, tag, tagsize); + a_Html_tag_set_align_attr (html, tag, tagsize); if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "width"))) { - props->set (CSS_PROPERTY_WIDTH, CSS_TYPE_LENGTH_PERCENTAGE, - a_Html_parse_length (html, attrbuf)); + html->styleEngine->setNonCssHint (CSS_PROPERTY_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, + a_Html_parse_length (html, attrbuf)); } - if (a_Html_tag_set_valign_attr (html, tag, tagsize, props)) + if (a_Html_tag_set_valign_attr (html, tag, tagsize)) new_style = TRUE; if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "bgcolor"))) { bgcolor = a_Html_color_parse(html, attrbuf, -1); if (bgcolor != -1) - props->set (CSS_PROPERTY_BACKGROUND_COLOR, CSS_TYPE_COLOR,bgcolor); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BACKGROUND_COLOR, + CSS_TYPE_COLOR, bgcolor); } - html->styleEngine->setNonCssHints (props); - delete props; - if (html->styleEngine->style ()->textAlign == TEXT_ALIGN_STRING) col_tb = new dw::TableCell ( @@ -288,7 +381,11 @@ static void Html_tag_open_table_cell(DilloHtml *html, else col_tb = new Textblock (prefs.limit_text_width); - col_tb->setStyle (html->styleEngine->style ()); + if (html->styleEngine->style()->borderCollapse == BORDER_MODEL_COLLAPSE){ + Html_set_collapsing_border_model(html, col_tb); + } else { + Html_set_separate_border_model(html, col_tb); + } ((dw::Table*)S_TOP(html)->table)->addCell (col_tb, colspan, rowspan); S_TOP(html)->textblock = html->dw = col_tb; diff --git a/src/uicmd.cc b/src/uicmd.cc index 93836735..5573db11 100644 --- a/src/uicmd.cc +++ b/src/uicmd.cc @@ -449,6 +449,8 @@ BrowserWindow *a_UIcmd_browser_window_new(int ww, int wh, // Now create the Dw render layout and viewport FltkPlatform *platform = new FltkPlatform (); Layout *layout = new Layout (platform); + style::Color *bgColor = style::Color::create (layout, prefs.bg_color); + layout->setBgColor (bgColor); FltkViewport *viewport = new FltkViewport (0, 0, 1, 1); if (prefs.buffered_drawing == 1) @@ -507,6 +509,8 @@ static BrowserWindow *UIcmd_tab_new(const void *vbw) // Now create the Dw render layout and viewport FltkPlatform *platform = new FltkPlatform (); Layout *layout = new Layout (platform); + style::Color *bgColor = style::Color::create (layout, prefs.bg_color); + layout->setBgColor (bgColor); FltkViewport *viewport = new FltkViewport (0, 0, 1, 1); @@ -1296,14 +1300,14 @@ void a_UIcmd_fullscreen_toggle(BrowserWindow *bw) * Search for next/previous occurrence of key. */ void a_UIcmd_findtext_search(BrowserWindow *bw, const char *key, - int case_sens, int backwards) + int case_sens, int backward) { Layout *l = (Layout *)bw->render_layout; - switch (l->search(key, case_sens, backwards)) { + switch (l->search(key, case_sens, backward)) { case FindtextState::RESTART: - a_UIcmd_set_msg(bw, "No further occurrences of \"%s\". " - "Restarting from the top.", key); + a_UIcmd_set_msg(bw, backward?"Top reached; restarting from the bottom." + :"Bottom reached; restarting from the top."); break; case FindtextState::NOT_FOUND: a_UIcmd_set_msg(bw, "\"%s\" not found.", key); @@ -1,7 +1,6 @@ /* * File: url.c * - * Copyright (C) 2001 Livio Baldini Soares <livio@linux.ime.usp.br> * Copyright (C) 2001-2009 Jorge Arellano Cid <jcid@dillo.org> * * This program is free software; you can redistribute it and/or modify @@ -2,7 +2,6 @@ * File : url.h - Dillo * * Copyright (C) 2001 Jorge Arellano Cid <jcid@dillo.org> - * 2001 Livio Baldini Soares <livio@linux.ime.usp.br> * * Parse and normalize all URL's inside Dillo. */ @@ -61,10 +61,13 @@ int a_Web_dispatch_by_type (const char *Type, DilloWeb *Web, if (Web->flags & WEB_RootUrl) { /* We have RootUrl! */ + style::Color *bgColor = style::Color::create (layout, prefs.bg_color); + Web->bgColor = bgColor->getColor (); + layout->setBgColor (bgColor); + /* Set a style for the widget */ StyleEngine styleEngine (layout); styleEngine.startElement ("body"); - Web->bgColor= styleEngine.backgroundStyle()->backgroundColor->getColor(); dw = (Widget*) a_Mime_set_viewer(Type, Web, Call, Data); if (dw == NULL) @@ -89,12 +92,12 @@ int a_Web_dispatch_by_type (const char *Type, DilloWeb *Web, } else { /* A non-RootUrl. At this moment we only handle image-children */ - if (!dStrncasecmp(Type, "image/", 6)) + if (!dStrncasecmp(Type, "image/", 6)) { dw = (Widget*) a_Mime_set_viewer(Type, Web, Call, Data); - } - - if (!dw) { - MSG_HTTP("unhandled MIME type: \"%s\"\n", Type); + } else { + MSG_HTTP("'%s' cannot be displayed as image; has media type '%s'\n", + URL_STR(Web->url), Type); + } } return (dw ? 1 : -1); } |