1
- /* ***************************************************************************
1
+ /* ***************************************************************************
2
2
* builder.c -- the GUI build module, parse UI config code and build UI.
3
3
*
4
4
* Copyright (c) 2018, Liu chao <lc-soft@live.cn> All rights reserved.
43
43
#include <libxml/xmlmemory.h>
44
44
#include <libxml/parser.h>
45
45
46
- #define PropNameIs (type ) (xmlStrcasecmp(prop ->name, BAD_CAST type ) == 0)
46
+ #define PropNameIs (PROP , NAME ) (xmlStrcasecmp(PROP ->name, (xmlChar*)NAME ) == 0)
47
47
48
48
enum ParserID {
49
49
ID_ROOT ,
@@ -71,9 +71,10 @@ typedef struct Parser {
71
71
72
72
struct XMLParserContextRec_ {
73
73
int id ;
74
- LCUI_Widget widget ;
75
74
LCUI_Widget root ;
76
- ParserPtr parent ;
75
+ LCUI_Widget widget ;
76
+ LCUI_Widget parent_widget ;
77
+ ParserPtr parent_parser ;
77
78
const char * space ;
78
79
};
79
80
@@ -82,10 +83,15 @@ static struct ModuleContext {
82
83
RBTree parsers ;
83
84
} self ;
84
85
86
+ #define EXIT (CODE ) code = CODE; goto exit;
87
+
85
88
/** 解析<resource>元素,根据相关参数载入资源 */
86
89
static int ParseResource (XMLParserContext ctx , xmlNodePtr node )
87
90
{
91
+
88
92
xmlAttrPtr prop ;
93
+
94
+ int code = PB_NEXT ;
89
95
char * prop_val , * type = NULL , * src = NULL ;
90
96
91
97
if (node -> type != XML_ELEMENT_NODE ) {
@@ -94,9 +100,9 @@ static int ParseResource(XMLParserContext ctx, xmlNodePtr node)
94
100
prop = node -> properties ;
95
101
while (prop ) {
96
102
prop_val = (char * )xmlGetProp (node , prop -> name );
97
- if (PropNameIs ("type" )) {
103
+ if (PropNameIs (prop , "type" )) {
98
104
type = prop_val ;
99
- } else if (PropNameIs ("src" )) {
105
+ } else if (PropNameIs (prop , "src" )) {
100
106
src = prop_val ;
101
107
} else {
102
108
xmlFree (prop_val );
@@ -107,25 +113,48 @@ static int ParseResource(XMLParserContext ctx, xmlNodePtr node)
107
113
return PB_WARNING ;
108
114
}
109
115
if (strstr (type , "application/font-" )) {
110
- LCUIFont_LoadFile (src );
111
- } else if (strstr (type , "text/css" )) {
116
+ if (LCUIFont_LoadFile (src ) < 1 ) {
117
+ EXIT (PB_WARNING );
118
+ }
119
+ } else if (strcmp (type , "text/css" ) == 0 ) {
112
120
if (src ) {
113
- LCUI_LoadCSSFile (src );
121
+ if (LCUI_LoadCSSFile (src ) != 0 ) {
122
+ EXIT (PB_WARNING );
123
+ }
114
124
}
115
125
for (node = node -> children ; node ; node = node -> next ) {
116
126
if (node -> type != XML_TEXT_NODE ) {
117
127
continue ;
118
128
}
119
129
LCUI_LoadCSSString ((char * )node -> content , ctx -> space );
120
130
}
131
+ } else if (strcmp (type , "text/xml" ) == 0 ) {
132
+ LCUI_Widget pack ;
133
+ if (!src ) {
134
+ EXIT (PB_WARNING );
135
+ }
136
+ pack = LCUIBuilder_LoadFile (src );
137
+ if (!pack ) {
138
+ EXIT (PB_WARNING );
139
+ }
140
+ if (ctx -> parent_widget ) {
141
+ Widget_Append (ctx -> parent_widget , pack );
142
+ } else if (ctx -> root ) {
143
+ Widget_Append (ctx -> root , pack );
144
+ } else {
145
+ Widget_Destroy (pack );
146
+ EXIT (PB_WARNING );
147
+ }
148
+ Widget_Unwrap (pack );
121
149
}
150
+ exit :
122
151
if (src ) {
123
152
xmlFree (src );
124
153
}
125
154
if (type ) {
126
155
xmlFree (type );
127
156
}
128
- return PB_NEXT ;
157
+ return code ;
129
158
}
130
159
131
160
/** 解析<ui>元素,主要作用是创建一个容纳全部部件的根级部件 */
@@ -134,7 +163,7 @@ static int ParseUI(XMLParserContext ctx, xmlNodePtr node)
134
163
if (node -> type != XML_ELEMENT_NODE ) {
135
164
return PB_NEXT ;
136
165
}
137
- if (ctx -> parent && ctx -> parent -> id != ID_ROOT ) {
166
+ if (ctx -> parent_parser && ctx -> parent_parser -> id != ID_ROOT ) {
138
167
return PB_ERROR ;
139
168
}
140
169
ctx -> widget = LCUIWidget_New (NULL );
@@ -149,8 +178,8 @@ static int ParseWidget(XMLParserContext ctx, xmlNodePtr node)
149
178
char * prop_val = NULL , * prop_name ;
150
179
LCUI_Widget w = NULL , parent = ctx -> widget ;
151
180
152
- if (ctx -> parent && ctx -> parent -> id != ID_UI &&
153
- ctx -> parent -> id != ID_WIDGET ) {
181
+ if (ctx -> parent_parser && ctx -> parent_parser -> id != ID_UI &&
182
+ ctx -> parent_parser -> id != ID_WIDGET ) {
154
183
return PB_ERROR ;
155
184
}
156
185
switch (node -> type ) {
@@ -178,7 +207,7 @@ static int ParseWidget(XMLParserContext ctx, xmlNodePtr node)
178
207
xmlFree (prop_val );
179
208
}
180
209
prop_val = (char * )xmlGetProp (node , prop -> name );
181
- if (PropNameIs ("type" )) {
210
+ if (PropNameIs (prop , "type" )) {
182
211
DEBUG_MSG ("widget: %p, set type: %s\n" , w , prop_val );
183
212
w -> proto = LCUIWidget_GetPrototype (prop_val );
184
213
if (w -> proto && w -> proto -> init ) {
@@ -188,11 +217,11 @@ static int ParseWidget(XMLParserContext ctx, xmlNodePtr node)
188
217
w -> type = strdup2 (prop_val );
189
218
}
190
219
continue ;
191
- } else if (PropNameIs ("id" )) {
220
+ } else if (PropNameIs (prop , "id" )) {
192
221
DEBUG_MSG ("widget: %p, set id: %s\n" , w , prop_val );
193
222
Widget_SetId (w , prop_val );
194
223
continue ;
195
- } else if (PropNameIs ("class" )) {
224
+ } else if (PropNameIs (prop , "class" )) {
196
225
DEBUG_MSG ("widget: %p, add class: %s\n" , w , prop_val );
197
226
Widget_AddClass (w , prop_val );
198
227
continue ;
@@ -243,19 +272,21 @@ static void ParseNode(XMLParserContext ctx, xmlNodePtr node)
243
272
{
244
273
ParserPtr p ;
245
274
XMLParserContextRec cur_ctx ;
275
+
246
276
for (; node ; node = node -> next ) {
247
277
if (node -> type == XML_ELEMENT_NODE ) {
248
278
p = RBTree_CustomGetData (& self .parsers , node -> name );
249
279
} else {
250
- p = ctx -> parent ;
280
+ p = ctx -> parent_parser ;
251
281
}
252
282
if (!p ) {
253
283
continue ;
254
284
}
255
285
cur_ctx = * ctx ;
286
+ cur_ctx .parent_widget = ctx -> widget ;
256
287
switch (p -> parse (& cur_ctx , node )) {
257
288
case PB_ENTER :
258
- cur_ctx .parent = p ;
289
+ cur_ctx .parent_parser = p ;
259
290
ParseNode (& cur_ctx , node -> children );
260
291
break ;
261
292
case PB_NEXT : break ;
@@ -285,10 +316,7 @@ LCUI_Widget LCUIBuilder_LoadString(const char *str, int size)
285
316
xmlNodePtr cur ;
286
317
XMLParserContextRec ctx ;
287
318
288
- ctx .root = NULL ;
289
- ctx .widget = NULL ;
290
- ctx .parent = NULL ;
291
- ctx .space = NULL ;
319
+ memset (& ctx , 0 , sizeof (ctx ));
292
320
doc = xmlParseMemory (str , size );
293
321
if (!doc ) {
294
322
LOG ("[builder] Failed to parse xml form memory\n" );
@@ -321,9 +349,7 @@ LCUI_Widget LCUIBuilder_LoadFile(const char *filepath)
321
349
xmlNodePtr cur ;
322
350
XMLParserContextRec ctx ;
323
351
324
- ctx .root = NULL ;
325
- ctx .widget = NULL ;
326
- ctx .parent = NULL ;
352
+ memset (& ctx , 0 , sizeof (ctx ));
327
353
ctx .space = filepath ;
328
354
doc = xmlParseFile (filepath );
329
355
if (!doc ) {
0 commit comments