summaryrefslogtreecommitdiff
path: root/render
diff options
context:
space:
mode:
authorMichael Drake <tlsa@netsurf-browser.org>2013-02-06 22:39:45 +0000
committerMichael Drake <tlsa@netsurf-browser.org>2013-02-06 22:39:45 +0000
commit762e1aad733c4d56edbb85c7b21b0951d8f759f2 (patch)
tree71305c5b65e055c907be507b6242285842bea72f /render
parent008cdb42d718ed1e1e61c9c16e6aa22bc345d202 (diff)
downloadnetsurf-762e1aad733c4d56edbb85c7b21b0951d8f759f2.tar.gz
netsurf-762e1aad733c4d56edbb85c7b21b0951d8f759f2.tar.bz2
First pass at getting html forms to use textarea widget.
(Input element types text & password, and textarea element.) Can edit and submit forms, but there are loads of issues.
Diffstat (limited to 'render')
-rw-r--r--render/box_construct.c164
-rw-r--r--render/box_textarea.c275
-rw-r--r--render/box_textarea.h44
-rw-r--r--render/form.c87
-rw-r--r--render/form.h12
-rw-r--r--render/html.c1
-rw-r--r--render/html.h1
-rw-r--r--render/html_forms.c3
-rw-r--r--render/html_interaction.c93
-rw-r--r--render/html_internal.h7
-rw-r--r--render/html_redraw.c20
-rw-r--r--render/layout.c15
12 files changed, 447 insertions, 275 deletions
diff --git a/render/box_construct.c b/render/box_construct.c
index 52c8cfee5..e5800edf8 100644
--- a/render/box_construct.c
+++ b/render/box_construct.c
@@ -38,6 +38,7 @@
#include "css/select.h"
#include "desktop/options.h"
#include "render/box.h"
+#include "render/box_textarea.h"
#include "render/form.h"
#include "render/html_internal.h"
#include "utils/corestrings.h"
@@ -111,7 +112,6 @@ static bool box_image(BOX_SPECIAL_PARAMS);
static bool box_textarea(BOX_SPECIAL_PARAMS);
static bool box_select(BOX_SPECIAL_PARAMS);
static bool box_input(BOX_SPECIAL_PARAMS);
-static bool box_input_text(BOX_SPECIAL_PARAMS, bool password);
static bool box_button(BOX_SPECIAL_PARAMS);
static bool box_frameset(BOX_SPECIAL_PARAMS);
static bool box_create_frameset(struct content_html_frames *f, dom_node *n,
@@ -2497,6 +2497,38 @@ bool box_iframe(BOX_SPECIAL_PARAMS)
/**
+ * Helper function for adding textarea widget to box.
+ *
+ * This is a load of hacks to ensure boxes replaced with textareas
+ * can be handled by the layout code.
+ */
+
+static bool box_input_text(html_content *html, struct box *box,
+ struct dom_node *node)
+{
+ struct box *inline_container, *inline_box;
+
+ box->type = BOX_INLINE_BLOCK;
+
+ inline_container = box_create(NULL, 0, false, 0, 0, 0, 0, html->bctx);
+ if (!inline_container)
+ return false;
+ inline_container->type = BOX_INLINE_CONTAINER;
+ inline_box = box_create(NULL, box->style, false, 0, 0, box->title, 0,
+ html->bctx);
+ if (!inline_box)
+ return false;
+ inline_box->type = BOX_TEXT;
+ inline_box->text = talloc_strdup(html->bctx, "");
+
+ box_add_child(inline_container, inline_box);
+ box_add_child(box, inline_container);
+
+ return box_textarea_create_textarea(html, box, node);
+}
+
+
+/**
* Form control [17.4].
*/
@@ -2518,7 +2550,7 @@ bool box_input(BOX_SPECIAL_PARAMS)
if (type && dom_string_caseless_lwc_isequal(type,
corestring_lwc_password)) {
- if (box_input_text(n, content, box, 0, true) == false)
+ if (box_input_text(content, box, n) == false)
goto no_memory;
} else if (type && dom_string_caseless_lwc_isequal(type,
@@ -2620,7 +2652,7 @@ bool box_input(BOX_SPECIAL_PARAMS)
}
} else {
/* the default type is "text" */
- if (box_input_text(n, content, box, 0, false) == false)
+ if (box_input_text(content, box, n) == false)
goto no_memory;
}
@@ -2639,52 +2671,6 @@ no_memory:
/**
- * Helper function for box_input().
- */
-
-bool box_input_text(BOX_SPECIAL_PARAMS, bool password)
-{
- struct box *inline_container, *inline_box;
-
- box->type = BOX_INLINE_BLOCK;
-
- inline_container = box_create(NULL, 0, false, 0, 0, 0, 0, content->bctx);
- if (!inline_container)
- return false;
- inline_container->type = BOX_INLINE_CONTAINER;
- inline_box = box_create(NULL, box->style, false, 0, 0, box->title, 0,
- content->bctx);
- if (!inline_box)
- return false;
- inline_box->type = BOX_TEXT;
- if (password) {
- inline_box->length = strlen(box->gadget->value);
- inline_box->text = talloc_array(content->bctx, char,
- inline_box->length + 1);
- if (!inline_box->text)
- return false;
- memset(inline_box->text, '*', inline_box->length);
- inline_box->text[inline_box->length] = '\0';
- } else {
- /* replace spaces/TABs with hard spaces to prevent line
- * wrapping */
- char *text = cnv_space2nbsp(box->gadget->value);
- if (!text)
- return false;
- inline_box->text = talloc_strdup(content->bctx, text);
- free(text);
- if (!inline_box->text)
- return false;
- inline_box->length = strlen(inline_box->text);
- }
- box_add_child(inline_container, inline_box);
- box_add_child(box, inline_container);
-
- return true;
-}
-
-
-/**
* Push button [17.5].
*/
@@ -2924,90 +2910,16 @@ no_memory:
bool box_textarea(BOX_SPECIAL_PARAMS)
{
- /* A textarea is an INLINE_BLOCK containing a single INLINE_CONTAINER,
- * which contains the text as runs of TEXT separated by BR. There is
- * at least one TEXT. The first and last boxes are TEXT.
- * Consecutive BR may not be present. These constraints are satisfied
- * by using a 0-length TEXT for blank lines. */
-
- const char *current;
- dom_string *area_data = NULL;
- dom_exception err;
- struct box *inline_container, *inline_box, *br_box;
- char *s;
- size_t len;
-
- box->type = BOX_INLINE_BLOCK;
+ /* Get the form_control for the DOM node */
box->gadget = html_forms_get_control_for_node(content->forms, n);
if (box->gadget == NULL)
return false;
- box->gadget->box = box;
- inline_container = box_create(NULL, 0, false, 0, 0, box->title, 0,
- content->bctx);
- if (inline_container == NULL)
- return false;
- inline_container->type = BOX_INLINE_CONTAINER;
- box_add_child(box, inline_container);
+ box->gadget->box = box;
- err = dom_node_get_text_content(n, &area_data);
- if (err != DOM_NO_ERR)
+ if (!box_input_text(content, box, n))
return false;
- if (area_data != NULL) {
- current = dom_string_data(area_data);
- } else {
- /* No content, or failed reading it: use a blank string */
- current = "";
- }
-
- while (true) {
- /* BOX_TEXT */
- len = strcspn(current, "\r\n");
- s = talloc_strndup(content->bctx, current, len);
- if (s == NULL) {
- if (area_data != NULL)
- dom_string_unref(area_data);
- return false;
- }
-
- inline_box = box_create(NULL, box->style, false, 0, 0,
- box->title, 0, content->bctx);
- if (inline_box == NULL) {
- if (area_data != NULL)
- dom_string_unref(area_data);
- return false;
- }
- inline_box->type = BOX_TEXT;
- inline_box->text = s;
- inline_box->length = len;
- box_add_child(inline_container, inline_box);
-
- current += len;
- if (current[0] == 0)
- /* finished */
- break;
-
- /* BOX_BR */
- br_box = box_create(NULL, box->style, false, 0, 0, box->title,
- 0, content->bctx);
- if (br_box == NULL) {
- if (area_data != NULL)
- dom_string_unref(area_data);
- return false;
- }
- br_box->type = BOX_BR;
- box_add_child(inline_container, br_box);
-
- if (current[0] == '\r' && current[1] == '\n')
- current += 2;
- else
- current++;
- }
-
- if (area_data != NULL)
- dom_string_unref(area_data);
-
*convert_children = false;
return true;
}
diff --git a/render/box_textarea.c b/render/box_textarea.c
new file mode 100644
index 000000000..3d2455f7c
--- /dev/null
+++ b/render/box_textarea.c
@@ -0,0 +1,275 @@
+/*
+ * Copyright 2013 Michael Drake <tlsa@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Box tree treeview box replacement (implementation).
+ */
+
+#include <dom/dom.h>
+
+#include "desktop/browser.h"
+#include "desktop/textarea.h"
+#include "desktop/textinput.h"
+#include "render/box_textarea.h"
+#include "render/font.h"
+#include "render/form.h"
+
+
+static bool box_textarea_browser_caret_callback(struct browser_window *bw,
+ uint32_t key, void *p1, void *p2)
+{
+ struct box *box = p1;
+ struct form_control *gadget = box->gadget;
+ struct textarea *ta = gadget->data.text.ta;
+ struct form* form = box->gadget->form;
+ html_content *html = p2;
+ struct content *c = (struct content *) html;
+
+ assert(ta != NULL);
+
+ if (gadget->type != GADGET_TEXTAREA) {
+ switch (key) {
+ case KEY_NL:
+ case KEY_CR:
+ if (form)
+ form_submit(content_get_url(c), html->bw,
+ form, 0);
+ return true;
+
+ case KEY_TAB:
+ {
+ struct form_control *next_input;
+ /* Find next text entry field that is actually
+ * displayed (i.e. has an associated box) */
+ for (next_input = gadget->next;
+ next_input &&
+ ((next_input->type != GADGET_TEXTBOX &&
+ next_input->type != GADGET_TEXTAREA &&
+ next_input->type != GADGET_PASSWORD) ||
+ !next_input->box);
+ next_input = next_input->next)
+ ;
+ if (!next_input)
+ return true;
+
+ textarea_set_caret(ta, -1);
+ textarea_set_caret(next_input->data.text.ta, 0);
+ }
+ return true;
+
+ case KEY_SHIFT_TAB:
+ {
+ struct form_control *prev_input;
+ /* Find previous text entry field that is actually
+ * displayed (i.e. has an associated box) */
+ for (prev_input = gadget->prev;
+ prev_input &&
+ ((prev_input->type != GADGET_TEXTBOX &&
+ prev_input->type != GADGET_TEXTAREA &&
+ prev_input->type != GADGET_PASSWORD) ||
+ !prev_input->box);
+ prev_input = prev_input->prev)
+ ;
+ if (!prev_input)
+ return true;
+
+ textarea_set_caret(ta, -1);
+ textarea_set_caret(prev_input->data.text.ta, 0);
+ }
+ return true;
+
+ default:
+ /* Pass to textarea widget */
+ break;
+ }
+ }
+
+ return textarea_keypress(ta, key);
+}
+
+
+static void box_textarea_browser_move_callback(struct browser_window *bw,
+ void *p1, void *p2)
+{
+}
+
+
+static bool box_textarea_browser_paste_callback(struct browser_window *bw,
+ const char *utf8, unsigned utf8_len, bool last,
+ void *p1, void *p2)
+{
+ printf("AWWOOOOOGA!\n");
+ return true;
+}
+
+
+/**
+ * Callback for html form textareas.
+ */
+static void box_textarea_callback(void *data, struct textarea_msg *msg)
+{
+ struct form_textarea_data *d = data;
+ struct content *c = (struct content *)d->html;
+ struct html_content *html = d->html;
+ struct form_control *gadget = d->gadget;
+ struct box *box = gadget->box;
+ union content_msg_data msg_data;
+
+ switch (msg->type) {
+ case TEXTAREA_MSG_DRAG_REPORT:
+ if (msg->data.drag == TEXTAREA_DRAG_NONE) {
+ /* Textarea drag finished */
+ html->textarea = NULL;
+
+ browser_window_set_drag_type(html->bw,
+ DRAGGING_NONE, NULL);
+
+ msg_data.pointer = BROWSER_POINTER_AUTO;
+ content_broadcast(c, CONTENT_MSG_POINTER, msg_data);
+ } else {
+ /* Textarea drag started */
+ struct rect rect = {
+ .x0 = INT_MIN,
+ .y0 = INT_MIN,
+ .x1 = INT_MAX,
+ .y1 = INT_MAX
+ };
+ browser_drag_type bdt;
+
+ if (msg->data.drag == TEXTAREA_DRAG_SCROLLBAR)
+ bdt = DRAGGING_CONTENT_TEXTAREA_SCROLLBAR;
+ else
+ bdt = DRAGGING_CONTENT_TEXTAREA_SELECTION;
+
+ browser_window_set_drag_type(html->bw, bdt, &rect);
+
+ html->textarea = msg->ta;
+ }
+ break;
+
+ case TEXTAREA_MSG_REDRAW_REQUEST:
+ /* Redraw the textarea */
+ /* TODO: don't redraw whole box, just the part asked for */
+ html__redraw_a_box(html, box);
+ break;
+
+ case TEXTAREA_MSG_MOVED_CARET:
+ if (html->bw == NULL)
+ break;
+
+ if (msg->data.caret.hidden) {
+ browser_window_remove_caret(html->bw);
+ } else {
+ browser_window_place_caret(html->bw,
+ msg->data.caret.x, msg->data.caret.y,
+ msg->data.caret.height,
+ box_textarea_browser_caret_callback,
+ box_textarea_browser_paste_callback,
+ box_textarea_browser_move_callback,
+ box, html);
+ }
+ break;
+ }
+}
+
+
+/* Exported interface, documented in box_textarea.h */
+bool box_textarea_create_textarea(html_content *html,
+ struct box *box, struct dom_node *node)
+{
+ dom_string *dom_text = NULL;
+ dom_exception err;
+ textarea_setup ta_setup;
+ textarea_flags ta_flags;
+ plot_font_style_t fstyle;
+ struct form_control *gadget = box->gadget;
+ const char *text;
+
+ /** TODO: Read only textarea */
+
+ assert(gadget != NULL);
+ assert(gadget->type == GADGET_TEXTAREA ||
+ gadget->type == GADGET_TEXTBOX ||
+ gadget->type == GADGET_PASSWORD);
+
+ if (gadget->type == GADGET_TEXTAREA) {
+ ta_flags = TEXTAREA_MULTILINE;
+
+ /* Get the textarea's initial content */
+ err = dom_node_get_text_content(node, &dom_text);
+ if (err != DOM_NO_ERR)
+ return false;
+
+ } else {
+ dom_html_input_element *input = (dom_html_input_element *) node;
+
+ if (gadget->type == GADGET_PASSWORD)
+ ta_flags = TEXTAREA_PASSWORD;
+ else
+ ta_flags = TEXTAREA_DEFAULT;
+
+ /* Get initial text */
+ err = dom_html_input_element_get_value(input, &dom_text);
+ if (err != DOM_NO_ERR)
+ return false;
+ }
+
+ if (dom_text != NULL) {
+ text = dom_string_data(dom_text);
+ } else {
+ /* No initial text, or failed reading it;
+ * use a blank string */
+ text = "";
+ }
+
+ gadget->data.text.data.html = html;
+ gadget->data.text.data.gadget = gadget;
+
+ font_plot_style_from_css(gadget->box->style, &fstyle);
+
+ /* Reset to correct values by layout */
+ ta_setup.width = 200;
+ ta_setup.height = 20;
+ ta_setup.pad_top = 4;
+ ta_setup.pad_right = 4;
+ ta_setup.pad_bottom = 4;
+ ta_setup.pad_left = 4;
+ ta_setup.border_width = 0;
+ ta_setup.border_col = 0x000000;
+ ta_setup.selected_text = 0xffffff;
+ ta_setup.selected_bg = 0x000000;
+ ta_setup.text = fstyle;
+ ta_setup.text.foreground = 0x000000;
+ ta_setup.text.background = NS_TRANSPARENT;
+
+ /* Hand reference to dom text over to gadget */
+ gadget->data.text.initial = dom_text;
+
+ gadget->data.text.ta = textarea_create(ta_flags, &ta_setup,
+ box_textarea_callback, &gadget->data.text.data);
+
+ if (gadget->data.text.ta == NULL) {
+ return false;
+ }
+
+ if (!textarea_set_text(gadget->data.text.ta, text))
+ return false;
+
+ return true;
+}
+
diff --git a/render/box_textarea.h b/render/box_textarea.h
new file mode 100644
index 000000000..30414e816
--- /dev/null
+++ b/render/box_textarea.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2013 Michael Drake <tlsa@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Box tree treeview box replacement (interface).
+ */
+
+
+
+#ifndef _NETSURF_RENDER_BOX_TEXTAREA_H_
+#define _NETSURF_RENDER_BOX_TEXTAREA_H_
+
+
+#include "render/box.h"
+#include "render/html_internal.h"
+
+struct dom_node;
+
+/**
+ * Create textarea widget for a form element
+ *
+ * \param html html content object
+ * \param box box with gadget to be given textarea widget
+ * \param node DOM node for form element
+ */
+bool box_textarea_create_textarea(html_content *html,
+ struct box *box, struct dom_node *node);
+
+#endif
diff --git a/render/form.c b/render/form.c
index 42e76e1f2..c2819b479 100644
--- a/render/form.c
+++ b/render/form.c
@@ -43,6 +43,7 @@
#include "desktop/plot_style.h"
#include "desktop/plotters.h"
#include "desktop/scrollbar.h"
+#include "desktop/textarea.h"
#include "render/box.h"
#include "render/font.h"
#include "render/form.h"
@@ -85,7 +86,6 @@ static plot_font_style_t plot_fstyle_entry = {
.foreground = 0x000000,
};
-static char *form_textarea_value(struct form_control *textarea);
static char *form_acceptable_charset(struct form *form);
static char *form_encode_item(const char *item, const char *charset,
const char *fallback);
@@ -252,6 +252,17 @@ void form_free_control(struct form_control *control)
form_free_select_menu(control);
}
+ if (control->type == GADGET_TEXTAREA ||
+ control->type == GADGET_TEXTBOX ||
+ control->type == GADGET_PASSWORD) {
+
+ if (control->data.text.initial != NULL)
+ dom_string_unref(control->data.text.initial);
+
+ if (control->data.text.ta != NULL)
+ textarea_destroy(control->data.text.ta);
+ }
+
free(control);
}
@@ -350,8 +361,6 @@ bool form_successful_controls(struct form *form,
switch (control->type) {
case GADGET_HIDDEN:
- case GADGET_TEXTBOX:
- case GADGET_PASSWORD:
if (control->value)
value = ENCODE_ITEM(control->value);
else
@@ -416,17 +425,26 @@ bool form_successful_controls(struct form *form,
continue;
break;
+ case GADGET_TEXTBOX:
+ case GADGET_PASSWORD:
case GADGET_TEXTAREA:
- {
+ {
char *v2;
+ int ta_len = textarea_get_text(
+ control->data.text.ta,
+ NULL, 0);
- /* textarea */
- value = form_textarea_value(control);
+ value = malloc(ta_len);
if (!value) {
LOG(("failed handling textarea"));
goto no_memory;
}
- if (value[0] == 0) {
+ textarea_get_text(control->data.text.ta,
+ value, ta_len);
+
+ if (control->type == GADGET_TEXTAREA &&
+ value[0] == '\0') {
+ /* Textarea not submitted if empty */
free(value);
continue;
}
@@ -440,7 +458,7 @@ bool form_successful_controls(struct form *form,
free(value);
value = v2;
- }
+ }
break;
case GADGET_IMAGE: {
@@ -617,59 +635,6 @@ no_memory:
/**
- * Find the value for a textarea control.
- *
- * \param textarea control of type GADGET_TEXTAREA
- * \return the value as a UTF-8 string on heap, or 0 on memory exhaustion
- */
-char *form_textarea_value(struct form_control *textarea)
-{
- unsigned int len = 0;
- char *value, *s;
- struct box *text_box;
-
- /* Textarea may have no associated box if styled with display: none */
- if (textarea->box == NULL) {
- /* Return the empty string: caller treats this as a
- * non-successful control. */
- return strdup("");
- }
-
- /* find required length */
- for (text_box = textarea->box->children->children; text_box;
- text_box = text_box->next) {
- if (text_box->type == BOX_TEXT)
- len += text_box->length + 1;
- else /* BOX_BR */
- len += 2;
- }
-
- /* construct value */
- s = value = malloc(len + 1);
- if (!s)
- return NULL;
-
- for (text_box = textarea->box->children->children; text_box;
- text_box = text_box->next) {
- if (text_box->type == BOX_TEXT) {
- strncpy(s, text_box->text, text_box->length);
- s += text_box->length;
- if (text_box->next && text_box->next->type != BOX_BR)
- /* only add space if this isn't
- * the last box on a line (or in the area) */
- *s++ = ' ';
- } else { /* BOX_BR */
- *s++ = '\r';
- *s++ = '\n';
- }
- }
- *s = 0;
-
- return value;
-}
-
-
-/**
* Encode controls using application/x-www-form-urlencoded.
*
* \param form form to which successful controls relate
diff --git a/render/form.h b/render/form.h
index 67372d5d5..b5f6a7e2c 100644
--- a/render/form.h
+++ b/render/form.h
@@ -34,6 +34,7 @@ struct form_control;
struct form_option;
struct form_select_menu;
struct html_content;
+struct dom_string;
/** Form submit method. */
typedef enum {
@@ -73,6 +74,12 @@ typedef enum {
GADGET_BUTTON
} form_control_type;
+/** Data for textarea */
+struct form_textarea_data {
+ struct html_content *html;
+ struct form_control *gadget;
+};
+
/** Form control. */
struct form_control {
void *node; /**< Corresponding DOM node */
@@ -111,6 +118,11 @@ struct form_control {
struct form_option *current;
struct form_select_menu *menu;
} select;
+ struct {
+ struct textarea *ta;
+ struct dom_string *initial;
+ struct form_textarea_data data;
+ } text; /**< input type=text or textarea */
} data;
struct form_control *prev; /**< Previous control in this form */
diff --git a/render/html.c b/render/html.c
index 3e26928fd..85e377095 100644
--- a/render/html.c
+++ b/render/html.c
@@ -344,6 +344,7 @@ html_create_html_data(html_content *c, const http_parameter *params)
c->page = NULL;
c->font_func = &nsfont;
c->scrollbar = NULL;
+ c->textarea = NULL;
c->scripts_count = 0;
c->scripts = NULL;
c->jscontext = NULL;
diff --git a/render/html.h b/render/html.h
index e11fc76ac..a9f7967f6 100644
--- a/render/html.h
+++ b/render/html.h
@@ -46,6 +46,7 @@ struct http_parameter;
struct imagemap;
struct object_params;
struct plotters;
+struct textarea;
struct scrollbar;
struct scrollbar_msg_data;
struct search_context;
diff --git a/render/html_forms.c b/render/html_forms.c
index d1223819a..c80edc6bb 100644
--- a/render/html_forms.c
+++ b/render/html_forms.c
@@ -523,7 +523,8 @@ invent_fake_gadget(dom_node *node)
}
/* documented in html_internal.h */
-struct form_control *html_forms_get_control_for_node(struct form *forms, dom_node *node)
+struct form_control *html_forms_get_control_for_node(struct form *forms,
+ dom_node *node)
{
struct form *f;
struct form_control *ctl = NULL;
diff --git a/render/html_interaction.c b/render/html_interaction.c
index d22869edc..a685241bc 100644
--- a/render/html_interaction.c
+++ b/render/html_interaction.c
@@ -35,6 +35,7 @@
#include "desktop/options.h"
#include "desktop/scrollbar.h"
#include "desktop/selection.h"
+#include "desktop/textarea.h"
#include "desktop/textinput.h"
#include "render/box.h"
#include "render/font.h"
@@ -592,94 +593,18 @@ void html_mouse_action(struct content *c, struct browser_window *bw,
status = messages_get("FormBadSubmit");
}
break;
- case GADGET_TEXTAREA:
- status = messages_get("FormTextarea");
- pointer = get_pointer_shape(gadget_box, false);
-
- if (mouse & (BROWSER_MOUSE_PRESS_1 |
- BROWSER_MOUSE_PRESS_2)) {
- if (text_box && selection_root(&html->sel) !=
- gadget_box)
- selection_init(&html->sel, gadget_box);
-
- textinput_textarea_click(c, mouse,
- gadget_box,
- gadget_box_x,
- gadget_box_y,
- x - gadget_box_x,
- y - gadget_box_y);
- }
-
- if (text_box) {
- int pixel_offset;
- size_t idx;
-
- font_plot_style_from_css(text_box->style,
- &fstyle);
-
- nsfont.font_position_in_string(&fstyle,
- text_box->text,
- text_box->length,
- x - gadget_box_x - text_box->x,
- &idx,
- &pixel_offset);
-
- selection_click(&html->sel, mouse,
- text_box->byte_offset + idx);
-
- if (selection_dragging(&html->sel)) {
- browser_window_set_drag_type(bw,
- DRAGGING_SELECTION,
- NULL);
- status = messages_get("Selecting");
- }
- }
- else if (mouse & BROWSER_MOUSE_PRESS_1)
- selection_clear(&html->sel, true);
- break;
case GADGET_TEXTBOX:
case GADGET_PASSWORD:
- status = messages_get("FormTextbox");
- pointer = get_pointer_shape(gadget_box, false);
-
- if ((mouse & BROWSER_MOUSE_PRESS_1) &&
- !(mouse & (BROWSER_MOUSE_MOD_1 |
- BROWSER_MOUSE_MOD_2))) {
- textinput_input_click(c,
- gadget_box,
- gadget_box_x,
- gadget_box_y,
- x - gadget_box_x,
- y - gadget_box_y);
- }
- if (text_box) {
- int pixel_offset;
- size_t idx;
-
- if (mouse & (BROWSER_MOUSE_DRAG_1 |
- BROWSER_MOUSE_DRAG_2))
- selection_init(&html->sel, gadget_box);
-
- font_plot_style_from_css(text_box->style,
- &fstyle);
-
- nsfont.font_position_in_string(&fstyle,
- text_box->text,
- text_box->length,
- x - gadget_box_x - text_box->x,
- &idx,
- &pixel_offset);
+ case GADGET_TEXTAREA:
+ if (gadget->type == GADGET_TEXTAREA)
+ status = messages_get("FormTextarea");
+ else
+ status = messages_get("FormTextbox");
- selection_click(&html->sel, mouse,
- text_box->byte_offset + idx);
+ pointer = get_pointer_shape(gadget_box, false);
- if (selection_dragging(&html->sel))
- browser_window_set_drag_type(bw,
- DRAGGING_SELECTION,
- NULL);
- }
- else if (mouse & BROWSER_MOUSE_PRESS_1)
- selection_clear(&html->sel, true);
+ textarea_mouse_action(gadget->data.text.ta, mouse,
+ x - gadget_box_x, y - gadget_box_y);
break;
case GADGET_HIDDEN:
/* not possible: no box generated */
diff --git a/render/html_internal.h b/render/html_internal.h
index 53021a15a..d09121675 100644
--- a/render/html_internal.h
+++ b/render/html_internal.h
@@ -102,6 +102,10 @@ typedef struct html_content {
* scrollbar, or NULL when no scrollbar drags active */
struct scrollbar *scrollbar;
+ /** Textarea capturing all mouse events, updated to any active HTML
+ * textarea, or NULL when no textarea drags active */
+ struct textarea *textarea;
+
/** Open core-handled form SELECT menu,
* or NULL if none currently open. */
struct form_control *visible_select_menu;
@@ -162,7 +166,8 @@ bool html_scripts_exec(html_content *c);
/* in render/html_forms.c */
struct form *html_forms_get_forms(const char *docenc, dom_html_document *doc);
-struct form_control *html_forms_get_control_for_node(struct form *forms, dom_node *node);
+struct form_control *html_forms_get_control_for_node(struct form *forms,
+ dom_node *node);
/* Useful dom_string pointers */
struct dom_string;
diff --git a/render/html_redraw.c b/render/html_redraw.c
index e305b7b08..fed5ffdc4 100644
--- a/render/html_redraw.c
+++ b/render/html_redraw.c
@@ -41,6 +41,7 @@
#include "desktop/options.h"
#include "desktop/print.h"
#include "desktop/scrollbar.h"
+#include "desktop/textarea.h"
#include "image/bitmap.h"
#include "render/box.h"
#include "render/font.h"
@@ -2109,7 +2110,11 @@ bool html_redraw_box(const html_content *html, struct box *box,
bg_box->type != BOX_TEXT &&
bg_box->type != BOX_INLINE_END &&
(bg_box->type != BOX_INLINE || bg_box->object ||
- bg_box->flags & IFRAME || box->flags & REPLACE_DIM)) {
+ bg_box->flags & IFRAME || box->flags & REPLACE_DIM ||
+ (bg_box->gadget != NULL &&
+ (bg_box->gadget->type == GADGET_TEXTAREA ||
+ bg_box->gadget->type == GADGET_TEXTBOX ||
+ bg_box->gadget->type == GADGET_PASSWORD)))) {
/* find intersection of clip box and border edge */
struct rect p;
p.x0 = x - border_left < r.x0 ? r.x0 : x - border_left;
@@ -2154,7 +2159,11 @@ bool html_redraw_box(const html_content *html, struct box *box,
if (box->style && box->type != BOX_TEXT &&
box->type != BOX_INLINE_END &&
(box->type != BOX_INLINE || box->object ||
- box->flags & IFRAME || box->flags & REPLACE_DIM) &&
+ box->flags & IFRAME || box->flags & REPLACE_DIM ||
+ (box->gadget != NULL &&
+ (box->gadget->type == GADGET_TEXTAREA ||
+ box->gadget->type == GADGET_TEXTBOX ||
+ box->gadget->type == GADGET_PASSWORD))) &&
(border_top || border_right ||
border_bottom || border_left)) {
if (!html_redraw_borders(box, x_parent, y_parent,
@@ -2398,6 +2407,13 @@ bool html_redraw_box(const html_content *html, struct box *box,
current_background_color, ctx))
return false;
+ } else if (box->gadget &&
+ (box->gadget->type == GADGET_TEXTAREA ||
+ box->gadget->type == GADGET_PASSWORD ||
+ box->gadget->type == GADGET_TEXTBOX)) {
+ textarea_redraw(box->gadget->data.text.ta,
+ x, y, current_background_color, &r, ctx);
+
} else if (box->text) {
if (!html_redraw_text_box(html, box, x, y, &r, scale,
current_background_color, ctx))
diff --git a/render/layout.c b/render/layout.c
index 331e1efdb..95903a2bb 100644
--- a/render/layout.c
+++ b/render/layout.c
@@ -46,6 +46,7 @@
#include "content/content_protected.h"
#include "desktop/options.h"
#include "desktop/scrollbar.h"
+#include "desktop/textarea.h"
#include "render/box.h"
#include "render/font.h"
#include "render/form.h"
@@ -650,6 +651,20 @@ bool layout_block_context(struct box *block, int viewport_height,
layout_apply_minmax_height(block, NULL);
}
+ if (block->gadget &&
+ (block->gadget->type == GADGET_TEXTAREA ||
+ block->gadget->type == GADGET_PASSWORD ||
+ block->gadget->type == GADGET_TEXTBOX)) {
+ int ta_width = block->padding[LEFT] + block->width +
+ block->padding[RIGHT];
+ int ta_height = block->padding[TOP] + block->height +
+ block->padding[BOTTOM];
+ textarea_set_layout(block->gadget->data.text.ta,
+ ta_width, ta_height,
+ block->padding[TOP], block->padding[RIGHT],
+ block->padding[BOTTOM], block->padding[LEFT]);
+ }
+
return true;
}