[project @ 2003-10-25 00:35:49 by bursa]

Split out and clean up form submit code.

svn path=/import/netsurf/; revision=374
This commit is contained in:
James Bursa 2003-10-25 00:35:49 +00:00
parent 099d537267
commit f1375fe19d
11 changed files with 367 additions and 308 deletions

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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 \

View File

@ -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++;
}

View File

@ -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;

175
render/form.c Normal file
View File

@ -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);
}
}

89
render/form.h Normal file
View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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;