From bb71de9938ea94117edc8b2f9dfc1e49b9a2cc17 Mon Sep 17 00:00:00 2001 From: James Bursa Date: Fri, 4 Jul 2003 21:17:53 +0000 Subject: [project @ 2003-07-04 21:17:53 by bursa] Clean up and add comments. svn path=/import/netsurf/; revision=202 --- render/box.c | 936 ++++++++++++++++++++++++++++------------------------------- 1 file changed, 437 insertions(+), 499 deletions(-) diff --git a/render/box.c b/render/box.c index 02bc675af..619c51449 100644 --- a/render/box.c +++ b/render/box.c @@ -16,6 +16,7 @@ #include "netsurf/content/fetchcache.h" #include "netsurf/css/css.h" #include "netsurf/render/box.h" +#include "netsurf/render/html.h" #ifdef riscos #include "netsurf/desktop/gui.h" #include "netsurf/riscos/font.h" @@ -25,29 +26,46 @@ #include "netsurf/utils/log.h" #include "netsurf/utils/utils.h" -/** - * internal functions - */ -struct fetch_data { - struct content *c; - unsigned int i; +/* status for box tree construction */ +struct status { + struct content *content; + char *href; + char *title; + struct form* current_form; + struct page_elements* elements; +}; + +/* result of converting a special case element */ +struct result { + struct box *box; /* box for element, if any, 0 otherwise */ + int convert_children; /* children should be converted */ }; static void box_add_child(struct box * parent, struct box * child); static struct box * box_create(box_type type, struct css_style * style, char *href, char *title); -static struct box * convert_xml_to_box(xmlNode * n, struct content *c, +static struct box * convert_xml_to_box(xmlNode * n, struct content *content, struct css_style * parent_style, struct css_selector ** selector, unsigned int depth, - struct box * parent, struct box * inline_container, - char *href, - struct gui_gadget* current_select, struct formoption* current_option, - struct gui_gadget* current_textarea, struct form* current_form, - struct page_elements* elements); + struct box * parent, struct box *inline_container, + struct status status); static struct css_style * box_get_style(struct content ** stylesheet, unsigned int stylesheet_count, struct css_style * parent_style, xmlNode * n, struct css_selector * selector, unsigned int depth); +static struct result box_a(xmlNode *n, struct status *status, + struct css_style *style); +static struct result box_image(xmlNode *n, struct status *status, + struct css_style *style); +static struct result box_form(xmlNode *n, struct status *status, + struct css_style *style); +static struct result box_textarea(xmlNode *n, struct status *status, + struct css_style *style); +static struct result box_select(xmlNode *n, struct status *status, + struct css_style *style); +struct result box_input(xmlNode *n, struct status *status, + struct css_style *style); +static void add_option(xmlNode* n, struct gui_gadget* current_select, char *text); static void box_normalise_block(struct box *block); static void box_normalise_table(struct box *table); static void box_normalise_table_row_group(struct box *row_group); @@ -55,24 +73,31 @@ static void box_normalise_table_row(struct box *row); static void box_normalise_inline_container(struct box *cont); static void gadget_free(struct gui_gadget* g); static void box_free_box(struct box *box); -static struct box* box_image(xmlNode *n, struct content *content, - struct css_style *style, char *href, char *title); -static struct box* box_textarea(xmlNode* n, struct css_style* style, struct form* current_form); -static struct box* box_select(xmlNode * n, struct css_style* style, struct form* current_form); -static struct formoption* box_option(xmlNode* n, struct css_style* style, struct gui_gadget* current_select); static struct box* box_object(xmlNode *n, struct content *content, struct css_style *style, char *href); static struct box* box_embed(xmlNode *n, struct content *content, struct css_style *style, char *href); static struct box* box_applet(xmlNode *n, struct content *content, struct css_style *style, char *href); -static void textarea_addtext(struct gui_gadget* textarea, char* text); -static void option_addtext(struct formoption* option, char* text); -static struct box* box_input(xmlNode * n, struct css_style* style, struct form* current_form, struct page_elements* elements); -static struct form* box_form(xmlNode* n); +static struct form* create_form(xmlNode* n); static void add_form_element(struct page_elements* pe, struct form* f); static void add_gadget_element(struct page_elements* pe, struct gui_gadget* g); -static void add_img_element(struct page_elements* pe, struct img* i); + +/* element_table must be sorted by name */ +struct element_entry { + char name[10]; /* element type */ + struct result (*convert)(xmlNode *n, struct status *status, + struct css_style *style); +}; +static const struct element_entry element_table[] = { + {"a", box_a}, + {"form", box_form}, + {"img", box_image}, + {"input", box_input}, + {"select", box_select}, + {"textarea", box_textarea} +}; +#define ELEMENT_TABLE_COUNT (sizeof(element_table) / sizeof(element_table[0])) /** @@ -105,11 +130,14 @@ struct box * box_create(box_type type, struct css_style * style, box->style = style; box->width = UNKNOWN_WIDTH; box->max_width = UNKNOWN_MAX_WIDTH; - box->text = 0; box->href = href; box->title = title; - box->length = 0; box->columns = 1; +#ifndef riscos + /* under RISC OS, xcalloc makes these unnecessary */ + box->text = 0; + box->space = 0; + box->length = 0; box->next = 0; box->prev = 0; box->children = 0; @@ -121,6 +149,7 @@ struct box * box_create(box_type type, struct css_style * style, box->font = 0; box->gadget = 0; box->object = 0; +#endif return box; } @@ -132,6 +161,7 @@ struct box * box_create(box_type type, struct css_style * style, void xml_to_box(xmlNode *n, struct content *c) { struct css_selector* selector = xcalloc(1, sizeof(struct css_selector)); + struct status status = {c, 0, 0, 0, &c->data.html.elements}; LOG(("node %p", n)); assert(c->type == CONTENT_HTML); @@ -147,8 +177,7 @@ void xml_to_box(xmlNode *n, struct content *c) c->data.html.object = xcalloc(0, sizeof(*c->data.html.object)); convert_xml_to_box(n, c, c->data.html.style, - &selector, 0, c->data.html.layout, 0, 0, 0, 0, - 0, 0, &c->data.html.elements); + &selector, 0, c->data.html.layout, 0, status); LOG(("normalising")); box_normalise_block(c->data.html.layout->children); } @@ -165,9 +194,7 @@ void xml_to_box(xmlNode *n, struct content *c) * depth depth in xml tree * parent parent in box tree * inline_container current inline container box, or 0 - * href current link, or 0 - * current_* forms state - * elements forms structure + * status status for forms etc. * * returns: * updated current inline container @@ -176,11 +203,8 @@ void xml_to_box(xmlNode *n, struct content *c) struct box * convert_xml_to_box(xmlNode * n, struct content *content, struct css_style * parent_style, struct css_selector ** selector, unsigned int depth, - struct box * parent, struct box * inline_container, - char *href, - struct gui_gadget* current_select, struct formoption* current_option, - struct gui_gadget* current_textarea, struct form* current_form, - struct page_elements* elements) + struct box * parent, struct box *inline_container, + struct status status) { struct box * box = 0; struct box * inline_container_c; @@ -190,13 +214,15 @@ struct box * convert_xml_to_box(xmlNode * n, struct content *content, char * text = 0; xmlChar * title0; char * title = 0; + int convert_children = 1; - assert(n != 0 && content != 0 && parent_style != 0 && selector != 0 && - parent != 0); + assert(n != 0 && parent_style != 0 && selector != 0 && parent != 0); LOG(("depth %i, node %p, node type %i", depth, n, n->type)); gui_multitask(); if (n->type == XML_ELEMENT_NODE) { + struct element_entry *element; + /* work out the style for this element */ *selector = xrealloc(*selector, (depth + 1) * sizeof(struct css_selector)); (*selector)[depth].element = (const char *) n->name; @@ -211,6 +237,7 @@ struct box * convert_xml_to_box(xmlNode * n, struct content *content, LOG(("display: %s", css_display_name[style->display])); if (style->display == CSS_DISPLAY_NONE) { free(style); + LOG(("depth %i, node %p, node type %i END", depth, n, n->type)); return inline_container; } /* floats are treated as blocks */ @@ -225,67 +252,13 @@ struct box * convert_xml_to_box(xmlNode * n, struct content *content, } /* special elements */ - if (strcmp((const char *) n->name, "a") == 0) { - if ((s = (char *) xmlGetProp(n, (const xmlChar *) "href"))) - href = s; - - } else if (strcmp((const char *) n->name, "form") == 0) { - struct form* form = box_form(n); - current_form = form; - add_form_element(elements, form); - - } else if (strcmp((const char *) n->name, "img") == 0) { - box = box_image(n, content, style, href, title); - - } else if (strcmp((const char *) n->name, "textarea") == 0) { - char * content = xmlNodeGetContent(n); - char * thistext = squash_tolat1(content); /* squash ? */ - LOG(("textarea")); - box = box_textarea(n, style, current_form); - current_textarea = box->gadget; - add_gadget_element(elements, box->gadget); - textarea_addtext(current_textarea, thistext); - xmlFree(content); - - } else if (strcmp((const char *) n->name, "select") == 0) { - LOG(("select")); - box = box_select(n, style, current_form); - current_select = box->gadget; - add_gadget_element(elements, box->gadget); - for (c = n->children; c != 0; c = c->next) { - if (strcmp((const char *) c->name, "option") == 0) { - char * content = xmlNodeGetContent(c); - char * thistext = squash_tolat1(content); - LOG(("option")); - current_option = box_option(c, style, current_select); - option_addtext(current_option, thistext); - xmlFree(content); - } - } - - } else if (strcmp((const char *) n->name, "input") == 0) { - LOG(("input")); - box = box_input(n, style, current_form, elements); - - } else if (strcmp((const char*) n->name, "object") == 0) { LOG(("object")); - box = box_object(n, content, style, href); - /* TODO - param data structure - - for (c = n->children; c != 0; c = c->next) { - - if (strcmp((const char*) c->name, "param") == 0) { - - LOG(("param")); - current_param = box_param(c, style, current_object); - } - } */ - - } else if (strcmp((const char*) n->name, "embed") == 0) { LOG(("embed")); - box = box_embed(n, content, style, href); - - } else if (strcmp((const char*) n->name, "applet") == 0) { LOG(("applet")); - box = box_applet(n, content, style, href); - + element = bsearch((const char *) n->name, element_table, + ELEMENT_TABLE_COUNT, sizeof(element_table[0]), + (int (*)(const void *, const void *)) strcmp); + if (element != 0) { + struct result res = element->convert(n, &status, style); + box = res.box; + convert_children = res.convert_children; } /* special elements must be inline or block */ @@ -294,28 +267,42 @@ struct box * convert_xml_to_box(xmlNode * n, struct content *content, } else if (n->type == XML_TEXT_NODE) { text = squash_tolat1(n->content); - } - content->size += sizeof(struct box) + sizeof(struct css_style); - - if (text != 0) { + /* if the text is just a space, combine it with the preceding + * text node, if any */ if (text[0] == ' ' && text[1] == 0) { if (inline_container != 0) { assert(inline_container->last != 0); inline_container->last->space = 1; } xfree(text); - if (style != 0) - free(style); + LOG(("depth %i, node %p, node type %i END", depth, n, n->type)); return inline_container; } + + /* text nodes are converted to inline boxes */ + box = box_create(BOX_INLINE, parent_style, status.href, title); + box->length = strlen(text); + if (text[box->length - 1] == ' ') { + box->space = 1; + box->length--; + } + box->text = text; + box->font = font_open(content->data.html.fonts, box->style); + + } else { + /* not an element or text node: ignore it (eg. comment) */ + LOG(("depth %i, node %p, node type %i END", depth, n, n->type)); + return inline_container; } + content->size += sizeof(struct box) + sizeof(struct css_style); + if (text != 0 || (box != 0 && style->display == CSS_DISPLAY_INLINE) || - (n->type == XML_ELEMENT_NODE && (style->float_ == CSS_FLOAT_LEFT || - style->float_ == CSS_FLOAT_RIGHT))) { - /* text nodes are converted to inline boxes, wrapped in an inline container block */ + style->float_ == CSS_FLOAT_LEFT || + style->float_ == CSS_FLOAT_RIGHT) { + /* this is an inline box */ if (inline_container == 0) { /* this is the first inline node: make a container */ inline_container = xcalloc(1, sizeof(struct box)); @@ -323,55 +310,44 @@ struct box * convert_xml_to_box(xmlNode * n, struct content *content, box_add_child(parent, inline_container); } - if (text != 0) { - LOG(("text node")); - box = box_create(BOX_INLINE, parent_style, href, title); + if (text != 0 || (box != 0 && style->float_ == CSS_FLOAT_NONE)) { + /* text or inline special box */ + assert(box != 0); box_add_child(inline_container, box); - box->length = strlen(text); - if (text[0] == ' ') { + if (text != 0 && text[0] == ' ') { box->length--; memmove(text, text + 1, box->length); if (box->prev != 0) box->prev->space = 1; } - if (text[box->length - 1] == ' ') { - box->space = 1; - box->length--; - } else { - box->space = 0; - } - box->text = text; - box->font = font_open(content->data.html.fonts, box->style); - - } else if (style->float_ == CSS_FLOAT_LEFT || style->float_ == CSS_FLOAT_RIGHT) { + LOG(("depth %i, node %p, node type %i END", depth, n, n->type)); + return inline_container; + } else { + /* float: insert a float box between the parent and current node */ + assert(style->float_ == CSS_FLOAT_LEFT || style->float_ == CSS_FLOAT_RIGHT); LOG(("float")); - parent = box_create(BOX_FLOAT_LEFT, 0, href, title); + parent = box_create(BOX_FLOAT_LEFT, 0, status.href, title); if (style->float_ == CSS_FLOAT_RIGHT) parent->type = BOX_FLOAT_RIGHT; box_add_child(inline_container, parent); if (style->display == CSS_DISPLAY_INLINE) style->display = CSS_DISPLAY_BLOCK; - - } else { - assert(box != 0); - box_add_child(inline_container, box); - return inline_container; } } - if (n->type == XML_ELEMENT_NODE && text == 0) { + assert(n->type == XML_ELEMENT_NODE); + switch (style->display) { case CSS_DISPLAY_BLOCK: /* blocks get a node in the box tree */ if (box == 0) - box = box_create(BOX_BLOCK, style, href, title); + box = box_create(BOX_BLOCK, style, status.href, title); else box->type = BOX_BLOCK; box_add_child(parent, box); inline_container_c = 0; - for (c = n->children; c != 0; c = c->next) + for (c = n->children; convert_children && c != 0; c = c->next) inline_container_c = convert_xml_to_box(c, content, style, selector, depth + 1, box, inline_container_c, - href, current_select, current_option, - current_textarea, current_form, elements); + status); if (style->float_ == CSS_FLOAT_NONE) /* continue in this inline container if this is a float */ inline_container = 0; @@ -382,44 +358,40 @@ struct box * convert_xml_to_box(xmlNode * n, struct content *content, for (c = n->children; c != 0; c = c->next) inline_container = convert_xml_to_box(c, content, style, selector, depth + 1, parent, inline_container, - href, current_select, current_option, - current_textarea, current_form, elements); + status); break; case CSS_DISPLAY_TABLE: - box = box_create(BOX_TABLE, style, href, title); + box = box_create(BOX_TABLE, style, status.href, title); box_add_child(parent, box); for (c = n->children; c != 0; c = c->next) convert_xml_to_box(c, content, style, selector, depth + 1, box, 0, - href, current_select, current_option, - current_textarea, current_form, elements); + status); inline_container = 0; break; case CSS_DISPLAY_TABLE_ROW_GROUP: case CSS_DISPLAY_TABLE_HEADER_GROUP: case CSS_DISPLAY_TABLE_FOOTER_GROUP: - box = box_create(BOX_TABLE_ROW_GROUP, style, href, title); + box = box_create(BOX_TABLE_ROW_GROUP, style, status.href, title); box_add_child(parent, box); inline_container_c = 0; for (c = n->children; c != 0; c = c->next) inline_container_c = convert_xml_to_box(c, content, style, selector, depth + 1, box, inline_container_c, - href, current_select, current_option, - current_textarea, current_form, elements); + status); inline_container = 0; break; case CSS_DISPLAY_TABLE_ROW: - box = box_create(BOX_TABLE_ROW, style, href, title); + box = box_create(BOX_TABLE_ROW, style, status.href, title); box_add_child(parent, box); for (c = n->children; c != 0; c = c->next) convert_xml_to_box(c, content, style, selector, depth + 1, box, 0, - href, current_select, current_option, - current_textarea, current_form, elements); + status); inline_container = 0; break; case CSS_DISPLAY_TABLE_CELL: - box = box_create(BOX_TABLE_CELL, style, href, title); + box = box_create(BOX_TABLE_CELL, style, status.href, title); if ((s = (char *) xmlGetProp(n, (const xmlChar *) "colspan"))) { if ((box->columns = strtol(s, 0, 10)) == 0) box->columns = 1; @@ -430,14 +402,12 @@ struct box * convert_xml_to_box(xmlNode * n, struct content *content, for (c = n->children; c != 0; c = c->next) inline_container_c = convert_xml_to_box(c, content, style, selector, depth + 1, box, inline_container_c, - href, current_select, current_option, - current_textarea, current_form, elements); + status); inline_container = 0; break; default: break; } - } LOG(("depth %i, node %p, node type %i END", depth, n, n->type)); return inline_container; @@ -445,7 +415,12 @@ struct box * convert_xml_to_box(xmlNode * n, struct content *content, /** - * get the style for an element + * Get the style for an element + * + * The style is collected from three sources: + * 1. any styles for this element in the document stylesheet(s) + * 2. non-CSS HTML attributes + * 3. the 'style' attribute */ struct css_style * box_get_style(struct content ** stylesheet, @@ -549,6 +524,293 @@ struct css_style * box_get_style(struct content ** stylesheet, } +/** + * Special case elements + * + * These functions are called by convert_xml_to_box when an element is being + * converted, according to the entries in element_table (top of file). + * + * The parameters are the xmlNode, a status structure for the conversion, and + * the style found for the element. + * + * If a box is created, it is returned in the result structure. The + * convert_children field should be 1 if convert_xml_to_box should convert the + * node's children recursively, 0 if it should ignore them (presumably they + * have been processed in some way by the function). + */ + +struct result box_a(xmlNode *n, struct status *status, + struct css_style *style) +{ + char *s; + if ((s = (char *) xmlGetProp(n, (const xmlChar *) "href"))) + status->href = s; + return (struct result) {0, 1}; +} + +struct result box_image(xmlNode *n, struct status *status, + struct css_style *style) +{ + struct box *box; + char *s, *url; + /*xmlChar *s2;*/ + + /* box type is decided by caller, BOX_INLINE is just a default */ + box = box_create(BOX_INLINE, style, status->href, status->title); + + /* handle alt text */ + /*if ((s2 = xmlGetProp(n, (const xmlChar *) "alt"))) { + box->text = squash_tolat1(s2); + box->length = strlen(box->text); + box->font = font_open(content->data.html.fonts, style); + free(s2); + }*/ + + /* img without src is an error */ + if (!(s = (char *) xmlGetProp(n, (const xmlChar *) "src"))) + return (struct result) {box, 0}; + + url = url_join(s, status->content->url); + LOG(("image '%s'", url)); + xmlFree(s); + + /* start fetch */ + html_fetch_object(status->content, url, box); + + return (struct result) {box, 0}; +} + +struct result box_form(xmlNode *n, struct status *status, + struct css_style *style) +{ + status->current_form = create_form(n); + add_form_element(status->elements, status->current_form); + return (struct result) {0, 1}; +} + +struct result box_textarea(xmlNode *n, struct status *status, + struct css_style *style) +{ + xmlChar *content; + struct box* box = 0; + char* s; + + box = box_create(BOX_INLINE, style, NULL, 0); + box->gadget = xcalloc(1, sizeof(struct gui_gadget)); + box->gadget->type = GADGET_TEXTAREA; + box->gadget->form = status->current_form; + + content = xmlNodeGetContent(n); + box->gadget->data.textarea.text = squash_tolat1(content); /* squash ? */ + xmlFree(content); + + if ((s = (char *) xmlGetProp(n, (const xmlChar *) "cols"))) + { + box->gadget->data.textarea.cols = atoi(s); + xmlFree(s); + } + else + box->gadget->data.textarea.cols = 40; + + if ((s = (char *) xmlGetProp(n, (const xmlChar *) "rows"))) + { + box->gadget->data.textarea.rows = atoi(s); + xmlFree(s); + } + else + box->gadget->data.textarea.rows = 16; + + if ((s = (char *) xmlGetProp(n, (const xmlChar *) "name"))) + { + box->gadget->name = s; + } + + add_gadget_element(status->elements, box->gadget); + + return (struct result) {box, 0}; +} + +struct result box_select(xmlNode *n, struct status *status, + struct css_style *style) +{ + struct box* box = 0; + char* s; + xmlNode *c; + + box = box_create(BOX_INLINE, style, NULL, 0); + box->gadget = xcalloc(1, sizeof(struct gui_gadget)); + box->gadget->type = GADGET_SELECT; + box->gadget->form = status->current_form; + + if ((s = (char *) xmlGetProp(n, (const xmlChar *) "size"))) + { + box->gadget->data.select.size = atoi(s); + xmlFree(s); + } + else + box->gadget->data.select.size = 1; + + if ((s = (char *) xmlGetProp(n, (const xmlChar *) "multiple"))) { + box->gadget->data.select.multiple = 1; + } + + if ((s = (char *) xmlGetProp(n, (const xmlChar *) "name"))) { + box->gadget->name = s; + } + + box->gadget->data.select.items = NULL; + box->gadget->data.select.numitems = 0; + /* TODO: multiple */ + + for (c = n->children; c != 0; c = c->next) { + if (strcmp((const char *) c->name, "option") == 0) { + xmlChar *content = xmlNodeGetContent(c); + add_option(c, box->gadget, squash_tolat1(content)); + xmlFree(content); + } + } + add_gadget_element(status->elements, box->gadget); + + return (struct result) {box, 0}; +} + +void add_option(xmlNode* n, struct gui_gadget* current_select, char *text) +{ + struct formoption* option; + char* s; + assert(current_select != 0); + + if (current_select->data.select.items == 0) + { + option = xcalloc(1, sizeof(struct formoption)); + current_select->data.select.items = option; + } + else + { + struct formoption* current; + option = xcalloc(1, sizeof(struct formoption)); + current = current_select->data.select.items; + /* TODO: make appending constant time */ + while (current->next != 0) + current = current->next; + current->next = option; + } + + option->text = text; + + if ((s = (char *) xmlGetProp(n, (const xmlChar *) "selected"))) { + option->selected = -1; + xmlFree(s); + } + + if ((s = (char *) xmlGetProp(n, (const xmlChar *) "value"))) { + option->value = s; + } +} + +struct result box_input(xmlNode *n, struct status *status, + struct css_style *style) +{ + struct box* box = 0; + struct gui_gadget *gadget = 0; + char *s, *type; + + type = (char *) xmlGetProp(n, (const xmlChar *) "type"); + + /* the default type is "text" */ + if (type == 0 || stricmp(type, "text") == 0 || + stricmp(type, "password") == 0) + { + box = box_create(BOX_INLINE, style, NULL, 0); + box->gadget = gadget = xcalloc(1, sizeof(struct gui_gadget)); + gadget->type = GADGET_TEXTBOX; + + gadget->data.textbox.maxlength = 32; + if ((s = (char *) xmlGetProp(n, (const xmlChar *) "maxlength"))) { + gadget->data.textbox.maxlength = atoi(s); + xmlFree(s); + } + + gadget->data.textbox.size = box->gadget->data.textbox.maxlength; + if ((s = (char *) xmlGetProp(n, (const xmlChar *) "size"))) { + gadget->data.textbox.size = atoi(s); + xmlFree(s); + } + + gadget->data.textbox.text = xcalloc( + gadget->data.textbox.maxlength + 2, sizeof(char)); + + if ((s = (char *) xmlGetProp(n, (const xmlChar *) "value"))) { + strncpy(gadget->data.textbox.text, s, + gadget->data.textbox.maxlength); + xmlFree(s); + } + + } + else if (stricmp(type, "hidden") == 0) + { + gadget = xcalloc(1, sizeof(struct gui_gadget)); + gadget->type = GADGET_HIDDEN; + + if ((s = (char *) xmlGetProp(n, (const xmlChar *) "value"))) + gadget->data.hidden.value = s; + } + else if (stricmp(type, "checkbox") == 0 || stricmp(type, "radio") == 0) + { + box = box_create(BOX_INLINE, style, NULL, 0); + box->gadget = gadget = xcalloc(1, sizeof(struct gui_gadget)); + if (type[0] == 'c' || type[0] == 'C') + gadget->type = GADGET_CHECKBOX; + else + gadget->type = GADGET_RADIO; + + if ((s = (char *) xmlGetProp(n, (const xmlChar *) "checked"))) { + if (gadget->type == GADGET_CHECKBOX) + gadget->data.checkbox.selected = -1; + else + gadget->data.radio.selected = -1; + xmlFree(s); + } + + if ((s = (char *) xmlGetProp(n, (const xmlChar *) "value"))) { + if (gadget->type == GADGET_CHECKBOX) + gadget->data.checkbox.value = s; + else + gadget->data.radio.value = s; + } + } + else if (stricmp(type, "submit") == 0 || stricmp(type, "reset") == 0) + { + box = box_create(BOX_INLINE, style, NULL, 0); + box->gadget = gadget = xcalloc(1, sizeof(struct gui_gadget)); + gadget->type = GADGET_ACTIONBUTTON; + + if ((s = (char *) xmlGetProp(n, (const xmlChar *) "value"))) { + gadget->data.actionbutt.label = s; + } + else + { + gadget->data.actionbutt.label = xstrdup(type); + gadget->data.actionbutt.label[0] = toupper(type[0]); + } + + box->gadget->data.actionbutt.butttype = strdup(type); + } + + if (type != 0) + xmlFree(type); + + if (gadget != 0) { + gadget->form = status->current_form; + if ((s = (char *) xmlGetProp(n, (const xmlChar *) "name"))) + gadget->name = s; + add_gadget_element(status->elements, gadget); + } + + return (struct result) {box, 0}; +} + + /** * print a box tree to standard output */ @@ -620,6 +882,7 @@ void box_normalise_block(struct box *block) assert(block != 0); assert(block->type == BOX_BLOCK || block->type == BOX_TABLE_CELL); LOG(("block %p, block->type %u", block, block->type)); + gui_multitask(); for (child = block->children; child != 0; child = next_child) { LOG(("child %p, child->type = %d", child, child->type)); @@ -1026,7 +1289,7 @@ void box_free_box(struct box *box) } free(box->text); - free(box->title); + xmlFree(box->title); /* only free href if we're the top most user */ if (box->href != 0) @@ -1040,349 +1303,10 @@ void box_free_box(struct box *box) /** - * add an image to the box tree + * form helper functions */ -struct box* box_image(xmlNode *n, struct content *content, - struct css_style *style, char *href, char *title) -{ - struct box *box; - char *s, *url; - xmlChar *s2; - struct fetch_data *fetch_data; - - /* box type is decided by caller, BOX_INLINE is just a default */ - box = box_create(BOX_INLINE, style, href, title); - - /* handle alt text */ - /*if ((s2 = xmlGetProp(n, (const xmlChar *) "alt"))) { - box->text = squash_tolat1(s2); - box->length = strlen(box->text); - box->font = font_open(content->data.html.fonts, style); - free(s2); - }*/ - - /* img without src is an error */ - if (!(s = (char *) xmlGetProp(n, (const xmlChar *) "src"))) - return box; - - url = url_join(s, content->url); - LOG(("image '%s'", url)); - xmlFree(s); - - /* start fetch */ - html_fetch_object(content, url, box); - - return box; -} - - -struct box* box_textarea(xmlNode* n, struct css_style* style, struct form* current_form) -{ - struct box* box = 0; - char* s; - - LOG(("creating box")); - box = box_create(BOX_INLINE, style, NULL, 0); - LOG(("creating gadget")); - box->gadget = xcalloc(1, sizeof(struct gui_gadget)); - box->gadget->type = GADGET_TEXTAREA; - box->gadget->form = current_form; - - box->text = 0; - box->length = 0; - box->font = 0; - - if ((s = (char *) xmlGetProp(n, (const xmlChar *) "cols"))) - { - box->gadget->data.textarea.cols = atoi(s); - xmlFree(s); - } - else - box->gadget->data.textarea.cols = 40; - - if ((s = (char *) xmlGetProp(n, (const xmlChar *) "rows"))) - { - box->gadget->data.textarea.rows = atoi(s); - xmlFree(s); - } - else - box->gadget->data.textarea.rows = 16; - - if ((s = (char *) xmlGetProp(n, (const xmlChar *) "name"))) - { - box->gadget->name = s; - } - - box->gadget->data.textarea.text = xcalloc(1, sizeof(char)); - - return box; -} - -struct box* box_select(xmlNode * n, struct css_style* style, struct form* current_form) -{ - struct box* box = 0; - char* s; - - LOG(("creating box")); - box = box_create(BOX_INLINE, style, NULL, 0); - LOG(("creating gadget")); - box->gadget = xcalloc(1, sizeof(struct gui_gadget)); - box->gadget->type = GADGET_SELECT; - box->gadget->form = current_form; - - box->text = 0; - box->length = 0; - box->font = 0; - - if ((s = (char *) xmlGetProp(n, (const xmlChar *) "size"))) - { - box->gadget->data.select.size = atoi(s); - xmlFree(s); - } - else - box->gadget->data.select.size = 1; - - if ((s = (char *) xmlGetProp(n, (const xmlChar *) "multiple"))) { - box->gadget->data.select.multiple = 1; - } - - if ((s = (char *) xmlGetProp(n, (const xmlChar *) "name"))) { - box->gadget->name = s; - } - - box->gadget->data.select.items = NULL; - box->gadget->data.select.numitems = 0; - /* to do: multiple, name */ - LOG(("returning from select")); - return box; -} - -struct formoption* box_option(xmlNode* n, struct css_style* style, struct gui_gadget* current_select) -{ - struct formoption* option; - char* s; - assert(current_select != 0); - - LOG(("realloc option")); - if (current_select->data.select.items == 0) - { - option = xcalloc(1, sizeof(struct formoption)); - current_select->data.select.items = option; - } - else - { - struct formoption* current; - option = xcalloc(1, sizeof(struct formoption)); - current = current_select->data.select.items; - while (current->next != 0) - current = current->next; - current->next = option; - } - - /* TO DO: set selected / value here */ - if ((s = (char *) xmlGetProp(n, (const xmlChar *) "selected"))) { - option->selected = -1; - xmlFree(s); - } - - if ((s = (char *) xmlGetProp(n, (const xmlChar *) "value"))) { - option->value = s; - } - - LOG(("returning")); - return option; -} - -void textarea_addtext(struct gui_gadget* textarea, char* text) -{ - assert (textarea != 0); - assert (text != 0); - - if (textarea->data.textarea.text == 0) - { - textarea->data.textarea.text = xstrdup(text); - } - else - { - textarea->data.textarea.text = xrealloc(textarea->data.textarea.text, strlen(textarea->data.textarea.text) + strlen(text) + 1); - strcat(textarea->data.textarea.text, text); - } -} - -void option_addtext(struct formoption* option, char* text) -{ - assert(option != 0); - assert(text != 0); - - if (option->text == 0) - { - LOG(("option->text is 0")); - option->text = xstrdup(text); - } - else - { - LOG(("option->text is realloced")); - option->text = xrealloc(option->text, strlen(option->text) + strlen(text) + 1); - strcat(option->text, text); - } - LOG(("returning")); - return; -} - -struct box* box_input(xmlNode * n, struct css_style* style, struct form* current_form, struct page_elements* elements) -{ - struct box* box = 0; - char* s; - char* type; - - if ((type = (char *) xmlGetProp(n, (const xmlChar *) "type"))) - { - if (stricmp(type, "hidden") == 0) - { - struct gui_gadget* g = xcalloc(1, sizeof(struct gui_gadget)); - g->type = GADGET_HIDDEN; - g->form = current_form; - - if ((s = (char *) xmlGetProp(n, (const xmlChar *) "value"))) { - g->data.hidden.value = s; - } - - if ((s = (char *) xmlGetProp(n, (const xmlChar *) "name"))) { - g->name = s; - } - add_gadget_element(elements, g); - } - - if (stricmp(type, "checkbox") == 0 || stricmp(type, "radio") == 0) - { - box = box_create(BOX_INLINE, style, NULL, 0); - box->gadget = xcalloc(1, sizeof(struct gui_gadget)); - if (type[0] == 'c') - box->gadget->type = GADGET_CHECKBOX; - else - box->gadget->type = GADGET_RADIO; - box->gadget->form = current_form; - - box->text = 0; - box->length = 0; - box->font = 0; - - if ((s = (char *) xmlGetProp(n, (const xmlChar *) "checked"))) { - if (type[0] == 'c') - box->gadget->data.checkbox.selected = -1; - else - box->gadget->data.radio.selected = -1; - xmlFree(s); - } - - if ((s = (char *) xmlGetProp(n, (const xmlChar *) "value"))) { - if (type[0] == 'c') - box->gadget->data.checkbox.value = s; - else - box->gadget->data.radio.value = s; - } - - if ((s = (char *) xmlGetProp(n, (const xmlChar *) "name"))) { - box->gadget->name = s; - } - add_gadget_element(elements, box->gadget); - } - - if (stricmp(type, "submit") == 0 || stricmp(type, "reset") == 0) - { - //style->display = CSS_DISPLAY_BLOCK; - - box = box_create(BOX_INLINE, style, NULL, 0); - box->gadget = xcalloc(1, sizeof(struct gui_gadget)); - box->gadget->type = GADGET_ACTIONBUTTON; - box->gadget->form = current_form; - - box->text = 0; - box->length = 0; - box->font = 0; - - if ((s = (char *) xmlGetProp(n, (const xmlChar *) "value"))) { - box->gadget->data.actionbutt.label = s; - } - else - { - box->gadget->data.actionbutt.label = xstrdup(type); - box->gadget->data.actionbutt.label[0] = toupper(type[0]); - } - - if ((s = (char *) xmlGetProp(n, (const xmlChar *) "name"))) { - box->gadget->name = s; - } - - box->gadget->data.actionbutt.butttype = strdup(type); - - add_gadget_element(elements, box->gadget); - } - - if (!(stricmp(type, "text") == 0 || stricmp(type, "password") == 0)) - { - - xmlFree (type); - return box; - } - - } - //style->display = CSS_DISPLAY_BLOCK; - fprintf(stderr, "CREATING TEXT BOX!\n"); - - box = box_create(BOX_INLINE, style, NULL, 0); - box->gadget = xcalloc(1, sizeof(struct gui_gadget)); - box->gadget->type = GADGET_TEXTBOX; - box->gadget->form = current_form; - - box->text = 0; - box->length = 0; - box->font = 0; - -#ifdef ARSEMONKEYS -// box->gadget->data.textbox.maxlength = 255; -// if ((s = (char *) xmlGetProp(n, (xmlChar *) "maxlength"))) -// -#endif - box->gadget->data.textbox.maxlength = 32; - if ((s = (char *) xmlGetProp(n, (const xmlChar *) "maxlength"))) { -//>>>>>> 1.31 - box->gadget->data.textbox.maxlength = atoi(s); - xmlFree(s); - } - -#ifdef ARSEMONKEYS -//<<<<<<< box.c -// box->gadget->data.textbox.size = 20;/*box->gadget->data.textbox.maxlength;*/ -// if ((s = (char *) xmlGetProp(n, (xmlChar *) "size"))) -//======= -#endif - box->gadget->data.textbox.size = box->gadget->data.textbox.maxlength; - if ((s = (char *) xmlGetProp(n, (const xmlChar *) "size"))) { - box->gadget->data.textbox.size = atoi(s); - xmlFree(s); - } - - box->gadget->data.textbox.text = xcalloc( - box->gadget->data.textbox.maxlength + 2, sizeof(char)); - - if ((s = (char *) xmlGetProp(n, (const xmlChar *) "value"))) { - strncpy(box->gadget->data.textbox.text, s, - box->gadget->data.textbox.maxlength); - xmlFree(s); - } - - if ((s = (char *) xmlGetProp(n, (const xmlChar *) "name"))) { - box->gadget->name = s; - } - add_gadget_element(elements, box->gadget); - - xmlFree(type); - return box; -} - -struct form* box_form(xmlNode* n) +struct form* create_form(xmlNode* n) { struct form* form; char* s; @@ -1417,17 +1341,34 @@ void add_gadget_element(struct page_elements* pe, struct gui_gadget* g) pe->numGadgets++; } -void add_img_element(struct page_elements* pe, struct img* i) -{ - pe->images = xrealloc(pe->images, (pe->numImages + 1) * sizeof(struct img*)); - pe->images[pe->numImages] = i; - pe->numImages++; -} /** * add an object to the box tree */ +/* } else if (strcmp((const char*) n->name, "object") == 0) { LOG(("object")); + box = box_object(n, content, style, href); +*/ /* TODO - param data structure + + for (c = n->children; c != 0; c = c->next) { + + if (strcmp((const char*) c->name, "param") == 0) { + + LOG(("param")); + current_param = box_param(c, style, current_object); + } + } */ +/* + } else if (strcmp((const char*) n->name, "embed") == 0) { LOG(("embed")); + box = box_embed(n, content, style, href); + + } else if (strcmp((const char*) n->name, "applet") == 0) { LOG(("applet")); + box = box_applet(n, content, style, href); + + } +*/ + + struct box* box_object(xmlNode *n, struct content *content, struct css_style *style, char *href) { @@ -1435,7 +1376,6 @@ struct box* box_object(xmlNode *n, struct content *content, struct plugin_object *po; char *s, *url; xmlChar *s2; - struct fetch_data *fetch_data; /* box type is decided by caller, BOX_INLINE is just a default */ box = box_create(BOX_INLINE, style, href, 0); @@ -1516,7 +1456,6 @@ struct box* box_embed(xmlNode *n, struct content *content, struct plugin_object *po; char *s, *url; xmlChar *s2; - struct fetch_data *fetch_data; /* box type is decided by caller, BOX_INLINE is just a default */ box = box_create(BOX_INLINE, style, href, 0); @@ -1550,7 +1489,6 @@ struct box* box_applet(xmlNode *n, struct content *content, struct plugin_object *po; char *s, *url; xmlChar *s2; - struct fetch_data *fetch_data; /* box type is decided by caller, BOX_INLINE is just a default */ box = box_create(BOX_INLINE, style, href, 0); -- cgit v1.2.3