diff options
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | dw/fltkplatform.cc | 6 | ||||
-rw-r--r-- | dw/fltkplatform.hh | 3 | ||||
-rw-r--r-- | dw/fltkui.cc | 140 | ||||
-rw-r--r-- | dw/fltkui.hh | 3 | ||||
-rw-r--r-- | dw/textblock.cc | 4 | ||||
-rw-r--r-- | dw/ui.hh | 3 | ||||
-rw-r--r-- | src/capi.c | 4 | ||||
-rw-r--r-- | src/form.cc | 16 | ||||
-rw-r--r-- | src/html.cc | 65 | ||||
-rw-r--r-- | test/dw_ui_test.cc | 5 |
11 files changed, 199 insertions, 54 deletions
@@ -33,7 +33,8 @@ dillo-3.1 [not released yet] - Fix crash that's possible searching for text while page still being built. Patches: Sebastian Geerken +- Image buffer/cache improvements. - Patch: Jorge Arellano Cid + - Fix for segfault when there's no dpid and view source is requested. + Patches: Jorge Arellano Cid +- Crosscompile/buildroot-friendly fltk-config test. Patch: Peter Seiderer +- HTML5 character references. @@ -43,6 +44,7 @@ dillo-3.1 [not released yet] - Abort failed queries. - In location bar, tend toward showing beginning of URL instead of end. - Handle irix's version of vsnprintf(). + - INPUT placeholder attribute. Patches: corvid +- Avoid requesting background images if an ancestor has display:none. Patch: Johannes Hofmann diff --git a/dw/fltkplatform.cc b/dw/fltkplatform.cc index 2fc7ff41..67b04688 100644 --- a/dw/fltkplatform.cc +++ b/dw/fltkplatform.cc @@ -413,9 +413,11 @@ FltkPlatform::FltkResourceFactory::createOptionMenuResource () core::ui::EntryResource * FltkPlatform::FltkResourceFactory::createEntryResource (int size, bool password, - const char *label) + const char *label, + const char *placeholder) { - return new ui::FltkEntryResource (platform, size, password, label); + return new ui::FltkEntryResource (platform, size, password, label, + placeholder); } core::ui::MultiLineTextResource * diff --git a/dw/fltkplatform.hh b/dw/fltkplatform.hh index cbf3c6f9..5aa86e62 100644 --- a/dw/fltkplatform.hh +++ b/dw/fltkplatform.hh @@ -110,7 +110,8 @@ private: int rows); core::ui::OptionMenuResource *createOptionMenuResource (); core::ui::EntryResource *createEntryResource (int size, bool password, - const char *label); + const char *label, + const char *placeholder); core::ui::MultiLineTextResource *createMultiLineTextResource (int cols, int rows); core::ui::CheckButtonResource *createCheckButtonResource (bool diff --git a/dw/fltkui.cc b/dw/fltkui.cc index 6099fd69..a648638d 100644 --- a/dw/fltkui.cc +++ b/dw/fltkui.cc @@ -42,18 +42,115 @@ */ /* - * Used to enable CTRL+{a,e,d,k} in form inputs (for start,end,del,cut) + * Used to show optional placeholder text and to enable CTRL+{a,e,d,k} in + * form inputs (for start,end,del,cut) */ class CustInput2 : public Fl_Input { public: - CustInput2 (int x, int y, int w, int h, const char* l=0) : - Fl_Input(x,y,w,h,l) {}; + CustInput2 (int x, int y, int w, int h, const char* l=0); + ~CustInput2 () { if (placeholder) free(placeholder); }; + void set_placeholder(const char *str); + int show_placeholder(); + int show_normal(const char *str); + void textcolor(Fl_Color c); + void input_type(int t); + int value(const char* str); + const char* value(); int handle(int e); +private: + Fl_Color dimmed(Fl_Color c) {return fl_color_average(c, color(), .33f); }; + char *placeholder; + bool showing_placeholder; + Fl_Color usual_color; + int usual_type; }; +CustInput2::CustInput2 (int x, int y, int w, int h, const char* l) : + Fl_Input(x,y,w,h,l) +{ + placeholder = NULL; + showing_placeholder = false; + usual_color = FL_BLACK; /* just init until widget style is set */ +}; + +/* + * Show normal text. + */ +int CustInput2::show_normal(const char *str) +{ + showing_placeholder = false; + Fl_Input::textcolor(usual_color); + Fl_Input::input_type(usual_type); + return Fl_Input::value(str); +} + +/* + * Show the placeholder text. + */ +int CustInput2::show_placeholder() +{ + showing_placeholder = true; + Fl_Input::textcolor(dimmed(usual_color)); + Fl_Input::input_type(FL_NORMAL_INPUT); + return Fl_Input::value(placeholder); +} + +/* + * Set the placeholder text. + */ +void CustInput2::set_placeholder(const char *str) +{ + if (placeholder) + free(placeholder); + placeholder = strdup(str); + + if ((Fl::focus() != this) && !*value()) { + show_placeholder(); + } +} + +/* + * Set the text color. + */ +void CustInput2::textcolor(Fl_Color c) +{ + usual_color = c; + if (showing_placeholder) + c = dimmed(c); + Fl_Input::textcolor(c); +} + +/* + * Set the input type (normal, password, etc.) + */ +void CustInput2::input_type(int t) +{ + usual_type = t; + Fl_Input::input_type(t); +} + +/* + * Set the value of the input. + * NOTE that we're not being very careful with the return value, which is + * supposed to be nonzero iff the value was changed. + */ +int CustInput2::value(const char *str) +{ + return (placeholder && (!str || !*str) && Fl::focus() != this) + ? show_placeholder() : show_normal(str); +} + +/* + * Return the value (text) of the input. + */ +const char* CustInput2::value() +{ + return showing_placeholder ? "" : Fl_Input::value(); +} + int CustInput2::handle(int e) { - int k = Fl::event_key(); + int rc, k = Fl::event_key(); _MSG("CustInput2::handle event=%d\n", e); @@ -82,8 +179,20 @@ int CustInput2::handle(int e) return 0; } } + } else if (e == FL_UNFOCUS) { + if (placeholder && !value()[0]) { + show_placeholder(); + } + } + + rc = Fl_Input::handle(e); + + if (rc && e == FL_FOCUS) { + // Nonzero return from handle() should mean that focus was accepted. + if (showing_placeholder) + show_normal(""); } - return Fl_Input::handle(e); + return rc; } @@ -607,13 +716,15 @@ Fl_Widget *FltkComplexButtonResource::createNewWidget (core::Allocation // ---------------------------------------------------------------------- FltkEntryResource::FltkEntryResource (FltkPlatform *platform, int size, - bool password, const char *label): + bool password, const char *label, + const char *placeholder): FltkSpecificResource <dw::core::ui::EntryResource> (platform) { this->size = size; this->password = password; this->label = label ? strdup(label) : NULL; this->label_w = 0; + this->placeholder = placeholder ? strdup(placeholder) : NULL; initText = NULL; editable = false; @@ -627,16 +738,17 @@ FltkEntryResource::~FltkEntryResource () free((char *)initText); if (label) free(label); + if (placeholder) + free(placeholder); } Fl_Widget *FltkEntryResource::createNewWidget (core::Allocation *allocation) { - Fl_Input *input = + CustInput2 *input = new CustInput2(allocation->x, allocation->y, allocation->width, allocation->ascent + allocation->descent); - if (password) - input->type(FL_SECRET_INPUT); + input->input_type(password ? FL_SECRET_INPUT : FL_NORMAL_INPUT); input->callback (widgetCallback, this); input->when (FL_WHEN_ENTER_KEY_ALWAYS); @@ -646,6 +758,8 @@ Fl_Widget *FltkEntryResource::createNewWidget (core::Allocation } if (initText) input->value (initText); + if (placeholder) + input->set_placeholder(placeholder); return input; } @@ -653,12 +767,12 @@ Fl_Widget *FltkEntryResource::createNewWidget (core::Allocation void FltkEntryResource::setWidgetStyle (Fl_Widget *widget, core::style::Style *style) { - Fl_Input *in = (Fl_Input *)widget; + CustInput2 *in = (CustInput2 *)widget; FltkResource::setWidgetStyle(widget, style); in->textcolor(widget->labelcolor()); - in->cursor_color(in->textcolor()); + in->cursor_color(widget->labelcolor()); in->textsize(in->labelsize()); in->textfont(in->labelfont()); @@ -729,7 +843,7 @@ void FltkEntryResource::widgetCallback (Fl_Widget *widget, void *data) const char *FltkEntryResource::getText () { - return ((Fl_Input*)widget)->value (); + return ((CustInput2*)widget)->value (); } void FltkEntryResource::setText (const char *text) @@ -738,7 +852,7 @@ void FltkEntryResource::setText (const char *text) free((char *)initText); initText = strdup (text); - ((Fl_Input*)widget)->value (initText); + ((CustInput2*)widget)->value (initText); } bool FltkEntryResource::isEditable () diff --git a/dw/fltkui.hh b/dw/fltkui.hh index 6ff024ca..fc22defd 100644 --- a/dw/fltkui.hh +++ b/dw/fltkui.hh @@ -303,6 +303,7 @@ private: const char *initText; char *label; int label_w; + char *placeholder; bool editable; static void widgetCallback (Fl_Widget *widget, void *data); @@ -314,7 +315,7 @@ protected: public: FltkEntryResource (FltkPlatform *platform, int size, bool password, - const char *label); + const char *label, const char *placeholder); ~FltkEntryResource (); void sizeRequest (core::Requisition *requisition); diff --git a/dw/textblock.cc b/dw/textblock.cc index e4bc72ab..40eb4014 100644 --- a/dw/textblock.cc +++ b/dw/textblock.cc @@ -577,7 +577,9 @@ void Textblock::sizeAllocateImpl (core::Allocation *allocation) core::Allocation childAllocation; core::Allocation *oldChildAllocation; - if (allocation->width != this->allocation.width) { + if (allocation->x != this->allocation.x || + allocation->y != this->allocation.y || + allocation->width != this->allocation.width) { redrawY = 0; DBG_OBJ_SET_NUM ("redrawY", redrawY); } @@ -580,7 +580,8 @@ public: selectionMode, int rows) = 0; virtual OptionMenuResource *createOptionMenuResource () = 0; virtual EntryResource *createEntryResource (int size, bool password, - const char *label) = 0; + const char *label, + const char *placeholder) = 0; virtual MultiLineTextResource *createMultiLineTextResource (int cols, int rows) = 0; virtual CheckButtonResource *createCheckButtonResource (bool activated) = 0; @@ -570,8 +570,8 @@ int a_Capi_dpi_send_data(const DilloUrl *url, void *bw, } else { /* Re-use an open connection */ conn = Capi_conn_find(server); - if (conn) { - /* found */ + if (conn && conn->InfoSend) { + /* found & active */ dbuf = a_Chain_dbuf_new(data, data_sz, 0); a_Capi_ccc(OpSend, 1, BCK, conn->InfoSend, dbuf, NULL); dFree(dbuf); diff --git a/src/form.cc b/src/form.cc index 9e7dc4f6..366b00b9 100644 --- a/src/form.cc +++ b/src/form.cc @@ -431,7 +431,7 @@ void Html_tag_open_input(DilloHtml *html, const char *tag, int tagsize) DilloHtmlInputType inp_type; Resource *resource = NULL; Embed *embed = NULL; - char *value, *name, *type, *init_str; + char *value, *name, *type, *init_str, *placeholder = NULL; const char *attrbuf, *label; bool init_val = false; ResourceFactory *factory; @@ -456,9 +456,10 @@ void Html_tag_open_input(DilloHtml *html, const char *tag, int tagsize) inp_type = DILLO_HTML_INPUT_UNKNOWN; if (!dStrAsciiCasecmp(type, "password")) { inp_type = DILLO_HTML_INPUT_PASSWORD; + placeholder = a_Html_get_attr_wdef(html, tag,tagsize,"placeholder",NULL); attrbuf = a_Html_get_attr(html, tag, tagsize, "size"); int size = Html_input_get_size(html, attrbuf); - resource = factory->createEntryResource (size, true, NULL); + resource = factory->createEntryResource (size, true, NULL, placeholder); init_str = value; } else if (!dStrAsciiCasecmp(type, "checkbox")) { inp_type = DILLO_HTML_INPUT_CHECKBOX; @@ -478,7 +479,7 @@ void Html_tag_open_input(DilloHtml *html, const char *tag, int tagsize) inp_type = DILLO_HTML_INPUT_HIDDEN; init_str = value; int size = Html_input_get_size(html, NULL); - resource = factory->createEntryResource(size, false, name); + resource = factory->createEntryResource(size, false, name, NULL); } else if (!dStrAsciiCasecmp(type, "submit")) { inp_type = DILLO_HTML_INPUT_SUBMIT; init_str = (value) ? value : dStrdup("submit"); @@ -531,9 +532,10 @@ void Html_tag_open_input(DilloHtml *html, const char *tag, int tagsize) } else { /* Text input, which also is the default */ inp_type = DILLO_HTML_INPUT_TEXT; + placeholder = a_Html_get_attr_wdef(html, tag,tagsize,"placeholder",NULL); attrbuf = a_Html_get_attr(html, tag, tagsize, "size"); int size = Html_input_get_size(html, attrbuf); - resource = factory->createEntryResource(size, false, NULL); + resource = factory->createEntryResource(size, false, NULL, placeholder); init_str = value; } if (resource) @@ -573,6 +575,7 @@ void Html_tag_open_input(DilloHtml *html, const char *tag, int tagsize) dFree(name); if (init_str != value) dFree(init_str); + dFree(placeholder); dFree(value); } @@ -606,7 +609,8 @@ void Html_tag_open_isindex(DilloHtml *html, const char *tag, int tagsize) HT2TB(html)->addText(attrbuf, html->wordStyle ()); ResourceFactory *factory = HT2LT(html)->getResourceFactory(); - EntryResource *entryResource = factory->createEntryResource (20,false,NULL); + EntryResource *entryResource = factory->createEntryResource (20, false, + NULL, NULL); embed = new Embed (entryResource); Html_add_input(html, DILLO_HTML_INPUT_INDEX, embed, NULL, NULL, FALSE); @@ -654,7 +658,7 @@ void Html_tag_content_textarea(DilloHtml *html, const char *tag, int tagsize) } else { if (html->DocType != DT_HTML || html->DocTypeVersion <= 4.01f) BUG_MSG("<textarea> requires rows attribute."); - rows = 10; + rows = 2; } if (rows < 1 || rows > MAX_ROWS) { int badRows = rows; diff --git a/src/html.cc b/src/html.cc index 571acf77..d2e513b2 100644 --- a/src/html.cc +++ b/src/html.cc @@ -3108,20 +3108,23 @@ static void Html_tag_close_pre(DilloHtml *html) * Check whether a tag is in the "excluding" element set for PRE * Excl. Set = {IMG, OBJECT, APPLET, BIG, SMALL, SUB, SUP, FONT, BASEFONT} */ -static int Html_tag_pre_excludes(int tag_idx) +static int Html_tag_pre_excludes(DilloHtml *html, int tag_idx) { - const char *es_set[] = {"img", "object", "applet", "big", "small", "sub", - "sup", "font", "basefont", NULL}; - static int ei_set[10], i; + if (!(html->DocType == DT_HTML && html->DocTypeVersion >= 5.0f)) { + /* HTML5 doesn't say anything about excluding elements */ + const char *es_set[] = {"img", "object", "applet", "big", "small", "sub", + "sup", "font", "basefont", NULL}; + static int ei_set[10], i; - /* initialize array */ - if (!ei_set[0]) - for (i = 0; es_set[i]; ++i) - ei_set[i] = a_Html_tag_index(es_set[i]); + /* initialize array */ + if (!ei_set[0]) + for (i = 0; es_set[i]; ++i) + ei_set[i] = a_Html_tag_index(es_set[i]); - for (i = 0; ei_set[i]; ++i) - if (tag_idx == ei_set[i]) - return 1; + for (i = 0; ei_set[i]; ++i) + if (tag_idx == ei_set[i]) + return 1; + } return 0; } @@ -3171,7 +3174,13 @@ static void Html_tag_open_meta(DilloHtml *html, const char *tag, int tagsize) /* only valid inside HEAD */ if (!(html->InFlags & IN_HEAD)) { - BUG_MSG("<meta> must be inside the HEAD section."); + if (!((html->DocType == DT_HTML && html->DocTypeVersion >= 5.0f) && + a_Html_get_attr(html, tag, tagsize, "itemprop"))) { + /* With the HTML 5.1 draft spec, meta with itemprop may appear + * in the body. + */ + BUG_MSG("This <meta> element must be inside the HEAD section."); + } return; } @@ -3409,14 +3418,13 @@ static void Html_tag_open_span(DilloHtml *html, const char *tag, int tagsize) } /* - * <DIV> (TODO: make a complete implementation) + * html5 sectioning stuff: article aside nav section header footer */ -static void Html_tag_open_div(DilloHtml *html, const char *tag, int tagsize) +static void Html_tag_open_sectioning(DilloHtml *html, const char *tag, + int tagsize) { const char *attrbuf; - a_Html_tag_set_align_attr (html, tag, tagsize); - if (prefs.show_tooltip && (attrbuf = a_Html_get_attr(html, tag, tagsize, "title"))) { @@ -3426,6 +3434,15 @@ static void Html_tag_open_div(DilloHtml *html, const char *tag, int tagsize) } /* + * <DIV> (TODO: make a complete implementation) + */ +static void Html_tag_open_div(DilloHtml *html, const char *tag, int tagsize) +{ + a_Html_tag_set_align_attr (html, tag, tagsize); + Html_tag_open_sectioning(html, tag, tagsize); +} + +/* * Default close for paragraph tags - pop the stack and break. */ static void Html_tag_close_par(DilloHtml *html) @@ -3474,8 +3491,8 @@ const TagInfo Tags[] = { {"address", B8(010110),'R',2,Html_tag_open_default, NULL, Html_tag_close_par}, {"area", B8(010001),'F',0, Html_tag_open_default, Html_tag_content_area, NULL}, - {"article", B8(011110),'R',2, Html_tag_open_default, NULL, NULL}, - {"aside", B8(011110),'R',2, Html_tag_open_default, NULL, NULL}, + {"article", B8(011110),'R',2, Html_tag_open_sectioning, NULL, NULL}, + {"aside", B8(011110),'R',2, Html_tag_open_sectioning, NULL, NULL}, {"audio", B8(011101),'R',2, Html_tag_open_audio, NULL, Html_tag_close_media}, {"b", B8(010101),'R',2, Html_tag_open_default, NULL, NULL}, {"base", B8(100001),'F',0, Html_tag_open_base, NULL, NULL}, @@ -3508,7 +3525,7 @@ const TagInfo Tags[] = { {"figcaption", B8(011110),'R',2, Html_tag_open_default, NULL, NULL}, {"figure", B8(011110),'R',2, Html_tag_open_default, NULL, NULL}, {"font", B8(010101),'R',2, Html_tag_open_font, NULL, NULL}, - {"footer", B8(011110),'R',2, Html_tag_open_default, NULL, NULL}, + {"footer", B8(011110),'R',2, Html_tag_open_sectioning, NULL, NULL}, {"form", B8(011110),'R',2, Html_tag_open_form, NULL, Html_tag_close_form}, {"frame", B8(010010),'F',0, Html_tag_open_frame, Html_tag_content_frame, NULL}, @@ -3521,7 +3538,7 @@ const TagInfo Tags[] = { {"h5", B8(010110),'R',2, Html_tag_open_h, NULL, NULL}, {"h6", B8(010110),'R',2, Html_tag_open_h, NULL, NULL}, {"head", B8(101101),'O',1, Html_tag_open_head, NULL, Html_tag_close_head}, - {"header", B8(011110),'R',2, Html_tag_open_default, NULL, NULL}, + {"header", B8(011110),'R',2, Html_tag_open_sectioning, NULL, NULL}, {"hr", B8(010010),'F',0, Html_tag_open_hr, Html_tag_content_hr, NULL}, {"html", B8(001110),'O',1, Html_tag_open_html, NULL, Html_tag_close_html}, @@ -3543,8 +3560,8 @@ const TagInfo Tags[] = { {"mark", B8(010101),'R',2, Html_tag_open_default, NULL, NULL}, /* menu 1010 -- TODO: not exactly 1010, it can contain LI and inline */ {"menu", B8(011010),'R',2, Html_tag_open_menu, NULL, Html_tag_close_par}, - {"meta", B8(100001),'F',0, Html_tag_open_meta, NULL, NULL}, - {"nav", B8(011110),'R',2, Html_tag_open_default, NULL, NULL}, + {"meta", B8(110001),'F',0, Html_tag_open_meta, NULL, NULL}, + {"nav", B8(011110),'R',2, Html_tag_open_sectioning, NULL, NULL}, /* noframes 1011 -- obsolete in HTML5 */ /* noscript 1011 */ {"object", B8(111101),'R',2, Html_tag_open_object, Html_tag_content_object, @@ -3560,7 +3577,7 @@ const TagInfo Tags[] = { {"s", B8(010101),'R',2, Html_tag_open_default, NULL, NULL}, {"samp", B8(010101),'R',2, Html_tag_open_default, NULL, NULL}, {"script", B8(111001),'R',2, Html_tag_open_script,NULL,Html_tag_close_script}, - {"section", B8(011110),'R',2, Html_tag_open_default, NULL, NULL}, + {"section", B8(011110),'R',2, Html_tag_open_sectioning, NULL, NULL}, {"select", B8(010101),'R',2, Html_tag_open_select,NULL,Html_tag_close_select}, {"small", B8(010101),'R',2, Html_tag_open_default, NULL, NULL}, {"source", B8(010001),'F',0, Html_tag_open_source, Html_tag_content_source, @@ -3961,7 +3978,7 @@ static void Html_process_tag(DilloHtml *html, char *tag, int tagsize) /* TODO: this is only raising a warning, take some defined action. * Note: apache uses IMG inside PRE (we could use its "alt"). */ - if ((html->InFlags & IN_PRE) && Html_tag_pre_excludes(ni)) + if ((html->InFlags & IN_PRE) && Html_tag_pre_excludes(html, ni)) BUG_MSG("<pre> is not allowed to contain <%s>.", Tags[ni].name); /* Make sure these elements don't nest each other */ diff --git a/test/dw_ui_test.cc b/test/dw_ui_test.cc index 086a4976..b70349ca 100644 --- a/test/dw_ui_test.cc +++ b/test/dw_ui_test.cc @@ -81,10 +81,11 @@ int main(int argc, char **argv) // First of all, the resources. Later, they are embedded into the // widget tree. EntryResource *entryres1 = - layout->getResourceFactory()->createEntryResource (10, false, NULL); + layout->getResourceFactory()->createEntryResource (10, false, NULL,NULL); entryres1->setText ("Hi!"); EntryResource *entryres2 = - layout->getResourceFactory()->createEntryResource (10, true, NULL); + layout->getResourceFactory()->createEntryResource (10, true, NULL, + "password field!"); MultiLineTextResource *textres = layout->getResourceFactory()->createMultiLineTextResource (15,3); RadioButtonResource *radiores1 = |