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 2009 Bo Yang <struggleyb.nku@gmail.com>
6 * Copyright 2014 Rupinder Singh Khokhar <rsk1coder99@gmail.com>
7 */
8
9 #include <assert.h>
10 #include <stdlib.h>
11
12 #include <dom/html/html_tablerow_element.h>
13 #include <dom/html/html_table_element.h>
14
15 #include "html/html_document.h"
16 #include "html/html_tablerow_element.h"
17 #include "html/html_collection.h"
18
19 #include "core/node.h"
20 #include "core/attr.h"
21 #include "utils/utils.h"
22
23 static struct dom_element_protected_vtable _protect_vtable = {
24 {
25 DOM_NODE_PROTECT_VTABLE_HTML_TABLE_ROW_ELEMENT
26 },
27 DOM_HTML_TABLE_ROW_ELEMENT_PROTECT_VTABLE
28 };
29
30 /**
31 * Create a dom_html_table_row_element table_row
32 *
33 * \param params The html element creation parameters
34 * \param ele The returned element table_row
35 * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
36 */
_dom_html_table_row_element_create(struct dom_html_element_create_params * params,struct dom_html_table_row_element ** ele)37 dom_exception _dom_html_table_row_element_create(
38 struct dom_html_element_create_params *params,
39 struct dom_html_table_row_element **ele)
40 {
41 struct dom_node_internal *node;
42
43 *ele = malloc(sizeof(dom_html_table_row_element));
44 if (*ele == NULL)
45 return DOM_NO_MEM_ERR;
46
47 /* Set up vtables */
48 node = (struct dom_node_internal *) *ele;
49 node->base.vtable = &_dom_html_element_vtable;
50 node->vtable = &_protect_vtable;
51
52 return _dom_html_table_row_element_initialise(params, *ele);
53 }
54
55 /**
56 * Initialise a dom_html_table_row_element table_row
57 *
58 * \param params The html element creation parameters
59 * \param ele The dom_html_table_row_element table_row
60 * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
61 */
_dom_html_table_row_element_initialise(struct dom_html_element_create_params * params,struct dom_html_table_row_element * ele)62 dom_exception _dom_html_table_row_element_initialise(
63 struct dom_html_element_create_params *params,
64 struct dom_html_table_row_element *ele)
65 {
66 return _dom_html_element_initialise(params, &ele->base);
67 }
68
69 /**
70 * Finalise a dom_html_table_row_element table_row
71 *
72 * \param ele The dom_html_table_row_element table_row
73 */
_dom_html_table_row_element_finalise(struct dom_html_table_row_element * ele)74 void _dom_html_table_row_element_finalise(struct dom_html_table_row_element *ele)
75 {
76 _dom_html_element_finalise(&ele->base);
77 }
78
79 /**
80 * Destroy a dom_html_table_row_element table_row
81 *
82 * \param ele The dom_html_table_row_element table_row
83 */
_dom_html_table_row_element_destroy(struct dom_html_table_row_element * ele)84 void _dom_html_table_row_element_destroy(struct dom_html_table_row_element *ele)
85 {
86 _dom_html_table_row_element_finalise(ele);
87 free(ele);
88 }
89
90 /*------------------------------------------------------------------------*/
91 /* The protected virtual functions */
92
93 /* The virtual function used to parse attribute value, see src/core/element.c
94 * for detail */
_dom_html_table_row_element_parse_attribute(dom_element * ele,dom_string * name,dom_string * value,dom_string ** parsed)95 dom_exception _dom_html_table_row_element_parse_attribute(dom_element *ele,
96 dom_string *name, dom_string *value,
97 dom_string **parsed)
98 {
99 UNUSED(ele);
100 UNUSED(name);
101
102 dom_string_ref(value);
103 *parsed = value;
104
105 return DOM_NO_ERR;
106 }
107
108 /* The virtual destroy function, see src/core/node.c for detail */
_dom_virtual_html_table_row_element_destroy(dom_node_internal * node)109 void _dom_virtual_html_table_row_element_destroy(dom_node_internal *node)
110 {
111 _dom_html_table_row_element_destroy((struct dom_html_table_row_element *) node);
112 }
113
114 /* The virtual copy function, see src/core/node.c for detail */
_dom_html_table_row_element_copy(dom_node_internal * old,dom_node_internal ** copy)115 dom_exception _dom_html_table_row_element_copy(
116 dom_node_internal *old, dom_node_internal **copy)
117 {
118 dom_html_table_row_element *new_node;
119 dom_exception err;
120
121 new_node = malloc(sizeof(dom_html_table_row_element));
122 if (new_node == NULL)
123 return DOM_NO_MEM_ERR;
124
125 err = dom_html_table_row_element_copy_internal(old, new_node);
126 if (err != DOM_NO_ERR) {
127 free(new_node);
128 return err;
129 }
130
131 *copy = (dom_node_internal *) new_node;
132
133 return DOM_NO_ERR;
134 }
135
_dom_html_table_row_element_copy_internal(dom_html_table_row_element * old,dom_html_table_row_element * new)136 dom_exception _dom_html_table_row_element_copy_internal(
137 dom_html_table_row_element *old,
138 dom_html_table_row_element *new)
139 {
140 dom_exception err;
141
142 err = dom_html_element_copy_internal(old, new);
143 if (err != DOM_NO_ERR) {
144 return err;
145 }
146
147 return DOM_NO_ERR;
148 }
149
150 /*-----------------------------------------------------------------------*/
151 /* API functions */
152
153 #define SIMPLE_GET(attr) \
154 dom_exception dom_html_table_row_element_get_##attr( \
155 dom_html_table_row_element *element, \
156 dom_string **attr) \
157 { \
158 dom_exception ret; \
159 dom_string *_memo_##attr; \
160 \
161 _memo_##attr = \
162 ((struct dom_html_document *) \
163 ((struct dom_node_internal *)element)->owner)->\
164 memoised[hds_##attr]; \
165 \
166 ret = dom_element_get_attribute(element, _memo_##attr, attr); \
167 \
168 return ret; \
169 }
170 #define SIMPLE_SET(attr) \
171 dom_exception dom_html_table_row_element_set_##attr( \
172 dom_html_table_row_element *element, \
173 dom_string *attr) \
174 { \
175 dom_exception ret; \
176 dom_string *_memo_##attr; \
177 \
178 _memo_##attr = \
179 ((struct dom_html_document *) \
180 ((struct dom_node_internal *)element)->owner)->\
181 memoised[hds_##attr]; \
182 \
183 ret = dom_element_set_attribute(element, _memo_##attr, attr); \
184 \
185 return ret; \
186 }
187
188 #define SIMPLE_GET_SET(attr) SIMPLE_GET(attr) SIMPLE_SET(attr)
189
190 SIMPLE_GET_SET(align);
191 SIMPLE_GET_SET(bg_color);
192 SIMPLE_GET_SET(ch);
193 SIMPLE_GET_SET(ch_off);
194 SIMPLE_GET_SET(v_align);
195
196 /**
197 * Get the index of the Row in logical order
198 *
199 * \param element The dom_html_table_row_element object
200 * \param index The Status
201 * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
202 */
dom_html_table_row_element_get_row_index(dom_html_table_row_element * table_row,int32_t * row_index)203 dom_exception dom_html_table_row_element_get_row_index(
204 dom_html_table_row_element *table_row, int32_t *row_index)
205 {
206 dom_exception exp;
207 dom_node_internal *n =
208 ((dom_node_internal *)table_row)->parent;
209 dom_node_internal *parent = n;
210 dom_html_document *doc =
211 (dom_html_document *) ((dom_node_internal *) table_row)->owner;
212
213 uint32_t count = 0;
214
215 for (n = n->first_child; n != (dom_node_internal *)table_row;
216 n = n->next) {
217 if(n->type == DOM_ELEMENT_NODE &&
218 dom_string_caseless_isequal(n->name,
219 doc->elements[DOM_HTML_ELEMENT_TYPE_TR])) {
220 count += 1;
221 }
222 }
223
224 if (dom_string_caseless_isequal((parent->parent)->name,
225 doc->elements[DOM_HTML_ELEMENT_TYPE_TABLE]) &&
226 dom_string_caseless_isequal(parent->name,
227 doc->elements[DOM_HTML_ELEMENT_TYPE_THEAD])) {
228 *row_index = count;
229 } else if (dom_string_caseless_isequal((parent->parent)->name,
230 doc->elements[DOM_HTML_ELEMENT_TYPE_TABLE]) &&
231 (dom_string_caseless_isequal(parent->name,
232 doc->elements[DOM_HTML_ELEMENT_TYPE_TBODY]) ||
233 dom_string_caseless_isequal(parent->name,
234 doc->elements[DOM_HTML_ELEMENT_TYPE_TFOOT]))) {
235 uint32_t len;
236 dom_html_table_section_element *t_head;
237 dom_html_collection *rows;
238
239 n = parent->parent;
240 exp = dom_html_table_element_get_t_head(
241 (dom_html_table_element *)(parent->parent),
242 &t_head);
243 if (exp != DOM_NO_ERR) {
244 return exp;
245 }
246
247 exp = dom_html_table_section_element_get_rows(t_head, &rows);
248 dom_node_unref(t_head);
249 if (exp != DOM_NO_ERR) {
250 return exp;
251 }
252
253 dom_html_collection_get_length(rows, &len);
254 dom_html_collection_unref(rows);
255
256 count += len;
257
258 for (n = n->first_child;n != parent && n != NULL;
259 n = n->next) {
260 if (dom_string_caseless_isequal(n->name,
261 doc->elements[DOM_HTML_ELEMENT_TYPE_TBODY])) {
262 exp = dom_html_table_section_element_get_rows(
263 (dom_html_table_section_element *)n,
264 &rows);
265 if (exp != DOM_NO_ERR) {
266 return exp;
267 }
268
269 exp = dom_html_collection_get_length(rows, &len);
270 dom_html_collection_unref(rows);
271 if (exp != DOM_NO_ERR) {
272 return exp;
273 }
274
275 count += len;
276 }
277 }
278 *row_index = (int32_t)count;
279
280 } else {
281 return DOM_HIERARCHY_REQUEST_ERR;
282 }
283 return DOM_NO_ERR;
284 }
285
286 /**
287 * Get the index of a row within its Section
288 *
289 * \param element The dom_html_table_row_element object
290 * \param index The Status
291 * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
292 */
dom_html_table_row_element_get_section_row_index(dom_html_table_row_element * table_row,int32_t * section_row_index)293 dom_exception dom_html_table_row_element_get_section_row_index(
294 dom_html_table_row_element *table_row, int32_t *section_row_index)
295 {
296 dom_node_internal *n = ((dom_node_internal *)table_row)->parent;
297 dom_html_document *doc = (dom_html_document *) ((dom_node_internal *) table_row)->owner;
298 int32_t count = 0;
299 for (n = n->first_child; n != (dom_node_internal *)table_row;
300 n = n->next) {
301 if (n->type == DOM_ELEMENT_NODE &&
302 dom_string_caseless_isequal(n->name,
303 doc->elements[DOM_HTML_ELEMENT_TYPE_TR])) {
304 count += 1;
305 }
306 }
307 *section_row_index = count;
308 return DOM_NO_ERR;
309 }
310
311 /**
312 * Callback for creating the Cells collection
313 *
314 * \param node The dom_node_internal object
315 * \param ctx The dom_html_document object (void *)
316 * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
317 */
table_cells_callback(struct dom_node_internal * node,void * ctx)318 static bool table_cells_callback(struct dom_node_internal *node, void *ctx)
319 {
320 dom_html_document *doc = ctx;
321 if (node->type == DOM_ELEMENT_NODE &&
322 dom_string_caseless_isequal(node->name,
323 doc->elements[DOM_HTML_ELEMENT_TYPE_TD])) {
324 return true;
325 }
326 return false;
327 }
328
329 /**
330 * Get the Cells collection
331 *
332 * \param element The dom_html_table_element object
333 * \param t_bodies The Status
334 * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
335 */
dom_html_table_row_element_get_cells(dom_html_table_row_element * element,dom_html_collection ** cells)336 dom_exception dom_html_table_row_element_get_cells(
337 dom_html_table_row_element *element,
338 dom_html_collection **cells)
339 {
340 dom_html_document *doc = (dom_html_document *) ((dom_node_internal *) element)->owner;
341 return _dom_html_collection_create(doc, (dom_node_internal *)element,
342 table_cells_callback, (void *)doc, cells);
343 }
344
345 /**
346 * Insert Cell before the given Index
347 *
348 * \param element The dom_html_table_row_element object
349 * \param index The Index of the Cell node to be inserted
350 * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
351 */
dom_html_table_row_element_insert_cell(dom_html_table_row_element * element,int32_t index,dom_html_element ** cell)352 dom_exception dom_html_table_row_element_insert_cell(
353 dom_html_table_row_element *element,
354 int32_t index, dom_html_element **cell) {
355 dom_html_document *doc = (dom_html_document *) ((dom_node_internal *) element)->owner;
356
357 dom_html_element *new_cell;
358
359 dom_html_collection *cells; /*< The collection of cells in input table_row_element*/
360 uint32_t len; /*< The size of the cell collection */
361 dom_exception exp; /*< Variable for getting the exceptions*/
362
363 struct dom_html_element_create_params params = {
364 .type = DOM_HTML_ELEMENT_TYPE_TD,
365 .doc = doc,
366 .name = doc->elements[DOM_HTML_ELEMENT_TYPE_TD],
367 .namespace = ((dom_node_internal *)element)->namespace,
368 .prefix = ((dom_node_internal *)element)->prefix
369 };
370
371 exp = _dom_html_element_create(¶ms, &new_cell);
372 if (exp != DOM_NO_ERR)
373 return exp;
374
375 exp = dom_html_table_row_element_get_cells(element, &cells);
376 if (exp != DOM_NO_ERR) {
377 dom_node_unref(new_cell);
378 return exp;
379 }
380
381 exp = dom_html_collection_get_length(cells, &len);
382 if (exp != DOM_NO_ERR) {
383 dom_node_unref(new_cell);
384 dom_html_collection_unref(cells);
385 return exp;
386 }
387
388 if (index < -1 || index > (int32_t)len) {
389 /* Check for index validity */
390 dom_node_unref(new_cell);
391 dom_html_collection_unref (cells);
392 return DOM_INDEX_SIZE_ERR;
393 } else if (index == -1 || index == (int32_t)len) {
394 dom_html_collection_unref(cells);
395
396 exp = dom_node_append_child(element, new_cell, cell);
397 dom_node_unref(new_cell);
398
399 } else {
400 dom_node *node;
401 dom_html_collection_item(cells, index, &node);
402 dom_html_collection_unref(cells);
403
404 exp = dom_node_insert_before(element, new_cell, node, cell);
405 dom_node_unref(new_cell);
406 dom_node_unref(node);
407 }
408
409 return exp;
410 }
411
412 /**
413 * Delete Cell at given Index
414 *
415 * \param element The dom_html_table_row_element object
416 * \param index The Index of the Cell node to be deleted
417 * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
418 */
dom_html_table_row_element_delete_cell(dom_html_table_row_element * element,int32_t index)419 dom_exception dom_html_table_row_element_delete_cell(
420 dom_html_table_row_element *element,
421 int32_t index) {
422 dom_node *node, *old_node; /*< The node at the (index)th position*/
423 dom_html_collection *cells; /*< The collection of rows in input table_row_element*/
424 uint32_t len; /*< The size of the row collection */
425 dom_exception exp; /*< Temporary variable to store & check the exceptions*/
426
427 exp = dom_html_table_row_element_get_cells(element, &cells);
428 if (exp != DOM_NO_ERR) {
429 return exp;
430 }
431
432 exp = dom_html_collection_get_length(cells, &len);
433 if (exp != DOM_NO_ERR) {
434 dom_html_collection_unref(cells);
435 return exp;
436 }
437
438 if (index < -1 || index >= (int32_t) len || len == 0) {
439 /* Check for index validity */
440 dom_html_collection_unref(cells);
441 return DOM_INDEX_SIZE_ERR;
442 }
443
444 if (index == -1)
445 index = len - 1;
446
447 exp = dom_html_collection_item(cells, index, &node);
448 if (exp != DOM_NO_ERR) {
449 dom_html_collection_unref(cells);
450 return exp;
451 }
452
453 exp = dom_node_remove_child(element, node, &old_node);
454 if (exp == DOM_NO_ERR)
455 dom_node_unref(old_node);
456
457 dom_node_unref(node);
458 dom_html_collection_unref(cells);
459
460 return exp;
461 }
462
463