[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:
parent
099d537267
commit
f1375fe19d
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
2
makefile
2
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 \
|
||||
|
|
164
render/box.c
164
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++;
|
||||
}
|
||||
|
|
63
render/box.h
63
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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue