00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <stdlib.h>
00025 #include <string.h>
00026 #include <xmlparse.h>
00027
00028 #include "debug.h"
00029 #include "macros.h"
00030 #include "Locale.h"
00031 #include "Common.h"
00032 #include "Memory.h"
00033 #include "Net.h"
00034
00035
00036 typedef struct LocaleItem_s
00037 {
00038 char *key;
00039 char *value;
00040 } LocaleItem_t;
00041
00042 struct Locale_s
00043 {
00044 gui_App_t *app;
00045 char *filename;
00046 char lang[3];
00047 int itemcount;
00048 LocaleItem_t *items;
00049 };
00050
00051 typedef struct LocaleParse_s
00052 {
00053 Locale_t *locale;
00054 List_t *keypairlist;
00055 int err;
00056 int parse_status;
00057 } LocaleParse_t;
00058
00059
00060 #define ERR_LOC_OK 0
00061 #define ERR_LOC_XML 1
00062 #define ERR_LOC_OUT_OF_MEMORY 2
00063 #define ERR_LOC_ARGUMENT_MISSING 3
00064 #define ERR_LOC_APP_NOTFOUND 4
00065 #define ERR_LOC_CLOSING_NOTFOUND 5
00066 #define ERR_LOC_LOCALE_CANTLOAD 6
00067
00068
00069 static u32 (*call_vector[LOCALE_FUNC_DONE-LOCALE_FUNCBASE+1])(tag *);
00070
00071 static char extension_gui[]="_gui_";
00072 static char extension_xml[]=".xml";
00073 #if DEBUG_LEVEL >= 1
00074 static char *errstr[]=
00075 {
00076 "OK",
00077 "XML Error",
00078 "Out of memory",
00079 "Argument missing",
00080 "App section not found",
00081 "Closing tag not found",
00082 "Locale XML cannot be loaded",
00083 NULL
00084 };
00085 #endif
00086
00087 static Locale_t *locale_CleanUpInternal(Locale_t *locale)
00088 {
00089 locale_CleanUp(locale);
00090 return(NULL);
00091 }
00092
00093
00094 static int locale_cmp(const void *e1, const void *e2)
00095 {
00096 LocaleItem_t *i1=(LocaleItem_t *)e1,*i2=(LocaleItem_t *)e2;
00097 return(strcmp(i1->key,i2->key));
00098 }
00099
00100
00101 static void locale_StartElement(void *userData, const char *name, const char **atts)
00102 {
00103 LocaleParse_t *locparse=(LocaleParse_t *)userData;
00104 int i;
00105 char *att,*value,*key;
00106 Node_t *node;
00107 LocaleItem_t *item;
00108
00109 debug_Begin();
00110
00111
00112 if(locparse->parse_status==0)
00113 {
00114 if(strcmp(name,"Translation")==0)
00115 {
00116 if(NULL!=(att=common_GetAttr(atts,"app"))&&strcmp(att,locparse->locale->app->name)==0)
00117 {
00118 locparse->parse_status=1;
00119 }
00120 }
00121 }
00122 else if(locparse->parse_status>0)
00123 {
00124 if(strcmp(name,"String")==0)
00125 {
00126 key=value=NULL;
00127 for(i=0;atts[i]!=NULL;i+=2)
00128 {
00129 if(strcmp(atts[i],"name")==0) key=(char *)atts[i+1];
00130 if(strcmp(atts[i],"value")==0) value=(char *)atts[i+1];
00131 }
00132 if(key!=NULL&&value!=NULL)
00133 {
00134 node=list_CreateNode();
00135 item=mem_malloc(sizeof(LocaleItem_t));
00136 item->key=mem_malloc(strlen(key)+1);
00137 item->value=mem_malloc(strlen(value)+1);
00138 if(node!=NULL&&item!=NULL&&item->key!=NULL&&item->value!=NULL)
00139 {
00140 list_SetNodeData(node,item);
00141 strcpy(item->key,key);
00142 strcpy(item->value,value);
00143 list_InsertNodeHead(locparse->keypairlist,node);
00144 }
00145 else locparse->err=ERR_LOC_OUT_OF_MEMORY;
00146 }
00147 else locparse->err=ERR_LOC_ARGUMENT_MISSING;
00148 }
00149 }
00150
00151 debug_End();
00152 }
00153
00154
00155 static void locale_EndElement(void *userData, const char *name)
00156 {
00157 LocaleParse_t *locparse=(LocaleParse_t *)userData;
00158
00159 debug_Begin();
00160
00161 if(locparse->parse_status>0&&strcmp(name,"Translation")==0) locparse->parse_status=-1;
00162
00163
00164 debug_End();
00165 }
00166
00167
00168 static Locale_t *locale_InitInternal(gui_App_t *app, char *lang)
00169 {
00170 Locale_t *locale=NULL;
00171 LocaleParse_t locparse;
00172 LocaleItem_t *item;
00173 int name_size,xmlret,i;
00174 char *file;
00175 XML_Parser ctxt;
00176 Node_t *node,*nextnode;
00177
00178 debug_Begin();
00179
00180 locparse.keypairlist=NULL;
00181 locparse.locale=NULL;
00182 locparse.err=ERR_LOC_OK;
00183 locparse.parse_status=0;
00184 if(lang!=NULL&&NULL!=(locale=mem_calloc(1,sizeof(Locale_t))))
00185 {
00186
00187 name_size=strlen(app->name)+strlen(extension_gui)+2+strlen(extension_xml);
00188 locale->app=app;
00189 locale->lang[0]=lang[0];
00190 locale->lang[1]=lang[1];
00191 locale->lang[2]='\0';
00192 locale->itemcount=0;
00193 if(NULL!=(locale->filename=mem_malloc(name_size+1)))
00194 {
00195 strcpy(locale->filename,app->name);
00196 strcat(locale->filename,extension_gui);
00197 strcat(locale->filename,locale->lang);
00198 strcat(locale->filename,extension_xml);
00199
00200 if(NULL!=(file=(char *)net_LoadFile(TAG_NET_CONN,locale->app->conn,TAG_NET_NAME,locale->filename,TAG_DONE)))
00201 {
00202 locparse.locale=locale;
00203 if(NULL!=(locparse.keypairlist=list_CreateList()))
00204 {
00205 if((ctxt=XML_ParserCreate(NULL)))
00206 {
00207 XML_SetUserData(ctxt,&locparse);
00208 XML_SetElementHandler(ctxt,locale_StartElement,locale_EndElement);
00209 xmlret=XML_Parse(ctxt,file,strlen(file),TRUE);
00210 if(!xmlret)
00211 {
00212 locparse.err=ERR_LOC_XML;
00213 debug_Error("%s: %s at line %d\n",locale->filename,XML_ErrorString(XML_GetErrorCode(ctxt)),XML_GetCurrentLineNumber(ctxt));
00214 }
00215 XML_ParserFree(ctxt);
00216 }
00217 locale->itemcount=list_GetNodeCount(locparse.keypairlist);
00218 if(NULL!=(locale->items=mem_malloc(locale->itemcount*sizeof(LocaleItem_t))))
00219 {
00220 for(i=0,node=list_GetNodeHead(locparse.keypairlist);node!=NULL;node=nextnode,i++)
00221 {
00222 nextnode=list_GetNodeNext(locparse.keypairlist,node);
00223 list_RemoveNode(locparse.keypairlist,node);
00224 if(NULL!=(item=list_GetNodeData(node)))
00225 {
00226 locale->items[i].key=item->key;
00227 locale->items[i].value=item->value;
00228 mem_free(item);
00229 }
00230 list_DeleteNode(node);
00231 }
00232 qsort(locale->items,locale->itemcount,sizeof(LocaleItem_t),locale_cmp);
00233 if(locparse.parse_status>=0||locparse.err!=ERR_LOC_OK)
00234 {
00235 locale=locale_CleanUpInternal(locale);
00236 if(locparse.parse_status==0) locparse.err=ERR_LOC_APP_NOTFOUND;
00237 else if(locparse.parse_status>0) locparse.err=ERR_LOC_CLOSING_NOTFOUND;
00238 }
00239 }
00240 else locale=locale_CleanUpInternal(locale);
00241 list_DeleteList(locparse.keypairlist);
00242 }
00243 mem_free(file);
00244 }
00245 else locale=locale_CleanUpInternal(locale);
00246 }
00247 else locale=locale_CleanUpInternal(locale);
00248 }
00249 if(locale==NULL&&locparse.err!=0) debug_Warning("%s",errstr[locparse.err]);
00250
00251 debug_End();
00252
00253 return(locale);
00254 }
00255
00256
00257 Locale_t *locale_Init(gui_App_t *app, char **lang, char *default_lang)
00258 {
00259 Locale_t *locale=NULL;
00260 int i;
00261
00262 debug_Begin();
00263
00264 call_vector[LOCALE_GETSTRING-LOCALE_FUNCBASE]=locale_GetStringTL;
00265 bases_modules.locale_Call=locale_Call;
00266 bases_modules.locale_CallTL=locale_CallTL;
00267
00268 if(lang!=NULL) for(i=0;lang[i]!=NULL&&locale==NULL;i++) locale=locale_InitInternal(app,lang[i]);
00269 if(locale==NULL) locale=locale_InitInternal(app,default_lang);
00270 if(locale==NULL) debug_Error("%s",errstr[ERR_LOC_LOCALE_CANTLOAD]);
00271
00272 debug_End();
00273
00274 return(locale);
00275 }
00276
00277
00278 void locale_CleanUp(Locale_t *locale)
00279 {
00280 int i;
00281
00282 debug_Begin();
00283
00284 if(locale!=NULL)
00285 {
00286 if(locale->filename!=NULL) mem_free(locale->filename);
00287 if(locale->items!=NULL)
00288 {
00289 for(i=0;i<locale->itemcount;i++)
00290 {
00291 if(NULL!=locale->items[i].key) mem_free(locale->items[i].key);
00292 if(NULL!=locale->items[i].value) mem_free(locale->items[i].value);
00293 }
00294 mem_free(locale->items);
00295 }
00296 mem_free(locale);
00297 }
00298
00299 debug_End();
00300 }
00301
00302
00307 u32 locale_GetString(u32 firsttag, ...)
00308 {
00309 return(locale_GetStringTL((tag *)&firsttag));
00310 }
00311 u32 locale_GetStringTL(tag *taglist)
00312 {
00313 Locale_t *locale;
00314 char *msg;
00315
00316 LocaleItem_t key,*found;
00317
00318 debug_Begin();
00319
00320 locale=(Locale_t *)tag_GetTagData(taglist,TAG_LOCALE_LOCALE,0L);
00321 msg=(char *)tag_GetTagData(taglist,TAG_LOCALE_MSG,0L);
00322
00323 if(locale!=NULL)
00324 {
00325 key.key=msg;
00326 found=bsearch(&key,locale->items,locale->itemcount,sizeof(LocaleItem_t),locale_cmp);
00327 if(found!=NULL) msg=found->value;
00328 }
00329
00330 debug_End();
00331
00332 return((u32)msg);
00333 }
00334
00335
00336 u32 locale_Call(int function, u32 firsttag, ...)
00337 {
00338 return(locale_CallTL(function,(tag *)&firsttag));
00339 }
00340 u32 locale_CallTL(int function, tag *taglist)
00341 {
00342 u32 ret=~0L;
00343
00344 debug_Begin();
00345
00346 debug_Message("function ID : %d",function-LOCALE_FUNCBASE);
00347
00348 if(function>=LOCALE_FUNCBASE&&function<LOCALE_FUNC_DONE)
00349 {
00350 ret=call_vector[function-LOCALE_FUNCBASE](taglist);
00351 }
00352 else debug_Warning("%s(): Function code out of range! code=0x%04x",__FUNCTION__,function);
00353
00354 debug_End();
00355
00356 return(ret);
00357 }