2 #include "tinyxml/tinyxml.h"
3 #include "../include/pnd_pxml.h"
4 #include "pnd_tinyxml.h"
6 //Easily change the tag names if required (globally in this file):
7 #include "pnd_pxml_names.h"
11 unsigned char pnd_pxml_load ( const char* pFilename, pnd_pxml_t *app ) {
16 f = fopen ( pFilename, "r" );
22 fseek ( f, 0, SEEK_END );
26 fseek ( f, 0, SEEK_SET );
28 b = (char*) malloc ( len );
35 fread ( b, 1, len, f );
37 return ( pnd_pxml_parse ( pFilename, b, len, app ) );
40 char *pnd_pxml_get_attribute(TiXmlElement *elem, const char *name)
42 const char *value = elem->Attribute(name);
49 unsigned char pnd_pxml_parse_titles(const TiXmlHandle hRoot, pnd_pxml_t *app)
52 app->titles_alloc_c = 4; //TODO: adjust this based on how many titles a PXML usually has. Power of 2.
54 app->titles = (pnd_localized_string_t *)malloc(sizeof(pnd_localized_string_t) * app->titles_alloc_c);
55 if (!app->titles) return (0); //errno = NOMEM
57 //Go through all title tags and load them.
58 for (pElem = hRoot.FirstChild(PND_PXML_ENAME_TITLE).Element(); pElem;
59 pElem = pElem->NextSiblingElement(PND_PXML_ENAME_TITLE))
62 if ( ! pElem->GetText() ) {
66 char *text = strdup(pElem->GetText());
69 char *lang = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_TITLELANG);
73 if (app->titles_c > app->titles_alloc_c) //we don't have enough strings allocated
75 app->titles_alloc_c <<= 1;
76 app->titles = (pnd_localized_string_t *)realloc((void*)app->titles, app->titles_alloc_c);
77 if (!app->titles) return (0); //errno = ENOMEM
80 pnd_localized_string_t *title = &app->titles[app->titles_c - 1];
81 title->language = lang;
88 unsigned char pnd_pxml_parse_descriptions(const TiXmlHandle hRoot, pnd_pxml_t *app)
91 app->descriptions_alloc_c = 4; //TODO: adjust this based on how many descriptions a PXML usually has. Power of 2.
93 app->descriptions = (pnd_localized_string_t *)malloc(sizeof(pnd_localized_string_t) * app->descriptions_alloc_c);
94 if (!app->descriptions)
96 app->descriptions_alloc_c = 0;
97 return (0); //errno = NOMEM
100 for (pElem = hRoot.FirstChild(PND_PXML_ENAME_DESCRIPTION).Element(); pElem;
101 pElem = pElem->NextSiblingElement(PND_PXML_ENAME_DESCRIPTION))
104 if ( ! pElem->GetText() ) {
108 char *text = strdup(pElem->GetText());
111 char *lang = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_DESCRLANG);
114 app->descriptions_c++;
115 if (app->descriptions_c > app->descriptions_alloc_c) //we don't have enough strings allocated
117 app->descriptions_alloc_c <<= 1;
118 app->descriptions = (pnd_localized_string_t*)realloc((void*)app->descriptions, app->descriptions_alloc_c);
119 if (!app->descriptions) return (0); //errno = ENOMEM
122 pnd_localized_string_t *description = &app->descriptions[app->descriptions_c - 1];
123 description->language = lang;
124 description->string = text;
129 unsigned char pnd_pxml_parse ( const char *pFilename, char *buffer, unsigned int length, pnd_pxml_t *app ) {
130 //Load the XML document
134 TiXmlElement *pElem = NULL;
136 //Find the root element
137 TiXmlHandle hDoc(&doc);
138 TiXmlHandle hRoot(0);
140 pElem = hDoc.FirstChild("PXML").Element();
141 if (!pElem) return (0);
142 hRoot = TiXmlHandle(pElem);
144 //Get unique ID first.
145 app->unique_id = pnd_pxml_get_attribute(hRoot.Element(), PND_PXML_ATTRNAME_UID);
147 //Everything related to the title:
148 pnd_pxml_parse_titles(hRoot, app);
150 //Everything description-related:
151 pnd_pxml_parse_descriptions(hRoot, app);
153 //Everything launcher-related in one tag:
154 if ( (pElem = hRoot.FirstChild(PND_PXML_ENAME_EXEC).Element()) )
156 app->background = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_EXECBG); //if this returns NULL, the struct is filled with NULL. No need to check.
157 app->standalone = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_EXECSTAL);
158 app->exec = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_EXECCMD);
159 app->startdir = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_EXECWD);
160 app->exec_no_x11 = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_EXECNOX11);
164 if ( (pElem = hRoot.FirstChild(PND_PXML_ENAME_ICON).Element()) )
166 app->icon = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_ICONSRC);
170 if ( (pElem = hRoot.FirstChild(PND_PXML_NODENAME_PREVPICS).Element()) )
172 //TODO: Change this if pnd_pxml_t gains the feature of more pics than 2.
173 if ( (pElem = pElem->FirstChildElement(PND_PXML_ENAME_PREVPIC)) )
175 app->previewpic1 = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_PREVPICSRC);
177 if ( (pElem = pElem->NextSiblingElement(PND_PXML_ENAME_PREVPIC)) )
179 app->previewpic2 = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_PREVPICSRC);
185 if ( (pElem = hRoot.FirstChild(PND_PXML_ENAME_AUTHOR).Element()) )
187 app->author_name = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_AUTHORNAME);
188 app->author_website = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_AUTHORWWW);
189 //TODO: Uncomment this if the author gets email support.
190 //app->author_email = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_AUTHOREMAIL));
194 if ( (pElem = hRoot.FirstChild(PND_PXML_ENAME_VERSION).Element()) )
196 app->version_major = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_VERMAJOR);
197 app->version_minor = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_VERMINOR);
198 app->version_release = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_VERREL);
199 app->version_build = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_VERBUILD);
202 //The OS version info:
203 if ( (pElem = hRoot.FirstChild(PND_PXML_ENAME_OSVERSION).Element()) )
205 app->osversion_major = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_OSVERMAJOR);
206 app->osversion_minor = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_OSVERMINOR);
207 app->osversion_release = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_OSVERREL);
208 app->osversion_build = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_OSVERBUILD);
211 int i; //For now, we need to keep track of the index of categories.
213 if ( (pElem = hRoot.FirstChildElement(PND_PXML_NODENAME_CATS).Element()) ) //First, enter the "categories" node.
217 //Goes through all the top-level categories and their sub-categories. i helps limit these to 2.
218 for (pElem = pElem->FirstChildElement(PND_PXML_ENAME_CAT); pElem && i < 2;
219 pElem = pElem->NextSiblingElement(PND_PXML_ENAME_CAT), i++)
221 //TODO: Fix pnd_pxml_t so that there can be more than 2 category 'trees' and more than 2 subcategories. Then this can be removed.
224 case 0: //first category counts as the main cat for now
225 app->main_category = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_CATNAME);
228 case 1: //...second as the alternative
229 app->altcategory = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_CATNAME);
232 TiXmlElement *pSubCatElem; //the sub-elements for a main category.
233 int j = 0; //the subcategory index within this category
235 //Goes through all the subcategories within this category. j helps limit these to 2.
236 for (pSubCatElem = pElem->FirstChildElement(PND_PXML_ENAME_SUBCAT); pSubCatElem && j < 2;
237 pSubCatElem = pSubCatElem->NextSiblingElement(PND_PXML_ENAME_SUBCAT), j++)
239 char *subcat = pnd_pxml_get_attribute(pSubCatElem, PND_PXML_ATTRNAME_SUBCATNAME);
240 if (!(subcat)) continue;
242 //TODO: This is ugly. Fix pnd_pxml_t so that there can be more than 2 category 'trees' and more than 2 subcategories. Then this can be removed.
243 switch (j & (i << 1))
246 app->subcategory1 = subcat;
249 app->subcategory2 = subcat;
252 app->altsubcategory1 = subcat;
255 app->altsubcategory2 = subcat;
261 //All file associations:
262 //Step into the associations node
263 if ( (pElem = hRoot.FirstChild(PND_PXML_NODENAME_ASSOCS).Element()) )
266 //Go through all associations. i serves as index; since the format only supports 3 associations we need to keep track of the number.
267 for (pElem = pElem->FirstChildElement(PND_PXML_ENAME_ASSOC); pElem && i < 3;
268 pElem = pElem->NextSiblingElement(PND_PXML_ENAME_ASSOC), i++)
270 char *name = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_ASSOCNAME);
271 char *filetype = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_ASSOCFTYPE);
272 char *paramter = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_ASSOCARGS);
274 if (!(name && filetype && paramter)) continue;
276 switch(i) //TODO: same problem here: only 3 associations supported
280 app->associationitem1_name = name;
281 app->associationitem1_filetype = filetype;
282 app->associationitem1_parameter = paramter;
287 app->associationitem2_name = name;
288 app->associationitem2_filetype = filetype;
289 app->associationitem2_parameter = paramter;
294 app->associationitem3_name = name;
295 app->associationitem3_filetype = filetype;
296 app->associationitem3_parameter = paramter;
302 //Performance related things (aka: Clockspeed XD):
303 pElem = hRoot.FirstChild(PND_PXML_ENAME_CLOCK).Element();
306 app->clockspeed = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_CLOCKFREQ);
310 pElem = hRoot.FirstChild ( PND_PXML_ENAME_PACKAGE ).Element();
312 app -> package_name = pnd_pxml_get_attribute ( pElem, PND_PXML_ATTRNAME_PACKAGE_NAME );
313 app -> package_release_date = pnd_pxml_get_attribute ( pElem, PND_PXML_ATTRNAME_PACKAGE_DATE );