summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/css.hh10
-rw-r--r--src/cssparser.cc135
-rw-r--r--src/cssparser.hh3
-rw-r--r--src/dicache.c13
-rw-r--r--src/form.cc32
-rw-r--r--src/html.cc153
-rw-r--r--src/html_common.hh16
-rw-r--r--src/image.cc43
-rw-r--r--src/image.hh8
-rw-r--r--src/imgbuf.cc6
-rw-r--r--src/imgbuf.hh2
-rw-r--r--src/menu.cc20
-rw-r--r--src/plain.cc7
-rw-r--r--src/prefs.c1
-rw-r--r--src/prefs.h1
-rw-r--r--src/prefsparser.cc1
-rw-r--r--src/styleengine.cc149
-rw-r--r--src/styleengine.hh30
-rw-r--r--src/table.cc20
-rw-r--r--src/uicmd.cc3
-rw-r--r--src/web.cc8
21 files changed, 513 insertions, 148 deletions
diff --git a/src/css.hh b/src/css.hh
index 6b142827..29f0b24a 100644
--- a/src/css.hh
+++ b/src/css.hh
@@ -45,6 +45,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 +231,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 +293,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 eda45472..e31c4090 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
};
@@ -139,11 +147,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},
@@ -694,6 +705,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:
@@ -734,6 +754,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. */
@@ -1004,6 +1030,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/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 03bcb736..1257c102 100644
--- a/src/html.cc
+++ b/src/html.cc
@@ -360,9 +360,9 @@ static void Html_add_textblock(DilloHtml *html, int space)
{
Textblock *textblock = new Textblock (prefs.limit_text_width);
- HT2TB(html)->addParbreak (space, html->styleEngine->wordStyle ());
- HT2TB(html)->addWidget (textblock, html->styleEngine->style ());
- HT2TB(html)->addParbreak (space, html->styleEngine->wordStyle ());
+ HT2TB(html)->addParbreak (space, html->wordStyle ());
+ HT2TB(html)->addWidget (textblock, html->style ());
+ HT2TB(html)->addParbreak (space, html->wordStyle ());
S_TOP(html)->textblock = html->dw = textblock;
S_TOP(html)->hand_over_break = true;
}
@@ -1040,11 +1040,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 ());
}
}
@@ -1077,12 +1077,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;
@@ -1110,20 +1109,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)
@@ -1176,8 +1174,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;
}
@@ -1215,20 +1212,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)
@@ -1262,7 +1257,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;
}
@@ -1290,7 +1285,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);
}
@@ -1816,6 +1811,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))
@@ -1856,7 +1855,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);
@@ -1870,35 +1869,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());
}
@@ -1970,28 +1974,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);
}
@@ -2004,8 +2008,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);
}
@@ -2026,7 +2030,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 ());
}
/*
@@ -2215,7 +2219,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();
@@ -2292,13 +2298,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. */
@@ -2306,8 +2316,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);
}
}
@@ -2350,8 +2359,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;
}
@@ -2494,7 +2509,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);
}
@@ -2528,7 +2543,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
@@ -2637,7 +2652,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 ());
}
/*
@@ -2648,7 +2663,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 ());
}
/*
@@ -2690,7 +2705,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;
@@ -2750,7 +2765,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;
@@ -2845,12 +2860,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 ());
}
/*
@@ -2860,7 +2875,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 ());
}
/*
@@ -2869,7 +2884,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 ());
}
/*
@@ -2886,7 +2901,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;
}
@@ -3218,7 +3233,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 ());
}
/*
@@ -3226,7 +3241,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);
}
@@ -3661,8 +3676,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;
@@ -3746,7 +3761,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 */
@@ -3757,7 +3772,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;
@@ -3784,8 +3799,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 47bf6240..98b31d32 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;
@@ -706,9 +817,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;
@@ -725,7 +836,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
@@ -753,7 +864,7 @@ Style * StyleEngine::style0 (int i) {
nonCssProperties);
// apply style
- apply (i, &attrs, &props);
+ apply (i, &attrs, &props, bw, url);
postprocessAttrs (&attrs);
@@ -762,14 +873,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;
@@ -782,7 +899,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) {
@@ -798,7 +915,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);
diff --git a/src/web.cc b/src/web.cc
index fcc65af8..0a8ee710 100644
--- a/src/web.cc
+++ b/src/web.cc
@@ -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);