diff options
Diffstat (limited to 'render')
-rw-r--r-- | render/box.c | 130 | ||||
-rw-r--r-- | render/box.h | 17 | ||||
-rw-r--r-- | render/layout.c | 13 |
3 files changed, 115 insertions, 45 deletions
diff --git a/render/box.c b/render/box.c index 4f76072f0..7caaae7e6 100644 --- a/render/box.c +++ b/render/box.c @@ -687,6 +687,7 @@ struct result box_textarea(xmlNode *n, struct status *status, box = box_create(style, NULL, 0); box->gadget = xcalloc(1, sizeof(struct gui_gadget)); + box->gadget->box = box; box->gadget->type = GADGET_TEXTAREA; box->gadget->form = status->current_form; style->display = CSS_DISPLAY_INLINE_BLOCK; @@ -727,74 +728,119 @@ struct result box_textarea(xmlNode *n, struct status *status, struct result box_select(xmlNode *n, struct status *status, struct css_style *style) { - struct box* box = 0; + struct box *box; + struct box *inline_container; + struct box *inline_box; + struct gui_gadget *gadget = xcalloc(1, sizeof(struct gui_gadget)); char* s; - xmlNode *c; + xmlNode *c, *c2; - box = box_create(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; + gadget->type = GADGET_SELECT; + gadget->form = status->current_form; + gadget->data.select.multiple = false; 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; + gadget->data.select.multiple = true; + xmlFree(s); } - box->gadget->data.select.items = NULL; - box->gadget->data.select.numitems = 0; - /* TODO: multiple */ + gadget->data.select.items = NULL; + gadget->data.select.last_item = NULL; + gadget->data.select.num_items = 0; + gadget->data.select.num_selected = 0; 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)); + add_option(c, gadget, squash_tolat1(content)); xmlFree(content); + gadget->data.select.num_items++; + } else if (strcmp((const char *) c->name, "optgroup") == 0) { + for (c2 = c->children; c2; c2 = c2->next) { + if (strcmp((const char *) c2->name, "option") == 0) { + xmlChar *content = xmlNodeGetContent(c2); + add_option(c2, gadget, squash_tolat1(content)); + xmlFree(content); + gadget->data.select.num_items++; + } + } } } - add_gadget_element(status->elements, box->gadget); + + if (gadget->data.select.num_items == 0) { + /* no options: ignore entire select */ + xfree(gadget); + return (struct result) {0, 0}; + } + + if ((s = (char *) xmlGetProp(n, (const xmlChar *) "name"))) { + gadget->name = s; + } + + box = box_create(style, NULL, 0); + box->gadget = gadget; + gadget->box = box; + style->display = CSS_DISPLAY_INLINE_BLOCK; + + inline_container = box_create(0, 0, 0); + inline_container->type = BOX_INLINE_CONTAINER; + inline_box = box_create(style, 0, 0); + inline_box->type = BOX_INLINE; + inline_box->style_clone = 1; + box_add_child(inline_container, inline_box); + box_add_child(box, inline_container); + + if (!gadget->data.select.multiple && + gadget->data.select.num_selected == 0) { + gadget->data.select.current = gadget->data.select.items; + gadget->data.select.current->selected = true; + gadget->data.select.num_selected = 1; + } + + if (gadget->data.select.num_selected == 0) + inline_box->text = xstrdup(messages_get("Form_None")); + else if (gadget->data.select.num_selected == 1) + inline_box->text = xstrdup(gadget->data.select.current->text); + else + inline_box->text = xstrdup(messages_get("Form_Many")); + + inline_box->length = strlen(inline_box->text); + inline_box->font = font_open(status->content->data.html.fonts, style); + + add_gadget_element(status->elements, gadget); return (struct result) {box, 0}; } void add_option(xmlNode* n, struct gui_gadget* current_select, char *text) { - struct formoption* option; - char* s; + struct formoption *option = xcalloc(1, sizeof(struct formoption)); + char *s, *c; + 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; - } + current_select->data.select.last_item->next = option; + current_select->data.select.last_item = option; + + for (c = text; *c; c++) + if (*c == ' ') + *c = 160; + option->selected = option->initial_selected = false; option->text = text; + option->value = 0; if ((s = (char *) xmlGetProp(n, (const xmlChar *) "selected"))) { - option->selected = -1; xmlFree(s); + if (current_select->data.select.num_selected == 0 || + current_select->data.select.multiple) { + option->selected = option->initial_selected = true; + current_select->data.select.num_selected++; + current_select->data.select.current = option; + } } if ((s = (char *) xmlGetProp(n, (const xmlChar *) "value"))) { @@ -816,11 +862,13 @@ struct result box_input(xmlNode *n, struct status *status, { box = box_input_text(n, status, style, false); gadget = box->gadget; + gadget->box = box; } else if (stricmp(type, "password") == 0) { box = box_input_text(n, status, style, true); gadget = box->gadget; + gadget->box = box; } else if (stricmp(type, "hidden") == 0) { @@ -835,6 +883,7 @@ struct result box_input(xmlNode *n, struct status *status, { box = box_create(style, NULL, 0); box->gadget = gadget = xcalloc(1, sizeof(struct gui_gadget)); + gadget->box = box; if (type[0] == 'c' || type[0] == 'C') gadget->type = GADGET_CHECKBOX; else @@ -880,6 +929,7 @@ struct result box_input(xmlNode *n, struct status *status, { box = box_create(style, NULL, 0); box->gadget = gadget = xcalloc(1, sizeof(struct gui_gadget)); + gadget->box = box; gadget->type = GADGET_IMAGE; if ((s = (char *) xmlGetProp(n, (const xmlChar*) "name"))) { gadget->data.image.n = s; @@ -922,6 +972,7 @@ struct box *box_input_text(xmlNode *n, struct status *status, style->display = CSS_DISPLAY_INLINE_BLOCK; box->gadget = xcalloc(1, sizeof(struct gui_gadget)); + box->gadget->box = box; box->gadget->maxlength = 100; if ((s = (char *) xmlGetProp(n, (const xmlChar *) "maxlength"))) { @@ -984,6 +1035,7 @@ struct result box_button(xmlNode *n, struct status *status, xmlFree(type); box->gadget->form = status->current_form; + box->gadget->box = box; box->gadget->name = (char *) xmlGetProp(n, (const xmlChar *) "name"); box->gadget->value = (char *) xmlGetProp(n, (const xmlChar *) "value"); diff --git a/render/box.h b/render/box.h index c411f47e3..2a3b15633 100644 --- a/render/box.h +++ b/render/box.h @@ -10,6 +10,7 @@ #define _NETSURF_RENDER_BOX_H_ #include <limits.h> +#include <stdbool.h> #include "libxml/HTMLparser.h" #include "netsurf/css/css.h" #include "netsurf/render/font.h" @@ -33,7 +34,8 @@ struct column { }; struct formoption { - int selected; + bool selected; + bool initial_selected; char* value; char* text; struct formoption* next; @@ -48,7 +50,8 @@ struct gui_gadget { char *name; char *value; char *initial_value; - struct form* form; + struct form *form; + struct box *box; struct box *caret_inline_container; struct box *caret_text_box; int caret_char_offset; @@ -65,10 +68,12 @@ struct gui_gadget { int mx, my; } image; struct { - int numitems; - struct formoption* items; - int size; - int multiple; + int num_items; + struct formoption *items, *last_item; + bool multiple; + int num_selected; + /** Currently selected item, if num_selected == 1. */ + struct formoption *current; } select; struct { int selected; diff --git a/render/layout.c b/render/layout.c index 4c9f2a832..2c3d04e05 100644 --- a/render/layout.c +++ b/render/layout.c @@ -874,6 +874,19 @@ void calculate_inline_container_widths(struct box *box) break; case BOX_INLINE_BLOCK: + if (child->style != 0 && + child->style->width.width == CSS_WIDTH_LENGTH) { + width = len(&child->style->width.value.length, + child->style); + if (min < width) min = width; + max += width; + } else { + calculate_widths(child); + if (min < child->min_width) min = child->min_width; + max += child->max_width; + } + break; + case BOX_FLOAT_LEFT: case BOX_FLOAT_RIGHT: if (child->style != 0 && |