From e8d0ba15ad4a91b4644cac0095f40bb3246ec509 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Wed, 29 Apr 2020 20:37:42 +0100 Subject: split html box processing code reduce the module size of the html box handling code by splitting into smaller sections. No functional code change. --- content/handlers/html/box_construct.c | 2021 ++------------------------------- 1 file changed, 88 insertions(+), 1933 deletions(-) (limited to 'content/handlers/html/box_construct.c') diff --git a/content/handlers/html/box_construct.c b/content/handlers/html/box_construct.c index a83330240..1637c0fb1 100644 --- a/content/handlers/html/box_construct.c +++ b/content/handlers/html/box_construct.c @@ -25,1885 +25,127 @@ * Implementation of conversion from DOM tree to box tree. */ -#include -#include -#include -#include -#include -#include - -#include "utils/config.h" -#include "utils/nsoption.h" -#include "utils/corestrings.h" -#include "utils/log.h" -#include "utils/messages.h" -#include "utils/talloc.h" -#include "utils/string.h" -#include "utils/ascii.h" -#include "netsurf/css.h" -#include "netsurf/misc.h" -#include "netsurf/plot_style.h" -#include "content/content_protected.h" -#include "css/hints.h" -#include "css/select.h" -#include "css/utils.h" -#include "desktop/gui_internal.h" - -#include "html/html.h" -#include "html/box.h" -#include "html/box_construct.h" -#include "html/box_normalise.h" -#include "html/box_textarea.h" -#include "html/form_internal.h" -#include "html/html_internal.h" - -/** - * Context for box tree construction - */ -struct box_construct_ctx { - html_content *content; /**< Content we're constructing for */ - - dom_node *n; /**< Current node to process */ - - struct box *root_box; /**< Root box in the tree */ - - box_construct_complete_cb cb; /**< Callback to invoke on completion */ - - int *bctx; /**< talloc context */ -}; - -/** - * Transient properties for construction of current node - */ -struct box_construct_props { - /** Style from which to inherit, or NULL if none */ - const css_computed_style *parent_style; - /** Current link target, or NULL if none */ - nsurl *href; - /** Current frame target, or NULL if none */ - const char *target; - /** Current title attribute, or NULL if none */ - const char *title; - /** Identity of the current block-level container */ - struct box *containing_block; - /** Current container for inlines, or NULL if none - * \note If non-NULL, will be the last child of containing_block */ - struct box *inline_container; - /** Whether the current node is the root of the DOM tree */ - bool node_is_root; -}; - -static const content_type image_types = CONTENT_IMAGE; - -/* 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"; - -/** - * mapping from CSS display to box type 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, */ - BOX_BLOCK, /* CSS_DISPLAY_BLOCK, */ - BOX_BLOCK, /* CSS_DISPLAY_LIST_ITEM, */ - BOX_INLINE, /* CSS_DISPLAY_RUN_IN, */ - BOX_INLINE_BLOCK, /* CSS_DISPLAY_INLINE_BLOCK, */ - BOX_TABLE, /* CSS_DISPLAY_TABLE, */ - BOX_TABLE, /* CSS_DISPLAY_INLINE_TABLE, */ - BOX_TABLE_ROW_GROUP, /* CSS_DISPLAY_TABLE_ROW_GROUP, */ - 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_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_NONE /* CSS_DISPLAY_NONE */ -}; - - -/** - * determine if a box is the root node - * - * \param n node to check - * \return true if node is root else false. - */ -static inline bool box_is_root(dom_node *n) -{ - dom_node *parent; - dom_node_type type; - dom_exception err; - - err = dom_node_get_parent_node(n, &parent); - if (err != DOM_NO_ERR) - return false; - - if (parent != NULL) { - err = dom_node_get_node_type(parent, &type); - - dom_node_unref(parent); - - if (err != DOM_NO_ERR) - return false; - - if (type != DOM_DOCUMENT_NODE) - return false; - } - - return true; -} - - -/** - * Destructor for object_params, for <object> elements - * - * \param o The object params being destroyed. - * \return 0 to allow talloc to continue destroying the tree. - */ -static int box_object_talloc_destructor(struct object_params *o) -{ - if (o->codebase != NULL) - nsurl_unref(o->codebase); - if (o->classid != NULL) - nsurl_unref(o->classid); - if (o->data != NULL) - nsurl_unref(o->data); - - return 0; -} - - -/** - * Parse a multi-length-list, as defined by HTML 4.01. - * - * \param ds dom string to parse - * \param count updated to number of entries - * \return array of struct box_multi_length, or 0 on memory exhaustion - */ -static struct frame_dimension * -box_parse_multi_lengths(const dom_string *ds, unsigned int *count) -{ - char *end; - unsigned int i, n; - struct frame_dimension *length; - const char *s; - - s = dom_string_data(ds); - - for (i = 0, n = 1; s[i]; i++) - if (s[i] == ',') - n++; - - length = calloc(n, sizeof(struct frame_dimension)); - if (!length) - return NULL; - - for (i = 0; i != n; i++) { - while (ascii_is_space(*s)) { - s++; - } - length[i].value = strtof(s, &end); - if (length[i].value <= 0) { - length[i].value = 1; - } - s = end; - switch (*s) { - case '%': - length[i].unit = FRAME_DIMENSION_PERCENT; - break; - case '*': - length[i].unit = FRAME_DIMENSION_RELATIVE; - break; - default: - length[i].unit = FRAME_DIMENSION_PIXELS; - break; - } - while (*s && *s != ',') { - s++; - } - if (*s == ',') { - s++; - } - } - - *count = n; - return length; -} - - -/** - * Destructor for content_html_frames, for frame elements - * - * \param f The frame params being destroyed. - * \return 0 to allow talloc to continue destroying the tree. - */ -static int box_frames_talloc_destructor(struct content_html_frames *f) -{ - if (f->url != NULL) { - nsurl_unref(f->url); - f->url = NULL; - } - - return 0; -} - - -/** - * create a frameset box tree - */ -static bool -box_create_frameset(struct content_html_frames *f, - dom_node *n, - html_content *content) -{ - unsigned int row, col, index, i; - unsigned int rows = 1, cols = 1; - dom_string *s; - dom_exception err; - nsurl *url; - struct frame_dimension *row_height = 0, *col_width = 0; - dom_node *c, *next; - struct content_html_frames *frame; - bool default_border = true; - colour default_border_colour = 0x000000; - - /* parse rows and columns */ - err = dom_element_get_attribute(n, corestring_dom_rows, &s); - if (err == DOM_NO_ERR && s != NULL) { - row_height = box_parse_multi_lengths(s, &rows); - dom_string_unref(s); - if (row_height == NULL) - return false; - } else { - row_height = calloc(1, sizeof(struct frame_dimension)); - if (row_height == NULL) - return false; - row_height->value = 100; - row_height->unit = FRAME_DIMENSION_PERCENT; - } - - err = dom_element_get_attribute(n, corestring_dom_cols, &s); - if (err == DOM_NO_ERR && s != NULL) { - col_width = box_parse_multi_lengths(s, &cols); - dom_string_unref(s); - if (col_width == NULL) { - free(row_height); - return false; - } - } else { - col_width = calloc(1, sizeof(struct frame_dimension)); - if (col_width == NULL) { - free(row_height); - return false; - } - col_width->value = 100; - col_width->unit = FRAME_DIMENSION_PERCENT; - } - - /* common extension: border="0|1" to control all children */ - err = dom_element_get_attribute(n, corestring_dom_border, &s); - if (err == DOM_NO_ERR && s != NULL) { - if ((dom_string_data(s)[0] == '0') && - (dom_string_data(s)[1] == '\0')) - default_border = false; - dom_string_unref(s); - } - - /* common extension: frameborder="yes|no" to control all children */ - err = dom_element_get_attribute(n, corestring_dom_frameborder, &s); - if (err == DOM_NO_ERR && s != NULL) { - if (dom_string_caseless_lwc_isequal(s, - corestring_lwc_no) == 0) - default_border = false; - dom_string_unref(s); - } - - /* common extension: bordercolor="#RRGGBB|" to control - *all children */ - err = dom_element_get_attribute(n, corestring_dom_bordercolor, &s); - if (err == DOM_NO_ERR && s != NULL) { - css_color color; - - if (nscss_parse_colour(dom_string_data(s), &color)) - default_border_colour = nscss_color_to_ns(color); - - dom_string_unref(s); - } - - /* update frameset and create default children */ - f->cols = cols; - f->rows = rows; - f->scrolling = BW_SCROLLING_NO; - f->children = talloc_array(content->bctx, struct content_html_frames, - (rows * cols)); - - talloc_set_destructor(f->children, box_frames_talloc_destructor); - - for (row = 0; row < rows; row++) { - for (col = 0; col < cols; col++) { - index = (row * cols) + col; - frame = &f->children[index]; - frame->cols = 0; - frame->rows = 0; - frame->width = col_width[col]; - frame->height = row_height[row]; - frame->margin_width = 0; - frame->margin_height = 0; - frame->name = NULL; - frame->url = NULL; - frame->no_resize = false; - frame->scrolling = BW_SCROLLING_AUTO; - frame->border = default_border; - frame->border_colour = default_border_colour; - frame->children = NULL; - } - } - free(col_width); - free(row_height); - - /* create the frameset windows */ - err = dom_node_get_first_child(n, &c); - if (err != DOM_NO_ERR) - return false; - - for (row = 0; c != NULL && row < rows; row++) { - for (col = 0; c != NULL && col < cols; col++) { - while (c != NULL) { - dom_node_type type; - dom_string *name; - - err = dom_node_get_node_type(c, &type); - if (err != DOM_NO_ERR) { - dom_node_unref(c); - return false; - } - - err = dom_node_get_node_name(c, &name); - if (err != DOM_NO_ERR) { - dom_node_unref(c); - return false; - } - - if (type != DOM_ELEMENT_NODE || - (!dom_string_caseless_lwc_isequal( - name, - corestring_lwc_frame) && - !dom_string_caseless_lwc_isequal( - name, - corestring_lwc_frameset - ))) { - err = dom_node_get_next_sibling(c, - &next); - if (err != DOM_NO_ERR) { - dom_string_unref(name); - dom_node_unref(c); - return false; - } - - dom_string_unref(name); - dom_node_unref(c); - c = next; - } else { - /* Got a FRAME or FRAMESET element */ - dom_string_unref(name); - break; - } - } - - if (c == NULL) - break; - - /* get current frame */ - index = (row * cols) + col; - frame = &f->children[index]; - - /* nest framesets */ - err = dom_node_get_node_name(c, &s); - if (err != DOM_NO_ERR) { - dom_node_unref(c); - return false; - } - - if (dom_string_caseless_lwc_isequal(s, - corestring_lwc_frameset)) { - dom_string_unref(s); - frame->border = 0; - if (box_create_frameset(frame, c, - content) == false) { - dom_node_unref(c); - return false; - } - - err = dom_node_get_next_sibling(c, &next); - if (err != DOM_NO_ERR) { - dom_node_unref(c); - return false; - } - - dom_node_unref(c); - c = next; - continue; - } - - dom_string_unref(s); - - /* get frame URL (not required) */ - url = NULL; - err = dom_element_get_attribute(c, corestring_dom_src, &s); - if (err == DOM_NO_ERR && s != NULL) { - box_extract_link(content, s, content->base_url, - &url); - dom_string_unref(s); - } - - /* copy url */ - if (url != NULL) { - /* no self-references */ - if (nsurl_compare(content->base_url, url, - NSURL_COMPLETE) == false) - frame->url = url; - url = NULL; - } - - /* fill in specified values */ - err = dom_element_get_attribute(c, corestring_dom_name, &s); - if (err == DOM_NO_ERR && s != NULL) { - frame->name = talloc_strdup(content->bctx, - dom_string_data(s)); - dom_string_unref(s); - } - - if (dom_element_has_attribute(c, corestring_dom_noresize, - &frame->no_resize) != DOM_NO_ERR) { - /* If we can't read the attribute for some reason, - * assume we didn't have it. - */ - frame->no_resize = false; - } - - err = dom_element_get_attribute(c, corestring_dom_frameborder, - &s); - if (err == DOM_NO_ERR && s != NULL) { - i = atoi(dom_string_data(s)); - frame->border = (i != 0); - dom_string_unref(s); - } - - err = dom_element_get_attribute(c, corestring_dom_scrolling, &s); - if (err == DOM_NO_ERR && s != NULL) { - if (dom_string_caseless_lwc_isequal(s, - corestring_lwc_yes)) - frame->scrolling = BW_SCROLLING_YES; - else if (dom_string_caseless_lwc_isequal(s, - corestring_lwc_no)) - frame->scrolling = BW_SCROLLING_NO; - dom_string_unref(s); - } - - err = dom_element_get_attribute(c, corestring_dom_marginwidth, - &s); - if (err == DOM_NO_ERR && s != NULL) { - frame->margin_width = atoi(dom_string_data(s)); - dom_string_unref(s); - } - - err = dom_element_get_attribute(c, corestring_dom_marginheight, - &s); - if (err == DOM_NO_ERR && s != NULL) { - frame->margin_height = atoi(dom_string_data(s)); - dom_string_unref(s); - } - - err = dom_element_get_attribute(c, corestring_dom_bordercolor, - &s); - if (err == DOM_NO_ERR && s != NULL) { - css_color color; - - if (nscss_parse_colour(dom_string_data(s), - &color)) - frame->border_colour = - nscss_color_to_ns(color); - - dom_string_unref(s); - } - - /* advance */ - err = dom_node_get_next_sibling(c, &next); - if (err != DOM_NO_ERR) { - dom_node_unref(c); - return false; - } - - dom_node_unref(c); - c = next; - } - } - - /* If the last child wasn't a frame, we still need to unref it */ - if (c != NULL) { - dom_node_unref(c); - } - - return true; -} - - -/** - * Destructor for content_html_iframe, for <iframe> elements - * - * \param f The iframe params being destroyed. - * \return 0 to allow talloc to continue destroying the tree. - */ -static int box_iframes_talloc_destructor(struct content_html_iframe *f) -{ - if (f->url != NULL) { - nsurl_unref(f->url); - f->url = NULL; - } - - return 0; -} - - -/** - * Get the value of a dom node element's attribute. - * - * \param n dom element node - * \param attribute name of attribute - * \param context talloc context for result buffer - * \param value updated to value, if the attribute is present - * \return true on success, false if attribute present but memory exhausted - * - * \note returning true does not imply that the attribute was found. If the - * attribute was not found, *value will be unchanged. - */ -static bool -box_get_attribute(dom_node *n, - const char *attribute, - void *context, - char **value) -{ - char *result; - dom_string *attr, *attr_name; - dom_exception err; - - err = dom_string_create_interned((const uint8_t *) attribute, - strlen(attribute), &attr_name); - if (err != DOM_NO_ERR) - return false; - - err = dom_element_get_attribute(n, attr_name, &attr); - if (err != DOM_NO_ERR) { - dom_string_unref(attr_name); - return false; - } - - dom_string_unref(attr_name); - - if (attr != NULL) { - result = talloc_strdup(context, dom_string_data(attr)); - - dom_string_unref(attr); - - if (result == NULL) - return false; - - *value = result; - } - - return true; -} - - -/** - * Helper function for adding textarea widget to box. - * - * This is a load of hacks to ensure boxes replaced with textareas - * can be handled by the layout code. - */ -static bool -box_input_text(html_content *html, struct box *box, struct dom_node *node) -{ - struct box *inline_container, *inline_box; - - box->type = BOX_INLINE_BLOCK; - - inline_container = box_create(NULL, 0, false, 0, 0, 0, 0, html->bctx); - if (!inline_container) - return false; - inline_container->type = BOX_INLINE_CONTAINER; - inline_box = box_create(NULL, box->style, false, 0, 0, box->title, 0, - html->bctx); - if (!inline_box) - return false; - inline_box->type = BOX_TEXT; - inline_box->text = talloc_strdup(html->bctx, ""); - - box_add_child(inline_container, inline_box); - box_add_child(box, inline_container); - - return box_textarea_create_textarea(html, box, node); -} - - -/** - * Add an option to a form select control (helper function for box_select()). - * - * \param control select containing the <option> - * \param n xml element node for <option> - * \return true on success, false on memory exhaustion - */ -static bool box_select_add_option(struct form_control *control, dom_node *n) -{ - char *value = NULL; - char *text = NULL; - char *text_nowrap = NULL; - bool selected; - dom_string *content, *s; - dom_exception err; - - err = dom_node_get_text_content(n, &content); - if (err != DOM_NO_ERR) - return false; - - if (content != NULL) { - text = squash_whitespace(dom_string_data(content)); - dom_string_unref(content); - } else { - text = strdup(""); - } - - if (text == NULL) - goto no_memory; - - err = dom_element_get_attribute(n, corestring_dom_value, &s); - if (err == DOM_NO_ERR && s != NULL) { - value = strdup(dom_string_data(s)); - dom_string_unref(s); - } else { - value = strdup(text); - } - - if (value == NULL) - goto no_memory; - - if (dom_element_has_attribute(n, corestring_dom_selected, &selected) != DOM_NO_ERR) { - /* Assume not selected if we can't read the attribute presence */ - selected = false; - } - - /* replace spaces/TABs with hard spaces to prevent line wrapping */ - text_nowrap = cnv_space2nbsp(text); - if (text_nowrap == NULL) - goto no_memory; - - if (form_add_option(control, value, text_nowrap, selected, n) == false) - goto no_memory; - - free(text); - - return true; - -no_memory: - free(value); - free(text); - free(text_nowrap); - return false; -} - - -/** - * \name Special case element handlers - * - * These functions are called by box_construct_element() when an element is - * being converted, according to the entries in element_table. - * - * The parameters are the xmlNode, the content for the document, and a partly - * filled in box structure for the element. - * - * Return true on success, false on memory exhaustion. Set *convert_children - * to false if children of this element in the XML tree should be skipped (for - * example, if they have been processed in some special way already). - * - * Elements ordered as in the HTML 4.01 specification. Section numbers in - * brackets [] refer to the spec. - * - * \{ - */ - -/** - * special element handler for Anchor [12.2]. - */ -static bool -box_a(dom_node *n, - html_content *content, - struct box *box, - bool *convert_children) -{ - bool ok; - nsurl *url; - dom_string *s; - dom_exception err; - - err = dom_element_get_attribute(n, corestring_dom_href, &s); - if (err == DOM_NO_ERR && s != NULL) { - ok = box_extract_link(content, s, content->base_url, &url); - dom_string_unref(s); - if (!ok) - return false; - if (url) { - if (box->href != NULL) - nsurl_unref(box->href); - box->href = url; - } - } - - /* name and id share the same namespace */ - err = dom_element_get_attribute(n, corestring_dom_name, &s); - if (err == DOM_NO_ERR && s != NULL) { - lwc_string *lwc_name; - - err = dom_string_intern(s, &lwc_name); - - dom_string_unref(s); - - if (err == DOM_NO_ERR) { - /* name replaces existing id - * TODO: really? */ - if (box->id != NULL) - lwc_string_unref(box->id); - - box->id = lwc_name; - } - } - - /* target frame [16.3] */ - err = dom_element_get_attribute(n, corestring_dom_target, &s); - if (err == DOM_NO_ERR && s != NULL) { - if (dom_string_caseless_lwc_isequal(s, - corestring_lwc__blank)) - box->target = TARGET_BLANK; - else if (dom_string_caseless_lwc_isequal(s, - corestring_lwc__top)) - box->target = TARGET_TOP; - else if (dom_string_caseless_lwc_isequal(s, - corestring_lwc__parent)) - box->target = TARGET_PARENT; - else if (dom_string_caseless_lwc_isequal(s, - corestring_lwc__self)) - /* the default may have been overridden by a - * , so this is different to 0 */ - box->target = TARGET_SELF; - else { - /* 6.16 says that frame names must begin with [a-zA-Z] - * This doesn't match reality, so just take anything */ - box->target = talloc_strdup(content->bctx, - dom_string_data(s)); - if (!box->target) { - dom_string_unref(s); - return false; - } - } - dom_string_unref(s); - } - - return true; -} - - -/** - * Document body special element handler [7.5.1]. - */ -static bool -box_body(dom_node *n, - html_content *content, - struct box *box, - bool *convert_children) -{ - css_color color; - - css_computed_background_color(box->style, &color); - if (nscss_color_is_transparent(color)) { - content->background_colour = NS_TRANSPARENT; - } else { - content->background_colour = nscss_color_to_ns(color); - } - - return true; -} - - -/** - * special element handler for forced line break [9.3.2]. - */ -static bool -box_br(dom_node *n, - html_content *content, - struct box *box, - bool *convert_children) -{ - box->type = BOX_BR; - return true; -} - - -/** - * special element handler for Push button [17.5]. - */ -static bool -box_button(dom_node *n, - html_content *content, - struct box *box, - bool *convert_children) -{ - struct form_control *gadget; - - gadget = html_forms_get_control_for_node(content->forms, n); - if (!gadget) - return false; - - gadget->html = content; - box->gadget = gadget; - box->flags |= IS_REPLACED; - gadget->box = box; - - box->type = BOX_INLINE_BLOCK; - - /* Just render the contents */ - - return true; -} - - -/** - * Canvas element - */ -static bool -box_canvas(dom_node *n, - html_content *content, - struct box *box, - bool *convert_children) -{ - /* If scripting is not enabled display the contents of canvas */ - if (!content->enable_scripting) { - return true; - } - *convert_children = false; - - return true; -} - - -/** - * Embedded object (not in any HTML specification: - * see http://wp.netscape.com/assist/net_sites/new_html3_prop.html ) - */ -static bool -box_embed(dom_node *n, - html_content *content, - struct box *box, - bool *convert_children) -{ - struct object_params *params; - struct object_param *param; - dom_namednodemap *attrs; - unsigned long idx; - uint32_t num_attrs; - dom_string *src; - dom_exception err; - - if (box->style && - ns_computed_display(box->style, box_is_root(n)) == CSS_DISPLAY_NONE) - return true; - - params = talloc(content->bctx, struct object_params); - if (params == NULL) - return false; - - talloc_set_destructor(params, box_object_talloc_destructor); - - params->data = NULL; - params->type = NULL; - params->codetype = NULL; - params->codebase = NULL; - params->classid = NULL; - params->params = NULL; - - /* src is a URL */ - err = dom_element_get_attribute(n, corestring_dom_src, &src); - if (err != DOM_NO_ERR || src == NULL) - return true; - if (box_extract_link(content, src, content->base_url, - ¶ms->data) == false) { - dom_string_unref(src); - return false; - } - - dom_string_unref(src); - - if (params->data == NULL) - return true; - - /* Don't include ourself */ - if (nsurl_compare(content->base_url, params->data, NSURL_COMPLETE)) - return true; - - /* add attributes as parameters to linked list */ - err = dom_node_get_attributes(n, &attrs); - if (err != DOM_NO_ERR) - return false; - - err = dom_namednodemap_get_length(attrs, &num_attrs); - if (err != DOM_NO_ERR) { - dom_namednodemap_unref(attrs); - return false; - } - - for (idx = 0; idx < num_attrs; idx++) { - dom_attr *attr; - dom_string *name, *value; - - err = dom_namednodemap_item(attrs, idx, (void *) &attr); - if (err != DOM_NO_ERR) { - dom_namednodemap_unref(attrs); - return false; - } - - err = dom_attr_get_name(attr, &name); - if (err != DOM_NO_ERR) { - dom_node_unref(attr); - dom_namednodemap_unref(attrs); - return false; - } - - if (dom_string_caseless_lwc_isequal(name, corestring_lwc_src)) { - dom_node_unref(attr); - dom_string_unref(name); - continue; - } - - err = dom_attr_get_value(attr, &value); - if (err != DOM_NO_ERR) { - dom_node_unref(attr); - dom_string_unref(name); - dom_namednodemap_unref(attrs); - return false; - } - - param = talloc(content->bctx, struct object_param); - if (param == NULL) { - dom_node_unref(attr); - dom_string_unref(value); - dom_string_unref(name); - dom_namednodemap_unref(attrs); - return false; - } - - param->name = talloc_strdup(content->bctx, dom_string_data(name)); - param->value = talloc_strdup(content->bctx, dom_string_data(value)); - param->type = NULL; - param->valuetype = talloc_strdup(content->bctx, "data"); - param->next = NULL; - - dom_string_unref(value); - dom_string_unref(name); - dom_node_unref(attr); - - if (param->name == NULL || param->value == NULL || - param->valuetype == NULL) { - dom_namednodemap_unref(attrs); - return false; - } - - param->next = params->params; - params->params = param; - } - - dom_namednodemap_unref(attrs); - - box->object_params = params; - - /* start fetch */ - box->flags |= IS_REPLACED; - return html_fetch_object(content, params->data, box, CONTENT_ANY, - content->base.available_width, 1000, false); -} - - -/** - * Window subdivision [16.2.1]. - */ -static bool -box_frameset(dom_node *n, - html_content *content, - struct box *box, - bool *convert_children) -{ - bool ok; - - if (content->frameset) { - NSLOG(netsurf, INFO, "Error: multiple framesets in document."); - /* Don't convert children */ - if (convert_children) - *convert_children = false; - /* And ignore this spurious frameset */ - box->type = BOX_NONE; - return true; - } - - content->frameset = talloc_zero(content->bctx, - struct content_html_frames); - if (!content->frameset) { - return false; - } - - ok = box_create_frameset(content->frameset, n, content); - if (ok) { - box->type = BOX_NONE; - } - - if (convert_children) { - *convert_children = false; - } - return ok; -} - - -/** - * Inline subwindow [16.5]. - */ -static bool -box_iframe(dom_node *n, - html_content *content, - struct box *box, - bool *convert_children) -{ - nsurl *url; - dom_string *s; - dom_exception err; - struct content_html_iframe *iframe; - int i; - - if (box->style && - ns_computed_display(box->style, box_is_root(n)) == CSS_DISPLAY_NONE) - return true; - - if (box->style && - css_computed_visibility(box->style) == CSS_VISIBILITY_HIDDEN) { - /* Don't create iframe discriptors for invisible iframes - * TODO: handle hidden iframes at browser_window generation - * time instead? */ - return true; - } - - /* get frame URL */ - err = dom_element_get_attribute(n, corestring_dom_src, &s); - if (err != DOM_NO_ERR || s == NULL) - return true; - if (box_extract_link(content, s, content->base_url, &url) == false) { - dom_string_unref(s); - return false; - } - dom_string_unref(s); - if (url == NULL) - return true; - - /* don't include ourself */ - if (nsurl_compare(content->base_url, url, NSURL_COMPLETE)) { - nsurl_unref(url); - return true; - } - - /* create a new iframe */ - iframe = talloc(content->bctx, struct content_html_iframe); - if (iframe == NULL) { - nsurl_unref(url); - return false; - } - - talloc_set_destructor(iframe, box_iframes_talloc_destructor); - - iframe->box = box; - iframe->margin_width = 0; - iframe->margin_height = 0; - iframe->name = NULL; - iframe->url = url; - iframe->scrolling = BW_SCROLLING_AUTO; - iframe->border = true; - - /* Add this iframe to the linked list of iframes */ - iframe->next = content->iframe; - content->iframe = iframe; - - /* fill in specified values */ - err = dom_element_get_attribute(n, corestring_dom_name, &s); - if (err == DOM_NO_ERR && s != NULL) { - iframe->name = talloc_strdup(content->bctx, dom_string_data(s)); - dom_string_unref(s); - } - - err = dom_element_get_attribute(n, corestring_dom_frameborder, &s); - if (err == DOM_NO_ERR && s != NULL) { - i = atoi(dom_string_data(s)); - iframe->border = (i != 0); - dom_string_unref(s); - } - - err = dom_element_get_attribute(n, corestring_dom_bordercolor, &s); - if (err == DOM_NO_ERR && s != NULL) { - css_color color; - - if (nscss_parse_colour(dom_string_data(s), &color)) - iframe->border_colour = nscss_color_to_ns(color); - - dom_string_unref(s); - } - - err = dom_element_get_attribute(n, corestring_dom_scrolling, &s); - if (err == DOM_NO_ERR && s != NULL) { - if (dom_string_caseless_lwc_isequal(s, - corestring_lwc_yes)) - iframe->scrolling = BW_SCROLLING_YES; - else if (dom_string_caseless_lwc_isequal(s, - corestring_lwc_no)) - iframe->scrolling = BW_SCROLLING_NO; - dom_string_unref(s); - } - - err = dom_element_get_attribute(n, corestring_dom_marginwidth, &s); - if (err == DOM_NO_ERR && s != NULL) { - iframe->margin_width = atoi(dom_string_data(s)); - dom_string_unref(s); - } - - err = dom_element_get_attribute(n, corestring_dom_marginheight, &s); - if (err == DOM_NO_ERR && s != NULL) { - iframe->margin_height = atoi(dom_string_data(s)); - dom_string_unref(s); - } - - /* box */ - assert(box->style); - box->flags |= IFRAME; - box->flags |= IS_REPLACED; - - /* Showing iframe, so don't show alternate content */ - if (convert_children) - *convert_children = false; - return true; -} - - -/** - * Embedded image [13.2]. - */ -static bool -box_image(dom_node *n, - html_content *content, - struct box *box, - bool *convert_children) -{ - bool ok; - dom_string *s; - dom_exception err; - nsurl *url; - enum css_width_e wtype; - enum css_height_e htype; - css_fixed value = 0; - css_unit wunit = CSS_UNIT_PX; - css_unit hunit = CSS_UNIT_PX; - - if (box->style && - ns_computed_display(box->style, box_is_root(n)) == CSS_DISPLAY_NONE) - return true; - - /* handle alt text */ - err = dom_element_get_attribute(n, corestring_dom_alt, &s); - if (err == DOM_NO_ERR && s != NULL) { - char *alt = squash_whitespace(dom_string_data(s)); - dom_string_unref(s); - if (alt == NULL) - return false; - box->text = talloc_strdup(content->bctx, alt); - free(alt); - if (box->text == NULL) - return false; - box->length = strlen(box->text); - } - - if (nsoption_bool(foreground_images) == false) { - return true; - } - - /* imagemap associated with this image */ - if (!box_get_attribute(n, "usemap", content->bctx, &box->usemap)) - return false; - if (box->usemap && box->usemap[0] == '#') - box->usemap++; - - /* get image URL */ - err = dom_element_get_attribute(n, corestring_dom_src, &s); - if (err != DOM_NO_ERR || s == NULL) - return true; - - if (box_extract_link(content, s, content->base_url, &url) == false) { - dom_string_unref(s); - return false; - } - - dom_string_unref(s); - - if (url == NULL) - return true; - - /* start fetch */ - box->flags |= IS_REPLACED; - ok = html_fetch_object(content, url, box, image_types, - content->base.available_width, 1000, false); - nsurl_unref(url); - - wtype = css_computed_width(box->style, &value, &wunit); - htype = css_computed_height(box->style, &value, &hunit); - - if (wtype == CSS_WIDTH_SET && - wunit != CSS_UNIT_PCT && - htype == CSS_HEIGHT_SET && - hunit != CSS_UNIT_PCT) { - /* We know the dimensions the image will be shown at - * before it's fetched. */ - box->flags |= REPLACE_DIM; - } - - return ok; -} - - -/** - * Form control [17.4]. - */ -static bool -box_input(dom_node *n, - html_content *content, - struct box *box, - bool *convert_children) -{ - struct form_control *gadget; - dom_string *type = NULL; - dom_exception err; - nsurl *url; - nserror error; - - gadget = html_forms_get_control_for_node(content->forms, n); - if (gadget == NULL) { - return false; - } - - box->gadget = gadget; - box->flags |= IS_REPLACED; - gadget->box = box; - gadget->html = content; - - /* get entry type */ - err = dom_element_get_attribute(n, corestring_dom_type, &type); - if ((err != DOM_NO_ERR) || (type == NULL)) { - /* no type so "text" is assumed */ - if (box_input_text(content, box, n) == false) { - return false; - } - *convert_children = false; - return true; - } - - if (dom_string_caseless_lwc_isequal(type, corestring_lwc_password)) { - if (box_input_text(content, box, n) == false) - goto no_memory; - - } else if (dom_string_caseless_lwc_isequal(type, corestring_lwc_file)) { - box->type = BOX_INLINE_BLOCK; - - } else if (dom_string_caseless_lwc_isequal(type, - corestring_lwc_hidden)) { - /* no box for hidden inputs */ - box->type = BOX_NONE; - - } else if ((dom_string_caseless_lwc_isequal(type, - corestring_lwc_checkbox) || - dom_string_caseless_lwc_isequal(type, - corestring_lwc_radio))) { - - } else if (dom_string_caseless_lwc_isequal(type, - corestring_lwc_submit) || - dom_string_caseless_lwc_isequal(type, - corestring_lwc_reset) || - dom_string_caseless_lwc_isequal(type, - corestring_lwc_button)) { - struct box *inline_container, *inline_box; - - if (box_button(n, content, box, 0) == false) - goto no_memory; - - inline_container = box_create(NULL, 0, false, 0, 0, 0, 0, - content->bctx); - if (inline_container == NULL) - goto no_memory; - - inline_container->type = BOX_INLINE_CONTAINER; - - inline_box = box_create(NULL, box->style, false, 0, 0, - box->title, 0, content->bctx); - if (inline_box == NULL) - goto no_memory; - - inline_box->type = BOX_TEXT; - - if (box->gadget->value != NULL) - inline_box->text = talloc_strdup(content->bctx, - box->gadget->value); - else if (box->gadget->type == GADGET_SUBMIT) - inline_box->text = talloc_strdup(content->bctx, - messages_get("Form_Submit")); - else if (box->gadget->type == GADGET_RESET) - inline_box->text = talloc_strdup(content->bctx, - messages_get("Form_Reset")); - else - inline_box->text = talloc_strdup(content->bctx, - "Button"); - - if (inline_box->text == NULL) - 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 (dom_string_caseless_lwc_isequal(type, - corestring_lwc_image)) { - gadget->type = GADGET_IMAGE; - - if (box->style && - ns_computed_display(box->style, - box_is_root(n)) != CSS_DISPLAY_NONE && - nsoption_bool(foreground_images) == true) { - dom_string *s; - - err = dom_element_get_attribute(n, corestring_dom_src, &s); - if (err == DOM_NO_ERR && s != NULL) { - error = nsurl_join(content->base_url, - dom_string_data(s), &url); - dom_string_unref(s); - if (error != NSERROR_OK) - goto no_memory; - - /* if url is equivalent to the parent's url, - * we've got infinite inclusion. stop it here - */ - if (nsurl_compare(url, content->base_url, - NSURL_COMPLETE) == false) { - if (!html_fetch_object(content, url, - box, image_types, - content->base. - available_width, - 1000, false)) { - nsurl_unref(url); - goto no_memory; - } - } - nsurl_unref(url); - } - } - } else { - /* unhandled type the default is "text" */ - if (box_input_text(content, box, n) == false) - goto no_memory; - } - - dom_string_unref(type); - - *convert_children = false; - - return true; - -no_memory: - dom_string_unref(type); - - return false; -} - - -/** - * Noscript element - */ -static bool -box_noscript(dom_node *n, - html_content *content, - struct box *box, - bool *convert_children) -{ - /* If scripting is enabled, do not display the contents of noscript */ - if (content->enable_scripting) { - *convert_children = false; - } - - return true; -} - - -/** - * Generic embedded object [13.3]. - */ -static bool -box_object(dom_node *n, - html_content *content, - struct box *box, - bool *convert_children) -{ - struct object_params *params; - struct object_param *param; - dom_string *codebase, *classid, *data; - dom_node *c; - dom_exception err; - - if (box->style && - ns_computed_display(box->style, box_is_root(n)) == CSS_DISPLAY_NONE) - return true; - - if (box_get_attribute(n, "usemap", content->bctx, &box->usemap) == - false) - return false; - if (box->usemap && box->usemap[0] == '#') - box->usemap++; - - params = talloc(content->bctx, struct object_params); - if (params == NULL) - return false; - - talloc_set_destructor(params, box_object_talloc_destructor); - - params->data = NULL; - params->type = NULL; - params->codetype = NULL; - params->codebase = NULL; - params->classid = NULL; - params->params = NULL; - - /* codebase, classid, and data are URLs - * (codebase is the base for the other two) */ - err = dom_element_get_attribute(n, corestring_dom_codebase, &codebase); - if (err == DOM_NO_ERR && codebase != NULL) { - if (box_extract_link(content, codebase, content->base_url, - ¶ms->codebase) == false) { - dom_string_unref(codebase); - return false; - } - dom_string_unref(codebase); - } - if (params->codebase == NULL) - params->codebase = nsurl_ref(content->base_url); - - err = dom_element_get_attribute(n, corestring_dom_classid, &classid); - if (err == DOM_NO_ERR && classid != NULL) { - if (box_extract_link(content, classid, - params->codebase, ¶ms->classid) == false) { - dom_string_unref(classid); - return false; - } - dom_string_unref(classid); - } - - err = dom_element_get_attribute(n, corestring_dom_data, &data); - if (err == DOM_NO_ERR && data != NULL) { - if (box_extract_link(content, data, - params->codebase, ¶ms->data) == false) { - dom_string_unref(data); - return false; - } - dom_string_unref(data); - } - - if (params->classid == NULL && params->data == NULL) - /* nothing to embed; ignore */ - return true; - - /* Don't include ourself */ - if (params->classid != NULL && nsurl_compare(content->base_url, - params->classid, NSURL_COMPLETE)) - return true; - - if (params->data != NULL && nsurl_compare(content->base_url, - params->data, NSURL_COMPLETE)) - return true; - - /* codetype and type are MIME types */ - if (box_get_attribute(n, "codetype", params, - ¶ms->codetype) == false) - return false; - if (box_get_attribute(n, "type", params, ¶ms->type) == false) - return false; - - /* classid && !data => classid is used (consult codetype) - * (classid || !classid) && data => data is used (consult type) - * !classid && !data => invalid; ignored */ - - if (params->classid != NULL && params->data == NULL && - params->codetype != NULL) { - lwc_string *icodetype; - lwc_error lerror; - - lerror = lwc_intern_string(params->codetype, - strlen(params->codetype), &icodetype); - if (lerror != lwc_error_ok) - return false; - - if (content_factory_type_from_mime_type(icodetype) == - CONTENT_NONE) { - /* can't handle this MIME type */ - lwc_string_unref(icodetype); - return true; - } - - lwc_string_unref(icodetype); - } - - if (params->data != NULL && params->type != NULL) { - lwc_string *itype; - lwc_error lerror; - - lerror = lwc_intern_string(params->type, strlen(params->type), - &itype); - if (lerror != lwc_error_ok) - return false; - - if (content_factory_type_from_mime_type(itype) == - CONTENT_NONE) { - /* can't handle this MIME type */ - lwc_string_unref(itype); - return true; - } - - lwc_string_unref(itype); - } - - /* add parameters to linked list */ - err = dom_node_get_first_child(n, &c); - if (err != DOM_NO_ERR) - return false; - - while (c != NULL) { - dom_node *next; - dom_node_type type; +#include - err = dom_node_get_node_type(c, &type); - if (err != DOM_NO_ERR) { - dom_node_unref(c); - return false; - } - - if (type == DOM_ELEMENT_NODE) { - dom_string *name; - - err = dom_node_get_node_name(c, &name); - if (err != DOM_NO_ERR) { - dom_node_unref(c); - return false; - } - - if (!dom_string_caseless_lwc_isequal(name, - corestring_lwc_param)) { - /* The first non-param child is the start of - * the alt html. Therefore, we should break - * out of this loop. */ - dom_string_unref(name); - dom_node_unref(c); - break; - } - dom_string_unref(name); - - param = talloc(params, struct object_param); - if (param == NULL) { - dom_node_unref(c); - return false; - } - param->name = NULL; - param->value = NULL; - param->type = NULL; - param->valuetype = NULL; - param->next = NULL; - - if (box_get_attribute(c, "name", param, - ¶m->name) == false) { - dom_node_unref(c); - return false; - } - - if (box_get_attribute(c, "value", param, - ¶m->value) == false) { - dom_node_unref(c); - return false; - } - - if (box_get_attribute(c, "type", param, - ¶m->type) == false) { - dom_node_unref(c); - return false; - } +#include "utils/errors.h" +#include "utils/nsoption.h" +#include "utils/corestrings.h" +#include "utils/talloc.h" +#include "utils/string.h" +#include "utils/ascii.h" +#include "netsurf/misc.h" +#include "css/select.h" +#include "desktop/gui_internal.h" - if (box_get_attribute(c, "valuetype", param, - ¶m->valuetype) == false) { - dom_node_unref(c); - return false; - } +#include "html/html_internal.h" +#include "html/box.h" +#include "html/box_manipulate.h" +#include "html/box_construct.h" +#include "html/box_special.h" +#include "html/box_normalise.h" +#include "html/form_internal.h" - if (param->valuetype == NULL) { - param->valuetype = talloc_strdup(param, "data"); - if (param->valuetype == NULL) { - dom_node_unref(c); - return false; - } - } +/** + * Context for box tree construction + */ +struct box_construct_ctx { + html_content *content; /**< Content we're constructing for */ - param->next = params->params; - params->params = param; - } + dom_node *n; /**< Current node to process */ - err = dom_node_get_next_sibling(c, &next); - if (err != DOM_NO_ERR) { - dom_node_unref(c); - return false; - } + struct box *root_box; /**< Root box in the tree */ - dom_node_unref(c); - c = next; - } + box_construct_complete_cb cb; /**< Callback to invoke on completion */ - box->object_params = params; + int *bctx; /**< talloc context */ +}; - /* start fetch (MIME type is ok or not specified) */ - box->flags |= IS_REPLACED; - if (!html_fetch_object(content, - params->data ? params->data : params->classid, - box, CONTENT_ANY, content->base.available_width, 1000, - false)) - return false; +/** + * Transient properties for construction of current node + */ +struct box_construct_props { + /** Style from which to inherit, or NULL if none */ + const css_computed_style *parent_style; + /** Current link target, or NULL if none */ + nsurl *href; + /** Current frame target, or NULL if none */ + const char *target; + /** Current title attribute, or NULL if none */ + const char *title; + /** Identity of the current block-level container */ + struct box *containing_block; + /** Current container for inlines, or NULL if none + * \note If non-NULL, will be the last child of containing_block */ + struct box *inline_container; + /** Whether the current node is the root of the DOM tree */ + bool node_is_root; +}; - *convert_children = false; - return true; -} +static const content_type image_types = CONTENT_IMAGE; +/* 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"; /** - * Preformatted text [9.3.4]. + * mapping from CSS display to box type this table must be in sync + * with libcss' css_display enum */ -static bool -box_pre(dom_node *n, - html_content *content, - struct box *box, - bool *convert_children) -{ - box->flags |= PRE_STRIP; - return true; -} +static const box_type box_map[] = { + 0, /* CSS_DISPLAY_INHERIT, */ + BOX_INLINE, /* CSS_DISPLAY_INLINE, */ + BOX_BLOCK, /* CSS_DISPLAY_BLOCK, */ + BOX_BLOCK, /* CSS_DISPLAY_LIST_ITEM, */ + BOX_INLINE, /* CSS_DISPLAY_RUN_IN, */ + BOX_INLINE_BLOCK, /* CSS_DISPLAY_INLINE_BLOCK, */ + BOX_TABLE, /* CSS_DISPLAY_TABLE, */ + BOX_TABLE, /* CSS_DISPLAY_INLINE_TABLE, */ + BOX_TABLE_ROW_GROUP, /* CSS_DISPLAY_TABLE_ROW_GROUP, */ + 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_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_NONE /* CSS_DISPLAY_NONE */ +}; /** - * Option selector [17.6]. + * determine if a box is the root node + * + * \param n node to check + * \return true if node is root else false. */ -static bool -box_select(dom_node *n, - html_content *content, - struct box *box, - bool *convert_children) +static inline bool box_is_root(dom_node *n) { - struct box *inline_container; - struct box *inline_box; - struct form_control *gadget; - dom_node *c, *c2; - dom_node *next, *next2; + dom_node *parent; + dom_node_type type; dom_exception err; - gadget = html_forms_get_control_for_node(content->forms, n); - if (gadget == NULL) + err = dom_node_get_parent_node(n, &parent); + if (err != DOM_NO_ERR) return false; - gadget->html = content; - err = dom_node_get_first_child(n, &c); - if (err != DOM_NO_ERR) { - form_free_control(gadget); - return false; - } + if (parent != NULL) { + err = dom_node_get_node_type(parent, &type); - while (c != NULL) { - dom_string *name; + dom_node_unref(parent); - err = dom_node_get_node_name(c, &name); - if (err != DOM_NO_ERR) { - dom_node_unref(c); - form_free_control(gadget); + if (err != DOM_NO_ERR) return false; - } - - if (dom_string_caseless_lwc_isequal(name, - corestring_lwc_option)) { - dom_string_unref(name); - - if (box_select_add_option(gadget, c) == false) { - dom_node_unref(c); - form_free_control(gadget); - return false; - } - } else if (dom_string_caseless_lwc_isequal(name, - corestring_lwc_optgroup)) { - dom_string_unref(name); - - err = dom_node_get_first_child(c, &c2); - if (err != DOM_NO_ERR) { - dom_node_unref(c); - form_free_control(gadget); - return false; - } - - while (c2 != NULL) { - dom_string *c2_name; - - err = dom_node_get_node_name(c2, &c2_name); - if (err != DOM_NO_ERR) { - dom_node_unref(c2); - dom_node_unref(c); - form_free_control(gadget); - return false; - } - - if (dom_string_caseless_lwc_isequal(c2_name, - corestring_lwc_option)) { - dom_string_unref(c2_name); - - if (box_select_add_option(gadget, - c2) == false) { - dom_node_unref(c2); - dom_node_unref(c); - form_free_control(gadget); - return false; - } - } else { - dom_string_unref(c2_name); - } - - err = dom_node_get_next_sibling(c2, &next2); - if (err != DOM_NO_ERR) { - dom_node_unref(c2); - dom_node_unref(c); - form_free_control(gadget); - return false; - } - - dom_node_unref(c2); - c2 = next2; - } - } else { - dom_string_unref(name); - } - err = dom_node_get_next_sibling(c, &next); - if (err != DOM_NO_ERR) { - dom_node_unref(c); - form_free_control(gadget); + if (type != DOM_DOCUMENT_NODE) return false; - } - - dom_node_unref(c); - c = next; - } - - if (gadget->data.select.num_items == 0) { - /* no options: ignore entire select */ - form_free_control(gadget); - return true; - } - - box->type = BOX_INLINE_BLOCK; - box->gadget = gadget; - box->flags |= IS_REPLACED; - gadget->box = box; - - inline_container = box_create(NULL, 0, false, 0, 0, 0, 0, content->bctx); - if (inline_container == NULL) - goto no_memory; - inline_container->type = BOX_INLINE_CONTAINER; - inline_box = box_create(NULL, box->style, false, 0, 0, box->title, 0, - content->bctx); - if (inline_box == NULL) - goto no_memory; - inline_box->type = BOX_TEXT; - box_add_child(inline_container, inline_box); - box_add_child(box, inline_container); - - if (gadget->data.select.multiple == false && - gadget->data.select.num_selected == 0) { - gadget->data.select.current = gadget->data.select.items; - gadget->data.select.current->initial_selected = - gadget->data.select.current->selected = true; - gadget->data.select.num_selected = 1; - dom_html_option_element_set_selected( - gadget->data.select.current->node, true); } - if (gadget->data.select.num_selected == 0) - inline_box->text = talloc_strdup(content->bctx, - messages_get("Form_None")); - else if (gadget->data.select.num_selected == 1) - inline_box->text = talloc_strdup(content->bctx, - gadget->data.select.current->text); - else - inline_box->text = talloc_strdup(content->bctx, - messages_get("Form_Many")); - if (inline_box->text == NULL) - goto no_memory; - - inline_box->length = strlen(inline_box->text); - - *convert_children = false; - return true; - -no_memory: - return false; -} - - -/** - * Multi-line text field [17.7]. - */ -static bool box_textarea(dom_node *n, - html_content *content, - struct box *box, - bool *convert_children) -{ - /* Get the form_control for the DOM node */ - box->gadget = html_forms_get_control_for_node(content->forms, n); - if (box->gadget == NULL) - return false; - - box->flags |= IS_REPLACED; - box->gadget->html = content; - box->gadget->box = box; - - if (!box_input_text(content, box, n)) - return false; - - *convert_children = false; return true; } -/** - * \} - */ - - /** * Extract transient construction properties * @@ -2244,93 +486,6 @@ box_construct_marker(struct box *box, } -/** - * call an elements special handler - */ -static bool -convert_special_elements(dom_node *node, - html_content *content, - struct box *box, - bool *convert_children) -{ - dom_exception exc; - dom_html_element_type tag_type; - bool res; - - exc = dom_html_element_get_tag_type(node, &tag_type); - if (exc != DOM_NO_ERR) { - tag_type = DOM_HTML_ELEMENT_TYPE__UNKNOWN; - } - - switch (tag_type) { - case DOM_HTML_ELEMENT_TYPE_A: - res = box_a(node, content, box, convert_children); - break; - - case DOM_HTML_ELEMENT_TYPE_BODY: - res = box_body(node, content, box, convert_children); - break; - - case DOM_HTML_ELEMENT_TYPE_BR: - res = box_br(node, content, box, convert_children); - break; - - case DOM_HTML_ELEMENT_TYPE_BUTTON: - res = box_button(node, content, box, convert_children); - break; - - case DOM_HTML_ELEMENT_TYPE_CANVAS: - res = box_canvas(node, content, box, convert_children); - break; - - case DOM_HTML_ELEMENT_TYPE_EMBED: - res = box_embed(node, content, box, convert_children); - break; - - case DOM_HTML_ELEMENT_TYPE_FRAMESET: - res = box_frameset(node, content, box, convert_children); - break; - - case DOM_HTML_ELEMENT_TYPE_IFRAME: - res = box_iframe(node, content, box, convert_children); - break; - - case DOM_HTML_ELEMENT_TYPE_IMG: - res = box_image(node, content, box, convert_children); - break; - - case DOM_HTML_ELEMENT_TYPE_INPUT: - res = box_input(node, content, box, convert_children); - break; - - case DOM_HTML_ELEMENT_TYPE_NOSCRIPT: - res = box_noscript(node, content, box, convert_children); - break; - - case DOM_HTML_ELEMENT_TYPE_OBJECT: - res = box_object(node, content, box, convert_children); - break; - - case DOM_HTML_ELEMENT_TYPE_PRE: - res = box_pre(node, content, box, convert_children); - break; - - case DOM_HTML_ELEMENT_TYPE_SELECT: - res = box_select(node, content, box, convert_children); - break; - - case DOM_HTML_ELEMENT_TYPE_TEXTAREA: - res = box_textarea(node, content, box, convert_children); - break; - - default: - res = true; - } - - return res; -} - - /** * Construct the box tree for an XML element. * -- cgit v1.2.3