summaryrefslogtreecommitdiff
path: root/render
diff options
context:
space:
mode:
authorJames Bursa <james@netsurf-browser.org>2003-10-01 22:48:39 +0000
committerJames Bursa <james@netsurf-browser.org>2003-10-01 22:48:39 +0000
commit7ef999c573131e802270aecb4daf77a42130c011 (patch)
treefafee19529230614105286e1725ad2b38a021ce7 /render
parent92d5404afad67e4d615f59a873449d25dc6b92aa (diff)
downloadnetsurf-7ef999c573131e802270aecb4daf77a42130c011.tar.gz
netsurf-7ef999c573131e802270aecb4daf77a42130c011.tar.bz2
[project @ 2003-10-01 22:48:39 by bursa]
Improvements to <select>. svn path=/import/netsurf/; revision=341
Diffstat (limited to 'render')
-rw-r--r--render/box.c130
-rw-r--r--render/box.h17
-rw-r--r--render/layout.c13
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 &&