summaryrefslogtreecommitdiff
path: root/render/box_construct.c
diff options
context:
space:
mode:
authorJohn Mark Bell <jmb@netsurf-browser.org>2009-02-20 11:39:25 +0000
committerJohn Mark Bell <jmb@netsurf-browser.org>2009-02-20 11:39:25 +0000
commitcc1094f0ac62db0d736b6e41e219fe628d22a69e (patch)
treeaaa69ff9929767133acc02c299c1a25c9540cddb /render/box_construct.c
parent0619131f20ad86fe640ea9a1a45d3ae7bf73c1d8 (diff)
downloadnetsurf-cc1094f0ac62db0d736b6e41e219fe628d22a69e.tar.gz
netsurf-cc1094f0ac62db0d736b6e41e219fe628d22a69e.tar.bz2
Utilise hubbub's form association callback.
Please can we dispense with the libxml binding? It's causing much #ifdef mess. Fix encoding of <input type=image> names -- previously were output as raw utf-8, rather than in the submission charset. Actually bother to destroy forms in a document, and the controls associated with them. We still leak non form-associated controls, but that's too much effort to fix right now. svn path=/trunk/netsurf/; revision=6573
Diffstat (limited to 'render/box_construct.c')
-rw-r--r--render/box_construct.c197
1 files changed, 118 insertions, 79 deletions
diff --git a/render/box_construct.c b/render/box_construct.c
index 94ca2ef57..4f9bdfd32 100644
--- a/render/box_construct.c
+++ b/render/box_construct.c
@@ -140,7 +140,9 @@ static bool box_a(BOX_SPECIAL_PARAMS);
static bool box_body(BOX_SPECIAL_PARAMS);
static bool box_br(BOX_SPECIAL_PARAMS);
static bool box_image(BOX_SPECIAL_PARAMS);
+#ifndef WITH_HUBBUB
static bool box_form(BOX_SPECIAL_PARAMS);
+#endif
static bool box_textarea(BOX_SPECIAL_PARAMS);
static bool box_select(BOX_SPECIAL_PARAMS);
static bool box_input(BOX_SPECIAL_PARAMS);
@@ -174,7 +176,9 @@ static const struct element_entry element_table[] = {
{"br", box_br},
{"button", box_button},
{"embed", box_embed},
+#ifndef WITH_HUBBUB
{"form", box_form},
+#endif
{"frameset", box_frameset},
{"iframe", box_iframe},
{"image", box_image},
@@ -2158,13 +2162,14 @@ bool box_iframe(BOX_SPECIAL_PARAMS)
}
+#ifndef WITH_HUBBUB
/**
* Interactive form [17.3].
*/
bool box_form(BOX_SPECIAL_PARAMS)
{
- char *xmlaction, *action, *faction, *method, *enctype, *charset, *target;
+ char *xmlaction, *action, *method, *enctype, *charset, *target;
form_method fmethod;
struct form *form;
url_func_result result;
@@ -2173,26 +2178,22 @@ bool box_form(BOX_SPECIAL_PARAMS)
xmlGetProp(n, (const xmlChar *) "action"))) {
/* the action attribute is required, but many forms fail to
* specify it. In the case where it is _not_ specified,
- * follow other browsers and make the form action the
- * URI of the page the form is contained in. */
- action = strdup("");
+ * follow other browsers and make the form action the URI of
+ * the page the form is contained in. */
+ action = strdup(content->data.html.base_url);
} else {
- action = strdup(xmlaction);
+ result = url_join(xmlaction, content->data.html.base_url,
+ &action);
+
xmlFree(xmlaction);
+
+ if (result != URL_FUNC_OK)
+ return false;
}
if (!action)
return false;
- result = url_join(action, content->data.html.base_url, &faction);
- if (result != URL_FUNC_OK) {
- free(action);
- return false;
- }
-
- /* No longer needed */
- free(action);
-
fmethod = method_GET;
if ((method = (char *) xmlGetProp(n, (const xmlChar *) "method"))) {
if (strcasecmp(method, "post") == 0) {
@@ -2214,20 +2215,24 @@ bool box_form(BOX_SPECIAL_PARAMS)
/* target for form data */
target = (char *) xmlGetProp(n, (const xmlChar *) "target");
- form = form_new(faction, target, fmethod, charset,
- content->data.html.encoding);
- if (!form) {
- free(faction);
- xmlFree(target);
+ form = form_new(n, action, target, fmethod, charset,
+ content->data.html.encoding);
+
+ free(action);
+ if (charset)
xmlFree(charset);
+ if (target)
+ xmlFree(target);
+
+ if (!form)
return false;
- }
+
form->prev = content->data.html.forms;
content->data.html.forms = form;
return true;
}
-
+#endif
/**
* Form control [17.4].
@@ -2241,25 +2246,36 @@ bool box_input(BOX_SPECIAL_PARAMS)
type = (char *) xmlGetProp(n, (const xmlChar *) "type");
+#ifdef WITH_HUBBUB
+ gadget = binding_get_control_for_node(content->data.html.parser_binding,
+ n);
+ if (!gadget)
+ goto no_memory;
+ box->gadget = gadget;
+ gadget->box = box;
+#endif
+
if (type && strcasecmp(type, "password") == 0) {
if (!box_input_text(n, content, box, 0, markup_track, author,
true))
goto no_memory;
+#ifndef WITH_HUBBUB
gadget = box->gadget;
gadget->box = box;
-
+#endif
} else if (type && strcasecmp(type, "file") == 0) {
box->type = BOX_INLINE_BLOCK;
- box->gadget = gadget = form_new_control(GADGET_FILE);
+#ifndef WITH_HUBBUB
+ box->gadget = gadget = form_new_control(n, GADGET_FILE);
if (!gadget)
goto no_memory;
gadget->box = box;
-
+#endif
} else if (type && strcasecmp(type, "hidden") == 0) {
/* no box for hidden inputs */
box->style->display = CSS_DISPLAY_NONE;
-
- gadget = form_new_control(GADGET_HIDDEN);
+#ifndef WITH_HUBBUB
+ gadget = form_new_control(n, GADGET_HIDDEN);
if (!gadget)
goto no_memory;
@@ -2270,11 +2286,12 @@ bool box_input(BOX_SPECIAL_PARAMS)
goto no_memory;
gadget->length = strlen(gadget->value);
}
-
+#endif
} else if (type && (strcasecmp(type, "checkbox") == 0 ||
strcasecmp(type, "radio") == 0)) {
- box->gadget = gadget = form_new_control(type[0] == 'c' ||
- type[0] == 'C' ? GADGET_CHECKBOX :
+#ifndef WITH_HUBBUB
+ box->gadget = gadget = form_new_control(n, type[0] == 'c' ||
+ type[0] == 'C' ? GADGET_CHECKBOX :
GADGET_RADIO);
if (!gadget)
goto no_memory;
@@ -2289,9 +2306,10 @@ bool box_input(BOX_SPECIAL_PARAMS)
goto no_memory;
gadget->length = strlen(gadget->value);
}
-
+#endif
} else if (type && (strcasecmp(type, "submit") == 0 ||
- strcasecmp(type, "reset") == 0)) {
+ strcasecmp(type, "reset") == 0 ||
+ strcasecmp(type, "button") == 0)) {
struct box *inline_container, *inline_box;
if (!box_button(n, content, box, 0, markup_track, author))
goto no_memory;
@@ -2310,30 +2328,9 @@ bool box_input(BOX_SPECIAL_PARAMS)
else if (box->gadget->type == GADGET_SUBMIT)
inline_box->text = talloc_strdup(content,
messages_get("Form_Submit"));
- else
+ else if (box->gadget->type == GADGET_RESET)
inline_box->text = talloc_strdup(content,
messages_get("Form_Reset"));
- if (!inline_box->text)
- goto no_memory;
- inline_box->length = strlen(inline_box->text);
- box_add_child(inline_container, inline_box);
- box_add_child(box, inline_container);
-
- } else if (type && strcasecmp(type, "button") == 0) {
- struct box *inline_container, *inline_box;
- if (!box_button(n, content, box, 0, markup_track, author))
- goto no_memory;
- inline_container = box_create(0, 0, 0, 0, 0, content);
- if (!inline_container)
- goto no_memory;
- inline_container->type = BOX_INLINE_CONTAINER;
- inline_box = box_create(box->style, 0, 0, box->title, 0,
- content);
- if (!inline_box)
- goto no_memory;
- inline_box->type = BOX_TEXT;
- if ((s = (char *) xmlGetProp(n, (const xmlChar *) "value")))
- inline_box->text = talloc_strdup(content, s);
else
inline_box->text = talloc_strdup(content, "Button");
if (!inline_box->text)
@@ -2341,12 +2338,13 @@ bool box_input(BOX_SPECIAL_PARAMS)
inline_box->length = strlen(inline_box->text);
box_add_child(inline_container, inline_box);
box_add_child(box, inline_container);
-
} else if (type && strcasecmp(type, "image") == 0) {
- box->gadget = gadget = form_new_control(GADGET_IMAGE);
+#ifndef WITH_HUBBUB
+ box->gadget = gadget = form_new_control(n, GADGET_IMAGE);
if (!gadget)
goto no_memory;
gadget->box = box;
+#endif
gadget->type = GADGET_IMAGE;
if (box->style && box->style->display != CSS_DISPLAY_NONE) {
@@ -2375,19 +2373,21 @@ bool box_input(BOX_SPECIAL_PARAMS)
free(url);
}
}
-
} else {
/* the default type is "text" */
if (!box_input_text(n, content, box, 0, markup_track, author,
false))
goto no_memory;
+#ifndef WITH_HUBBUB
gadget = box->gadget;
gadget->box = box;
+#endif
}
if (type)
xmlFree(type);
+#ifndef WITH_HUBBUB
if (gadget) {
if (content->data.html.forms)
form_add_control(content->data.html.forms, gadget);
@@ -2399,6 +2399,7 @@ bool box_input(BOX_SPECIAL_PARAMS)
goto no_memory;
}
}
+#endif
*convert_children = false;
return true;
@@ -2406,9 +2407,10 @@ bool box_input(BOX_SPECIAL_PARAMS)
no_memory:
if (type)
xmlFree(type);
+#ifndef WITH_HUBBUB
if (gadget)
form_free_control(gadget);
-
+#endif
return false;
}
@@ -2419,14 +2421,17 @@ no_memory:
bool box_input_text(BOX_SPECIAL_PARAMS, bool password)
{
+#ifndef WITH_HUBBUB
char *s;
+#endif
struct box *inline_container, *inline_box;
box->type = BOX_INLINE_BLOCK;
- box->gadget = form_new_control((password) ? GADGET_PASSWORD :
+#ifndef WITH_HUBBUB
+ box->gadget = form_new_control(n, (password) ? GADGET_PASSWORD :
GADGET_TEXTBOX);
if (!box->gadget)
- return 0;
+ return false;
box->gadget->box = box;
if ((s = (char *) xmlGetProp(n, (const xmlChar *) "maxlength"))) {
@@ -2446,6 +2451,7 @@ bool box_input_text(BOX_SPECIAL_PARAMS, bool password)
return NULL;
}
box->gadget->length = strlen(box->gadget->value);
+#endif
inline_container = box_create(0, 0, 0, 0, 0, content);
if (!inline_container)
@@ -2488,19 +2494,16 @@ bool box_input_text(BOX_SPECIAL_PARAMS, bool password)
bool box_button(BOX_SPECIAL_PARAMS)
{
+#ifndef WITH_HUBBUB
xmlChar *s;
char *type = (char *) xmlGetProp(n, (const xmlChar *) "type");
- box->type = BOX_INLINE_BLOCK;
-
if (!type || strcasecmp(type, "submit") == 0) {
- box->gadget = form_new_control(GADGET_SUBMIT);
+ box->gadget = form_new_control(n, GADGET_SUBMIT);
} else if (strcasecmp(type, "reset") == 0) {
- box->gadget = form_new_control(GADGET_RESET);
+ box->gadget = form_new_control(n, GADGET_RESET);
} else {
- /* type="button" or unknown: just render the contents */
- xmlFree(type);
- return true;
+ box->gadget = form_new_control(n, GADGET_BUTTON);
}
if (type)
@@ -2512,6 +2515,7 @@ bool box_button(BOX_SPECIAL_PARAMS)
if (content->data.html.forms)
form_add_control(content->data.html.forms, box->gadget);
box->gadget->box = box;
+
if ((s = xmlGetProp(n, (const xmlChar *) "name")) != NULL) {
box->gadget->name = strdup((char *) s);
xmlFree(s);
@@ -2524,6 +2528,20 @@ bool box_button(BOX_SPECIAL_PARAMS)
if (!box->gadget->value)
return false;
}
+#else
+ struct form_control *gadget;
+
+ gadget = binding_get_control_for_node(content->data.html.parser_binding,
+ n);
+ if (!gadget)
+ return false;
+
+ box->gadget = gadget;
+ gadget->box = box;
+#endif
+ box->type = BOX_INLINE_BLOCK;
+
+ /* Just render the contents */
return true;
}
@@ -2538,23 +2556,24 @@ bool box_select(BOX_SPECIAL_PARAMS)
struct box *inline_container;
struct box *inline_box;
struct form_control *gadget;
- char* s;
+#ifndef WITH_HUBBUB
+ char *s;
+#endif
xmlNode *c, *c2;
- gadget = form_new_control(GADGET_SELECT);
+#ifndef WITH_HUBBUB
+ gadget = form_new_control(n, GADGET_SELECT);
+#else
+ gadget = binding_get_control_for_node(content->data.html.parser_binding,
+ n);
+#endif
if (!gadget)
return false;
- gadget->data.select.multiple = false;
- if ((s = (char *) xmlGetProp(n, (const xmlChar *) "multiple"))) {
- gadget->data.select.multiple = true;
- xmlFree(s);
- }
-
- gadget->data.select.items = NULL;
- gadget->data.select.last_item = NULL;
- gadget->data.select.num_items = 0;
- gadget->data.select.num_selected = 0;
+#ifndef WITH_HUBBUB
+ gadget->data.select.multiple =
+ xmlHasProp(n, (const xmlChar *) "multiple");
+#endif
for (c = n->children; c; c = c->next) {
if (strcmp((const char *) c->name, "option") == 0) {
@@ -2573,16 +2592,20 @@ bool box_select(BOX_SPECIAL_PARAMS)
if (gadget->data.select.num_items == 0) {
/* no options: ignore entire select */
+#ifndef WITH_HUBBUB
form_free_control(gadget);
+#endif
return true;
}
+#ifndef WITH_HUBBUB
if ((s = (char *) xmlGetProp(n, (const xmlChar *) "name"))) {
gadget->name = strdup(s);
xmlFree(s);
if (!gadget->name)
goto no_memory;
}
+#endif
box->type = BOX_INLINE_BLOCK;
box->gadget = gadget;
@@ -2621,14 +2644,18 @@ bool box_select(BOX_SPECIAL_PARAMS)
inline_box->length = strlen(inline_box->text);
+#ifndef WITH_HUBBUB
if (content->data.html.forms)
form_add_control(content->data.html.forms, box->gadget);
+#endif
*convert_children = false;
return true;
no_memory:
+#ifndef WITH_HUBBUB
form_free_control(gadget);
+#endif
return false;
}
@@ -2709,17 +2736,24 @@ bool box_textarea(BOX_SPECIAL_PARAMS)
size_t len;
box->type = BOX_INLINE_BLOCK;
- box->gadget = form_new_control(GADGET_TEXTAREA);
+#ifndef WITH_HUBBUB
+ box->gadget = form_new_control(n, GADGET_TEXTAREA);
+#else
+ box->gadget = binding_get_control_for_node(
+ content->data.html.parser_binding, n);
+#endif
if (!box->gadget)
return false;
box->gadget->box = box;
+#ifndef WITH_HUBBUB
if ((s = (char *) xmlGetProp(n, (const xmlChar *) "name"))) {
box->gadget->name = strdup(s);
xmlFree(s);
if (!box->gadget->name)
return false;
}
+#endif
inline_container = box_create(0, 0, 0, box->title, 0, content);
if (!inline_container)
@@ -2727,6 +2761,9 @@ bool box_textarea(BOX_SPECIAL_PARAMS)
inline_container->type = BOX_INLINE_CONTAINER;
box_add_child(box, inline_container);
+ /** \todo Is it really necessary to reparse the content of a
+ * textarea element to remove entities? Hubbub will do that for us.
+ */
n2 = n->children;
buf = xmlBufferCreate();
while(n2) {
@@ -2806,8 +2843,10 @@ bool box_textarea(BOX_SPECIAL_PARAMS)
xmlFree(string);
xmlBufferFree(buf);
+#ifndef WITH_HUBBUB
if (content->data.html.forms)
form_add_control(content->data.html.forms, box->gadget);
+#endif
*convert_children = false;
return true;