summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjcid <devnull@localhost>2008-06-07 15:29:01 +0200
committerjcid <devnull@localhost>2008-06-07 15:29:01 +0200
commit062c2f0de95a179cd28cfe847be838621f898584 (patch)
tree57b06edae4e731761a31bfdf92179f330f49dd7a
parent17b813d3c5a99f57d6e430261b8f969db21cf1d2 (diff)
- html.cc cleanup (in progress): source split.
-rw-r--r--src/form.cc1795
-rw-r--r--src/form.hh31
-rw-r--r--src/html.cc1949
-rw-r--r--src/html_common.hh32
4 files changed, 1967 insertions, 1840 deletions
diff --git a/src/form.cc b/src/form.cc
index 08062a7a..bf6e4ea8 100644
--- a/src/form.cc
+++ b/src/form.cc
@@ -11,3 +11,1798 @@
#include "form.hh"
#include "html_common.hh"
+
+#include <errno.h>
+#include <iconv.h>
+
+#include "lout/misc.hh"
+#include "dw/core.hh"
+#include "dw/textblock.hh"
+
+#include "misc.h"
+#include "msg.h"
+#include "debug.h"
+#include "prefs.h"
+#include "nav.h"
+#include "uicmd.hh"
+
+using namespace dw;
+using namespace dw::core;
+using namespace dw::core::style;
+
+/*
+ * Forward declarations
+ */
+
+class DilloHtmlReceiver;
+class DilloHtmlInput;
+typedef struct _DilloHtmlSelect DilloHtmlSelect;
+typedef struct _DilloHtmlOption DilloHtmlOption;
+
+static Dstr *Html_encode_text(iconv_t encoder, Dstr **input);
+static void Html_urlencode_append(Dstr *str, const char *val);
+static void Html_append_input_urlencode(Dstr *data, const char *name,
+ const char *value);
+static void Html_append_input_multipart_files(Dstr* data, const char *boundary,
+ const char *name, Dstr *file,
+ const char *filename);
+static void Html_append_input_multipart(Dstr *data, const char *boundary,
+ const char *name, const char *value);
+static void Html_append_clickpos_urlencode(Dstr *data,
+ Dstr *name, int x,int y);
+static void Html_append_clickpos_multipart(Dstr *data, const char *boundary,
+ Dstr *name, int x, int y);
+static void Html_get_input_values(const DilloHtmlInput *input,
+ bool is_active_submit, Dlist *values);
+
+static dw::core::ui::Embed *Html_input_image(DilloHtml *html,
+ const char *tag, int tagsize,
+ DilloHtmlForm *form);
+
+static void Html_option_finish(DilloHtml *html);
+
+/*
+ * Typedefs
+ */
+
+typedef enum {
+ DILLO_HTML_INPUT_UNKNOWN,
+ DILLO_HTML_INPUT_TEXT,
+ DILLO_HTML_INPUT_PASSWORD,
+ DILLO_HTML_INPUT_CHECKBOX,
+ DILLO_HTML_INPUT_RADIO,
+ DILLO_HTML_INPUT_IMAGE,
+ DILLO_HTML_INPUT_FILE,
+ DILLO_HTML_INPUT_BUTTON,
+ DILLO_HTML_INPUT_HIDDEN,
+ DILLO_HTML_INPUT_SUBMIT,
+ DILLO_HTML_INPUT_RESET,
+ DILLO_HTML_INPUT_BUTTON_SUBMIT,
+ DILLO_HTML_INPUT_BUTTON_RESET,
+ DILLO_HTML_INPUT_SELECT,
+ DILLO_HTML_INPUT_SEL_LIST,
+ DILLO_HTML_INPUT_TEXTAREA,
+ DILLO_HTML_INPUT_INDEX
+} DilloHtmlInputType;
+
+/*
+ * Class declarations
+ */
+
+class DilloHtmlForm {
+ friend class DilloHtmlReceiver;
+
+ DilloHtml *html;
+ void eventHandler(dw::core::ui::Resource *resource,
+ int click_x, int click_y);
+
+public: //BUG: for now everything is public
+ DilloHtmlMethod method;
+ DilloUrl *action;
+ DilloHtmlEnc enc;
+ char *submit_charset;
+
+ lout::misc::SimpleVector<DilloHtmlInput*> *inputs;
+
+ int num_entry_fields;
+ int num_submit_buttons;
+
+ DilloHtmlReceiver *form_receiver;
+
+public:
+ DilloHtmlForm (DilloHtml *html,
+ DilloHtmlMethod method, const DilloUrl *action,
+ DilloHtmlEnc enc, const char *charset);
+ ~DilloHtmlForm ();
+ DilloHtmlInput *getCurrentInput ();
+ DilloHtmlInput *getInput (dw::core::ui::Resource *resource);
+ DilloHtmlInput *getRadioInput (const char *name);
+ void reset ();
+ void addInput(DilloHtmlInputType type,
+ dw::core::ui::Embed *embed,
+ const char *name,
+ const char *init_str,
+ DilloHtmlSelect *select,
+ bool_t init_val);
+ DilloUrl *buildQueryUrl(DilloHtmlInput *input, int click_x, int click_y);
+ Dstr *buildQueryData(DilloHtmlInput *active_submit, int x, int y);
+ char *makeMultipartBoundary(iconv_t encoder, DilloHtmlInput *active_submit);
+};
+
+class DilloHtmlReceiver:
+ public dw::core::ui::Resource::ActivateReceiver,
+ public dw::core::ui::ButtonResource::ClickedReceiver
+{
+ friend class DilloHtmlForm;
+ DilloHtmlForm* form;
+ DilloHtmlReceiver (DilloHtmlForm* form2) { form = form2; }
+ ~DilloHtmlReceiver () { }
+ void activate (dw::core::ui::Resource *resource);
+ void clicked (dw::core::ui::ButtonResource *resource,
+ int buttonNo, int x, int y);
+};
+
+struct _DilloHtmlOption {
+ char *value, *content;
+ bool selected, enabled;
+};
+
+struct _DilloHtmlSelect {
+ lout::misc::SimpleVector<DilloHtmlOption *> *options;
+};
+
+class DilloHtmlInput {
+
+ // DilloHtmlForm::addInput() calls connectTo()
+ friend class DilloHtmlForm;
+
+public: //BUG: for now everything is public
+ DilloHtmlInputType type;
+ dw::core::ui::Embed *embed; /* May be NULL (think: hidden input) */
+ char *name;
+ char *init_str; /* note: some overloading - for buttons, init_str
+ is simply the value of the button; for text
+ entries, it is the initial value */
+ DilloHtmlSelect *select;
+ bool_t init_val; /* only meaningful for buttons */
+ Dstr *file_data; /* only meaningful for file inputs.
+ todo: may become a list... */
+
+private:
+ void connectTo(DilloHtmlReceiver *form_receiver);
+
+public:
+ DilloHtmlInput (DilloHtmlInputType type,
+ dw::core::ui::Embed *embed,
+ const char *name,
+ const char *init_str,
+ DilloHtmlSelect *select,
+ bool_t init_val);
+ ~DilloHtmlInput ();
+ void reset();
+};
+
+/*
+ * Form API
+ */
+
+DilloHtmlForm *a_Html_form_new (DilloHtml *html,
+ DilloHtmlMethod method,
+ const DilloUrl *action,
+ DilloHtmlEnc enc,
+ const char *charset)
+{
+ return new DilloHtmlForm (html,method,action,enc,charset);
+}
+
+void a_Html_form_delete (DilloHtmlForm *form)
+{
+ delete form;
+}
+
+/*
+ * Form parsing functions
+ */
+
+/*
+ * Handle <FORM> tag
+ */
+void Html_tag_open_form(DilloHtml *html, const char *tag, int tagsize)
+{
+ DilloUrl *action;
+ DilloHtmlMethod method;
+ DilloHtmlEnc enc;
+ char *charset, *first;
+ const char *attrbuf;
+
+ DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
+
+ if (html->InFlags & IN_FORM) {
+ BUG_MSG("nested forms\n");
+ return;
+ }
+ html->InFlags |= IN_FORM;
+ html->InFlags &= ~IN_SELECT;
+ html->InFlags &= ~IN_OPTION;
+ html->InFlags &= ~IN_TEXTAREA;
+
+ method = DILLO_HTML_METHOD_GET;
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "method"))) {
+ if (!dStrcasecmp(attrbuf, "post"))
+ method = DILLO_HTML_METHOD_POST;
+ /* todo: maybe deal with unknown methods? */
+ }
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "action")))
+ action = a_Html_url_new(html, attrbuf, NULL, 0, 0, 0, 0);
+ else
+ action = a_Url_dup(html->base_url);
+ enc = DILLO_HTML_ENC_URLENCODING;
+ if ((method == DILLO_HTML_METHOD_POST) &&
+ ((attrbuf = a_Html_get_attr(html, tag, tagsize, "enctype")))) {
+ if (!dStrcasecmp(attrbuf, "multipart/form-data"))
+ enc = DILLO_HTML_ENC_MULTIPART;
+ }
+ charset = NULL;
+ first = NULL;
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "accept-charset"))) {
+ /* a list of acceptable charsets, separated by commas or spaces */
+ char *ptr = first = dStrdup(attrbuf);
+ while (ptr && !charset) {
+ char *curr = dStrsep(&ptr, " ,");
+ if (!dStrcasecmp(curr, "utf-8")) {
+ charset = curr;
+ } else if (!dStrcasecmp(curr, "UNKNOWN")) {
+ /* defined to be whatever encoding the document is in */
+ charset = html->charset;
+ }
+ }
+ if (!charset)
+ charset = first;
+ }
+ if (!charset)
+ charset = html->charset;
+ html->formNew(method, action, enc, charset);
+ dFree(first);
+ a_Url_free(action);
+}
+
+void Html_tag_close_form(DilloHtml *html, int TagIdx)
+{
+ static const char *SubmitTag =
+ "<input type='submit' value='?Submit?' alt='dillo-generated-button'>";
+ DilloHtmlForm *form;
+// int i;
+
+ if (html->InFlags & IN_FORM) {
+ form = html->getCurrentForm ();
+ /* If we don't have a submit button and the user desires one,
+ let's add a custom one */
+ if (form->num_submit_buttons == 0) {
+ if (prefs.show_extra_warnings || form->num_entry_fields != 1)
+ BUG_MSG("FORM lacks a Submit button\n");
+ if (prefs.generate_submit) {
+ BUG_MSG(" (added a submit button internally)\n");
+ Html_tag_open_input(html, SubmitTag, strlen(SubmitTag));
+ form->num_submit_buttons = 0;
+ }
+ }
+
+// /* Make buttons sensitive again */
+// for (i = 0; i < form->inputs->size(); i++) {
+// input_i = form->inputs->get(i);
+// /* Check for tricky HTML (e.g. <input type=image>) */
+// if (!input_i->widget)
+// continue;
+// if (input_i->type == DILLO_HTML_INPUT_SUBMIT ||
+// input_i->type == DILLO_HTML_INPUT_RESET) {
+// gtk_widget_set_sensitive(input_i->widget, TRUE);
+// } else if (input_i->type == DILLO_HTML_INPUT_IMAGE ||
+// input_i->type == DILLO_HTML_INPUT_BUTTON_SUBMIT ||
+// input_i->type == DILLO_HTML_INPUT_BUTTON_RESET) {
+// a_Dw_button_set_sensitive(DW_BUTTON(input_i->widget), TRUE);
+// }
+// }
+ }
+
+ html->InFlags &= ~IN_FORM;
+ html->InFlags &= ~IN_SELECT;
+ html->InFlags &= ~IN_OPTION;
+ html->InFlags &= ~IN_TEXTAREA;
+
+ a_Html_pop_tag(html, TagIdx);
+}
+
+/*
+ * Add a new input to current form
+ */
+void Html_tag_open_input(DilloHtml *html, const char *tag, int tagsize)
+{
+ DilloHtmlForm *form;
+ DilloHtmlInputType inp_type;
+ dw::core::ui::Embed *embed = NULL;
+ char *value, *name, *type, *init_str;
+ const char *attrbuf, *label;
+ bool_t init_val = FALSE;
+
+ if (!(html->InFlags & IN_FORM)) {
+ BUG_MSG("<input> element outside <form>\n");
+ return;
+ }
+ if (html->InFlags & IN_SELECT) {
+ BUG_MSG("<input> element inside <select>\n");
+ return;
+ }
+ if (html->InFlags & IN_BUTTON) {
+ BUG_MSG("<input> element inside <button>\n");
+ return;
+ }
+
+ form = html->getCurrentForm ();
+
+ /* Get 'value', 'name' and 'type' */
+ value = a_Html_get_attr_wdef(html, tag, tagsize, "value", NULL);
+ name = a_Html_get_attr_wdef(html, tag, tagsize, "name", NULL);
+ type = a_Html_get_attr_wdef(html, tag, tagsize, "type", "");
+
+ init_str = NULL;
+ inp_type = DILLO_HTML_INPUT_UNKNOWN;
+ if (!dStrcasecmp(type, "password")) {
+ inp_type = DILLO_HTML_INPUT_PASSWORD;
+ dw::core::ui::EntryResource *entryResource =
+ HT2LT(html)->getResourceFactory()->createEntryResource (10, true);
+ embed = new dw::core::ui::Embed (entryResource);
+ init_str = (value) ? value : NULL;
+ } else if (!dStrcasecmp(type, "checkbox")) {
+ inp_type = DILLO_HTML_INPUT_CHECKBOX;
+ dw::core::ui::CheckButtonResource *check_b_r =
+ HT2LT(html)->getResourceFactory()->createCheckButtonResource(false);
+ embed = new dw::core::ui::Embed (check_b_r);
+ init_val = (a_Html_get_attr(html, tag, tagsize, "checked") != NULL);
+ init_str = (value) ? value : dStrdup("on");
+ } else if (!dStrcasecmp(type, "radio")) {
+ inp_type = DILLO_HTML_INPUT_RADIO;
+ dw::core::ui::RadioButtonResource *rb_r = NULL;
+ DilloHtmlInput *input = form->getRadioInput(name);
+ if (input)
+ rb_r =
+ (dw::core::ui::RadioButtonResource*)
+ input->embed->getResource();
+ rb_r = HT2LT(html)->getResourceFactory()
+ ->createRadioButtonResource(rb_r, false);
+ embed = new dw::core::ui::Embed (rb_r);
+ init_val = (a_Html_get_attr(html, tag, tagsize, "checked") != NULL);
+ init_str = (value) ? value : NULL;
+ } else if (!dStrcasecmp(type, "hidden")) {
+ inp_type = DILLO_HTML_INPUT_HIDDEN;
+ if (value)
+ init_str = dStrdup(a_Html_get_attr(html, tag, tagsize, "value"));
+ } else if (!dStrcasecmp(type, "submit")) {
+ inp_type = DILLO_HTML_INPUT_SUBMIT;
+ init_str = (value) ? value : dStrdup("submit");
+ dw::core::ui::LabelButtonResource *label_b_r =
+ HT2LT(html)->getResourceFactory()
+ ->createLabelButtonResource(init_str);
+ embed = new dw::core::ui::Embed (label_b_r);
+// gtk_widget_set_sensitive(widget, FALSE); /* Until end of FORM! */
+ } else if (!dStrcasecmp(type, "reset")) {
+ inp_type = DILLO_HTML_INPUT_RESET;
+ init_str = (value) ? value : dStrdup("Reset");
+ dw::core::ui::LabelButtonResource *label_b_r =
+ HT2LT(html)->getResourceFactory()
+ ->createLabelButtonResource(init_str);
+ embed = new dw::core::ui::Embed (label_b_r);
+// gtk_widget_set_sensitive(widget, FALSE); /* Until end of FORM! */
+ } else if (!dStrcasecmp(type, "image")) {
+ if (URL_FLAGS(html->base_url) & URL_SpamSafe) {
+ /* Don't request the image; make a text submit button instead */
+ inp_type = DILLO_HTML_INPUT_SUBMIT;
+ attrbuf = a_Html_get_attr(html, tag, tagsize, "alt");
+ label = attrbuf ? attrbuf : value ? value : name ? name : "Submit";
+ init_str = dStrdup(label);
+ dw::core::ui::LabelButtonResource *label_b_r =
+ HT2LT(html)->getResourceFactory()
+ ->createLabelButtonResource(init_str);
+ embed = new dw::core::ui::Embed (label_b_r);
+// gtk_widget_set_sensitive(widget, FALSE); /* Until end of FORM! */
+ } else {
+ inp_type = DILLO_HTML_INPUT_IMAGE;
+ /* use a dw_image widget */
+ embed = Html_input_image(html, tag, tagsize, form);
+ init_str = value;
+ }
+ } else if (!dStrcasecmp(type, "file")) {
+ if (form->method != DILLO_HTML_METHOD_POST) {
+ BUG_MSG("Forms with file input MUST use HTTP POST method\n");
+ MSG("File input ignored in form not using HTTP POST method\n");
+ } else if (form->enc != DILLO_HTML_ENC_MULTIPART) {
+ BUG_MSG("Forms with file input MUST use multipart/form-data"
+ " encoding\n");
+ MSG("File input ignored in form not using multipart/form-data"
+ " encoding\n");
+ } else {
+ inp_type = DILLO_HTML_INPUT_FILE;
+ init_str = dStrdup("File selector");
+ dw::core::ui::LabelButtonResource *lbr =
+ HT2LT(html)->getResourceFactory()->
+ createLabelButtonResource(init_str);
+ embed = new dw::core::ui::Embed (lbr);
+ }
+ } else if (!dStrcasecmp(type, "button")) {
+ inp_type = DILLO_HTML_INPUT_BUTTON;
+ if (value) {
+ init_str = value;
+ dw::core::ui::LabelButtonResource *label_b_r =
+ HT2LT(html)->getResourceFactory()
+ ->createLabelButtonResource(init_str);
+ embed = new dw::core::ui::Embed (label_b_r);
+ }
+ } else if (!dStrcasecmp(type, "text") || !*type) {
+ /* Text input, which also is the default */
+ inp_type = DILLO_HTML_INPUT_TEXT;
+ dw::core::ui::EntryResource *entryResource =
+ HT2LT(html)->getResourceFactory()->createEntryResource (10, false);
+ embed = new dw::core::ui::Embed (entryResource);
+ init_str = (value) ? value : NULL;
+ } else {
+ /* Unknown input type */
+ BUG_MSG("Unknown input type: \"%s\"\n", type);
+ }
+
+ if (inp_type != DILLO_HTML_INPUT_UNKNOWN) {
+ form->addInput(inp_type, embed, name,
+ (init_str) ? init_str : "", NULL, init_val);
+ }
+
+ if (embed != NULL && inp_type != DILLO_HTML_INPUT_IMAGE &&
+ inp_type != DILLO_HTML_INPUT_UNKNOWN) {
+ if (inp_type == DILLO_HTML_INPUT_TEXT ||
+ inp_type == DILLO_HTML_INPUT_PASSWORD) {
+ dw::core::ui::EntryResource *entryres =
+ (dw::core::ui::EntryResource*)embed->getResource();
+ /* Readonly or not? */
+ if (a_Html_get_attr(html, tag, tagsize, "readonly"))
+ entryres->setEditable(false);
+
+// /* Set width of the entry */
+// if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "size")))
+// gtk_widget_set_usize(widget, (strtol(attrbuf, NULL, 10) + 1) *
+// gdk_char_width(widget->style->font, '0'), 0);
+//
+// /* Maximum length of the text in the entry */
+// if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "maxlength")))
+// gtk_entry_set_max_length(GTK_ENTRY(widget),
+// strtol(attrbuf, NULL, 10));
+ }
+
+ if (prefs.standard_widget_colors) {
+ HTML_SET_TOP_ATTR(html, color, NULL);
+ HTML_SET_TOP_ATTR(html, backgroundColor, NULL);
+ }
+ DW2TB(html->dw)->addWidget (embed, S_TOP(html)->style);
+ }
+
+ dFree(type);
+ dFree(name);
+ if (init_str != value)
+ dFree(init_str);
+ dFree(value);
+}
+
+/*
+ * The ISINDEX tag is just a deprecated form of <INPUT type=text> with
+ * implied FORM, afaics.
+ */
+void Html_tag_open_isindex(DilloHtml *html, const char *tag, int tagsize)
+{
+ DilloHtmlForm *form;
+ DilloUrl *action;
+ dw::core::ui::Embed *embed;
+ const char *attrbuf;
+
+ if (html->InFlags & IN_FORM) {
+ MSG("<isindex> inside <form> not handled.\n");
+ return;
+ }
+
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "action")))
+ action = a_Html_url_new(html, attrbuf, NULL, 0, 0, 0, 0);
+ else
+ action = a_Url_dup(html->base_url);
+
+ html->formNew(DILLO_HTML_METHOD_GET, action, DILLO_HTML_ENC_URLENCODING,
+ html->charset);
+
+ form = html->getCurrentForm ();
+
+ DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
+
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "prompt")))
+ DW2TB(html->dw)->addText(dStrdup(attrbuf), S_TOP(html)->style);
+
+ dw::core::ui::EntryResource *entryResource =
+ HT2LT(html)->getResourceFactory()->createEntryResource (10, false);
+ embed = new dw::core::ui::Embed (entryResource);
+ form->addInput(DILLO_HTML_INPUT_INDEX, embed, NULL, NULL, NULL, FALSE);
+
+ if (prefs.standard_widget_colors) {
+ HTML_SET_TOP_ATTR(html, color, NULL);
+ HTML_SET_TOP_ATTR(html, backgroundColor, NULL);
+ }
+ DW2TB(html->dw)->addWidget (embed, S_TOP(html)->style);
+
+ a_Url_free(action);
+}
+
+/*
+ * The textarea tag
+ * (todo: It doesn't support wrapping).
+ */
+void Html_tag_open_textarea(DilloHtml *html, const char *tag, int tagsize)
+{
+ DilloHtmlForm *form;
+ char *name;
+ const char *attrbuf;
+ int cols, rows;
+
+ /* We can't push a new <FORM> because the 'action' URL is unknown */
+ if (!(html->InFlags & IN_FORM)) {
+ BUG_MSG("<textarea> outside <form>\n");
+ html->ReqTagClose = TRUE;
+ return;
+ }
+ if (html->InFlags & IN_TEXTAREA) {
+ BUG_MSG("nested <textarea>\n");
+ html->ReqTagClose = TRUE;
+ return;
+ }
+
+ html->InFlags |= IN_TEXTAREA;
+ form = html->getCurrentForm ();
+ a_Html_stash_init(html);
+ S_TOP(html)->parse_mode = DILLO_HTML_PARSE_MODE_VERBATIM;
+
+ cols = 20;
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "cols")))
+ cols = strtol(attrbuf, NULL, 10);
+ rows = 10;
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "rows")))
+ rows = strtol(attrbuf, NULL, 10);
+ name = NULL;
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "name")))
+ name = dStrdup(attrbuf);
+
+ dw::core::ui::MultiLineTextResource *textres =
+ HT2LT(html)->getResourceFactory()->createMultiLineTextResource (cols,
+ rows);
+
+ dw::core::ui::Embed *embed = new dw::core::ui::Embed(textres);
+ /* Readonly or not? */
+ if (a_Html_get_attr(html, tag, tagsize, "readonly"))
+ textres->setEditable(false);
+
+ form->addInput(DILLO_HTML_INPUT_TEXTAREA, embed, name, NULL, NULL, false);
+
+ DW2TB(html->dw)->addWidget (embed, S_TOP(html)->style);
+
+// widget = gtk_text_new(NULL, NULL);
+// /* compare <input type=text> */
+// gtk_signal_connect_after(GTK_OBJECT(widget), "button_press_event",
+// GTK_SIGNAL_FUNC(gtk_true),
+// NULL);
+//
+// /* Calculate the width and height based on the cols and rows
+// * todo: Get it right... Get the metrics from the font that will be used.
+// */
+// gtk_widget_set_usize(widget, 6 * cols, 16 * rows);
+//
+// /* If the attribute readonly isn't specified we make the textarea
+// * editable. If readonly is set we don't have to do anything.
+// */
+// if (!a_Html_get_attr(html, tag, tagsize, "readonly"))
+// gtk_text_set_editable(GTK_TEXT(widget), TRUE);
+//
+// scroll = gtk_scrolled_window_new(NULL, NULL);
+// gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),
+// GTK_POLICY_AUTOMATIC,
+// GTK_POLICY_AUTOMATIC);
+// gtk_container_add(GTK_CONTAINER(scroll), widget);
+// gtk_widget_show(widget);
+// gtk_widget_show(scroll);
+//
+// form->addInput(DILLO_HTML_INPUT_TEXTAREA,
+// widget, name, NULL, NULL, FALSE);
+// dFree(name);
+//
+// embed_gtk = a_Dw_embed_gtk_new ();
+// a_Dw_embed_gtk_add_gtk (DW_EMBED_GTK (embed_gtk), scroll);
+// DW2TB(html->dw)->addWidget (embed_gtk,
+// S_TOP(html)->style);
+}
+
+/*
+ * Close textarea
+ * (TEXTAREA is parsed in VERBATIM mode, and entities are handled here)
+ */
+void Html_tag_close_textarea(DilloHtml *html, int TagIdx)
+{
+ char *str;
+ DilloHtmlForm *form;
+ DilloHtmlInput *input;
+ int i;
+
+ if (html->InFlags & IN_FORM &&
+ html->InFlags & IN_TEXTAREA) {
+ /* Remove the line ending that follows the opening tag */
+ if (html->Stash->str[0] == '\r')
+ dStr_erase(html->Stash, 0, 1);
+ if (html->Stash->str[0] == '\n')
+ dStr_erase(html->Stash, 0, 1);
+
+ /* As the spec recommends to canonicalize line endings, it is safe
+ * to replace '\r' with '\n'. It will be canonicalized anyway! */
+ for (i = 0; i < html->Stash->len; ++i) {
+ if (html->Stash->str[i] == '\r') {
+ if (html->Stash->str[i + 1] == '\n')
+ dStr_erase(html->Stash, i, 1);
+ else
+ html->Stash->str[i] = '\n';
+ }
+ }
+
+ /* The HTML3.2 spec says it can have "text and character entities". */
+ str = a_Html_parse_entities(html, html->Stash->str, html->Stash->len);
+ form = html->getCurrentForm ();
+ input = form->getCurrentInput ();
+ input->init_str = str;
+ ((dw::core::ui::MultiLineTextResource *)input->embed->getResource ())
+ ->setText(str);
+
+ html->InFlags &= ~IN_TEXTAREA;
+ }
+ a_Html_pop_tag(html, TagIdx);
+}
+
+/*
+ * <SELECT>
+ */
+/* The select tag is quite tricky, because of gorpy html syntax. */
+void Html_tag_open_select(DilloHtml *html, const char *tag, int tagsize)
+{
+// const char *attrbuf;
+// int size, type, multi;
+
+ if (!(html->InFlags & IN_FORM)) {
+ BUG_MSG("<select> outside <form>\n");
+ return;
+ }
+ if (html->InFlags & IN_SELECT) {
+ BUG_MSG("nested <select>\n");
+ return;
+ }
+ html->InFlags |= IN_SELECT;
+ html->InFlags &= ~IN_OPTION;
+
+ DilloHtmlForm *form = html->getCurrentForm ();
+ char *name = a_Html_get_attr_wdef(html, tag, tagsize, "name", NULL);
+ dw::core::ui::ResourceFactory *factory =
+ HT2LT(html)->getResourceFactory ();
+ DilloHtmlInputType type;
+ dw::core::ui::SelectionResource *res;
+ if (a_Html_get_attr(html, tag, tagsize, "multiple")) {
+ type = DILLO_HTML_INPUT_SEL_LIST;
+ res = factory->createListResource (dw::core::ui::ListResource::SELECTION_MULTIPLE);
+ } else {
+ type = DILLO_HTML_INPUT_SELECT;
+ res = factory->createOptionMenuResource ();
+ }
+ dw::core::ui::Embed *embed = new dw::core::ui::Embed(res);
+ if (prefs.standard_widget_colors) {
+ HTML_SET_TOP_ATTR(html, color, NULL);
+ HTML_SET_TOP_ATTR(html, backgroundColor, NULL);
+ }
+ DW2TB(html->dw)->addWidget (embed, S_TOP(html)->style);
+
+// size = 0;
+// if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "size")))
+// size = strtol(attrbuf, NULL, 10);
+//
+// multi = (a_Html_get_attr(html, tag, tagsize, "multiple")) ? 1 : 0;
+// if (size < 1)
+// size = multi ? 10 : 1;
+//
+// if (size == 1) {
+// menu = gtk_menu_new();
+// widget = gtk_option_menu_new();
+// type = DILLO_HTML_INPUT_SELECT;
+// } else {
+// menu = gtk_list_new();
+// widget = menu;
+// if (multi)
+// gtk_list_set_selection_mode(GTK_LIST(menu), GTK_SELECTION_MULTIPLE);
+// type = DILLO_HTML_INPUT_SEL_LIST;
+// }
+
+ DilloHtmlSelect *select = new DilloHtmlSelect;
+ select->options = new misc::SimpleVector<DilloHtmlOption *> (4);
+ form->addInput(type, embed, name, NULL, select, false);
+ a_Html_stash_init(html);
+ dFree(name);
+}
+
+/*
+ * ?
+ */
+void Html_tag_close_select(DilloHtml *html, int TagIdx)
+{
+ if (html->InFlags & IN_FORM &&
+ html->InFlags & IN_SELECT) {
+ if (html->InFlags & IN_OPTION)
+ Html_option_finish(html);
+ html->InFlags &= ~IN_SELECT;
+ html->InFlags &= ~IN_OPTION;
+
+ DilloHtmlForm *form = html->getCurrentForm ();
+ DilloHtmlInput *input = form->getCurrentInput ();
+ dw::core::ui::SelectionResource *res =
+ (dw::core::ui::SelectionResource*)input->embed->getResource();
+
+ int size = input->select->options->size ();
+ if (size > 0) {
+ // is anything selected?
+ bool some_selected = false;
+ for (int i = 0; i < size; i++) {
+ DilloHtmlOption *option =
+ input->select->options->get (i);
+ if (option->selected) {
+ some_selected = true;
+ break;
+ }
+ }
+
+ // select the first if nothing else is selected
+ // BUG(?): should not do this for MULTI selections
+ if (! some_selected)
+ input->select->options->get (0)->selected = true;
+
+ // add the items to the resource
+ for (int i = 0; i < size; i++) {
+ DilloHtmlOption *option =
+ input->select->options->get (i);
+ bool enabled = option->enabled;
+ bool selected = option->selected;
+ res->addItem(option->content,enabled,selected);
+ }
+ }
+ }
+
+ a_Html_pop_tag(html, TagIdx);
+}
+
+/*
+ * <OPTION>
+ */
+void Html_tag_open_option(DilloHtml *html, const char *tag, int tagsize)
+{
+ if (!(html->InFlags & IN_FORM &&
+ html->InFlags & IN_SELECT ))
+ return;
+ if (html->InFlags & IN_OPTION)
+ Html_option_finish(html);
+ html->InFlags |= IN_OPTION;
+
+ DilloHtmlForm *form = html->getCurrentForm ();
+ DilloHtmlInput *input = form->getCurrentInput ();
+
+ if (input->type == DILLO_HTML_INPUT_SELECT ||
+ input->type == DILLO_HTML_INPUT_SEL_LIST) {
+
+ DilloHtmlOption *option = new DilloHtmlOption;
+ option->value =
+ a_Html_get_attr_wdef(html, tag, tagsize, "value", NULL);
+ option->content = NULL;
+ option->selected =
+ (a_Html_get_attr(html, tag, tagsize, "selected") != NULL);
+ option->enabled =
+ (a_Html_get_attr(html, tag, tagsize, "disabled") == NULL);
+
+ int size = input->select->options->size ();
+ input->select->options->increase ();
+ input->select->options->set (size, option);
+ }
+
+ a_Html_stash_init(html);
+}
+
+/*
+ * <BUTTON>
+ */
+void Html_tag_open_button(DilloHtml *html, const char *tag, int tagsize)
+{
+ /*
+ * Buttons are rendered on one line, this is (at several levels) a
+ * bit simpler. May be changed in the future.
+ */
+ DilloHtmlForm *form;
+ DilloHtmlInputType inp_type;
+ char *type;
+
+ if (!(html->InFlags & IN_FORM)) {
+ BUG_MSG("<button> element outside <form>\n");
+ return;
+ }
+ if (html->InFlags & IN_BUTTON) {
+ BUG_MSG("nested <button>\n");
+ return;
+ }
+ html->InFlags |= IN_BUTTON;
+
+ form = html->getCurrentForm ();
+ type = a_Html_get_attr_wdef(html, tag, tagsize, "type", "");
+
+ if (!dStrcasecmp(type, "button")) {
+ inp_type = DILLO_HTML_INPUT_BUTTON;
+ } else if (!dStrcasecmp(type, "reset")) {
+ inp_type = DILLO_HTML_INPUT_BUTTON_RESET;
+ } else if (!dStrcasecmp(type, "submit") || !*type) {
+ /* submit button is the default */
+ inp_type = DILLO_HTML_INPUT_BUTTON_SUBMIT;
+ } else {
+ inp_type = DILLO_HTML_INPUT_UNKNOWN;
+ BUG_MSG("Unknown button type: \"%s\"\n", type);
+ }
+
+ if (inp_type != DILLO_HTML_INPUT_UNKNOWN) {
+ /* Render the button */
+ dw::core::style::StyleAttrs style_attrs;
+ dw::core::style::Style *style;
+ dw::core::Widget *page;
+ dw::core::ui::Embed *embed;
+ char *name, *value;
+
+ style_attrs = *S_TOP(html)->style;
+ style_attrs.margin.setVal(0);
+ style_attrs.borderWidth.setVal(0);
+ style_attrs.padding.setVal(0);
+ style = Style::create (HT2LT(html), &style_attrs);
+
+ page = new Textblock (prefs.limit_text_width);
+ page->setStyle (style);
+
+ dw::core::ui::ComplexButtonResource *complex_b_r =
+ HT2LT(html)->getResourceFactory()
+ ->createComplexButtonResource(page, true);
+ embed = new dw::core::ui::Embed(complex_b_r);
+// a_Dw_button_set_sensitive (DW_BUTTON (button), FALSE);
+
+ DW2TB(html->dw)->addParbreak (5, style);
+ DW2TB(html->dw)->addWidget (embed, style);
+ DW2TB(html->dw)->addParbreak (5, style);
+ style->unref ();
+
+ S_TOP(html)->textblock = html->dw = page;
+ /* right button press for menus for button contents */
+ html->connectSignals(page);
+
+ value = a_Html_get_attr_wdef(html, tag, tagsize, "value", NULL);
+ name = a_Html_get_attr_wdef(html, tag, tagsize, "name", NULL);
+
+ form->addInput(inp_type, embed, name, value, NULL, FALSE);
+ dFree(name);
+ dFree(value);
+ }
+ dFree(type);
+}
+
+/*
+ * Handle close <BUTTON>
+ */
+void Html_tag_close_button(DilloHtml *html, int TagIdx)
+{
+ html->InFlags &= ~IN_BUTTON;
+ a_Html_pop_tag(html, TagIdx);
+}
+
+/*
+ * Class implementations
+ */
+
+/*
+ * DilloHtmlForm
+ */
+
+/*
+ * Constructor
+ */
+DilloHtmlForm::DilloHtmlForm (DilloHtml *html2,
+ DilloHtmlMethod method2,
+ const DilloUrl *action2,
+ DilloHtmlEnc enc2,
+ const char *charset)
+{
+ html = html2;
+ method = method2;
+ action = a_Url_dup(action2);
+ enc = enc2;
+ submit_charset = dStrdup(charset);
+ inputs = new misc::SimpleVector <DilloHtmlInput*> (4);
+ num_entry_fields = 0;
+ num_submit_buttons = 0;
+ form_receiver = new DilloHtmlReceiver (this);
+}
+
+/*
+ * Destructor
+ */
+DilloHtmlForm::~DilloHtmlForm ()
+{
+ a_Url_free(action);
+ dFree(submit_charset);
+ for (int j = 0; j < inputs->size(); j++)
+ delete inputs->get(j);
+ delete(inputs);
+ if (form_receiver)
+ delete(form_receiver);
+}
+
+/*
+ * Get the current input.
+ */
+DilloHtmlInput *DilloHtmlForm::getCurrentInput ()
+{
+ return inputs->get (inputs->size() - 1);
+}
+
+/*
+ * Reset all inputs containing reset to their initial values. In
+ * general, reset is the reset button for the form.
+ */
+void DilloHtmlForm::reset ()
+{
+ int size = inputs->size();
+ for (int i = 0; i < size; i++)
+ inputs->get(i)->reset();
+}
+
+/*
+ * Add a new input, setting the initial values.
+ */
+void DilloHtmlForm::addInput(DilloHtmlInputType type,
+ dw::core::ui::Embed *embed,
+ const char *name,
+ const char *init_str,
+ DilloHtmlSelect *select,
+ bool_t init_val)
+{
+ _MSG("name=[%s] init_str=[%s] init_val=[%d]\n",
+ name, init_str, init_val);
+ DilloHtmlInput *input =
+ new DilloHtmlInput (type,embed,name,init_str,select,init_val);
+ input->connectTo (form_receiver);
+ int ni = inputs->size ();
+ inputs->increase ();
+ inputs->set (ni,input);
+
+ /* some stats */
+ if (type == DILLO_HTML_INPUT_PASSWORD ||
+ type == DILLO_HTML_INPUT_TEXT) {
+ num_entry_fields++;
+ } else if (type == DILLO_HTML_INPUT_SUBMIT ||
+ type == DILLO_HTML_INPUT_BUTTON_SUBMIT ||
+ type == DILLO_HTML_INPUT_IMAGE) {
+ num_submit_buttons++;
+ }
+}
+
+void DilloHtmlForm::eventHandler(dw::core::ui::Resource *resource,
+ int click_x, int click_y)
+{
+ MSG("DilloHtmlForm::eventHandler\n");
+
+ DilloHtmlInput *input = getInput(resource);
+ BrowserWindow *bw = html->bw;
+
+ if (!input) {
+ MSG("DilloHtmlForm::eventHandler: ERROR, input not found!\n");
+ } else if (num_entry_fields > 1 &&
+ !prefs.enterpress_forces_submit &&
+ (input->type == DILLO_HTML_INPUT_TEXT ||
+ input->type == DILLO_HTML_INPUT_PASSWORD)) {
+ /* do nothing */
+ } else if (input->type == DILLO_HTML_INPUT_FILE) {
+ /* read the file into cache */
+ const char *filename = a_UIcmd_select_file();
+ if (filename) {
+ dw::core::ui::LabelButtonResource *lbr =
+ (dw::core::ui::LabelButtonResource*)input->embed->getResource();
+ a_UIcmd_set_msg(bw, "Loading file...");
+ dStr_free(input->file_data, 1);
+ input->file_data = a_Misc_file2dstr(filename);
+ if (input->file_data) {
+ a_UIcmd_set_msg(bw, "File loaded.");
+ lbr->setLabel(filename);
+ } else {
+ a_UIcmd_set_msg(bw, "ERROR: can't load: %s", filename);
+ }
+ }
+ } else if (input->type == DILLO_HTML_INPUT_RESET ||
+ input->type == DILLO_HTML_INPUT_BUTTON_RESET) {
+ reset();
+ } else {
+ DilloUrl *url = buildQueryUrl(input, click_x, click_y);
+ if (url) {
+ a_Nav_push(bw, url);
+ a_Url_free(url);
+ }
+ // /* now, make the rendered area have its focus back */
+ // gtk_widget_grab_focus(GTK_BIN(bw->render_main_scroll)->child);
+ }
+}
+
+/*
+ * Return the input with a given resource.
+ */
+DilloHtmlInput *DilloHtmlForm::getInput (dw::core::ui::Resource *resource)
+{
+ for (int idx = 0; idx < inputs->size(); idx++) {
+ DilloHtmlInput *input = inputs->get(idx);
+ if (input->embed &&
+ resource == input->embed->getResource())
+ return input;
+ }
+ return NULL;
+}
+
+/*
+ * Return a Radio input for the given name.
+ */
+DilloHtmlInput *DilloHtmlForm::getRadioInput (const char *name)
+{
+ for (int idx = 0; idx < inputs->size(); idx++) {
+ DilloHtmlInput *input = inputs->get(idx);
+ if (input->type == DILLO_HTML_INPUT_RADIO &&
+ input->name && !dStrcasecmp(input->name, name))
+ return input;
+ }
+ return NULL;
+}
+
+/*
+ * Generate a boundary string for use in separating the parts of a
+ * multipart/form-data submission.
+ */
+char *DilloHtmlForm::makeMultipartBoundary(iconv_t encoder,
+ DilloHtmlInput *active_submit)
+{
+ const int max_tries = 10;
+ Dlist *values = dList_new(5);
+ Dstr *DataStr = dStr_new("");
+ Dstr *boundary = dStr_new("");
+ char *ret = NULL;
+
+ /* fill DataStr with names, filenames, and values */
+ for (int input_idx = 0; input_idx < inputs->size(); input_idx++) {
+ Dstr *dstr;
+ DilloHtmlInput *input = inputs->get (input_idx);
+ bool is_active_submit = (input == active_submit);
+ Html_get_input_values(input, is_active_submit, values);
+
+ if (input->name) {
+ dstr = dStr_new(input->name);
+ dstr = Html_encode_text(encoder, &dstr);
+ dStr_append_l(DataStr, dstr->str, dstr->len);
+ dStr_free(dstr, 1);
+ }
+ if (input->type == DILLO_HTML_INPUT_FILE) {
+ dw::core::ui::LabelButtonResource *lbr =
+ (dw::core::ui::LabelButtonResource*)input->embed->getResource();
+ const char *filename = lbr->getLabel();
+ if (filename[0] && strcmp(filename, input->init_str)) {
+ dstr = dStr_new(filename);
+ dstr = Html_encode_text(encoder, &dstr);
+ dStr_append_l(DataStr, dstr->str, dstr->len);
+ dStr_free(dstr, 1);
+ }
+ }
+ int length = dList_length(values);
+ for (int i = 0; i < length; i++) {
+ dstr = (Dstr *) dList_nth_data(values, 0);
+ dList_remove(values, dstr);
+ if (input->type != DILLO_HTML_INPUT_FILE)
+ dstr = Html_encode_text(encoder, &dstr);
+ dStr_append_l(DataStr, dstr->str, dstr->len);
+ dStr_free(dstr, 1);
+ }
+ }
+
+ /* generate a boundary that is not contained within the data */
+ for (int i = 0; i < max_tries && !ret; i++) {
+ // Firefox-style boundary
+ dStr_sprintf(boundary, "---------------------------%d%d%d",
+ rand(), rand(), rand());
+ dStr_truncate(boundary, 70);
+ if (dStr_memmem(DataStr, boundary) == NULL)
+ ret = boundary->str;
+ }
+ dList_free(values);
+ dStr_free(DataStr, 1);
+ dStr_free(boundary, (ret == NULL));
+ return ret;
+}
+
+/*
+ * Construct the data for a query URL
+ */
+Dstr *DilloHtmlForm::buildQueryData(DilloHtmlInput *active_submit,
+ int x, int y)
+{
+ Dstr *DataStr = NULL;
+ char *boundary = NULL;
+ iconv_t encoder = (iconv_t) -1;
+
+ if (submit_charset && dStrcasecmp(submit_charset, "UTF-8")) {
+ encoder = iconv_open(submit_charset, "UTF-8");
+ if (encoder == (iconv_t) -1) {
+ MSG_WARN("Cannot convert to character encoding '%s'\n",
+ submit_charset);
+ } else {
+ MSG("Form character encoding: '%s'\n", submit_charset);
+ }
+ }
+
+ if (enc == DILLO_HTML_ENC_MULTIPART) {
+ if (!(boundary = makeMultipartBoundary(encoder, active_submit)))
+ MSG_ERR("Cannot generate multipart/form-data boundary.\n");
+ }
+
+ if ((enc == DILLO_HTML_ENC_URLENCODING) || (boundary != NULL)) {
+ Dlist *values = dList_new(5);
+
+ DataStr = dStr_sized_new(4096);
+ for (int input_idx = 0; input_idx < inputs->size(); input_idx++) {
+ DilloHtmlInput *input = inputs->get (input_idx);
+ Dstr *name = dStr_new(input->name);
+ bool is_active_submit = (input == active_submit);
+
+ name = Html_encode_text(encoder, &name);
+ Html_get_input_values(input, is_active_submit, values);
+
+ if (input->type == DILLO_HTML_INPUT_FILE &&
+ dList_length(values) > 0) {
+ if (dList_length(values) > 1)
+ MSG_WARN("multiple files per form control not supported\n");
+ Dstr *file = (Dstr *) dList_nth_data(values, 0);
+ dList_remove(values, file);
+
+ /* Get filename and encode it. Do not encode file contents. */
+ dw::core::ui::LabelButtonResource *lbr =
+ (dw::core::ui::LabelButtonResource*)input->embed->getResource();
+ const char *filename = lbr->getLabel();
+ if (filename[0] && strcmp(filename, input->init_str)) {
+ char *p = strrchr(filename, '/');
+ if (p)
+ filename = p + 1; /* don't reveal path */
+ Dstr *dfilename = dStr_new(filename);
+ dfilename = Html_encode_text(encoder, &dfilename);
+ Html_append_input_multipart_files(DataStr, boundary,
+ name->str, file, dfilename->str);
+ dStr_free(dfilename, 1);
+ }
+ dStr_free(file, 1);
+ } else if (input->type == DILLO_HTML_INPUT_INDEX) {
+ Dstr *val = (Dstr *) dList_nth_data(values, 0);
+ dList_remove(values, val);
+ val = Html_encode_text(encoder, &val);
+ Html_urlencode_append(DataStr, val->str);
+ dStr_free(val, 1);
+ } else {
+ int length = dList_length(values), i;
+ for (i = 0; i < length; i++) {
+ Dstr *val = (Dstr *) dList_nth_data(values, 0);
+ dList_remove(values, val);
+ val = Html_encode_text(encoder, &val);
+ if (enc == DILLO_HTML_ENC_URLENCODING)
+ Html_append_input_urlencode(DataStr, name->str, val->str);
+ else if (enc == DILLO_HTML_ENC_MULTIPART)
+ Html_append_input_multipart(DataStr, boundary, name->str,
+ val->str);
+ dStr_free(val, 1);
+ }
+ if (i && input->type == DILLO_HTML_INPUT_IMAGE) {
+ /* clickpos to accompany the value just appended */
+ if (enc == DILLO_HTML_ENC_URLENCODING)
+ Html_append_clickpos_urlencode(DataStr, name, x, y);
+ else if (enc == DILLO_HTML_ENC_MULTIPART)
+ Html_append_clickpos_multipart(DataStr, boundary, name, x,y);
+ }
+ }
+ dStr_free(name, 1);
+ }
+ if (DataStr->len > 0) {
+ if (enc == DILLO_HTML_ENC_URLENCODING) {
+ if (DataStr->str[DataStr->len - 1] == '&')
+ dStr_truncate(DataStr, DataStr->len - 1);
+ } else if (enc == DILLO_HTML_ENC_MULTIPART) {
+ dStr_append(DataStr, "--");
+ }
+ }
+ dList_free(values);
+ }
+ dFree(boundary);
+ if (encoder != (iconv_t) -1)
+ (void)iconv_close(encoder);
+ return DataStr;
+}
+
+/*
+ * Build a new query URL.
+ * (Called by eventHandler())
+ * click_x and click_y are used only by input images.
+ */
+DilloUrl *DilloHtmlForm::buildQueryUrl(DilloHtmlInput *input,
+ int click_x, int click_y)
+{
+ DilloUrl *new_url = NULL;
+
+ if ((method == DILLO_HTML_METHOD_GET) ||
+ (method == DILLO_HTML_METHOD_POST)) {
+ Dstr *DataStr;
+ DilloHtmlInput *active_submit = NULL;
+
+ _MSG("DilloHtmlForm::buildQueryUrl: action=%s\n",URL_STR_(action));
+
+ if (num_submit_buttons > 0) {
+ if ((input->type == DILLO_HTML_INPUT_SUBMIT) ||
+ (input->type == DILLO_HTML_INPUT_IMAGE) ||
+ (input->type == DILLO_HTML_INPUT_BUTTON_SUBMIT)) {
+ active_submit = input;
+ }
+ }
+
+ DataStr = buildQueryData(active_submit, click_x, click_y);
+ if (DataStr) {
+ /* action was previously resolved against base URL */
+ char *action_str = dStrdup(URL_STR(action));
+
+ if (method == DILLO_HTML_METHOD_POST) {
+ new_url = a_Url_new(action_str, NULL, 0, 0, 0);
+ /* new_url keeps the dStr and sets DataStr to NULL */
+ a_Url_set_data(new_url, &DataStr);
+ a_Url_set_flags(new_url, URL_FLAGS(new_url) | URL_Post);
+ if (enc == DILLO_HTML_ENC_MULTIPART)
+ a_Url_set_flags(new_url, URL_FLAGS(new_url) | URL_MultipartEnc);
+ } else {
+ /* remove <fragment> and <query> sections if present */
+ char *url_str, *p;
+ if ((p = strchr(action_str, '#')))
+ *p = 0;
+ if ((p = strchr(action_str, '?')))
+ *p = 0;
+
+ url_str = dStrconcat(action_str, "?", DataStr->str, NULL);
+ new_url = a_Url_new(url_str, NULL, 0, 0, 0);
+ a_Url_set_flags(new_url, URL_FLAGS(new_url) | URL_Get);
+ dFree(url_str);
+ }
+ dStr_free(DataStr, 1);
+ dFree(action_str);
+ }
+ } else {
+ MSG("DilloHtmlForm::buildQueryUrl: Method unknown\n");
+ }
+
+ return new_url;
+}
+
+/*
+ * DilloHtmlReceiver
+ *
+ * TODO: Currently there's "clicked" for buttons, we surely need "enter" for
+ * textentries, and maybe the "mouseover, ...." set for Javascript.
+ */
+
+void DilloHtmlReceiver::activate (dw::core::ui::Resource *resource)
+{
+ form->eventHandler(resource, -1, -1);
+}
+
+void DilloHtmlReceiver::clicked (dw::core::ui::ButtonResource *resource,
+ int buttonNo, int x, int y)
+{
+ form->eventHandler(resource, x, y);
+}
+
+/*
+ * DilloHtmlInput
+ */
+
+/*
+ * Constructor
+ */
+DilloHtmlInput::DilloHtmlInput (DilloHtmlInputType type2,
+ dw::core::ui::Embed *embed2,
+ const char *name2,
+ const char *init_str2,
+ DilloHtmlSelect *select2,
+ bool_t init_val2)
+{
+ type = type2;
+ embed = embed2;
+ name = (name2) ? dStrdup(name2) : NULL;
+ init_str = (init_str2) ? dStrdup(init_str2) : NULL;
+ select = select2;
+ init_val = init_val2;
+ file_data = NULL;
+ reset ();
+}
+
+/*
+ * Destructor
+ */
+DilloHtmlInput::~DilloHtmlInput ()
+{
+ dFree(name);
+ dFree(init_str);
+ dStr_free(file_data, 1);
+
+ if (type == DILLO_HTML_INPUT_SELECT ||
+ type == DILLO_HTML_INPUT_SEL_LIST) {
+
+ int size = select->options->size ();
+ for (int k = 0; k < size; k++) {
+ DilloHtmlOption *option =
+ select->options->get (k);
+ dFree(option->value);
+ dFree(option->content);
+ delete(option);
+ }
+ delete(select->options);
+ delete(select);
+ }
+}
+
+/*
+ * Connect to a receiver.
+ */
+void DilloHtmlInput::connectTo(DilloHtmlReceiver *form_receiver)
+{
+ dw::core::ui::Resource *resource = NULL;
+ if (embed)
+ resource = embed->getResource ();
+ switch (type) {
+ case DILLO_HTML_INPUT_UNKNOWN:
+ case DILLO_HTML_INPUT_HIDDEN:
+ case DILLO_HTML_INPUT_CHECKBOX:
+ case DILLO_HTML_INPUT_RADIO:
+ case DILLO_HTML_INPUT_BUTTON:
+ case DILLO_HTML_INPUT_TEXTAREA:
+ case DILLO_HTML_INPUT_SELECT:
+ case DILLO_HTML_INPUT_SEL_LIST:
+ // do nothing
+ break;
+ case DILLO_HTML_INPUT_TEXT:
+ case DILLO_HTML_INPUT_PASSWORD:
+ case DILLO_HTML_INPUT_INDEX:
+ if (resource)
+ resource->connectActivate (form_receiver);
+ break;
+ case DILLO_HTML_INPUT_SUBMIT:
+ case DILLO_HTML_INPUT_RESET:
+ case DILLO_HTML_INPUT_BUTTON_SUBMIT:
+ case DILLO_HTML_INPUT_BUTTON_RESET:
+ case DILLO_HTML_INPUT_IMAGE:
+ case DILLO_HTML_INPUT_FILE:
+ if (resource)
+ ((dw::core::ui::ButtonResource *)resource)
+ ->connectClicked (form_receiver);
+ break;
+ }
+}
+
+/*
+ * Reset to the initial value.
+ */
+void DilloHtmlInput::reset ()
+{
+ switch (type) {
+ case DILLO_HTML_INPUT_TEXT:
+ case DILLO_HTML_INPUT_PASSWORD:
+ {
+ dw::core::ui::EntryResource *entryres =
+ (dw::core::ui::EntryResource*)embed->getResource();
+ entryres->setText(init_str ? init_str : "");
+ }
+ break;
+ case DILLO_HTML_INPUT_CHECKBOX:
+ case DILLO_HTML_INPUT_RADIO:
+ {
+ dw::core::ui::ToggleButtonResource *tb_r =
+ (dw::core::ui::ToggleButtonResource*)embed->getResource();
+ tb_r->setActivated(init_val);
+ }
+ break;
+ case DILLO_HTML_INPUT_SELECT:
+ if (select != NULL) {
+ /* this is in reverse order so that, in case more than one was
+ * selected, we get the last one, which is consistent with handling
+ * of multiple selected options in the layout code. */
+// for (i = select->num_options - 1; i >= 0; i--) {
+// if (select->options[i].init_val) {
+// gtk_menu_item_activate(GTK_MENU_ITEM
+// (select->options[i].menuitem));
+// Html_select_set_history(input);
+// break;
+// }
+// }
+ }
+ break;
+ case DILLO_HTML_INPUT_SEL_LIST:
+ if (!select)
+ break;
+// for (i = 0; i < select->num_options; i++) {
+// if (select->options[i].init_val) {
+// if (select->options[i].menuitem->state == GTK_STATE_NORMAL)
+// gtk_list_select_child(GTK_LIST(select->menu),
+// select->options[i].menuitem);
+// } else {
+// if (select->options[i].menuitem->state==GTK_STATE_SELECTED)
+// gtk_list_unselect_child(GTK_LIST(select->menu),
+// select->options[i].menuitem);
+// }
+// }
+ break;
+ case DILLO_HTML_INPUT_TEXTAREA:
+ if (init_str != NULL) {
+ dw::core::ui::MultiLineTextResource *textres =
+ (dw::core::ui::MultiLineTextResource*)embed->getResource();
+ textres->setText(init_str ? init_str : "");
+ }
+ break;
+ case DILLO_HTML_INPUT_FILE:
+ {
+ dw::core::ui::LabelButtonResource *lbr =
+ (dw::core::ui::LabelButtonResource*)embed->getResource();
+ lbr->setLabel(init_str);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+/*
+ * Utilities
+ */
+
+/*
+ * Pass input text through character set encoder.
+ * Return value: same input Dstr if no encoding is needed.
+ new Dstr when encoding (input Dstr is freed).
+ */
+static Dstr *Html_encode_text(iconv_t encoder, Dstr **input)
+{
+ int rc = 0;
+ Dstr *output;
+ const int bufsize = 128;
+ inbuf_t *inPtr;
+ char *buffer, *outPtr;
+ size_t inLeft, outRoom;
+ bool bad_chars = false;
+
+ if ((encoder == (iconv_t) -1) || *input == NULL || (*input)->len == 0)
+ return *input;
+
+ output = dStr_new("");
+ inPtr = (*input)->str;
+ inLeft = (*input)->len;
+ buffer = dNew(char, bufsize);
+
+ while ((rc != EINVAL) && (inLeft > 0)) {
+
+ outPtr = buffer;
+ outRoom = bufsize;
+
+ rc = iconv(encoder, &inPtr, &inLeft, &outPtr, &outRoom);
+
+ // iconv() on success, number of bytes converted
+ // -1, errno == EILSEQ illegal byte sequence found
+ // EINVAL partial character ends source buffer
+ // E2BIG destination buffer is full
+ //
+ // GNU iconv has the undocumented(!) behavior that EILSEQ is also
+ // returned when a character cannot be converted.
+
+ dStr_append_l(output, buffer, bufsize - outRoom);
+
+ if (rc == -1) {
+ rc = errno;
+ }
+ if (rc == EILSEQ){
+ /* count chars? (would be utf-8-specific) */
+ bad_chars = true;
+ inPtr++;
+ inLeft--;
+ dStr_append_c(output, '?');
+ } else if (rc == EINVAL) {
+ MSG_ERR("Html_decode_text: bad source string\n");
+ }
+ }
+
+ if (bad_chars) {
+ /*
+ * It might be friendly to inform the caller, who would know whether
+ * it is safe to display the beginning of the string in a message
+ * (isn't, e.g., a password).
+ */
+ MSG_WARN("String cannot be converted cleanly.\n");
+ }
+
+ dFree(buffer);
+ dStr_free(*input, 1);
+
+ return output;
+}
+
+/*
+ * Urlencode 'val' and append it to 'str'
+ */
+static void Html_urlencode_append(Dstr *str, const char *val)
+{
+ char *enc_val = a_Url_encode_hex_str(val);
+ dStr_append(str, enc_val);
+ dFree(enc_val);
+}
+
+/*
+ * Append a name-value pair to url data using url encoding.
+ */
+static void Html_append_input_urlencode(Dstr *data, const char *name,
+ const char *value)
+{
+ if (name && name[0]) {
+ Html_urlencode_append(data, name);
+ dStr_append_c(data, '=');
+ Html_urlencode_append(data, value);
+ dStr_append_c(data, '&');
+ }
+}
+
+/*
+ * Append files to URL data using multipart encoding.
+ * Currently only accepts one file.
+ */
+static void Html_append_input_multipart_files(Dstr* data, const char *boundary,
+ const char *name, Dstr *file,
+ const char *filename)
+{
+ const char *ctype, *ext;
+
+ if (name && name[0]) {
+ (void)a_Misc_get_content_type_from_data(file->str, file->len, &ctype);
+ /* Heuristic: text/plain with ".htm[l]" extension -> text/html */
+ if ((ext = strrchr(filename, '.')) &&
+ !dStrcasecmp(ctype, "text/plain") &&
+ (!dStrcasecmp(ext, ".html") || !dStrcasecmp(ext, ".htm"))) {
+ ctype = "text/html";
+ }
+
+ if (data->len == 0) {
+ dStr_append(data, "--");
+ dStr_append(data, boundary);
+ }
+ // todo: encode name, filename
+ dStr_sprintfa(data,
+ "\r\n"
+ "Content-Disposition: form-data; name=\"%s\"; "
+ "filename=\"%s\"\r\n"
+ "Content-Type: %s\r\n"
+ "\r\n", name, filename, ctype);
+
+ dStr_append_l(data, file->str, file->len);
+
+ dStr_sprintfa(data,
+ "\r\n"
+ "--%s", boundary);
+ }
+}
+
+/*
+ * Append a name-value pair to url data using multipart encoding.
+ */
+static void Html_append_input_multipart(Dstr *data, const char *boundary,
+ const char *name, const char *value)
+{
+ if (name && name[0]) {
+ if (data->len == 0) {
+ dStr_append(data, "--");
+ dStr_append(data, boundary);
+ }
+ // todo: encode name (RFC 2231) [coming soon]
+ dStr_sprintfa(data,
+ "\r\n"
+ "Content-Disposition: form-data; name=\"%s\"\r\n"
+ "\r\n"
+ "%s\r\n"
+ "--%s",
+ name, value, boundary);
+ }
+}
+
+/*
+ * Append an image button click position to url data using url encoding.
+ */
+static void Html_append_clickpos_urlencode(Dstr *data,
+ Dstr *name, int x,int y)
+{
+ if (name->len) {
+ Html_urlencode_append(data, name->str);
+ dStr_sprintfa(data, ".x=%d&", x);
+ Html_urlencode_append(data, name->str);
+ dStr_sprintfa(data, ".y=%d&", y);
+ } else
+ dStr_sprintfa(data, "x=%d&y=%d&", x, y);
+}
+
+/*
+ * Append an image button click position to url data using multipart encoding.
+ */
+static void Html_append_clickpos_multipart(Dstr *data, const char *boundary,
+ Dstr *name, int x, int y)
+{
+ char posstr[16];
+ int orig_len = name->len;
+
+ if (orig_len)
+ dStr_append_c(name, '.');
+ dStr_append_c(name, 'x');
+
+ snprintf(posstr, 16, "%d", x);
+ Html_append_input_multipart(data, boundary, name->str, posstr);
+ dStr_truncate(name, name->len - 1);
+ dStr_append_c(name, 'y');
+ snprintf(posstr, 16, "%d", y);
+ Html_append_input_multipart(data, boundary, name->str, posstr);
+ dStr_truncate(name, orig_len);
+}
+
+/*
+ * Get the values for a "successful control".
+ */
+static void Html_get_input_values(const DilloHtmlInput *input,
+ bool is_active_submit, Dlist *values)
+{
+ switch (input->type) {
+ case DILLO_HTML_INPUT_TEXT:
+ case DILLO_HTML_INPUT_PASSWORD:
+ case DILLO_HTML_INPUT_INDEX:
+ {
+ dw::core::ui::EntryResource *entryres =
+ (dw::core::ui::EntryResource*)input->embed->getResource();
+ dList_append(values, dStr_new(entryres->getText()));
+ }
+ break;
+ case DILLO_HTML_INPUT_TEXTAREA:
+ {
+ dw::core::ui::MultiLineTextResource *textres =
+ (dw::core::ui::MultiLineTextResource*)input->embed->getResource();
+ dList_append(values, dStr_new(textres->getText()));
+ }
+ break;
+ case DILLO_HTML_INPUT_CHECKBOX:
+ case DILLO_HTML_INPUT_RADIO:
+ {
+ dw::core::ui::ToggleButtonResource *cb_r =
+ (dw::core::ui::ToggleButtonResource*)input->embed->getResource();
+ if (input->name && input->init_str && cb_r->isActivated()) {
+ dList_append(values, dStr_new(input->init_str));
+ }
+ }
+ break;
+ case DILLO_HTML_INPUT_SUBMIT:
+ case DILLO_HTML_INPUT_BUTTON_SUBMIT:
+ if (is_active_submit)
+ dList_append(values, dStr_new(input->init_str));
+ break;
+ case DILLO_HTML_INPUT_HIDDEN:
+ dList_append(values, dStr_new(input->init_str));
+ break;
+ case DILLO_HTML_INPUT_SELECT:
+ case DILLO_HTML_INPUT_SEL_LIST:
+ { // brackets for compiler happiness.
+ dw::core::ui::SelectionResource *sel_res =
+ (dw::core::ui::SelectionResource*)input->embed->getResource();
+ int size = input->select->options->size ();
+ for (int i = 0; i < size; i++) {
+ if (sel_res->isSelected(i)) {
+ DilloHtmlOption *option = input->select->options->get(i);
+ char *val = option->value ? option->value : option->content;
+ dList_append(values, dStr_new(val));
+ }
+ }
+ }
+ break;
+ case DILLO_HTML_INPUT_IMAGE:
+ if (is_active_submit) {
+ dList_append(values, dStr_new(input->init_str));
+ }
+ break;
+ case DILLO_HTML_INPUT_FILE:
+ {
+ dw::core::ui::LabelButtonResource *lbr =
+ (dw::core::ui::LabelButtonResource*)input->embed->getResource();
+ const char *filename = lbr->getLabel();
+ if (filename[0] && strcmp(filename, input->init_str)) {
+ if (input->file_data) {
+ Dstr *file = dStr_sized_new(input->file_data->len);
+ dStr_append_l(file, input->file_data->str, input->file_data->len);
+ dList_append(values, file);
+ } else {
+ MSG("FORM file input \"%s\" not loaded.\n", filename);
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+/*
+ * Create input image for the form
+ */
+static dw::core::ui::Embed *Html_input_image(DilloHtml *html,
+ const char *tag, int tagsize,
+ DilloHtmlForm *form)
+{
+ const char *attrbuf;
+ StyleAttrs style_attrs;
+ DilloImage *Image;
+ dw::core::ui::Embed *button = NULL;
+ DilloUrl *url = NULL;
+
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "src")) &&
+ (url = a_Html_url_new(html, attrbuf, NULL, 0, 0, 0, 0))) {
+ style_attrs = *S_TOP(html)->style;
+ style_attrs.cursor = CURSOR_POINTER;
+
+ /* create new image and add it to the button */
+ if ((Image = a_Html_add_new_image(html, tag, tagsize, url, &style_attrs,
+ FALSE))) {
+ Style *style = Style::create (HT2LT(html), &style_attrs);
+ IM2DW(Image)->setStyle (style);
+ dw::core::ui::ComplexButtonResource *complex_b_r =
+ HT2LT(html)->getResourceFactory()->createComplexButtonResource(
+ IM2DW(Image), false);
+ button = new dw::core::ui::Embed(complex_b_r);
+ DW2TB(html->dw)->addWidget (button, style);
+// gtk_widget_set_sensitive(widget, FALSE); /* Until end of FORM! */
+ style->unref();
+
+ /* a right button press brings up the image menu */
+ html->connectSignals((Widget*)Image->dw);
+ } else {
+ a_Url_free(url);
+ }
+ }
+
+ if (!button)
+ DEBUG_MSG(10, "Html_input_image: unable to create image submit.\n");
+ return button;
+}
+
+/*
+ * ?
+ */
+static void Html_option_finish(DilloHtml *html)
+{
+ DilloHtmlForm *form = html->getCurrentForm ();
+ DilloHtmlInput *input = form->getCurrentInput ();
+ if (input->type == DILLO_HTML_INPUT_SELECT ||
+ input->type == DILLO_HTML_INPUT_SEL_LIST) {
+ DilloHtmlSelect *select =
+ input->select;
+ DilloHtmlOption *option =
+ select->options->get (select->options->size() - 1);
+ option->content =
+ a_Html_parse_entities(html, html->Stash->str, html->Stash->len);
+ }
+}
diff --git a/src/form.hh b/src/form.hh
index 291bfd75..af7ff6f4 100644
--- a/src/form.hh
+++ b/src/form.hh
@@ -1,6 +1,8 @@
#ifndef __FORM_HH__
#define __FORM_HH__
+#include "url.h"
+
/*
* Typedefs
*/
@@ -21,5 +23,34 @@ typedef enum {
*/
class DilloHtmlForm;
+class DilloHtml;
+
+/*
+ * Form API
+ */
+
+DilloHtmlForm *a_Html_form_new(DilloHtml *html,
+ DilloHtmlMethod method,
+ const DilloUrl *action,
+ DilloHtmlEnc enc,
+ const char *charset);
+
+void a_Html_form_delete(DilloHtmlForm* form);
+
+/*
+ * Form parsing functions
+ */
+
+void Html_tag_open_form(DilloHtml *html, const char *tag, int tagsize);
+void Html_tag_close_form(DilloHtml *html, int TagIdx);
+void Html_tag_open_input(DilloHtml *html, const char *tag, int tagsize);
+void Html_tag_open_isindex(DilloHtml *html, const char *tag, int tagsize);
+void Html_tag_open_textarea(DilloHtml *html, const char *tag, int tagsize);
+void Html_tag_close_textarea(DilloHtml *html, int TagIdx);
+void Html_tag_open_select(DilloHtml *html, const char *tag, int tagsize);
+void Html_tag_close_select(DilloHtml *html, int TagIdx);
+void Html_tag_open_option(DilloHtml *html, const char *tag, int tagsize);
+void Html_tag_open_button(DilloHtml *html, const char *tag, int tagsize);
+void Html_tag_close_button(DilloHtml *html, int TagIdx);
#endif /* __FORM_HH__ */
diff --git a/src/html.cc b/src/html.cc
index 05371926..0eb7952d 100644
--- a/src/html.cc
+++ b/src/html.cc
@@ -81,10 +81,6 @@ class DilloHtml;
typedef void (*TagOpenFunct) (DilloHtml *Html, const char *Tag, int Tagsize);
typedef void (*TagCloseFunct) (DilloHtml *Html, int TagIdx);
typedef struct _DilloHtmlClass DilloHtmlClass;
-class DilloHtmlReceiver;
-class DilloHtmlInput;
-typedef struct _DilloHtmlSelect DilloHtmlSelect;
-typedef struct _DilloHtmlOption DilloHtmlOption;
typedef enum {
SEEK_ATTR_START,
@@ -102,125 +98,6 @@ typedef enum {
HTML_ParseEntities = 1 << 2
} DilloHtmlTagParsingFlags;
-typedef enum {
- DILLO_HTML_INPUT_UNKNOWN,
- DILLO_HTML_INPUT_TEXT,
- DILLO_HTML_INPUT_PASSWORD,
- DILLO_HTML_INPUT_CHECKBOX,
- DILLO_HTML_INPUT_RADIO,
- DILLO_HTML_INPUT_IMAGE,
- DILLO_HTML_INPUT_FILE,
- DILLO_HTML_INPUT_BUTTON,
- DILLO_HTML_INPUT_HIDDEN,
- DILLO_HTML_INPUT_SUBMIT,
- DILLO_HTML_INPUT_RESET,
- DILLO_HTML_INPUT_BUTTON_SUBMIT,
- DILLO_HTML_INPUT_BUTTON_RESET,
- DILLO_HTML_INPUT_SELECT,
- DILLO_HTML_INPUT_SEL_LIST,
- DILLO_HTML_INPUT_TEXTAREA,
- DILLO_HTML_INPUT_INDEX
-} DilloHtmlInputType;
-
-/*-----------------------------------------------------------------------------
- * Data Structures
- *---------------------------------------------------------------------------*/
-
-class DilloHtmlForm {
- friend class DilloHtmlReceiver;
-
- DilloHtml *html;
- void eventHandler(Resource *resource, int click_x, int click_y);
-
-public: //BUG: for now everything is public
- DilloHtmlMethod method;
- DilloUrl *action;
- DilloHtmlEnc enc;
- char *submit_charset;
-
- misc::SimpleVector<DilloHtmlInput*> *inputs;
-
- int num_entry_fields;
- int num_submit_buttons;
-
- DilloHtmlReceiver *form_receiver;
-
-public:
- DilloHtmlForm (DilloHtml *html,
- DilloHtmlMethod method, const DilloUrl *action,
- DilloHtmlEnc enc, const char *charset);
- ~DilloHtmlForm ();
- inline DilloHtmlInput *getCurrentInput ();
- DilloHtmlInput *getInput (Resource *resource);
- DilloHtmlInput *getRadioInput (const char *name);
- void reset ();
- void addInput(DilloHtmlInputType type,
- Embed *embed,
- const char *name,
- const char *init_str,
- DilloHtmlSelect *select,
- bool_t init_val);
- DilloUrl *buildQueryUrl(DilloHtmlInput *input, int click_x, int click_y);
- Dstr *buildQueryData(DilloHtmlInput *active_submit, int x, int y);
- char *makeMultipartBoundary(iconv_t encoder, DilloHtmlInput *active_submit);
-};
-
-class DilloHtmlReceiver:
- public Resource::ActivateReceiver,
- public ButtonResource::ClickedReceiver
-{
- friend class DilloHtmlForm;
- DilloHtmlForm* form;
- DilloHtmlReceiver (DilloHtmlForm* form2) { form = form2; }
- ~DilloHtmlReceiver () { }
- void activate (Resource *resource);
- void clicked (ButtonResource *resource, int buttonNo, int x, int y);
-};
-
-struct _DilloHtmlOption {
- char *value, *content;
- bool selected, enabled;
-};
-
-struct _DilloHtmlSelect {
- misc::SimpleVector<DilloHtmlOption *> *options;
-};
-
-class DilloHtmlInput {
-
- // DilloHtmlForm::addInput() calls connectTo()
- friend class DilloHtmlForm;
-
-public: //BUG: for now everything is public
- DilloHtmlInputType type;
- Embed *embed; /* May be NULL (think: hidden input) */
- char *name;
- char *init_str; /* note: some overloading - for buttons, init_str
- is simply the value of the button; for text
- entries, it is the initial value */
- DilloHtmlSelect *select;
- bool_t init_val; /* only meaningful for buttons */
- Dstr *file_data; /* only meaningful for file inputs.
- todo: may become a list... */
-
-private:
- void connectTo(DilloHtmlReceiver *form_receiver);
-
-public:
- DilloHtmlInput (DilloHtmlInputType type,
- Embed *embed,
- const char *name,
- const char *init_str,
- DilloHtmlSelect *select,
- bool_t init_val);
- ~DilloHtmlInput ();
- void reset();
-};
-
-/*-----------------------------------------------------------------------------
- * Classes
- *---------------------------------------------------------------------------*/
-
/*
* Exported function with C linkage.
@@ -232,20 +109,11 @@ void *a_Html_text(const char *type, void *P, CA_Callback_t *Call,void **Data);
/*-----------------------------------------------------------------------------
* Forward declarations
*---------------------------------------------------------------------------*/
-static const char *Html_get_attr(DilloHtml *html,
- const char *tag,
- int tagsize,
- const char *attrname);
static const char *Html_get_attr2(DilloHtml *html,
const char *tag,
int tagsize,
const char *attrname,
int tag_parsing_flags);
-static char *Html_get_attr_wdef(DilloHtml *html,
- const char *tag,
- int tagsize,
- const char *attrname,
- const char *def);
static void Html_add_widget(DilloHtml *html, Widget *widget,
char *width_str, char *height_str,
StyleAttrs *style_attrs);
@@ -253,15 +121,8 @@ static int Html_write_raw(DilloHtml *html, char *buf, int bufsize, int Eof);
static void Html_load_image(BrowserWindow *bw, DilloUrl *url,
DilloImage *image);
static void Html_callback(int Op, CacheClient_t *Client);
-static void Html_tag_open_input(DilloHtml *html, const char *tag, int tagsize);
static int Html_tag_index(const char *tag);
static void Html_tag_cleanup_at_close(DilloHtml *html, int TagIdx);
-static DilloHtmlForm *Html_form_new (DilloHtml *html,
- DilloHtmlMethod method,
- const DilloUrl *action,
- DilloHtmlEnc enc,
- const char *charset);
-static void Html_form_delete (DilloHtmlForm *form);
/*-----------------------------------------------------------------------------
* Local Data
@@ -308,10 +169,10 @@ void DilloHtml::bugMessage(const char *format, ... )
* Wrapper for a_Url_new that adds an error detection message.
* (if use_base_url is TRUE, html->base_url is used)
*/
-static DilloUrl *Html_url_new(DilloHtml *html,
- const char *url_str, const char *base_url,
- int flags, int32_t posx, int32_t posy,
- int use_base_url)
+DilloUrl *a_Html_url_new(DilloHtml *html,
+ const char *url_str, const char *base_url,
+ int flags, int32_t posx, int32_t posy,
+ int use_base_url)
{
DilloUrl *url;
int n_ic, n_ic_spc;
@@ -444,7 +305,7 @@ static void Html_tag_set_align_attr(DilloHtml *html, const char *tag,
{
const char *align, *charattr;
- if ((align = Html_get_attr(html, tag, tagsize, "align"))) {
+ if ((align = a_Html_get_attr(html, tag, tagsize, "align"))) {
if (dStrcasecmp (align, "left") == 0)
HTML_SET_TOP_ATTR (html, textAlign, TEXT_ALIGN_LEFT);
else if (dStrcasecmp (align, "right") == 0)
@@ -456,7 +317,7 @@ static void Html_tag_set_align_attr(DilloHtml *html, const char *tag,
else if (dStrcasecmp (align, "char") == 0) {
/* todo: Actually not supported for <p> etc. */
HTML_SET_TOP_ATTR (html, textAlign, TEXT_ALIGN_STRING);
- if ((charattr = Html_get_attr(html, tag, tagsize, "char"))) {
+ if ((charattr = a_Html_get_attr(html, tag, tagsize, "char"))) {
if (charattr[0] == 0)
/* todo: ALIGN=" ", and even ALIGN="&32;" will reult in
* an empty string (don't know whether the latter is
@@ -481,7 +342,7 @@ static bool_t Html_tag_set_valign_attr(DilloHtml *html, const char *tag,
{
const char *attr;
- if ((attr = Html_get_attr(html, tag, tagsize, "valign"))) {
+ if ((attr = a_Html_get_attr(html, tag, tagsize, "valign"))) {
if (dStrcasecmp (attr, "top") == 0)
style_attrs->valign = VALIGN_TOP;
else if (dStrcasecmp (attr, "bottom") == 0)
@@ -720,7 +581,7 @@ DilloHtml::~DilloHtml()
a_Url_free(base_url);
for (int i = 0; i < forms->size(); i++)
- Html_form_delete (forms->get(i));
+ a_Html_form_delete (forms->get(i));
delete(forms);
for (int i = 0; i < links->size(); i++)
@@ -833,7 +694,7 @@ void DilloHtml::finishParsing(int ClientKey)
int DilloHtml::formNew(DilloHtmlMethod method, const DilloUrl *action,
DilloHtmlEnc enc, const char *charset)
{
- DilloHtmlForm *form = Html_form_new (this,method,action,enc,charset);
+ DilloHtmlForm *form = a_Html_form_new (this,method,action,enc,charset);
int nf = forms->size ();
forms->increase ();
forms->set (nf, form);
@@ -970,264 +831,9 @@ bool DilloHtml::HtmlLinkReceiver::click (Widget *widget, int link, int img,
}
/*
- * Create and initialize a new DilloHtmlForm class
- */
-DilloHtmlForm::DilloHtmlForm (DilloHtml *html2,
- DilloHtmlMethod method2,
- const DilloUrl *action2,
- DilloHtmlEnc enc2,
- const char *charset)
-{
- html = html2;
- method = method2;
- action = a_Url_dup(action2);
- enc = enc2;
- submit_charset = dStrdup(charset);
- inputs = new misc::SimpleVector <DilloHtmlInput*> (4);
- num_entry_fields = 0;
- num_submit_buttons = 0;
- form_receiver = new DilloHtmlReceiver (this);
-}
-
-/*
- * API wrapper for DilloHtmlForm::DilloHtmlForm().
- */
-
-static DilloHtmlForm *Html_form_new (DilloHtml *html,
- DilloHtmlMethod method,
- const DilloUrl *action,
- DilloHtmlEnc enc,
- const char *charset)
-{
- return new DilloHtmlForm (html,method,action,enc,charset);
-}
-
-/*
- * Free memory used by the DilloHtmlForm class.
- */
-DilloHtmlForm::~DilloHtmlForm ()
-{
- a_Url_free(action);
- dFree(submit_charset);
- for (int j = 0; j < inputs->size(); j++)
- delete inputs->get(j);
- delete(inputs);
- if (form_receiver)
- delete(form_receiver);
-}
-
-/*
- * API wrapper for DilloHtmlForm::~DilloHtmlForm().
- */
-
-static void Html_form_delete (DilloHtmlForm *form)
-{
- delete form;
-}
-
-/*
- * Get the current input.
- */
-DilloHtmlInput *DilloHtmlForm::getCurrentInput ()
-{
- return inputs->get (inputs->size() - 1);
-}
-
-/*
- * Reset all inputs containing reset to their initial values. In
- * general, reset is the reset button for the form.
- */
-void DilloHtmlForm::reset ()
-{
- int size = inputs->size();
- for (int i = 0; i < size; i++)
- inputs->get(i)->reset();
-}
-
-/*
- * Add a new input, setting the initial values.
- */
-void DilloHtmlForm::addInput(DilloHtmlInputType type,
- Embed *embed,
- const char *name,
- const char *init_str,
- DilloHtmlSelect *select,
- bool_t init_val)
-{
- _MSG("name=[%s] init_str=[%s] init_val=[%d]\n",
- name, init_str, init_val);
- DilloHtmlInput *input =
- new DilloHtmlInput (type,embed,name,init_str,select,init_val);
- input->connectTo (form_receiver);
- int ni = inputs->size ();
- inputs->increase ();
- inputs->set (ni,input);
-
- /* some stats */
- if (type == DILLO_HTML_INPUT_PASSWORD ||
- type == DILLO_HTML_INPUT_TEXT) {
- num_entry_fields++;
- } else if (type == DILLO_HTML_INPUT_SUBMIT ||
- type == DILLO_HTML_INPUT_BUTTON_SUBMIT ||
- type == DILLO_HTML_INPUT_IMAGE) {
- num_submit_buttons++;
- }
-}
-
-/*
- * Create and initialize a new DilloHtmlInput class
- */
-DilloHtmlInput::DilloHtmlInput (DilloHtmlInputType type2,
- Embed *embed2,
- const char *name2,
- const char *init_str2,
- DilloHtmlSelect *select2,
- bool_t init_val2)
-{
- type = type2;
- embed = embed2;
- name = (name2) ? dStrdup(name2) : NULL;
- init_str = (init_str2) ? dStrdup(init_str2) : NULL;
- select = select2;
- init_val = init_val2;
- file_data = NULL;
- reset ();
-}
-
-/*
- * Free memory used by the DilloHtmlInput class.
- */
-DilloHtmlInput::~DilloHtmlInput ()
-{
- dFree(name);
- dFree(init_str);
- dStr_free(file_data, 1);
-
- if (type == DILLO_HTML_INPUT_SELECT ||
- type == DILLO_HTML_INPUT_SEL_LIST) {
-
- int size = select->options->size ();
- for (int k = 0; k < size; k++) {
- DilloHtmlOption *option =
- select->options->get (k);
- dFree(option->value);
- dFree(option->content);
- delete(option);
- }
- delete(select->options);
- delete(select);
- }
-}
-
-/*
- * Connect to a receiver.
- */
-void DilloHtmlInput::connectTo(DilloHtmlReceiver *form_receiver)
-{
- Resource *resource = NULL;
- if (embed)
- resource = embed->getResource ();
- switch (type) {
- case DILLO_HTML_INPUT_UNKNOWN:
- case DILLO_HTML_INPUT_HIDDEN:
- case DILLO_HTML_INPUT_CHECKBOX:
- case DILLO_HTML_INPUT_RADIO:
- case DILLO_HTML_INPUT_BUTTON:
- case DILLO_HTML_INPUT_TEXTAREA:
- case DILLO_HTML_INPUT_SELECT:
- case DILLO_HTML_INPUT_SEL_LIST:
- // do nothing
- break;
- case DILLO_HTML_INPUT_TEXT:
- case DILLO_HTML_INPUT_PASSWORD:
- case DILLO_HTML_INPUT_INDEX:
- if (resource)
- resource->connectActivate (form_receiver);
- break;
- case DILLO_HTML_INPUT_SUBMIT:
- case DILLO_HTML_INPUT_RESET:
- case DILLO_HTML_INPUT_BUTTON_SUBMIT:
- case DILLO_HTML_INPUT_BUTTON_RESET:
- case DILLO_HTML_INPUT_IMAGE:
- case DILLO_HTML_INPUT_FILE:
- if (resource)
- ((ButtonResource *)resource)->connectClicked (form_receiver);
- break;
- }
-}
-
-/*
- * Reset to the initial value.
- */
-void DilloHtmlInput::reset ()
-{
- switch (type) {
- case DILLO_HTML_INPUT_TEXT:
- case DILLO_HTML_INPUT_PASSWORD:
- EntryResource *entryres;
- entryres = (EntryResource*)embed->getResource();
- entryres->setText(init_str ? init_str : "");
- break;
- case DILLO_HTML_INPUT_CHECKBOX:
- case DILLO_HTML_INPUT_RADIO:
- ToggleButtonResource *tb_r;
- tb_r = (ToggleButtonResource*)embed->getResource();
- tb_r->setActivated(init_val);
- break;
- case DILLO_HTML_INPUT_SELECT:
- if (select != NULL) {
- /* this is in reverse order so that, in case more than one was
- * selected, we get the last one, which is consistent with handling
- * of multiple selected options in the layout code. */
-// for (i = select->num_options - 1; i >= 0; i--) {
-// if (select->options[i].init_val) {
-// gtk_menu_item_activate(GTK_MENU_ITEM
-// (select->options[i].menuitem));
-// Html_select_set_history(input);
-// break;
-// }
-// }
- }
- break;
- case DILLO_HTML_INPUT_SEL_LIST:
- if (!select)
- break;
-// for (i = 0; i < select->num_options; i++) {
-// if (select->options[i].init_val) {
-// if (select->options[i].menuitem->state == GTK_STATE_NORMAL)
-// gtk_list_select_child(GTK_LIST(select->menu),
-// select->options[i].menuitem);
-// } else {
-// if (select->options[i].menuitem->state==GTK_STATE_SELECTED)
-// gtk_list_unselect_child(GTK_LIST(select->menu),
-// select->options[i].menuitem);
-// }
-// }
- break;
- case DILLO_HTML_INPUT_TEXTAREA:
- if (init_str != NULL) {
- MultiLineTextResource *textres;
- textres =
- (MultiLineTextResource*)
- embed->getResource();
- textres->setText(init_str ? init_str : "");
- }
- break;
- case DILLO_HTML_INPUT_FILE:
- { LabelButtonResource *lbr =
- (LabelButtonResource *)embed->getResource();
- lbr->setLabel(init_str);
- break;
- }
- default:
- break;
- }
-}
-
-/*
* Initialize the stash buffer
*/
-static void Html_stash_init(DilloHtml *html)
+void a_Html_stash_init(DilloHtml *html)
{
S_TOP(html)->parse_mode = DILLO_HTML_PARSE_MODE_STASH;
html->StashSpace = FALSE;
@@ -1438,8 +1044,7 @@ static int Html_parse_entity(DilloHtml *html, const char *token,
* Convert all the entities in a token to utf8 encoding. Takes
* a token and its length, and returns a newly allocated string.
*/
-static char *
- Html_parse_entities(DilloHtml *html, const char *token, int toksize)
+char *a_Html_parse_entities(DilloHtml *html, const char *token, int toksize)
{
const char *esc_set = "&\xE2\xC2";
char *new_str, buf[4];
@@ -1569,7 +1174,7 @@ static void Html_process_word(DilloHtml *html, const char *word, int size)
dStr_append_c(html->Stash, ' ');
html->StashSpace = FALSE;
}
- Pword = Html_parse_entities(html, word, size);
+ Pword = a_Html_parse_entities(html, word, size);
dStr_append(html->Stash, Pword);
dFree(Pword);
@@ -1584,7 +1189,7 @@ static void Html_process_word(DilloHtml *html, const char *word, int size)
} else if (parse_mode == DILLO_HTML_PARSE_MODE_PRE) {
/* all this overhead is to catch white-space entities */
- Pword = Html_parse_entities(html, word, size);
+ Pword = a_Html_parse_entities(html, word, size);
for (start = i = 0; Pword[i]; start = i)
if (isspace(Pword[i])) {
while (Pword[++i] && isspace(Pword[i]));
@@ -1601,7 +1206,7 @@ static void Html_process_word(DilloHtml *html, const char *word, int size)
} else {
/* Collapse white-space entities inside the word (except &nbsp;) */
- Pword = Html_parse_entities(html, word, size);
+ Pword = a_Html_parse_entities(html, word, size);
for (i = 0; Pword[i]; ++i)
if (strchr("\t\f\n\r", Pword[i]))
for (j = i; (Pword[j] = Pword[j+1]); ++j);
@@ -1762,7 +1367,7 @@ static void Html_tag_cleanup_at_close(DilloHtml *html, int TagIdx)
/*
* Cleanup (conditional), and Pop the tag (if it matches)
*/
-static void Html_pop_tag(DilloHtml *html, int TagIdx)
+void a_Html_pop_tag(DilloHtml *html, int TagIdx)
{
Html_tag_cleanup_at_close(html, TagIdx);
}
@@ -1981,7 +1586,7 @@ static void Html_tag_close_html(DilloHtml *html, int TagIdx)
/* beware of pages with multiple HTML close tags... :-P */
html->InFlags &= ~IN_HTML;
}
- Html_pop_tag(html, TagIdx);
+ a_Html_pop_tag(html, TagIdx);
}
/*
@@ -2017,7 +1622,7 @@ static void Html_tag_close_head(DilloHtml *html, int TagIdx)
html->InFlags &= ~IN_HEAD;
}
- Html_pop_tag(html, TagIdx);
+ a_Html_pop_tag(html, TagIdx);
}
/*
@@ -2027,7 +1632,7 @@ static void Html_tag_close_head(DilloHtml *html, int TagIdx)
static void Html_tag_open_title(DilloHtml *html, const char *tag, int tagsize)
{
++html->Num_TITLE;
- Html_stash_init(html);
+ a_Html_stash_init(html);
}
/*
@@ -2043,7 +1648,7 @@ static void Html_tag_close_title(DilloHtml *html, int TagIdx)
} else {
BUG_MSG("the TITLE element must be inside the HEAD section\n");
}
- Html_pop_tag(html, TagIdx);
+ a_Html_pop_tag(html, TagIdx);
}
/*
@@ -2053,7 +1658,7 @@ static void Html_tag_close_title(DilloHtml *html, int TagIdx)
*/
static void Html_tag_open_script(DilloHtml *html, const char *tag, int tagsize)
{
- Html_stash_init(html);
+ a_Html_stash_init(html);
S_TOP(html)->parse_mode = DILLO_HTML_PARSE_MODE_VERBATIM;
}
@@ -2063,7 +1668,7 @@ static void Html_tag_open_script(DilloHtml *html, const char *tag, int tagsize)
static void Html_tag_close_script(DilloHtml *html, int TagIdx)
{
/* eventually the stash will be sent to an interpreter for parsing */
- Html_pop_tag(html, TagIdx);
+ a_Html_pop_tag(html, TagIdx);
}
/*
@@ -2073,7 +1678,7 @@ static void Html_tag_close_script(DilloHtml *html, int TagIdx)
*/
static void Html_tag_open_style(DilloHtml *html, const char *tag, int tagsize)
{
- Html_stash_init(html);
+ a_Html_stash_init(html);
S_TOP(html)->parse_mode = DILLO_HTML_PARSE_MODE_VERBATIM;
}
@@ -2083,7 +1688,7 @@ static void Html_tag_open_style(DilloHtml *html, const char *tag, int tagsize)
static void Html_tag_close_style(DilloHtml *html, int TagIdx)
{
/* eventually the stash will be sent to an interpreter for parsing */
- Html_pop_tag(html, TagIdx);
+ a_Html_pop_tag(html, TagIdx);
}
/*
@@ -2113,7 +1718,7 @@ static void Html_tag_open_body(DilloHtml *html, const char *tag, int tagsize)
textblock = DW2TB(html->dw);
if (!prefs.force_my_colors) {
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "bgcolor"))) {
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "bgcolor"))) {
color = Html_color_parse(html, attrbuf, prefs.bg_color);
if (color == 0xffffff && !prefs.allow_white_bg)
color = prefs.bg_color;
@@ -2127,16 +1732,16 @@ static void Html_tag_open_body(DilloHtml *html, const char *tag, int tagsize)
Color::createShaded (HT2LT(html), color));
}
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "text"))) {
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "text"))) {
color = Html_color_parse(html, attrbuf, prefs.text_color);
HTML_SET_TOP_ATTR (html, color,
Color::createSimple (HT2LT(html),color));
}
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "link")))
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "link")))
html->link_color = Html_color_parse(html, attrbuf, prefs.link_color);
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "vlink")))
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "vlink")))
html->visited_color = Html_color_parse(html, attrbuf,
prefs.visited_color);
@@ -2162,7 +1767,7 @@ static void Html_tag_close_body(DilloHtml *html, int TagIdx)
/* some tag soup pages use multiple BODY tags... */
html->InFlags &= ~IN_BODY;
}
- Html_pop_tag(html, TagIdx);
+ a_Html_pop_tag(html, TagIdx);
}
/*
@@ -2197,11 +1802,11 @@ static void Html_tag_open_table(DilloHtml *html, const char *tag, int tagsize)
DW2TB(html->dw)->addParbreak (0, S_TOP(html)->style);
#ifdef USE_TABLES
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "border")))
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "border")))
border = isdigit(attrbuf[0]) ? strtol (attrbuf, NULL, 10) : 1;
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "cellspacing")))
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "cellspacing")))
cellspacing = strtol (attrbuf, NULL, 10);
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "cellpadding")))
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "cellpadding")))
cellpadding = strtol (attrbuf, NULL, 10);
/* The style for the table */
@@ -2220,10 +1825,10 @@ static void Html_tag_open_table(DilloHtml *html, const char *tag, int tagsize)
style_attrs.hBorderSpacing = cellspacing;
style_attrs.vBorderSpacing = cellspacing;
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "width")))
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "width")))
style_attrs.width = Html_parse_length (html, attrbuf);
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "align"))) {
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "align"))) {
if (dStrcasecmp (attrbuf, "left") == 0)
style_attrs.textAlign = TEXT_ALIGN_LEFT;
else if (dStrcasecmp (attrbuf, "right") == 0)
@@ -2233,7 +1838,7 @@ static void Html_tag_open_table(DilloHtml *html, const char *tag, int tagsize)
}
if (!prefs.force_my_colors &&
- (attrbuf = Html_get_attr(html, tag, tagsize, "bgcolor"))) {
+ (attrbuf = a_Html_get_attr(html, tag, tagsize, "bgcolor"))) {
bgcolor = Html_color_parse(html, attrbuf, -1);
if (bgcolor != -1) {
if (bgcolor == 0xffffff && !prefs.allow_white_bg)
@@ -2302,14 +1907,14 @@ static void Html_tag_open_table_cell(DilloHtml *html,
/* continues */
case DILLO_HTML_TABLE_MODE_TR:
case DILLO_HTML_TABLE_MODE_TD:
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "colspan"))) {
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "colspan"))) {
char *invalid;
colspan = strtol(attrbuf, &invalid, 10);
if ((colspan < 0) || (attrbuf == invalid))
colspan = 1;
}
/* todo: check errors? */
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "rowspan")))
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "rowspan")))
rowspan = MAX(1, strtol (attrbuf, NULL, 10));
/* text style */
@@ -2317,7 +1922,7 @@ static void Html_tag_open_table_cell(DilloHtml *html,
style_attrs = *old_style;
if (!S_TOP(html)->cell_text_align_set)
style_attrs.textAlign = text_align;
- if (Html_get_attr(html, tag, tagsize, "nowrap"))
+ if (a_Html_get_attr(html, tag, tagsize, "nowrap"))
style_attrs.whiteSpace = WHITE_SPACE_NOWRAP;
else
style_attrs.whiteSpace = WHITE_SPACE_NORMAL;
@@ -2331,7 +1936,7 @@ static void Html_tag_open_table_cell(DilloHtml *html,
style_attrs = *S_TOP(html)->table_cell_style;
new_style = FALSE;
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "width"))) {
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "width"))) {
style_attrs.width = Html_parse_length (html, attrbuf);
new_style = TRUE;
}
@@ -2340,7 +1945,7 @@ static void Html_tag_open_table_cell(DilloHtml *html,
new_style = TRUE;
if (!prefs.force_my_colors &&
- (attrbuf = Html_get_attr(html, tag, tagsize, "bgcolor"))) {
+ (attrbuf = a_Html_get_attr(html, tag, tagsize, "bgcolor"))) {
bgcolor = Html_color_parse(html, attrbuf, -1);
if (bgcolor != -1) {
if (bgcolor == 0xffffff && !prefs.allow_white_bg)
@@ -2427,7 +2032,7 @@ static void Html_tag_open_tr(DilloHtml *html, const char *tag, int tagsize)
style = NULL;
if (!prefs.force_my_colors &&
- (attrbuf = Html_get_attr(html, tag, tagsize, "bgcolor"))) {
+ (attrbuf = a_Html_get_attr(html, tag, tagsize, "bgcolor"))) {
bgcolor = Html_color_parse(html, attrbuf, -1);
if (bgcolor != -1) {
if (bgcolor == 0xffffff && !prefs.allow_white_bg)
@@ -2446,7 +2051,7 @@ static void Html_tag_open_tr(DilloHtml *html, const char *tag, int tagsize)
if (style)
style->unref ();
- if (Html_get_attr (html, tag, tagsize, "align")) {
+ if (a_Html_get_attr (html, tag, tagsize, "align")) {
S_TOP(html)->cell_text_align_set = TRUE;
Html_tag_set_align_attr (html, tag, tagsize);
}
@@ -2488,10 +2093,10 @@ static void Html_tag_open_frame (DilloHtml *html, const char *tag, int tagsize)
textblock = DW2TB(html->dw);
- if (!(attrbuf = Html_get_attr(html, tag, tagsize, "src")))
+ if (!(attrbuf = a_Html_get_attr(html, tag, tagsize, "src")))
return;
- if (!(url = Html_url_new(html, attrbuf, NULL, 0, 0, 0, 0)))
+ if (!(url = a_Html_url_new(html, attrbuf, NULL, 0, 0, 0, 0)))
return;
src = dStrdup(attrbuf);
@@ -2525,7 +2130,7 @@ static void Html_tag_open_frame (DilloHtml *html, const char *tag, int tagsize)
} else {
/* FRAME:
* If 'name' tag is present use it, if not use 'src' value */
- if (!(attrbuf = Html_get_attr(html, tag, tagsize, "name"))) {
+ if (!(attrbuf = a_Html_get_attr(html, tag, tagsize, "name"))) {
textblock->addText (dStrdup(src), link_style);
} else {
textblock->addText (dStrdup(attrbuf), link_style);
@@ -2569,7 +2174,7 @@ static void Html_tag_open_h(DilloHtml *html, const char *tag, int tagsize)
a_Menu_pagemarks_set_text(html->bw, html->Stash->str);
a_Menu_pagemarks_add(html->bw, DW2TB(html->dw),
S_TOP(html)->style, (tag[2] - '0'));
- Html_stash_init(html);
+ a_Html_stash_init(html);
S_TOP(html)->parse_mode =
DILLO_HTML_PARSE_MODE_STASH_AND_BODY;
}
@@ -2581,7 +2186,7 @@ static void Html_tag_close_h(DilloHtml *html, int TagIdx)
{
a_Menu_pagemarks_set_text(html->bw, html->Stash->str);
DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
- Html_pop_tag(html, TagIdx);
+ a_Html_pop_tag(html, TagIdx);
}
/*
@@ -2607,94 +2212,6 @@ static void Html_tag_open_br(DilloHtml *html, const char *tag, int tagsize)
}
/*
- * <BUTTON>
- */
-static void Html_tag_open_button(DilloHtml *html, const char *tag, int tagsize)
-{
- /*
- * Buttons are rendered on one line, this is (at several levels) a
- * bit simpler. May be changed in the future.
- */
- DilloHtmlForm *form;
- DilloHtmlInputType inp_type;
- char *type;
-
- if (!(html->InFlags & IN_FORM)) {
- BUG_MSG("<button> element outside <form>\n");
- return;
- }
- if (html->InFlags & IN_BUTTON) {
- BUG_MSG("nested <button>\n");
- return;
- }
- html->InFlags |= IN_BUTTON;
-
- form = html->getCurrentForm ();
- type = Html_get_attr_wdef(html, tag, tagsize, "type", "");
-
- if (!dStrcasecmp(type, "button")) {
- inp_type = DILLO_HTML_INPUT_BUTTON;
- } else if (!dStrcasecmp(type, "reset")) {
- inp_type = DILLO_HTML_INPUT_BUTTON_RESET;
- } else if (!dStrcasecmp(type, "submit") || !*type) {
- /* submit button is the default */
- inp_type = DILLO_HTML_INPUT_BUTTON_SUBMIT;
- } else {
- inp_type = DILLO_HTML_INPUT_UNKNOWN;
- BUG_MSG("Unknown button type: \"%s\"\n", type);
- }
-
- if (inp_type != DILLO_HTML_INPUT_UNKNOWN) {
- /* Render the button */
- StyleAttrs style_attrs;
- Style *style;
- Widget *page;
- Embed *embed;
- char *name, *value;
-
- style_attrs = *S_TOP(html)->style;
- style_attrs.margin.setVal(0);
- style_attrs.borderWidth.setVal(0);
- style_attrs.padding.setVal(0);
- style = Style::create (HT2LT(html), &style_attrs);
-
- page = new Textblock (prefs.limit_text_width);
- page->setStyle (style);
-
- ComplexButtonResource *complex_b_r = HT2LT(html)->
- getResourceFactory()->createComplexButtonResource(page, true);
- embed = new Embed(complex_b_r);
-// a_Dw_button_set_sensitive (DW_BUTTON (button), FALSE);
-
- DW2TB(html->dw)->addParbreak (5, style);
- DW2TB(html->dw)->addWidget (embed, style);
- DW2TB(html->dw)->addParbreak (5, style);
- style->unref ();
-
- S_TOP(html)->textblock = html->dw = page;
- /* right button press for menus for button contents */
- html->connectSignals(page);
-
- value = Html_get_attr_wdef(html, tag, tagsize, "value", NULL);
- name = Html_get_attr_wdef(html, tag, tagsize, "name", NULL);
-
- form->addInput(inp_type, embed, name, value, NULL, FALSE);
- dFree(name);
- dFree(value);
- }
- dFree(type);
-}
-
-/*
- * Handle close <BUTTON>
- */
-static void Html_tag_close_button(DilloHtml *html, int TagIdx)
-{
- html->InFlags &= ~IN_BUTTON;
- Html_pop_tag(html, TagIdx);
-}
-
-/*
* <FONT>
*/
static void Html_tag_open_font(DilloHtml *html, const char *tag, int tagsize)
@@ -2709,7 +2226,7 @@ static void Html_tag_open_font(DilloHtml *html, const char *tag, int tagsize)
old_style = S_TOP(html)->style;
style_attrs = *old_style;
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "color"))) {
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "color"))) {
if (prefs.contrast_visited_color && html->InVisitedLink) {
color = html->visited_color;
} else {
@@ -2721,7 +2238,7 @@ static void Html_tag_open_font(DilloHtml *html, const char *tag, int tagsize)
}
#if 0
- //if ((attrbuf = Html_get_attr(html, tag, tagsize, "face"))) {
+ //if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "face"))) {
// font = *( style_attrs.font );
// font.name = attrbuf;
// style_attrs.font = a_Dw_style_font_new_from_list (&font);
@@ -2742,7 +2259,7 @@ static void Html_tag_open_abbr(DilloHtml *html, const char *tag, int tagsize)
// DwTooltip *tooltip;
// const char *attrbuf;
//
-// if ((attrbuf = Html_get_attr(html, tag, tagsize, "title"))) {
+// if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "title"))) {
// tooltip = a_Dw_tooltip_new_no_ref(attrbuf);
// HTML_SET_TOP_ATTR(html, x_tooltip, tooltip);
// }
@@ -2819,9 +2336,10 @@ static void Html_tag_open_tt(DilloHtml *html, const char *tag, int tagsize)
* Read image-associated tag attributes,
* create new image and add it to the html page (if add is TRUE).
*/
-static DilloImage *Html_add_new_image(DilloHtml *html, const char *tag,
- int tagsize, DilloUrl *url,
- StyleAttrs *style_attrs, bool_t add)
+DilloImage *a_Html_add_new_image(DilloHtml *html, const char *tag,
+ int tagsize, DilloUrl *url,
+ dw::core::style::StyleAttrs *style_attrs,
+ bool_t add)
{
const int MAX_W = 6000, MAX_H = 6000;
@@ -2833,16 +2351,16 @@ static DilloImage *Html_add_new_image(DilloHtml *html, const char *tag,
bool load_now;
// if (prefs.show_tooltip &&
-// (attrbuf = Html_get_attr(html, tag, tagsize, "title")))
+// (attrbuf = a_Html_get_attr(html, tag, tagsize, "title")))
// style_attrs->x_tooltip = a_Dw_tooltip_new_no_ref(attrbuf);
- alt_ptr = Html_get_attr_wdef(html, tag, tagsize, "alt", NULL);
+ alt_ptr = a_Html_get_attr_wdef(html, tag, tagsize, "alt", NULL);
if (!prefs.load_images && (!alt_ptr || !*alt_ptr)) {
dFree(alt_ptr);
alt_ptr = dStrdup("[IMG]"); // Place holder for img_off mode
}
- width_ptr = Html_get_attr_wdef(html, tag, tagsize, "width", NULL);
- height_ptr = Html_get_attr_wdef(html, tag, tagsize, "height", NULL);
+ width_ptr = a_Html_get_attr_wdef(html, tag, tagsize, "width", NULL);
+ height_ptr = a_Html_get_attr_wdef(html, tag, tagsize, "height", NULL);
// Check for malicious values
// TODO: the same for percentage and relative lengths.
if (width_ptr) {
@@ -2857,7 +2375,7 @@ static DilloImage *Html_add_new_image(DilloHtml *html, const char *tag,
dFree(width_ptr);
dFree(height_ptr);
width_ptr = height_ptr = NULL;
- MSG("Html_add_new_image: suspicious image size request %dx%d\n", w, h);
+ MSG("a_Html_add_new_image: suspicious image size request %dx%d\n", w, h);
}
/* todo: we should scale the image respecting its ratio.
@@ -2868,14 +2386,14 @@ static DilloImage *Html_add_new_image(DilloHtml *html, const char *tag,
*/
/* Spacing to the left and right */
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "hspace"))) {
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "hspace"))) {
space = strtol(attrbuf, NULL, 10);
if (space > 0)
style_attrs->margin.left = style_attrs->margin.right = space;
}
/* Spacing at the top and bottom */
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "vspace"))) {
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "vspace"))) {
space = strtol(attrbuf, NULL, 10);
if (space > 0)
style_attrs->margin.top = style_attrs->margin.bottom = space;
@@ -2941,16 +2459,16 @@ static void Html_tag_open_img(DilloHtml *html, const char *tag, int tagsize)
if (URL_FLAGS(html->base_url) & URL_SpamSafe)
return;
- if (!(attrbuf = Html_get_attr(html, tag, tagsize, "src")) ||
- !(url = Html_url_new(html, attrbuf, NULL, 0, 0, 0, 0)))
+ if (!(attrbuf = a_Html_get_attr(html, tag, tagsize, "src")) ||
+ !(url = a_Html_url_new(html, attrbuf, NULL, 0, 0, 0, 0)))
return;
textblock = DW2TB(html->dw);
usemap_url = NULL;
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "usemap")))
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "usemap")))
/* todo: usemap URLs outside of the document are not used. */
- usemap_url = Html_url_new(html, attrbuf, NULL, 0, 0, 0, 0);
+ usemap_url = a_Html_url_new(html, attrbuf, NULL, 0, 0, 0, 0);
/* Set the style attributes for this image */
style_attrs = *S_TOP(html)->style;
@@ -2958,7 +2476,7 @@ static void Html_tag_open_img(DilloHtml *html, const char *tag, int tagsize)
usemap_url != NULL) {
/* Images within links */
border = 1;
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "border")))
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "border")))
border = strtol (attrbuf, NULL, 10);
if (S_TOP(html)->style->x_link != -1) {
@@ -2973,10 +2491,10 @@ static void Html_tag_open_img(DilloHtml *html, const char *tag, int tagsize)
style_attrs.borderWidth.setVal (border);
}
- Image = Html_add_new_image(html, tag, tagsize, url, &style_attrs, TRUE);
+ Image = a_Html_add_new_image(html, tag, tagsize, url, &style_attrs, TRUE);
/* Image maps */
- if (Html_get_attr(html, tag, tagsize, "ismap")) {
+ if (a_Html_get_attr(html, tag, tagsize, "ismap")) {
((::dw::Image*)Image->dw)->setIsMap();
_MSG(" Html_tag_open_img: server-side map (ISMAP)\n");
} else if (S_TOP(html)->style->x_link != -1 &&
@@ -3006,9 +2524,9 @@ static void Html_tag_open_map(DilloHtml *html, const char *tag, int tagsize)
if (html->InFlags & IN_MAP) {
BUG_MSG("nested <map>\n");
} else {
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "name"))) {
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "name"))) {
hash_name = dStrconcat("#", attrbuf, NULL);
- url = Html_url_new(html, hash_name, NULL, 0, 0, 0, 0);
+ url = a_Html_url_new(html, hash_name, NULL, 0, 0, 0, 0);
html->maps.startNewMap(new ::object::String(url->url_string->str));
a_Url_free (url);
dFree(hash_name);
@@ -3023,7 +2541,7 @@ static void Html_tag_open_map(DilloHtml *html, const char *tag, int tagsize)
static void Html_tag_close_map(DilloHtml *html, int TagIdx)
{
html->InFlags &= ~IN_MAP;
- Html_pop_tag(html, TagIdx);
+ a_Html_pop_tag(html, TagIdx);
}
/*
@@ -3074,7 +2592,7 @@ static void Html_tag_open_area(DilloHtml *html, const char *tag, int tagsize)
BUG_MSG("<area> element not inside <map>\n");
return;
}
- attrbuf = Html_get_attr(html, tag, tagsize, "shape");
+ attrbuf = a_Html_get_attr(html, tag, tagsize, "shape");
if (!attrbuf || !*attrbuf || !dStrcasecmp(attrbuf, "rect")) {
/* the default shape is a rectangle */
@@ -3092,7 +2610,7 @@ static void Html_tag_open_area(DilloHtml *html, const char *tag, int tagsize)
}
if (type == RECTANGLE || type == CIRCLE || type == POLYGON) {
/* todo: add support for coords in % */
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "coords"))) {
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "coords"))) {
coords = Html_read_coords(html, attrbuf);
if (type == RECTANGLE) {
@@ -3126,10 +2644,10 @@ static void Html_tag_open_area(DilloHtml *html, const char *tag, int tagsize)
}
}
if (shape != NULL || type == BACKGROUND) {
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "href"))) {
- url = Html_url_new(html, attrbuf, NULL, 0, 0, 0, 0);
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "href"))) {
+ url = a_Html_url_new(html, attrbuf, NULL, 0, 0, 0, 0);
dReturn_if_fail ( url != NULL );
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "alt")))
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "alt")))
a_Url_set_alt(url, attrbuf);
link = Html_set_new_link(html, &url);
@@ -3196,12 +2714,12 @@ static void Html_tag_open_a(DilloHtml *html, const char *tag, int tagsize)
if (html->InFlags & IN_MAP)
Html_tag_open_area(html, tag, tagsize);
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "href"))) {
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "href"))) {
/* if it's a javascript link, extract the reference. */
if (tolower(attrbuf[0]) == 'j')
attrbuf = Html_get_javascript_link(html);
- url = Html_url_new(html, attrbuf, NULL, 0, 0, 0, 0);
+ url = a_Html_url_new(html, attrbuf, NULL, 0, 0, 0, 0);
dReturn_if_fail ( url != NULL );
old_style = S_TOP(html)->style;
@@ -3224,7 +2742,7 @@ static void Html_tag_open_a(DilloHtml *html, const char *tag, int tagsize)
html->link_color);
}
-// if ((attrbuf = Html_get_attr(html, tag, tagsize, "title")))
+// if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "title")))
// style_attrs.x_tooltip = a_Dw_tooltip_new_no_ref(attrbuf);
style_attrs.textDecoration |= TEXT_DECORATION_UNDERLINE;
@@ -3236,7 +2754,7 @@ static void Html_tag_open_a(DilloHtml *html, const char *tag, int tagsize)
old_style->unref ();
}
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "name"))) {
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "name"))) {
if (prefs.show_extra_warnings)
Html_check_name_val(html, attrbuf, "name");
/* html->NameVal is freed in Html_process_tag */
@@ -3251,7 +2769,7 @@ static void Html_tag_open_a(DilloHtml *html, const char *tag, int tagsize)
static void Html_tag_close_a(DilloHtml *html, int TagIdx)
{
html->InVisitedLink = FALSE;
- Html_pop_tag(html, TagIdx);
+ a_Html_pop_tag(html, TagIdx);
}
/*
@@ -3307,7 +2825,7 @@ static void Html_tag_open_ul(DilloHtml *html, const char *tag, int tagsize)
DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
Html_add_indented(html, 40, 0, 9);
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "type"))) {
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "type"))) {
/* list_style_type explicitly defined */
if (dStrncasecmp(attrbuf, "disc", 4) == 0)
list_style_type = LIST_STYLE_TYPE_DISC;
@@ -3382,7 +2900,7 @@ static void Html_tag_open_ol(DilloHtml *html, const char *tag, int tagsize)
list_style_type = LIST_STYLE_TYPE_DECIMAL;
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "type"))) {
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "type"))) {
if (*attrbuf == '1')
list_style_type = LIST_STYLE_TYPE_DECIMAL;
else if (*attrbuf == 'a')
@@ -3398,7 +2916,7 @@ static void Html_tag_open_ol(DilloHtml *html, const char *tag, int tagsize)
HTML_SET_TOP_ATTR(html, listStyleType, list_style_type);
S_TOP(html)->list_type = HTML_LIST_ORDERED;
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "start")) &&
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "start")) &&
(n = (int) strtol(attrbuf, NULL, 10)) < 0) {
BUG_MSG( "illegal '-' character in START attribute; Starting from 0\n");
n = 0;
@@ -3449,7 +2967,7 @@ static void Html_tag_open_li(DilloHtml *html, const char *tag, int tagsize)
switch (S_TOP(html)->list_type) {
case HTML_LIST_ORDERED:
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "value")) &&
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "value")) &&
(*list_number = strtol(attrbuf, NULL, 10)) < 0) {
BUG_MSG("illegal negative LIST VALUE attribute; Starting from 0\n");
*list_number = 0;
@@ -3476,7 +2994,7 @@ static void Html_tag_close_li(DilloHtml *html, int TagIdx)
html->InFlags &= ~IN_LI;
html->WordAfterLI = FALSE;
((ListItem *)html->dw)->flush (false);
- Html_pop_tag(html, TagIdx);
+ a_Html_pop_tag(html, TagIdx);
}
/*
@@ -3493,14 +3011,14 @@ static void Html_tag_open_hr(DilloHtml *html, const char *tag, int tagsize)
style_attrs = *S_TOP(html)->style;
- width_ptr = Html_get_attr_wdef(html, tag, tagsize, "width", "100%");
+ width_ptr = a_Html_get_attr_wdef(html, tag, tagsize, "width", "100%");
style_attrs.width = Html_parse_length (html, width_ptr);
dFree(width_ptr);
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "size")))
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "size")))
size = strtol(attrbuf, NULL, 10);
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "align"))) {
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "align"))) {
if (dStrcasecmp (attrbuf, "left") == 0)
style_attrs.textAlign = TEXT_ALIGN_LEFT;
else if (dStrcasecmp (attrbuf, "right") == 0)
@@ -3510,7 +3028,7 @@ static void Html_tag_open_hr(DilloHtml *html, const char *tag, int tagsize)
}
/* todo: evaluate attribute */
- if (Html_get_attr(html, tag, tagsize, "noshade")) {
+ if (a_Html_get_attr(html, tag, tagsize, "noshade")) {
style_attrs.setBorderStyle (BORDER_SOLID);
style_attrs.setBorderColor (
Color::createShaded (HT2LT(html), style_attrs.color->getColor()));
@@ -3589,7 +3107,7 @@ static void Html_tag_close_pre(DilloHtml *html, int TagIdx)
{
html->InFlags &= ~IN_PRE;
DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
- Html_pop_tag(html, TagIdx);
+ a_Html_pop_tag(html, TagIdx);
}
/*
@@ -3614,114 +3132,6 @@ static int Html_tag_pre_excludes(int tag_idx)
}
/*
- * Handle <FORM> tag
- */
-static void Html_tag_open_form(DilloHtml *html, const char *tag, int tagsize)
-{
- DilloUrl *action;
- DilloHtmlMethod method;
- DilloHtmlEnc enc;
- char *charset, *first;
- const char *attrbuf;
-
- DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
-
- if (html->InFlags & IN_FORM) {
- BUG_MSG("nested forms\n");
- return;
- }
- html->InFlags |= IN_FORM;
- html->InFlags &= ~IN_SELECT;
- html->InFlags &= ~IN_OPTION;
- html->InFlags &= ~IN_TEXTAREA;
-
- method = DILLO_HTML_METHOD_GET;
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "method"))) {
- if (!dStrcasecmp(attrbuf, "post"))
- method = DILLO_HTML_METHOD_POST;
- /* todo: maybe deal with unknown methods? */
- }
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "action")))
- action = Html_url_new(html, attrbuf, NULL, 0, 0, 0, 0);
- else
- action = a_Url_dup(html->base_url);
- enc = DILLO_HTML_ENC_URLENCODING;
- if ((method == DILLO_HTML_METHOD_POST) &&
- ((attrbuf = Html_get_attr(html, tag, tagsize, "enctype")))) {
- if (!dStrcasecmp(attrbuf, "multipart/form-data"))
- enc = DILLO_HTML_ENC_MULTIPART;
- }
- charset = NULL;
- first = NULL;
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "accept-charset"))) {
- /* a list of acceptable charsets, separated by commas or spaces */
- char *ptr = first = dStrdup(attrbuf);
- while (ptr && !charset) {
- char *curr = dStrsep(&ptr, " ,");
- if (!dStrcasecmp(curr, "utf-8")) {
- charset = curr;
- } else if (!dStrcasecmp(curr, "UNKNOWN")) {
- /* defined to be whatever encoding the document is in */
- charset = html->charset;
- }
- }
- if (!charset)
- charset = first;
- }
- if (!charset)
- charset = html->charset;
- html->formNew(method, action, enc, charset);
- dFree(first);
- a_Url_free(action);
-}
-
-static void Html_tag_close_form(DilloHtml *html, int TagIdx)
-{
- static const char *SubmitTag =
- "<input type='submit' value='?Submit?' alt='dillo-generated-button'>";
- DilloHtmlForm *form;
-// int i;
-
- if (html->InFlags & IN_FORM) {
- form = html->getCurrentForm ();
- /* If we don't have a submit button and the user desires one,
- let's add a custom one */
- if (form->num_submit_buttons == 0) {
- if (prefs.show_extra_warnings || form->num_entry_fields != 1)
- BUG_MSG("FORM lacks a Submit button\n");
- if (prefs.generate_submit) {
- BUG_MSG(" (added a submit button internally)\n");
- Html_tag_open_input(html, SubmitTag, strlen(SubmitTag));
- form->num_submit_buttons = 0;
- }
- }
-
-// /* Make buttons sensitive again */
-// for (i = 0; i < form->inputs->size(); i++) {
-// input_i = form->inputs->get(i);
-// /* Check for tricky HTML (e.g. <input type=image>) */
-// if (!input_i->widget)
-// continue;
-// if (input_i->type == DILLO_HTML_INPUT_SUBMIT ||
-// input_i->type == DILLO_HTML_INPUT_RESET) {
-// gtk_widget_set_sensitive(input_i->widget, TRUE);
-// } else if (input_i->type == DILLO_HTML_INPUT_IMAGE ||
-// input_i->type == DILLO_HTML_INPUT_BUTTON_SUBMIT ||
-// input_i->type == DILLO_HTML_INPUT_BUTTON_RESET) {
-// a_Dw_button_set_sensitive(DW_BUTTON(input_i->widget), TRUE);
-// }
-// }
- }
-
- html->InFlags &= ~IN_FORM;
- html->InFlags &= ~IN_SELECT;
- html->InFlags &= ~IN_OPTION;
- html->InFlags &= ~IN_TEXTAREA;
-
- Html_pop_tag(html, TagIdx);
-}
-
-/*
* Handle <META>
* We do not support http-equiv=refresh because it's non standard,
* (the HTML 4.01 SPEC recommends explicitly to avoid it), and it
@@ -3755,9 +3165,9 @@ static void Html_tag_open_meta(DilloHtml *html, const char *tag, int tagsize)
return;
}
- if ((equiv = Html_get_attr(html, tag, tagsize, "http-equiv"))) {
+ if ((equiv = a_Html_get_attr(html, tag, tagsize, "http-equiv"))) {
if (!dStrcasecmp(equiv, "refresh") &&
- (content = Html_get_attr(html, tag, tagsize, "content"))) {
+ (content = a_Html_get_attr(html, tag, tagsize, "content"))) {
/* Get delay, if present, and make a message with it */
if ((delay = strtol(content, NULL, 0)))
@@ -3785,7 +3195,7 @@ static void Html_tag_open_meta(DilloHtml *html, const char *tag, int tagsize)
dStr_free(ds_msg, 1);
} else if (!dStrcasecmp(equiv, "content-type") &&
- (content = Html_get_attr(html, tag, tagsize, "content"))) {
+ (content = a_Html_get_attr(html, tag, tagsize, "content"))) {
if (a_Misc_content_type_cmp(html->content_type, content)) {
const bool_t force = FALSE;
const char *new_content =
@@ -3819,1145 +3229,6 @@ static void Html_tag_open_meta(DilloHtml *html, const char *tag, int tagsize)
/*
- * Pass input text through character set encoder.
- * Return value: same input Dstr if no encoding is needed.
- new Dstr when encoding (input Dstr is freed).
- */
-static Dstr *Html_encode_text(iconv_t encoder, Dstr **input)
-{
- int rc = 0;
- Dstr *output;
- const int bufsize = 128;
- inbuf_t *inPtr;
- char *buffer, *outPtr;
- size_t inLeft, outRoom;
- bool bad_chars = false;
-
- if ((encoder == (iconv_t) -1) || *input == NULL || (*input)->len == 0)
- return *input;
-
- output = dStr_new("");
- inPtr = (*input)->str;
- inLeft = (*input)->len;
- buffer = dNew(char, bufsize);
-
- while ((rc != EINVAL) && (inLeft > 0)) {
-
- outPtr = buffer;
- outRoom = bufsize;
-
- rc = iconv(encoder, &inPtr, &inLeft, &outPtr, &outRoom);
-
- // iconv() on success, number of bytes converted
- // -1, errno == EILSEQ illegal byte sequence found
- // EINVAL partial character ends source buffer
- // E2BIG destination buffer is full
- //
- // GNU iconv has the undocumented(!) behavior that EILSEQ is also
- // returned when a character cannot be converted.
-
- dStr_append_l(output, buffer, bufsize - outRoom);
-
- if (rc == -1) {
- rc = errno;
- }
- if (rc == EILSEQ){
- /* count chars? (would be utf-8-specific) */
- bad_chars = true;
- inPtr++;
- inLeft--;
- dStr_append_c(output, '?');
- } else if (rc == EINVAL) {
- MSG_ERR("Html_decode_text: bad source string\n");
- }
- }
-
- if (bad_chars) {
- /*
- * It might be friendly to inform the caller, who would know whether
- * it is safe to display the beginning of the string in a message
- * (isn't, e.g., a password).
- */
- MSG_WARN("String cannot be converted cleanly.\n");
- }
-
- dFree(buffer);
- dStr_free(*input, 1);
-
- return output;
-}
-
-/*
- * Urlencode 'val' and append it to 'str'
- */
-static void Html_urlencode_append(Dstr *str, const char *val)
-{
- char *enc_val = a_Url_encode_hex_str(val);
- dStr_append(str, enc_val);
- dFree(enc_val);
-}
-
-/*
- * Append a name-value pair to url data using url encoding.
- */
-static void Html_append_input_urlencode(Dstr *data, const char *name,
- const char *value)
-{
- if (name && name[0]) {
- Html_urlencode_append(data, name);
- dStr_append_c(data, '=');
- Html_urlencode_append(data, value);
- dStr_append_c(data, '&');
- }
-}
-
-/*
- * Append files to URL data using multipart encoding.
- * Currently only accepts one file.
- */
-static void Html_append_input_multipart_files(Dstr* data, const char *boundary,
- const char *name, Dstr *file,
- const char *filename)
-{
- const char *ctype, *ext;
-
- if (name && name[0]) {
- (void)a_Misc_get_content_type_from_data(file->str, file->len, &ctype);
- /* Heuristic: text/plain with ".htm[l]" extension -> text/html */
- if ((ext = strrchr(filename, '.')) &&
- !dStrcasecmp(ctype, "text/plain") &&
- (!dStrcasecmp(ext, ".html") || !dStrcasecmp(ext, ".htm"))) {
- ctype = "text/html";
- }
-
- if (data->len == 0) {
- dStr_append(data, "--");
- dStr_append(data, boundary);
- }
- // todo: encode name, filename
- dStr_sprintfa(data,
- "\r\n"
- "Content-Disposition: form-data; name=\"%s\"; "
- "filename=\"%s\"\r\n"
- "Content-Type: %s\r\n"
- "\r\n", name, filename, ctype);
-
- dStr_append_l(data, file->str, file->len);
-
- dStr_sprintfa(data,
- "\r\n"
- "--%s", boundary);
- }
-}
-
-/*
- * Append a name-value pair to url data using multipart encoding.
- */
-static void Html_append_input_multipart(Dstr *data, const char *boundary,
- const char *name, const char *value)
-{
- if (name && name[0]) {
- if (data->len == 0) {
- dStr_append(data, "--");
- dStr_append(data, boundary);
- }
- // todo: encode name (RFC 2231) [coming soon]
- dStr_sprintfa(data,
- "\r\n"
- "Content-Disposition: form-data; name=\"%s\"\r\n"
- "\r\n"
- "%s\r\n"
- "--%s",
- name, value, boundary);
- }
-}
-
-/*
- * Append an image button click position to url data using url encoding.
- */
-static void Html_append_clickpos_urlencode(Dstr *data, Dstr *name, int x,int y)
-{
- if (name->len) {
- Html_urlencode_append(data, name->str);
- dStr_sprintfa(data, ".x=%d&", x);
- Html_urlencode_append(data, name->str);
- dStr_sprintfa(data, ".y=%d&", y);
- } else
- dStr_sprintfa(data, "x=%d&y=%d&", x, y);
-}
-
-/*
- * Append an image button click position to url data using multipart encoding.
- */
-static void Html_append_clickpos_multipart(Dstr *data, const char *boundary,
- Dstr *name, int x, int y)
-{
- char posstr[16];
- int orig_len = name->len;
-
- if (orig_len)
- dStr_append_c(name, '.');
- dStr_append_c(name, 'x');
-
- snprintf(posstr, 16, "%d", x);
- Html_append_input_multipart(data, boundary, name->str, posstr);
- dStr_truncate(name, name->len - 1);
- dStr_append_c(name, 'y');
- snprintf(posstr, 16, "%d", y);
- Html_append_input_multipart(data, boundary, name->str, posstr);
- dStr_truncate(name, orig_len);
-}
-
-/*
- * Get the values for a "successful control".
- */
-static void Html_get_input_values(const DilloHtmlInput *input,
- bool is_active_submit, Dlist *values)
-{
- switch (input->type) {
- case DILLO_HTML_INPUT_TEXT:
- case DILLO_HTML_INPUT_PASSWORD:
- case DILLO_HTML_INPUT_INDEX:
- EntryResource *entryres;
- entryres = (EntryResource*)input->embed->getResource();
- dList_append(values, dStr_new(entryres->getText()));
- break;
- case DILLO_HTML_INPUT_TEXTAREA:
- MultiLineTextResource *textres;
- textres = (MultiLineTextResource*)input->embed->getResource();
- dList_append(values, dStr_new(textres->getText()));
- break;
- case DILLO_HTML_INPUT_CHECKBOX:
- case DILLO_HTML_INPUT_RADIO:
- ToggleButtonResource *cb_r;
- cb_r = (ToggleButtonResource*)input->embed->getResource();
- if (input->name && input->init_str && cb_r->isActivated()) {
- dList_append(values, dStr_new(input->init_str));
- }
- break;
- case DILLO_HTML_INPUT_SUBMIT:
- case DILLO_HTML_INPUT_BUTTON_SUBMIT:
- if (is_active_submit)
- dList_append(values, dStr_new(input->init_str));
- break;
- case DILLO_HTML_INPUT_HIDDEN:
- dList_append(values, dStr_new(input->init_str));
- break;
- case DILLO_HTML_INPUT_SELECT:
- case DILLO_HTML_INPUT_SEL_LIST:
- { // brackets for compiler happiness.
- SelectionResource *sel_res =
- (SelectionResource*)input->embed->getResource();
- int size = input->select->options->size ();
- for (int i = 0; i < size; i++) {
- if (sel_res->isSelected(i)) {
- DilloHtmlOption *option = input->select->options->get(i);
- char *val = option->value ? option->value : option->content;
- dList_append(values, dStr_new(val));
- }
- }
- break;
- }
- case DILLO_HTML_INPUT_IMAGE:
- if (is_active_submit) {
- dList_append(values, dStr_new(input->init_str));
- }
- break;
- case DILLO_HTML_INPUT_FILE:
- { LabelButtonResource *lbr =
- (LabelButtonResource*)input->embed->getResource();
- const char *filename = lbr->getLabel();
- if (filename[0] && strcmp(filename, input->init_str)) {
- if (input->file_data) {
- Dstr *file = dStr_sized_new(input->file_data->len);
- dStr_append_l(file, input->file_data->str, input->file_data->len);
- dList_append(values, file);
- } else {
- MSG("FORM file input \"%s\" not loaded.\n", filename);
- }
- }
- break;
- }
- default:
- break;
- }
-}
-
-/*
- * Generate a boundary string for use in separating the parts of a
- * multipart/form-data submission.
- */
-char *DilloHtmlForm::makeMultipartBoundary(iconv_t encoder,
- DilloHtmlInput *active_submit)
-{
- const int max_tries = 10;
- Dlist *values = dList_new(5);
- Dstr *DataStr = dStr_new("");
- Dstr *boundary = dStr_new("");
- char *ret = NULL;
-
- /* fill DataStr with names, filenames, and values */
- for (int input_idx = 0; input_idx < inputs->size(); input_idx++) {
- Dstr *dstr;
- DilloHtmlInput *input = inputs->get (input_idx);
- bool is_active_submit = (input == active_submit);
- Html_get_input_values(input, is_active_submit, values);
-
- if (input->name) {
- dstr = dStr_new(input->name);
- dstr = Html_encode_text(encoder, &dstr);
- dStr_append_l(DataStr, dstr->str, dstr->len);
- dStr_free(dstr, 1);
- }
- if (input->type == DILLO_HTML_INPUT_FILE) {
- LabelButtonResource *lbr =
- (LabelButtonResource*)input->embed->getResource();
- const char *filename = lbr->getLabel();
- if (filename[0] && strcmp(filename, input->init_str)) {
- dstr = dStr_new(filename);
- dstr = Html_encode_text(encoder, &dstr);
- dStr_append_l(DataStr, dstr->str, dstr->len);
- dStr_free(dstr, 1);
- }
- }
- int length = dList_length(values);
- for (int i = 0; i < length; i++) {
- dstr = (Dstr *) dList_nth_data(values, 0);
- dList_remove(values, dstr);
- if (input->type != DILLO_HTML_INPUT_FILE)
- dstr = Html_encode_text(encoder, &dstr);
- dStr_append_l(DataStr, dstr->str, dstr->len);
- dStr_free(dstr, 1);
- }
- }
-
- /* generate a boundary that is not contained within the data */
- for (int i = 0; i < max_tries && !ret; i++) {
- // Firefox-style boundary
- dStr_sprintf(boundary, "---------------------------%d%d%d",
- rand(), rand(), rand());
- dStr_truncate(boundary, 70);
- if (dStr_memmem(DataStr, boundary) == NULL)
- ret = boundary->str;
- }
- dList_free(values);
- dStr_free(DataStr, 1);
- dStr_free(boundary, (ret == NULL));
- return ret;
-}
-
-/*
- * Construct the data for a query URL
- */
-Dstr *DilloHtmlForm::buildQueryData(DilloHtmlInput *active_submit,
- int x, int y)
-{
- Dstr *DataStr = NULL;
- char *boundary = NULL;
- iconv_t encoder = (iconv_t) -1;
-
- if (submit_charset && dStrcasecmp(submit_charset, "UTF-8")) {
- encoder = iconv_open(submit_charset, "UTF-8");
- if (encoder == (iconv_t) -1) {
- MSG_WARN("Cannot convert to character encoding '%s'\n",
- submit_charset);
- } else {
- MSG("Form character encoding: '%s'\n", submit_charset);
- }
- }
-
- if (enc == DILLO_HTML_ENC_MULTIPART) {
- if (!(boundary = makeMultipartBoundary(encoder, active_submit)))
- MSG_ERR("Cannot generate multipart/form-data boundary.\n");
- }
-
- if ((enc == DILLO_HTML_ENC_URLENCODING) || (boundary != NULL)) {
- Dlist *values = dList_new(5);
-
- DataStr = dStr_sized_new(4096);
- for (int input_idx = 0; input_idx < inputs->size(); input_idx++) {
- DilloHtmlInput *input = inputs->get (input_idx);
- Dstr *name = dStr_new(input->name);
- bool is_active_submit = (input == active_submit);
-
- name = Html_encode_text(encoder, &name);
- Html_get_input_values(input, is_active_submit, values);
-
- if (input->type == DILLO_HTML_INPUT_FILE &&
- dList_length(values) > 0) {
- if (dList_length(values) > 1)
- MSG_WARN("multiple files per form control not supported\n");
- Dstr *file = (Dstr *) dList_nth_data(values, 0);
- dList_remove(values, file);
-
- /* Get filename and encode it. Do not encode file contents. */
- LabelButtonResource *lbr =
- (LabelButtonResource*)input->embed->getResource();
- const char *filename = lbr->getLabel();
- if (filename[0] && strcmp(filename, input->init_str)) {
- char *p = strrchr(filename, '/');
- if (p)
- filename = p + 1; /* don't reveal path */
- Dstr *dfilename = dStr_new(filename);
- dfilename = Html_encode_text(encoder, &dfilename);
- Html_append_input_multipart_files(DataStr, boundary,
- name->str, file, dfilename->str);
- dStr_free(dfilename, 1);
- }
- dStr_free(file, 1);
- } else if (input->type == DILLO_HTML_INPUT_INDEX) {
- Dstr *val = (Dstr *) dList_nth_data(values, 0);
- dList_remove(values, val);
- val = Html_encode_text(encoder, &val);
- Html_urlencode_append(DataStr, val->str);
- dStr_free(val, 1);
- } else {
- int length = dList_length(values), i;
- for (i = 0; i < length; i++) {
- Dstr *val = (Dstr *) dList_nth_data(values, 0);
- dList_remove(values, val);
- val = Html_encode_text(encoder, &val);
- if (enc == DILLO_HTML_ENC_URLENCODING)
- Html_append_input_urlencode(DataStr, name->str, val->str);
- else if (enc == DILLO_HTML_ENC_MULTIPART)
- Html_append_input_multipart(DataStr, boundary, name->str,
- val->str);
- dStr_free(val, 1);
- }
- if (i && input->type == DILLO_HTML_INPUT_IMAGE) {
- /* clickpos to accompany the value just appended */
- if (enc == DILLO_HTML_ENC_URLENCODING)
- Html_append_clickpos_urlencode(DataStr, name, x, y);
- else if (enc == DILLO_HTML_ENC_MULTIPART)
- Html_append_clickpos_multipart(DataStr, boundary, name, x,y);
- }
- }
- dStr_free(name, 1);
- }
- if (DataStr->len > 0) {
- if (enc == DILLO_HTML_ENC_URLENCODING) {
- if (DataStr->str[DataStr->len - 1] == '&')
- dStr_truncate(DataStr, DataStr->len - 1);
- } else if (enc == DILLO_HTML_ENC_MULTIPART) {
- dStr_append(DataStr, "--");
- }
- }
- dList_free(values);
- }
- dFree(boundary);
- if (encoder != (iconv_t) -1)
- (void)iconv_close(encoder);
- return DataStr;
-}
-
-/*
- * Build a new query URL.
- * (Called by a_Html_form_event_handler())
- * click_x and click_y are used only by input images.
- */
-DilloUrl *DilloHtmlForm::buildQueryUrl(DilloHtmlInput *input,
- int click_x, int click_y)
-{
- DilloUrl *new_url = NULL;
-
- if ((method == DILLO_HTML_METHOD_GET) ||
- (method == DILLO_HTML_METHOD_POST)) {
- Dstr *DataStr;
- DilloHtmlInput *active_submit = NULL;
-
- _MSG("DilloHtmlForm::buildQueryUrl: action=%s\n",URL_STR_(action));
-
- if (num_submit_buttons > 0) {
- if ((input->type == DILLO_HTML_INPUT_SUBMIT) ||
- (input->type == DILLO_HTML_INPUT_IMAGE) ||
- (input->type == DILLO_HTML_INPUT_BUTTON_SUBMIT)) {
- active_submit = input;
- }
- }
-
- DataStr = buildQueryData(active_submit, click_x, click_y);
- if (DataStr) {
- /* action was previously resolved against base URL */
- char *action_str = dStrdup(URL_STR(action));
-
- if (method == DILLO_HTML_METHOD_POST) {
- new_url = a_Url_new(action_str, NULL, 0, 0, 0);
- /* new_url keeps the dStr and sets DataStr to NULL */
- a_Url_set_data(new_url, &DataStr);
- a_Url_set_flags(new_url, URL_FLAGS(new_url) | URL_Post);
- if (enc == DILLO_HTML_ENC_MULTIPART)
- a_Url_set_flags(new_url, URL_FLAGS(new_url) | URL_MultipartEnc);
- } else {
- /* remove <fragment> and <query> sections if present */
- char *url_str, *p;
- if ((p = strchr(action_str, '#')))
- *p = 0;
- if ((p = strchr(action_str, '?')))
- *p = 0;
-
- url_str = dStrconcat(action_str, "?", DataStr->str, NULL);
- new_url = a_Url_new(url_str, NULL, 0, 0, 0);
- a_Url_set_flags(new_url, URL_FLAGS(new_url) | URL_Get);
- dFree(url_str);
- }
- dStr_free(DataStr, 1);
- dFree(action_str);
- }
- } else {
- MSG("DilloHtmlForm::buildQueryUrl: Method unknown\n");
- }
-
- return new_url;
-}
-
-/*
- * Handlers for events related to forms.
- *
- * TODO: Currently there's "clicked" for buttons, we surely need "enter" for
- * textentries, and maybe the "mouseover, ...." set for Javascript.
- */
-
-void DilloHtmlReceiver::activate (Resource *resource)
-{
- form->eventHandler(resource, -1, -1);
-}
-
-void DilloHtmlReceiver::clicked (ButtonResource *resource,
- int buttonNo, int x, int y)
-{
- form->eventHandler(resource, x, y);
-}
-
-void DilloHtmlForm::eventHandler(Resource *resource, int click_x, int click_y)
-{
- MSG("DilloHtmlForm::eventHandler\n");
-
- DilloHtmlInput *input = getInput(resource);
- BrowserWindow *bw = html->bw;
-
- if (!input) {
- MSG("DilloHtmlForm::eventHandler: ERROR, input not found!\n");
- } else if (num_entry_fields > 1 &&
- !prefs.enterpress_forces_submit &&
- (input->type == DILLO_HTML_INPUT_TEXT ||
- input->type == DILLO_HTML_INPUT_PASSWORD)) {
- /* do nothing */
- } else if (input->type == DILLO_HTML_INPUT_FILE) {
- /* read the file into cache */
- const char *filename = a_UIcmd_select_file();
- if (filename) {
- LabelButtonResource *lbr =
- (LabelButtonResource*)input->embed->getResource();
- a_UIcmd_set_msg(bw, "Loading file...");
- dStr_free(input->file_data, 1);
- input->file_data = a_Misc_file2dstr(filename);
- if (input->file_data) {
- a_UIcmd_set_msg(bw, "File loaded.");
- lbr->setLabel(filename);
- } else {
- a_UIcmd_set_msg(bw, "ERROR: can't load: %s", filename);
- }
- }
- } else if (input->type == DILLO_HTML_INPUT_RESET ||
- input->type == DILLO_HTML_INPUT_BUTTON_RESET) {
- reset();
- } else {
- DilloUrl *url = buildQueryUrl(input, click_x, click_y);
- if (url) {
- a_Nav_push(bw, url);
- a_Url_free(url);
- }
- // /* now, make the rendered area have its focus back */
- // gtk_widget_grab_focus(GTK_BIN(bw->render_main_scroll)->child);
- }
-}
-
-/*
- * Return the input with a given resource.
- */
-DilloHtmlInput *DilloHtmlForm::getInput (Resource *resource)
-{
- for (int idx = 0; idx < inputs->size(); idx++) {
- DilloHtmlInput *input = inputs->get(idx);
- if (input->embed &&
- resource == input->embed->getResource())
- return input;
- }
- return NULL;
-}
-
-/*
- * Create input image for the form
- */
-static Embed *Html_input_image(DilloHtml *html, const char *tag, int tagsize,
- DilloHtmlForm *form)
-{
- const char *attrbuf;
- StyleAttrs style_attrs;
- DilloImage *Image;
- Embed *button = NULL;
- DilloUrl *url = NULL;
-
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "src")) &&
- (url = Html_url_new(html, attrbuf, NULL, 0, 0, 0, 0))) {
- style_attrs = *S_TOP(html)->style;
- style_attrs.cursor = CURSOR_POINTER;
-
- /* create new image and add it to the button */
- if ((Image = Html_add_new_image(html, tag, tagsize, url, &style_attrs,
- FALSE))) {
- Style *style = Style::create (HT2LT(html), &style_attrs);
- IM2DW(Image)->setStyle (style);
- ComplexButtonResource *complex_b_r =
- HT2LT(html)->getResourceFactory()->createComplexButtonResource(
- IM2DW(Image), false);
- button = new Embed(complex_b_r);
- DW2TB(html->dw)->addWidget (button, style);
-// gtk_widget_set_sensitive(widget, FALSE); /* Until end of FORM! */
- style->unref();
-
- /* a right button press brings up the image menu */
- html->connectSignals((Widget*)Image->dw);
- } else {
- a_Url_free(url);
- }
- }
-
- if (!button)
- DEBUG_MSG(10, "Html_input_image: unable to create image submit.\n");
- return button;
-}
-
-/*
- * Add a new input to current form
- */
-static void Html_tag_open_input(DilloHtml *html, const char *tag, int tagsize)
-{
- DilloHtmlForm *form;
- DilloHtmlInputType inp_type;
- Embed *embed = NULL;
- char *value, *name, *type, *init_str;
- const char *attrbuf, *label;
- bool_t init_val = FALSE;
-
- if (!(html->InFlags & IN_FORM)) {
- BUG_MSG("<input> element outside <form>\n");
- return;
- }
- if (html->InFlags & IN_SELECT) {
- BUG_MSG("<input> element inside <select>\n");
- return;
- }
- if (html->InFlags & IN_BUTTON) {
- BUG_MSG("<input> element inside <button>\n");
- return;
- }
-
- form = html->getCurrentForm ();
-
- /* Get 'value', 'name' and 'type' */
- value = Html_get_attr_wdef(html, tag, tagsize, "value", NULL);
- name = Html_get_attr_wdef(html, tag, tagsize, "name", NULL);
- type = Html_get_attr_wdef(html, tag, tagsize, "type", "");
-
- init_str = NULL;
- inp_type = DILLO_HTML_INPUT_UNKNOWN;
- if (!dStrcasecmp(type, "password")) {
- inp_type = DILLO_HTML_INPUT_PASSWORD;
- EntryResource *entryResource =
- HT2LT(html)->getResourceFactory()->createEntryResource (10, true);
- embed = new Embed (entryResource);
- init_str = (value) ? value : NULL;
- } else if (!dStrcasecmp(type, "checkbox")) {
- inp_type = DILLO_HTML_INPUT_CHECKBOX;
- CheckButtonResource *check_b_r = HT2LT(html)->getResourceFactory()
- ->createCheckButtonResource(false);
- embed = new Embed (check_b_r);
- init_val = (Html_get_attr(html, tag, tagsize, "checked") != NULL);
- init_str = (value) ? value : dStrdup("on");
- } else if (!dStrcasecmp(type, "radio")) {
- inp_type = DILLO_HTML_INPUT_RADIO;
- RadioButtonResource *rb_r = NULL;
- DilloHtmlInput *input = form->getRadioInput(name);
- if (input)
- rb_r = (RadioButtonResource*)input->embed->getResource();
- rb_r = HT2LT(html)->getResourceFactory()
- ->createRadioButtonResource(rb_r, false);
- embed = new Embed (rb_r);
- init_val = (Html_get_attr(html, tag, tagsize, "checked") != NULL);
- init_str = (value) ? value : NULL;
- } else if (!dStrcasecmp(type, "hidden")) {
- inp_type = DILLO_HTML_INPUT_HIDDEN;
- if (value)
- init_str = dStrdup(Html_get_attr(html, tag, tagsize, "value"));
- } else if (!dStrcasecmp(type, "submit")) {
- inp_type = DILLO_HTML_INPUT_SUBMIT;
- init_str = (value) ? value : dStrdup("submit");
- LabelButtonResource *label_b_r = HT2LT(html)->getResourceFactory()
- ->createLabelButtonResource(init_str);
- embed = new Embed (label_b_r);
-// gtk_widget_set_sensitive(widget, FALSE); /* Until end of FORM! */
- } else if (!dStrcasecmp(type, "reset")) {
- inp_type = DILLO_HTML_INPUT_RESET;
- init_str = (value) ? value : dStrdup("Reset");
- LabelButtonResource *label_b_r = HT2LT(html)->getResourceFactory()
- ->createLabelButtonResource(init_str);
- embed = new Embed (label_b_r);
-// gtk_widget_set_sensitive(widget, FALSE); /* Until end of FORM! */
- } else if (!dStrcasecmp(type, "image")) {
- if (URL_FLAGS(html->base_url) & URL_SpamSafe) {
- /* Don't request the image; make a text submit button instead */
- inp_type = DILLO_HTML_INPUT_SUBMIT;
- attrbuf = Html_get_attr(html, tag, tagsize, "alt");
- label = attrbuf ? attrbuf : value ? value : name ? name : "Submit";
- init_str = dStrdup(label);
- LabelButtonResource *label_b_r = HT2LT(html)->getResourceFactory()
- ->createLabelButtonResource(init_str);
- embed = new Embed (label_b_r);
-// gtk_widget_set_sensitive(widget, FALSE); /* Until end of FORM! */
- } else {
- inp_type = DILLO_HTML_INPUT_IMAGE;
- /* use a dw_image widget */
- embed = Html_input_image(html, tag, tagsize, form);
- init_str = value;
- }
- } else if (!dStrcasecmp(type, "file")) {
- if (form->method != DILLO_HTML_METHOD_POST) {
- BUG_MSG("Forms with file input MUST use HTTP POST method\n");
- MSG("File input ignored in form not using HTTP POST method\n");
- } else if (form->enc != DILLO_HTML_ENC_MULTIPART) {
- BUG_MSG("Forms with file input MUST use multipart/form-data"
- " encoding\n");
- MSG("File input ignored in form not using multipart/form-data"
- " encoding\n");
- } else {
- inp_type = DILLO_HTML_INPUT_FILE;
- init_str = dStrdup("File selector");
- LabelButtonResource *lbr =
- HT2LT(html)->getResourceFactory()->
- createLabelButtonResource(init_str);
- embed = new Embed (lbr);
- }
- } else if (!dStrcasecmp(type, "button")) {
- inp_type = DILLO_HTML_INPUT_BUTTON;
- if (value) {
- init_str = value;
- LabelButtonResource *label_b_r = HT2LT(html)->getResourceFactory()
- ->createLabelButtonResource(init_str);
- embed = new Embed (label_b_r);
- }
- } else if (!dStrcasecmp(type, "text") || !*type) {
- /* Text input, which also is the default */
- inp_type = DILLO_HTML_INPUT_TEXT;
- EntryResource *entryResource =
- HT2LT(html)->getResourceFactory()->createEntryResource (10, false);
- embed = new Embed (entryResource);
- init_str = (value) ? value : NULL;
- } else {
- /* Unknown input type */
- BUG_MSG("Unknown input type: \"%s\"\n", type);
- }
-
- if (inp_type != DILLO_HTML_INPUT_UNKNOWN) {
- form->addInput(inp_type, embed, name,
- (init_str) ? init_str : "", NULL, init_val);
- }
-
- if (embed != NULL && inp_type != DILLO_HTML_INPUT_IMAGE &&
- inp_type != DILLO_HTML_INPUT_UNKNOWN) {
- if (inp_type == DILLO_HTML_INPUT_TEXT ||
- inp_type == DILLO_HTML_INPUT_PASSWORD) {
- EntryResource *entryres = (EntryResource*)embed->getResource();
- /* Readonly or not? */
- if (Html_get_attr(html, tag, tagsize, "readonly"))
- entryres->setEditable(false);
-
-// /* Set width of the entry */
-// if ((attrbuf = Html_get_attr(html, tag, tagsize, "size")))
-// gtk_widget_set_usize(widget, (strtol(attrbuf, NULL, 10) + 1) *
-// gdk_char_width(widget->style->font, '0'), 0);
-//
-// /* Maximum length of the text in the entry */
-// if ((attrbuf = Html_get_attr(html, tag, tagsize, "maxlength")))
-// gtk_entry_set_max_length(GTK_ENTRY(widget),
-// strtol(attrbuf, NULL, 10));
- }
-
- if (prefs.standard_widget_colors) {
- HTML_SET_TOP_ATTR(html, color, NULL);
- HTML_SET_TOP_ATTR(html, backgroundColor, NULL);
- }
- DW2TB(html->dw)->addWidget (embed, S_TOP(html)->style);
- }
-
- dFree(type);
- dFree(name);
- if (init_str != value)
- dFree(init_str);
- dFree(value);
-}
-
-/*
- * Return a Radio input for the given name.
- */
-DilloHtmlInput *DilloHtmlForm::getRadioInput (const char *name)
-{
- for (int idx = 0; idx < inputs->size(); idx++) {
- DilloHtmlInput *input = inputs->get(idx);
- if (input->type == DILLO_HTML_INPUT_RADIO &&
- input->name && !dStrcasecmp(input->name, name))
- return input;
- }
- return NULL;
-}
-
-/*
- * The ISINDEX tag is just a deprecated form of <INPUT type=text> with
- * implied FORM, afaics.
- */
-static void Html_tag_open_isindex(DilloHtml *html,
- const char *tag, int tagsize)
-{
- DilloHtmlForm *form;
- DilloUrl *action;
- Embed *embed;
- const char *attrbuf;
-
- if (html->InFlags & IN_FORM) {
- MSG("<isindex> inside <form> not handled.\n");
- return;
- }
-
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "action")))
- action = Html_url_new(html, attrbuf, NULL, 0, 0, 0, 0);
- else
- action = a_Url_dup(html->base_url);
-
- html->formNew(DILLO_HTML_METHOD_GET, action, DILLO_HTML_ENC_URLENCODING,
- html->charset);
-
- form = html->getCurrentForm ();
-
- DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
-
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "prompt")))
- DW2TB(html->dw)->addText(dStrdup(attrbuf), S_TOP(html)->style);
-
- EntryResource *entryResource =
- HT2LT(html)->getResourceFactory()->createEntryResource (10, false);
- embed = new Embed (entryResource);
- form->addInput(DILLO_HTML_INPUT_INDEX, embed, NULL, NULL, NULL, FALSE);
-
- if (prefs.standard_widget_colors) {
- HTML_SET_TOP_ATTR(html, color, NULL);
- HTML_SET_TOP_ATTR(html, backgroundColor, NULL);
- }
- DW2TB(html->dw)->addWidget (embed, S_TOP(html)->style);
-
- a_Url_free(action);
-}
-
-/*
- * Close textarea
- * (TEXTAREA is parsed in VERBATIM mode, and entities are handled here)
- */
-static void Html_tag_close_textarea(DilloHtml *html, int TagIdx)
-{
- char *str;
- DilloHtmlForm *form;
- DilloHtmlInput *input;
- int i;
-
- if (html->InFlags & IN_FORM &&
- html->InFlags & IN_TEXTAREA) {
- /* Remove the line ending that follows the opening tag */
- if (html->Stash->str[0] == '\r')
- dStr_erase(html->Stash, 0, 1);
- if (html->Stash->str[0] == '\n')
- dStr_erase(html->Stash, 0, 1);
-
- /* As the spec recommends to canonicalize line endings, it is safe
- * to replace '\r' with '\n'. It will be canonicalized anyway! */
- for (i = 0; i < html->Stash->len; ++i) {
- if (html->Stash->str[i] == '\r') {
- if (html->Stash->str[i + 1] == '\n')
- dStr_erase(html->Stash, i, 1);
- else
- html->Stash->str[i] = '\n';
- }
- }
-
- /* The HTML3.2 spec says it can have "text and character entities". */
- str = Html_parse_entities(html, html->Stash->str, html->Stash->len);
- form = html->getCurrentForm ();
- input = form->getCurrentInput ();
- input->init_str = str;
- ((MultiLineTextResource *)input->embed->getResource ())
- ->setText(str);
-
- html->InFlags &= ~IN_TEXTAREA;
- }
- Html_pop_tag(html, TagIdx);
-}
-
-/*
- * The textarea tag
- * (todo: It doesn't support wrapping).
- */
-static void Html_tag_open_textarea(DilloHtml *html,
- const char *tag, int tagsize)
-{
- DilloHtmlForm *form;
- char *name;
- const char *attrbuf;
- int cols, rows;
-
- /* We can't push a new <FORM> because the 'action' URL is unknown */
- if (!(html->InFlags & IN_FORM)) {
- BUG_MSG("<textarea> outside <form>\n");
- html->ReqTagClose = TRUE;
- return;
- }
- if (html->InFlags & IN_TEXTAREA) {
- BUG_MSG("nested <textarea>\n");
- html->ReqTagClose = TRUE;
- return;
- }
-
- html->InFlags |= IN_TEXTAREA;
- form = html->getCurrentForm ();
- Html_stash_init(html);
- S_TOP(html)->parse_mode = DILLO_HTML_PARSE_MODE_VERBATIM;
-
- cols = 20;
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "cols")))
- cols = strtol(attrbuf, NULL, 10);
- rows = 10;
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "rows")))
- rows = strtol(attrbuf, NULL, 10);
- name = NULL;
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "name")))
- name = dStrdup(attrbuf);
-
- MultiLineTextResource *textres =
- HT2LT(html)->getResourceFactory()->createMultiLineTextResource (cols,
- rows);
-
- Embed *embed;
- embed = new Embed(textres);
- /* Readonly or not? */
- if (Html_get_attr(html, tag, tagsize, "readonly"))
- textres->setEditable(false);
-
- form->addInput(DILLO_HTML_INPUT_TEXTAREA, embed, name, NULL, NULL, false);
-
- DW2TB(html->dw)->addWidget (embed, S_TOP(html)->style);
-
-// widget = gtk_text_new(NULL, NULL);
-// /* compare <input type=text> */
-// gtk_signal_connect_after(GTK_OBJECT(widget), "button_press_event",
-// GTK_SIGNAL_FUNC(gtk_true),
-// NULL);
-//
-// /* Calculate the width and height based on the cols and rows
-// * todo: Get it right... Get the metrics from the font that will be used.
-// */
-// gtk_widget_set_usize(widget, 6 * cols, 16 * rows);
-//
-// /* If the attribute readonly isn't specified we make the textarea
-// * editable. If readonly is set we don't have to do anything.
-// */
-// if (!Html_get_attr(html, tag, tagsize, "readonly"))
-// gtk_text_set_editable(GTK_TEXT(widget), TRUE);
-//
-// scroll = gtk_scrolled_window_new(NULL, NULL);
-// gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),
-// GTK_POLICY_AUTOMATIC,
-// GTK_POLICY_AUTOMATIC);
-// gtk_container_add(GTK_CONTAINER(scroll), widget);
-// gtk_widget_show(widget);
-// gtk_widget_show(scroll);
-//
-// form->addInput(DILLO_HTML_INPUT_TEXTAREA,
-// widget, name, NULL, NULL, FALSE);
-// dFree(name);
-//
-// embed_gtk = a_Dw_embed_gtk_new ();
-// a_Dw_embed_gtk_add_gtk (DW_EMBED_GTK (embed_gtk), scroll);
-// DW2TB(html->dw)->addWidget (embed_gtk,
-// S_TOP(html)->style);
-}
-
-/*
- * <SELECT>
- */
-/* The select tag is quite tricky, because of gorpy html syntax. */
-static void Html_tag_open_select(DilloHtml *html, const char *tag, int tagsize)
-{
-// const char *attrbuf;
-// int size, type, multi;
-
- if (!(html->InFlags & IN_FORM)) {
- BUG_MSG("<select> outside <form>\n");
- return;
- }
- if (html->InFlags & IN_SELECT) {
- BUG_MSG("nested <select>\n");
- return;
- }
- html->InFlags |= IN_SELECT;
- html->InFlags &= ~IN_OPTION;
-
- DilloHtmlForm *form = html->getCurrentForm ();
- char *name = Html_get_attr_wdef(html, tag, tagsize, "name", NULL);
- ResourceFactory *factory = HT2LT(html)->getResourceFactory ();
- DilloHtmlInputType type;
- SelectionResource *res;
- if (Html_get_attr(html, tag, tagsize, "multiple")) {
- type = DILLO_HTML_INPUT_SEL_LIST;
- res = factory->createListResource (ListResource::SELECTION_MULTIPLE);
- } else {
- type = DILLO_HTML_INPUT_SELECT;
- res = factory->createOptionMenuResource ();
- }
- Embed *embed;
- embed = new Embed(res);
- if (prefs.standard_widget_colors) {
- HTML_SET_TOP_ATTR(html, color, NULL);
- HTML_SET_TOP_ATTR(html, backgroundColor, NULL);
- }
- DW2TB(html->dw)->addWidget (embed, S_TOP(html)->style);
-
-// size = 0;
-// if ((attrbuf = Html_get_attr(html, tag, tagsize, "size")))
-// size = strtol(attrbuf, NULL, 10);
-//
-// multi = (Html_get_attr(html, tag, tagsize, "multiple")) ? 1 : 0;
-// if (size < 1)
-// size = multi ? 10 : 1;
-//
-// if (size == 1) {
-// menu = gtk_menu_new();
-// widget = gtk_option_menu_new();
-// type = DILLO_HTML_INPUT_SELECT;
-// } else {
-// menu = gtk_list_new();
-// widget = menu;
-// if (multi)
-// gtk_list_set_selection_mode(GTK_LIST(menu), GTK_SELECTION_MULTIPLE);
-// type = DILLO_HTML_INPUT_SEL_LIST;
-// }
-
- DilloHtmlSelect *select = new DilloHtmlSelect;
- select->options = new misc::SimpleVector<DilloHtmlOption *> (4);
- form->addInput(type, embed, name, NULL, select, false);
- Html_stash_init(html);
- dFree(name);
-}
-
-/*
- * ?
- */
-static void Html_option_finish(DilloHtml *html)
-{
- DilloHtmlForm *form = html->getCurrentForm ();
- DilloHtmlInput *input = form->getCurrentInput ();
- if (input->type == DILLO_HTML_INPUT_SELECT ||
- input->type == DILLO_HTML_INPUT_SEL_LIST) {
- DilloHtmlSelect *select =
- input->select;
- DilloHtmlOption *option =
- select->options->get (select->options->size() - 1);
- option->content =
- Html_parse_entities(html, html->Stash->str, html->Stash->len);
- }
-}
-
-/*
- * <OPTION>
- */
-static void Html_tag_open_option(DilloHtml *html, const char *tag, int tagsize)
-{
- if (!(html->InFlags & IN_FORM &&
- html->InFlags & IN_SELECT ))
- return;
- if (html->InFlags & IN_OPTION)
- Html_option_finish(html);
- html->InFlags |= IN_OPTION;
-
- DilloHtmlForm *form = html->getCurrentForm ();
- DilloHtmlInput *input = form->getCurrentInput ();
-
- if (input->type == DILLO_HTML_INPUT_SELECT ||
- input->type == DILLO_HTML_INPUT_SEL_LIST) {
-
- DilloHtmlOption *option = new DilloHtmlOption;
- option->value =
- Html_get_attr_wdef(html, tag, tagsize, "value", NULL);
- option->content = NULL;
- option->selected =
- (Html_get_attr(html, tag, tagsize, "selected") != NULL);
- option->enabled =
- (Html_get_attr(html, tag, tagsize, "disabled") == NULL);
-
- int size = input->select->options->size ();
- input->select->options->increase ();
- input->select->options->set (size, option);
- }
-
- Html_stash_init(html);
-}
-
-/*
- * ?
- */
-static void Html_tag_close_select(DilloHtml *html, int TagIdx)
-{
- if (html->InFlags & IN_FORM &&
- html->InFlags & IN_SELECT) {
- if (html->InFlags & IN_OPTION)
- Html_option_finish(html);
- html->InFlags &= ~IN_SELECT;
- html->InFlags &= ~IN_OPTION;
-
- DilloHtmlForm *form = html->getCurrentForm ();
- DilloHtmlInput *input = form->getCurrentInput ();
- SelectionResource *res =
- (SelectionResource*)input->embed->getResource();
-
- int size = input->select->options->size ();
- if (size > 0) {
- // is anything selected?
- bool some_selected = false;
- for (int i = 0; i < size; i++) {
- DilloHtmlOption *option =
- input->select->options->get (i);
- if (option->selected) {
- some_selected = true;
- break;
- }
- }
-
- // select the first if nothing else is selected
- // BUG(?): should not do this for MULTI selections
- if (! some_selected)
- input->select->options->get (0)->selected = true;
-
- // add the items to the resource
- for (int i = 0; i < size; i++) {
- DilloHtmlOption *option =
- input->select->options->get (i);
- bool enabled = option->enabled;
- bool selected = option->selected;
- res->addItem(option->content,enabled,selected);
- }
- }
- }
-
- Html_pop_tag(html, TagIdx);
-}
-
-/*
* Set the Document Base URI
*/
static void Html_tag_open_base(DilloHtml *html, const char *tag, int tagsize)
@@ -4966,8 +3237,8 @@ static void Html_tag_open_base(DilloHtml *html, const char *tag, int tagsize)
DilloUrl *BaseUrl;
if (html->InFlags & IN_HEAD) {
- if ((attrbuf = Html_get_attr(html, tag, tagsize, "href"))) {
- BaseUrl = Html_url_new(html, attrbuf, "", 0, 0, 0, 1);
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "href"))) {
+ BaseUrl = a_Html_url_new(html, attrbuf, "", 0, 0, 0, 1);
if (URL_SCHEME_(BaseUrl)) {
/* Pass the URL_SpamSafe flag to the new base url */
a_Url_set_flags(
@@ -5055,7 +3326,7 @@ static void Html_tag_open_div(DilloHtml *html, const char *tag, int tagsize)
static void Html_tag_close_div(DilloHtml *html, int TagIdx)
{
DW2TB(html->dw)->addParbreak (0, S_TOP(html)->style);
- Html_pop_tag(html, TagIdx);
+ a_Html_pop_tag(html, TagIdx);
}
/*
@@ -5063,7 +3334,7 @@ static void Html_tag_close_div(DilloHtml *html, int TagIdx)
*/
static void Html_tag_close_default(DilloHtml *html, int TagIdx)
{
- Html_pop_tag(html, TagIdx);
+ a_Html_pop_tag(html, TagIdx);
}
/*
@@ -5072,7 +3343,7 @@ static void Html_tag_close_default(DilloHtml *html, int TagIdx)
static void Html_tag_close_par(DilloHtml *html, int TagIdx)
{
DW2TB(html->dw)->addParbreak (9, S_TOP(html)->style);
- Html_pop_tag(html, TagIdx);
+ a_Html_pop_tag(html, TagIdx);
}
@@ -5613,27 +3884,27 @@ static const char *Html_get_attr2(DilloHtml *html,
/*
* Call Html_get_attr2 telling it to parse entities and strip the result
*/
-static const char *Html_get_attr(DilloHtml *html,
- const char *tag,
- int tagsize,
- const char *attrname)
+const char *a_Html_get_attr(DilloHtml *html,
+ const char *tag,
+ int tagsize,
+ const char *attrname)
{
return Html_get_attr2(html, tag, tagsize, attrname,
HTML_LeftTrim | HTML_RightTrim | HTML_ParseEntities);
}
/*
- * "Html_get_attr with default"
- * Call Html_get_attr() and dStrdup() the returned string.
+ * "a_Html_get_attr with default"
+ * Call a_Html_get_attr() and dStrdup() the returned string.
* If the attribute isn't found a copy of 'def' is returned.
*/
-static char *Html_get_attr_wdef(DilloHtml *html,
- const char *tag,
- int tagsize,
- const char *attrname,
- const char *def)
+char *a_Html_get_attr_wdef(DilloHtml *html,
+ const char *tag,
+ int tagsize,
+ const char *attrname,
+ const char *def)
{
- const char *attrbuf = Html_get_attr(html, tag, tagsize, attrname);
+ const char *attrbuf = a_Html_get_attr(html, tag, tagsize, attrname);
return attrbuf ? dStrdup(attrbuf) : dStrdup(def);
}
diff --git a/src/html_common.hh b/src/html_common.hh
index 8cae537b..0587a54e 100644
--- a/src/html_common.hh
+++ b/src/html_common.hh
@@ -7,6 +7,7 @@
#include "lout/misc.hh"
#include "dw/core.hh"
#include "dw/image.hh"
+#include "dw/style.hh"
#include "image.hh"
@@ -219,8 +220,37 @@ public:
void finishParsing(int ClientKey);
int formNew(DilloHtmlMethod method, const DilloUrl *action,
DilloHtmlEnc enc, const char *charset);
- inline DilloHtmlForm *getCurrentForm ();
+ DilloHtmlForm *getCurrentForm ();
void loadImages (const DilloUrl *pattern);
};
+/*
+ * Parser functions
+ */
+
+const char *a_Html_get_attr(DilloHtml *html,
+ const char *tag,
+ int tagsize,
+ const char *attrname);
+
+char *a_Html_get_attr_wdef(DilloHtml *html,
+ const char *tag,
+ int tagsize,
+ const char *attrname,
+ const char *def);
+
+DilloUrl *a_Html_url_new(DilloHtml *html,
+ const char *url_str, const char *base_url,
+ int flags, int32_t posx, int32_t posy,
+ int use_base_url);
+
+DilloImage *a_Html_add_new_image(DilloHtml *html, const char *tag,
+ int tagsize, DilloUrl *url,
+ dw::core::style::StyleAttrs *style_attrs,
+ bool_t add);
+
+char *a_Html_parse_entities(DilloHtml *html, const char *token, int toksize);
+void a_Html_pop_tag(DilloHtml *html, int TagIdx);
+void a_Html_stash_init(DilloHtml *html);
+
#endif /* __HTML_COMMON_HH__ */