NetSurf
box_textarea.c
Go to the documentation of this file.
1/*
2 * Copyright 2013 Michael Drake <tlsa@netsurf-browser.org>
3 *
4 * This file is part of NetSurf, http://www.netsurf-browser.org/
5 *
6 * NetSurf is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * NetSurf is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19/**
20 * \file
21 * Box tree treeview box replacement (implementation).
22 */
23
24#include <string.h>
25#include <dom/dom.h>
26
27#include "utils/config.h"
28#include "utils/log.h"
29#include "utils/messages.h"
30#include "netsurf/keypress.h"
31#include "netsurf/misc.h"
32#include "desktop/textarea.h"
33
34#include "html/private.h"
35#include "html/interaction.h"
36#include "html/box.h"
37#include "html/box_inspect.h"
38#include "html/box_textarea.h"
39#include "html/font.h"
40#include "html/form_internal.h"
41
42
43nserror box_textarea_keypress(html_content *html, struct box *box, uint32_t key)
44{
45 struct form_control *gadget = box->gadget;
46 struct textarea *ta = gadget->data.text.ta;
47 struct form* form = box->gadget->form;
48 struct content *c = (struct content *)html;
49 nserror res = NSERROR_OK;
50
51 assert(ta != NULL);
52
53 if (gadget->type == GADGET_TEXTAREA) {
54 if (textarea_keypress(ta, key)) {
55 return NSERROR_OK;
56 } else {
57 return NSERROR_INVALID;
58 }
59 }
60
61 /* non textarea input */
62 switch (key) {
63 case NS_KEY_NL:
64 case NS_KEY_CR:
65 if (form) {
67 html->bw,
68 form,
69 NULL);
70 }
71 break;
72
73 case NS_KEY_TAB:
74 {
75 struct form_control *next_input;
76 /* Find next text entry field that is actually
77 * displayed (i.e. has an associated box) */
78 for (next_input = gadget->next;
79 next_input &&
80 ((next_input->type != GADGET_TEXTBOX &&
81 next_input->type != GADGET_TEXTAREA &&
82 next_input->type != GADGET_PASSWORD) ||
83 !next_input->box);
84 next_input = next_input->next)
85 ;
86
87 if (next_input != NULL) {
89 textarea_set_caret(next_input->data.text.ta, 0);
90 }
91 }
92 break;
93
95 {
96 struct form_control *prev_input;
97 /* Find previous text entry field that is actually
98 * displayed (i.e. has an associated box) */
99 for (prev_input = gadget->prev;
100 prev_input &&
101 ((prev_input->type != GADGET_TEXTBOX &&
102 prev_input->type != GADGET_TEXTAREA &&
103 prev_input->type != GADGET_PASSWORD) ||
104 !prev_input->box);
105 prev_input = prev_input->prev)
106 ;
107
108 if (prev_input != NULL) {
110 textarea_set_caret(prev_input->data.text.ta, 0);
111 }
112 }
113 break;
114
115 default:
116 /* Pass to textarea widget */
117 if (!textarea_keypress(ta, key)) {
118 res = NSERROR_INVALID;
119 }
120 break;
121 }
122
123 return res;
124}
125
126
127/**
128 * Callback for html form textareas.
129 */
130static void box_textarea_callback(void *data, struct textarea_msg *msg)
131{
132 struct form_textarea_data *d = data;
133 struct form_control *gadget = d->gadget;
134 struct html_content *html = d->gadget->html;
135 struct box *box = gadget->box;
136
137 switch (msg->type) {
139 if (msg->data.drag == TEXTAREA_DRAG_NONE) {
140 /* Textarea drag finished */
141 html_drag_type drag_type = HTML_DRAG_NONE;
142 union html_drag_owner drag_owner;
143 drag_owner.no_owner = true;
144
145 html_set_drag_type(html, drag_type, drag_owner,
146 NULL);
147 } else {
148 /* Textarea drag started */
149 struct rect rect = {
150 .x0 = INT_MIN,
151 .y0 = INT_MIN,
152 .x1 = INT_MAX,
153 .y1 = INT_MAX
154 };
155 union html_drag_owner drag_owner;
156 drag_owner.textarea = box;
157
158 switch (msg->data.drag) {
162 drag_owner,
163 &rect);
164 break;
165
169 drag_owner,
170 &rect);
171 break;
172
173 default:
174 NSLOG(netsurf, INFO,
175 "Drag type %d not handled.",
176 msg->data.drag);
177 /* This is a logic faliure in the
178 * front end code so abort.
179 */
180 assert(0);
181 break;
182 }
183 }
184 break;
185
187 {
188 /* Request redraw of the required textarea rectangle */
189 int x, y;
190
191 if (html->reflowing == true) {
192 /* Can't redraw during layout, and it will
193 * be redrawn after layout anyway. */
194 break;
195 }
196
197 box_coords(box, &x, &y);
198
199 content__request_redraw((struct content *)html,
200 x + msg->data.redraw.x0,
201 y + msg->data.redraw.y0,
202 msg->data.redraw.x1 - msg->data.redraw.x0,
203 msg->data.redraw.y1 - msg->data.redraw.y0);
204 }
205 break;
206
208 if (msg->data.selection.have_selection) {
209 /* Textarea now has a selection */
210 union html_selection_owner sel_owner;
211 sel_owner.textarea = box;
212
214 sel_owner,
216 } else {
217 /* The textarea now has no selection */
218 union html_selection_owner sel_owner;
219 sel_owner.none = true;
220
222 sel_owner, true);
223 }
224 break;
225
227 if (html->bw == NULL)
228 break;
229
230 if (msg->data.caret.type == TEXTAREA_CARET_HIDE) {
231 union html_focus_owner focus_owner;
232 focus_owner.textarea = box;
234 focus_owner, true, 0, 0, 0, NULL);
235 } else {
236 union html_focus_owner focus_owner;
237 focus_owner.textarea = box;
239 focus_owner, false,
240 msg->data.caret.pos.x,
241 msg->data.caret.pos.y,
242 msg->data.caret.pos.height,
243 msg->data.caret.pos.clip);
244 }
245 break;
246
250 msg->data.modified.len));
251 break;
252 }
253}
254
255
256/* Exported interface, documented in box_textarea.h */
258 struct box *box, struct dom_node *node)
259{
260 dom_string *dom_text = NULL;
261 dom_exception err;
262 textarea_setup ta_setup;
263 textarea_flags ta_flags;
264 plot_font_style_t fstyle = {
266 .size = 10 * PLOT_STYLE_SCALE,
267 .weight = 400,
268 .flags = FONTF_NONE,
269 .background = 0,
270 .foreground = 0,
271 };
272 bool read_only = false;
273 bool disabled = false;
274 struct form_control *gadget = box->gadget;
275 const char *text;
276
277 assert(gadget != NULL);
278 assert(gadget->type == GADGET_TEXTAREA ||
279 gadget->type == GADGET_TEXTBOX ||
280 gadget->type == GADGET_PASSWORD);
281
282 if (gadget->type == GADGET_TEXTAREA) {
283 dom_html_text_area_element *textarea =
284 (dom_html_text_area_element *) node;
285 ta_flags = TEXTAREA_MULTILINE;
286
287 err = dom_html_text_area_element_get_read_only(
288 textarea, &read_only);
289 if (err != DOM_NO_ERR)
290 return false;
291
292 err = dom_html_text_area_element_get_disabled(
294 if (err != DOM_NO_ERR)
295 return false;
296
297 /* Get the textarea's initial content */
298 err = dom_html_text_area_element_get_value(textarea, &dom_text);
299 if (err != DOM_NO_ERR)
300 return false;
301
302 } else {
303 dom_html_input_element *input = (dom_html_input_element *) node;
304
305 err = dom_html_input_element_get_read_only(
306 input, &read_only);
307 if (err != DOM_NO_ERR)
308 return false;
309
310 err = dom_html_input_element_get_disabled(
311 input, &disabled);
312 if (err != DOM_NO_ERR)
313 return false;
314
315 if (gadget->type == GADGET_PASSWORD)
316 ta_flags = TEXTAREA_PASSWORD;
317 else
318 ta_flags = TEXTAREA_DEFAULT;
319
320 /* Get initial text */
321 err = dom_html_input_element_get_value(input, &dom_text);
322 if (err != DOM_NO_ERR)
323 return false;
324 }
325
326 if (dom_text != NULL) {
327 text = dom_string_data(dom_text);
328 } else {
329 /* No initial text, or failed reading it;
330 * use a blank string */
331 text = "";
332 }
333
334 if (read_only || disabled)
335 ta_flags |= TEXTAREA_READONLY;
336
337 gadget->data.text.data.gadget = gadget;
338
339 /* Reset to correct values by layout */
340 ta_setup.width = 200;
341 ta_setup.height = 20;
342 ta_setup.pad_top = 4;
343 ta_setup.pad_right = 4;
344 ta_setup.pad_bottom = 4;
345 ta_setup.pad_left = 4;
346
347 /* Set remaining data */
348 ta_setup.border_width = 0;
349 ta_setup.border_col = 0x000000;
350 ta_setup.text = fstyle;
351 ta_setup.text.background = NS_TRANSPARENT;
352 /* Make selected text either black or white, as gives greatest contrast
353 * with background colour. */
354 ta_setup.selected_bg = fstyle.foreground;
356
357 /* Hand reference to dom text over to gadget */
358 gadget->data.text.initial = dom_text;
359
360 gadget->data.text.ta = textarea_create(ta_flags, &ta_setup,
361 box_textarea_callback, &gadget->data.text.data);
362
363 if (gadget->data.text.ta == NULL) {
364 return false;
365 }
366
367 if (!textarea_set_text(gadget->data.text.ta, text))
368 return false;
369
370 return true;
371}
Box interface.
void box_coords(struct box *box, int *x, int *y)
Find the absolute coordinates of a box.
Definition: box_inspect.c:549
HTML Box tree inspection interface.
bool box_textarea_create_textarea(html_content *html, struct box *box, struct dom_node *node)
Create textarea widget for a form element.
Definition: box_textarea.c:257
nserror box_textarea_keypress(html_content *html, struct box *box, uint32_t key)
Handle form textarea keypress input.
Definition: box_textarea.c:43
static void box_textarea_callback(void *data, struct textarea_msg *msg)
Callback for html form textareas.
Definition: box_textarea.c:130
Box tree treeview box replacement (interface).
char * strndup(const char *s, size_t n)
Duplicate up to n characters of a string.
Definition: utils.c:332
Internal font handling interfaces.
void content__request_redraw(struct content *c, int x, int y, int width, int height)
Request a redraw of an area of a content.
Definition: content.c:459
nsurl * content_get_url(struct content *c)
Retrieve URL associated with content.
Definition: content.c:1051
struct textarea * textarea_create(const textarea_flags flags, const textarea_setup *setup, textarea_client_callback callback, void *data)
Create a text area.
Definition: textarea.c:1852
bool textarea_set_caret(struct textarea *ta, int caret)
Set the caret's position.
Definition: textarea.c:2112
bool textarea_set_text(struct textarea *ta, const char *text)
Set the text in a text area, discarding any current text.
Definition: textarea.c:1995
bool textarea_keypress(struct textarea *ta, uint32_t key)
Key press handling for text areas.
Definition: textarea.c:2450
Single/Multi-line UTF-8 text area interface.
textarea_flags
Text area flags.
Definition: textarea.h:40
@ TEXTAREA_PASSWORD
Obscured display.
Definition: textarea.h:45
@ TEXTAREA_DEFAULT
Standard input.
Definition: textarea.h:41
@ TEXTAREA_READONLY
Non-editable.
Definition: textarea.h:43
@ TEXTAREA_MULTILINE
Multiline area.
Definition: textarea.h:42
@ TEXTAREA_DRAG_SCROLLBAR
Definition: textarea.h:54
@ TEXTAREA_DRAG_NONE
Definition: textarea.h:53
@ TEXTAREA_DRAG_SELECTION
Definition: textarea.h:55
@ TEXTAREA_MSG_SELECTION_REPORT
Textarea text selection presence.
Definition: textarea.h:64
@ TEXTAREA_MSG_TEXT_MODIFIED
Textarea text modified.
Definition: textarea.h:67
@ TEXTAREA_MSG_DRAG_REPORT
Textarea drag start/end report.
Definition: textarea.h:63
@ TEXTAREA_MSG_REDRAW_REQUEST
Textarea redraw request.
Definition: textarea.h:65
@ TEXTAREA_MSG_CARET_UPDATE
Textarea caret.
Definition: textarea.h:66
nserror
Enumeration of error codes.
Definition: errors.h:29
@ NSERROR_INVALID
Invalid data.
Definition: errors.h:49
@ NSERROR_OK
No error.
Definition: errors.h:30
void form_gadget_update_value(struct form_control *control, char *value)
Update gadget value.
Definition: form.c:2128
nserror form_submit(nsurl *page_url, struct browser_window *target, struct form *form, struct form_control *submit_button)
navigate browser window based on form submission.
Definition: form.c:2047
Interface to form handling functions internal to HTML content handler.
@ GADGET_TEXTAREA
Definition: form_internal.h:53
@ GADGET_PASSWORD
Definition: form_internal.h:55
@ GADGET_TEXTBOX
Definition: form_internal.h:49
Interface to platform-specific miscellaneous browser operation table.
void html_set_drag_type(html_content *html, html_drag_type drag_type, union html_drag_owner drag_owner, const struct rect *rect)
Set our drag status, and inform whatever owns the content.
Definition: interaction.c:1659
void html_set_focus(html_content *html, html_focus_type focus_type, union html_focus_owner focus_owner, bool hide_caret, int x, int y, int height, const struct rect *clip)
Set our input focus, and inform whatever owns the content.
Definition: interaction.c:1696
void html_set_selection(html_content *html, html_selection_type selection_type, union html_selection_owner selection_owner, bool read_only)
Set our selection status, and inform whatever owns the content.
Definition: interaction.c:1754
HTML content user interaction handling.
Interface to key press operations.
@ NS_KEY_SHIFT_TAB
Definition: keypress.h:39
@ NS_KEY_CR
Definition: keypress.h:40
@ NS_KEY_TAB
Definition: keypress.h:36
@ NS_KEY_NL
Definition: keypress.h:38
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:116
Localised message support (interface).
#define colour_to_bw_furthest(c0)
Definition: plot_style.h:193
@ FONTF_NONE
Definition: plot_style.h:102
@ PLOT_FONT_FAMILY_SANS_SERIF
Definition: plot_style.h:89
#define NS_TRANSPARENT
Transparent colour value.
Definition: plot_style.h:39
#define PLOT_STYLE_SCALE
Scaling factor for plot styles.
Definition: plot_style.h:45
Private data for text/html content.
html_drag_type
Definition: private.h:39
@ HTML_DRAG_TEXTAREA_SELECTION
Not own; drag in scrollbar widget.
Definition: private.h:43
@ HTML_DRAG_NONE
Definition: private.h:40
@ HTML_DRAG_TEXTAREA_SCROLLBAR
Not own; drag in textarea widget.
Definition: private.h:44
@ HTML_FOCUS_TEXTAREA
Focus belongs to textarea.
Definition: private.h:78
@ HTML_SELECTION_NONE
Definition: private.h:60
@ HTML_SELECTION_TEXTAREA
No selection.
Definition: private.h:61
Interface to utility string handling.
Node in box tree.
Definition: box.h:177
struct form_control * gadget
Form control data, or NULL if not a form control.
Definition: box.h:423
Content which corresponds to a single URL.
Form control.
Definition: form_internal.h:73
struct form_textarea_data data
struct form_control * prev
Previous control in this form.
form_control_type type
Type of control.
Definition: form_internal.h:79
struct form * form
Containing form.
Definition: form_internal.h:81
void * node
Corresponding DOM node.
Definition: form_internal.h:74
struct form_control * next
Next control in this form.
bool disabled
Whether control is disabled.
Definition: form_internal.h:87
struct textarea * ta
struct html_content * html
HTML content containing control.
Definition: form_internal.h:77
struct box * box
Box for control.
Definition: form_internal.h:89
Data for textarea.
Definition: form_internal.h:63
struct form_control * gadget
Definition: form_internal.h:64
HTML form.
Data specific to CONTENT_HTML.
Definition: private.h:93
struct browser_window * bw
Browser window containing this document, or NULL if not open.
Definition: private.h:177
bool reflowing
Whether a layout (reflow) is in progress.
Definition: private.h:122
Font style for plotting.
Definition: plot_style.h:111
plot_font_generic_family_t family
Generic family to plot with.
Definition: plot_style.h:118
colour foreground
Colour of text.
Definition: plot_style.h:123
colour background
Background colour to blend to, if appropriate.
Definition: plot_style.h:122
Rectangle coordinates.
Definition: types.h:40
int x0
Definition: types.h:41
int y0
Top left.
Definition: types.h:41
int x1
Definition: types.h:42
int y1
Bottom right.
Definition: types.h:42
textarea message
Definition: textarea.h:74
struct textarea_msg::@79::@81 caret
With _CARET_UPDATE.
unsigned int len
Byte length of text.
Definition: textarea.h:99
struct textarea_msg::@79::@80 selection
With _SELECTION_REPORT.
struct textarea_msg::@79::@81::@84 pos
With _CARET_SET_POS.
bool read_only
Selection can't be cut.
Definition: textarea.h:82
const char * text
UTF8 text.
Definition: textarea.h:98
textarea_msg_type type
Indicates message data type.
Definition: textarea.h:77
struct rect redraw
With _REDRAW_REQUEST.
Definition: textarea.h:84
int height
Caret height.
Definition: textarea.h:93
struct textarea_msg::@79::@82 modified
With _TEXT_MODIFIED.
union textarea_msg::@79 data
Depends on msg type.
int y
Caret y-coord.
Definition: textarea.h:92
bool have_selection
Selection exists.
Definition: textarea.h:81
textarea_drag_type drag
With _DRAG_REPORT.
Definition: textarea.h:79
int x
Caret x-coord.
Definition: textarea.h:91
struct rect * clip
Caret clip rect.
Definition: textarea.h:94
textarea setup parameters
Definition: textarea.h:108
int pad_top
Textarea top padding.
Definition: textarea.h:112
colour border_col
Textarea border colour.
Definition: textarea.h:118
int height
Textarea height.
Definition: textarea.h:110
int width
Textarea width.
Definition: textarea.h:109
int border_width
Textarea border width.
Definition: textarea.h:117
int pad_right
Textarea right padding.
Definition: textarea.h:113
int pad_left
Textarea left padding.
Definition: textarea.h:115
plot_font_style_t text
Textarea background colour and font.
Definition: textarea.h:122
int pad_bottom
Textarea bottom padding.
Definition: textarea.h:114
colour selected_text
Textarea selected text colour.
Definition: textarea.h:120
colour selected_bg
Textarea selection background colour.
Definition: textarea.h:121
For drags we don't own.
Definition: private.h:52
bool no_owner
Definition: private.h:53
struct box * textarea
Definition: private.h:56
For directing input.
Definition: private.h:84
struct box * textarea
Definition: private.h:86
For getting at selections in this content or things in this content.
Definition: private.h:69
struct box * textarea
Definition: private.h:71
static nserror text(const struct redraw_context *ctx, const struct plot_font_style *fstyle, int x, int y, const char *text, size_t length)
Text plotting.
Definition: plot.c:978