diff options
author | corvid <corvid@lavabit.com> | 2013-04-20 23:04:29 +0000 |
---|---|---|
committer | corvid <corvid@lavabit.com> | 2013-04-20 23:04:29 +0000 |
commit | b1823faf24501fce566fde182a5f56217c3b8dcc (patch) | |
tree | b2f04fc1793580ed46a7242570c5cfe9e9316168 /src | |
parent | 871b8716ba736be7953f71e1d62c8a9f2cb07ca5 (diff) |
implement OPTGROUP in src/
I wrote nearly all of this last year, and I've just been going back over it
now. As I recall, I initially also tried: select holds optgroups and options,
and optgroups hold options (instead of this flat array of options, optgroups,
and close-optgroups), but the code wasn't coming out any cleaner, so...
Diffstat (limited to 'src')
-rw-r--r-- | src/form.cc | 206 | ||||
-rw-r--r-- | src/form.hh | 2 | ||||
-rw-r--r-- | src/html.cc | 5 | ||||
-rw-r--r-- | src/html_common.hh | 11 |
4 files changed, 169 insertions, 55 deletions
diff --git a/src/form.cc b/src/form.cc index d9537036..10b4347f 100644 --- a/src/form.cc +++ b/src/form.cc @@ -36,7 +36,6 @@ using namespace dw::core::ui; class DilloHtmlReceiver; class DilloHtmlSelect; -class DilloHtmlOption; static Embed *Html_input_image(DilloHtml *html, const char *tag, int tagsize); @@ -166,29 +165,64 @@ public: void setEnabled(bool enabled) {if (embed) embed->setEnabled(enabled); }; }; -class DilloHtmlSelect { - friend class DilloHtmlInput; +class DilloHtmlOptbase +{ +public: + virtual ~DilloHtmlOptbase () {}; + virtual bool isSelected() {return false;} + virtual bool select() {return false;} + virtual const char *getValue() {return NULL;} + virtual void setContent(const char *str, int len) + {MSG_ERR("Form: Optbase setContent()\n");} + virtual void addSelf(SelectionResource *res) = 0; +}; + +class DilloHtmlOptgroup : public DilloHtmlOptbase { private: - lout::misc::SimpleVector<DilloHtmlOption *> *options; - DilloHtmlSelect (); - ~DilloHtmlSelect (); + char *label; + bool enabled; public: - DilloHtmlOption *getCurrentOption (); - void addOption (char *value, bool selected, bool enabled); - void ensureSelection (); - void addOptionsTo (SelectionResource *res); - void reset (SelectionResource *res); - void appendValuesTo (Dlist *values, SelectionResource *res); + DilloHtmlOptgroup (char *label, bool enabled); + virtual ~DilloHtmlOptgroup (); + void addSelf (SelectionResource *res) + {res->pushGroup(label, enabled);} +}; + +class DilloHtmlOptgroupClose : public DilloHtmlOptbase { +public: + virtual ~DilloHtmlOptgroupClose () {}; + void addSelf (SelectionResource *res) + {res->popGroup();} }; -class DilloHtmlOption { +class DilloHtmlOption : public DilloHtmlOptbase { friend class DilloHtmlSelect; public: char *value, *content; bool selected, enabled; -private: DilloHtmlOption (char *value, bool selected, bool enabled); - ~DilloHtmlOption (); + virtual ~DilloHtmlOption (); + bool isSelected() {return selected;} + bool select() {return (selected = true);} + const char *getValue() {return value ? value : content;} + void setContent(const char *str, int len) {content = dStrndup(str, len);} + void addSelf (SelectionResource *res) + {res->addItem(content, enabled, selected);} +}; + +class DilloHtmlSelect { + friend class DilloHtmlInput; +private: + lout::misc::SimpleVector<DilloHtmlOptbase *> *opts; + DilloHtmlSelect (); + ~DilloHtmlSelect (); +public: + DilloHtmlOptbase *getCurrentOpt (); + void addOpt (DilloHtmlOptbase *opt); + void ensureSelection (); + void addOptsTo (SelectionResource *res); + void reset (SelectionResource *res); + void appendValuesTo (Dlist *values, SelectionResource *res); }; /* @@ -767,7 +801,66 @@ void Html_tag_close_select(DilloHtml *html) select->ensureSelection (); } SelectionResource *res = (SelectionResource*)input->embed->getResource(); - select->addOptionsTo (res); + select->addOptsTo (res); + } +} + +void Html_tag_open_optgroup(DilloHtml *html, const char *tag, int tagsize) +{ + MSG("OPEN OPTGROUP\n"); + + if (!(html->InFlags & IN_SELECT)) { + BUG_MSG("<optgroup> element outside <select>\n"); + return; + } + if (html->InFlags & IN_OPTGROUP) { + BUG_MSG("nested <optgroup>\n"); + return; + } + if (html->InFlags & IN_OPTION) { + Html_option_finish(html); + html->InFlags &= ~IN_OPTION; + } + + html->InFlags |= IN_OPTGROUP; + + DilloHtmlInput *input = Html_get_current_input(html); + + if (input->type == DILLO_HTML_INPUT_SELECT || + input->type == DILLO_HTML_INPUT_SEL_LIST) { + char *label = a_Html_get_attr_wdef(html, tag, tagsize, "label", NULL); + bool enabled = (a_Html_get_attr(html, tag, tagsize, "disabled") == NULL); + + if (!label) { + BUG_MSG("label attribute is required for <optgroup>\n"); + label = strdup(""); + } + + DilloHtmlOptgroup *opt = + new DilloHtmlOptgroup (label, enabled); + + input->select->addOpt(opt); + } +} + +void Html_tag_close_optgroup(DilloHtml *html) +{ + if (html->InFlags & IN_OPTGROUP) { + html->InFlags &= ~IN_OPTGROUP; + + if (html->InFlags & IN_OPTION) { + Html_option_finish(html); + html->InFlags &= ~IN_OPTION; + } + + DilloHtmlInput *input = Html_get_current_input(html); + + if (input->type == DILLO_HTML_INPUT_SELECT || + input->type == DILLO_HTML_INPUT_SEL_LIST) { + DilloHtmlOptgroupClose *opt = new DilloHtmlOptgroupClose (); + + input->select->addOpt(opt); + } } } @@ -791,7 +884,11 @@ void Html_tag_open_option(DilloHtml *html, const char *tag, int tagsize) char *value = a_Html_get_attr_wdef(html, tag, tagsize, "value", NULL); bool selected = (a_Html_get_attr(html, tag, tagsize,"selected") != NULL); bool enabled = (a_Html_get_attr(html, tag, tagsize, "disabled") == NULL); - input->select->addOption(value, selected, enabled); + + DilloHtmlOption *option = + new DilloHtmlOption (value, selected, enabled); + + input->select->addOpt(option); } a_Html_stash_init(html); @@ -1792,7 +1889,7 @@ void DilloHtmlInput::reset () */ DilloHtmlSelect::DilloHtmlSelect () { - options = new misc::SimpleVector<DilloHtmlOption *> (4); + opts = new misc::SimpleVector<DilloHtmlOptbase *> (4); } /* @@ -1800,24 +1897,22 @@ DilloHtmlSelect::DilloHtmlSelect () */ DilloHtmlSelect::~DilloHtmlSelect () { - int size = options->size (); + int size = opts->size (); for (int k = 0; k < size; k++) - delete options->get (k); - delete options; + delete opts->get (k); + delete opts; } -DilloHtmlOption *DilloHtmlSelect::getCurrentOption () +DilloHtmlOptbase *DilloHtmlSelect::getCurrentOpt () { - return options->get (options->size() - 1); + return opts->get (opts->size() - 1); } -void DilloHtmlSelect::addOption (char *value, bool selected, bool enabled) +void DilloHtmlSelect::addOpt (DilloHtmlOptbase *opt) { - DilloHtmlOption *option = - new DilloHtmlOption (value, selected, enabled); - int size = options->size (); - options->increase (); - options->set (size, option); + int size = opts->size (); + opts->increase (); + opts->set (size, opt); } /* @@ -1825,48 +1920,64 @@ void DilloHtmlSelect::addOption (char *value, bool selected, bool enabled) */ void DilloHtmlSelect::ensureSelection() { - int size = options->size (); + int size = opts->size (); if (size > 0) { for (int i = 0; i < size; i++) { - DilloHtmlOption *option = options->get (i); - if (option->selected) + DilloHtmlOptbase *opt = opts->get (i); + if (opt->isSelected()) return; } - DilloHtmlOption *option = options->get (0); - option->selected = true; + for (int i = 0; i < size; i++) { + DilloHtmlOptbase *opt = opts->get (i); + if (opt->select()) + break; + } } } -void DilloHtmlSelect::addOptionsTo (SelectionResource *res) +void DilloHtmlSelect::addOptsTo (SelectionResource *res) { - int size = options->size (); + int size = opts->size (); for (int i = 0; i < size; i++) { - DilloHtmlOption *option = options->get (i); - res->addItem(option->content, option->enabled, option->selected); + DilloHtmlOptbase *opt = opts->get (i); + opt->addSelf(res); } } void DilloHtmlSelect::reset (SelectionResource *res) { - int size = options->size (); + int size = opts->size (); for (int i = 0; i < size; i++) { - DilloHtmlOption *option = options->get (i); - res->setItem(i, option->selected); + DilloHtmlOptbase *opt = opts->get (i); + res->setItem(i, opt->isSelected()); } } void DilloHtmlSelect::appendValuesTo (Dlist *values, SelectionResource *res) { - int size = options->size (); + int size = opts->size (); for (int i = 0; i < size; i++) { if (res->isSelected (i)) { - DilloHtmlOption *option = options->get (i); - char *val = option->value ? option->value : option->content; - dList_append(values, dStr_new(val)); + DilloHtmlOptbase *opt = opts->get (i); + const char *val = opt->getValue(); + + if (val) + dList_append(values, dStr_new(val)); } } } +DilloHtmlOptgroup::DilloHtmlOptgroup (char *label, bool enabled) +{ + this->label = label; + this->enabled = enabled; +} + +DilloHtmlOptgroup::~DilloHtmlOptgroup () +{ + dFree(label); +} + /* * DilloHtmlOption */ @@ -1930,8 +2041,7 @@ static void Html_option_finish(DilloHtml *html) DilloHtmlInput *input = Html_get_current_input(html); if (input->type == DILLO_HTML_INPUT_SELECT || input->type == DILLO_HTML_INPUT_SEL_LIST) { - DilloHtmlOption *option = - input->select->getCurrentOption (); - option->content = dStrndup(html->Stash->str, html->Stash->len); + DilloHtmlOptbase *opt = input->select->getCurrentOpt (); + opt->setContent (html->Stash->str, html->Stash->len); } } diff --git a/src/form.hh b/src/form.hh index 640e7e69..cab2d7f2 100644 --- a/src/form.hh +++ b/src/form.hh @@ -58,6 +58,8 @@ void Html_tag_open_select(DilloHtml *html, const char *tag, int tagsize); void Html_tag_close_select(DilloHtml *html); void Html_tag_open_option(DilloHtml *html, const char *tag, int tagsize); void Html_tag_close_option(DilloHtml *html); +void Html_tag_open_optgroup(DilloHtml *html, const char *tag, int tagsize); +void Html_tag_close_optgroup(DilloHtml *html); void Html_tag_open_button(DilloHtml *html, const char *tag, int tagsize); void Html_tag_close_button(DilloHtml *html); diff --git a/src/html.cc b/src/html.cc index 41ccf95f..896700ec 100644 --- a/src/html.cc +++ b/src/html.cc @@ -3192,8 +3192,9 @@ const TagInfo Tags[] = { /* noscript 1011 */ {"object", B8(111101),'R',2, Html_tag_open_object, NULL, NULL}, {"ol", B8(011010),'R',2, Html_tag_open_ol, NULL, NULL}, - /* optgroup */ - {"option", B8(010001),'O',1, Html_tag_open_option,NULL,Html_tag_close_option}, + {"optgroup", B8(010101),'O',1, Html_tag_open_optgroup, NULL, + Html_tag_close_optgroup}, + {"option", B8(010001),'O',0, Html_tag_open_option,NULL,Html_tag_close_option}, {"p", B8(010110),'O',1, Html_tag_open_p, NULL, NULL}, /* param 010001 'F' */ {"pre", B8(010110),'R',2, Html_tag_open_pre, NULL, Html_tag_close_pre}, diff --git a/src/html_common.hh b/src/html_common.hh index cdb856db..44730a57 100644 --- a/src/html_common.hh +++ b/src/html_common.hh @@ -80,11 +80,12 @@ typedef enum { IN_FORM = 1 << 3, IN_SELECT = 1 << 4, IN_OPTION = 1 << 5, - IN_TEXTAREA = 1 << 6, - IN_MAP = 1 << 7, - IN_PRE = 1 << 8, - IN_BUTTON = 1 << 9, - IN_LI = 1 << 10, + IN_OPTGROUP = 1 << 6, + IN_TEXTAREA = 1 << 7, + IN_BUTTON = 1 << 8, + IN_MAP = 1 << 9, + IN_PRE = 1 << 10, + IN_LI = 1 << 11, } DilloHtmlProcessingState; /* |