diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/css.hh | 12 | ||||
-rw-r--r-- | src/cssparser.cc | 173 | ||||
-rw-r--r-- | src/cssparser.hh | 3 | ||||
-rw-r--r-- | src/dicache.c | 13 | ||||
-rw-r--r-- | src/dillo.cc | 5 | ||||
-rw-r--r-- | src/form.cc | 32 | ||||
-rw-r--r-- | src/html.cc | 156 | ||||
-rw-r--r-- | src/html_common.hh | 16 | ||||
-rw-r--r-- | src/image.cc | 43 | ||||
-rw-r--r-- | src/image.hh | 8 | ||||
-rw-r--r-- | src/imgbuf.cc | 6 | ||||
-rw-r--r-- | src/imgbuf.hh | 2 | ||||
-rw-r--r-- | src/menu.cc | 20 | ||||
-rw-r--r-- | src/plain.cc | 7 | ||||
-rw-r--r-- | src/prefs.c | 1 | ||||
-rw-r--r-- | src/prefs.h | 1 | ||||
-rw-r--r-- | src/prefsparser.cc | 1 | ||||
-rw-r--r-- | src/styleengine.cc | 149 | ||||
-rw-r--r-- | src/styleengine.hh | 30 | ||||
-rw-r--r-- | src/table.cc | 20 | ||||
-rw-r--r-- | src/uicmd.cc | 3 | ||||
-rw-r--r-- | src/web.cc | 8 |
22 files changed, 545 insertions, 164 deletions
@@ -37,6 +37,8 @@ typedef enum { 'margin-*-width'). */ CSS_TYPE_SIGNED_LENGTH, /* As CSS_TYPE_LENGTH but may be negative. */ CSS_TYPE_LENGTH_PERCENTAGE_NUMBER, /* <length> or <percentage>, or <number> */ + CSS_TYPE_AUTO, /* Represented as CssLength of type + CSS_LENGTH_TYPE_AUTO */ CSS_TYPE_COLOR, /* Represented as integer. */ CSS_TYPE_FONT_WEIGHT, /* this very special and only used by 'font-weight' */ @@ -45,6 +47,8 @@ typedef enum { opposed to CSS_TYPE_ENUM and CSS_TYPE_MULTI_ENUM). Used for 'font-family'. */ + CSS_TYPE_URI, /* <uri> */ + CSS_TYPE_BACKGROUND_POSITION, CSS_TYPE_UNUSED /* Not yet used. Will itself get unused some day. */ } CssValueType; @@ -229,9 +233,15 @@ typedef enum { CSS_PROPERTY_LAST } CssPropertyName; +typedef struct { + int32_t posX; + int32_t posY; +} CssBackgroundPosition; + typedef union { int32_t intVal; char *strVal; + CssBackgroundPosition *posVal; } CssPropertyValue; typedef enum { @@ -285,6 +295,8 @@ class CssProperty { case CSS_TYPE_SYMBOL: dFree (value.strVal); break; + case CSS_TYPE_BACKGROUND_POSITION: + dFree (value.posVal); default: break; } diff --git a/src/cssparser.cc b/src/cssparser.cc index 67d8ff54..4ff8f4f7 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_background_attachment_enum_vals[] = { + "scroll", "fixed", NULL +}; + +static const char *const Css_background_repeat_enum_vals[] = { + "repeat", "repeat-x", "repeat-y", "no-repeat", NULL +}; + static const char *const Css_border_collapse_enum_vals[] = { "separate", "collapse", NULL }; @@ -151,11 +159,14 @@ static const char *const Css_word_spacing_enum_vals[] = { }; const CssPropertyInfo Css_property_info[CSS_PROPERTY_LAST] = { - {"background-attachment", {CSS_TYPE_UNUSED}, NULL}, + {"background-attachment", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED}, + Css_background_attachment_enum_vals}, {"background-color", {CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, NULL}, - {"background-image", {CSS_TYPE_UNUSED}, NULL}, - {"background-position", {CSS_TYPE_UNUSED}, NULL}, - {"background-repeat", {CSS_TYPE_UNUSED}, NULL}, + {"background-image", {CSS_TYPE_URI, CSS_TYPE_UNUSED}, NULL}, + {"background-position", {CSS_TYPE_BACKGROUND_POSITION, CSS_TYPE_UNUSED}, + NULL}, + {"background-repeat", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED}, + Css_background_repeat_enum_vals}, {"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}, @@ -206,8 +217,8 @@ const CssPropertyInfo Css_property_info[CSS_PROPERTY_LAST] = { 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}, - {"left", {CSS_TYPE_LENGTH_PERCENTAGE, CSS_TYPE_UNUSED}, NULL}, + {"height", {CSS_TYPE_LENGTH_PERCENTAGE, CSS_TYPE_AUTO, CSS_TYPE_UNUSED}, NULL}, + {"left", {CSS_TYPE_UNUSED}, NULL}, {"letter-spacing", {CSS_TYPE_ENUM, CSS_TYPE_SIGNED_LENGTH, CSS_TYPE_UNUSED}, Css_letter_spacing_enum_vals}, {"line-height", @@ -218,10 +229,14 @@ const CssPropertyInfo Css_property_info[CSS_PROPERTY_LAST] = { Css_list_style_position_enum_vals}, {"list-style-type", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED}, Css_list_style_type_enum_vals}, - {"margin-bottom", {CSS_TYPE_SIGNED_LENGTH, CSS_TYPE_UNUSED}, NULL}, - {"margin-left", {CSS_TYPE_SIGNED_LENGTH, CSS_TYPE_UNUSED}, NULL}, - {"margin-right", {CSS_TYPE_SIGNED_LENGTH, CSS_TYPE_UNUSED}, NULL}, - {"margin-top", {CSS_TYPE_SIGNED_LENGTH, CSS_TYPE_UNUSED}, NULL}, + {"margin-bottom", + {CSS_TYPE_SIGNED_LENGTH, CSS_TYPE_AUTO, CSS_TYPE_UNUSED}, NULL}, + {"margin-left", + {CSS_TYPE_SIGNED_LENGTH, CSS_TYPE_AUTO, CSS_TYPE_UNUSED}, NULL}, + {"margin-right", + {CSS_TYPE_SIGNED_LENGTH, CSS_TYPE_AUTO, CSS_TYPE_UNUSED}, NULL}, + {"margin-top", + {CSS_TYPE_SIGNED_LENGTH, CSS_TYPE_AUTO, CSS_TYPE_UNUSED}, NULL}, {"marker-offset", {CSS_TYPE_UNUSED}, NULL}, {"marks", {CSS_TYPE_UNUSED}, NULL}, {"max-height", {CSS_TYPE_UNUSED}, NULL}, @@ -251,7 +266,7 @@ const CssPropertyInfo Css_property_info[CSS_PROPERTY_LAST] = { {"vertical-align",{CSS_TYPE_ENUM, CSS_TYPE_UNUSED},Css_vertical_align_vals}, {"visibility", {CSS_TYPE_UNUSED}, NULL}, {"white-space", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED}, Css_white_space_vals}, - {"width", {CSS_TYPE_LENGTH_PERCENTAGE, CSS_TYPE_UNUSED}, NULL}, + {"width", {CSS_TYPE_LENGTH_PERCENTAGE, CSS_TYPE_AUTO, CSS_TYPE_UNUSED}, NULL}, {"word-spacing", {CSS_TYPE_ENUM, CSS_TYPE_SIGNED_LENGTH, CSS_TYPE_UNUSED}, Css_word_spacing_enum_vals}, {"z-index", {CSS_TYPE_UNUSED}, NULL}, @@ -706,6 +721,15 @@ bool CssParser::tokenMatchesProperty(CssPropertyName prop, CssValueType *type) } break; + case CSS_TYPE_BACKGROUND_POSITION: + if (ttype == CSS_TK_SYMBOL && + (dStrAsciiCasecmp(tval, "center") == 0 || + dStrAsciiCasecmp(tval, "left") == 0 || + dStrAsciiCasecmp(tval, "right") == 0 || + dStrAsciiCasecmp(tval, "top") == 0 || + dStrAsciiCasecmp(tval, "bottom") == 0)) + return true; + // Fall Through (lenght and percentage) case CSS_TYPE_LENGTH_PERCENTAGE: case CSS_TYPE_LENGTH_PERCENTAGE_NUMBER: case CSS_TYPE_LENGTH: @@ -713,9 +737,12 @@ bool CssParser::tokenMatchesProperty(CssPropertyName prop, CssValueType *type) return false; // Fall Through case CSS_TYPE_SIGNED_LENGTH: - if (ttype == CSS_TK_DECINT || - ttype == CSS_TK_FLOAT || - (ttype == CSS_TK_SYMBOL && dStrAsciiCasecmp(tval, "auto") == 0)) + if (ttype == CSS_TK_DECINT || ttype == CSS_TK_FLOAT) + return true; + break; + + case CSS_TYPE_AUTO: + if (ttype == CSS_TK_SYMBOL && dStrAsciiCasecmp(tval, "auto") == 0) return true; break; @@ -746,6 +773,12 @@ bool CssParser::tokenMatchesProperty(CssPropertyName prop, CssValueType *type) } break; + case CSS_TYPE_URI: + if (ttype == CSS_TK_SYMBOL && + dStrAsciiCasecmp(tval, "url") == 0) + return true; + break; + case CSS_TYPE_UNUSED: case CSS_TYPE_INTEGER: /* Not used for parser values. */ @@ -939,13 +972,16 @@ bool CssParser::parseValue(CssPropertyName prop, ret = true; val->intVal = CSS_CREATE_LENGTH(fval, lentype); - } else if (ttype == CSS_TK_SYMBOL && !dStrAsciiCasecmp(tval, "auto")) { - ret = true; - val->intVal = CSS_LENGTH_TYPE_AUTO; - nextToken(); } break; + case CSS_TYPE_AUTO: + assert (ttype == CSS_TK_SYMBOL && !dStrAsciiCasecmp(tval, "auto")); + ret = true; + val->intVal = CSS_LENGTH_TYPE_AUTO; + nextToken(); + break; + case CSS_TYPE_COLOR: if (ttype == CSS_TK_COLOR) { val->intVal = a_Color_parse(tval, -1, &err); @@ -1016,6 +1052,107 @@ bool CssParser::parseValue(CssPropertyName prop, } break; + case CSS_TYPE_URI: + if (ttype == CSS_TK_SYMBOL && + dStrAsciiCasecmp(tval, "url") == 0) { + val->strVal = parseUrl(); + nextToken(); + if (val->strVal) + ret = true; + } + break; + + case CSS_TYPE_BACKGROUND_POSITION: + // 'background-position' consists of one or two values: vertical and + // horizontal position; in most cases in this order. However, as long it + // is unambigous, the order can be switched: "10px left" and "left 10px" + // are both possible and have the same effect. For this reason, all + // possibilities are tested in parallel. + + bool h[2], v[2]; + int pos[2]; + h[0] = v[0] = h[1] = v[1] = false; + + // First: collect values in pos[0] and pos[1], and determine whether + // they can be used for a horizontal (h[i]) or vertical (v[i]) position + // (or both). When neither h[i] or v[i] is set, pos[i] is undefined. + for (i = 0; i < 2; i++) { + CssValueType typeTmp; + // tokenMatchesProperty will, for CSS_PROPERTY_BACKGROUND_POSITION, + // work on both parts, since they are exchangable. + if (tokenMatchesProperty (CSS_PROPERTY_BACKGROUND_POSITION, + &typeTmp)) { + h[i] = ttype != CSS_TK_SYMBOL || + (dStrAsciiCasecmp(tval, "top") != 0 && + dStrAsciiCasecmp(tval, "bottom") != 0); + v[i] = ttype != CSS_TK_SYMBOL || + (dStrAsciiCasecmp(tval, "left") != 0 && + dStrAsciiCasecmp(tval, "right") != 0); + } else + // No match. + h[i] = v[i] = false; + + if (h[i] || v[i]) { + // Calculate values. + if (ttype == CSS_TK_SYMBOL) { + if (dStrAsciiCasecmp(tval, "top") == 0 || + dStrAsciiCasecmp(tval, "left") == 0) { + pos[i] = CSS_CREATE_LENGTH (0.0, CSS_LENGTH_TYPE_PERCENTAGE); + nextToken(); + } else if (dStrAsciiCasecmp(tval, "center") == 0) { + pos[i] = CSS_CREATE_LENGTH (0.5, CSS_LENGTH_TYPE_PERCENTAGE); + nextToken(); + } else if (dStrAsciiCasecmp(tval, "bottom") == 0 || + dStrAsciiCasecmp(tval, "right") == 0) { + pos[i] = CSS_CREATE_LENGTH (1.0, CSS_LENGTH_TYPE_PERCENTAGE); + nextToken(); + } else + // tokenMatchesProperty should have returned "false" already. + lout::misc::assertNotReached (); + } else { + // We can assume <length> or <percentage> here ... + CssPropertyValue valTmp; + if (parseValue(prop, CSS_TYPE_LENGTH_PERCENTAGE, &valTmp)) { + pos[i] = valTmp.intVal; + ret = true; + } else + // ... but something may still fail. + h[i] = v[i] = false; + } + } + + // If the first value cannot be read, do not read the second. + if (!h[i] && !v[i]) + break; + } + + // Second: Create the final value. Order will be determined here. + if (v[0] || h[0]) { + // If second value is not set, it is set to "center", i. e. 50%, (see + // CSS specification), which is suitable for both dimensions. + if (!h[1] && !v[1]) { + pos[1] = CSS_CREATE_LENGTH (0.5, CSS_LENGTH_TYPE_PERCENTAGE); + h[1] = v[1] = true; + } + + // Only valid, when a combination h/v or v/h is possible. + if ((h[0] && v[1]) || (v[0] && h[1])) { + ret = true; + val->posVal = dNew(CssBackgroundPosition, 1); + + // Prefer combination h/v: + if (h[0] && v[1]) { + val->posVal->posX = pos[0]; + val->posVal->posY = pos[1]; + } else { + // This should be v/h: + val->posVal->posX = pos[1]; + val->posVal->posY = pos[0]; + } + } + } + break; + case CSS_TYPE_UNUSED: /* nothing */ break; diff --git a/src/cssparser.hh b/src/cssparser.hh index 8609877b..30d02eee 100644 --- a/src/cssparser.hh +++ b/src/cssparser.hh @@ -2,7 +2,8 @@ #define __CSSPARSER_HH__ #include "css.hh" -#include "html_common.hh" + +class DilloHtml; class CssParser { private: diff --git a/src/dicache.c b/src/dicache.c index 55232846..db3b86b2 100644 --- a/src/dicache.c +++ b/src/dicache.c @@ -276,7 +276,8 @@ void a_Dicache_set_parms(DilloUrl *url, int version, DilloImage *Image, /* BUG: there's just one image-type now */ #define I_RGB 0 - DicEntry->v_imgbuf = a_Imgbuf_new(Image->dw, I_RGB, width, height, gamma); + DicEntry->v_imgbuf = + a_Imgbuf_new(Image->layout, I_RGB, width, height, gamma); DicEntry->TotalSize = width * height * 3; DicEntry->width = width; @@ -402,7 +403,8 @@ static void *Dicache_image(int ImgType, const char *MimeType, void *Ptr, dReturn_val_if_fail(MimeType && Ptr, NULL); if (!web->Image) { - web->Image = a_Image_new(NULL, web->bgColor); + web->Image = + a_Image_new_with_dw(web->bw->render_layout, NULL, web->bgColor); a_Image_ref(web->Image); } @@ -429,7 +431,7 @@ static void *Dicache_image(int ImgType, const char *MimeType, void *Ptr, *Data = DicEntry->DecoderData; *Call = (CA_Callback_t) a_Dicache_callback; - return (web->Image->dw); + return (a_Image_get_dw (web->Image)); } /* @@ -516,9 +518,12 @@ void a_Dicache_callback(int Op, CacheClient_t *Client) Image->ScanNumber = DicEntry->ScanNumber; } } - } else if (Op == CA_Close || Op == CA_Abort) { + } else if (Op == CA_Close) { a_Image_close(Image); a_Bw_close_client(Web->bw, Client->Key); + } else if (Op == CA_Abort) { + a_Image_abort(Image); + a_Bw_close_client(Web->bw, Client->Key); } } diff --git a/src/dillo.cc b/src/dillo.cc index e519d4df..2b9f1645 100644 --- a/src/dillo.cc +++ b/src/dillo.cc @@ -53,6 +53,7 @@ #include "domain.h" #include "auth.h" +#include "lout/debug.hh" #include "dw/fltkcore.hh" #include "dw/textblock.hh" @@ -375,6 +376,10 @@ static DilloUrl *makeStartUrl(char *str, bool local) */ int main(int argc, char **argv) { + DBG_OBJ_COLOR("#c0ff80", "dw::*"); + DBG_OBJ_COLOR("#c0c0ff", "dw::fltk::*"); + DBG_OBJ_COLOR("#ffa0a0", "dw::core::*"); + uint_t opt_id; uint_t options_got = 0; uint32_t xid = 0; diff --git a/src/form.cc b/src/form.cc index 8476b73b..c5bb10af 100644 --- a/src/form.cc +++ b/src/form.cc @@ -340,7 +340,7 @@ void Html_tag_open_form(DilloHtml *html, const char *tag, int tagsize) char *charset, *first; const char *attrbuf; - HT2TB(html)->addParbreak (9, html->styleEngine->wordStyle ()); + HT2TB(html)->addParbreak (9, html->wordStyle ()); if (html->InFlags & IN_FORM) { BUG_MSG("nested forms\n"); @@ -567,7 +567,7 @@ void Html_tag_open_input(DilloHtml *html, const char *tag, int tagsize) html->styleEngine->setNonCssHint (PROPERTY_X_TOOLTIP, CSS_TYPE_STRING, attrbuf); } - HT2TB(html)->addWidget (embed, html->styleEngine->backgroundStyle()); + HT2TB(html)->addWidget (embed, html->backgroundStyle()); } dFree(type); dFree(name); @@ -600,17 +600,17 @@ void Html_tag_open_isindex(DilloHtml *html, const char *tag, int tagsize) html->charset); html->InFlags |= IN_FORM; - HT2TB(html)->addParbreak (9, html->styleEngine->wordStyle ()); + HT2TB(html)->addParbreak (9, html->wordStyle ()); if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "prompt"))) - HT2TB(html)->addText(attrbuf, html->styleEngine->wordStyle ()); + HT2TB(html)->addText(attrbuf, html->wordStyle ()); ResourceFactory *factory = HT2LT(html)->getResourceFactory(); EntryResource *entryResource = factory->createEntryResource (20,false,NULL); embed = new Embed (entryResource); Html_add_input(html, DILLO_HTML_INPUT_INDEX, embed, NULL, NULL, FALSE); - HT2TB(html)->addWidget (embed, html->styleEngine->backgroundStyle ()); + HT2TB(html)->addWidget (embed, html->backgroundStyle ()); a_Url_free(action); html->InFlags &= ~IN_FORM; @@ -675,7 +675,7 @@ void Html_tag_content_textarea(DilloHtml *html, const char *tag, int tagsize) textres->setEditable(false); Html_add_input(html, DILLO_HTML_INPUT_TEXTAREA, embed, name, NULL, false); - HT2TB(html)->addWidget (embed, html->styleEngine->backgroundStyle ()); + HT2TB(html)->addWidget (embed, html->backgroundStyle ()); dFree(name); } @@ -766,7 +766,7 @@ void Html_tag_open_select(DilloHtml *html, const char *tag, int tagsize) html->styleEngine->setNonCssHint (PROPERTY_X_TOOLTIP, CSS_TYPE_STRING, attrbuf); } - HT2TB(html)->addWidget (embed, html->styleEngine->backgroundStyle ()); + HT2TB(html)->addWidget (embed, html->backgroundStyle ()); Html_add_input(html, type, embed, name, NULL, false); a_Html_stash_init(html); @@ -938,16 +938,16 @@ void Html_tag_open_button(DilloHtml *html, const char *tag, int tagsize) * but it caused 100% CPU usage. */ page = new Textblock (false); - page->setStyle (html->styleEngine->backgroundStyle ()); + page->setStyle (html->backgroundStyle ()); ResourceFactory *factory = HT2LT(html)->getResourceFactory(); Resource *resource = factory->createComplexButtonResource(page, true); embed = new Embed(resource); // a_Dw_button_set_sensitive (DW_BUTTON (button), FALSE); - HT2TB(html)->addParbreak (5, html->styleEngine->wordStyle ()); - HT2TB(html)->addWidget (embed, html->styleEngine->backgroundStyle ()); - HT2TB(html)->addParbreak (5, html->styleEngine->wordStyle ()); + HT2TB(html)->addParbreak (5, html->wordStyle ()); + HT2TB(html)->addWidget (embed, html->backgroundStyle ()); + HT2TB(html)->addParbreak (5, html->wordStyle ()); S_TOP(html)->textblock = html->dw = page; @@ -2005,12 +2005,16 @@ static Embed *Html_input_image(DilloHtml *html, const char *tag, int tagsize) /* create new image and add it to the button */ a_Html_image_attrs(html, tag, tagsize); if ((Image = a_Html_image_new(html, tag, tagsize))) { - IM2DW(Image)->setStyle (html->styleEngine->backgroundStyle ()); + // At this point, we know that Image->ir represents an image + // widget. Notice that the order of the casts matters, because + // of multiple inheritance. + dw::Image *dwi = (dw::Image*)(dw::core::ImgRenderer*)Image->img_rndr; + dwi->setStyle (html->backgroundStyle ()); ResourceFactory *factory = HT2LT(html)->getResourceFactory(); ComplexButtonResource *complex_b_r = - factory->createComplexButtonResource(IM2DW(Image), false); + factory->createComplexButtonResource(dwi, false); button = new Embed(complex_b_r); - HT2TB(html)->addWidget (button, html->styleEngine->style ()); + HT2TB(html)->addWidget (button, html->style ()); } if (!button) MSG("Html_input_image: unable to create image submit.\n"); diff --git a/src/html.cc b/src/html.cc index 46b502e5..74b90577 100644 --- a/src/html.cc +++ b/src/html.cc @@ -359,12 +359,11 @@ bool a_Html_tag_set_valign_attr(DilloHtml *html, const char *tag, int tagsize) static void Html_add_textblock(DilloHtml *html, int space) { Textblock *textblock = new Textblock (prefs.limit_text_width); - Style *style = html->styleEngine->style (); - HT2TB(html)->addParbreak (space, html->styleEngine->wordStyle ()); - HT2TB(html)->addWidget (textblock, style); // Works also for floats etc. - - HT2TB(html)->addParbreak (space, html->styleEngine->wordStyle ()); + HT2TB(html)->addParbreak (space, html->wordStyle ()); + HT2TB(html)->addWidget (textblock, html->style ()); /* Works also for floats + etc. */ + HT2TB(html)->addParbreak (space, html->wordStyle ()); S_TOP(html)->textblock = html->dw = textblock; S_TOP(html)->hand_over_break = true; } @@ -1042,11 +1041,11 @@ static void Html_process_space_pre_line(DilloHtml *html, const char *space, breakCnt++; html->PrevWasCR = (space[i] == '\r'); - HT2TB(html)->addLinebreak (html->styleEngine->wordStyle ()); + HT2TB(html)->addLinebreak (html->wordStyle ()); } } if (breakCnt == 0) { - HT2TB(html)->addSpace(html->styleEngine->wordStyle ()); + HT2TB(html)->addSpace(html->wordStyle ()); } } @@ -1079,12 +1078,11 @@ static void Html_process_space(DilloHtml *html, const char *space, if (spaceCnt) { spc = dStrnfill(spaceCnt, ' '); - HT2TB(html)->addText (spc, spaceCnt, - html->styleEngine->wordStyle ()); + HT2TB(html)->addText (spc, spaceCnt, html->wordStyle ()); dFree(spc); spaceCnt = 0; } - HT2TB(html)->addLinebreak (html->styleEngine->wordStyle ()); + HT2TB(html)->addLinebreak (html->wordStyle ()); html->pre_column = 0; } html->PreFirstChar = false; @@ -1112,20 +1110,19 @@ static void Html_process_space(DilloHtml *html, const char *space, if (spaceCnt) { // add break possibility for the white-space:pre-wrap case - HT2TB(html)->addBreakOption (html->styleEngine->wordStyle (), false); + HT2TB(html)->addBreakOption (html->wordStyle (), false); spc = dStrnfill(spaceCnt, ' '); - HT2TB(html)->addText (spc, spaceCnt, html->styleEngine->wordStyle ()); + HT2TB(html)->addText (spc, spaceCnt, html->wordStyle ()); dFree(spc); } } else { if (SGML_SPCDEL) { /* SGML_SPCDEL ignores white space immediately after an open tag */ - } else if (html->styleEngine->wordStyle ()->whiteSpace == - WHITE_SPACE_PRE_LINE) { + } else if (html->wordStyle ()->whiteSpace == WHITE_SPACE_PRE_LINE) { Html_process_space_pre_line(html, space, spacesize); } else { - HT2TB(html)->addSpace(html->styleEngine->wordStyle ()); + HT2TB(html)->addSpace(html->wordStyle ()); } if (parse_mode == DILLO_HTML_PARSE_MODE_STASH_AND_BODY) @@ -1178,8 +1175,7 @@ static void Html_process_word(DilloHtml *html, const char *word, int size) Html_process_space(html, Pword + start, i - start); } else { while (Pword[++i] && !isspace(Pword[i])) ; - HT2TB(html)->addText(Pword + start, i - start, - html->styleEngine->wordStyle ()); + HT2TB(html)->addText(Pword + start, i - start, html->wordStyle ()); html->pre_column += i - start; html->PreFirstChar = false; } @@ -1217,20 +1213,18 @@ 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; - HT2TB(html)->addBreakOption(html->styleEngine->wordStyle (), false); + HT2TB(html)->addBreakOption(html->wordStyle (), false); } else if (a_Utf8_ideographic(word2+i, beyond_word2, &len)) { i += len; - HT2TB(html)->addText(word2 + start, i - start, - html->styleEngine->wordStyle ()); - HT2TB(html)->addBreakOption(html->styleEngine->wordStyle (), false); + HT2TB(html)->addText(word2 + start, i - start, html->wordStyle ()); + HT2TB(html)->addBreakOption(html->wordStyle (), false); } else { do { i += len; } while (word2[i] && !isspace(word2[i]) && strncmp(word2+i, utf8_zero_width_space, 3) && (!a_Utf8_ideographic(word2+i, beyond_word2, &len))); - HT2TB(html)->addText(word2 + start, i - start, - html->styleEngine->wordStyle ()); + HT2TB(html)->addText(word2 + start, i - start, html->wordStyle ()); } } if (Pword == word2) @@ -1264,7 +1258,7 @@ static void Html_eventually_pop_dw(DilloHtml *html, bool hand_over_break) { if (html->dw != S_TOP(html)->textblock) { if (hand_over_break) - HT2TB(html)->handOverBreak (html->styleEngine->style ()); + HT2TB(html)->handOverBreak (html->style ()); HT2TB(html)->flush (); html->dw = S_TOP(html)->textblock; } @@ -1292,7 +1286,7 @@ static void Html_push_tag(DilloHtml *html, int tag_idx) */ static void Html_force_push_tag(DilloHtml *html, int tag_idx) { - html->styleEngine->startElement (tag_idx); + html->startElement (tag_idx); Html_push_tag(html, tag_idx); } @@ -1818,6 +1812,10 @@ static void Html_tag_open_body(DilloHtml *html, const char *tag, int tagsize) int32_t color; int tag_index_a = a_Html_tag_index ("a"); style::Color *bgColor; + style::StyleImage *bgImage; + style::BackgroundRepeat bgRepeat; + style::BackgroundAttachment bgAttachment; + style::Length bgPositionX, bgPositionY; _MSG("Html_tag_open_body Num_BODY=%d\n", html->Num_BODY); if (!(html->InFlags & IN_BODY)) @@ -1858,7 +1856,7 @@ static void Html_tag_open_body(DilloHtml *html, const char *tag, int tagsize) CSS_TYPE_COLOR, color); } - html->styleEngine->restyle (); + html->restyle (); if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "link"))) { html->non_css_link_color = a_Html_color_parse(html, attrbuf, -1); @@ -1872,35 +1870,40 @@ static void Html_tag_open_body(DilloHtml *html, const char *tag, int tagsize) BUG_MSG("<body> vlink attribute is obsolete.\n"); } - html->dw->setStyle (html->styleEngine->style ()); + html->dw->setStyle (html->style ()); bgColor = html->styleEngine->backgroundColor (); - if (bgColor) HT2LT(html)->setBgColor(bgColor); + bgImage = html->styleEngine->backgroundImage (&bgRepeat, &bgAttachment, + &bgPositionX, &bgPositionY); + if (bgImage) + HT2LT(html)->setBgImage(bgImage, bgRepeat, bgAttachment, bgPositionX, + bgPositionY); + /* Determine a color for visited links. * This color is computed once per page and used for immediate feedback * when clicking a link. * On reload style including color for visited links is computed properly * according to CSS. */ - html->styleEngine->startElement (tag_index_a); + html->startElement (tag_index_a); html->styleEngine->setPseudoVisited (); if (html->non_css_visited_color != -1) { html->styleEngine->setNonCssHint (CSS_PROPERTY_COLOR, CSS_TYPE_COLOR, html->non_css_visited_color); } - html->visited_color = html->styleEngine->style ()->color->getColor (); + html->visited_color = html->style ()->color->getColor (); html->styleEngine->endElement (tag_index_a); if (prefs.contrast_visited_color) { /* get a color that has a "safe distance" from text, link and bg */ html->visited_color = a_Color_vc(html->visited_color, - html->styleEngine->style ()->color->getColor(), + html->style ()->color->getColor(), html->non_css_link_color, - html->styleEngine->backgroundStyle()->backgroundColor->getColor()); + html->backgroundStyle()->backgroundColor->getColor()); } @@ -1972,28 +1975,28 @@ static void src = dStrdup(attrbuf); - textblock->addParbreak (5, html->styleEngine->wordStyle ()); + textblock->addParbreak (5, html->wordStyle ()); bullet = new Bullet(); - textblock->addWidget(bullet, html->styleEngine->wordStyle ()); - textblock->addSpace(html->styleEngine->wordStyle ()); + textblock->addWidget(bullet, html->wordStyle ()); + textblock->addSpace(html->wordStyle ()); if (D_ASCII_TOLOWER(tag[1]) == 'i') { /* IFRAME usually comes with very long advertising/spying URLS, * to not break rendering we will force name="IFRAME" */ - textblock->addText ("IFRAME", html->styleEngine->wordStyle ()); + textblock->addText ("IFRAME", html->wordStyle ()); } else { /* FRAME: * If 'name' tag is present use it, if not use 'src' value */ if (!(attrbuf = a_Html_get_attr(html, tag, tagsize, "name"))) { - textblock->addText (src, html->styleEngine->wordStyle ()); + textblock->addText (src, html->wordStyle ()); } else { - textblock->addText (attrbuf, html->styleEngine->wordStyle ()); + textblock->addText (attrbuf, html->wordStyle ()); } } - textblock->addParbreak (5, html->styleEngine->wordStyle ()); + textblock->addParbreak (5, html->wordStyle ()); dFree(src); } @@ -2006,8 +2009,8 @@ static void static void Html_tag_content_frameset (DilloHtml *html, const char *tag, int tagsize) { - HT2TB(html)->addParbreak (9, html->styleEngine->wordStyle ()); - HT2TB(html)->addText("--FRAME--", html->styleEngine->wordStyle ()); + HT2TB(html)->addParbreak (9, html->wordStyle ()); + HT2TB(html)->addText("--FRAME--", html->wordStyle ()); Html_add_textblock(html, 5); } @@ -2028,7 +2031,7 @@ static void Html_tag_open_h(DilloHtml *html, const char *tag, int tagsize) */ static void Html_tag_content_br(DilloHtml *html, const char *tag, int tagsize) { - HT2TB(html)->addLinebreak (html->styleEngine->wordStyle ()); + HT2TB(html)->addLinebreak (html->wordStyle ()); } /* @@ -2217,7 +2220,9 @@ DilloImage *a_Html_image_new(DilloHtml *html, const char *tag, int tagsize) alt_ptr = dStrdup("[IMG]"); // Place holder for img_off mode } - image = a_Image_new(alt_ptr, 0); + dw::Image *dw = new dw::Image(alt_ptr); + image = + a_Image_new(html->dw->getLayout(), (void*)(dw::core::ImgRenderer*)dw, 0); if (HT2TB(html)->getBgColor()) image->bg_color = HT2TB(html)->getBgColor()->getColor(); @@ -2294,13 +2299,17 @@ static void Html_tag_content_img(DilloHtml *html, const char *tag, int tagsize) /* TODO: usemap URLs outside of the document are not used. */ usemap_url = a_Html_url_new(html, attrbuf, NULL, 0); - HT2TB(html)->addWidget((Widget*)Image->dw, html->styleEngine->style()); + // At this point, we know that Image->ir represents an image + // widget. Notice that the order of the casts matters, because of + // multiple inheritance. + dw::Image *dwi = (dw::Image*)(dw::core::ImgRenderer*)Image->img_rndr; + HT2TB(html)->addWidget(dwi, html->style()); /* Image maps */ if (a_Html_get_attr(html, tag, tagsize, "ismap")) { - ((::dw::Image*)Image->dw)->setIsMap(); + dwi->setIsMap(); _MSG(" Html_tag_open_img: server-side map (ISMAP)\n"); - } else if (html->styleEngine->style ()->x_link != -1 && + } else if (html->style ()->x_link != -1 && usemap_url == NULL) { /* For simple links, we have to suppress the "image_pressed" signal. * This is overridden for USEMAP images. */ @@ -2308,8 +2317,7 @@ static void Html_tag_content_img(DilloHtml *html, const char *tag, int tagsize) } if (usemap_url) { - ((::dw::Image*)Image->dw)->setUseMap(&html->maps, - new ::object::String(URL_STR(usemap_url))); + dwi->setUseMap(&html->maps, new ::object::String(URL_STR(usemap_url))); a_Url_free (usemap_url); } } @@ -2352,8 +2360,14 @@ static void Html_tag_close_map(DilloHtml *html) for (int i = 0; i < html->images->size(); i++) { DilloImage *img = html->images->get(i)->image; - if (img) - ((dw::Image*) img->dw)->forceMapRedraw(); + if (img) { + // At this point, we know that img->ir represents an image + // widget. (Really? Is this assumtion safe?) Notice that the + // order of the casts matters, because of multiple + // inheritance. + dw::Image *dwi = (dw::Image*)(dw::core::ImgRenderer*)img->img_rndr; + dwi->forceMapRedraw(); + } } html->InFlags &= ~IN_MAP; } @@ -2496,7 +2510,7 @@ static void Html_tag_open_object(DilloHtml *html, const char *tag, int tagsize) html->styleEngine->setNonCssHint(PROPERTY_X_LINK, CSS_TYPE_INTEGER, Html_set_new_link(html, &url)); - HT2TB(html)->addText("[OBJECT]", html->styleEngine->wordStyle ()); + HT2TB(html)->addText("[OBJECT]", html->wordStyle ()); } a_Url_free(base_url); } @@ -2530,7 +2544,7 @@ static const char* Html_get_javascript_link(DilloHtml *html) static void Html_add_anchor(DilloHtml *html, const char *name) { _MSG("Registering ANCHOR: %s\n", name); - if (!HT2TB(html)->addAnchor (name, html->styleEngine->style ())) + if (!HT2TB(html)->addAnchor (name, html->style ())) BUG_MSG("Anchor names must be unique within the document ('%s')\n",name); /* * According to Sec. 12.2.1 of the HTML 4.01 spec, "anchor names that @@ -2639,7 +2653,7 @@ static void Html_tag_open_q(DilloHtml *html, const char *tag, int tagsize) const char *U201C = "\xe2\x80\x9c"; html->styleEngine->inheritBackgroundColor (); - HT2TB(html)->addText (U201C, html->styleEngine->wordStyle ()); + HT2TB(html)->addText (U201C, html->wordStyle ()); } /* @@ -2650,7 +2664,7 @@ static void Html_tag_close_q(DilloHtml *html) /* Right Double Quotation Mark */ const char *U201D = "\xe2\x80\x9d"; - HT2TB(html)->addText (U201D, html->styleEngine->wordStyle ()); + HT2TB(html)->addText (U201D, html->wordStyle ()); } /* @@ -2692,7 +2706,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 ()); + HT2TB(html)->addParbreak (9, html->wordStyle ()); S_TOP(html)->list_type = HTML_LIST_UNORDERED; S_TOP(html)->list_number = 0; @@ -2752,7 +2766,7 @@ static void Html_tag_open_ol(DilloHtml *html, const char *tag, int tagsize) */ static void Html_tag_open_li(DilloHtml *html, const char *tag, int tagsize) { - Style *style = html->styleEngine->style (); + Style *style = html->style (); int *list_number; const char *attrbuf; @@ -2847,12 +2861,12 @@ static void Html_tag_open_hr(DilloHtml *html, const char *tag, int tagsize) static void Html_tag_content_hr(DilloHtml *html, const char *tag, int tagsize) { Widget *hruler; - HT2TB(html)->addParbreak (5, html->styleEngine->wordStyle ()); + HT2TB(html)->addParbreak (5, html->wordStyle ()); hruler = new Ruler(); - hruler->setStyle (html->styleEngine->style ()); - HT2TB(html)->addWidget (hruler, html->styleEngine->style ()); - HT2TB(html)->addParbreak (5, html->styleEngine->wordStyle ()); + hruler->setStyle (html->style ()); + HT2TB(html)->addWidget (hruler, html->style ()); + HT2TB(html)->addParbreak (5, html->wordStyle ()); } /* @@ -2862,7 +2876,7 @@ 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 ()); + HT2TB(html)->addParbreak (9, html->wordStyle ()); } /* @@ -2871,7 +2885,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 ()); + HT2TB(html)->addParbreak (9, html->wordStyle ()); } /* @@ -2888,7 +2902,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 ()); + HT2TB(html)->addParbreak (9, html->wordStyle ()); html->InFlags |= IN_PRE; } @@ -3220,7 +3234,7 @@ static void Html_tag_open_div(DilloHtml *html, const char *tag, int tagsize) */ static void Html_tag_close_par(DilloHtml *html) { - HT2TB(html)->addParbreak (9, html->styleEngine->wordStyle ()); + HT2TB(html)->addParbreak (9, html->wordStyle ()); } /* @@ -3228,7 +3242,7 @@ static void Html_tag_close_par(DilloHtml *html) */ static void Html_tag_content_wbr(DilloHtml *html, const char *tag, int tagsize) { - HT2TB(html)->addBreakOption(html->styleEngine->wordStyle (), true); + HT2TB(html)->addBreakOption(html->wordStyle (), true); } @@ -3663,8 +3677,8 @@ static void Html_display_block(DilloHtml *html) static void Html_display_listitem(DilloHtml *html) { - Style *style = html->styleEngine->style (); - Style *wordStyle = html->styleEngine->wordStyle (); + Style *style = html->style (); + Style *wordStyle = html->wordStyle (); Widget **ref_list_item; ListItem *list_item; int *list_number; @@ -3748,7 +3762,7 @@ static void Html_process_tag(DilloHtml *html, char *tag, int tagsize) /* Push the tag into the stack */ Html_push_tag(html, ni); - html->styleEngine->startElement (ni); + html->startElement (ni); _MSG("Open : %*s%s\n", html->stack->size(), " ", Tags[ni].name); /* Parse attributes that can appear on any tag */ @@ -3759,7 +3773,7 @@ static void Html_process_tag(DilloHtml *html, char *tag, int tagsize) Tags[ni].open (html, tag, tagsize); if (! S_TOP(html)->display_none) { - switch (html->styleEngine->style ()->display) { + switch (html->style ()->display) { case DISPLAY_BLOCK: Html_display_block(html); break; @@ -3786,8 +3800,8 @@ static void Html_process_tag(DilloHtml *html, char *tag, int tagsize) if (S_TOP(html)->parse_mode == DILLO_HTML_PARSE_MODE_VERBATIM) { /* don't change anything */ } else if (S_TOP(html)->parse_mode != DILLO_HTML_PARSE_MODE_PRE && - (html->styleEngine->style ()->whiteSpace == WHITE_SPACE_PRE || - html->styleEngine->style ()->whiteSpace == WHITE_SPACE_PRE_WRAP)) { + (html->style ()->whiteSpace == WHITE_SPACE_PRE || + html->style ()->whiteSpace == WHITE_SPACE_PRE_WRAP)) { S_TOP(html)->parse_mode = DILLO_HTML_PARSE_MODE_PRE; html->pre_column = 0; html->PreFirstChar = true; diff --git a/src/html_common.hh b/src/html_common.hh index 6c5d4807..a43d91b7 100644 --- a/src/html_common.hh +++ b/src/html_common.hh @@ -218,6 +218,22 @@ public: bool_t unloadedImages(); void loadImages (const DilloUrl *pattern); void addCssUrl(const DilloUrl *url); + + // useful shortcuts + inline void startElement (int tag) + { styleEngine->startElement (tag, bw, base_url); } + inline void startElement (const char *tagname) + { styleEngine->startElement (tagname, bw, base_url); } + + inline dw::core::style::Style *backgroundStyle () + { return styleEngine->backgroundStyle (bw, base_url); } + inline dw::core::style::Style *style () + { return styleEngine->style (bw, base_url); } + inline dw::core::style::Style *wordStyle () + { return styleEngine->wordStyle (bw, base_url); } + + inline void restyle () { styleEngine->restyle (bw, base_url); } + }; /* diff --git a/src/image.cc b/src/image.cc index c499d977..9915023a 100644 --- a/src/image.cc +++ b/src/image.cc @@ -23,19 +23,20 @@ using namespace dw::core; -// Image to Object-Image macro -#define I2DW(Image) ((dw::Image*)(Image->dw)) +// Image to Object-ImgRenderer macro +#define I2IR(Image) ((dw::core::ImgRenderer*)(Image->img_rndr)) /* * Create and initialize a new image structure. */ -DilloImage *a_Image_new(const char *alt_text, int32_t bg_color) +DilloImage *a_Image_new(void *layout, void *img_rndr, int32_t bg_color) { DilloImage *Image; Image = dNew(DilloImage, 1); - Image->dw = (void*) new dw::Image(alt_text); + Image->layout = layout; + Image->img_rndr = img_rndr; Image->width = 0; Image->height = 0; Image->bg_color = bg_color; @@ -49,6 +50,26 @@ DilloImage *a_Image_new(const char *alt_text, int32_t bg_color) } /* + * Create and initialize a new image structure with an image widget. + */ +DilloImage *a_Image_new_with_dw(void *layout, const char *alt_text, + int32_t bg_color) +{ + dw::Image *dw = new dw::Image(alt_text); + return a_Image_new(layout, (void*)(dw::core::ImgRenderer*)dw, bg_color); +} + +/* + * Return the image renderer as a widget. This is somewhat tricky, + * since simple casting leads to wrong (and hard to debug) results, + * because of multiple inheritance. This function can be used from C + * code, where only access to void* is possible. + */ +void *a_Image_get_dw(DilloImage *Image) +{ + return (dw::Image*)(dw::core::ImgRenderer*)Image->img_rndr; +} +/* * Deallocate an Image structure */ static void Image_free(DilloImage *Image) @@ -88,7 +109,7 @@ void a_Image_set_parms(DilloImage *Image, void *v_imgbuf, DilloUrl *url, _MSG("a_Image_set_parms: width=%d height=%d\n", width, height); bool resize = (Image->width != width || Image->height != height); - I2DW(Image)->setBuffer((Imgbuf*)v_imgbuf, resize); + I2IR(Image)->setBuffer((Imgbuf*)v_imgbuf, resize); if (!Image->BitVec) Image->BitVec = a_Bitvec_new(height); @@ -106,7 +127,7 @@ void a_Image_write(DilloImage *Image, uint_t y) dReturn_if_fail ( y < Image->height ); /* Update the row in DwImage */ - I2DW(Image)->drawRow(y); + I2IR(Image)->drawRow(y); a_Bitvec_set_bit(Image->BitVec, y); Image->State = IMG_Write; } @@ -117,5 +138,15 @@ void a_Image_write(DilloImage *Image, uint_t y) void a_Image_close(DilloImage *Image) { _MSG("a_Image_close\n"); + I2IR(Image)->finish(); +} + +/* + * Implement the abort method + */ +void a_Image_abort(DilloImage *Image) +{ + _MSG("a_Image_abort\n"); + I2IR(Image)->fatal(); } diff --git a/src/image.hh b/src/image.hh index a66edaae..39fe0405 100644 --- a/src/image.hh +++ b/src/image.hh @@ -44,7 +44,7 @@ typedef enum { } ImageState; struct _DilloImage { - void *dw; + void *layout, *img_rndr; /* Parameters as told by image data */ uint_t width; @@ -62,7 +62,10 @@ struct _DilloImage { /* * Function prototypes */ -DilloImage *a_Image_new(const char *alt_text, int32_t bg_color); +DilloImage *a_Image_new(void *layout, void *img_rndr, int32_t bg_color); +DilloImage *a_Image_new_with_dw(void *layout, const char *alt_text, + int32_t bg_color); +void *a_Image_get_dw(DilloImage *Image); void a_Image_ref(DilloImage *Image); void a_Image_unref(DilloImage *Image); @@ -71,6 +74,7 @@ void a_Image_set_parms(DilloImage *Image, void *v_imgbuf, DilloUrl *url, DilloImgType type); void a_Image_write(DilloImage *Image, uint_t y); void a_Image_close(DilloImage *Image); +void a_Image_abort(DilloImage *Image); #ifdef __cplusplus diff --git a/src/imgbuf.cc b/src/imgbuf.cc index 16eb5c31..48e6bde5 100644 --- a/src/imgbuf.cc +++ b/src/imgbuf.cc @@ -90,10 +90,9 @@ void a_Imgbuf_unref(void *v_imgbuf) /* * Create a new Imgbuf */ -void *a_Imgbuf_new(void *v_dw, int img_type, uint_t width, uint_t height, +void *a_Imgbuf_new(void *layout, int img_type, uint_t width, uint_t height, double gamma) { - Layout *layout = ((Widget*)v_dw)->getLayout(); if (!layout) { MSG_ERR("a_Imgbuf_new: layout is NULL.\n"); exit(1); @@ -104,7 +103,8 @@ void *a_Imgbuf_new(void *v_dw, int img_type, uint_t width, uint_t height, linebuf = (uchar_t*) dRealloc(linebuf, linebuf_size); } - return (void*)layout->createImgbuf(Imgbuf::RGB, width, height, gamma); + return (void*)((Layout*)layout)->createImgbuf(Imgbuf::RGB, width, height, + gamma); } /* diff --git a/src/imgbuf.hh b/src/imgbuf.hh index af0bf9a6..efa1b48c 100644 --- a/src/imgbuf.hh +++ b/src/imgbuf.hh @@ -16,7 +16,7 @@ extern "C" { */ void a_Imgbuf_ref(void *v_imgbuf); void a_Imgbuf_unref(void *v_imgbuf); -void *a_Imgbuf_new(void *v_dw, int img_type, uint_t width, uint_t height, +void *a_Imgbuf_new(void *v_ir, int img_type, uint_t width, uint_t height, double gamma); int a_Imgbuf_last_reference(void *v_imgbuf); void a_Imgbuf_update(void *v_imgbuf, const uchar_t *buf, DilloImgType type, diff --git a/src/menu.cc b/src/menu.cc index 617297ce..b93106e1 100644 --- a/src/menu.cc +++ b/src/menu.cc @@ -679,6 +679,18 @@ static void Menu_imgload_toggle_cb(Fl_Widget *wid, void*) } /* + * Toggle loading of background images. + */ +static void Menu_bgimg_load_toggle_cb(Fl_Widget *wid, void*) +{ + Fl_Menu_Item *item = (Fl_Menu_Item*) wid; + + item->flags ^= FL_MENU_VALUE; + prefs.load_background_images = item->flags & FL_MENU_VALUE ? 1 : 0; + a_UIcmd_repush(popup_bw); +} + +/* * Tools popup menu (construction & popup) */ void a_Menu_tools_popup(BrowserWindow *bw, int x, int y) @@ -691,6 +703,8 @@ void a_Menu_tools_popup(BrowserWindow *bw, int x, int y) {"Use embedded CSS", 0, Menu_embedded_css_cb, 0, FL_MENU_TOGGLE|FL_MENU_DIVIDER,0,0,0,0}, {"Load images", 0, Menu_imgload_toggle_cb, 0, + FL_MENU_TOGGLE,0,0,0,0}, + {"Load background images", 0, Menu_bgimg_load_toggle_cb, 0, FL_MENU_TOGGLE|FL_MENU_DIVIDER,0,0,0,0}, {"Panel size", 0, Menu_nop_cb, (void*)"Submenu1", FL_SUBMENU,0,0,0,0}, {"tiny", 0,Menu_panel_change_cb,(void*)0,FL_MENU_RADIO,0,0,0,0}, @@ -713,8 +727,10 @@ void a_Menu_tools_popup(BrowserWindow *bw, int x, int y) pm[1].set(); if (prefs.load_images) pm[2].set(); - pm[4+cur_panelsize].setonly(); - cur_smallicons ? pm[7].set() : pm[7].clear(); + if (prefs.load_background_images) + pm[3].set(); + pm[5+cur_panelsize].setonly(); + cur_smallicons ? pm[8].set() : pm[8].clear(); item = pm->popup(x, y); if (item) { diff --git a/src/plain.cc b/src/plain.cc index d63ce6cf..d09f6d79 100644 --- a/src/plain.cc +++ b/src/plain.cc @@ -97,9 +97,10 @@ DilloPlain::DilloPlain(BrowserWindow *p_bw) Layout *layout = (Layout*) bw->render_layout; StyleEngine styleEngine (layout); - styleEngine.startElement ("body"); - styleEngine.startElement ("pre"); - widgetStyle = styleEngine.wordStyle (); + // TODO (3x) No URL? + styleEngine.startElement ("body", bw, NULL); + styleEngine.startElement ("pre", bw, NULL); + widgetStyle = styleEngine.wordStyle (bw, NULL); widgetStyle->ref (); /* The context menu */ diff --git a/src/prefs.c b/src/prefs.c index a192c324..257e4a05 100644 --- a/src/prefs.c +++ b/src/prefs.c @@ -68,6 +68,7 @@ void a_Prefs_init(void) prefs.http_user_agent = dStrdup(PREFS_HTTP_USER_AGENT); prefs.limit_text_width = FALSE; prefs.load_images=TRUE; + prefs.load_background_images=TRUE; prefs.load_stylesheets=TRUE; prefs.middle_click_drags_page = TRUE; prefs.middle_click_opens_new_tab = TRUE; diff --git a/src/prefs.h b/src/prefs.h index de3e0342..bb97651e 100644 --- a/src/prefs.h +++ b/src/prefs.h @@ -88,6 +88,7 @@ typedef struct { bool_t show_quit_dialog; bool_t fullwindow_start; bool_t load_images; + bool_t load_background_images; bool_t load_stylesheets; bool_t parse_embedded_css; int32_t buffered_drawing; diff --git a/src/prefsparser.cc b/src/prefsparser.cc index 86f8580c..81b097e7 100644 --- a/src/prefsparser.cc +++ b/src/prefsparser.cc @@ -79,6 +79,7 @@ int PrefsParser::parseOption(char *name, char *value) { "http_user_agent", &prefs.http_user_agent, PREFS_STRING }, { "limit_text_width", &prefs.limit_text_width, PREFS_BOOL }, { "load_images", &prefs.load_images, PREFS_BOOL }, + { "load_background_images", &prefs.load_background_images, PREFS_BOOL }, { "load_stylesheets", &prefs.load_stylesheets, PREFS_BOOL }, { "middle_click_drags_page", &prefs.middle_click_drags_page, PREFS_BOOL }, diff --git a/src/styleengine.cc b/src/styleengine.cc index 8817479f..2da9d8f7 100644 --- a/src/styleengine.cc +++ b/src/styleengine.cc @@ -15,10 +15,49 @@ #include "misc.h" #include "html_common.hh" #include "styleengine.hh" +#include "web.hh" +#include "capi.h" using namespace lout::misc; using namespace dw::core::style; +/** + * Signal handler for "delete": This handles the case when an instance + * of StyleImage is deleted, possibly when the cache client is still + * active. + * + * \todo Not neccessary for dw::Image? (dw::Image also implements + * lout::signal::ObservedObject.) + */ +class StyleImageDeletionReceiver: + public lout::signal::ObservedObject::DeletionReceiver +{ + int clientKey; + +public: + StyleImageDeletionReceiver (int clientKey); + ~StyleImageDeletionReceiver (); + + void deleted (lout::signal::ObservedObject *object); +}; + +StyleImageDeletionReceiver::StyleImageDeletionReceiver (int clientKey) +{ + this->clientKey = clientKey; +} + +StyleImageDeletionReceiver::~StyleImageDeletionReceiver () +{ +} + +void StyleImageDeletionReceiver::deleted (lout::signal::ObservedObject *object) +{ + a_Capi_stop_client (clientKey, 0); + delete this; +} + +// ---------------------------------------------------------------------- + StyleEngine::StyleEngine (dw::core::Layout *layout) { StyleAttrs style_attrs; FontAttrs font_attrs; @@ -92,8 +131,8 @@ void StyleEngine::stackPop () { /** * \brief tell the styleEngine that a new html element has started. */ -void StyleEngine::startElement (int element) { - style (); // ensure that style of current node is computed +void StyleEngine::startElement (int element, BrowserWindow *bw, DilloUrl *url) { + style (bw, url); // ensure that style of current node is computed stackPush (); Node *n = stack->getLastRef (); @@ -103,8 +142,9 @@ void StyleEngine::startElement (int element) { n->doctreeNode = dn; } -void StyleEngine::startElement (const char *tagname) { - startElement (a_Html_tag_index (tagname)); +void StyleEngine::startElement (const char *tagname, BrowserWindow *bw, + DilloUrl *url) { + startElement (a_Html_tag_index (tagname), bw, url); } void StyleEngine::setId (const char *id) { @@ -207,6 +247,26 @@ dw::core::style::Color *StyleEngine::backgroundColor () { return NULL; } +dw::core::style::StyleImage *StyleEngine::backgroundImage + (dw::core::style::BackgroundRepeat *bgRepeat, + dw::core::style::BackgroundAttachment *bgAttachment, + dw::core::style::Length *bgPositionX, + dw::core::style::Length *bgPositionY) { + for (int i = 1; i < stack->size (); i++) { + Node *n = stack->getRef (i); + + if (n->style && n->style->backgroundImage) { + *bgRepeat = n->style->backgroundRepeat; + *bgAttachment = n->style->backgroundAttachment; + *bgPositionX = n->style->backgroundPositionX; + *bgPositionY = n->style->backgroundPositionY; + return n->style->backgroundImage; + } + } + + return NULL; +} + /** * \brief set the CSS pseudo class :link. */ @@ -238,6 +298,16 @@ void StyleEngine::preprocessAttrs (dw::core::style::StyleAttrs *attrs) { if (stack->getRef (stack->size () - 2)->inheritBackgroundColor) { attrs->backgroundColor = stack->getRef (stack->size () - 2)->style->backgroundColor; + attrs->backgroundImage = + stack->getRef (stack->size () - 2)->style->backgroundImage; + attrs->backgroundRepeat = + stack->getRef (stack->size () - 2)->style->backgroundRepeat; + attrs->backgroundAttachment = + stack->getRef (stack->size () - 2)->style->backgroundAttachment; + attrs->backgroundPositionX = + stack->getRef (stack->size () - 2)->style->backgroundPositionX; + attrs->backgroundPositionY = + stack->getRef (stack->size () - 2)->style->backgroundPositionY; attrs->valign = stack->getRef (stack->size () - 2)->style->valign; } @@ -281,7 +351,8 @@ void StyleEngine::postprocessAttrs (dw::core::style::StyleAttrs *attrs) { /** * \brief Make changes to StyleAttrs attrs according to CssPropertyList props. */ -void StyleEngine::apply (int i, StyleAttrs *attrs, CssPropertyList *props) { +void StyleEngine::apply (int i, StyleAttrs *attrs, CssPropertyList *props, + BrowserWindow *bw, DilloUrl *url) { FontAttrs fontAttrs = *attrs->font; Font *parentFont = stack->get (i - 1).style->font; char *c, *fontName; @@ -441,6 +512,10 @@ void StyleEngine::apply (int i, StyleAttrs *attrs, CssPropertyList *props) { switch (p->name) { /* \todo missing cases */ + case CSS_PROPERTY_BACKGROUND_ATTACHMENT: + attrs->backgroundAttachment = + (BackgroundAttachment) p->value.intVal; + break; case CSS_PROPERTY_BACKGROUND_COLOR: if (prefs.allow_white_bg || p->value.intVal != 0xffffff) attrs->backgroundColor = Color::create(layout, p->value.intVal); @@ -448,6 +523,42 @@ void StyleEngine::apply (int i, StyleAttrs *attrs, CssPropertyList *props) { attrs->backgroundColor = Color::create(layout, prefs.white_bg_replacement); break; + case CSS_PROPERTY_BACKGROUND_IMAGE: + if (prefs.load_background_images) + { + DilloUrl *imgUrl = + a_Url_new (p->value.strVal, a_Url_str (url)); + + attrs->backgroundImage = StyleImage::create(); + DilloImage *image = + a_Image_new(layout, + (void*)attrs->backgroundImage + ->getMainImgRenderer(), + 0xffffff); + + DilloWeb *web = a_Web_new(bw, imgUrl, url); + web->Image = image; + a_Image_ref(image); + web->flags |= WEB_Image; + + int clientKey; + if ((clientKey = a_Capi_open_url(web, NULL, NULL)) != 0) { + a_Bw_add_client(bw, clientKey, 0); + a_Bw_add_url(bw, url); + attrs->backgroundImage->connectDeletion + (new StyleImageDeletionReceiver (clientKey)); + } + } + break; + case CSS_PROPERTY_BACKGROUND_POSITION: + computeLength (&attrs->backgroundPositionX, p->value.posVal->posX, + attrs->font); + computeLength (&attrs->backgroundPositionY, p->value.posVal->posY, + attrs->font); + break; + case CSS_PROPERTY_BACKGROUND_REPEAT: + attrs->backgroundRepeat = (BackgroundRepeat) p->value.intVal; + break; case CSS_PROPERTY_BORDER_COLLAPSE: attrs->borderCollapse = (BorderCollapse) p->value.intVal; break; @@ -727,9 +838,9 @@ void StyleEngine::computeBorderWidth (int *dest, CssProperty *p, * A normal style might have backgroundColor == NULL to indicate a transparent * background. This method ensures that backgroundColor is set. */ -Style * StyleEngine::backgroundStyle () { +Style * StyleEngine::backgroundStyle (BrowserWindow *bw, DilloUrl *url) { if (!stack->getRef (stack->size () - 1)->backgroundStyle) { - StyleAttrs attrs = *style (); + StyleAttrs attrs = *style (bw, url); for (int i = stack->size () - 1; i >= 0 && ! attrs.backgroundColor; i--) attrs.backgroundColor = stack->getRef (i)->style->backgroundColor; @@ -746,7 +857,7 @@ 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 (int i) { +Style * StyleEngine::style0 (int i, BrowserWindow *bw, DilloUrl *url) { CssPropertyList props, *styleAttrProperties, *styleAttrPropertiesImportant; CssPropertyList *nonCssProperties; // get previous style from the stack @@ -774,7 +885,7 @@ Style * StyleEngine::style0 (int i) { nonCssProperties); // apply style - apply (i, &attrs, &props); + apply (i, &attrs, &props, bw, url); postprocessAttrs (&attrs); @@ -783,14 +894,20 @@ Style * StyleEngine::style0 (int i) { return stack->getRef (i)->style; } -Style * StyleEngine::wordStyle0 () { - StyleAttrs attrs = *style (); +Style * StyleEngine::wordStyle0 (BrowserWindow *bw, DilloUrl *url) { + StyleAttrs attrs = *style (bw, url); attrs.resetValues (); - if (stack->getRef (stack->size() - 1)->inheritBackgroundColor) - attrs.backgroundColor = style ()->backgroundColor; + if (stack->getRef (stack->size() - 1)->inheritBackgroundColor) { + attrs.backgroundColor = style (bw, url)->backgroundColor; + attrs.backgroundImage = style (bw, url)->backgroundImage; + attrs.backgroundRepeat = style (bw, url)->backgroundRepeat; + attrs.backgroundAttachment = style (bw, url)->backgroundAttachment; + attrs.backgroundPositionX = style (bw, url)->backgroundPositionX; + attrs.backgroundPositionY = style (bw, url)->backgroundPositionY; + } - attrs.valign = style ()->valign; + attrs.valign = style (bw, url)->valign; stack->getRef(stack->size() - 1)->wordStyle = Style::create(&attrs); return stack->getRef (stack->size () - 1)->wordStyle; @@ -803,7 +920,7 @@ Style * StyleEngine::wordStyle0 () { * and thereby after the HTML-element has been opened. * Note that restyle() does not change any styles in the widget tree. */ -void StyleEngine::restyle () { +void StyleEngine::restyle (BrowserWindow *bw, DilloUrl *url) { for (int i = 1; i < stack->size (); i++) { Node *n = stack->getRef (i); if (n->style) { @@ -819,7 +936,7 @@ void StyleEngine::restyle () { n->backgroundStyle = NULL; } - style0 (i); + style0 (i, bw, url); } } diff --git a/src/styleengine.hh b/src/styleengine.hh index 237008a6..714553ff 100644 --- a/src/styleengine.hh +++ b/src/styleengine.hh @@ -40,8 +40,8 @@ class StyleEngine { void stackPop (); void buildUserAgentStyle (); void buildUserStyle (); - dw::core::style::Style *style0 (int i); - dw::core::style::Style *wordStyle0 (); + dw::core::style::Style *style0 (int i, BrowserWindow *bw, DilloUrl *url); + dw::core::style::Style *wordStyle0 (BrowserWindow *bw, DilloUrl *url); inline void setNonCssHint(CssPropertyName name, CssValueType type, CssPropertyValue value) { Node *n = stack->getRef (stack->size () - 1); @@ -52,7 +52,8 @@ class StyleEngine { } 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); + void apply (int i, dw::core::style::StyleAttrs *attrs, + CssPropertyList *props, BrowserWindow *bw, DilloUrl *url); bool computeValue (int *dest, CssLength value, dw::core::style::Font *font); bool computeValue (int *dest, CssLength value, @@ -68,8 +69,8 @@ class StyleEngine { void parse (DilloHtml *html, DilloUrl *url, const char *buf, int buflen, CssOrigin origin); - void startElement (int tag); - void startElement (const char *tagname); + void startElement (int tag, BrowserWindow *bw, DilloUrl *url); + void startElement (const char *tagname, BrowserWindow *bw, DilloUrl *url); void setId (const char *id); const char * getId () { return doctree->top ()->id; }; void setClass (const char *klass); @@ -91,25 +92,32 @@ class StyleEngine { } void inheritNonCssHints (); void clearNonCssHints (); - void restyle (); + void restyle (BrowserWindow *bw, DilloUrl *url); void inheritBackgroundColor (); /* \todo get rid of this somehow */ - dw::core::style::Style *backgroundStyle (); + dw::core::style::Style *backgroundStyle (BrowserWindow *bw, + DilloUrl *url); dw::core::style::Color *backgroundColor (); + dw::core::style::StyleImage *backgroundImage + (dw::core::style::BackgroundRepeat *bgRepeat, + dw::core::style::BackgroundAttachment *bgAttachment, + dw::core::style::Length *bgPositionX, + dw::core::style::Length *bgPositionY); - inline dw::core::style::Style *style () { + inline dw::core::style::Style *style (BrowserWindow *bw, DilloUrl *url) { dw::core::style::Style *s = stack->getRef (stack->size () - 1)->style; if (s) return s; else - return style0 (stack->size () - 1); + return style0 (stack->size () - 1, bw, url); }; - inline dw::core::style::Style *wordStyle () { + inline dw::core::style::Style *wordStyle (BrowserWindow *bw, + DilloUrl *url) { dw::core::style::Style *s = stack->getRef(stack->size()-1)->wordStyle; if (s) return s; else - return wordStyle0 (); + return wordStyle0 (bw, url); }; }; diff --git a/src/table.cc b/src/table.cc index 15200516..a3002ebf 100644 --- a/src/table.cc +++ b/src/table.cc @@ -114,7 +114,7 @@ void Html_tag_open_table(DilloHtml *html, const char *tag, int tagsize) BUG_MSG("<table> bgcolor attribute is obsolete.\n"); } - html->styleEngine->style (); // evaluate now, so we can build non-css hints for the cells + html->style (); // evaluate now, so we can build non-css hints for the cells /* The style for the cells */ html->styleEngine->clearNonCssHints (); @@ -155,10 +155,10 @@ void Html_tag_content_table(DilloHtml *html, const char *tag, int tagsize) { dw::core::Widget *table; - HT2TB(html)->addParbreak (0, html->styleEngine->wordStyle ()); + HT2TB(html)->addParbreak (0, html->wordStyle ()); table = new dw::Table(prefs.limit_text_width); - HT2TB(html)->addWidget (table, html->styleEngine->style ()); - HT2TB(html)->addParbreak (0, html->styleEngine->wordStyle ()); + HT2TB(html)->addWidget (table, html->style ()); + HT2TB(html)->addParbreak (0, html->wordStyle ()); S_TOP(html)->table_mode = DILLO_HTML_TABLE_MODE_TOP; S_TOP(html)->table_border_mode = DILLO_HTML_TABLE_BORDER_SEPARATE; @@ -221,7 +221,7 @@ void Html_tag_content_tr(DilloHtml *html, const char *tag, int tagsize) case DILLO_HTML_TABLE_MODE_TOP: case DILLO_HTML_TABLE_MODE_TR: case DILLO_HTML_TABLE_MODE_TD: - ((dw::Table*)S_TOP(html)->table)->addRow (html->styleEngine->style ()); + ((dw::Table*)S_TOP(html)->table)->addRow (html->style ()); default: break; } @@ -302,10 +302,10 @@ static void Html_set_collapsing_border_model(DilloHtml *html, Widget *col_tb) int borderWidth, marginWidth; tableStyle = ((dw::Table*)S_TOP(html)->table)->getStyle (); - borderWidth = html->styleEngine->style ()->borderWidth.top; + borderWidth = html->style ()->borderWidth.top; marginWidth = tableStyle->margin.top; - collapseCellAttrs = *(html->styleEngine->style ()); + collapseCellAttrs = *(html->style ()); collapseCellAttrs.margin.setVal (0); collapseCellAttrs.borderWidth.left = 0; collapseCellAttrs.borderWidth.top = 0; @@ -344,7 +344,7 @@ 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 ()); + separateCellAttrs = *(html->style ()); /* CSS2 17.5: Internal table elements do not have margins */ separateCellAttrs.margin.setVal (0); separateStyle = Style::create(&separateCellAttrs); @@ -443,7 +443,7 @@ static void Html_tag_content_table_cell(DilloHtml *html, /* TODO: check errors? */ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "rowspan"))) rowspan = MAX(1, strtol (attrbuf, NULL, 10)); - if (html->styleEngine->style ()->textAlign + if (html->style ()->textAlign == TEXT_ALIGN_STRING) col_tb = new dw::TableCell ( ((dw::Table*)S_TOP(html)->table)->getCellRef (), @@ -451,7 +451,7 @@ static void Html_tag_content_table_cell(DilloHtml *html, else col_tb = new Textblock (prefs.limit_text_width); - if (html->styleEngine->style()->borderCollapse == BORDER_MODEL_COLLAPSE){ + if (html->style()->borderCollapse == BORDER_MODEL_COLLAPSE){ Html_set_collapsing_border_model(html, col_tb); } else { Html_set_separate_border_model(html, col_tb); diff --git a/src/uicmd.cc b/src/uicmd.cc index 84e7e4cd..4f737255 100644 --- a/src/uicmd.cc +++ b/src/uicmd.cc @@ -583,6 +583,9 @@ static BrowserWindow *UIcmd_tab_new(CustTabs *tabs, UI *old_ui, int focus) Layout *layout = new Layout (platform); style::Color *bgColor = style::Color::create (layout, prefs.bg_color); layout->setBgColor (bgColor); + layout->setBgImage (NULL, style::BACKGROUND_REPEAT, + style::BACKGROUND_ATTACHMENT_SCROLL, + style::createPerLength (0), style::createPerLength (0)); // set_render_layout() sets the proper viewport size FltkViewport *viewport = new FltkViewport (0, 0, 0, 1); @@ -67,16 +67,20 @@ int a_Web_dispatch_by_type (const char *Type, DilloWeb *Web, style::Color *bgColor = style::Color::create (layout, prefs.bg_color); Web->bgColor = bgColor->getColor (); layout->setBgColor (bgColor); + layout->setBgImage (NULL, style::BACKGROUND_REPEAT, + style::BACKGROUND_ATTACHMENT_SCROLL, + style::createPerLength (0), + style::createPerLength (0)); /* Set a style for the widget */ StyleEngine styleEngine (layout); - styleEngine.startElement ("body"); + styleEngine.startElement ("body", Web->bw, Web->url); dw = (Widget*) viewer(Type, Web, Call, Data); if (dw == NULL) return -1; - dw->setStyle (styleEngine.style ()); + dw->setStyle (styleEngine.style (Web->bw, Web->url)); /* This method frees the old dw if any */ layout->setWidget(dw); |