diff options
-rw-r--r-- | !NetSurf/Resources/en/Messages | 2 | ||||
-rw-r--r-- | desktop/browser.c | 49 | ||||
-rw-r--r-- | render/box.c | 130 | ||||
-rw-r--r-- | render/box.h | 17 | ||||
-rw-r--r-- | render/layout.c | 13 | ||||
-rw-r--r-- | riscos/htmlredraw.c | 3 |
6 files changed, 155 insertions, 59 deletions
diff --git a/!NetSurf/Resources/en/Messages b/!NetSurf/Resources/en/Messages index ffa532ad5..c33aa7b06 100644 --- a/!NetSurf/Resources/en/Messages +++ b/!NetSurf/Resources/en/Messages @@ -30,5 +30,7 @@ Downloaded:Download complete, %lu bytes # Forms Form_Submit:Submit Form_Reset:Reset +Form_None: +Form_Many:(Many) Not2xx:Server returned an error diff --git a/desktop/browser.c b/desktop/browser.c index 4da14f1f6..a38640276 100644 --- a/desktop/browser.c +++ b/desktop/browser.c @@ -21,6 +21,7 @@ #include "netsurf/render/font.h" #include "netsurf/render/layout.h" #include "netsurf/utils/log.h" +#include "netsurf/utils/messages.h" #include "netsurf/utils/utils.h" static void browser_window_start_throbber(struct browser_window* bw); @@ -464,20 +465,44 @@ void browser_window_gadget_select(struct browser_window* bw, struct gui_gadget* { struct formoption* o; int count; - - count = 0; - o = g->data.select.items; - while (o != NULL) - { - if (g->data.select.multiple == 0) - o->selected = 0; - if (count == item) - o->selected = !(o->selected); - o = o->next; - count++; + struct box *inline_box = g->box->children->children; + int x, y; + + for (count = 0, o = g->data.select.items; + o != NULL; + count++, o = o->next) { + if (!g->data.select.multiple) + o->selected = false; + if (count == item) { + if (g->data.select.multiple) { + if (o->selected) { + o->selected = false; + g->data.select.num_selected--; + } else { + o->selected = true; + g->data.select.num_selected++; + } + } else { + o->selected = true; + } + } + if (o->selected) + g->data.select.current = o; } - gui_redraw_gadget(bw, g); + xfree(inline_box->text); + if (g->data.select.num_selected == 0) + inline_box->text = xstrdup(messages_get("Form_None")); + else if (g->data.select.num_selected == 1) + inline_box->text = xstrdup(g->data.select.current->text); + else + inline_box->text = xstrdup(messages_get("Form_Many")); + inline_box->width = g->box->width; + inline_box->length = strlen(inline_box->text); + + box_coords(g->box, &x, &y); + gui_window_redraw(bw->window, x, y, + x + g->box->width, y + g->box->height); } int browser_window_gadget_click(struct browser_window* bw, unsigned long click_x, unsigned long click_y) 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 && diff --git a/riscos/htmlredraw.c b/riscos/htmlredraw.c index d0bce76dc..d41702692 100644 --- a/riscos/htmlredraw.c +++ b/riscos/htmlredraw.c @@ -126,8 +126,7 @@ void html_redraw_box(struct content *content, struct box * box, content_redraw(box->object, x, y, width, height, x0, y0, x1, y1); } else if (box->gadget && - (box->gadget->type == GADGET_SELECT || - box->gadget->type == GADGET_CHECKBOX || + (box->gadget->type == GADGET_CHECKBOX || box->gadget->type == GADGET_RADIO)) { wimp_icon icon; |