summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Bursa <james@netsurf-browser.org>2003-10-25 00:35:49 +0000
committerJames Bursa <james@netsurf-browser.org>2003-10-25 00:35:49 +0000
commitf1375fe19db064fcebf00433ce73eab99be038ef (patch)
tree19e239a41a8a68baab5b444447adc3aae5bf04fa
parent099d537267e8e4114128e59e2614c99d77dd4feb (diff)
downloadnetsurf-f1375fe19db064fcebf00433ce73eab99be038ef.tar.gz
netsurf-f1375fe19db064fcebf00433ce73eab99be038ef.tar.bz2
[project @ 2003-10-25 00:35:49 by bursa]
Split out and clean up form submit code. svn path=/import/netsurf/; revision=374
-rw-r--r--desktop/browser.c159
-rw-r--r--desktop/browser.h4
-rw-r--r--desktop/gui.h2
-rw-r--r--makefile2
-rw-r--r--render/box.c164
-rw-r--r--render/box.h63
-rw-r--r--render/form.c175
-rw-r--r--render/form.h89
-rw-r--r--riscos/gui.c7
-rw-r--r--riscos/gui.h2
-rw-r--r--riscos/htmlredraw.c8
11 files changed, 367 insertions, 308 deletions
diff --git a/desktop/browser.c b/desktop/browser.c
index 1eb881f1c..67a4670dc 100644
--- a/desktop/browser.c
+++ b/desktop/browser.c
@@ -21,6 +21,7 @@
#include "netsurf/desktop/browser.h"
#include "netsurf/render/box.h"
#include "netsurf/render/font.h"
+#include "netsurf/render/form.h"
#include "netsurf/render/layout.h"
#include "netsurf/utils/log.h"
#include "netsurf/utils/messages.h"
@@ -41,14 +42,13 @@ static void browser_window_callback(content_msg msg, struct content *c,
void *p1, void *p2, const char *error);
static void download_window_callback(content_msg msg, struct content *c,
void *p1, void *p2, const char *error);
-static void clear_radio_gadgets(struct browser_window* bw, struct box* box, struct gui_gadget* group);
-static void gui_redraw_gadget2(struct browser_window* bw, struct box* box, struct gui_gadget* g,
+static void clear_radio_gadgets(struct browser_window* bw, struct box* box, struct form_control* group);
+static void gui_redraw_gadget2(struct browser_window* bw, struct box* box, struct form_control* g,
unsigned long x, unsigned long y);
-static void browser_window_gadget_select(struct browser_window* bw, struct gui_gadget* g, int item);
+static void browser_window_gadget_select(struct browser_window* bw, struct form_control* g, int item);
static int browser_window_gadget_click(struct browser_window* bw, unsigned long click_x, unsigned long click_y);
-static void browser_form_submit(struct browser_window *bw, struct form *form);
-static char* browser_form_construct_get(struct page_elements *elements, struct formsubmit* fs);
-static void browser_form_get_append(char **s, int *length, char sep, char *name, char *value);
+static void browser_form_submit(struct browser_window *bw, struct form *form,
+ struct form_control *submit_button);
static void browser_window_textarea_click(struct browser_window* bw,
unsigned long actual_x, unsigned long actual_y,
long x, long y,
@@ -370,8 +370,7 @@ void browser_window_callback(content_msg msg, struct content *c,
break;
case CONTENT_MSG_REFORMAT:
- if (bw->current_content->status == CONTENT_STATUS_DONE)
- browser_window_reformat(bw, 0);
+ browser_window_reformat(bw, 0);
break;
default:
@@ -413,7 +412,7 @@ void download_window_callback(content_msg msg, struct content *c,
}
}
-void clear_radio_gadgets(struct browser_window* bw, struct box* box, struct gui_gadget* group)
+void clear_radio_gadgets(struct browser_window* bw, struct box* box, struct form_control* group)
{
struct box* c;
if (box == NULL)
@@ -440,7 +439,7 @@ void clear_radio_gadgets(struct browser_window* bw, struct box* box, struct gui_
clear_radio_gadgets(bw, c, group);
}
-void gui_redraw_gadget2(struct browser_window* bw, struct box* box, struct gui_gadget* g,
+void gui_redraw_gadget2(struct browser_window* bw, struct box* box, struct form_control* g,
unsigned long x, unsigned long y)
{
struct box* c;
@@ -458,15 +457,15 @@ void gui_redraw_gadget2(struct browser_window* bw, struct box* box, struct gui_g
gui_redraw_gadget2(bw, c, g, box->x + x, box->y + y);
}
-void gui_redraw_gadget(struct browser_window* bw, struct gui_gadget* g)
+void gui_redraw_gadget(struct browser_window* bw, struct form_control* g)
{
assert(bw->current_content->type == CONTENT_HTML);
gui_redraw_gadget2(bw, bw->current_content->data.html.layout->children, g, 0, 0);
}
-void browser_window_gadget_select(struct browser_window* bw, struct gui_gadget* g, int item)
+void browser_window_gadget_select(struct browser_window* bw, struct form_control* g, int item)
{
- struct formoption* o;
+ struct form_option* o;
int count;
struct box *inline_box = g->box->children->children;
int x, y;
@@ -533,7 +532,7 @@ int browser_window_gadget_click(struct browser_window* bw, unsigned long click_x
if (click_boxes[i].box->gadget)
{
- struct gui_gadget* g = click_boxes[i].box->gadget;
+ struct form_control* g = click_boxes[i].box->gadget;
/* gadget clicked */
switch (g->type)
@@ -551,7 +550,7 @@ int browser_window_gadget_click(struct browser_window* bw, unsigned long click_x
gui_redraw_gadget(bw, g);
break;
case GADGET_SUBMIT:
- browser_form_submit(bw, g->form);
+ browser_form_submit(bw, g->form, g);
break;
case GADGET_TEXTAREA:
browser_window_textarea_click(bw,
@@ -576,7 +575,7 @@ int browser_window_gadget_click(struct browser_window* bw, unsigned long click_x
box_coords(click_boxes[i].box, &x, &y);
g->data.image.mx = click_x - x;
g->data.image.my = click_y - y;
- browser_form_submit(bw, g->form);
+ browser_form_submit(bw, g->form, g);
break;
}
@@ -1068,7 +1067,7 @@ void browser_window_input_callback(struct browser_window *bw, char key, void *p)
char_offset--;
} else if (key == 10 || key == 13) {
/* Return/Enter hit */
- browser_form_submit(bw, form);
+ browser_form_submit(bw, form, 0);
/*TODO: remove caret from new page */
} else if (key == 9) {
/* Tab */
@@ -1570,31 +1569,28 @@ void browser_window_redraw_boxes(struct browser_window* bw, struct box_position*
}
-void browser_form_submit(struct browser_window *bw, struct form *form)
+void browser_form_submit(struct browser_window *bw, struct form *form,
+ struct form_control *submit_button)
{
- /*create submission request*/
- struct formsubmit* fs = (struct formsubmit*) xcalloc(1, sizeof(struct formsubmit));
- fs->form = form;
- /*fs->items = g;*/
- LOG(("Submission request created"));
+ struct form_successful_control *success;
- if (fs->form->method == method_GET) {
+ success = form_successful_controls(form, submit_button);
+
+ if (form->method == method_GET) {
/*GET request*/
/*GET basically munges the entire form data
into one URL. */
- char *url = browser_form_construct_get(&bw->current_content->data.html.elements,
- fs);
-
- LOG(("GET request"));
-
- /*send request*/
+ char *data = form_url_encode(success);
+ char *url = xcalloc(1, strlen(form->action) + strlen(data) + 2);
+ sprintf(url, "%s?%s", form->action, data);
+ free(data);
browser_window_open_location(bw, url);
xfree(url);
} else {
/*POST request*/
- assert(fs->form->method == method_POST);
+ assert(form->method == method_POST);
LOG(("POST request - not implemented yet"));
@@ -1604,104 +1600,5 @@ void browser_form_submit(struct browser_window *bw, struct form *form)
body.*/
}
- xfree(fs);
-}
-
-
-char* browser_form_construct_get(struct page_elements *elements, struct formsubmit* fs)
-{
- char *ret;
- int i,j, length;
- struct formoption* opt;
-
- ret = xstrdup(fs->form->action);
- length = strlen(ret);
-
- j=0;
- for (i=0;i<elements->numGadgets;i++){
- if(elements->gadgets[i]->form == fs->form){
-
- if(elements->gadgets[i]->name != 0){
- char *value = 0;
-
- switch(elements->gadgets[i]->type){
-
- case GADGET_HIDDEN: value = elements->gadgets[i]->data.hidden.value;
- break;
- case GADGET_TEXTBOX: value = elements->gadgets[i]->value;
- break;
- case GADGET_PASSWORD: value = elements->gadgets[i]->value;
- break;
- case GADGET_RADIO: if(elements->gadgets[i]->data.radio.selected == -1)
- value = elements->gadgets[i]->data.radio.value;
- break;
- case GADGET_CHECKBOX: if(elements->gadgets[i]->data.checkbox.selected == 1)
- value = elements->gadgets[i]->data.checkbox.value;
- break;
- case GADGET_SELECT: opt = elements->gadgets[i]->data.select.items;
- while(opt != NULL){
- if(opt->selected == -1 || opt->selected == 1) {
- browser_form_get_append(&ret, &length, j == 0 ? '?' : '&',
- elements->gadgets[i]->name, opt->value);
- j++;
- }
- opt = opt->next;
- }
- break;
- case GADGET_TEXTAREA: /* TODO */
- break;
- case GADGET_IMAGE: sprintf(elements->gadgets[i]->data.image.name,
- "%s.x",
- elements->gadgets[i]->data.image.n);
- sprintf(elements->gadgets[i]->data.image.value,
- "%d",
- elements->gadgets[i]->data.image.mx);
- browser_form_get_append(&ret, &length,
- j == 0 ? '?' : '&',
- elements->gadgets[i]->data.image.name,
- elements->gadgets[i]->data.image.value);
- sprintf(elements->gadgets[i]->data.image.name,
- "%s.y",
- elements->gadgets[i]->data.image.n);
- sprintf(elements->gadgets[i]->data.image.value,
- "%d",
- elements->gadgets[i]->data.image.my);
- browser_form_get_append(&ret, &length,
- j == 0 ? '?' : '&',
- elements->gadgets[i]->data.image.name,
- elements->gadgets[i]->data.image.value);
- j++;
- break;
- default: break;
- }
-
- if (value != 0) {
- browser_form_get_append(&ret, &length, j == 0 ? '?' : '&',
- elements->gadgets[i]->name, value);
- j++;
- }
- }
-
- }
- }
- return ret;
-}
-
-
-void browser_form_get_append(char **s, int *length, char sep, char *name, char *value)
-{
- unsigned int length1;
-
- name = curl_escape(name, 0);
- value = curl_escape(value, 0);
- length1 = 2 + strlen(name) + strlen(value);
-
- LOG(("append %c%s=%s, length1 %i, *s %p", sep, name, value, length1, *s));
- *s = xrealloc(*s, *length + length1 + 1);
-
- sprintf(*s + *length, "%c%s=%s", sep, name, value);
- *length += length1;
-
- curl_free(name);
- curl_free(value);
+ form_free_successful(success);
}
diff --git a/desktop/browser.h b/desktop/browser.h
index 8bd4f437b..38dc3628b 100644
--- a/desktop/browser.h
+++ b/desktop/browser.h
@@ -80,7 +80,7 @@ struct browser_action
action_buttons buttons;
} mouse;
struct {
- struct gui_gadget* g;
+ struct form_control* g;
int item;
} gadget_select;
} data;
@@ -114,7 +114,7 @@ int box_position_gt(struct box_position* x, struct box_position* y);
int box_position_eq(struct box_position* x, struct box_position* y);
int box_position_distance(struct box_position* x, struct box_position* y);
-void gui_redraw_gadget(struct browser_window* bw, struct gui_gadget* g);
+void gui_redraw_gadget(struct browser_window* bw, struct form_control* g);
void browser_window_stop_throbber(struct browser_window* bw);
void browser_window_reformat(struct browser_window* bw, int scroll_to_top);
diff --git a/desktop/gui.h b/desktop/gui.h
index 619ded567..bb52979c2 100644
--- a/desktop/gui.h
+++ b/desktop/gui.h
@@ -58,7 +58,7 @@ gui_safety gui_window_set_redraw_safety(gui_window* g, gui_safety s);
void gui_window_start_throbber(gui_window* g);
void gui_window_stop_throbber(gui_window* g);
-void gui_gadget_combo(struct browser_window* bw, struct gui_gadget* g, unsigned long mx, unsigned long my);
+void gui_gadget_combo(struct browser_window* bw, struct form_control* g, unsigned long mx, unsigned long my);
void gui_window_place_caret(gui_window *g, int x, int y, int height);
diff --git a/makefile b/makefile
index 269f2a728..1efd0c5ae 100644
--- a/makefile
+++ b/makefile
@@ -8,7 +8,7 @@ CC = riscos-gcc
CC_DEBUG = gcc
OBJECTS_COMMON = cache.o content.o fetch.o fetchcache.o other.o \
css.o css_enum.o parser.o ruleset.o scanner.o \
- box.o html.o layout.o textplain.o \
+ box.o form.o html.o layout.o textplain.o \
messages.o utils.o
OBJECTS = $(OBJECTS_COMMON) \
browser.o netsurf.o \
diff --git a/render/box.c b/render/box.c
index 77fc99f00..3ad80ffad 100644
--- a/render/box.c
+++ b/render/box.c
@@ -18,6 +18,7 @@
#include "netsurf/css/css.h"
#include "netsurf/render/box.h"
#include "netsurf/render/font.h"
+#include "netsurf/render/form.h"
#include "netsurf/render/html.h"
#ifdef riscos
#include "netsurf/desktop/gui.h"
@@ -70,7 +71,7 @@ static struct box *box_input_text(xmlNode *n, struct status *status,
struct css_style *style, bool password);
static struct result box_button(xmlNode *n, struct status *status,
struct css_style *style);
-static void add_option(xmlNode* n, struct gui_gadget* current_select, char *text);
+static void add_option(xmlNode* n, struct form_control* current_select, char *text);
static void box_normalise_block(struct box *block);
static void box_normalise_table(struct box *table);
void box_normalise_table_row_group(struct box *row_group,
@@ -78,7 +79,7 @@ void box_normalise_table_row_group(struct box *row_group,
void box_normalise_table_row(struct box *row,
unsigned int **row_span, unsigned int *table_columns);
static void box_normalise_inline_container(struct box *cont);
-static void gadget_free(struct gui_gadget* g);
+static void gadget_free(struct form_control* g);
static void box_free_box(struct box *box);
static struct result box_object(xmlNode *n, struct status *status,
struct css_style *style);
@@ -88,9 +89,8 @@ static struct result box_applet(xmlNode *n, struct status *status,
struct css_style *style);
static struct result box_iframe(xmlNode *n, struct status *status,
struct css_style *style);
-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_gadget_element(struct page_elements* pe, struct form_control* g);
static bool plugin_decode(struct content* content, char* url, struct box* box,
struct object_params* po);
@@ -370,7 +370,7 @@ struct box * convert_xml_to_box(xmlNode * n, struct content *content,
}
box = box_create(parent_style, status.href, title);
- box->text = text;
+ box->text = text;
box->style_clone = 1;
box->length = strlen(text);
if (text[box->length - 1] == ' ') {
@@ -653,7 +653,7 @@ struct css_style * box_get_style(struct content ** stylesheet,
xmlFree(s);
}
}
-
+
if ((s = (char *) xmlGetProp(n, (const xmlChar *) "style"))) {
struct css_style * astyle = xcalloc(1, sizeof(struct css_style));
memcpy(astyle, &css_empty_style, sizeof(struct css_style));
@@ -737,9 +737,27 @@ struct result box_image(xmlNode *n, struct status *status,
struct result box_form(xmlNode *n, struct status *status,
struct css_style *style)
{
+ char* s;
struct box *box;
+ struct form *form;
+
box = box_create(style, status->href, status->title);
- status->current_form = create_form(n);
+
+ status->current_form = form = xcalloc(1, sizeof(*form));
+
+ if ((s = (char *) xmlGetProp(n, (const xmlChar *) "action"))) {
+ form->action = s;
+ }
+
+ form->method = method_GET;
+ if ((s = (char *) xmlGetProp(n, (const xmlChar *) "method"))) {
+ if (stricmp(s, "post") == 0)
+ form->method = method_POST;
+ xmlFree(s);
+ }
+
+ form->controls = form->last_control = 0;
+
add_form_element(status->elements, status->current_form);
return (struct result) {box, 1};
}
@@ -752,10 +770,10 @@ struct result box_textarea(xmlNode *n, struct status *status,
char* s;
box = box_create(style, NULL, 0);
- box->gadget = xcalloc(1, sizeof(struct gui_gadget));
+ box->gadget = xcalloc(1, sizeof(struct form_control));
box->gadget->box = box;
box->gadget->type = GADGET_TEXTAREA;
- box->gadget->form = status->current_form;
+ form_add_control(status->current_form, box->gadget);
style->display = CSS_DISPLAY_INLINE_BLOCK;
/* split the content at newlines and make an inline container with an
@@ -800,12 +818,12 @@ struct result box_select(xmlNode *n, struct status *status,
struct box *box;
struct box *inline_container;
struct box *inline_box;
- struct gui_gadget *gadget = xcalloc(1, sizeof(struct gui_gadget));
+ struct form_control *gadget = xcalloc(1, sizeof(struct form_control));
char* s;
xmlNode *c, *c2;
gadget->type = GADGET_SELECT;
- gadget->form = status->current_form;
+ form_add_control(status->current_form, gadget);
gadget->data.select.multiple = false;
if ((s = (char *) xmlGetProp(n, (const xmlChar *) "multiple"))) {
@@ -882,9 +900,9 @@ struct result box_select(xmlNode *n, struct status *status,
return (struct result) {box, 0};
}
-void add_option(xmlNode* n, struct gui_gadget* current_select, char *text)
+void add_option(xmlNode* n, struct form_control* current_select, char *text)
{
- struct formoption *option = xcalloc(1, sizeof(struct formoption));
+ struct form_option *option = xcalloc(1, sizeof(struct form_option));
char *s, *c;
assert(current_select != 0);
@@ -922,7 +940,7 @@ struct result box_input(xmlNode *n, struct status *status,
struct css_style *style)
{
struct box* box = 0;
- struct gui_gadget *gadget = 0;
+ struct form_control *gadget = 0;
char *s, *type, *url;
type = (char *) xmlGetProp(n, (const xmlChar *) "type");
@@ -943,16 +961,16 @@ struct result box_input(xmlNode *n, struct status *status,
else if (stricmp(type, "hidden") == 0)
{
/* no box for hidden inputs */
- gadget = xcalloc(1, sizeof(struct gui_gadget));
+ gadget = xcalloc(1, sizeof(struct form_control));
gadget->type = GADGET_HIDDEN;
if ((s = (char *) xmlGetProp(n, (const xmlChar *) "value")))
- gadget->data.hidden.value = s;
+ gadget->value = s;
}
else if (stricmp(type, "checkbox") == 0 || stricmp(type, "radio") == 0)
{
box = box_create(style, NULL, 0);
- box->gadget = gadget = xcalloc(1, sizeof(struct gui_gadget));
+ box->gadget = gadget = xcalloc(1, sizeof(struct form_control));
gadget->box = box;
if (type[0] == 'c' || type[0] == 'C')
gadget->type = GADGET_CHECKBOX;
@@ -967,12 +985,8 @@ struct result box_input(xmlNode *n, struct status *status,
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;
- }
+ if ((s = (char *) xmlGetProp(n, (const xmlChar *) "value")))
+ gadget->value = s;
}
else if (stricmp(type, "submit") == 0 || stricmp(type, "reset") == 0)
{
@@ -998,33 +1012,21 @@ struct result box_input(xmlNode *n, struct status *status,
else if (stricmp(type, "image") == 0)
{
box = box_create(style, NULL, 0);
- box->gadget = gadget = xcalloc(1, sizeof(struct gui_gadget));
+ box->gadget = gadget = xcalloc(1, sizeof(struct form_control));
gadget->box = box;
gadget->type = GADGET_IMAGE;
- if ((s = (char *) xmlGetProp(n, (const xmlChar*) "name"))) {
- gadget->data.image.n = s;
- }
- if ((s = (char *) xmlGetProp(n, (const xmlChar*) "width"))) {
- gadget->data.image.width = (atoi(s));
- }
- if ((s = (char *) xmlGetProp(n, (const xmlChar*) "height"))) {
- gadget->data.image.height = (atoi(s));
- }
if ((s = (char *) xmlGetProp(n, (const xmlChar*) "src"))) {
- url = url_join(strdup(s), status->content->url);
+ url = url_join(s, status->content->url);
html_fetch_object(status->content, url, box);
+ xmlFree(s);
}
- gadget->data.image.name =
- xcalloc(strlen(gadget->data.image.n) + 5, sizeof(char));
- gadget->data.image.value =
- xcalloc(strlen(gadget->data.image.n) + 20, sizeof(char));
}
if (type != 0)
xmlFree(type);
if (gadget != 0) {
- gadget->form = status->current_form;
+ form_add_control(status->current_form, gadget);
gadget->name = (char *) xmlGetProp(n, (const xmlChar *) "name");
add_gadget_element(status->elements, gadget);
}
@@ -1041,7 +1043,7 @@ struct box *box_input_text(xmlNode *n, struct status *status,
struct box *inline_container, *inline_box;
style->display = CSS_DISPLAY_INLINE_BLOCK;
- box->gadget = xcalloc(1, sizeof(struct gui_gadget));
+ box->gadget = xcalloc(1, sizeof(struct form_control));
box->gadget->box = box;
box->gadget->maxlength = 100;
@@ -1090,10 +1092,10 @@ struct result box_button(xmlNode *n, struct status *status,
style->display = CSS_DISPLAY_INLINE_BLOCK;
if (!type || strcasecmp(type, "submit") == 0) {
- box->gadget = xcalloc(1, sizeof(struct gui_gadget));
+ box->gadget = xcalloc(1, sizeof(struct form_control));
box->gadget->type = GADGET_SUBMIT;
} else if (strcasecmp(type, "reset") == 0) {
- box->gadget = xcalloc(1, sizeof(struct gui_gadget));
+ box->gadget = xcalloc(1, sizeof(struct form_control));
box->gadget->type = GADGET_RESET;
} else {
/* type="button" or unknown: just render the contents */
@@ -1104,7 +1106,7 @@ struct result box_button(xmlNode *n, struct status *status,
if (type)
xmlFree(type);
- box->gadget->form = status->current_form;
+ form_add_control(status->current_form, box->gadget);
box->gadget->box = box;
box->gadget->name = (char *) xmlGetProp(n, (const xmlChar *) "name");
box->gadget->value = (char *) xmlGetProp(n, (const xmlChar *) "value");
@@ -1561,50 +1563,27 @@ void box_normalise_inline_container(struct box *cont)
}
-void gadget_free(struct gui_gadget* g)
+void gadget_free(struct form_control* g)
{
- struct formoption *o, *o1;
+ struct form_option *o, *o1;
if (g->name != 0)
xmlFree(g->name);
free(g->value);
free(g->initial_value);
- switch (g->type)
- {
- case GADGET_HIDDEN:
- if (g->data.hidden.value != 0)
- xmlFree(g->data.hidden.value);
- break;
- case GADGET_RADIO:
- if (g->data.checkbox.value != 0)
- xmlFree(g->data.radio.value);
- break;
- case GADGET_CHECKBOX:
- if (g->data.checkbox.value != 0)
- xmlFree(g->data.checkbox.value);
- break;
- case GADGET_IMAGE:
- if (g->data.image.n != 0)
- xmlFree(g->data.image.n);
- if (g->data.image.name != 0)
- xfree(g->data.image.name);
- if (g->data.image.value != 0)
- xfree(g->data.image.value);
- break;
- case GADGET_SELECT:
- o = g->data.select.items;
- while (o != NULL)
- {
- if (o->text != 0)
- xmlFree(o->text);
- if (o->value != 0)
- xmlFree(o->value);
- o1 = o->next;
- xfree(o);
- o = o1;
- }
- break;
+ if (g->type == GADGET_SELECT) {
+ o = g->data.select.items;
+ while (o != NULL)
+ {
+ if (o->text != 0)
+ xmlFree(o->text);
+ if (o->value != 0)
+ xmlFree(o->value);
+ o1 = o->next;
+ xfree(o);
+ o = o1;
+ }
}
}
@@ -1649,27 +1628,6 @@ void box_free_box(struct box *box)
* form helper functions
*/
-struct form* create_form(xmlNode* n)
-{
- struct form* form;
- char* s;
-
- form = xcalloc(1, sizeof(*form));
-
- if ((s = (char *) xmlGetProp(n, (const xmlChar *) "action"))) {
- form->action = s;
- }
-
- form->method = method_GET;
- if ((s = (char *) xmlGetProp(n, (const xmlChar *) "method"))) {
- if (stricmp(s, "post") == 0)
- form->method = method_POST;
- xmlFree(s);
- }
-
- return form;
-}
-
void add_form_element(struct page_elements* pe, struct form* f)
{
pe->forms = xrealloc(pe->forms, (pe->numForms + 1) * sizeof(struct form*));
@@ -1677,9 +1635,9 @@ void add_form_element(struct page_elements* pe, struct form* f)
pe->numForms++;
}
-void add_gadget_element(struct page_elements* pe, struct gui_gadget* g)
+void add_gadget_element(struct page_elements* pe, struct form_control* g)
{
- pe->gadgets = xrealloc(pe->gadgets, (pe->numGadgets + 1) * sizeof(struct gui_gadget*));
+ pe->gadgets = xrealloc(pe->gadgets, (pe->numGadgets + 1) * sizeof(struct form_control*));
pe->gadgets[pe->numGadgets] = g;
pe->numGadgets++;
}
diff --git a/render/box.h b/render/box.h
index 76c9500c9..2c76f3ffd 100644
--- a/render/box.h
+++ b/render/box.h
@@ -33,59 +33,8 @@ struct column {
unsigned long min, max, width;
};
-struct formoption {
- bool selected;
- bool initial_selected;
- char* value;
- char* text;
- struct formoption* next;
-};
-
struct box;
-struct gui_gadget {
- enum { GADGET_HIDDEN = 0, GADGET_TEXTBOX, GADGET_RADIO, GADGET_CHECKBOX,
- GADGET_SELECT, GADGET_TEXTAREA,
- GADGET_IMAGE, GADGET_PASSWORD, GADGET_SUBMIT, GADGET_RESET } type;
- char *name;
- char *value;
- char *initial_value;
- struct form *form;
- struct box *box;
- struct box *caret_inline_container;
- struct box *caret_text_box;
- int caret_char_offset;
- unsigned int maxlength;
- union {
- struct {
- char* value;
- } hidden;
- struct {
- char* name;
- char* value;
- char* n;
- int width, height;
- int mx, my;
- } image;
- struct {
- 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;
- char* value;
- } checkbox;
- struct {
- int selected;
- char* value;
- } radio;
- } data;
-};
-
/* parameters for <object> and related elements */
struct object_params {
char* data;
@@ -137,28 +86,22 @@ struct box {
struct box * next_float;
struct column *col;
struct font_data *font;
- struct gui_gadget* gadget;
+ struct form_control* gadget;
struct content* object; /* usually an image */
struct object_params *object_params;
void* object_state; /* state of any object */
};
-struct form
-{
- char* action; /* url */
- enum {method_GET, method_POST} method;
-};
-
struct formsubmit
{
struct form* form;
- struct gui_gadget* items;
+ struct form_control* items;
};
struct page_elements
{
struct form** forms;
- struct gui_gadget** gadgets;
+ struct form_control** gadgets;
struct img** images;
int numForms;
int numGadgets;
diff --git a/render/form.c b/render/form.c
new file mode 100644
index 000000000..f4ed0a9f8
--- /dev/null
+++ b/render/form.c
@@ -0,0 +1,175 @@
+/*
+ * This file is part of NetSurf, http://netsurf.sourceforge.net/
+ * Licensed under the GNU General Public License,
+ * http://www.opensource.org/licenses/gpl-license
+ * Copyright 2003 James Bursa <bursa@users.sourceforge.net>
+ * Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
+ */
+
+/** \file
+ * Form handling functions (implementation).
+ */
+
+#include <assert.h>
+#include <string.h>
+#include "curl/curl.h"
+#include "netsurf/render/form.h"
+#include "netsurf/utils/utils.h"
+
+
+/**
+ * Add a control to the list of controls in a form.
+ */
+
+void form_add_control(struct form *form, struct form_control *control)
+{
+ control->form = form;
+ if (form->controls) {
+ assert(form->last_control);
+ form->last_control->next = control;
+ control->next = 0;
+ form->last_control = control;
+ } else {
+ form->controls = form->last_control = control;
+ }
+}
+
+
+/**
+ * Identify 'successful' controls.
+ *
+ * See HTML 4.01 section 17.13.2.
+ */
+
+struct form_successful_control *form_successful_controls(struct form *form,
+ struct form_control *submit_button)
+{
+ struct form_control *control;
+ struct form_option *option;
+ struct form_successful_control sentinel, *last_success;
+ last_success = &sentinel;
+
+ for (control = form->controls; control; control = control->next) {
+ struct form_successful_control *success_new;
+
+ /* ignore disabled controls */
+ if (control->disabled)
+ continue;
+
+ /* ignore controls with no name */
+ if (!control->name)
+ continue;
+
+ /* only the activated submit button is successful */
+ if (control->type == GADGET_SUBMIT && control != submit_button)
+ continue;
+
+ /* ignore checkboxes and radio buttons which aren't selected */
+ if (control->type == GADGET_CHECKBOX && !control->data.checkbox.selected)
+ continue;
+ if (control->type == GADGET_RADIO && !control->data.radio.selected)
+ continue;
+
+ /* select */
+ if (control->type == GADGET_SELECT) {
+ for (option = control->data.select.items; option;
+ option = option->next) {
+ if (option->selected && option->value) {
+ success_new = xcalloc(1, sizeof(*success_new));
+ success_new->name = xstrdup(control->name);
+ success_new->value = xstrdup(option->value);
+ success_new->next = 0;
+ last_success->next = success_new;
+ last_success = success_new;
+ }
+ }
+ continue;
+ }
+
+ /* textarea */
+ if (control->type == GADGET_TEXTAREA) {
+ /* TODO */
+ continue;
+ }
+
+ /* image */
+ if (control->type == GADGET_IMAGE) {
+ int len = strlen(control->name) + 3;
+ /* x */
+ success_new = xcalloc(1, sizeof(*success_new));
+ success_new->name = xcalloc(1, len);
+ sprintf(success_new->name, "%s.x", control->name);
+ success_new->value = xcalloc(1, 20);
+ sprintf(success_new->value, "%i", control->data.image.mx);
+ success_new->next = 0;
+ last_success->next = success_new;
+ last_success = success_new;
+ /* y */
+ success_new = xcalloc(1, sizeof(*success_new));
+ success_new->name = xcalloc(1, len);
+ sprintf(success_new->name, "%s.y", control->name);
+ success_new->value = xcalloc(1, 20);
+ sprintf(success_new->value, "%i", control->data.image.my);
+ success_new->next = 0;
+ last_success->next = success_new;
+ last_success = success_new;
+ }
+
+ /* ignore reset */
+ if (control->type == GADGET_RESET)
+ continue;
+
+ /* all others added if they have a value */
+ if (control->value) {
+ success_new = xcalloc(1, sizeof(*success_new));
+ success_new->name = xstrdup(control->name);
+ success_new->value = xstrdup(control->value);
+ success_new->next = 0;
+ last_success->next = success_new;
+ last_success = success_new;
+ }
+ }
+
+ return sentinel.next;
+}
+
+
+/**
+ * Encode controls using application/x-www-form-urlencoded.
+ */
+
+char *form_url_encode(struct form_successful_control *control)
+{
+ char *s = xcalloc(1, 0);
+ int len = 0, len1;
+
+ for (; control; control = control->next) {
+ char *name = curl_escape(control->name, 0);
+ char *value = curl_escape(control->value, 0);
+ len1 = len + strlen(name) + strlen(value) + 2;
+ s = xrealloc(s, len1 + 1);
+ sprintf(s + len, "%s=%s&", name, value);
+ len = len1;
+ curl_free(name);
+ curl_free(value);
+ }
+ if (len)
+ s[len - 1] = 0;
+ return s;
+}
+
+
+/**
+ * Free a linked list of form_successful_control.
+ */
+
+void form_free_successful(struct form_successful_control *control)
+{
+ struct form_successful_control *next;
+ for (; control; control = next) {
+ next = control->next;
+ free(control->name);
+ free(control->value);
+ free(control);
+ }
+}
diff --git a/render/form.h b/render/form.h
new file mode 100644
index 000000000..b81abf01a
--- /dev/null
+++ b/render/form.h
@@ -0,0 +1,89 @@
+/*
+ * This file is part of NetSurf, http://netsurf.sourceforge.net/
+ * Licensed under the GNU General Public License,
+ * http://www.opensource.org/licenses/gpl-license
+ * Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
+ * Copyright 2003 James Bursa <bursa@users.sourceforge.net>
+ */
+
+/** \file
+ * Form handling functions (interface).
+ */
+
+#ifndef _NETSURF_RENDER_FORM_H_
+#define _NETSURF_RENDER_FORM_H_
+
+#include <stdbool.h>
+#include "netsurf/render/box.h"
+
+struct form_control;
+struct form_option;
+
+/** HTML form. */
+struct form {
+ char *action; /* url */
+ enum {method_GET, method_POST} method;
+ struct form_control *controls; /**< Linked list of controls. */
+ struct form_control *last_control; /**< Last control in list. */
+};
+
+/** Form control. */
+struct form_control {
+ enum { GADGET_HIDDEN, GADGET_TEXTBOX, GADGET_RADIO, GADGET_CHECKBOX,
+ GADGET_SELECT, GADGET_TEXTAREA, GADGET_IMAGE,
+ GADGET_PASSWORD, GADGET_SUBMIT, GADGET_RESET } type;
+ char *name;
+ char *value;
+ char *initial_value;
+ bool disabled;
+ struct form *form;
+ struct box *box;
+ struct box *caret_inline_container;
+ struct box *caret_text_box;
+ int caret_char_offset;
+ unsigned int maxlength;
+ union {
+ struct {
+ int mx, my;
+ } image;
+ struct {
+ int num_items;
+ struct form_option *items, *last_item;
+ bool multiple;
+ int num_selected;
+ /** Currently selected item, if num_selected == 1. */
+ struct form_option *current;
+ } select;
+ struct {
+ int selected;
+ } checkbox;
+ struct {
+ int selected;
+ } radio;
+ } data;
+ struct form_control *next; /**< Next control in this form. */
+};
+
+/** Option in a select. */
+struct form_option {
+ bool selected;
+ bool initial_selected;
+ char* value;
+ char* text;
+ struct form_option* next;
+};
+
+/** Successful control, as defined by HTML 4.01 17.13. */
+struct form_successful_control {
+ char *name; /**< Control name. */
+ char *value; /**< Current value. */
+ struct form_successful_control *next; /**< Next in linked list. */
+};
+
+void form_add_control(struct form *form, struct form_control *control);
+struct form_successful_control *form_successful_controls(struct form *form,
+ struct form_control *submit_button);
+char *form_url_encode(struct form_successful_control *control);
+void form_free_successful(struct form_successful_control *control);
+
+#endif
diff --git a/riscos/gui.c b/riscos/gui.c
index ca21c4e83..328d40691 100644
--- a/riscos/gui.c
+++ b/riscos/gui.c
@@ -25,6 +25,7 @@
#include "netsurf/desktop/netsurf.h"
#include "netsurf/desktop/options.h"
#include "netsurf/render/font.h"
+#include "netsurf/render/form.h"
#include "netsurf/render/html.h"
#include "netsurf/riscos/about.h"
#include "netsurf/riscos/gui.h"
@@ -71,7 +72,7 @@ int ro_save_data(void *data, unsigned long length, char *file_name, bits file_ty
wimp_menu* combo_menu;
-struct gui_gadget* current_gadget;
+struct form_control* current_gadget;
int TOOLBAR_HEIGHT = 128;
@@ -1282,10 +1283,10 @@ void gui_window_stop_throbber(gui_window* g)
wimp_set_icon_state(g->data.browser.toolbar, ro_theme_icon(current_theme, THEME_TOOLBAR, "TOOLBAR_THROBBER"), 0, 0);
}
-void gui_gadget_combo(struct browser_window* bw, struct gui_gadget* g, unsigned long mx, unsigned long my)
+void gui_gadget_combo(struct browser_window* bw, struct form_control* g, unsigned long mx, unsigned long my)
{
int count = 0;
- struct formoption* o;
+ struct form_option* o;
wimp_pointer pointer;
if (combo_menu != NULL)
diff --git a/riscos/gui.h b/riscos/gui.h
index 3ad54ed0a..a88ff0476 100644
--- a/riscos/gui.h
+++ b/riscos/gui.h
@@ -22,7 +22,7 @@ extern wimp_w dialog_info, dialog_saveas, dialog_config, dialog_config_br,
extern wimp_menu *current_menu, *iconbar_menu, *browser_menu,
*combo_menu, *theme_menu;
extern int current_menu_x, current_menu_y, iconbar_menu_height;
-extern struct gui_gadget *current_gadget;
+extern struct form_control *current_gadget;
extern const char *HOME_URL;
extern gui_window *window_list;
diff --git a/riscos/htmlredraw.c b/riscos/htmlredraw.c
index 83e7b4009..d60d97a31 100644
--- a/riscos/htmlredraw.c
+++ b/riscos/htmlredraw.c
@@ -13,6 +13,7 @@
#include "oslib/font.h"
#include "netsurf/css/css.h"
#include "netsurf/content/content.h"
+#include "netsurf/render/form.h"
#include "netsurf/render/html.h"
#include "netsurf/riscos/gui.h"
#include "netsurf/utils/log.h"
@@ -56,14 +57,9 @@ void html_redraw(struct content *c, long x, long y,
/* validation strings can't be const */
-static char validation_textarea[] = "R7;L";
-static char validation_textbox[] = "";
-static char validation_password[] = "D*";
static char validation_select[] = "R2";
static char validation_checkbox_selected[] = "Sopton";
static char validation_checkbox_unselected[] = "Soptoff";
-static char validation_radio_selected[] = "Sradioon";
-static char validation_radio_unselected[] = "Sradiooff";
static char select_text_multiple[] = "<Multiple>"; /* TODO: read from messages */
static char select_text_none[] = "<None>";
@@ -79,7 +75,7 @@ void html_redraw_box(struct content *content, struct box * box,
{
struct box *c;
char *select_text;
- struct formoption *opt;
+ struct form_option *opt;
int width, height, x0, y0, x1, y1;
x += box->x * 2;