00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <stdlib.h>
00027 #include <string.h>
00028 #include <xmlparse.h>
00029
00030 #include "debug.h"
00031 #include "macros.h"
00032 #include "Common.h"
00033 #include "Memory.h"
00034 #include "Locale.h"
00035 #include "Skin.h"
00036 #include "Window.h"
00037
00038 #include "xml_Gui.h"
00039
00040
00041 #define GXML_MAXIMUM_LEVEL 64
00042 #define GXML_TAGLISTSIZE 32
00043
00044 struct gxml_GadgetInfo
00045 {
00046 u32 gadget_id;
00047 char *class_name;
00048 };
00049
00050
00051 struct gxml_UserData
00052 {
00053 Gadget_t *tree;
00054 int level;
00055 int status;
00056 char *layoutname;
00057 char *layouttype;
00058 Window_t *window;
00059 gadget_Check_t *check;
00060 List_t *gadget_list;
00061 int err;
00062 gadget_Binding_t *commonbind;
00063 char *appname;
00064 Locale_t *locale;
00065 u32 gadget_id_base;
00066 Gadget_t *gadgets[GXML_MAXIMUM_LEVEL];
00067 tag taglist[GXML_TAGLISTSIZE];
00068 };
00069
00070
00071 #define ERR_NONE 0
00072 #define ERR_OUT_OF_MEMORY 1
00073 #define ERR_INVALID_DATATYPE 2
00074 #define ERR_CANT_CREATE_GADGET 3
00075 #define ERR_TOO_DEEP_HIERARCHY 4
00076 #define ERR_ILLEGAL_CLASS 5
00077 #define ERR_VALIDATE_ERROR 6
00078 #define ERR_XML_ERROR 7
00079 #define ERR_REQUIRED_MISSING 8
00080 #define ERR_TYPE_MISMATCH 9
00081
00082
00083 static u32 (*call_vector[GXML_FUNC_DONE-GXML_FUNCBASE+1])(tag *);
00084
00085
00086 #if DEBUG_LEVEL >= 1
00087 static char *errstr[]=
00088 {
00089 "OK",
00090 "Out of memory",
00091 "Invalid datatype",
00092 "Can't create gadget",
00093 "Too deep hierarchy",
00094 "Illegal class",
00095 "Validate error",
00096 "XML error",
00097 "Required ID missing",
00098 "Type mismatch",
00099 NULL
00100 };
00101 #endif
00102
00103
00104 static int gxml_HandleAttr(struct gxml_UserData *u, tag *curr_tag, char *name, char *value, gadget_Binding_t *bind)
00105 {
00106 debug_Begin();
00107
00108 curr_tag->Name=TAG_SKIP;
00109 if(u->commonbind!=NULL) gadget_Bind(TAG_GADGET_LOCALE,u->locale,TAG_GADGET_BINDING,u->commonbind,
00110 TAG_GADGET_NAME,name,TAG_GADGET_VALUE,value,TAG_GADGET_TAGNAME,&curr_tag->Name,
00111 TAG_GADGET_TAGVALUE,&curr_tag->Data,TAG_DONE);
00112 if(curr_tag->Name==TAG_SKIP) gadget_Bind(TAG_GADGET_LOCALE,u->locale,TAG_GADGET_BINDING,bind,
00113 TAG_GADGET_NAME,name,TAG_GADGET_VALUE,value,TAG_GADGET_TAGNAME,&curr_tag->Name,
00114 TAG_GADGET_TAGVALUE,&curr_tag->Data,TAG_DONE);
00115
00116 debug_End();
00117
00118 return(1);
00119 }
00120
00121
00122 static void gxml_StartElement(void *userData, const char *name, const char **atts)
00123 {
00124 struct gxml_UserData *u=(struct gxml_UserData *)userData;
00125 int i,_w,_i,tagindex;
00126 char *id,*app,*type;
00127 gadget_Descriptor_t dsc;
00128 gadget_ClassData_t *gadget_class;
00129 Gadget_t *parent;
00130 gadget_Binding_t *bind;
00131 Node_t *node;
00132 struct gxml_GadgetInfo *ginfo;
00133
00134 debug_Begin();
00135
00136 u->level++;
00137
00138 if(u->status==0)
00139 {
00140 if((strcmp(name,"Gui")==0))
00141 {
00142 if(u->appname!=NULL)
00143 {
00144 if(NULL!=(app=common_GetAttr(atts,"App")))
00145 {
00146
00147 if(strcmp(u->appname,app)==0) u->status=1;
00148 }
00149 else u->status=1;
00150 }
00151 else u->status=1;
00152 }
00153 }
00154 else if(u->status==1)
00155 {
00156 if((strcmp(name,"Layout")==0)&&NULL!=(id=common_GetAttr(atts,"id"))&&NULL!=(type=common_GetAttr(atts,"type")))
00157 {
00158 if(strcmp(id,u->layoutname)==0)
00159 {
00160 if(NULL==u->layouttype||0==strcmp(type,u->layouttype))
00161
00162 if(NULL!=u->layouttype)
00163 {
00164 if(strcmp(type,"system")==0) u->gadget_id_base=GADGET_SYSBASE;
00165 else if(strcmp(type,"gadget")==0) u->gadget_id_base=GADGET_SUBGADGET_BASE;
00166 }
00167 u->status=2;
00168 }
00169 }
00170 }
00171 else if(u->status>1)
00172 {
00173 dsc.level=u->level-3;
00174 dsc.class_name=(char *)name;
00175
00176
00177
00178
00179
00180
00181 if(NULL==(gadget_class=(gadget_ClassData_t *)gadget_FindClassByName(TAG_GADGET_CLASS_NAME,dsc.class_name,TAG_DONE)))
00182 {
00183 gadget_LoadClass(window_GetApp(u->window),dsc.class_name,window_GetSkin(u->window));
00184 }
00185
00186 if(NULL!=(gadget_class=(gadget_ClassData_t *)gadget_FindClassByName(TAG_GADGET_CLASS_NAME,dsc.class_name,TAG_DONE)))
00187 {
00188 bind=gadget_class->xmlbinding;
00189 dsc.gadget_id=GADGET_ILLEGAL_ID;
00190 dsc.weight=1;
00191 for(i=0;atts[i]!=NULL;i+=2);
00192 i>>=1;
00193 dsc.taglist=u->taglist;
00194 if(i>=GXML_TAGLISTSIZE) dsc.taglist=mem_malloc((i+1)*sizeof(tag));
00195 if(dsc.taglist!=NULL)
00196 {
00197 for(tagindex=_w=_i=i=0;atts[i]!=NULL;i+=2)
00198 {
00199
00200 if(_w==0&&strcmp(atts[i],"weight")==0)
00201 {
00202 _w=1;
00203 dsc.weight=atoi(atts[i+1]);
00204
00205 }
00206 else if(_i==0&&strcmp(atts[i],"id")==0)
00207 {
00208 _i=1;
00209 dsc.gadget_id=atoi(atts[i+1])+u->gadget_id_base;
00210
00211 node=list_CreateNode();
00212 if(node!=NULL&&NULL!=(ginfo=mem_malloc(sizeof(struct gxml_GadgetInfo))))
00213 {
00214 ginfo->gadget_id=dsc.gadget_id;
00215 ginfo->class_name=gadget_class->class_name;
00216 list_SetNodeData(node,ginfo);
00217 list_InsertNodeTail(u->gadget_list,node);
00218 } else u->err=ERR_OUT_OF_MEMORY;
00219 }
00220 else
00221 {
00222 tagindex+=gxml_HandleAttr(u,&dsc.taglist[tagindex],(char *)atts[i],(char *)atts[i+1],bind);
00223 }
00224 }
00225 if(dsc.level<GXML_MAXIMUM_LEVEL)
00226 {
00227 parent=NULL;
00228 if(dsc.level>0) parent=u->gadgets[dsc.level-1];
00229
00230
00231 dsc.taglist[tagindex].Name=TAG_DONE;
00232 dsc.taglist[tagindex].Data=0L;
00233 u->gadgets[dsc.level]=(Gadget_t *)gadget_New(TAG_GADGET_DESCRIPTOR,&dsc,TAG_GADGET_WINDOW,u->window,TAG_GADGET_PARENT,parent,TAG_DONE);
00234 if(u->gadgets[dsc.level]==NULL) u->err=ERR_CANT_CREATE_GADGET;
00235 }
00236 else u->err=ERR_TOO_DEEP_HIERARCHY;
00237 if(dsc.taglist!=u->taglist) mem_free(dsc.taglist);
00238 }
00239 } else { u->err=ERR_ILLEGAL_CLASS; debug_Error("Illegal class found!"); }
00240 }
00241
00242 debug_End();
00243 }
00244
00245
00246 static void gxml_EndElement(void *userData, const char *name)
00247 {
00248 struct gxml_UserData *u=(struct gxml_UserData *)userData;
00249
00250 debug_Begin();
00251
00252
00253 u->level--;
00254 if(strcmp(name,"Layout")==0&&u->status>1&&u->level<=4) u->status=-1;
00255
00256 debug_End();
00257 }
00258
00259
00260 static int gxml_CheckGui(gadget_Check_t *check, List_t *gadget_list)
00261 {
00262 int ret=0,i;
00263 Node_t *node;
00264 struct gxml_GadgetInfo *ginfo;
00265
00266 debug_Begin();
00267
00268 for(i=0;check[i].gadget_id!=GADGET_ILLEGAL_ID;i++)
00269 {
00270
00271 for(ginfo=NULL,node=list_GetNodeHead(gadget_list);node!=NULL;node=list_GetNodeNext(gadget_list,node))
00272 {
00273 ginfo=(struct gxml_GadgetInfo *)list_GetNodeData(node);
00274 if(ginfo->gadget_id==check[i].gadget_id) break;
00275 ginfo=NULL;
00276 }
00277 if((check[i].flags&GADGET_REQUIRED)!=0&&ginfo==NULL) { ret=ERR_REQUIRED_MISSING; break; }
00278 if(ginfo!=NULL&&0!=strcmp(ginfo->class_name,check[i].class_name)) { ret=ERR_TYPE_MISMATCH; break; }
00279 }
00280
00281 debug_End();
00282
00283 return(ret);
00284 }
00285
00286
00296 u32 gxml_CreateGadgetTree(u32 firsttag, ...)
00297 {
00298 return(gxml_CreateGadgetTreeTL((tag *)&firsttag));
00299 }
00300 u32 gxml_CreateGadgetTreeTL(tag *taglist)
00301 {
00302 char *xml_file;
00303 Locale_t *locale;
00304 char *type;
00305 char *layoutname;
00306 char *appname;
00307 Window_t *window;
00308 gadget_Check_t *check;
00309
00310 Gadget_t *ret=NULL;
00311 int xmlret,valid=0,err=ERR_OUT_OF_MEMORY;
00312 XML_Parser ctxt;
00313 struct gxml_UserData *userdata;
00314 Node_t *node,*nextnode;
00315 struct gxml_GadgetInfo *ginfo;
00316
00317 debug_Begin();
00318
00319 xml_file=(char *)tag_GetTagData(taglist,TAG_GXML_XML_FILE,0L);
00320 locale=(Locale_t *)tag_GetTagData(taglist,TAG_GXML_LOCALE,0L);
00321 type=(char *)tag_GetTagData(taglist,TAG_GXML_TYPE,0L);
00322 layoutname=(char *)tag_GetTagData(taglist,TAG_GXML_LAYOUTNAME,0L);
00323 appname=(char *)tag_GetTagData(taglist,TAG_GXML_APPNAME,0L);
00324 window=(Window_t *)tag_GetTagData(taglist,TAG_GXML_WINDOW,0L);
00325 check=(gadget_Check_t *)tag_GetTagData(taglist,TAG_GXML_CHECK,0L);
00326
00327 if(xml_file!=NULL&&NULL!=(userdata=mem_malloc(sizeof(struct gxml_UserData))))
00328 {
00329 userdata->tree=NULL;
00330 userdata->level=0;
00331 userdata->status=0;
00332 userdata->layoutname=layoutname;
00333 userdata->window=window;
00334 userdata->gadgets[0]=NULL;
00335 userdata->check=check;
00336 userdata->err=0;
00337 userdata->commonbind=gadget_GetCommonBind();
00338 userdata->appname=appname;
00339 userdata->layouttype=type;
00340 userdata->locale=locale;
00341 userdata->gadget_id_base=0;
00342 if(NULL!=(userdata->gadget_list=list_CreateList()))
00343 {
00344 if((ctxt=XML_ParserCreate(NULL)))
00345 {
00346 XML_SetUserData(ctxt,userdata);
00347 XML_SetElementHandler(ctxt,gxml_StartElement,gxml_EndElement);
00348 xmlret=XML_Parse(ctxt,xml_file,strlen(xml_file),TRUE);
00349 if(!xmlret)
00350 {
00351 debug_Error("%s at line %d\n",XML_ErrorString(XML_GetErrorCode(ctxt)),XML_GetCurrentLineNumber(ctxt));
00352 userdata->err=ERR_XML_ERROR;
00353 }
00354 XML_ParserFree(ctxt);
00355 }
00356 if(userdata->check!=NULL) valid=gxml_CheckGui(userdata->check,userdata->gadget_list);
00357 for(node=list_GetNodeHead(userdata->gadget_list);node!=NULL;node=nextnode)
00358 {
00359 nextnode=list_GetNodeNext(userdata->gadget_list,node);
00360 list_RemoveNode(userdata->gadget_list,node);
00361 if(NULL!=(ginfo=list_GetNodeData(node)))
00362 {
00363 list_SetNodeData(node,NULL);
00364 mem_free(ginfo);
00365 }
00366 list_DeleteNode(node);
00367 }
00368 list_DeleteList(userdata->gadget_list);
00369 if(valid!=0)
00370 {
00371 userdata->err=valid;
00372 if(NULL!=userdata->gadgets[0]) gadget_DeleteSubtree(TAG_GADGET_OBJECT,userdata->gadgets[0],TAG_DONE);
00373 userdata->gadgets[0]=NULL;
00374 }
00375 }
00376 ret=userdata->gadgets[0];
00377 err=userdata->err;
00378 mem_free(userdata);
00379 }
00380 if(err!=0) debug_Error("%s\n",errstr[err]);
00381
00382 debug_End();
00383
00384 return((u32)ret);
00385 }
00386
00387 int gxml_Init(void)
00388 {
00389 call_vector[GXML_CREATEGADGETTREE-GXML_FUNCBASE]=gxml_CreateGadgetTreeTL;
00390 bases_modules.gxml_Call=gxml_Call;
00391 bases_modules.gxml_CallTL=gxml_CallTL;
00392 return(0);
00393 }
00394
00395 void gxml_CleanUp(void)
00396 {
00397 debug_Begin();
00398 debug_End();
00399
00400 return;
00401 }
00402
00403
00404 u32 gxml_Call(int function, u32 firsttag, ...)
00405 {
00406 return(gxml_CallTL(function,(tag *)&firsttag));
00407 }
00408 u32 gxml_CallTL(int function, tag *taglist)
00409 {
00410 u32 ret=~0L;
00411
00412 debug_Begin();
00413
00414 debug_Message("function ID : %d",function-GXML_FUNCBASE);
00415
00416 if(function>=GXML_FUNCBASE&&function<GXML_FUNC_DONE)
00417 {
00418 ret=call_vector[function-GXML_FUNCBASE](taglist);
00419 }
00420 else debug_Warning("%s(): Function code out of range! code=0x%04x",__FUNCTION__,function);
00421
00422 debug_End();
00423
00424 return(ret);
00425 }