Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

themeloader.cpp

Go to the documentation of this file.
00001 /*
00002     ParaGUI - crossplatform widgetset
00003     Copyright (C) 2000,2001,2002  Alexander Pipelka
00004  
00005     This library is free software; you can redistribute it and/or
00006     modify it under the terms of the GNU Library General Public
00007     License as published by the Free Software Foundation; either
00008     version 2 of the License, or (at your option) any later version.
00009  
00010     This library is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013     Library General Public License for more details.
00014  
00015     You should have received a copy of the GNU Library General Public
00016     License along with this library; if not, write to the Free
00017     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018  
00019     Alexander Pipelka
00020     pipelka@teleweb.at
00021  
00022     Last Update:      $Author: mbickel $
00023     Update Date:      $Date: 2007-04-13 16:16:02 $
00024     Source File:      $Source: /home/cvspsrv/cvsroot/games/asc/source/libs/paragui/src/themes/themeloader.cpp,v $
00025     CVS/RCS Revision: $Revision: 1.2 $
00026     Status:           $State: Exp $
00027 */
00028 
00029 #include "paragui.h"
00030 #include "pgcolor.h"
00031 
00032 #include "theme_priv.h"
00033 #include "pglog.h"
00034 #include "pgfilearchive.h"
00035 #include "pgdraw.h"
00036 
00037 #include <string>
00038 #include <expat.h>
00039 #include <iostream>
00040 
00041 // Expat UNICODE workaround - copied from xmltchar.h (Expat dist) - Inserted by Ales Teska
00042 #ifdef XML_UNICODE
00043 #ifndef XML_UNICODE_WCHAR_T
00044 #error UNICODE version requires a 16-bit Unicode-compatible wchar_t=20
00045 #endif
00046 #define T(x) L ## x
00047 #define tcscmp wcscmp
00048 #else /* not XML_UNICODE */
00049 #define T(x) x
00050 #define tcscmp strcmp
00051 #endif
00052 
00053 typedef struct _PARSE_INFO {
00054         int depth;
00055         int mode;
00056         THEME_THEME* theme;
00057         std::string str_currentWidget;
00058         std::string str_currentObject;
00059         THEME_WIDGET* p_currentWidget;
00060         THEME_OBJECT* p_currentObject;
00061         std::string themename;
00062 }
00063 PARSE_INFO;
00064 
00065 
00066 #define THEMEMODE_NONE                  0
00067 #define THEMEMODE_THEME                 1
00068 #define THEMEMODE_WIDGET                2
00069 #define THEMEMODE_OBJECT                3
00070 
00071 #define THEME_SUFFIX ".theme"
00072 
00073 #define BUFFSIZE        8192
00074 
00075 static char* buff;
00076 
00077 void parseGlobProps(PARSE_INFO* info, const XML_Char* name, const XML_Char** atts) {
00078 
00079         if(strcmp(name, "theme") == 0) {
00080                 // create new theme template
00081                 info->theme = new THEME_THEME;
00082         } else {
00083                 std::cerr << "UNKNOWN PROP: " << name << std::endl;
00084         }
00085 }
00086 
00087 void parseThemeProps(PARSE_INFO* info, const XML_Char* prop, const XML_Char** atts) {
00088         const XML_Char* val = atts[1];
00089         int i=0;
00090 
00091         if(tcscmp(T(prop), T("title")) == 0) {
00092                 info->theme->title = val;
00093         } else if (tcscmp(T(prop), T("description")) == 0) {
00094                 info->theme->description = val;
00095         } else if (tcscmp(T(prop), T("author")) == 0) {
00096                 info->theme->author = val;
00097         } else if (tcscmp(T(prop), T("email")) == 0) {
00098                 info->theme->email = val;
00099         } else if (tcscmp(T(prop), T("widget")) == 0) {
00100                 THEME_WIDGET* widget = new THEME_WIDGET;
00101                 widget->type = "";
00102                 info->p_currentWidget = widget;
00103                 info->mode = THEMEMODE_WIDGET;
00104         } else if(tcscmp(T(prop), T("font")) == 0) {
00105                 THEME_FONT* font = new THEME_FONT;
00106                 font->size = 14;
00107 
00108                 for(i=0; atts[i]; i += 2) {
00109                         if(tcscmp(T(atts[i]), T("name")) == 0) {
00110                                 font->name = atts[i+1];
00111                         } else if(tcscmp(T(atts[i]), T("value")) == 0) {
00112                                 font->value = atts[i+1];
00113                         } else if(tcscmp(T(atts[i]), T("size")) == 0) {
00114                                 font->size = atoi(atts[i+1]);
00115                         } else {
00116                                 std::cerr << "UNKNOWN FONT ATTRIBUTE: " << atts[i] << std::endl;
00117                         }
00118                 }
00119 
00120                 info->theme->defaultfont = font;
00121         } else {
00122                 std::cerr << "UNKNOWN THEME ATTRIBUTE: " << prop << std::endl;
00123         }
00124 
00125 }
00126 
00127 void parseWidgetProps(PARSE_INFO* info, const XML_Char* prop, const XML_Char** atts) {
00128         std::string val=atts[1];
00129 
00130         if(tcscmp(T(prop), T("type")) == 0) {
00131                 info->p_currentWidget->type = val;
00132                 info->theme->widget[val] = info->p_currentWidget;
00133         } else if(tcscmp(T(prop), T("object")) == 0) {
00134                 THEME_OBJECT* object = new THEME_OBJECT;
00135                 object->type = "";
00136                 object->name = "";
00137                 info->p_currentObject = object;
00138                 info->mode = THEMEMODE_OBJECT;
00139         } else {
00140                 std::cerr << "UNKNOWN WIDGET ATTRIBUTE: " << prop << std::endl;
00141         }
00142 }
00143 
00144 void parseObjectProps(PARSE_INFO* info, const XML_Char* prop, const XML_Char** atts) {
00145         std::string val=atts[1];
00146         int i;
00147         THEME_OBJECT* object = info->p_currentObject;
00148 
00149         //
00150         //      TYPE
00151         //
00152 
00153         if(tcscmp(T(prop), T("type")) == 0) {
00154                 object->type = val;
00155         }
00156 
00157         //
00158         //      NAME
00159         //
00160 
00161         else if(tcscmp(T(prop), T("name")) == 0) {
00162                 object->name = val;
00163                 info->p_currentWidget->object[object->name] = object;
00164         }
00165 
00166         //
00167         //      FILENAME
00168         //
00169 
00170         else if(tcscmp(T(prop), T("filename")) == 0) {
00171                 THEME_FILENAME* filename = new THEME_FILENAME;
00172                 filename->hasColorKey = false;
00173 
00174                 for(i=0; atts[i]; i += 2) {
00175                         if(tcscmp(T(atts[i]), T("name")) == 0) {
00176                                 filename->name = atts[i+1];
00177                         } else if(tcscmp(T(atts[i]), T("value")) == 0) {
00178                                 filename->value = atts[i+1];
00179                         } else if(tcscmp(T(atts[i]), T("colorkey")) == 0) {
00180                                 sscanf(atts[i+1], "0x%08x", (unsigned int*)(&filename->colorkey));
00181                                 filename->hasColorKey = true;
00182                         } else {
00183                                 std::cerr << "UNKNOWN FILENAME ATTRIBUTE: " << atts[i] << std::endl;
00184                         }
00185                 }
00186 
00187                 // load the image file
00188                 filename->surface = PG_FileArchive::LoadSurface(filename->value, true);
00189 
00190                 if(filename->surface == NULL) {
00191                         delete filename;
00192                         return;
00193                 }
00194 
00195                 // set the colorkey (if there is any)
00196                 if(filename->hasColorKey && filename->surface) {
00197                         PG_Color c = filename->colorkey;
00198                         Uint32 key = c.MapRGB(filename->surface->format);
00199                         SDL_SetColorKey(filename->surface, SDL_SRCCOLORKEY, key);
00200                 }
00201                 object->filename[filename->name] = filename;
00202         }
00203 
00204         //
00205         //      FONT
00206         //
00207 
00208         else if(tcscmp(T(prop), T("font")) == 0) {
00209                 THEME_FONT* font = new THEME_FONT;
00210                 font->size = 14;
00211 
00212                 for(i=0; atts[i]; i += 2) {
00213                         if(tcscmp(T(atts[i]), T("name")) == 0) {
00214                                 font->name = atts[i+1];
00215                         } else if(tcscmp(T(atts[i]), T("value")) == 0) {
00216                                 font->name = atts[i+1];
00217                                 font->value = atts[i+1];
00218                         } else if(tcscmp(T(atts[i]), T("size")) == 0) {
00219                                 font->size = atoi(atts[i+1]);
00220                         } else {
00221                                 std::cerr << "UNKNOWN FONT ATTRIBUTE: " << atts[i] << std::endl;
00222                         }
00223                 }
00224 
00225                 object->font = font;
00226         }
00227 
00228         //
00229         //      PROPERTY
00230         //
00231 
00232         else if(tcscmp(T(prop), T("property")) == 0) {
00233                 THEME_PROPERTY* property = new THEME_PROPERTY;
00234 
00235                 for(i=0; atts[i]; i += 2) {
00236                         if(tcscmp(T(atts[i]), T("name")) == 0) {
00237                                 property->name = atts[i+1];
00238                         } else if(tcscmp(T(atts[i]), T("value")) == 0) {
00239                                 if(tcscmp(T(atts[i+1]), T("TILE")) == 0) {
00240                                         property->value = PG_Draw::TILE;
00241                                 } else if(tcscmp(T(atts[i+1]), T("STRETCH")) == 0) {
00242                                         property->value = PG_Draw::STRETCH;
00243                                 } else if(tcscmp(T(atts[i+1]), T("3TILEH")) == 0) {
00244                                         property->value = PG_Draw::TILE3H;
00245                                 } else if(tcscmp(T(atts[i+1]), T("3TILEV")) == 0) {
00246                                         property->value = PG_Draw::TILE3V;
00247                                 } else if(tcscmp(T(atts[i+1]), T("9TILE")) == 0) {
00248                                         property->value = PG_Draw::TILE9;
00249                                 } else {
00250                                         property->value = atoi(atts[i+1]);
00251                                 }
00252                         } else {
00253                                 std::cerr << "UNKNOWN PROPERTY ATTRIBUTE: " << atts[i] << std::endl;
00254                         }
00255                 }
00256                 object->property[property->name] = property;
00257         }
00258 
00259         //
00260         //      COLOR
00261         //
00262 
00263         else if(tcscmp(T(prop), T("color")) == 0) {
00264                 THEME_PROPERTY* property = new THEME_PROPERTY;
00265 
00266                 for(i=0; atts[i]; i += 2) {
00267                         if(tcscmp(T(atts[i]), T("name")) == 0) {
00268                                 property->name = atts[i+1];
00269                         } else if(tcscmp(T(atts[i]), T("value")) == 0) {
00270                                 unsigned int value;
00271                                 sscanf(atts[i+1], "0x%08x", &value);
00272                                 property->value = value;
00273                         } else {
00274                                 std::cerr << "UNKNOWN COLOR ATTRIBUTE: " << atts[i] << std::endl;
00275                         }
00276                 }
00277                 object->property[property->name] = property;
00278         }
00279 
00280         //
00281         //      GRADIENT
00282         //
00283 
00284         else if(tcscmp(T(prop), T("gradient")) == 0) {
00285                 THEME_GRADIENT* gradient = new THEME_GRADIENT;
00286                 Uint32 c;
00287                 std::string val;
00288 
00289                 for(i=0; atts[i]; i += 2) {
00290 
00291                         if(tcscmp(T(atts[i]), T("name")) == 0) {
00292                                 gradient->name = atts[i+1];
00293                         } else if(tcscmp(T(atts[i]), T("color0")) == 0) {
00294                                 val = atts[i+1];
00295                                 sscanf(val.c_str(), "0x%08x", &c);
00296                                 gradient->colors[0] = c;
00297                         } else if(tcscmp(T(atts[i]), T("color1")) == 0) {
00298                                 val = atts[i+1];
00299                                 sscanf(val.c_str(), "0x%08x", &c);
00300                                 gradient->colors[1] = c;
00301                         } else if(tcscmp(T(atts[i]), T("color2")) == 0) {
00302                                 val = atts[i+1];
00303                                 sscanf(val.c_str(), "0x%08x", &c);
00304                                 gradient->colors[2] = c;
00305                         } else if(tcscmp(T(atts[i]), T("color3")) == 0) {
00306                                 val = atts[i+1];
00307                                 sscanf(val.c_str(), "0x%08x", &c);
00308                                 gradient->colors[3] = c;
00309                         } else {
00310                                 std::cerr << "UNKNOWN PROPERTY ATTRIBUTE: " << atts[i] << std::endl;
00311                         }
00312                 }
00313 
00314                 /*for(i=0; i<4; i++) {
00315                         gradient->gradient.colors[i] = gradient->color[i];
00316                 }*/
00317 
00318                 object->gradient[gradient->name] = gradient;
00319         }
00320 
00321         //
00322         //      STRING
00323         //
00324         else if(tcscmp(T(prop), T("string")) == 0) {
00325                 THEME_STRING* str = new THEME_STRING;
00326 
00327                 for(i=0; atts[i]; i += 2) {
00328 
00329                         if(tcscmp(T(atts[i]), T("name")) == 0) {
00330                                 str->name = atts[i+1];
00331                         } else if(tcscmp(T(atts[i]), T("value")) == 0) {
00332                                 str->value = atts[i+1];
00333                         } else {
00334                                 std::cerr << "UNKNOWN STRING ATTRIBUTE: " << atts[i] << std::endl;
00335                         }
00336                 }
00337 
00338                 object->strings.insert(info->p_currentObject->strings.end(), str);
00339         }
00340 
00341         //
00342         //      UNKNOWN OBJECT ATTRIBUTE
00343         //
00344 
00345         else {
00346                 std::cerr << "UNKNOWN OBJECT ATTRIBUTE: " << prop << std::endl;
00347         }
00348 }
00349 
00350 
00351 void handlerStart(void* userData, const XML_Char *name, const XML_Char** atts) {
00352         PARSE_INFO* info = (PARSE_INFO*)userData;
00353 
00354         info->depth++;
00355 
00356         switch(info->mode) {
00357                 case THEMEMODE_NONE:
00358                         parseGlobProps(info, name, atts);
00359                         info->mode = THEMEMODE_THEME;
00360                         break;
00361 
00362                 case THEMEMODE_THEME:
00363                         parseThemeProps(info, name, atts);
00364                         break;
00365 
00366                 case THEMEMODE_WIDGET:
00367                         parseWidgetProps(info, name, atts);
00368                         break;
00369 
00370                 case THEMEMODE_OBJECT:
00371                         parseObjectProps(info, name, atts);
00372                         break;
00373         }
00374 }
00375 
00376 void handlerEnd(void* userData, const XML_Char* name) {
00377         PARSE_INFO* info = (PARSE_INFO*)userData;
00378 
00379         if(tcscmp(T(name), T("object")) == 0) {
00380                 info->mode = THEMEMODE_WIDGET;
00381         } else if(tcscmp(T(name), T("widget")) == 0) {
00382                 info->mode = THEMEMODE_THEME;
00383         } else if(tcscmp(T(name), T("theme")) == 0) {
00384                 info->mode = THEMEMODE_NONE;
00385         }
00386 
00387         info->depth--;
00388 }
00389 
00390 PG_Theme* PG_Theme::Load(const std::string& xmltheme) {
00391         std::string filename;
00392         buff = new char[BUFFSIZE];
00393 
00394         // create new parse info
00395         PARSE_INFO info;
00396 
00397         // init parseinfo
00398         info.theme = NULL;
00399         info.p_currentWidget = NULL;
00400         info.p_currentObject = NULL;
00401         info.depth = 0;
00402         info.mode = THEMEMODE_NONE;
00403 
00404         filename = xmltheme;
00405 
00406         // check if we have a compressed themefile somewhere
00407         filename = xmltheme + ".zip";
00408 
00409         // and add it to the searchpath
00410         if(PG_FileArchive::Exists(filename)) {
00411                 const char* path = PG_FileArchive::GetRealDir(filename);
00412                 char sep = PG_FileArchive::GetDirSeparator()[0];
00413 
00414                 std::string fullpath = (std::string)path;
00415                 if(fullpath[fullpath.size()-1] != sep) {
00416                         fullpath += sep;
00417                 }
00418                 fullpath += filename;
00419 
00420                 bool rc = PG_FileArchive::AddArchive(fullpath);
00421                 if(rc) {
00422                         PG_LogMSG("added '%s' to the searchpath", fullpath.c_str());
00423                 } else {
00424                         PG_LogWRN("failed to add '%s'", fullpath.c_str());
00425                         PG_LogWRN("%s", PG_FileArchive::GetLastError());
00426                 }
00427         }
00428 
00429         // try to open the theme
00430 
00431         filename = xmltheme + THEME_SUFFIX;
00432         if(!PG_FileArchive::Exists(filename)) {
00433                 PG_LogERR("theme '%s' not found !", filename.c_str());
00434                 return NULL;
00435         }
00436 
00437         info.themename = xmltheme;
00438 
00439         // create a parser
00440         XML_Parser p = XML_ParserCreate(NULL);
00441 
00442         // set userdata (parseinfo)
00443         XML_SetUserData(p, (void*)&info);
00444         XML_SetElementHandler(p, handlerStart, handlerEnd);
00445 
00446         // create an input-stream
00447 
00448         PG_File* file = PG_FileArchive::OpenFile(filename);
00449 
00450         if(!file) {
00451                 XML_ParserFree(p);
00452                 delete[] buff;
00453                 return NULL;
00454         }
00455 
00456         // do the parsing
00457         while (!file->eof()) {
00458                 int done;
00459 
00460                 int n = file->read(buff, BUFFSIZE);
00461                 done = file->eof();
00462 
00463                 if (! XML_Parse(p, buff, n, done)) {
00464                         PG_LogERR("Parse error at line %i:", XML_GetCurrentLineNumber(p));
00465                         PG_LogERR("%s", XML_ErrorString(XML_GetErrorCode(p)));
00466                         XML_ParserFree(p);
00467                         delete[] buff;
00468                         return NULL;
00469                 }
00470 
00471                 if(done) {
00472                         break;
00473                 }
00474         }
00475 
00476         // free the parser
00477         XML_ParserFree(p);
00478 
00479         // close the file
00480         delete file;
00481         delete[] buff;
00482 
00483         PG_LogMSG("theme '%s' loaded sucessfully", filename.c_str());
00484 
00485         return info.theme;
00486 }
00487 
00488 void PG_Theme::Unload(PG_Theme* theme) {
00489         delete theme;
00490 }

Generated on Tue Jun 24 01:27:53 2008 for Advanced Strategic Command by  doxygen 1.4.2