summaryrefslogtreecommitdiff
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
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
-rw-r--r--!NetSurf/Resources/en/Messages2
-rw-r--r--desktop/browser.c49
-rw-r--r--render/box.c130
-rw-r--r--render/box.h17
-rw-r--r--render/layout.c13
-rw-r--r--riscos/htmlredraw.c3
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;