From 062c2f0de95a179cd28cfe847be838621f898584 Mon Sep 17 00:00:00 2001 From: jcid Date: Sat, 7 Jun 2008 15:29:01 +0200 Subject: - html.cc cleanup (in progress): source split. --- src/form.cc | 1795 +++++++++++++++++++++++++++++++++++++++++++++++ src/form.hh | 31 + src/html.cc | 1949 +++------------------------------------------------- src/html_common.hh | 32 +- 4 files changed, 1967 insertions(+), 1840 deletions(-) (limited to 'src') 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 +#include + +#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 *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 *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
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 = + ""; + 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. ) */ +// 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(" element outside \n"); + return; + } + if (html->InFlags & IN_SELECT) { + BUG_MSG(" element inside element inside