1- /* ***************************************************************************
1+ /* ***************************************************************************
22 * builder.c -- the GUI build module, parse UI config code and build UI.
33 *
44 * Copyright (c) 2018, Liu chao <lc-soft@live.cn> All rights reserved.
4343#include <libxml/xmlmemory.h>
4444#include <libxml/parser.h>
4545
46- #define PropNameIs (type ) (xmlStrcasecmp(prop ->name, BAD_CAST type ) == 0)
46+ #define PropNameIs (PROP , NAME ) (xmlStrcasecmp(PROP ->name, (xmlChar*)NAME ) == 0)
4747
4848enum ParserID {
4949 ID_ROOT ,
@@ -71,9 +71,10 @@ typedef struct Parser {
7171
7272struct XMLParserContextRec_ {
7373 int id ;
74- LCUI_Widget widget ;
7574 LCUI_Widget root ;
76- ParserPtr parent ;
75+ LCUI_Widget widget ;
76+ LCUI_Widget parent_widget ;
77+ ParserPtr parent_parser ;
7778 const char * space ;
7879};
7980
@@ -82,10 +83,15 @@ static struct ModuleContext {
8283 RBTree parsers ;
8384} self ;
8485
86+ #define EXIT (CODE ) code = CODE; goto exit;
87+
8588/** 解析<resource>元素,根据相关参数载入资源 */
8689static int ParseResource (XMLParserContext ctx , xmlNodePtr node )
8790{
91+
8892 xmlAttrPtr prop ;
93+
94+ int code = PB_NEXT ;
8995 char * prop_val , * type = NULL , * src = NULL ;
9096
9197 if (node -> type != XML_ELEMENT_NODE ) {
@@ -94,9 +100,9 @@ static int ParseResource(XMLParserContext ctx, xmlNodePtr node)
94100 prop = node -> properties ;
95101 while (prop ) {
96102 prop_val = (char * )xmlGetProp (node , prop -> name );
97- if (PropNameIs ("type" )) {
103+ if (PropNameIs (prop , "type" )) {
98104 type = prop_val ;
99- } else if (PropNameIs ("src" )) {
105+ } else if (PropNameIs (prop , "src" )) {
100106 src = prop_val ;
101107 } else {
102108 xmlFree (prop_val );
@@ -107,25 +113,48 @@ static int ParseResource(XMLParserContext ctx, xmlNodePtr node)
107113 return PB_WARNING ;
108114 }
109115 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 ) {
112120 if (src ) {
113- LCUI_LoadCSSFile (src );
121+ if (LCUI_LoadCSSFile (src ) != 0 ) {
122+ EXIT (PB_WARNING );
123+ }
114124 }
115125 for (node = node -> children ; node ; node = node -> next ) {
116126 if (node -> type != XML_TEXT_NODE ) {
117127 continue ;
118128 }
119129 LCUI_LoadCSSString ((char * )node -> content , ctx -> space );
120130 }
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 );
121149 }
150+ exit :
122151 if (src ) {
123152 xmlFree (src );
124153 }
125154 if (type ) {
126155 xmlFree (type );
127156 }
128- return PB_NEXT ;
157+ return code ;
129158}
130159
131160/** 解析<ui>元素,主要作用是创建一个容纳全部部件的根级部件 */
@@ -134,7 +163,7 @@ static int ParseUI(XMLParserContext ctx, xmlNodePtr node)
134163 if (node -> type != XML_ELEMENT_NODE ) {
135164 return PB_NEXT ;
136165 }
137- if (ctx -> parent && ctx -> parent -> id != ID_ROOT ) {
166+ if (ctx -> parent_parser && ctx -> parent_parser -> id != ID_ROOT ) {
138167 return PB_ERROR ;
139168 }
140169 ctx -> widget = LCUIWidget_New (NULL );
@@ -149,8 +178,8 @@ static int ParseWidget(XMLParserContext ctx, xmlNodePtr node)
149178 char * prop_val = NULL , * prop_name ;
150179 LCUI_Widget w = NULL , parent = ctx -> widget ;
151180
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 ) {
154183 return PB_ERROR ;
155184 }
156185 switch (node -> type ) {
@@ -178,7 +207,7 @@ static int ParseWidget(XMLParserContext ctx, xmlNodePtr node)
178207 xmlFree (prop_val );
179208 }
180209 prop_val = (char * )xmlGetProp (node , prop -> name );
181- if (PropNameIs ("type" )) {
210+ if (PropNameIs (prop , "type" )) {
182211 DEBUG_MSG ("widget: %p, set type: %s\n" , w , prop_val );
183212 w -> proto = LCUIWidget_GetPrototype (prop_val );
184213 if (w -> proto && w -> proto -> init ) {
@@ -188,11 +217,11 @@ static int ParseWidget(XMLParserContext ctx, xmlNodePtr node)
188217 w -> type = strdup2 (prop_val );
189218 }
190219 continue ;
191- } else if (PropNameIs ("id" )) {
220+ } else if (PropNameIs (prop , "id" )) {
192221 DEBUG_MSG ("widget: %p, set id: %s\n" , w , prop_val );
193222 Widget_SetId (w , prop_val );
194223 continue ;
195- } else if (PropNameIs ("class" )) {
224+ } else if (PropNameIs (prop , "class" )) {
196225 DEBUG_MSG ("widget: %p, add class: %s\n" , w , prop_val );
197226 Widget_AddClass (w , prop_val );
198227 continue ;
@@ -243,19 +272,21 @@ static void ParseNode(XMLParserContext ctx, xmlNodePtr node)
243272{
244273 ParserPtr p ;
245274 XMLParserContextRec cur_ctx ;
275+
246276 for (; node ; node = node -> next ) {
247277 if (node -> type == XML_ELEMENT_NODE ) {
248278 p = RBTree_CustomGetData (& self .parsers , node -> name );
249279 } else {
250- p = ctx -> parent ;
280+ p = ctx -> parent_parser ;
251281 }
252282 if (!p ) {
253283 continue ;
254284 }
255285 cur_ctx = * ctx ;
286+ cur_ctx .parent_widget = ctx -> widget ;
256287 switch (p -> parse (& cur_ctx , node )) {
257288 case PB_ENTER :
258- cur_ctx .parent = p ;
289+ cur_ctx .parent_parser = p ;
259290 ParseNode (& cur_ctx , node -> children );
260291 break ;
261292 case PB_NEXT : break ;
@@ -285,10 +316,7 @@ LCUI_Widget LCUIBuilder_LoadString(const char *str, int size)
285316 xmlNodePtr cur ;
286317 XMLParserContextRec ctx ;
287318
288- ctx .root = NULL ;
289- ctx .widget = NULL ;
290- ctx .parent = NULL ;
291- ctx .space = NULL ;
319+ memset (& ctx , 0 , sizeof (ctx ));
292320 doc = xmlParseMemory (str , size );
293321 if (!doc ) {
294322 LOG ("[builder] Failed to parse xml form memory\n" );
@@ -321,9 +349,7 @@ LCUI_Widget LCUIBuilder_LoadFile(const char *filepath)
321349 xmlNodePtr cur ;
322350 XMLParserContextRec ctx ;
323351
324- ctx .root = NULL ;
325- ctx .widget = NULL ;
326- ctx .parent = NULL ;
352+ memset (& ctx , 0 , sizeof (ctx ));
327353 ctx .space = filepath ;
328354 doc = xmlParseFile (filepath );
329355 if (!doc ) {
0 commit comments