diff options
Diffstat (limited to 'render/box_construct.c')
-rw-r--r-- | render/box_construct.c | 997 |
1 files changed, 293 insertions, 704 deletions
diff --git a/render/box_construct.c b/render/box_construct.c index b8aa5e600..564a443c3 100644 --- a/render/box_construct.c +++ b/render/box_construct.c @@ -37,6 +37,8 @@ #include "utils/config.h" #include "content/content.h" #include "css/css.h" +#include "css/utils.h" +#include "css/select.h" #include "desktop/browser.h" #include "desktop/options.h" #include "render/box.h" @@ -82,59 +84,30 @@ static const content_type image_types[] = { #endif CONTENT_UNKNOWN }; -#define MAX_SPAN (100) - - /* the strings are not important, since we just compare the pointers */ const char *TARGET_SELF = "_self"; const char *TARGET_PARENT = "_parent"; const char *TARGET_TOP = "_top"; const char *TARGET_BLANK = "_blank"; -/* keeps track of markup presentation */ -struct markup_track { - enum { - ALIGN_NONE, - ALIGN_LEFT, - ALIGN_CENTER, - ALIGN_RIGHT - } align; - bool cell_border; - colour border_color; - - bool cell_padding; - long padding_width; - - bool table; -}; - static bool convert_xml_to_box(xmlNode *n, struct content *content, - struct css_style *parent_style, + const css_computed_style *parent_style, struct box *parent, struct box **inline_container, - char *href, const char *target, char *title, - struct markup_track markup_track, - struct css_importance *author); + char *href, const char *target, char *title); bool box_construct_element(xmlNode *n, struct content *content, - struct css_style *parent_style, + const css_computed_style *parent_style, struct box *parent, struct box **inline_container, - char *href, const char *target, char *title, - struct markup_track markup_track, - struct css_importance *author); + char *href, const char *target, char *title); bool box_construct_text(xmlNode *n, struct content *content, - struct css_style *parent_style, + const css_computed_style *parent_style, struct box *parent, struct box **inline_container, char *href, const char *target, char *title); -static struct css_style * box_get_style(struct content *c, - struct css_style *parent_style, - xmlNode *n, struct markup_track *markup_track, - struct css_importance *author); -static void box_solve_display(struct css_style *style, bool root); +static css_computed_style * box_get_style(struct content *c, + const css_computed_style *parent_style, xmlNode *n); static void box_text_transform(char *s, unsigned int len, - css_text_transform tt); + enum css_text_transform tt); #define BOX_SPECIAL_PARAMS xmlNode *n, struct content *content, \ - struct box *box, bool *convert_children, \ - struct markup_track markup_track, \ - struct css_importance *author + struct box *box, bool *convert_children static bool box_a(BOX_SPECIAL_PARAMS); static bool box_body(BOX_SPECIAL_PARAMS); static bool box_br(BOX_SPECIAL_PARAMS); @@ -157,8 +130,10 @@ static bool box_get_attribute(xmlNode *n, const char *attribute, void *context, char **value); static struct frame_dimension *box_parse_multi_lengths(const char *s, unsigned int *count); -static void parse_inline_colour(char *text, colour *variable); - +static bool fetch_object_interned_url(struct content *c, lwc_string *url, + struct box *box, const content_type *permitted_types, + int available_width, int available_height, + bool background); /* element_table must be sorted by name */ struct element_entry { @@ -195,12 +170,7 @@ static const struct element_entry element_table[] = { bool xml_to_box(xmlNode *n, struct content *c) { struct box root; - struct box *inline_container = 0; - struct css_importance author; - struct markup_track markup_track; - markup_track.cell_border = false; - markup_track.cell_padding = false; - markup_track.align = ALIGN_NONE; + struct box *inline_container = NULL; assert(c->type == CONTENT_HTML); @@ -214,20 +184,12 @@ bool xml_to_box(xmlNode *n, struct content *c) root.float_children = NULL; root.next_float = NULL; - c->data.html.style = talloc_memdup(c, &css_base_style, - sizeof css_base_style); - if (!c->data.html.style) - return false; - c->data.html.style->font_size.value.length.value = - option_font_size * 0.1; - /* and get the default font family from the options */ - c->data.html.style->font_family = option_font_default; - c->data.html.object_count = 0; c->data.html.object = 0; - if (!convert_xml_to_box(n, c, c->data.html.style, &root, - &inline_container, 0, 0, 0, markup_track, &author)) + /* The root box's style */ + if (!convert_xml_to_box(n, c, NULL, &root, + &inline_container, 0, 0, 0)) return false; if (!box_normalise_block(&root, c)) @@ -241,7 +203,7 @@ bool xml_to_box(xmlNode *n, struct content *c) /* mapping from CSS display to box type - * this table must be in sync with css/css_enums */ + * this table must be in sync with libcss' css_display enum */ static const box_type box_map[] = { 0, /*CSS_DISPLAY_INHERIT,*/ BOX_INLINE, /*CSS_DISPLAY_INLINE,*/ @@ -255,10 +217,11 @@ static const box_type box_map[] = { BOX_TABLE_ROW_GROUP, /*CSS_DISPLAY_TABLE_HEADER_GROUP,*/ BOX_TABLE_ROW_GROUP, /*CSS_DISPLAY_TABLE_FOOTER_GROUP,*/ BOX_TABLE_ROW, /*CSS_DISPLAY_TABLE_ROW,*/ - BOX_INLINE, /*CSS_DISPLAY_TABLE_COLUMN_GROUP,*/ - BOX_INLINE, /*CSS_DISPLAY_TABLE_COLUMN,*/ + BOX_NONE, /*CSS_DISPLAY_TABLE_COLUMN_GROUP,*/ + BOX_NONE, /*CSS_DISPLAY_TABLE_COLUMN,*/ BOX_TABLE_CELL, /*CSS_DISPLAY_TABLE_CELL,*/ - BOX_INLINE /*CSS_DISPLAY_TABLE_CAPTION,*/ + BOX_INLINE, /*CSS_DISPLAY_TABLE_CAPTION,*/ + BOX_NONE /*CSS_DISPLAY_NONE*/ }; @@ -267,31 +230,25 @@ static const box_type box_map[] = { * * \param n fragment of xml tree * \param content content of type CONTENT_HTML that is being processed - * \param parent_style style at this point in xml tree + * \param parent_style style at this point in xml tree, or NULL for root box * \param parent parent in box tree * \param inline_container current inline container box, or 0, updated to * new current inline container on exit * \param href current link URL, or 0 if not in a link * \param target current link target, or 0 if none * \param title current title, or 0 if none - * \param markup_track track presentation markup that affects descendents - * \param author denotes whether current style has author level - * importance for certain properties * \return true on success, false on memory exhaustion */ bool convert_xml_to_box(xmlNode *n, struct content *content, - struct css_style *parent_style, + const css_computed_style *parent_style, struct box *parent, struct box **inline_container, - char *href, const char *target, char *title, - struct markup_track markup_track, - struct css_importance *author) + char *href, const char *target, char *title) { switch (n->type) { case XML_ELEMENT_NODE: return box_construct_element(n, content, parent_style, parent, - inline_container, - href, target, title, markup_track, author); + inline_container, href, target, title); case XML_TEXT_NODE: return box_construct_text(n, content, parent_style, parent, inline_container, href, target, title); @@ -307,25 +264,20 @@ bool convert_xml_to_box(xmlNode *n, struct content *content, * * \param n XML node of type XML_ELEMENT_NODE * \param content content of type CONTENT_HTML that is being processed - * \param parent_style style at this point in xml tree + * \param parent_style style at this point in xml tree, or NULL for root node * \param parent parent in box tree * \param inline_container current inline container box, or 0, updated to * new current inline container on exit * \param href current link URL, or 0 if not in a link * \param target current link target, or 0 if none * \param title current title, or 0 if none - * \param markup_track track presentation markup that affects descendents - * \param author denotes whether current style has author level - * importance for certain properties * \return true on success, false on memory exhaustion */ bool box_construct_element(xmlNode *n, struct content *content, - struct css_style *parent_style, + const css_computed_style *parent_style, struct box *parent, struct box **inline_container, - char *href, const char *target, char *title, - struct markup_track markup_track, - struct css_importance *author) + char *href, const char *target, char *title) { bool convert_children = true; char *id = 0; @@ -333,14 +285,14 @@ bool box_construct_element(xmlNode *n, struct content *content, struct box *box = 0; struct box *inline_container_c; struct box *inline_end; - struct css_style *style = 0; + css_computed_style *style = 0; struct element_entry *element; xmlChar *title0; xmlNode *c; + lwc_string *bgimage_uri; assert(n); assert(n->type == XML_ELEMENT_NODE); - assert(parent_style); assert(parent); assert(inline_container); @@ -352,18 +304,23 @@ bool box_construct_element(xmlNode *n, struct content *content, */ parent->strip_leading_newline = 0; - style = box_get_style(content, parent_style, n, &markup_track, author); + style = box_get_style(content, parent_style, n); if (!style) return false; /* extract title attribute, if present */ if ((title0 = xmlGetProp(n, (const xmlChar *) "title"))) { char *title1 = squash_whitespace((char *) title0); + xmlFree(title0); + if (!title1) return false; + title = talloc_strdup(content, title1); + free(title1); + if (!title) return false; } @@ -376,8 +333,25 @@ bool box_construct_element(xmlNode *n, struct content *content, box = box_create(style, href, target, title, id, content); if (!box) return false; - /* set box type from style */ - box->type = box_map[style->display]; + /* set box type from computed display */ + if ((css_computed_position(style) == CSS_POSITION_ABSOLUTE || + css_computed_position(style) == CSS_POSITION_FIXED) && + (css_computed_display_static(style) == + CSS_DISPLAY_INLINE || + css_computed_display_static(style) == + CSS_DISPLAY_INLINE_BLOCK || + css_computed_display_static(style) == + CSS_DISPLAY_INLINE_TABLE)) { + /* Special case for absolute positioning: make absolute inlines + * into inline block so that the boxes are constructed in an + * inline container as if they were not absolutely positioned. + * Layout expects and handles this. */ + box->type = box_map[CSS_DISPLAY_INLINE_BLOCK]; + } else { + /* Normal mapping */ + box->type = box_map[css_computed_display(style, + n->parent == NULL)]; + } /* special elements */ element = bsearch((const char *) n->name, element_table, @@ -385,16 +359,17 @@ bool box_construct_element(xmlNode *n, struct content *content, (int (*)(const void *, const void *)) strcmp); if (element) { /* a special convert function exists for this element */ - if (!element->convert(n, content, box, &convert_children, - markup_track, author)) + if (!element->convert(n, content, box, &convert_children)) return false; + href = box->href; target = box->target; } - if (style->display == CSS_DISPLAY_NONE) { + if (box->type == BOX_NONE || css_computed_display(box->style, + n->parent == NULL) == CSS_DISPLAY_NONE) { /* Free style and invalidate box's style pointer */ - talloc_free(style); + css_computed_style_destroy(style); box->style = NULL; /* If this box has an associated gadget, invalidate the @@ -416,60 +391,71 @@ bool box_construct_element(xmlNode *n, struct content *content, (box->type == BOX_INLINE || box->type == BOX_BR || box->type == BOX_INLINE_BLOCK || - style->float_ == CSS_FLOAT_LEFT || - style->float_ == CSS_FLOAT_RIGHT)) { + css_computed_float(style) == CSS_FLOAT_LEFT || + css_computed_float(style) == CSS_FLOAT_RIGHT)) { /* this is the first inline in a block: make a container */ *inline_container = box_create(0, 0, 0, 0, 0, content); if (!*inline_container) return false; + (*inline_container)->type = BOX_INLINE_CONTAINER; + box_add_child(parent, *inline_container); } if (box->type == BOX_INLINE || box->type == BOX_BR) { /* inline box: add to tree and recurse */ box_add_child(*inline_container, box); + if (convert_children && n->children) { for (c = n->children; c; c = c->next) if (!convert_xml_to_box(c, content, style, parent, inline_container, - href, target, title, - markup_track, author)) + href, target, title)) return false; + inline_end = box_create(style, href, target, title, id, content); if (!inline_end) return false; + inline_end->type = BOX_INLINE_END; + if (*inline_container) box_add_child(*inline_container, inline_end); else box_add_child(box->parent, inline_end); + box->inline_end = inline_end; inline_end->inline_end = box; } } else if (box->type == BOX_INLINE_BLOCK) { /* inline block box: add to tree and recurse */ box_add_child(*inline_container, box); + inline_container_c = 0; + for (c = n->children; convert_children && c; c = c->next) if (!convert_xml_to_box(c, content, style, box, &inline_container_c, - href, target, title, markup_track, - author)) + href, target, title)) return false; } else { /* list item: compute marker, then treat as non-inline box */ - if (style->display == CSS_DISPLAY_LIST_ITEM) { + if (css_computed_display(style, n->parent == NULL) == + CSS_DISPLAY_LIST_ITEM) { + lwc_string *image_uri; struct box *marker; + marker = box_create(style, 0, 0, title, 0, content); if (!marker) return false; + marker->type = BOX_BLOCK; + /** \todo marker content (list-style-type) */ - switch (style->list_style_type) { + switch (css_computed_list_style_type(style)) { case CSS_LIST_STYLE_TYPE_DISC: - default: /* 2022 BULLET */ marker->text = (char *) "\342\200\242"; marker->length = 3; @@ -489,6 +475,7 @@ bool box_construct_element(xmlNode *n, struct content *content, case CSS_LIST_STYLE_TYPE_LOWER_ROMAN: case CSS_LIST_STYLE_TYPE_UPPER_ALPHA: case CSS_LIST_STYLE_TYPE_UPPER_ROMAN: + default: if (parent->last) { struct box *last = parent->last; @@ -515,9 +502,11 @@ bool box_construct_element(xmlNode *n, struct content *content, list_marker->rows + 1; } } + marker->text = talloc_array(content, char, 20); if (!marker->text) return false; + snprintf(marker->text, 20, "%u.", marker->rows); marker->length = strlen(marker->text); break; @@ -526,43 +515,50 @@ bool box_construct_element(xmlNode *n, struct content *content, marker->length = 0; break; } - if (style->list_style_image.type == - CSS_LIST_STYLE_IMAGE_URI) { - if (!html_fetch_object(content, - style->list_style_image.uri, + + if (css_computed_list_style_image(style, &image_uri) == + CSS_LIST_STYLE_IMAGE_URI && + image_uri != NULL) { + if (!fetch_object_interned_url(content, + image_uri, marker, 0, content->available_width, 1000, false)) return false; } + box->list_marker = marker; marker->parent = box; } /* float: insert a float box between the parent and * current node. Note: new parent will be the float */ - if (style->float_ == CSS_FLOAT_LEFT || - style->float_ == CSS_FLOAT_RIGHT) { + if (css_computed_float(style) == CSS_FLOAT_LEFT || + css_computed_float(style) == CSS_FLOAT_RIGHT) { parent = box_create(0, href, target, title, 0, content); if (!parent) return false; - if (style->float_ == CSS_FLOAT_LEFT) + + if (css_computed_float(style) == CSS_FLOAT_LEFT) parent->type = BOX_FLOAT_LEFT; else parent->type = BOX_FLOAT_RIGHT; + box_add_child(*inline_container, parent); } /* non-inline box: add to tree and recurse */ box_add_child(parent, box); + inline_container_c = 0; + for (c = n->children; convert_children && c; c = c->next) if (!convert_xml_to_box(c, content, style, box, &inline_container_c, - href, target, title, markup_track, - author)) + href, target, title)) return false; - if (style->float_ == CSS_FLOAT_NONE) + + if (css_computed_float(style) == CSS_FLOAT_NONE) /* new inline container unless this is a float */ *inline_container = 0; } @@ -571,23 +567,23 @@ bool box_construct_element(xmlNode *n, struct content *content, if ((s = (char *) xmlGetProp(n, (const xmlChar *) "colspan"))) { if (isdigit(s[0])) { box->columns = strtol(s, NULL, 10); - if ((MAX_SPAN < box->columns) || (box->columns < 1)) - box->columns = 1; } xmlFree(s); } + if ((s = (char *) xmlGetProp(n, (const xmlChar *) "rowspan"))) { if (isdigit(s[0])) { box->rows = strtol(s, NULL, 10); - if ((MAX_SPAN < box->rows) || (box->rows < 1)) - box->rows = 1; } xmlFree(s); } /* fetch any background image for this box */ - if (style->background_image.type == CSS_BACKGROUND_IMAGE_URI) { - if (!html_fetch_object(content, style->background_image.uri, + if (css_computed_background_image(style, &bgimage_uri) == + CSS_BACKGROUND_IMAGE_IMAGE && + bgimage_uri != NULL) { + if (!fetch_object_interned_url(content, + bgimage_uri, box, image_types, content->available_width, 1000, true)) return false; @@ -613,7 +609,7 @@ bool box_construct_element(xmlNode *n, struct content *content, */ bool box_construct_text(xmlNode *n, struct content *content, - struct css_style *parent_style, + const css_computed_style *parent_style, struct box *parent, struct box **inline_container, char *href, const char *target, char *title) { @@ -625,8 +621,9 @@ bool box_construct_text(xmlNode *n, struct content *content, assert(parent); assert(inline_container); - if (parent_style->white_space == CSS_WHITE_SPACE_NORMAL || - parent_style->white_space == CSS_WHITE_SPACE_NOWRAP) { + if (css_computed_white_space(parent_style) == CSS_WHITE_SPACE_NORMAL || + css_computed_white_space(parent_style) == + CSS_WHITE_SPACE_NOWRAP) { char *text = squash_whitespace((char *) n->content); if (!text) return false; @@ -643,10 +640,14 @@ bool box_construct_text(xmlNode *n, struct content *content, parent = parent->parent; box_dump(stderr, parent, 0); } + assert((*inline_container)->last != 0); + (*inline_container)->last->space = 1; } + free(text); + return true; } @@ -657,34 +658,48 @@ bool box_construct_text(xmlNode *n, struct content *content, free(text); return false; } + (*inline_container)->type = BOX_INLINE_CONTAINER; + box_add_child(parent, *inline_container); } - box = box_create(parent_style, href, target, title, 0, content); + /** \todo Dropping const here is not clever */ + box = box_create((css_computed_style *) parent_style, + href, target, title, 0, content); if (!box) { free(text); return false; } + box->type = BOX_TEXT; + box->text = talloc_strdup(content, text); free(text); if (!box->text) return false; + box->length = strlen(box->text); + /* strip ending space char off */ if (box->length > 1 && box->text[box->length - 1] == ' ') { box->space = 1; box->length--; } - if (parent_style->text_transform != CSS_TEXT_TRANSFORM_NONE) + + if (css_computed_text_transform(parent_style) != + CSS_TEXT_TRANSFORM_NONE) box_text_transform(box->text, box->length, - parent_style->text_transform); - if (parent_style->white_space == CSS_WHITE_SPACE_NOWRAP) { + css_computed_text_transform(parent_style)); + + if (css_computed_white_space(parent_style) == + CSS_WHITE_SPACE_NOWRAP) { unsigned int i; + for (i = 0; i != box->length && box->text[i] != ' '; ++i) ; /* no body */ + if (i != box->length) { /* there is a space in text block and we * want all spaces to be converted to NBSP @@ -699,9 +714,12 @@ bool box_construct_text(xmlNode *n, struct content *content, } box_add_child(*inline_container, box); + if (box->text[0] == ' ') { box->length--; + memmove(box->text, &box->text[1], box->length); + if (box->prev != NULL) box->prev->space = 1; } @@ -710,17 +728,22 @@ bool box_construct_text(xmlNode *n, struct content *content, /* white-space: pre */ char *text = cnv_space2nbsp((char *) n->content); char *current; + enum css_white_space white_space = + css_computed_white_space(parent_style); + /* note: pre-wrap/pre-line are unimplemented */ - assert(parent_style->white_space == CSS_WHITE_SPACE_PRE || - parent_style->white_space == - CSS_WHITE_SPACE_PRE_LINE || - parent_style->white_space == - CSS_WHITE_SPACE_PRE_WRAP); + assert(white_space == CSS_WHITE_SPACE_PRE || + white_space == CSS_WHITE_SPACE_PRE_LINE || + white_space == CSS_WHITE_SPACE_PRE_WRAP); + if (!text) return false; - if (parent_style->text_transform != CSS_TEXT_TRANSFORM_NONE) + + if (css_computed_text_transform(parent_style) != + CSS_TEXT_TRANSFORM_NONE) box_text_transform(text, strlen(text), - parent_style->text_transform); + css_computed_text_transform(parent_style)); + current = text; /* swallow a single leading new line */ @@ -739,7 +762,9 @@ bool box_construct_text(xmlNode *n, struct content *content, do { size_t len = strcspn(current, "\r\n"); char old = current[len]; + current[len] = 0; + if (!*inline_container) { *inline_container = box_create(0, 0, 0, 0, 0, content); @@ -747,26 +772,37 @@ bool box_construct_text(xmlNode *n, struct content *content, free(text); return false; } + (*inline_container)->type = BOX_INLINE_CONTAINER; + box_add_child(parent, *inline_container); } - box = box_create(parent_style, href, target, title, 0, - content); + + /** \todo Dropping const isn't clever */ + box = box_create((css_computed_style *) parent_style, + href, target, title, 0, content); if (!box) { free(text); return false; } + box->type = BOX_TEXT; + box->text = talloc_strdup(content, current); if (!box->text) { free(text); return false; } + box->length = strlen(box->text); + box_add_child(*inline_container, box); + current[len] = old; + current += len; + if (current[0] == '\r' && current[1] == '\n') { current += 2; *inline_container = 0; @@ -775,6 +811,7 @@ bool box_construct_text(xmlNode *n, struct content *content, *inline_container = 0; } } while (*current); + free(text); } @@ -782,524 +819,69 @@ bool box_construct_text(xmlNode *n, struct content *content, } +static void *myrealloc(void *ptr, size_t len, void *pw) +{ + return talloc_realloc_size(pw, ptr, len); +} + /** * Get the style for an element. * * \param c content of type CONTENT_HTML that is being processed - * \param parent_style style at this point in xml tree + * \param parent_style style at this point in xml tree, or NULL for root * \param n node in xml tree - * \param markup_track track presentation markup that affects descendents - * \param author denotes whether current style has author level - * importance for certain properties - * \return the new style, or 0 on memory exhaustion - * - * The style is collected from three sources: - * 1. any styles for this element in the document stylesheet(s) - * 2. the 'style' attribute - * 3. non-CSS HTML attributes (subject to importance of CSS style properties) + * \return the new style, or NULL on memory exhaustion */ - -struct css_style * box_get_style(struct content *c, - struct css_style *parent_style, - xmlNode *n, struct markup_track *markup_track, - struct css_importance *author) +css_computed_style *box_get_style(struct content *c, + const css_computed_style *parent_style, + xmlNode *n) { char *s; - struct css_style *style; - struct css_style *style_new; - char *url; - url_func_result res; - colour border_color = 0x888888; /* mid-grey default for tables */ - - /* if not in a table, switch off cellpadding and cell borders - * and record that we're not in a table */ - if (strcmp((const char *) n->name, "thead") != 0 && - strcmp((const char *) n->name, "tbody") != 0 && - strcmp((const char *) n->name, "tfoot") != 0 && - strcmp((const char *) n->name, "tr") != 0 && - strcmp((const char *) n->name, "td") != 0 && - strcmp((const char *) n->name, "th") != 0 && - strcmp((const char *) n->name, "col") != 0 && - strcmp((const char *) n->name, "colgroup") != 0) { - markup_track->cell_border = false; - markup_track->cell_padding = false; - markup_track->table = false; - } - - style = talloc_memdup(c, parent_style, sizeof *style); - if (!style) - return 0; - - style_new = talloc_memdup(c, &css_blank_style, sizeof *style_new); - if (!style_new) - return 0; - css_get_style(c->data.html.working_stylesheet, n, style_new, author); - css_cascade(style, style_new, NULL); + css_stylesheet *inline_style = NULL; + css_computed_style *partial; + css_computed_style *style; - /* style_new isn't needed past this point */ - talloc_free(style_new); - - /* Handle style attribute. (style attribute values have high enough - * specificity to override existing style data.) */ + /* Firstly, construct inline stylesheet, if any */ if ((s = (char *) xmlGetProp(n, (const xmlChar *) "style"))) { - struct css_style *astyle; - astyle = css_duplicate_style(&css_empty_style); - if (!astyle) { - xmlFree(s); - return 0; - } - css_parse_property_list(c, astyle, s); - css_cascade(style, astyle, author); - css_free_style(astyle); - xmlFree(s); - } - - /* Apply presentational HTML attributes to style - * (Only apply if style property does not have "author" level - * importance or higher.) - */ - - /* This property only applies to the body element, if you believe - * the spec. Many browsers seem to allow it on other elements too, - * so let's be generic ;) */ - if (!author->background_image && (s = (char *) xmlGetProp(n, - (const xmlChar *) "background"))) { - res = url_join(s, c->data.html.base_url, &url); - xmlFree(s); - if (res == URL_FUNC_NOMEM) { - return 0; - } else if (res == URL_FUNC_OK) { - /* if url is equivalent to the parent's url, - * we've got infinite inclusion: ignore */ - if (strcmp(url, c->data.html.base_url) == 0) - free(url); - else { - style->background_image.type = - CSS_BACKGROUND_IMAGE_URI; - style->background_image.uri = talloc_strdup( - c, url); - free(url); - if (!style->background_image.uri) - return 0; - } - } - } - - if (!author->background_color && (s = (char *) xmlGetProp(n, - (const xmlChar *) "bgcolor"))) { - parse_inline_colour(s, &style->background_color); - xmlFree(s); - } - - if (!author->color && (s = (char *) xmlGetProp(n, - (const xmlChar *) "color"))) { - parse_inline_colour(s, &style->color); - xmlFree(s); - } - - if (!author->height && (s = (char *) xmlGetProp(n, - (const xmlChar *) "height")) && - ((strcmp((const char *) n->name, "iframe") == 0) || - (strcmp((const char *) n->name, "td") == 0) || - (strcmp((const char *) n->name, "th") == 0) || - (strcmp((const char *) n->name, "tr") == 0) || - (strcmp((const char *) n->name, "img") == 0) || - (strcmp((const char *) n->name, "object") == 0) || - (strcmp((const char *) n->name, "applet") == 0))) { - float value = isdigit(s[0]) ? atof(s) : -1; - if (value <= 0 || strlen(s) == 0) { - /* ignore negative values and height="" */ - } else if (strrchr(s, '%')) { - style->height.height = CSS_HEIGHT_PERCENT; - style->height.value.percent = value; - } else { - style->height.height = CSS_HEIGHT_LENGTH; - style->height.value.length.unit = CSS_UNIT_PX; - style->height.value.length.value = value; - } - xmlFree(s); - } - - if (!author->width && strcmp((const char *) n->name, "input") == 0) { - int size = -1; - if ((s = (char *) xmlGetProp(n, (const xmlChar *) "size"))) { - size = isdigit(s[0]) ? atoi(s): -1; - if (0 < size) { - char *type = (char *) xmlGetProp(n, - (const xmlChar *) "type"); - style->width.width = CSS_WIDTH_LENGTH; - if (!type || strcasecmp(type, "text") == 0 || - strcasecmp(type, "password") == 0) - /* in characters for text, password */ - style->width.value.length.unit = - CSS_UNIT_EX; - else if (strcasecmp(type, "file") != 0) - /* in pixels otherwise; ignore width - * on file, because we do them - * differently to most browsers */ - style->width.value.length.unit = - CSS_UNIT_PX; - style->width.value.length.value = size; - if (type) - xmlFree(type); - } - xmlFree(s); - } - /* If valid maxlength value is provided, the size attribute is - * unset and maxlength is small, use it to reduce input width - * to sensible size */ - if ((s = (char *) xmlGetProp(n, (const xmlChar *) - "maxlength"))) { - int maxlength = isdigit(s[0]) ? atoi(s): -1; - if (0 < maxlength && size == -1 && maxlength < 10) { - char *type; - /* Bump up really small widths */ - maxlength = maxlength < 5 ? maxlength + 1 : - maxlength; - type = (char *) xmlGetProp(n, - (const xmlChar *) "type"); - style->width.width = CSS_WIDTH_LENGTH; - if (!type || strcasecmp(type, "text") == 0 || - strcasecmp(type, "password") == 0) - /* in characters for text, password */ - style->width.value.length.unit = - CSS_UNIT_EX; - style->width.value.length.value = maxlength; - if (type) - xmlFree(type); - } - xmlFree(s); - } - } + inline_style = nscss_create_inline_style( + (uint8_t *) s, strlen(s), + c->data.html.encoding, c->url, false, + c->data.html.dict, myrealloc, c); - if (!author->color && strcmp((const char *) n->name, "body") == 0) { - if ((s = (char *) xmlGetProp(n, (const xmlChar *) "text"))) { - parse_inline_colour(s, &style->color); - xmlFree(s); - } - } - - if (!author->width && (s = (char *) xmlGetProp(n, - (const xmlChar *) "width")) && - ((strcmp((const char *) n->name, "hr") == 0) || - (strcmp((const char *) n->name, "iframe") == 0) || - (strcmp((const char *) n->name, "img") == 0) || - (strcmp((const char *) n->name, "object") == 0) || - (strcmp((const char *) n->name, "table") == 0) || - (strcmp((const char *) n->name, "td") == 0) || - (strcmp((const char *) n->name, "th") == 0) || - (strcmp((const char *) n->name, "applet") == 0))) { - float value = isdigit(s[0]) ? atof(s) : -1; - if (value < 0 || strlen(s) == 0) { - /* ignore negative values and width="" */ - } else if (strrchr(s, '%')) { - style->width.width = CSS_WIDTH_PERCENT; - style->width.value.percent = value; - } else { - style->width.width = CSS_WIDTH_LENGTH; - style->width.value.length.unit = CSS_UNIT_PX; - style->width.value.length.value = value; - } xmlFree(s); - } - - if (strcmp((const char *) n->name, "textarea") == 0) { - if (!author->height && (s = (char *) xmlGetProp(n, - (const xmlChar *) "rows"))) { - int value = isdigit(s[0]) ? atoi(s): -1; - if (0 < value) { - style->height.height = CSS_HEIGHT_LENGTH; - style->height.value.length.unit = CSS_UNIT_EM; - style->height.value.length.value = value; - } - xmlFree(s); - } - if (!author->width && (s = (char *) xmlGetProp(n, - (const xmlChar *) "cols"))) { - int value = isdigit(s[0]) ? atoi(s): -1; - if (0 < value) { - style->width.width = CSS_WIDTH_LENGTH; - style->width.value.length.unit = CSS_UNIT_EX; - style->width.value.length.value = value; - } - xmlFree(s); - } - } - - if (strcmp((const char *) n->name, "table") == 0) { - if (!author->border_spacing && (s = (char *) xmlGetProp(n, - (const xmlChar *) "cellspacing"))) { - /* percentage cellspacing not implemented */ - if (!strrchr(s, '%')) { - int value = isdigit(s[0]) ? atoi(s): -1; - if (0 <= value) { - style->border_spacing.border_spacing = - CSS_BORDER_SPACING_LENGTH; - style->border_spacing.horz.unit = - style->border_spacing.vert.unit = - CSS_UNIT_PX; - style->border_spacing.horz.value = - style->border_spacing.vert.value = - value; - } - } - xmlFree(s); - } - - if ((s = (char *) xmlGetProp(n, - (const xmlChar *) "bordercolor"))) { - parse_inline_colour(s, &border_color); - xmlFree(s); - } - if ((s = (char *) xmlGetProp(n, - (const xmlChar *) "border"))) { - int border_width = atoi(s); - /* precentage border width not implemented */ - if (!strrchr(s, '%') && 0 < border_width) { - unsigned int i; - for (i = 0; i != 4; i++) { - if (!author->border_color[i]) - style->border[i].color = - border_color; - if (!author->border_width[i]) { - style->border[i].width.width = - CSS_BORDER_WIDTH_LENGTH; - style->border[i].width.value. - value = border_width; - style->border[i].width.value. - unit = CSS_UNIT_PX; - } - if (!author->border_style[i]) - style->border[i].style = - CSS_BORDER_STYLE_OUTSET; - } - } - xmlFree(s); - } - } - if (strcmp((const char *) n->name, "td") == 0 || - strcmp((const char *) n->name, "th") == 0) { - /* set any cellborders stipulated by associated table */ - if (markup_track->cell_border) { - unsigned int i; - for (i = 0; i != 4; i++) { - if (!author->border_color[i]) - style->border[i].color = markup_track-> - border_color; - if (!author->border_width[i]) { - style->border[i].width.width = - CSS_BORDER_WIDTH_LENGTH; - style->border[i].width.value.value = 1; - style->border[i].width.value.unit = - CSS_UNIT_PX; - } - if (!author->border_style[i]) - style->border[i].style = - CSS_BORDER_STYLE_INSET; - } - } - /* set any cellpadding stipulated by associated table */ - if (markup_track->cell_padding) { - unsigned int i; - for (i = 0; i != 4; i++) { - if (!author->padding[i]) { - style->padding[i].padding = - CSS_PADDING_LENGTH; - style->padding[i].value.length.value = - markup_track->padding_width; - style->padding[i].value.length.unit = - CSS_UNIT_PX; - } - } - } + if (inline_style == NULL) + return NULL; } - if ((strcmp((const char *) n->name, "img") == 0) || - (strcmp((const char *) n->name, "image") == 0) || - (strcmp((const char *) n->name, "applet") == 0)) { - if ((s = (char *) xmlGetProp(n, - (const xmlChar *) "hspace"))) { - /* percentage hspace not implemented */ - if (!strrchr(s, '%')) { - int value = isdigit(s[0]) ? atoi(s): -1; - if (0 <= value && !author->margin[LEFT]) { - style->margin[LEFT].margin = - CSS_MARGIN_LENGTH; - style->margin[LEFT].value.length.value = - value; - style->margin[LEFT].value.length.unit = - CSS_UNIT_PX; - } - if (0 <= value && !author->margin[RIGHT]) { - style->margin[RIGHT].margin = - CSS_MARGIN_LENGTH; - style->margin[RIGHT].value.length. - value = value; - style->margin[RIGHT].value.length.unit = - CSS_UNIT_PX; - } - } - xmlFree(s); - } - if ((s = (char *) xmlGetProp(n, - (const xmlChar *) "vspace"))) { - /* percentage vspace not implemented */ - if (!strrchr(s, '%')) { - int value = isdigit(s[0]) ? atoi(s): -1; - if (0 <= value && !author->margin[TOP]) { - style->margin[TOP].margin = - CSS_MARGIN_LENGTH; - style->margin[TOP].value.length.value = - value; - style->margin[TOP].value.length.unit = - CSS_UNIT_PX; - } - if (0 <= value && !author->margin[BOTTOM]) { - style->margin[BOTTOM].margin = - CSS_MARGIN_LENGTH; - style->margin[BOTTOM].value.length. - value = value; - style->margin[BOTTOM].value.length. - unit = CSS_UNIT_PX; - } - } - xmlFree(s); - } - } + /* Select partial style for element */ + partial = nscss_get_style(c, n, CSS_PSEUDO_ELEMENT_NONE, + CSS_MEDIA_SCREEN, inline_style, myrealloc, c); - /* Handle markup-originating alignment of block level elements. - * Adjust left and right margins. text-align property is handled in - * the default CSS file. - */ - if (markup_track->align != ALIGN_NONE && - (style->display == CSS_DISPLAY_BLOCK || - style->display == CSS_DISPLAY_TABLE) && - (strcmp((const char *) n->name, "blockquote") != 0)) { - if (!author->margin[LEFT]) { - if (markup_track->align == ALIGN_LEFT) { - /* left */ - style->margin[LEFT].margin = CSS_MARGIN_LENGTH; - style->margin[LEFT].value.length.value = 0; - style->margin[LEFT].value.length.unit = - CSS_UNIT_PX; - } else - /* center or right */ - style->margin[LEFT].margin = CSS_MARGIN_AUTO; - } - - if (!author->margin[RIGHT]) { - if (markup_track->align == ALIGN_RIGHT) { - /* right */ - style->margin[RIGHT].margin = CSS_MARGIN_LENGTH; - style->margin[RIGHT].value.length.value= 0; - style->margin[RIGHT].value.length.unit = - CSS_UNIT_PX; - } else - /* left or center */ - style->margin[RIGHT].margin = CSS_MARGIN_AUTO; - } - if (author->margin[LEFT] || author->margin[RIGHT]) { - /* author stylesheet sets a margin so stop markup - * alignment model propagation */ - markup_track->align = ALIGN_NONE; - } - } - /* Centered tables are a special case. The align attribute only - * affects the current element (table) and overrides any existing - * HTML alignment rule. Tables aligned to left or right are floated - * by the default CSS file. */ - if (!author->margin[LEFT] && !author->margin[RIGHT] && - strcmp((const char *) n->name, "table") == 0) { - if ((s = (char *) xmlGetProp(n, - (const xmlChar *) "align"))) { - if (strcasecmp(s, "center") == 0) { - style->margin[LEFT].margin = CSS_MARGIN_AUTO; - style->margin[RIGHT].margin = CSS_MARGIN_AUTO; - } - xmlFree(s); - } - } + /* No longer need inline style */ + if (inline_style != NULL) + css_stylesheet_destroy(inline_style); - box_solve_display(style, !n->parent); + /* Failed selecting partial style -- bail out */ + if (partial == NULL) + return NULL; - /* Update markup_track with attributes which affect children of - * current box. */ + /* If there's a parent style, compose with partial to obtain + * complete computed style for element */ + if (parent_style != NULL) { + css_error error; - /* Handle html block level element alignment model. - * Note that only margins of block level children are considered, - * text-align for the current block can be handled in the default - * CSS file. - */ - if (strcmp((const char *) n->name, "center") == 0) - markup_track->align = ALIGN_CENTER; - else if (strcmp((const char *) n->name, "div") == 0 || - strcmp((const char *) n->name, "col") == 0 || - strcmp((const char *) n->name, "colgroup") == 0 || - strcmp((const char *) n->name, "tbody") == 0 || - strcmp((const char *) n->name, "td") == 0 || - strcmp((const char *) n->name, "tfoot") == 0 || - strcmp((const char *) n->name, "th") == 0 || - strcmp((const char *) n->name, "thead") == 0 || - strcmp((const char *) n->name, "tr") == 0) { - - if ((s = (char *) xmlGetProp(n, (const xmlChar *) "align"))) { - if (strcasecmp(s, "center") == 0) - markup_track->align = ALIGN_CENTER; - else if (strcasecmp(s, "right") == 0) - markup_track->align = ALIGN_RIGHT; - else if (strcasecmp(s, "left") == 0) - markup_track->align = ALIGN_LEFT; - xmlFree(s); - /* Need to remember if we're in a table, so that any - * alignment rules set on the table's elements won't - * get overridden by the default alignment of a cell - * with no align attribute. At this point, we're in a - * table if the element isn't a div */ - if (strcmp((const char *) n->name, "div") != 0) - markup_track->table = true; + error = css_computed_style_compose(parent_style, partial, + nscss_compute_font_size, NULL, partial); + if (error != CSS_OK) { + css_computed_style_destroy(partial); + return NULL; } - } - /* Table cells without an align value have a default implied - * alignment. */ - if (strcmp((const char *) n->name, "td") == 0 && !markup_track->table) { - if (!(s = (char *) xmlGetProp(n, (const xmlChar *) "align"))) - markup_track->align = ALIGN_LEFT; - else - xmlFree(s); - } - if (strcmp((const char *) n->name, "th") == 0 && !markup_track->table) { - if (!(s = (char *) xmlGetProp(n, (const xmlChar *) "align"))) - markup_track->align = ALIGN_CENTER; - else - xmlFree(s); - } - /* Some of TABLE's attributes apply to the table cells contained - * within the table. Those details are stored so they may be applied - * to the cells when we get to them. */ - if (strcmp((const char *) n->name, "table") == 0) { - if ((s = (char *) xmlGetProp(n, - (const xmlChar *) "cellpadding"))) { - char *endp; - long value = strtol(s, &endp, 10); - /* precentage padding width not implemented */ - if (*endp == 0 && 0 <= value && value < 1000) { - markup_track->padding_width = value; - markup_track->cell_padding = true; - } - xmlFree(s); - } - if ((s = (char *) xmlGetProp(n, - (const xmlChar *) "border"))) { - int border_width = atoi(s); - markup_track->border_color = border_color; - /* percentage border width not implemented */ - if (!strrchr(s, '%') && 0 < border_width) { - markup_track->cell_border = true; - } - xmlFree(s); - } + style = partial; + } else { + /* No parent style, so partial must be fully computed */ + style = partial; } return style; @@ -1307,52 +889,6 @@ struct css_style * box_get_style(struct content *c, /** - * Calculate 'display' based on 'display', 'position', and 'float', as given - * by CSS 2.1 9.7. - * - * \param style style to update - * \param root this is the root element - */ - -void box_solve_display(struct css_style *style, bool root) -{ - if (style->display == CSS_DISPLAY_NONE) /* 1. */ - return; - else if (style->position == CSS_POSITION_ABSOLUTE || - style->position == CSS_POSITION_FIXED) /* 2. */ - style->float_ = CSS_FLOAT_NONE; - else if (style->float_ != CSS_FLOAT_NONE) /* 3. */ - ; - else if (root) /* 4. */ - ; - else /* 5. */ - return; - - /* Special case for absolute positioning: make absolute inlines into - * inline block so that the boxes are constructed in an inline container - * as if they were not absolutely positioned. Layout expects and - * handles this. */ - if ((style->position == CSS_POSITION_ABSOLUTE || - style->position == CSS_POSITION_FIXED) && - (style->display == CSS_DISPLAY_INLINE || - style->display == CSS_DISPLAY_INLINE_BLOCK || - style->display == CSS_DISPLAY_INLINE_TABLE)) { - style->display = CSS_DISPLAY_INLINE_BLOCK; - return; - } - - /* map specified value to computed value using table given in 9.7 */ - if (style->display == CSS_DISPLAY_INLINE_TABLE) - style->display = CSS_DISPLAY_TABLE; - else if (style->display == CSS_DISPLAY_LIST_ITEM || - style->display == CSS_DISPLAY_TABLE) - ; /* same as specified */ - else - style->display = CSS_DISPLAY_BLOCK; -} - - -/** * Apply the CSS text-transform property to given text for its ASCII chars. * * \param s string to transform @@ -1360,8 +896,7 @@ void box_solve_display(struct css_style *style, bool root) * \param tt transform type */ -void box_text_transform(char *s, unsigned int len, - css_text_transform tt) +void box_text_transform(char *s, unsigned int len, enum css_text_transform tt) { unsigned int i; if (len == 0) @@ -1416,7 +951,15 @@ void box_text_transform(char *s, unsigned int len, bool box_body(BOX_SPECIAL_PARAMS) { - content->data.html.background_colour = box->style->background_color; + enum css_background_color type; + css_color color; + + type = css_computed_background_color(box->style, &color); + if (type == CSS_BACKGROUND_COLOR_TRANSPARENT) + content->data.html.background_colour = NS_TRANSPARENT; + else + content->data.html.background_colour = nscss_color_to_ns(color); + return true; } @@ -1507,7 +1050,8 @@ bool box_image(BOX_SPECIAL_PARAMS) char *s, *url; xmlChar *alt, *src; - if (box->style && box->style->display == CSS_DISPLAY_NONE) + if (box->style && css_computed_display(box->style, + n->parent == NULL) == CSS_DISPLAY_NONE) return true; /* handle alt text */ @@ -1558,7 +1102,8 @@ bool box_object(BOX_SPECIAL_PARAMS) xmlNode *c; struct box *inline_container = 0; - if (box->style && box->style->display == CSS_DISPLAY_NONE) + if (box->style && css_computed_display(box->style, + n->parent == NULL) == CSS_DISPLAY_NONE) return true; if (!box_get_attribute(n, "usemap", content, &box->usemap)) @@ -1685,8 +1230,7 @@ bool box_object(BOX_SPECIAL_PARAMS) /* convert children and place into fallback */ for (c = n->children; c; c = c->next) { if (!convert_xml_to_box(c, content, box->style, box, - &inline_container, 0, 0, 0, markup_track, - author)) + &inline_container, 0, 0, 0)) return false; } box->fallback = box->children; @@ -1849,7 +1393,7 @@ bool box_frameset(BOX_SPECIAL_PARAMS) if (convert_children) *convert_children = false; /* And ignore this spurious frameset */ - box->style->display = CSS_DISPLAY_NONE; + box->type = BOX_NONE; return true; } @@ -1860,7 +1404,7 @@ bool box_frameset(BOX_SPECIAL_PARAMS) ok = box_create_frameset(content->data.html.frameset, n, content); if (ok) - box->style->display = CSS_DISPLAY_NONE; + box->type = BOX_NONE; if (convert_children) *convert_children = false; @@ -1920,7 +1464,11 @@ bool box_create_frameset(struct content_html_frames *f, xmlNode *n, /* common extension: bordercolor="#RRGGBB|<named colour>" to control *all children */ if ((s = (char *) xmlGetProp(n, (const xmlChar *) "bordercolor"))) { - parse_inline_colour(s, &default_border_colour); + css_color color; + + if (nscss_parse_colour((const char *) s, &color)) + default_border_colour = nscss_color_to_ns(color); + xmlFree(s); } @@ -2030,7 +1578,13 @@ bool box_create_frameset(struct content_html_frames *f, xmlNode *n, } if ((s = (char *) xmlGetProp(c, (const xmlChar *) "bordercolor"))) { - parse_inline_colour(s, &frame->border_colour); + css_color color; + + if (nscss_parse_colour((const char *) s, + &color)) + frame->border_colour = + nscss_color_to_ns(color); + xmlFree(s); } @@ -2100,7 +1654,11 @@ bool box_iframe(BOX_SPECIAL_PARAMS) xmlFree(s); } if ((s = (char *) xmlGetProp(n, (const xmlChar *) "bordercolor"))) { - parse_inline_colour(s, &iframe->border_colour); + css_color color; + + if (nscss_parse_colour(s, &color)) + iframe->border_colour = nscss_color_to_ns(color); + xmlFree(s); } if ((s = (char *) xmlGetProp(n, @@ -2155,31 +1713,36 @@ bool box_input(BOX_SPECIAL_PARAMS) gadget->box = box; if (type && strcasecmp(type, "password") == 0) { - if (!box_input_text(n, content, box, 0, markup_track, author, - true)) + if (!box_input_text(n, content, box, 0, true)) goto no_memory; } else if (type && strcasecmp(type, "file") == 0) { box->type = BOX_INLINE_BLOCK; } else if (type && strcasecmp(type, "hidden") == 0) { /* no box for hidden inputs */ - box->style->display = CSS_DISPLAY_NONE; + box->type = BOX_NONE; } else if (type && (strcasecmp(type, "checkbox") == 0 || strcasecmp(type, "radio") == 0)) { } else if (type && (strcasecmp(type, "submit") == 0 || strcasecmp(type, "reset") == 0 || strcasecmp(type, "button") == 0)) { struct box *inline_container, *inline_box; - if (!box_button(n, content, box, 0, markup_track, author)) + + if (!box_button(n, content, box, 0)) goto no_memory; + inline_container = box_create(0, 0, 0, 0, 0, content); if (!inline_container) goto no_memory; + inline_container->type = BOX_INLINE_CONTAINER; + inline_box = box_create(box->style, 0, 0, box->title, 0, content); if (!inline_box) goto no_memory; + inline_box->type = BOX_TEXT; + if (box->gadget->value != NULL) inline_box->text = talloc_strdup(content, box->gadget->value); @@ -2191,15 +1754,20 @@ bool box_input(BOX_SPECIAL_PARAMS) messages_get("Form_Reset")); else inline_box->text = talloc_strdup(content, "Button"); + if (!inline_box->text) goto no_memory; + inline_box->length = strlen(inline_box->text); + box_add_child(inline_container, inline_box); + box_add_child(box, inline_container); } else if (type && strcasecmp(type, "image") == 0) { gadget->type = GADGET_IMAGE; - if (box->style && box->style->display != CSS_DISPLAY_NONE) { + if (box->style && css_computed_display(box->style, + n->parent == NULL) != CSS_DISPLAY_NONE) { if ((s = (char *) xmlGetProp(n, (const xmlChar*) "src"))) { res = url_join(s, @@ -2227,8 +1795,7 @@ bool box_input(BOX_SPECIAL_PARAMS) } } else { /* the default type is "text" */ - if (!box_input_text(n, content, box, 0, markup_track, author, - false)) + if (!box_input_text(n, content, box, 0, false)) goto no_memory; } @@ -2582,7 +2149,8 @@ bool box_embed(BOX_SPECIAL_PARAMS) xmlChar *src; xmlAttr *a; - if (box->style && box->style->display == CSS_DISPLAY_NONE) + if (box->style && css_computed_display(box->style, + n->parent == NULL) == CSS_DISPLAY_NONE) return true; params = talloc(content, struct object_params); @@ -2790,18 +2358,39 @@ struct frame_dimension *box_parse_multi_lengths(const char *s, return length; } - /** - * Parse an inline colour string + * Fetch an object from an interned URL + * + * \param c Current content + * \param url URL to fetch + * \param box Box containing object + * \param permitted_types Array of permitted types terminated by + * CONTENT_UNKNOWN, or NULL for all types + * \param available_width Estimate of width of object + * \param available_height Estimate of height of object + * \param background This object forms the box background + * \return true on success, false on memory exhaustion */ -static void parse_inline_colour(char *s, colour *variable) { - colour new_colour = CSS_COLOR_NONE; - if (s[0] == '#') { - if (strlen(s) == 7) - new_colour = hex_colour(s + 1, 6); - } else { - new_colour = named_colour(s); - } - if (new_colour != CSS_COLOR_NONE) - *variable = new_colour; +bool fetch_object_interned_url(struct content *c, lwc_string *url, + struct box *box, const content_type *permitted_types, + int available_width, int available_height, + bool background) +{ + char *url_buf; + bool ret = true; + + url_buf = malloc(lwc_string_length(url) + 1); + if (url_buf == NULL) + return false; + + memcpy(url_buf, lwc_string_data(url), lwc_string_length(url)); + url_buf[lwc_string_length(url)] = '\0'; + + ret = html_fetch_object(c, url_buf, box, permitted_types, + available_width, available_height, background); + + free(url_buf); + + return ret; } + |