1 /*
2 * Copyright (C) 2018-2021 Alexander Borisov
3 *
4 * Author: Alexander Borisov <borisov@lexbor.com>
5 */
6
7 #include "lexbor/core/mraw.h"
8
9 #include "lexbor/html/interface.h"
10 #include "lexbor/html/interfaces/document.h"
11
12 #include "lexbor/dom/interface.h"
13
14 #define LXB_HTML_INTERFACE_RES_CONSTRUCTORS
15 #define LXB_HTML_INTERFACE_RES_DESTRUCTOR
16 #include "lexbor/html/interface_res.h"
17
18
19 static lxb_dom_element_t *
20 lxb_html_interface_clone_element(lxb_dom_document_t *document,
21 const lxb_dom_element_t *element);
22
23
24 lxb_dom_interface_t *
lxb_html_interface_create(lxb_html_document_t * document,lxb_tag_id_t tag_id,lxb_ns_id_t ns)25 lxb_html_interface_create(lxb_html_document_t *document, lxb_tag_id_t tag_id,
26 lxb_ns_id_t ns)
27 {
28 lxb_dom_node_t *node;
29
30 if (tag_id >= LXB_TAG__LAST_ENTRY) {
31 if (ns == LXB_NS_HTML) {
32 lxb_html_unknown_element_t *unel;
33
34 unel = lxb_html_unknown_element_interface_create(document);
35 node = lxb_dom_interface_node(unel);
36 }
37 else if (ns == LXB_NS_SVG) {
38 /* TODO: For this need implement SVGElement */
39 lxb_dom_element_t *domel;
40
41 domel = lxb_dom_element_interface_create(&document->dom_document);
42 node = lxb_dom_interface_node(domel);
43 }
44 else {
45 lxb_dom_element_t *domel;
46
47 domel = lxb_dom_element_interface_create(&document->dom_document);
48 node = lxb_dom_interface_node(domel);
49 }
50 }
51 else {
52 node = lxb_html_interface_res_constructors[tag_id][ns](document);
53 }
54
55 if (node == NULL) {
56 return NULL;
57 }
58
59 node->local_name = tag_id;
60 node->ns = ns;
61
62 return node;
63 }
64
65 lxb_dom_interface_t *
lxb_html_interface_clone(lxb_dom_document_t * document,const lxb_dom_interface_t * intrfc)66 lxb_html_interface_clone(lxb_dom_document_t *document,
67 const lxb_dom_interface_t *intrfc)
68 {
69 const lxb_dom_node_t *node = intrfc;
70
71 if (document == NULL) {
72 document = node->owner_document;
73 }
74
75 switch (node->type) {
76 case LXB_DOM_NODE_TYPE_ELEMENT:
77 return lxb_html_interface_clone_element(document, intrfc);
78
79 case LXB_DOM_NODE_TYPE_TEXT:
80 return lxb_dom_text_interface_clone(document, intrfc);
81
82 case LXB_DOM_NODE_TYPE_PROCESSING_INSTRUCTION:
83 return lxb_dom_processing_instruction_interface_clone(document,
84 intrfc);
85 case LXB_DOM_NODE_TYPE_COMMENT:
86 return lxb_dom_comment_interface_clone(document, intrfc);
87
88 case LXB_DOM_NODE_TYPE_DOCUMENT:
89 return lxb_dom_document_interface_clone(document, intrfc);
90
91 case LXB_DOM_NODE_TYPE_DOCUMENT_TYPE:
92 return lxb_dom_document_type_interface_clone(document, intrfc);
93
94 default:
95 return lxb_dom_node_interface_clone(document, node, false);
96 }
97 }
98
99 static lxb_dom_element_t *
lxb_html_interface_clone_element(lxb_dom_document_t * document,const lxb_dom_element_t * element)100 lxb_html_interface_clone_element(lxb_dom_document_t *document,
101 const lxb_dom_element_t *element)
102 {
103 lxb_dom_element_t *new;
104 const lxb_dom_node_t *node = lxb_dom_interface_node(element);
105
106 new = lxb_html_interface_create((lxb_html_document_t *) document,
107 node->local_name, node->ns);
108 if (new == NULL) {
109 return NULL;
110 }
111
112 if (lxb_dom_element_interface_copy(new, element) != LXB_STATUS_OK) {
113 return lxb_dom_element_interface_destroy(new);
114 }
115
116 return new;
117 }
118
119 lxb_dom_interface_t *
lxb_html_interface_destroy(lxb_dom_interface_t * intrfc)120 lxb_html_interface_destroy(lxb_dom_interface_t *intrfc)
121 {
122 if (intrfc == NULL) {
123 return NULL;
124 }
125
126 lxb_dom_node_t *node = intrfc;
127
128 switch (node->type) {
129 case LXB_DOM_NODE_TYPE_TEXT:
130 case LXB_DOM_NODE_TYPE_COMMENT:
131 case LXB_DOM_NODE_TYPE_ELEMENT:
132 case LXB_DOM_NODE_TYPE_DOCUMENT:
133 case LXB_DOM_NODE_TYPE_DOCUMENT_TYPE:
134 if (node->local_name >= LXB_TAG__LAST_ENTRY) {
135 if (node->ns == LXB_NS_HTML) {
136 return lxb_html_unknown_element_interface_destroy(intrfc);
137 }
138 else if (node->ns == LXB_NS_SVG) {
139 /* TODO: For this need implement SVGElement */
140 return lxb_dom_element_interface_destroy(intrfc);
141 }
142 else {
143 return lxb_dom_element_interface_destroy(intrfc);
144 }
145 }
146 else {
147 return lxb_html_interface_res_destructor[node->local_name][node->ns](intrfc);
148 }
149
150 case LXB_DOM_NODE_TYPE_ATTRIBUTE:
151 return lxb_dom_attr_interface_destroy(intrfc);
152
153 case LXB_DOM_NODE_TYPE_CDATA_SECTION:
154 return lxb_dom_cdata_section_interface_destroy(intrfc);
155
156 case LXB_DOM_NODE_TYPE_DOCUMENT_FRAGMENT:
157 return lxb_dom_document_fragment_interface_destroy(intrfc);
158
159 case LXB_DOM_NODE_TYPE_PROCESSING_INSTRUCTION:
160 return lxb_dom_processing_instruction_interface_destroy(intrfc);
161
162 default:
163 return NULL;
164 }
165 }
166