1 /*
2  * This file is part of libdom.
3  * Licensed under the MIT License,
4  *                http://www.opensource.org/licenses/mit-license.php
5  * Copyright 2012 Daniel Silverstone <dsilvers@netsurf-browser.org>
6  */
7 
8 #include <assert.h>
9 #include <stdlib.h>
10 
11 #include <dom/html/html_text_area_element.h>
12 
13 #include "html/html_document.h"
14 #include "html/html_text_area_element.h"
15 
16 #include "core/node.h"
17 #include "core/attr.h"
18 #include "utils/utils.h"
19 
20 static struct dom_element_protected_vtable _protect_vtable = {
21 	{
22 		DOM_NODE_PROTECT_VTABLE_HTML_TEXT_AREA_ELEMENT
23 	},
24 	DOM_HTML_TEXT_AREA_ELEMENT_PROTECT_VTABLE
25 };
26 
27 /**
28  * Create a dom_html_text_area_element object
29  *
30  * \param params  The html element creation parameters
31  * \param ele     The returned element object
32  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
33  */
_dom_html_text_area_element_create(struct dom_html_element_create_params * params,struct dom_html_text_area_element ** ele)34 dom_exception _dom_html_text_area_element_create(
35 		struct dom_html_element_create_params *params,
36 		struct dom_html_text_area_element **ele)
37 {
38 	struct dom_node_internal *node;
39 
40 	*ele = malloc(sizeof(dom_html_text_area_element));
41 	if (*ele == NULL)
42 		return DOM_NO_MEM_ERR;
43 
44 	/* Set up vtables */
45 	node = (struct dom_node_internal *) *ele;
46 	node->base.vtable = &_dom_html_element_vtable;
47 	node->vtable = &_protect_vtable;
48 
49 	return _dom_html_text_area_element_initialise(params, *ele);
50 }
51 
52 /**
53  * Initialise a dom_html_text_area_element object
54  *
55  * \param params  The html element creation parameters
56  * \param ele     The dom_html_text_area_element object
57  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
58  */
_dom_html_text_area_element_initialise(struct dom_html_element_create_params * params,struct dom_html_text_area_element * ele)59 dom_exception _dom_html_text_area_element_initialise(
60 		struct dom_html_element_create_params *params,
61 		struct dom_html_text_area_element *ele)
62 {
63 	ele->form = NULL;
64 	ele->default_value = NULL;
65 	ele->default_value_set = false;
66 	ele->value = NULL;
67 	ele->value_set = false;
68 
69 	return _dom_html_element_initialise(params, &ele->base);
70 }
71 
72 /**
73  * Finalise a dom_html_text_area_element object
74  *
75  * \param ele  The dom_html_text_area_element object
76  */
_dom_html_text_area_element_finalise(struct dom_html_text_area_element * ele)77 void _dom_html_text_area_element_finalise(struct dom_html_text_area_element *ele)
78 {
79 	if (ele->default_value != NULL) {
80 		dom_string_unref(ele->default_value);
81 		ele->default_value = NULL;
82 		ele->default_value_set = false;
83 	}
84 
85 	if (ele->value != NULL) {
86 		dom_string_unref(ele->value);
87 		ele->value = NULL;
88 		ele->value_set = false;
89 	}
90 
91 	_dom_html_element_finalise(&ele->base);
92 }
93 
94 /**
95  * Destroy a dom_html_text_area_element object
96  *
97  * \param ele  The dom_html_text_area_element object
98  */
_dom_html_text_area_element_destroy(struct dom_html_text_area_element * ele)99 void _dom_html_text_area_element_destroy(struct dom_html_text_area_element *ele)
100 {
101 	_dom_html_text_area_element_finalise(ele);
102 	free(ele);
103 }
104 
105 /*-----------------------------------------------------------------------*/
106 /* Public APIs */
107 
108 /**
109  * Get the disabled property
110  *
111  * \param ele       The dom_html_text_area_element object
112  * \param disabled  The returned status
113  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
114  */
dom_html_text_area_element_get_disabled(dom_html_text_area_element * ele,bool * disabled)115 dom_exception dom_html_text_area_element_get_disabled(dom_html_text_area_element *ele,
116 		bool *disabled)
117 {
118 	return dom_html_element_get_bool_property(&ele->base, "disabled",
119 			SLEN("disabled"), disabled);
120 }
121 
122 /**
123  * Set the disabled property
124  *
125  * \param ele       The dom_html_text_area_element object
126  * \param disabled  The status
127  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
128  */
dom_html_text_area_element_set_disabled(dom_html_text_area_element * ele,bool disabled)129 dom_exception dom_html_text_area_element_set_disabled(dom_html_text_area_element *ele,
130 		bool disabled)
131 {
132 	return dom_html_element_set_bool_property(&ele->base, "disabled",
133 			SLEN("disabled"), disabled);
134 }
135 
136 /**
137  * Get the readOnly property
138  *
139  * \param ele       The dom_html_text_area_element object
140  * \param disabled  The returned status
141  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
142  */
dom_html_text_area_element_get_read_only(dom_html_text_area_element * ele,bool * read_only)143 dom_exception dom_html_text_area_element_get_read_only(dom_html_text_area_element *ele,
144 		bool *read_only)
145 {
146 	return dom_html_element_get_bool_property(&ele->base, "readonly",
147 			SLEN("readonly"), read_only);
148 }
149 
150 /**
151  * Set the readOnly property
152  *
153  * \param ele       The dom_html_text_area_element object
154  * \param disabled  The status
155  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
156  */
dom_html_text_area_element_set_read_only(dom_html_text_area_element * ele,bool read_only)157 dom_exception dom_html_text_area_element_set_read_only(dom_html_text_area_element *ele,
158 		bool read_only)
159 {
160 	return dom_html_element_set_bool_property(&ele->base, "readonly",
161 			SLEN("readonly"), read_only);
162 }
163 
164 /**
165  * Get the defaultValue property
166  *
167  * \param ele       The dom_html_text_area_element object
168  * \param disabled  The returned status
169  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
170  */
dom_html_text_area_element_get_default_value(dom_html_text_area_element * ele,dom_string ** default_value)171 dom_exception dom_html_text_area_element_get_default_value(
172 	dom_html_text_area_element *ele, dom_string **default_value)
173 {
174 	dom_exception err;
175 
176 	if (ele->default_value_set == false) {
177 		err = dom_node_get_text_content((dom_node *)ele,
178 						&ele->default_value);
179 		if (err == DOM_NO_ERR) {
180 			ele->default_value_set = true;
181 		}
182 	}
183 
184 	*default_value = ele->default_value;
185 
186 	if (*default_value != NULL)
187 		dom_string_ref(*default_value);
188 
189 	return DOM_NO_ERR;
190 }
191 
192 /**
193  * Set the defaultValue property
194  *
195  * \param ele       The dom_html_text_area_element object
196  * \param disabled  The status
197  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
198  */
dom_html_text_area_element_set_default_value(dom_html_text_area_element * ele,dom_string * default_value)199 dom_exception dom_html_text_area_element_set_default_value(
200 	dom_html_text_area_element *ele, dom_string *default_value)
201 {
202 	if (ele->default_value != NULL)
203 		dom_string_unref(ele->default_value);
204 
205 	ele->default_value = default_value;
206 	ele->default_value_set = true;
207 
208 	if (ele->default_value != NULL)
209 		dom_string_ref(ele->default_value);
210 
211 	return DOM_NO_ERR;
212 }
213 
214 /**
215  * Get the value property
216  *
217  * \param ele       The dom_html_text_area_element object
218  * \param disabled  The returned status
219  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
220  */
dom_html_text_area_element_get_value(dom_html_text_area_element * ele,dom_string ** value)221 dom_exception dom_html_text_area_element_get_value(
222 	dom_html_text_area_element *ele, dom_string **value)
223 {
224 	dom_exception err;
225 
226 	if (ele->value_set == false) {
227 		err = dom_node_get_text_content((dom_node *)ele,
228 						&ele->value);
229 		if (err == DOM_NO_ERR) {
230 			ele->default_value_set = true;
231 			if (ele->default_value_set == false) {
232 				ele->default_value_set = true;
233 				ele->default_value = ele->value;
234 				dom_string_ref(ele->default_value);
235 			}
236 		}
237 	}
238 
239 	*value = ele->value;
240 
241 	if (*value != NULL)
242 		dom_string_ref(*value);
243 
244 	return DOM_NO_ERR;
245 }
246 
247 /**
248  * Set the value property
249  *
250  * \param ele       The dom_html_text_area_element object
251  * \param disabled  The status
252  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
253  */
dom_html_text_area_element_set_value(dom_html_text_area_element * ele,dom_string * value)254 dom_exception dom_html_text_area_element_set_value(
255 	dom_html_text_area_element *ele, dom_string *value)
256 {
257 	dom_exception err;
258 
259 	if (ele->default_value_set == false) {
260 		err = dom_node_get_text_content((dom_node *)ele,
261 						&ele->default_value);
262 		if (err == DOM_NO_ERR) {
263 			ele->default_value_set = true;
264 		}
265 	}
266 
267 	if (ele->value != NULL)
268 		dom_string_unref(ele->value);
269 
270 	ele->value = value;
271 	ele->value_set = true;
272 
273 	if (ele->value != NULL)
274 		dom_string_ref(ele->value);
275 
276 	return dom_node_set_text_content((dom_node *)ele, ele->value);
277 }
278 
279 /*------------------------------------------------------------------------*/
280 /* The protected virtual functions */
281 
282 /* The virtual function used to parse attribute value, see src/core/element.c
283  * for detail */
_dom_html_text_area_element_parse_attribute(dom_element * ele,dom_string * name,dom_string * value,dom_string ** parsed)284 dom_exception _dom_html_text_area_element_parse_attribute(dom_element *ele,
285 		dom_string *name, dom_string *value,
286 		dom_string **parsed)
287 {
288 	UNUSED(ele);
289 	UNUSED(name);
290 
291 	dom_string_ref(value);
292 	*parsed = value;
293 
294 	return DOM_NO_ERR;
295 }
296 
297 /* The virtual destroy function, see src/core/node.c for detail */
_dom_virtual_html_text_area_element_destroy(dom_node_internal * node)298 void _dom_virtual_html_text_area_element_destroy(dom_node_internal *node)
299 {
300 	_dom_html_text_area_element_destroy((struct dom_html_text_area_element *) node);
301 }
302 
303 /* The virtual copy function, see src/core/node.c for detail */
_dom_html_text_area_element_copy(dom_node_internal * old,dom_node_internal ** copy)304 dom_exception _dom_html_text_area_element_copy(
305 		dom_node_internal *old, dom_node_internal **copy)
306 {
307 	dom_html_text_area_element *new_node;
308 	dom_exception err;
309 
310 	new_node = malloc(sizeof(dom_html_text_area_element));
311 	if (new_node == NULL)
312 		return DOM_NO_MEM_ERR;
313 
314 	err = dom_html_text_area_element_copy_internal(old, new_node);
315 	if (err != DOM_NO_ERR) {
316 		free(new_node);
317 		return err;
318 	}
319 
320 	*copy = (dom_node_internal *) new_node;
321 
322 	return DOM_NO_ERR;
323 }
324 
_dom_html_text_area_element_copy_internal(dom_html_text_area_element * old,dom_html_text_area_element * new)325 dom_exception _dom_html_text_area_element_copy_internal(
326 		dom_html_text_area_element *old,
327 		dom_html_text_area_element *new)
328 {
329 	dom_exception err;
330 
331 	err = dom_html_element_copy_internal(old, new);
332 	if (err != DOM_NO_ERR) {
333 		return err;
334 	}
335 
336 	/* TODO: We don't seem to keep a ref to form element, so just
337 	 *       copy the pointer for now. */
338 	new->form = old->form;
339 
340 	new->default_value = dom_string_ref(old->default_value);
341 	new->default_value_set = old->default_value_set;
342 	new->value = dom_string_ref(old->value);
343 	new->value_set = old->value_set;
344 
345 	return DOM_NO_ERR;
346 }
347 
348 /*-----------------------------------------------------------------------*/
349 /* API functions */
350 
351 #define SIMPLE_GET(attr)						\
352 	dom_exception dom_html_text_area_element_get_##attr(		\
353 		dom_html_text_area_element *element,			\
354 		dom_string **attr)					\
355 	{								\
356 		dom_exception ret;					\
357 		dom_string *_memo_##attr;				\
358 									\
359 		_memo_##attr =						\
360 			((struct dom_html_document *)			\
361 			 ((struct dom_node_internal *)element)->owner)->\
362 			memoised[hds_##attr];				\
363 									\
364 		ret = dom_element_get_attribute(element, _memo_##attr, attr); \
365 									\
366 		return ret;						\
367 	}
368 #define SIMPLE_SET(attr)						\
369 dom_exception dom_html_text_area_element_set_##attr(			\
370 		dom_html_text_area_element *element,			\
371 		dom_string *attr)					\
372 	{								\
373 		dom_exception ret;					\
374 		dom_string *_memo_##attr;				\
375 									\
376 		_memo_##attr =						\
377 			((struct dom_html_document *)			\
378 			 ((struct dom_node_internal *)element)->owner)->\
379 			memoised[hds_##attr];				\
380 									\
381 		ret = dom_element_set_attribute(element, _memo_##attr, attr); \
382 									\
383 		return ret;						\
384 	}
385 
386 #define SIMPLE_GET_SET(attr) SIMPLE_GET(attr) SIMPLE_SET(attr)
387 
388 SIMPLE_GET_SET(access_key);
389 SIMPLE_GET_SET(name);
390 
dom_html_text_area_element_get_type(dom_html_text_area_element * text_area,dom_string ** type)391 dom_exception dom_html_text_area_element_get_type(
392 	dom_html_text_area_element *text_area, dom_string **type)
393 {
394 	dom_html_document *html = (dom_html_document *)
395 		((dom_node_internal *)text_area)->owner;
396 
397 	*type = html->memoised[hds_textarea];
398 	dom_string_ref(*type);
399 
400 	return DOM_NO_ERR;
401 }
402 
dom_html_text_area_element_get_tab_index(dom_html_text_area_element * text_area,int32_t * tab_index)403 dom_exception dom_html_text_area_element_get_tab_index(
404 	dom_html_text_area_element *text_area, int32_t *tab_index)
405 {
406 	return dom_html_element_get_int32_t_property(&text_area->base, "tabindex",
407 			SLEN("tabindex"), tab_index);
408 }
409 
dom_html_text_area_element_set_tab_index(dom_html_text_area_element * text_area,uint32_t tab_index)410 dom_exception dom_html_text_area_element_set_tab_index(
411 	dom_html_text_area_element *text_area, uint32_t tab_index)
412 {
413 	return dom_html_element_set_int32_t_property(&text_area->base, "tabindex",
414 			SLEN("tabindex"), tab_index);
415 }
416 
dom_html_text_area_element_get_cols(dom_html_text_area_element * text_area,int32_t * cols)417 dom_exception dom_html_text_area_element_get_cols(
418 	dom_html_text_area_element *text_area, int32_t *cols)
419 {
420 	return dom_html_element_get_int32_t_property(&text_area->base, "cols",
421 			SLEN("cols"), cols);
422 }
423 
dom_html_text_area_element_set_cols(dom_html_text_area_element * text_area,uint32_t cols)424 dom_exception dom_html_text_area_element_set_cols(
425 	dom_html_text_area_element *text_area, uint32_t cols)
426 {
427 	return dom_html_element_set_int32_t_property(&text_area->base, "cols",
428 			SLEN("cols"), cols);
429 }
430 
dom_html_text_area_element_get_rows(dom_html_text_area_element * text_area,int32_t * rows)431 dom_exception dom_html_text_area_element_get_rows(
432 	dom_html_text_area_element *text_area, int32_t *rows)
433 {
434 	return dom_html_element_get_int32_t_property(&text_area->base, "rows",
435 			SLEN("rows"), rows);
436 }
437 
dom_html_text_area_element_set_rows(dom_html_text_area_element * text_area,uint32_t rows)438 dom_exception dom_html_text_area_element_set_rows(
439 	dom_html_text_area_element *text_area, uint32_t rows)
440 {
441 	return dom_html_element_set_int32_t_property(&text_area->base, "rows",
442 			SLEN("rows"), rows);
443 }
444 
dom_html_text_area_element_get_form(dom_html_text_area_element * text_area,dom_html_form_element ** form)445 dom_exception dom_html_text_area_element_get_form(
446 	dom_html_text_area_element *text_area, dom_html_form_element **form)
447 {
448 	*form = text_area->form;
449 
450 	if (*form != NULL)
451 		dom_node_ref(*form);
452 
453 	return DOM_NO_ERR;
454 }
455 
_dom_html_text_area_element_set_form(dom_html_text_area_element * text_area,dom_html_form_element * form)456 dom_exception _dom_html_text_area_element_set_form(
457 	dom_html_text_area_element *text_area, dom_html_form_element *form)
458 {
459 	text_area->form = form;
460 
461 	return DOM_NO_ERR;
462 }
463 
464 /**
465  * Blur this control
466  *
467  * \param ele  The form object
468  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
469  */
dom_html_text_area_element_blur(dom_html_text_area_element * ele)470 dom_exception dom_html_text_area_element_blur(dom_html_text_area_element *ele)
471 {
472 	struct dom_html_document *doc =
473 		(dom_html_document *) dom_node_get_owner(ele);
474 	bool success = false;
475 	assert(doc != NULL);
476 
477 	/* This event does not bubble & is Non-cancellable. Mentioned in w3 specs. More research is needed to prove why. */
478 	return _dom_dispatch_generic_event((dom_document *) doc,
479 					   (dom_event_target *) ele,
480 					   doc->memoised[hds_blur], false,
481 					   false, &success);
482 }
483 
484 /**
485  * Focus this control
486  *
487  * \param ele  The form object
488  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
489  */
dom_html_text_area_element_focus(dom_html_text_area_element * ele)490 dom_exception dom_html_text_area_element_focus(dom_html_text_area_element *ele)
491 {
492 	struct dom_html_document *doc =
493 		(dom_html_document *) dom_node_get_owner(ele);
494 	bool success = false;
495 	assert(doc != NULL);
496 
497 	/* This event does not bubble & is Non-cancellable. Mentioned in w3 specs. More research is needed to prove why. */
498 	return _dom_dispatch_generic_event((dom_document *)doc,
499 					   (dom_event_target *) ele,
500 					   doc->memoised[hds_focus], false,
501 					   false, &success);
502 }
503 
504 /**
505  * Select this control
506  *
507  * \param ele  The form object
508  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
509  */
dom_html_text_area_element_select(dom_html_text_area_element * ele)510 dom_exception dom_html_text_area_element_select(dom_html_text_area_element *ele)
511 {
512 	struct dom_html_document *doc =
513 		(dom_html_document *) dom_node_get_owner(ele);
514 	bool success = false;
515 	assert(doc != NULL);
516 
517 	/* This event bubbles & is non-cancelable. Mentioned in w3 specs. More research is needed to prove why. */
518 	return _dom_dispatch_generic_event((dom_document *)doc,
519 					   (dom_event_target *) ele,
520 					   doc->memoised[hds_select], true,
521 					   false, &success);
522 }
523