Merged in changes from dflemstr (thanks!)
authorskeezix <skeezix@flotsam-vm.(none)>
Wed, 25 Mar 2009 01:47:19 +0000 (21:47 -0400)
committerskeezix <skeezix@flotsam-vm.(none)>
Wed, 25 Mar 2009 01:47:19 +0000 (21:47 -0400)
Fixed a couple NULLs in there (well fixed, or a quick hack to cover 'em up, whichever :)
Redid sample apps to use new PXML format so they actually provide info to discotest

21 files changed:
Makefile
docs/PXML_proposed_spec.html [new file with mode: 0644]
docs/PXML_schema.xsd [new file with mode: 0644]
docs/examples/PXML.xml [new file with mode: 0644]
include/pnd_pxml.h
include/pnd_pxml_names.h [new file with mode: 0644]
lib/pnd_pxml.c
lib/pnd_tinyxml.cpp
test/rawpxmltest.c [new file with mode: 0644]
testdata/app2/sampleapp4/PXML.xml
testdata/apps/sampleapp/PXML.xml [deleted file]
testdata/apps/sampleapp1/PXML.xml [new file with mode: 0644]
testdata/apps/sampleapp1/program.exe [moved from testdata/apps/sampleapp/program.exe with 100% similarity]
testdata/apps/sampleapp1/zeldaicon.png [new file with mode: 0644]
testdata/apps/sampleapp2/PXML.xml
testdata/apps/sampleapp2/zeldaicon.png [new file with mode: 0644]
testdata/apps/sampleapp3/PXML.xml
testdata/pndsample/x86_echo.pnd
testdata/pndsample/x86_echo/PXML.xml
testdata/pndsample/x86_ls.pnd
testdata/pndsample/x86_ls/PXML.xml

index f2122a4..daa1877 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -22,10 +22,10 @@ SOLIB1 = libpnd.so.1.0.1    # versioned name
 XMLOBJ = lib/tinyxml/tinystr.o lib/tinyxml/tinyxml.o lib/tinyxml/tinyxmlerror.o lib/tinyxml/tinyxmlparser.o
 ALLOBJ = pnd_conf.o pnd_container.o pnd_discovery.o pnd_pxml.o pnd_notify.o pnd_locate.o pnd_tinyxml.o pnd_pndfiles.o pnd_apps.o pnd_utility.o pnd_desktop.o
 
-all: ${SOLIB} ${LIB} conftest discotest notifytest locatetest pndnotifyd
+all: ${SOLIB} ${LIB} conftest discotest notifytest locatetest pndnotifyd rawpxmltest
 
 clean:
-       ${RM} -f ${ALLOBJ} ${XMLOBJ} ${LIB} ${SOLIB1} locatetest.o bin/locatetest conftest.o bin/conftest discotest.o bin/discotest bin/notifytest notifytest.o bin/pndnotifyd pndnotifyd.o ${SOLIB} testdata/dotdesktop/*.desktop testdata/apps/*.pnd testdata/dotdesktop/*.png deployment/usr/lib/libpnd* deployment/usr/bin/pndnotifyd deployment/usr/pandora/scripts/* deployment/etc/sudoers deployment/etc/init.d/pndnotifyd
+       ${RM} -f ${ALLOBJ} ${XMLOBJ} ${LIB} ${SOLIB1} locatetest.o bin/locatetest conftest.o bin/conftest discotest.o bin/discotest bin/notifytest notifytest.o bin/rawpxmltest rawpxmltest.o bin/pndnotifyd pndnotifyd.o ${SOLIB} testdata/dotdesktop/*.desktop testdata/apps/*.pnd testdata/dotdesktop/*.png deployment/usr/lib/libpnd* deployment/usr/bin/pndnotifyd deployment/usr/pandora/scripts/* deployment/etc/sudoers deployment/etc/init.d/pndnotifyd
        ${RM} -rf deployment/media
        find . -name "*~*" -exec rm {} \; -print
 
@@ -87,3 +87,6 @@ notifytest:   notifytest.o ${LIB}
 
 locatetest:    locatetest.o ${SOLIB1}
        ${CC} -lstdc++ -o bin/locatetest locatetest.o ${SOLIB1}
+
+rawpxmltest:    rawpxmltest.o ${LIB}
+       ${CC} -lstdc++ -o bin/rawpxmltest rawpxmltest.o ${LIB}
diff --git a/docs/PXML_proposed_spec.html b/docs/PXML_proposed_spec.html
new file mode 100644 (file)
index 0000000..b4b019f
--- /dev/null
@@ -0,0 +1,446 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>The PXML file format</title>
+    <style type="text/css">
+      body { background-color: white; }
+      h1 {
+        color: rgb(0, 0, 32);
+        font: normal 2em sans-serif;
+        counter-reset: section;
+        border-bottom: thin solid blue;
+      }
+      h2:before {
+        counter-increment: section;
+        content: counter(section) ". ";
+        font: normal 0.5em sans-serif;
+        color: gray;
+      }
+      h2 {
+        margin-top: 2.1em;
+        color: rgb(0, 0, 64);
+        font: normal 1.4em sans-serif;
+        counter-reset: subsection;
+      }
+      h3:before {
+        counter-increment: subsection;
+        content: counter(section) ". " counter(subsection) ". ";
+        font: normal 0.5em sans-serif;
+        color: gray;
+      }
+      h3 {
+        margin-top: 2em;
+        color: rgb(0, 0, 96);
+        font: normal 1.2em sans-serif;
+        counter-reset: element;
+      }
+      h4:before {
+        counter-increment: element;
+        content: counter(section) ". " counter(subsection) ". " counter(element) ". ";
+        font: normal 0.5em sans-serif;
+        color: gray;
+      }
+      h4 {
+        margin-top: 0.5em;
+        color: rgb(0, 0, 128);
+        font: normal 1.1em sans-serif;
+      }
+      p {
+        color: rgb(64, 64, 64);
+        font: normal 1em sans-serif;
+      }
+      ol {
+        color: rgb(32, 32, 32);
+        font: normal 1em sans-serif;
+      }
+      div.code {
+        font: normal 1em monospace;
+        color: black;
+        background-color: rgb(196, 196, 196);
+        border: thin solid #888;
+        min-width: 10em;
+        margin: 1em;
+        padding: 0.5em;
+        overflow: auto;
+        outline: #444 solid thin;
+      }
+      brack:before { content: "("; } /* just for fun XD */
+      brack:after { content: ")"; }
+      imp { font-weight: bold; }
+    </style>
+  </head>
+  <body>
+    <h1>The PXML file format specification</h1>
+
+
+    <h2>Introduction</h2>
+    <p><imp>
+      Attention: at the present time, the PXML file format isn't set in stone, and is therefore subject to change.
+      There is no guarantee that the format or the schema are bug-free or will be changed at any time.
+      Please wait until this standard is finished before writing a PXML file.
+    </imp></p>
+    <p>
+      This is the human-readable specification for the PXML file format.
+      The PXML file format is used in <imp>your</imp> applications for the <a href="http://openpandora.org">OpenPandora®</a> <brack>that you package in <q>.pnd</q>-files or distribute otherwise</brack>, to make it possible for menus and launchers to use your applications and their properties.
+    </p>
+    <p>
+      A PXML file should be appended to your <q>.pnd</q>-file, using the tools provided for that purpose, or put in a directory that you want to serve as a redistributable package, to make it possible for launchers and menus to find it.
+      It should have the name <q>PXML.xml</q> <brack>not case sensitive</brack>, and there should only be one such file.
+      The contents of the PXML file should also comply to this specification <imp>without exception</imp>, to guarantee that everyone will be able to read it.
+    </p>
+    <p>
+      The PXML format is XML-based and fully XML-compliant, which means that it can be read and written by any XML reader or writer.
+      Included with this specification should also be a <q>.xsd</q>-file, which is used by XML tools to validate PXML files.
+      A <q>.xsd</q>-file is also known as a XML schema, and can be called the <q>computer-readable</q> version of this document. It is very good practice to validate your PXML-files with that schema before publishing them.
+    </p>
+    <p>
+      To write a PXML file, you also need to know the basics of writing a XML file.
+      It boils down to the following:
+      <ol>
+        <li>If an element contains text or other elements, it needs a start-tag and an end-tag. This looks like this:
+          <div class="code">
+            &lt;exampleelement someattribute="something"&gt;something inside it&lt;/exampleeelement&gt;
+          </div>
+        </li>
+        <li>If an element does <imp>not</imp> contain other elements or text, but only attributes, it looks like this: 
+          <div class="code">
+            &lt;exampleelement2 someattribute="something" /&gt;
+          </div>
+        </li>
+      </ol>
+    </p>
+
+
+    <h2>Format</h2>
+    <p>
+      The PXML-file is split up into multiple so-called <imp>elements</imp>, each of which specify one property of the
+      <q>.pnd</q>-package.
+      All of these elements are surrounded with a <imp><q>&lt;PXML&gt;</q>-tag</imp>, which tells the readers of the file that the data within that tag belongs to a PXML file. The tag and elements should be defined as follows:
+    </p>
+
+    <h3>The PXML-tag</h3>
+    <p>
+      The PXML-tag serves as the container for all PXML elements. It is the first thing that should occur in your PXML file.
+      An example <q>&lt;PXML&gt;</q>-tag would look like this:
+    </p>
+    <div class="code">
+      &lt;PXML xmlns="http://openpandora.org/namespaces/PXML" id="uniqueID"&gt;<br/>
+      &nbsp;&nbsp;&lt;!--All of the PXML elements should be put here--&gt;<br/>
+      &lt;/PXML&gt;
+    </div>
+    <p>
+      As you can see, the PXML tag accepts a few <imp>attributes</imp>, namely the <q>id</q> and <q>xmlns</q> attributes.
+    </p>
+    <p>
+      The <imp><q>xmlns</q></imp> attribute is required by the XML standard, and guarantees that this file will be identified as a PXML file.
+      You <imp>must</imp> include the xmlns attribute, exactly as shown, in your PXML file, with the URL as specified.
+      Only then can it be guaranteed that the file will be read at all by launchers and menu apps.
+    </p>
+    <p>
+      The <imp><q>id</q></imp> attribute specifies an identifier for your PND package, and should be something globally unique so that no two PND packages have the same id.
+      This can be achieved by appending some random number to your application name, and to use that as your id; or to simply generate a completely random, very long id.
+      If this id already is used in another PND file, those two PND files will conflict with each other, and unforseeable errors will occur.
+      Please put effort into generating an unique id for your PXML-file.
+    </p>
+
+    <h3>The title element</h3>
+    <h4>Description</h4>
+    <p>
+      The <imp>title</imp> element specifies the text that is shown to the users of your PND file as the application title.
+      This element can be specified multiple times in multiple languages <brack>the language is indicated by the lang attribute</brack>.
+    </p>
+    <p>
+      At least one <q>title</q>-element is required, in the <q>en_US</q> <brack>American English</brack> language.
+    </p>
+    <h4>Example</h4>
+    <div class="code">
+      &lt;title lang="en_US"&gt;Your application name&lt;/title&gt;<br/><br/>
+      &lt;title lang="de_DE"&gt;Deinen Programmnamen&lt;/title&gt;
+    </div>
+
+    <h3>The description element</h3>
+    <h4>Description</h4>
+    <p>
+      The <imp>description</imp> element specifies the text that is shown to the users of your PND file as the application description.
+      This element can be specified multiple times in multiple languages <brack>the language is indicated by the lang attribute</brack>.
+    </p>
+    <p>
+      At least one <q>description</q>-element is required, in the <q>en_US</q> <brack>American English</brack> language.
+    </p>
+    <h4>Example</h4>
+    <div class="code">
+      &lt;description lang="en_US"&gt;Your long description of this application, describing it's purpose and highlighting it's features.&lt;/description&gt;<br/><br/>
+      &lt;description lang="de_DE"&gt;Deine etwas längere Programmbeschreibung, die den Sinn des Programmes und den wichtigsten Features beschreiben sollte.&lt;/description&gt;
+    </div>
+
+    <h3>The exec element</h3>
+    <h4>Description</h4>
+    <p>
+      The <imp>exec</imp> element should specify all the information needed to execute your application.<br/>
+      An exec element <imp>must</imp> be included in every PXML file.
+      It accepts the following attributes:
+    </p>
+    <p>
+      The <imp>command</imp> attribute specifies the path to the executable file.
+      This should be a relative path to a file within the PND package.
+    </p>
+    <p>
+      The <imp>startdir</imp> attribute specifies the starting directory <brack>Also known as the working directory</brack> that the application should start in.
+      This should be a relative path to a directory within the PND package, or to a well-known directory in the Pandora file system.
+    </p>
+    <p>
+      The <imp>standalone</imp> attribute specifies wether or not this application can run on its own, or if it needs parameters to run.<br/>
+      A value of <q>true</q> or <q>1</q> means that the application can be run without parameters.<br/>
+      A value of <q>false</q> or <q>0</q> means that the application must be run with parameters.
+    </p>
+    <p>
+      The <imp>background</imp> attribute specifies wether or not this application should run in the background, and it should be possible to switch to other apps while it is running, or if it is the only application that should be running.<br/>
+      A value of <q>true</q> or <q>1</q> means that the application can run in the background.<br/>
+      A value of <q>false</q> or <q>0</q> means that the application must be run as the only application.
+    </p>
+    <h4>Example</h4>
+    <div class="code">
+      &lt;exec background="true" startdir="/usr/share/icons/" standalone="true" command="./myprogram"/&gt;
+    </div>
+
+    <h3>The icon element</h3>
+    <h4>Description</h4>
+    <p>
+      The <imp>icon</imp> element should specify a nice icon for your program.<br/>
+      An icon element <imp>is optional</imp>.
+      It accepts the following attributes:
+    </p>
+    <p>
+      The <imp>src</imp> attribute specifies the path to the image file used as the icon.
+    </p>
+    <h4>Example</h4>
+    <div class="code">
+      &lt;icon src="./images/icon.png"/&gt;
+    </div>
+
+    <h3>The previewpics element</h3>
+    <h4>Description</h4>
+    <p>
+      The <imp>previewpics</imp> element is an element that contains multiple other elements.<br/>
+      A previewpics element <imp>is optional</imp>.
+    </p>
+    <p>
+      It contains multiple <imp>pic</imp>-elements. Every pic-element represents one preview picture.
+      If the previewpics element is specified, it must contain at least one pic element.
+    </p>
+    <p>
+      The <imp>src</imp> attribute on a pic element specifies the path to the image file used as the preview picture.
+    </p>
+    <h4>Example</h4>
+    <div class="code">
+      &lt;previewpics&gt;<br/>
+      &nbsp;&nbsp;&lt;pic src="./preview/pic1.jpg"/&gt;<br/>
+      &nbsp;&nbsp;&lt;pic src="./preview/pic2.jpg"/&gt;<br/>
+      &lt;/previewpics&gt;
+    </div>
+
+    <h3>The author element</h3>
+    <h4>Description</h4>
+    <p>
+      The <imp>author</imp> element is an element that is used by the author to introduce him/herself.<br/>
+      An author element <imp>is optional</imp>. It accepts the following attributes:
+    </p>
+    <p>
+      The <imp>name</imp> attribute specifies the name of the author.
+    </p>
+    <p>
+      The <imp>website</imp> attribute specifies the website of the author.
+    </p>
+    <p>
+      The <imp>email</imp> attribute specifies the e-mail of the author.<br/>
+      <imp>This attribute is not yet supported.</imp>
+    </p>
+    <h4>Example</h4>
+    <div class="code">
+      &lt;author name="Bjornhild Andersson" website="http://some.website.with.author.info"/&gt;
+    </div>
+
+    <h3>The version element</h3>
+    <h4>Description</h4>
+    <p>
+      The <imp>version</imp> element specifies the application version.<br/>
+      A version element <imp>is required</imp>. It accepts the following attributes:
+    </p>
+    <p>
+      The <imp>major</imp> attribute specifies the major version number. This number should be 0 or more.
+    </p>
+    <p>
+      The <imp>minor</imp> attribute specifies the minor version number. This number should be 0 or more.
+    </p>
+    <p>
+      The <imp>release</imp> attribute specifies the release number. This number should be 0 or more.
+    </p>
+    <p>
+      The <imp>build</imp> attribute specifies what build the application is at. This number should be 0 or more.
+    </p>
+    <h4>Example</h4>
+    <div class="code">
+      &lt;version major="1" minor="1" release="1" build="2"/&gt;
+    </div>
+
+    <h3>The osversion element</h3>
+    <h4>Description</h4>
+    <p>
+      The <imp>osversion</imp> element specifies the application version.<br/>
+      An osversion element <imp>is optional</imp>. It accepts the same attributes as the version element.
+    <h4>Example</h4>
+    <div class="code">
+      &lt;osversion major="1" minor="1" release="1" build="2"/&gt;
+    </div>
+
+    <h3>The categories element</h3>
+    <h4>Description</h4>
+    <p>
+      The <imp>categories</imp> element is an element that contains multiple other elements.<br/>
+      A categories element <imp>is required, and must contain at least one category</imp>.
+    </p>
+    <p>
+      It contains multiple <imp>category</imp>-elements. Every category-element represents one category that this app can be sorted into.
+      Valid categories are (among others):
+      <ol>
+        <li>Development</li>
+        <li>Education</li>
+        <li>Games</li>
+        <li>Graphics</li>
+        <li>Internet</li>
+        <li>Multimedia</li>
+        <li>Office</li>
+        <li>Settings</li>
+        <li>System</li>
+        <li>Utilities</li>
+      </ol>
+    </p>
+    <p>
+      The category-element takes one attribute: The <imp>name</imp>-attribute.
+      This attribute represents the category name, which preferrably should be one of the above.
+    </p>
+    <p>
+      A category-element can contain further child-elements: <imp>subcategory</imp>-elements.
+      These represent the subcategories of a category that the app will be sorted into.
+    </p>
+    <p>
+      The subcategory-element also takes a <imp>name</imp>-attribute; this attibute can contain any name for your subcategory.
+    </p>
+    <h4>Example</h4>
+    <div class="code">
+      &lt;categories&gt;<br/>
+      &nbsp;&nbsp;&lt;category name="Games"&gt;<br/>
+      &nbsp;&nbsp;&nbsp;&nbsp;&lt;subcategory name="Strategy"/&gt;<br/>
+      &nbsp;&nbsp;&nbsp;&nbsp;&lt;subcategory name="Turn-based"/&gt;<br/>
+      &nbsp;&nbsp;&lt;/category&gt;<br/>
+      &nbsp;&nbsp;&lt;category name="Graphics"&gt;<br/>
+      &nbsp;&nbsp;&nbsp;&nbsp;&lt;subcategory name="Image Editors"/&gt;<br/>
+      &nbsp;&nbsp;&lt;/category&gt;<br/>
+      &lt;/categories&gt;<br/>
+    </div>
+
+    <h3>The associations element</h3>
+    <h4>Description</h4>
+    <p>
+      The <imp>associations</imp> element is an element that contains multiple other elements.<br/>
+      An associations element <imp>is optional, except if exec.standalone is false</imp>.
+    </p>
+    <p>
+      It contains multiple <imp>association</imp>-elements. Every association-element represents one file action association.
+    </p>
+    <p>
+      The <imp>name</imp> attribute on an association element specifies the user-friendly action name for the association.
+    </p>
+    <p>
+      The <imp>filetype</imp> attribute on an association element specifies what file types (in MIME format) that this association should apply to.
+    </p>
+    <p>
+      The <imp>exec</imp> attribute on an association element specifies the command-line arguments that should be given to the program, when this action is performed.
+      The exec can contain a <q>%s</q>, which indicates where the file name of the file, that the action is performed on, should be inserted.<br/>
+      For example, if the exec-line is <q>--file %s --type lol</q>, and you have a file "lol.bmp" that the action is performed on, the exec-line is transformed into <q>--file "lol.bmp" --type lol</q>
+    </p>
+    <h4>Example</h4>
+    <div class="code">
+      &lt;associations&gt;<br/>
+      &nbsp;&nbsp;&lt;association name="Open Bitmap Image" filetype="image/bmp" exec="-f %s --no-deinterlacing"/&gt;<br/>
+      &nbsp;&nbsp;&lt;association name="Crash the computer with a stylesheet" filetype="text/css" exec="-f %s --crash-on-success"/&gt;<br/>
+      &lt;/associations&gt;
+    </div>
+
+    <h3>The clockspeed element</h3>
+    <h4>Description</h4>
+    <p>
+      The <imp>clockspeed</imp> element specifies what clockspeed this app should run at.<br/>
+      A clockspeed element <imp>is optional</imp>. It accepts the following attributes:
+    </p>
+    <p>
+      The <imp>frequency</imp> attribute specifies the wanted frequency, in megahertz <brack>mHz</brack>.
+    </p>
+    <h4>Example</h4>
+    <div class="code">
+      &lt;clockspeed frequency="600"/&gt;
+    </div>
+
+
+    <h2>Example file</h2>
+    <div class="code">
+      &lt;?xml&nbsp;version="1.0"&nbsp;encoding="UTF-8"?&gt;<br/>
+      &lt;PXML&nbsp;id="youruniqueID"&nbsp;xmlns="http://openpandora.org/namespaces/PXML"&gt;<br/>
+      &nbsp;&nbsp;&lt;title&nbsp;lang="en_US"&gt;Program&nbsp;Title&lt;/title&gt;<br/>
+      &nbsp;&nbsp;&lt;title&nbsp;lang="de_DE"&gt;German&nbsp;Program&nbsp;Title&lt;/title&gt;<br/>
+      <br/>
+      &nbsp;&nbsp;&lt;exec&nbsp;background="true"&nbsp;startdir="/usr/share/icons/"&nbsp;standalone="true"&nbsp;command="./program"/&gt;<br/>
+      <br/>
+      &nbsp;&nbsp;&lt;icon&nbsp;src="./program.png"/&gt;<br/>
+      <br/>
+      &nbsp;&nbsp;&lt;description&nbsp;lang="en_US"&gt;This&nbsp;is&nbsp;the&nbsp;English&nbsp;Description&nbsp;of&nbsp;the&nbsp;file.&lt;/description&gt;<br/>
+      &nbsp;&nbsp;&lt;description&nbsp;lang="de_DE"&gt;This&nbsp;would&nbsp;be&nbsp;the&nbsp;German&nbsp;description.&lt;/description&gt;<br/>
+      <br/>
+      &nbsp;&nbsp;&lt;previewpics&gt;<br/>
+      &nbsp;&nbsp;&nbsp;&nbsp;&lt;pic&nbsp;src="./preview/pic1.jpg"/&gt;<br/>
+      &nbsp;&nbsp;&nbsp;&nbsp;&lt;pic&nbsp;src="./preview/pic2.jpg"/&gt;<br/>
+      &nbsp;&nbsp;&lt;/previewpics&gt;<br/>
+      <br/>
+      &nbsp;&nbsp;&lt;author&nbsp;name="Some Dudeson"&nbsp;website="http://a.bc.de"/&gt;<br/>
+      <br/>
+      &nbsp;&nbsp;&lt;version&nbsp;major="1"&nbsp;minor="1"&nbsp;release="1"&nbsp;build="2"/&gt;<br/>
+      &nbsp;&nbsp;&lt;osversion&nbsp;major="1"&nbsp;minor="0"&nbsp;release="0"&nbsp;build="0"/&gt;<br/>
+      <br/>
+      &nbsp;&nbsp;&lt;categories&gt;<br/>
+      &nbsp;&nbsp;&nbsp;&nbsp;&lt;category&nbsp;name="Main&nbsp;category"&gt;<br/>
+      &nbsp;&nbsp;&nbsp;&nbsp;&lt;subcategory&nbsp;name="Subcategory&nbsp;1"/&gt;<br/>
+      &nbsp;&nbsp;&nbsp;&nbsp;&lt;subcategory&nbsp;name="Subcategory&nbsp;2"/&gt;<br/>
+      &nbsp;&nbsp;&nbsp;&nbsp;&lt;/category&gt;<br/>
+      &nbsp;&nbsp;&nbsp;&nbsp;&lt;category&nbsp;name="Alternative&nbsp;category"&gt;<br/>
+      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;subcategory&nbsp;name="Alternative&nbsp;Subcategory&nbsp;1"/&gt;<br/>
+      &nbsp;&nbsp;&nbsp;&nbsp;&lt;/category&gt;<br/>
+      &nbsp;&nbsp;&lt;/categories&gt;<br/>
+      <br/>
+      &nbsp;&nbsp;&lt;associations&gt;<br/>
+      &nbsp;&nbsp;&nbsp;&nbsp;&lt;association&nbsp;name="View&nbsp;Word&nbsp;File"&nbsp;filetype="application/msword"&nbsp;exec="-f&nbsp;%s&nbsp;-t&nbsp;doc"/&gt;<br/>
+      &nbsp;&nbsp;&lt;/associations&gt;<br/>
+      <br/>
+      &nbsp;&nbsp;&lt;clockspeed&nbsp;frequency="600"/&gt;&lt;!--Frequency&nbsp;in&nbsp;Hz--&gt;<br/>
+      &lt;/PXML&gt;<br/>
+    </div>
+
+
+    <h2>Validation</h2>
+    <p>To validate a PXML file, you need a XSD (XML schema) validator, and you have to know how to use it.</p>
+    <p>You will also need to put the XML schema for the PXML format in the same folder as your PXML file.</p>
+    <p>
+      When you have done that, and know how to use it, you need to change a few things in your PXML file.
+      In your PXML tag, change the contents from this:
+    </p>
+    <div class="code">
+      &lt;PXML id="..." xmlns="http://openpandora.org/namespaces/PXML"&gt;...
+    </div>
+    <p>...to this:</p>
+    <div class="code">
+      &lt;PXML id="..." xmlns="http://openpandora.org/namespaces/PXML" <imp>xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="PXML_schema.xsd"</imp>&gt;...
+    </div>
+    <p>
+      Now the PXML file can be validated.
+    </p>
+  </body>
+</html>
\ No newline at end of file
diff --git a/docs/PXML_schema.xsd b/docs/PXML_schema.xsd
new file mode 100644 (file)
index 0000000..2d28bbe
--- /dev/null
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="utf-16"?>
+<xs:schema id="NewDataSet" targetNamespace="http://openpandora.org/namespaces/PXML" xmlns="http://openpandora.org/namespaces/PXML" xmlns:xs="http://www.w3.org/2001/XMLSchema" attributeFormDefault="unqualified" elementFormDefault="unqualified">
+  <xs:element name="PXML">
+    <xs:complexType>
+      <xs:all>
+        <!--Execution params -->
+        <xs:element name="exec">
+          <xs:complexType>
+            <xs:attribute name="background" type="xs:boolean" />
+            <xs:attribute name="startdir" use="optional" type="xs:string" />
+            <xs:attribute name="standalone" type="xs:boolean" />
+            <xs:attribute name="command" type="xs:string" />
+          </xs:complexType>
+        </xs:element>
+        <!--Author info-->
+        <xs:element name="author" maxOccurs="1">
+          <xs:complexType>
+            <xs:attribute name="name" type="xs:string" />
+            <xs:attribute name="website" type="xs:string" />
+            <xs:attribute name="email" type="xs:string" />
+          </xs:complexType>
+        </xs:element>
+        <!--Icon-->
+        <xs:element name="icon" maxOccurs="unbounded">
+          <xs:complexType>
+            <xs:attribute name="src" type="xs:string" />
+          </xs:complexType>
+        </xs:element>
+        <!--App version info-->
+        <xs:element name="version">
+          <xs:complexType>
+            <xs:attribute name="major" type="xs:nonNegativeInteger" />
+            <xs:attribute name="minor" type="xs:nonNegativeInteger" />
+            <xs:attribute name="release" type="xs:nonNegativeInteger" />
+            <xs:attribute name="build" type="xs:nonNegativeInteger" />
+          </xs:complexType>
+        </xs:element>
+        <!--OS Version info-->
+        <xs:element name="osversion">
+          <xs:complexType>
+            <xs:attribute name="major" type="xs:nonNegativeInteger" />
+            <xs:attribute name="minor" type="xs:nonNegativeInteger" />
+            <xs:attribute name="release" type="xs:nonNegativeInteger" />
+            <xs:attribute name="build" type="xs:nonNegativeInteger" />
+          </xs:complexType>
+        </xs:element>
+        <!--Title-->
+        <xs:element name="title">
+          <xs:complexType>
+            <xs:simpleContent>
+              <xs:extension base="xs:string">
+                <xs:attribute name="lang" type="xs:language" />
+              </xs:extension>
+            </xs:simpleContent>
+          </xs:complexType>
+        </xs:element>
+        <!--Description-->
+        <xs:element name="description">
+          <xs:complexType>
+            <xs:simpleContent>
+              <xs:extension base="xs:string">
+                <xs:attribute name="lang" type="xs:language" />
+              </xs:extension>
+            </xs:simpleContent>
+          </xs:complexType>
+        </xs:element>
+        <!--Preview pics-->
+        <xs:element name="previewpics" use="optional">
+          <xs:complexType>
+            <xs:sequence>
+              <xs:element name="pic" maxOccurs="unbounded">
+                <xs:complexType>
+                  <xs:attribute name="src" type="xs:string" />
+                </xs:complexType>
+              </xs:element>
+            </xs:sequence>
+          </xs:complexType>
+        </xs:element>
+        <!--Categories-->
+        <xs:element name="categories">
+          <xs:complexType>
+            <xs:sequence>
+              <xs:element name="category" maxOccurs="unbounded">
+                <xs:complexType>
+                  <xs:sequence>
+                    <xs:element name="subcategory" maxOccurs="unbounded">
+                      <xs:complexType>
+                        <xs:attribute name="name" type="xs:normalizedString" />
+                      </xs:complexType>
+                    </xs:element>
+                  </xs:sequence>
+                  <xs:attribute name="name" type="xs:normalizedString" />
+                </xs:complexType>
+              </xs:element>
+            </xs:sequence>
+          </xs:complexType>
+        </xs:element>
+        <!--Associations-->
+        <xs:element name="associations" use="optional">
+          <xs:complexType>
+            <xs:sequence>
+              <xs:element name="association" maxOccurs="unbounded">
+                <xs:complexType>
+                  <xs:attribute name="name" type="xs:normalizedString" />
+                  <xs:attribute name="filetype" type="xs:string" />
+                  <xs:attribute name="arguments" type="xs:string" />
+                </xs:complexType>
+              </xs:element>
+            </xs:sequence>
+          </xs:complexType>
+        </xs:element>
+        <!--Clockspeed-->
+        <xs:element name="clockspeed">
+          <xs:complexType>
+            <xs:attribute name="frequency" type="xs:PositiveInteger" />
+          </xs:complexType>
+        </xs:element>
+      </xs:all>
+      <!--AppID-->
+      <xs:attribute name="id" type="xs:normalizedString" />
+    </xs:complexType>
+  </xs:element>
+</xs:schema>
\ No newline at end of file
diff --git a/docs/examples/PXML.xml b/docs/examples/PXML.xml
new file mode 100644 (file)
index 0000000..76f1e11
--- /dev/null
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<PXML xmlns="http://openpandora.org/namespaces/PXML" 
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="youruniqueID" xsi:noNamespaceSchemaLocation="PXML_schema.xsd">
+  <title lang="en_US">Program Title</title>
+  <title lang="de_DE">German Program Title</title>
+
+  <exec background="true" startdir="/usr/share/icons/" standalone="true" command="program.exe"/>
+
+  <icon src="program.png"/>
+
+  <description lang="en_US">This is the English Description of the file.</description>
+  <description lang="de_DE">This would be the German description.</description>
+
+  <previewpics>
+    <pic src="./preview/pic1.jpg"/>
+    <pic src="./preview/pic2.jpg"/>
+  </previewpics>
+
+  <author name="EvilDragon" website="http://www.openpandora.org"/><!--Optional email and website, name required-->
+
+  <version major="1" minor="1" release="1" build="2"/><!--This program's version-->
+  <osversion major="1" minor="0" release="0" build="0"/><!--The minimum OS version required-->
+
+  <categories>
+    <category name="Main category"><!--category like "Games", "Graphics", "Internet" etc-->
+    <subcategory name="Subcategory 1"/><!--subcategory, like "Board Games", "Strategy", "First Person Shooters"-->
+    <subcategory name="Subcategory 2"/>
+    </category>
+    <category name="Alternative category">
+      <subcategory name="Alternative Subcategory 1"/>
+    </category>
+  </categories>
+
+  <associations>
+    <!--File associations, with a short description, an extension, and start params.-->
+    <association name="View Word File" filetype="application/msword" exec="-f %s -t doc"/>
+  </associations>
+
+  <clockspeed frequency="600"/><!--Frequency in Hz-->
+
+  <configuration for="gmenupandora">......kfujl........</configuration><!--random data, this is for specific menus-->
+  <configuration for="anothermenu">......qwe......fwer.....</configuration>
+</PXML>
index 775aef0..f54b9b7 100644 (file)
@@ -9,7 +9,7 @@ extern "C" {
 // this code is for very basic PXML.xml file parsing
 
 #define PXML_FILENAME "PXML.xml" /* a specification defined name */
-#define PXML_TAGHEAD "<PXML>" /* case insensitive */
+#define PXML_TAGHEAD "<PXML" /* case insensitive; allow for trailing attributes */
 #define PXML_TAGFOOT "</PXML>" /* case insensitive */
 
 // use this handle to interact with PXML; this hides the mechanics of parsing a PXML file so that
@@ -42,6 +42,7 @@ char *pnd_pxml_get_app_name_en ( pnd_pxml_handle h );
 char *pnd_pxml_get_app_name_de ( pnd_pxml_handle h );
 char *pnd_pxml_get_app_name_it ( pnd_pxml_handle h );
 char *pnd_pxml_get_app_name_fr ( pnd_pxml_handle h );
+char *pnd_pxml_get_app_name ( pnd_pxml_handle h, char *iso_lang );
 char *pnd_pxml_get_unique_id ( pnd_pxml_handle h );
 char *pnd_pxml_get_standalone ( pnd_pxml_handle h );
 char *pnd_pxml_get_icon ( pnd_pxml_handle h );
@@ -49,6 +50,7 @@ char *pnd_pxml_get_description_en ( pnd_pxml_handle h );
 char *pnd_pxml_get_description_de ( pnd_pxml_handle h );
 char *pnd_pxml_get_description_it ( pnd_pxml_handle h );
 char *pnd_pxml_get_description_fr ( pnd_pxml_handle h );
+char *pnd_pxml_get_description ( pnd_pxml_handle h, char *iso_lang);
 char *pnd_pxml_get_previewpic1 ( pnd_pxml_handle h );
 char *pnd_pxml_get_previewpic2 ( pnd_pxml_handle h );
 char *pnd_pxml_get_author_name ( pnd_pxml_handle h );
@@ -90,17 +92,21 @@ unsigned char pnd_is_pxml_valid_app ( pnd_pxml_handle h ); // returns 1 when pxm
 
 typedef struct
 {
-       char *title_en;
-       char *title_de;
-       char *title_it;
-       char *title_fr;
+       char *language;
+       char *string;
+} pnd_localized_string_t;
+
+typedef struct
+{
+       pnd_localized_string_t *titles;
+       int titles_c;
+       int titles_alloc_c;
        char *unique_id;
        char *standalone;
        char *icon;
-       char *description_en;
-       char *description_de;
-       char *description_it;
-       char *description_fr;
+       pnd_localized_string_t *descriptions;
+       int descriptions_c;
+       int descriptions_alloc_c;
        char *previewpic1;
        char *previewpic2;
        char *author_name;
diff --git a/include/pnd_pxml_names.h b/include/pnd_pxml_names.h
new file mode 100644 (file)
index 0000000..5076736
--- /dev/null
@@ -0,0 +1,88 @@
+#ifndef h_pnd_pxml_names_h
+#define h_pnd_pxml_names_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* <PXML id="..."> ...*/
+#define PND_PXML_ATTRNAME_UID "id"
+
+/* <title lang="..."> */
+#define PND_PXML_ENAME_TITLE "title"
+#define PND_PXML_ATTRNAME_TITLELANG "lang"
+
+/* <description lang="...">... */
+#define PND_PXML_ENAME_DESCRIPTION "description"
+#define PND_PXML_ATTRNAME_DESCRLANG "lang"
+
+/* <exec background="true" standalone="false" command="..." startdir="..." /> */
+#define PND_PXML_ENAME_EXEC "exec"
+#define PND_PXML_ATTRNAME_EXECBG "background"
+#define PND_PXML_ATTRNAME_EXECSTAL "standalone"
+#define PND_PXML_ATTRNAME_EXECCMD "command"
+#define PND_PXML_ATTRNAME_EXECWD "startdir"
+
+/* <icon src="..." /> */
+#define PND_PXML_ENAME_ICON "icon"
+#define PND_PXML_ATTRNAME_ICONSRC "src"
+
+/* <previewpics>
+ *   <pic src="..." />
+ * </previewpics>
+ */
+#define PND_PXML_NODENAME_PREVPICS "previewpics"
+#define PND_PXML_ENAME_PREVPIC "pic"
+#define PND_PXML_ATTRNAME_PREVPICSRC "src"
+
+/* <author name="..." website="..." email="..." /> */
+#define PND_PXML_ENAME_AUTHOR "author"
+#define PND_PXML_ATTRNAME_AUTHORNAME "name"
+#define PND_PXML_ATTRNAME_AUTHORWWW "website"
+#define PND_PXML_ATTRNAME_AUTHOREMAIL "email"
+
+/* <version major="1" minor="1" release="1" build="2" /> */
+#define PND_PXML_ENAME_VERSION "version"
+#define PND_PXML_ATTRNAME_VERMAJOR "major"
+#define PND_PXML_ATTRNAME_VERMINOR "minor"
+#define PND_PXML_ATTRNAME_VERREL "release"
+#define PND_PXML_ATTRNAME_VERBUILD "build"
+
+/* <osversion major="1" minor="0" release="0" build="0" /> */
+#define PND_PXML_ENAME_OSVERSION "osversion"
+#define PND_PXML_ATTRNAME_OSVERMAJOR "major"
+#define PND_PXML_ATTRNAME_OSVERMINOR "minor"
+#define PND_PXML_ATTRNAME_OSVERREL "release"
+#define PND_PXML_ATTRNAME_OSVERBUILD "build"
+
+/* <categories>
+ *   <category name="...">
+ *     <subcategory name="..." />
+ *   </category>
+ * </categories>
+ */
+#define PND_PXML_NODENAME_CATS "categories"
+#define PND_PXML_ENAME_CAT "category"
+#define PND_PXML_ATTRNAME_CATNAME "name"
+#define PND_PXML_ENAME_SUBCAT "subcategory"
+#define PND_PXML_ATTRNAME_SUBCATNAME "name"
+
+/* <associations>
+ *   <association name="CSS File" filetype="text/css" exec="-f %s -t css" />
+ * </associations>
+ */
+#define PND_PXML_NODENAME_ASSOCS "associations"
+#define PND_PXML_ENAME_ASSOC "association"
+#define PND_PXML_ATTRNAME_ASSOCNAME "name"
+#define PND_PXML_ATTRNAME_ASSOCFTYPE "filetype"
+#define PND_PXML_ATTRNAME_ASSOCARGS "arguments"
+
+/* <clockspeed frequency="600" /> */
+#define PND_PXML_ENAME_CLOCK "clockspeed"
+#define PND_PXML_ATTRNAME_CLOCKFREQ "frequency"
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif /* ifndef h_pnd_pxml_names_h */
\ No newline at end of file
index 78c41e7..6b1c96e 100644 (file)
@@ -40,39 +40,31 @@ pnd_pxml_handle pnd_pxml_fetch_buffer ( char *filename, char *buffer ) {
 void pnd_pxml_delete ( pnd_pxml_handle h ) {
   pnd_pxml_t *p = (pnd_pxml_t*) h;
 
-  if ( p -> title_en ) {
-    free ( p -> title_en );
-  }
-  if ( p -> title_de ) {
-    free ( p -> title_de );
-  }
-  if ( p -> title_it ) {
-    free ( p -> title_it );
-  }
-  if ( p -> title_fr ) {
-    free ( p -> title_fr );
+  int i;
+  if (p->titles) {
+    for (i = 0; i < p->titles_c; i++)
+    {
+      free(p->titles[i].language);
+      free(p->titles[i].string);
+    }
+    free(p->titles);
   }
-  if ( p -> unique_id ) {
-    free ( p -> unique_id );
+
+  if (p->descriptions) {
+    for (i = 0; i < p->descriptions_c; i++)
+    {
+      free(p->descriptions[i].language);
+      free(p->descriptions[i].string);
+    }
+    free(p->descriptions);
   }
+
   if ( p -> standalone ) {
     free ( p -> standalone );
   }
   if ( p -> icon ) {
     free ( p -> icon );
   }
-  if ( p -> description_en ) {
-    free ( p -> description_en );
-  }
-  if ( p -> description_de ) {
-    free ( p -> description_de );
-  }
-  if ( p -> description_it ) {
-    free ( p -> description_it );
-  }
-  if ( p -> description_fr ) {
-    free ( p -> description_fr );
-  }
   if ( p -> previewpic1 ) {
     free ( p -> previewpic1 );
   }
@@ -167,25 +159,50 @@ void pnd_pxml_delete ( pnd_pxml_handle h ) {
     free ( p -> startdir );
   }
 
+  free(p); /*very important!*/
+
   return;
 }
 
 void pnd_pxml_set_app_name ( pnd_pxml_handle h, char *v ) {
+  /* 
+   * Please do not use this function if it can be avoided; it is only here for compatibility.
+   * The function might fail on low memory, and there's no way for the user to know when this happens.
+   */
   pnd_pxml_t *p = (pnd_pxml_t*) h;
-  if ( p -> title_en ) {
-    free ( p -> title_en );
-    p -> title_en = NULL;
+  char has_en_field = 0;
+  int i;
+
+  if (!v) return; /*TODO: add error information? Make it possible to set the string to NULL?*/
+
+  for (i = 0; i < p->titles_c; i++)
+  {
+    if (strncmp("en", p->titles[i].language, 2) == 0) /*strict comparison; match "en_US", "en_GB" etc... All these are set.*/
+    {
+      free(p->titles[i].string);
+      p->titles[i].string = strdup(v);
+      has_en_field = 1;
+    }
   }
 
-  if ( v ) {
-    p -> title_en = strdup ( v );
+  if (!has_en_field)
+  {
+    p->titles_c++;
+    if (p->titles_c > p->titles_alloc_c) //we don't have enough strings allocated
+    {
+      p->titles_alloc_c <<= 1;
+      p->titles = (pnd_localized_string_t *)realloc((void*)p->titles, p->titles_alloc_c);
+      if (!p->titles) return; //errno = ENOMEM
+    }
+    p->titles[p->titles_c - 1].language = "en_US";
+    p->titles[p->titles_c - 1].string = strdup(v);
   }
 
   return;
 }
 
 unsigned char pnd_is_pxml_valid_app ( pnd_pxml_handle h ) {
-  pnd_pxml_t *p = (pnd_pxml_t*) h;
+  //pnd_pxml_t *p = (pnd_pxml_t*) h; //unused atm
 
   // for now, lets just verify the exec-path is valid
 
@@ -241,24 +258,48 @@ signed char pnd_pxml_merge_override ( pnd_pxml_handle h, char *searchpath ) {
   return ( retval );
 }
 
+char *pnd_pxml_get_best_localized_string(pnd_localized_string_t strings[], int strings_c, char *iso_lang)
+{
+  int i;
+  int similarity_weight = 0xff; /*Set to something Really Bad in the beginning*/
+  char *best_match = NULL;
+
+  for(i = 0; i < strings_c; i++)
+  {
+    int new_weight = abs(strcmp(strings[i].language, iso_lang));
+    if (new_weight < similarity_weight)
+    {
+      similarity_weight = new_weight;
+      best_match = strings[i].string;
+    }
+  }
+
+  if ( best_match ) {
+    return strdup(best_match);
+  }
+
+  return ( NULL );
+}
+
+char *pnd_pxml_get_app_name ( pnd_pxml_handle h, char *iso_lang ) {
+  pnd_pxml_t *p = (pnd_pxml_t *) h;
+  return pnd_pxml_get_best_localized_string(p->titles, p->titles_c, iso_lang);
+}
+
 char *pnd_pxml_get_app_name_en ( pnd_pxml_handle h ) {
-  pnd_pxml_t *p = (pnd_pxml_t*) h;
-  return ( p -> title_en );
+  return pnd_pxml_get_app_name(h, "en");
 }
 
 char *pnd_pxml_get_app_name_de ( pnd_pxml_handle h ) {
-  pnd_pxml_t *p = (pnd_pxml_t*) h;
-  return ( p -> title_de );
+  return pnd_pxml_get_app_name(h, "de");
 }
 
 char *pnd_pxml_get_app_name_it ( pnd_pxml_handle h ) {
-  pnd_pxml_t *p = (pnd_pxml_t*) h;
-  return ( p -> title_it );
+  return pnd_pxml_get_app_name(h, "it");
 }
 
 char *pnd_pxml_get_app_name_fr ( pnd_pxml_handle h ) {
-  pnd_pxml_t *p = (pnd_pxml_t*) h;
-  return ( p -> title_fr );
+  return pnd_pxml_get_app_name(h, "fr");
 }
 
 char *pnd_pxml_get_unique_id ( pnd_pxml_handle h ) {
@@ -276,24 +317,25 @@ char *pnd_pxml_get_icon ( pnd_pxml_handle h ) {
   return ( p -> icon );
 }
 
+char *pnd_pxml_get_app_description ( pnd_pxml_handle h, char *iso_lang ) {
+  pnd_pxml_t *p = (pnd_pxml_t *) h;
+  return pnd_pxml_get_best_localized_string(p->descriptions, p->descriptions_c, iso_lang);
+}
+
 char *pnd_pxml_get_description_en ( pnd_pxml_handle h ) {
-  pnd_pxml_t *p = (pnd_pxml_t*) h;
-  return ( p -> description_en );
+  return pnd_pxml_get_app_description(h, "en");
 }
 
 char *pnd_pxml_get_description_de ( pnd_pxml_handle h ) {
-  pnd_pxml_t *p = (pnd_pxml_t*) h;
-  return ( p -> description_de );
+  return pnd_pxml_get_app_description(h, "de");
 }
 
 char *pnd_pxml_get_description_it ( pnd_pxml_handle h ) {
-  pnd_pxml_t *p = (pnd_pxml_t*) h;
-  return ( p -> description_it );
+  return pnd_pxml_get_app_description(h, "it");
 }
 
 char *pnd_pxml_get_description_fr ( pnd_pxml_handle h ) {
-  pnd_pxml_t *p = (pnd_pxml_t*) h;
-  return ( p -> description_fr );
+  return pnd_pxml_get_app_description(h, "fr");
 }
 
 char *pnd_pxml_get_previewpic1 ( pnd_pxml_handle h ) {
index e0f2daa..9fbb25f 100644 (file)
@@ -3,6 +3,9 @@
 #include "../include/pnd_pxml.h"
 #include "pnd_tinyxml.h"
 
+//Easily change the tag names if required (globally in this file):
+#include "pnd_pxml_names.h"
+
 extern "C" {
 
 unsigned char pnd_pxml_load ( const char* pFilename, pnd_pxml_t *app ) {
@@ -34,303 +37,275 @@ unsigned char pnd_pxml_load ( const char* pFilename, pnd_pxml_t *app ) {
   return ( pnd_pxml_parse ( pFilename, b, len, app ) );
 }
 
-unsigned char pnd_pxml_parse ( const char *pFilename, char *buffer, unsigned int length, pnd_pxml_t *app ) {
-
-  //TiXmlDocument doc(pFilename);
-  //if (!doc.LoadFile()) return;
+char *pnd_pxml_get_attribute(TiXmlElement *elem, const char *name)
+{
+       const char *value = elem->Attribute(name);
+       if (value)
+               return strdup(value);
+       else
+               return NULL;
+}
 
-  TiXmlDocument doc;
+unsigned char pnd_pxml_parse_titles(const TiXmlHandle hRoot, pnd_pxml_t *app)
+{
+       TiXmlElement *pElem;
+       app->titles_alloc_c = 4;  //TODO: adjust this based on how many titles a PXML usually has. Power of 2.
 
-  doc.Parse ( buffer );
+       app->titles = (pnd_localized_string_t *)malloc(sizeof(pnd_localized_string_t) * app->titles_alloc_c);
+       if (!app->titles) return (0); //errno = NOMEM
 
-       TiXmlHandle hDoc(&doc);
-       TiXmlElement* pElem;
-       TiXmlHandle hRoot(0);
-
-       pElem=hDoc.FirstChildElement().Element();
-       if (!pElem) return ( 0 );
-       hRoot=TiXmlHandle(pElem);
-
-       pElem = hRoot.FirstChild( "title" ).FirstChildElement("en").Element();
-       if ( pElem )
+       //Go through all title tags and load them.
+       for (pElem = hRoot.FirstChild(PND_PXML_ENAME_TITLE).Element(); pElem;
+               pElem = pElem->NextSiblingElement(PND_PXML_ENAME_TITLE))
        {
-               app->title_en = strdup(pElem->GetText());
-       }
 
-       pElem = hRoot.FirstChild( "title" ).FirstChildElement("de").Element();
-       if ( pElem )
-       {
-               app->title_de = strdup(pElem->GetText());
-       }
+         if ( ! pElem->GetText() ) {
+           continue;
+         }
 
-       pElem = hRoot.FirstChild( "title" ).FirstChildElement("it").Element();
-       if ( pElem )
-       {
-               app->title_it = strdup(pElem->GetText());
-       }
-       
-       pElem = hRoot.FirstChild( "title" ).FirstChildElement("fr").Element();
-       if ( pElem )
-       {
-               app->title_fr = strdup(pElem->GetText());
-       }
+               char *text = strdup(pElem->GetText());
+               if (!text) continue;
 
-       pElem=hRoot.FirstChild("unique_id").Element();
-       if (pElem)
-       {       
-               app->unique_id = strdup(pElem->GetText());
-       }
+               char *lang = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_TITLELANG);
+               if (!lang) continue;
 
-       pElem=hRoot.FirstChild("standalone").Element();
-       if (pElem)
-       {       
-               app->standalone = strdup(pElem->GetText());
-       }
-
-       pElem=hRoot.FirstChild("icon").Element();
-       if (pElem)
-       {       
-#if 0
-               char anotherbuffer [ FILENAME_MAX ];
-               strcpy ( anotherbuffer, pFilename );
-               char *s = strstr ( anotherbuffer, PXML_FILENAME );
-               if ( s ) {
-                 strcpy ( s, strdup(pElem->GetText()));
-                 app->icon = strdup(anotherbuffer);
-               } else if ( ( s = strrchr ( anotherbuffer, '/' ) ) ) {
-                 s += 1;
-                 strcpy ( s, strdup(pElem->GetText()));
-                 app->icon = strdup(anotherbuffer);
+               app->titles_c++;
+               if (app->titles_c > app->titles_alloc_c) //we don't have enough strings allocated
+               {
+                       app->titles_alloc_c <<= 1;
+                       app->titles = (pnd_localized_string_t *)realloc((void*)app->titles, app->titles_alloc_c);
+                       if (!app->titles) return (0); //errno = ENOMEM
                }
-#endif
-               app->icon = strdup ( pElem->GetText() );
-       }
-
-       pElem = hRoot.FirstChild( "description" ).FirstChildElement("en").Element();
-       if ( pElem )
-       {
-               app->description_en = strdup(pElem->GetText());
-       }
-
-       pElem = hRoot.FirstChild( "description" ).FirstChildElement("de").Element();
-       if ( pElem )
-       {
-               app->description_de = strdup(pElem->GetText());
-       }
 
-       pElem = hRoot.FirstChild( "description" ).FirstChildElement("it").Element();
-       if ( pElem )
-       {
-               app->description_it = strdup(pElem->GetText());
-       }
-       
-       pElem = hRoot.FirstChild( "description" ).FirstChildElement("fr").Element();
-       if ( pElem )
-       {
-               app->description_fr = strdup(pElem->GetText());
-       }
-
-       pElem = hRoot.FirstChild( "previewpic" ).FirstChildElement("pic1").Element();
-       if ( pElem )
-       {
-               app->previewpic1 = strdup(pElem->GetText());
+               pnd_localized_string_t *title = &app->titles[app->titles_c - 1];
+               title->language = lang;
+               title->string = text;
        }
 
-       pElem = hRoot.FirstChild( "previewpic" ).FirstChildElement("pic2").Element();
-       if ( pElem )
-       {
-               app->previewpic2 = strdup(pElem->GetText());
-       }
+       return (1);
+}
 
-       pElem = hRoot.FirstChild( "author" ).FirstChildElement("name").Element();
-       if ( pElem )
-       {
-               app->author_name = strdup(pElem->GetText());
-       }
+unsigned char pnd_pxml_parse_descriptions(const TiXmlHandle hRoot, pnd_pxml_t *app)
+{
+       TiXmlElement *pElem;
+       app->descriptions_alloc_c = 4; //TODO: adjust this based on how many descriptions a PXML usually has. Power of 2.
 
-       pElem = hRoot.FirstChild( "author" ).FirstChildElement("website").Element();
-       if ( pElem )
+       app->descriptions = (pnd_localized_string_t *)malloc(sizeof(pnd_localized_string_t) * app->descriptions_alloc_c);
+       if (!app->descriptions) 
        {
-               app->author_website = strdup(pElem->GetText());;
+               app->descriptions_alloc_c = 0;
+               return (0); //errno = NOMEM
        }
 
-       pElem = hRoot.FirstChild( "version" ).FirstChildElement("major").Element();
-       if ( pElem )
+       for (pElem = hRoot.FirstChild(PND_PXML_ENAME_DESCRIPTION).Element(); pElem; 
+               pElem = pElem->NextSiblingElement(PND_PXML_ENAME_DESCRIPTION))
        {
-               app->version_major = strdup(pElem->GetText());
-       }       
 
-       pElem = hRoot.FirstChild( "version" ).FirstChildElement("minor").Element();
-       if ( pElem )
-       {
-               app->version_minor = strdup(pElem->GetText());
-       }       
+         if ( ! pElem->GetText() ) {
+           continue;
+         }
 
-       pElem = hRoot.FirstChild( "version" ).FirstChildElement("release").Element();
-       if ( pElem )
-       {
-               app->version_release = strdup(pElem->GetText());
-       }       
+               char *text = strdup(pElem->GetText());
+               if (!text) continue;
 
-       pElem = hRoot.FirstChild( "version" ).FirstChildElement("build").Element();
-       if ( pElem )
-       {
-               app->version_build = strdup(pElem->GetText());
-       }
+               char *lang = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_DESCRLANG);
+               if (!lang) continue;
 
-       pElem=hRoot.FirstChild("exec").Element();
-       if (pElem)
-       {       
-#if 0
-               char anotherbuffer [ FILENAME_MAX ];
-               strcpy ( anotherbuffer, pFilename );
-               char *s = strstr ( anotherbuffer, PXML_FILENAME );
-               printf ( "exec %s\n", pElem->GetText() );
-               if ( s ) {
-                 strcpy ( s, strdup(pElem->GetText()));
-                 app->exec = strdup(anotherbuffer);
-               } else if ( ( s = strrchr ( anotherbuffer, '/' ) ) ) {
-                 s += 1;
-                 strcpy ( s, strdup(pElem->GetText()));
-                 app->exec = strdup(anotherbuffer);
+               app->descriptions_c++;
+               if (app->descriptions_c > app->descriptions_alloc_c) //we don't have enough strings allocated
+               {
+                       app->descriptions_alloc_c <<= 1;
+                       app->descriptions = (pnd_localized_string_t*)realloc((void*)app->descriptions, app->descriptions_alloc_c);
+                       if (!app->descriptions) return (0); //errno = ENOMEM
                }
-#endif
-               app->exec = strdup ( pElem->GetText() );
-       }       
 
-       pElem = hRoot.FirstChild( "category" ).FirstChildElement("main").Element();
-       if ( pElem )
-       {
-               app->main_category = strdup(pElem->GetText());
+               pnd_localized_string_t *description = &app->descriptions[app->descriptions_c - 1];
+               description->language = lang;
+               description->string = text;
        }
+       return (1);
+}
 
-       pElem = hRoot.FirstChild( "category" ).FirstChildElement("subcategory1").Element();
-       if ( pElem )
-       {
-               app->subcategory1 = strdup(pElem->GetText());
-       }
+unsigned char pnd_pxml_parse ( const char *pFilename, char *buffer, unsigned int length, pnd_pxml_t *app ) {
+       //Load the XML document
+       TiXmlDocument doc;
+       doc.Parse(buffer);
 
-       pElem = hRoot.FirstChild( "category" ).FirstChildElement("subcategory2").Element();
-       if ( pElem )
-       {
-               app->subcategory2 = strdup(pElem->GetText());
-       }
+       TiXmlElement *pElem = NULL;
 
-       pElem = hRoot.FirstChild( "altcategory" ).FirstChildElement("main").Element();
-       if ( pElem )
-       {
-               app->altcategory = strdup(pElem->GetText());
-       }
+       //Find the root element
+       TiXmlHandle hDoc(&doc);
+       TiXmlHandle hRoot(0);
 
-       pElem = hRoot.FirstChild( "altcategory" ).FirstChildElement("subcategory1").Element();
-       if ( pElem )
-       {
-               app->altsubcategory1 = strdup(pElem->GetText());
-       }
+       pElem = hDoc.FirstChild("PXML").Element();
+       if (!pElem) return (0);
+       hRoot = TiXmlHandle(pElem);
 
-       pElem = hRoot.FirstChild( "altcategory" ).FirstChildElement("subcategory2").Element();
-       if ( pElem )
-       {
-               app->altsubcategory2 = strdup(pElem->GetText());
-       }
+       //Get unique ID first.
+       app->unique_id = pnd_pxml_get_attribute(hRoot.Element(), PND_PXML_ATTRNAME_UID);
 
-       pElem = hRoot.FirstChild( "osversion" ).FirstChildElement("major").Element();
-       if ( pElem )
-       {
-               app->osversion_major = strdup(pElem->GetText());
-       }       
+       //Everything related to the title:
+       pnd_pxml_parse_titles(hRoot, app);
 
-       pElem = hRoot.FirstChild( "osversion" ).FirstChildElement("minor").Element();
-       if ( pElem )
-       {
-               app->osversion_minor = strdup(pElem->GetText());
-       }       
-
-       pElem = hRoot.FirstChild( "osversion" ).FirstChildElement("release").Element();
-       if ( pElem )
-       {
-               app->osversion_release = strdup(pElem->GetText());
-       }       
+       //Everything description-related:
+       pnd_pxml_parse_descriptions(hRoot, app);
 
-       pElem = hRoot.FirstChild( "osversion" ).FirstChildElement("build").Element();
-       if ( pElem )
+       //Everything launcher-related in one tag:
+       if ( (pElem = hRoot.FirstChild(PND_PXML_ENAME_EXEC).Element()) )
        {
-               app->osversion_build = strdup(pElem->GetText());
+               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.
+               app->standalone = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_EXECSTAL);
+               app->exec       = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_EXECCMD);
+               app->startdir   = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_EXECWD);
        }
 
-       pElem = hRoot.FirstChild( "associationitem1" ).FirstChildElement("name").Element();
-       if ( pElem )
+       //The app icon:
+       if ( (pElem = hRoot.FirstChild(PND_PXML_ENAME_ICON).Element()) )
        {
-               app->associationitem1_name = strdup(pElem->GetText());
+               app->icon       = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_ICONSRC);
        }
 
-       pElem = hRoot.FirstChild( "associationitem1" ).FirstChildElement("filetype").Element();
-       if ( pElem )
+       //The preview pics:
+       if ( (pElem = hRoot.FirstChild(PND_PXML_NODENAME_PREVPICS).Element()) )
        {
-               app->associationitem1_filetype = strdup(pElem->GetText());
-       }
+               //TODO: Change this if pnd_pxml_t gains the feature of more pics than 2.
+               if ( (pElem = pElem->FirstChildElement(PND_PXML_ENAME_PREVPIC)) )
+               {
+                       app->previewpic1 = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_PREVPICSRC);
 
-       pElem = hRoot.FirstChild( "associationitem1" ).FirstChildElement("parameter").Element();
-       if ( pElem )
-       {
-               app->associationitem1_parameter = strdup(pElem->GetText());
-       }
+                       if ( (pElem = pElem->NextSiblingElement(PND_PXML_ENAME_PREVPIC)) )
+                       {
+                               app->previewpic2 = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_PREVPICSRC);
+                       }
+               }       
+       } //previewpic
 
-       pElem = hRoot.FirstChild( "associationitem2" ).FirstChildElement("name").Element();
-       if ( pElem )
+       //The author info:
+       if ( (pElem = hRoot.FirstChild(PND_PXML_ENAME_AUTHOR).Element()) )
        {
-               app->associationitem2_name = strdup(pElem->GetText());
+               app->author_name    = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_AUTHORNAME);
+               app->author_website = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_AUTHORWWW);
+               //TODO: Uncomment this if the author gets email support.
+               //app->author_email = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_AUTHOREMAIL));
        }
 
-       pElem = hRoot.FirstChild( "associationitem2" ).FirstChildElement("filetype").Element();
-       if ( pElem )
+       //The version info:
+       if ( (pElem = hRoot.FirstChild(PND_PXML_ENAME_VERSION).Element()) )
        {
-               app->associationitem2_filetype = strdup(pElem->GetText());
+               app->version_major   = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_VERMAJOR);
+               app->version_minor   = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_VERMINOR);
+               app->version_release = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_VERREL);
+               app->version_build   = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_VERBUILD);
        }
 
-       pElem = hRoot.FirstChild( "associationitem2" ).FirstChildElement("parameter").Element();
-       if ( pElem )
+       //The OS version info:
+       if ( (pElem = hRoot.FirstChild(PND_PXML_ENAME_OSVERSION).Element()) )
        {
-               app->associationitem2_parameter = strdup(pElem->GetText());
+               app->osversion_major   = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_OSVERMAJOR);
+               app->osversion_minor   = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_OSVERMINOR);
+               app->osversion_release = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_OSVERREL);
+               app->osversion_build   = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_OSVERBUILD);
        }
 
-       pElem = hRoot.FirstChild( "associationitem3" ).FirstChildElement("name").Element();
-       if ( pElem )
+       int i; //For now, we need to keep track of the index of categories.
+       //Categories:
+       if ( (pElem = hRoot.FirstChildElement(PND_PXML_NODENAME_CATS).Element()) ) //First, enter the "categories" node.
        {
-               app->associationitem3_name = strdup(pElem->GetText());
-       }
+               i = 0;
 
-       pElem = hRoot.FirstChild( "associationitem3" ).FirstChildElement("filetype").Element();
-       if ( pElem )
-       {
-               app->associationitem3_filetype = strdup(pElem->GetText());
-       }
+               //Goes through all the top-level categories and their sub-categories. i helps limit these to 2.
+               for (pElem = pElem->FirstChildElement(PND_PXML_ENAME_CAT); pElem && i < 2; 
+                       pElem = pElem->NextSiblingElement(PND_PXML_ENAME_CAT), i++)
+               {
+                       //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.
+                       switch (i)
+                       {
+                       case 0: //first category counts as the main cat for now
+                               app->main_category = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_CATNAME);
+                               break;
 
-       pElem = hRoot.FirstChild( "associationitem3" ).FirstChildElement("parameter").Element();
-       if ( pElem )
-       {
-               app->associationitem3_parameter = strdup(pElem->GetText());
-       }
+                       case 1: //...second as the alternative
+                               app->altcategory = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_CATNAME);
+                       }
 
-       pElem=hRoot.FirstChild("clockspeed").Element();
-       if (pElem)
-       {       
-               app->clockspeed = strdup(pElem->GetText());
+                       TiXmlElement *pSubCatElem; //the sub-elements for a main category.
+                       int j = 0; //the subcategory index within this category
+
+                       //Goes through all the subcategories within this category. j helps limit these to 2.
+                       for (pSubCatElem = pElem->FirstChildElement(PND_PXML_ENAME_SUBCAT); pSubCatElem && j < 2;
+                               pSubCatElem = pSubCatElem->NextSiblingElement(PND_PXML_ENAME_SUBCAT), j++)
+                       {
+                               char *subcat = pnd_pxml_get_attribute(pSubCatElem, PND_PXML_ATTRNAME_SUBCATNAME);
+                               if (!(subcat)) continue;
+
+                               //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.
+                               switch (j & (i << 1))
+                               {
+                               case 0:
+                                       app->subcategory1 = subcat;
+                                       break;
+                               case 1:
+                                       app->subcategory2 = subcat;
+                                       break;
+                               case 2:
+                                       app->altsubcategory1 = subcat;
+                                       break;
+                               case 3:
+                                       app->altsubcategory2 = subcat;
+                               }
+                       }
+               }
        }
 
-       pElem=hRoot.FirstChild("background").Element();
-       if (pElem)
-       {       
-               app->background = strdup(pElem->GetText());
+       //All file associations:
+       //Step into the associations node
+       if ( (pElem = hRoot.FirstChild(PND_PXML_NODENAME_ASSOCS).Element()) )
+       {
+               i = 0;
+               //Go through all associations. i serves as index; since the format only supports 3 associations we need to keep track of the number.
+               for (pElem = pElem->FirstChildElement(PND_PXML_ENAME_ASSOC); pElem && i < 3; 
+                       pElem = pElem->NextSiblingElement(PND_PXML_ENAME_ASSOC), i++)
+               {
+                       char *name = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_ASSOCNAME);
+                       char *filetype = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_ASSOCFTYPE);
+                       char *paramter = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_ASSOCARGS);
+
+                       if (!(name && filetype && paramter)) continue;
+
+                       switch(i) //TODO: same problem here: only 3 associations supported
+                       {
+                               case 0:
+                               {
+                                       app->associationitem1_name      = name;
+                                       app->associationitem1_filetype  = filetype;
+                                       app->associationitem1_parameter = paramter;
+                                       break;
+                               }
+                               case 1:
+                               {
+                                       app->associationitem2_name      = name;
+                                       app->associationitem2_filetype  = filetype;
+                                       app->associationitem2_parameter = paramter;
+                                       break;
+                               }
+                               case 2:
+                               {
+                                       app->associationitem3_name      = name;
+                                       app->associationitem3_filetype  = filetype;
+                                       app->associationitem3_parameter = paramter;
+                               }
+                       }
+               }
        }
 
-       pElem=hRoot.FirstChild("startdir").Element();
+       //Performance related things (aka: Clockspeed XD):
+       pElem = hRoot.FirstChild(PND_PXML_ENAME_CLOCK).Element();
        if (pElem)
        {       
-               app->startdir = strdup(pElem->GetText());
+               app->clockspeed = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_CLOCKFREQ);
        }
 
-       return ( 1 );
+       return (1);
 }
 
 } // extern C
diff --git a/test/rawpxmltest.c b/test/rawpxmltest.c
new file mode 100644 (file)
index 0000000..26e3a96
--- /dev/null
@@ -0,0 +1,72 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <pnd_pxml.h>
+
+//A simple test for the new format. No content-checking whatsoever...
+//lots of ^C^V
+//Used like a unit test, almost
+int main (int argc, char **argv)
+{
+       if (argc != 2) 
+       {
+               printf("Wrong nr of args.\nUsage: %s <pxml filename>\n", argv[0]);
+               return 1;
+       }
+
+       pnd_pxml_handle h = pnd_pxml_fetch(argv[1]);
+
+       if (!h)
+       {
+               printf("Could not load file \"%s\"\n", argv[1]);
+               return 1;
+       }
+
+       char *data; //for all values
+
+       if ( (data = pnd_pxml_get_app_name_en(h)) ) printf("Appname(en): %s\n", data);
+       if ( (data = pnd_pxml_get_app_name_de(h)) ) printf("Appname(de): %s\n", data);
+       if ( (data = pnd_pxml_get_app_name_it(h)) ) printf("Appname(it): %s\n", data);
+       if ( (data = pnd_pxml_get_app_name_fr(h)) ) printf("Appname(fr): %s\n", data);
+
+       if ( (data = pnd_pxml_get_unique_id(h)) ) printf("UID: %s\n", data);
+
+       if ( (data = pnd_pxml_get_standalone(h)) ) printf("Standalone: %s\n", data);
+
+       if ( (data = pnd_pxml_get_icon(h)) ) printf("Icon: %s\n", data);
+
+       if ( (data = pnd_pxml_get_description_en(h)) ) printf("Description(en): %s\n", data);
+       if ( (data = pnd_pxml_get_description_de(h)) ) printf("Description(de): %s\n", data);
+       if ( (data = pnd_pxml_get_description_it(h)) ) printf("Description(it): %s\n", data);
+       if ( (data = pnd_pxml_get_description_fr(h)) ) printf("Description(fr): %s\n", data);
+
+       if ( (data = pnd_pxml_get_previewpic1(h)) ) printf("Pic1: %s\n", data);
+       if ( (data = pnd_pxml_get_previewpic2(h)) ) printf("Pic2: %s\n", data);
+
+       if ( (data = pnd_pxml_get_author_name(h)) ) printf("Author name: %s\n", data);
+       if ( (data = pnd_pxml_get_author_website(h)) ) printf("Author website: %s\n", data);
+
+       if ( (data = pnd_pxml_get_version_major(h)) ) printf("Version major: %s\n", data);
+       if ( (data = pnd_pxml_get_version_minor(h)) ) printf("Version minor: %s\n", data);
+       if ( (data = pnd_pxml_get_version_release(h)) ) printf("Version release: %s\n", data);
+       if ( (data = pnd_pxml_get_version_build(h)) ) printf("Version build: %s\n", data);
+
+       if ( (data = pnd_pxml_get_osversion_major(h)) ) printf("OSVersion major: %s\n", data);
+       if ( (data = pnd_pxml_get_osversion_minor(h)) ) printf("OSVersion minor: %s\n", data);
+       if ( (data = pnd_pxml_get_osversion_release(h)) ) printf("OSVersion release: %s\n", data);
+       if ( (data = pnd_pxml_get_osversion_build(h)) ) printf("OSVersion build: %s\n", data);
+
+       if ( (data = pnd_pxml_get_exec(h)) ) printf("Application exec: %s\n", data);
+
+       if ( (data = pnd_pxml_get_main_category(h)) ) printf("Category 1: %s\n", data);
+       if ( (data = pnd_pxml_get_subcategory1(h)) ) printf("Category 1 sub 1: %s\n", data);
+       if ( (data = pnd_pxml_get_subcategory2(h)) ) printf("Category 1 sub 2: %s\n", data);
+       if ( (data = pnd_pxml_get_altcategory(h)) ) printf("Category 2: %s\n", data);
+       if ( (data = pnd_pxml_get_altsubcategory1(h)) ) printf("Category 2 sub 1: %s\n", data);
+       if ( (data = pnd_pxml_get_altsubcategory2(h)) ) printf("Category 2 sub 2: %s\n", data);
+
+       pnd_pxml_delete(h);
+
+       return 0;
+}
index bbc7afb..61a1c74 100644 (file)
@@ -1,86 +1,43 @@
-<PXML>
-<title>
-       <en>sample 4</en>
-       <de>Program Title in German Language</de>
-       <fr>Program Title in French Language</fr>
-       <it>Program Title in Italian Language</it>
-</title>
+<?xml version="1.0" encoding="UTF-8"?>
+<PXML xmlns="http://openpandora.org/namespaces/PXML" 
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="jeff.sample.4" xsi:noNamespaceSchemaLocation="PXML_schema.xsd">
+  <title lang="en_US">Sample App 4 Alt Path</title>
+  <title lang="de_DE">Sample App 4 Alt Path - German</title>
 
-<unique_id>345jaloo</unique_id>
+  <exec background="true" startdir="/usr/share/icons/" standalone="true" command="program.exe"/>
 
-<standalone>Yes</standalone>
+  <icon src="viscountofadrilankha.png"/>
 
-<icon>zeldaicon.png</icon>
+  <description lang="en_US">This is the English Description of the file.</description>
+  <description lang="de_DE">This would be the German description.</description>
 
-<description>
-       <en>This is the [b]English Description[/b] of the file.
-            Can use [i]multiple lines[/i] and BBCode.</en>
-       <de>The German Description</de>
-       <it>The Italian Description</it>
-       <fr>The French Description</fr>
-</description>
+  <previewpics>
+    <pic src="./preview/pic1.jpg"/>
+    <pic src="./preview/pic2.jpg"/>
+  </previewpics>
 
-<previewpic>
-       <pic1>./preview/pic1.jpg</pic1>
-       <pic2>./preview/pic2.jpg</pic2>
-</previewpic>
+  <author name="EvilDragon" website="http://www.openpandora.org"/><!--Optional email and website, name required-->
 
-<author>
-       <name>EvilDragon</name>
-       <website>http://www.openpandora.org</website>
-</author>
+  <version major="1" minor="1" release="1" build="2"/><!--This program's version-->
+  <osversion major="1" minor="0" release="0" build="0"/><!--The minimum OS version required-->
 
-<version>
-       <major>1</major>
-       <minor>1</minor>
-       <release>1</release>
-       <build>2</build>
-</version>
+  <categories>
+    <category name="Main category"><!--category like "Games", "Graphics", "Internet" etc-->
+    <subcategory name="Subcategory 1"/><!--subcategory, like "Board Games", "Strategy", "First Person Shooters"-->
+    <subcategory name="Subcategory 2"/>
+    </category>
+    <category name="Alternative category">
+      <subcategory name="Alternative Subcategory 1"/>
+    </category>
+  </categories>
 
-<exec>program.exe</exec>
+  <associations>
+    <!--File associations, with a short description, an extension, and start params.-->
+    <association name="View Word File" filetype="application/msword" exec="-f %s -t doc"/>
+  </associations>
 
-<category>
-       <main>Main category</main>
-       <subcategory1>Subcategory 1</subcategory1>
-       <subcategory2>Subcategory 2</subcategory2>
-</category>
-
-<altcategory>
-       <main>Alternate category</main>
-       <subcategory1>Alternate Subcategory 1</subcategory1>
-       <subcategory2>Alternate Subcategory 2</subcategory2>
-</altcategory>
-
-<osversion> 
-       <major>1</major>
-       <minor>1</minor>
-       <release>1</release>
-       <build>2</build>
-</osversion>
-
-<associationitem1>
-       <name>View this Picture</name>
-       <filetype>jpg,bmp,gif</filetype>
-       <parameter>­view</parameter>
-</associationitem1>
-
-<associationitem2>
-       <name>Convert this Picture</name>
-       <filetype>jpg,bmp,gif</filetype>
-       <parameter>­convert</parameter>
-</associationitem2>
-
-<associationitem3>
-       <name>Watch This Movie</name>
-       <filetype>mpg,avi,wmv</filetype>
-       <parameter>­convert</parameter>
-</associationitem3>
-
-<clockspeed>600</clockspeed>
-
-<background>Yes</background>
-
-<startdir>../differentdir</startdir>
+  <clockspeed frequency="600"/><!--Frequency in Hz-->
 
+  <configuration for="gmenupandora">......kfujl........</configuration><!--random data, this is for specific menus-->
+  <configuration for="anothermenu">......qwe......fwer.....</configuration>
 </PXML>
-
diff --git a/testdata/apps/sampleapp/PXML.xml b/testdata/apps/sampleapp/PXML.xml
deleted file mode 100644 (file)
index 776b9b7..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-<?xml version="1.0"?>
-<PXML>
-<title>
-       <en>Program Title</en>
-       <de>Program Title in German Language</de>
-       <fr>Program Title in French Language</fr>
-       <it>Program Title in Italian Language</it>
-</title>
-
-<unique_id>123shaboo</unique_id>
-
-<standalone>Yes</standalone>
-
-<icon>program.png</icon>
-
-<description>
-       <en>This is the [b]English Description[/b] of the file.
-            Can use [i]multiple lines[/i] and BBCode.</en>
-       <de>The German Description</de>
-       <it>The Italian Description</it>
-       <fr>The French Description</fr>
-</description>
-
-<previewpic>
-       <pic1>./preview/pic1.jpg</pic1>
-       <pic2>./preview/pic2.jpg</pic2>
-</previewpic>
-
-<author>
-       <name>EvilDragon</name>
-       <website>http://www.openpandora.org</website>
-</author>
-
-<version>
-       <major>1</major>
-       <minor>1</minor>
-       <release>1</release>
-       <build>2</build>
-</version>
-
-<exec>program.exe</exec>
-
-<category>
-       <main>Main category</main>
-       <subcategory1>Subcategory 1</subcategory1>
-       <subcategory2>Subcategory 2</subcategory2>
-</category>
-
-<altcategory>
-       <main>Alternate category</main>
-       <subcategory1>Alternate Subcategory 1</subcategory1>
-       <subcategory2>Alternate Subcategory 2</subcategory2>
-</altcategory>
-
-<osversion> 
-       <major>1</major>
-       <minor>1</minor>
-       <release>1</release>
-       <build>2</build>
-</osversion>
-
-<associationitem1>
-       <name>View this Picture</name>
-       <filetype>jpg,bmp,gif</filetype>
-       <parameter>­view</parameter>
-</associationitem1>
-
-<associationitem2>
-       <name>Convert this Picture</name>
-       <filetype>jpg,bmp,gif</filetype>
-       <parameter>­convert</parameter>
-</associationitem2>
-
-<associationitem3>
-       <name>Watch This Movie</name>
-       <filetype>mpg,avi,wmv</filetype>
-       <parameter>­convert</parameter>
-</associationitem3>
-
-<clockspeed>600</clockspeed>
-
-<background>Yes</background>
-
-<startdir>../differentdir</startdir>
-
-</PXML>
diff --git a/testdata/apps/sampleapp1/PXML.xml b/testdata/apps/sampleapp1/PXML.xml
new file mode 100644 (file)
index 0000000..893c1cd
--- /dev/null
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<PXML xmlns="http://openpandora.org/namespaces/PXML" 
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="jeff.sample.1" xsi:noNamespaceSchemaLocation="PXML_schema.xsd">
+  <title lang="en_US">Sample App 1</title>
+  <title lang="de_DE">Sample App 1 - German</title>
+
+  <exec background="true" startdir="/usr/share/icons/" standalone="true" command="program.exe"/>
+
+  <description lang="en_US">This is the English Description of the file.</description>
+  <description lang="de_DE">This would be the German description.</description>
+
+  <previewpics>
+    <pic src="./preview/pic1.jpg"/>
+    <pic src="./preview/pic2.jpg"/>
+  </previewpics>
+
+  <author name="EvilDragon" website="http://www.openpandora.org"/><!--Optional email and website, name required-->
+
+  <version major="1" minor="1" release="1" build="2"/><!--This program's version-->
+  <osversion major="1" minor="0" release="0" build="0"/><!--The minimum OS version required-->
+
+  <categories>
+    <category name="Main category"><!--category like "Games", "Graphics", "Internet" etc-->
+    <subcategory name="Subcategory 1"/><!--subcategory, like "Board Games", "Strategy", "First Person Shooters"-->
+    <subcategory name="Subcategory 2"/>
+    </category>
+    <category name="Alternative category">
+      <subcategory name="Alternative Subcategory 1"/>
+    </category>
+  </categories>
+
+  <associations>
+    <!--File associations, with a short description, an extension, and start params.-->
+    <association name="View Word File" filetype="application/msword" exec="-f %s -t doc"/>
+  </associations>
+
+  <clockspeed frequency="600"/><!--Frequency in Hz-->
+
+  <configuration for="gmenupandora">......kfujl........</configuration><!--random data, this is for specific menus-->
+  <configuration for="anothermenu">......qwe......fwer.....</configuration>
+</PXML>
diff --git a/testdata/apps/sampleapp1/zeldaicon.png b/testdata/apps/sampleapp1/zeldaicon.png
new file mode 100644 (file)
index 0000000..140a393
Binary files /dev/null and b/testdata/apps/sampleapp1/zeldaicon.png differ
index f126e60..8cb0749 100644 (file)
@@ -1,84 +1,43 @@
-<?xml version="1.0"?>
-<PXML>
-<title>
-       <en>Program Title</en>
-       <de>Program Title in German Language</de>
-       <fr>Program Title in French Language</fr>
-       <it>Program Title in Italian Language</it>
-</title>
+<?xml version="1.0" encoding="UTF-8"?>
+<PXML xmlns="http://openpandora.org/namespaces/PXML" 
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="jeff.sample.2" xsi:noNamespaceSchemaLocation="PXML_schema.xsd">
+  <title lang="en_US">Sample App 2</title>
+  <title lang="de_DE">Sample App 2 - German</title>
 
-<unique_id>124bingle</unique_id>
+  <exec background="true" startdir="/usr/share/icons/" standalone="true" command="program.exe"/>
 
-<standalone>Yes</standalone>
+  <icon src="cyborgdonut.png"/>
 
-<description>
-       <en>This is the [b]English Description[/b] of the file.
-            Can use [i]multiple lines[/i] and BBCode.</en>
-       <de>The German Description</de>
-       <it>The Italian Description</it>
-       <fr>The French Description</fr>
-</description>
+  <description lang="en_US">This is the English Description of the file.</description>
+  <description lang="de_DE">This would be the German description.</description>
 
-<previewpic>
-       <pic1>./preview/pic1.jpg</pic1>
-       <pic2>./preview/pic2.jpg</pic2>
-</previewpic>
+  <previewpics>
+    <pic src="./preview/pic1.jpg"/>
+    <pic src="./preview/pic2.jpg"/>
+  </previewpics>
 
-<author>
-       <name>EvilDragon</name>
-       <website>http://www.openpandora.org</website>
-</author>
+  <author name="EvilDragon" website="http://www.openpandora.org"/><!--Optional email and website, name required-->
 
-<version>
-       <major>1</major>
-       <minor>1</minor>
-       <release>1</release>
-       <build>2</build>
-</version>
+  <version major="1" minor="1" release="1" build="2"/><!--This program's version-->
+  <osversion major="1" minor="0" release="0" build="0"/><!--The minimum OS version required-->
 
-<exec>program.exe</exec>
+  <categories>
+    <category name="Main category"><!--category like "Games", "Graphics", "Internet" etc-->
+    <subcategory name="Subcategory 1"/><!--subcategory, like "Board Games", "Strategy", "First Person Shooters"-->
+    <subcategory name="Subcategory 2"/>
+    </category>
+    <category name="Alternative category">
+      <subcategory name="Alternative Subcategory 1"/>
+    </category>
+  </categories>
 
-<category>
-       <main>Main category</main>
-       <subcategory1>Subcategory 1</subcategory1>
-       <subcategory2>Subcategory 2</subcategory2>
-</category>
+  <associations>
+    <!--File associations, with a short description, an extension, and start params.-->
+    <association name="View Word File" filetype="application/msword" exec="-f %s -t doc"/>
+  </associations>
 
-<altcategory>
-       <main>Alternate category</main>
-       <subcategory1>Alternate Subcategory 1</subcategory1>
-       <subcategory2>Alternate Subcategory 2</subcategory2>
-</altcategory>
-
-<osversion> 
-       <major>1</major>
-       <minor>1</minor>
-       <release>1</release>
-       <build>2</build>
-</osversion>
-
-<associationitem1>
-       <name>View this Picture</name>
-       <filetype>jpg,bmp,gif</filetype>
-       <parameter>­view</parameter>
-</associationitem1>
-
-<associationitem2>
-       <name>Convert this Picture</name>
-       <filetype>jpg,bmp,gif</filetype>
-       <parameter>­convert</parameter>
-</associationitem2>
-
-<associationitem3>
-       <name>Watch This Movie</name>
-       <filetype>mpg,avi,wmv</filetype>
-       <parameter>­convert</parameter>
-</associationitem3>
-
-<clockspeed>600</clockspeed>
-
-<background>Yes</background>
-
-<startdir>../differentdir</startdir>
+  <clockspeed frequency="600"/><!--Frequency in Hz-->
 
+  <configuration for="gmenupandora">......kfujl........</configuration><!--random data, this is for specific menus-->
+  <configuration for="anothermenu">......qwe......fwer.....</configuration>
 </PXML>
diff --git a/testdata/apps/sampleapp2/zeldaicon.png b/testdata/apps/sampleapp2/zeldaicon.png
new file mode 100644 (file)
index 0000000..140a393
Binary files /dev/null and b/testdata/apps/sampleapp2/zeldaicon.png differ
index a83165f..495f5ee 100644 (file)
@@ -1,86 +1,43 @@
-<PXML>
-<title>
-       <en>sample 3</en>
-       <de>Program Title in German Language</de>
-       <fr>Program Title in French Language</fr>
-       <it>Program Title in Italian Language</it>
-</title>
+<?xml version="1.0" encoding="UTF-8"?>
+<PXML xmlns="http://openpandora.org/namespaces/PXML" 
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="jeff.sample.3" xsi:noNamespaceSchemaLocation="PXML_schema.xsd">
+  <title lang="en_US">Sample App 3</title>
+  <title lang="de_DE">Sample App 3 - German</title>
 
-<unique_id>256twinky</unique_id>
+  <exec background="true" startdir="/usr/share/icons/" standalone="true" command="program.exe"/>
 
-<standalone>Yes</standalone>
+  <icon src="zeldaicon.png"/>
 
-<icon>zeldaicon.png</icon>
+  <description lang="en_US">This is the English Description of the file.</description>
+  <description lang="de_DE">This would be the German description.</description>
 
-<description>
-       <en>This is the [b]English Description[/b] of the file.
-            Can use [i]multiple lines[/i] and BBCode.</en>
-       <de>The German Description</de>
-       <it>The Italian Description</it>
-       <fr>The French Description</fr>
-</description>
+  <previewpics>
+    <pic src="./preview/pic1.jpg"/>
+    <pic src="./preview/pic2.jpg"/>
+  </previewpics>
 
-<previewpic>
-       <pic1>./preview/pic1.jpg</pic1>
-       <pic2>./preview/pic2.jpg</pic2>
-</previewpic>
+  <author name="EvilDragon" website="http://www.openpandora.org"/><!--Optional email and website, name required-->
 
-<author>
-       <name>EvilDragon</name>
-       <website>http://www.openpandora.org</website>
-</author>
+  <version major="1" minor="1" release="1" build="2"/><!--This program's version-->
+  <osversion major="1" minor="0" release="0" build="0"/><!--The minimum OS version required-->
 
-<version>
-       <major>1</major>
-       <minor>1</minor>
-       <release>1</release>
-       <build>2</build>
-</version>
+  <categories>
+    <category name="Main category"><!--category like "Games", "Graphics", "Internet" etc-->
+    <subcategory name="Subcategory 1"/><!--subcategory, like "Board Games", "Strategy", "First Person Shooters"-->
+    <subcategory name="Subcategory 2"/>
+    </category>
+    <category name="Alternative category">
+      <subcategory name="Alternative Subcategory 1"/>
+    </category>
+  </categories>
 
-<exec>program.exe</exec>
+  <associations>
+    <!--File associations, with a short description, an extension, and start params.-->
+    <association name="View Word File" filetype="application/msword" exec="-f %s -t doc"/>
+  </associations>
 
-<category>
-       <main>Main category</main>
-       <subcategory1>Subcategory 1</subcategory1>
-       <subcategory2>Subcategory 2</subcategory2>
-</category>
-
-<altcategory>
-       <main>Alternate category</main>
-       <subcategory1>Alternate Subcategory 1</subcategory1>
-       <subcategory2>Alternate Subcategory 2</subcategory2>
-</altcategory>
-
-<osversion> 
-       <major>1</major>
-       <minor>1</minor>
-       <release>1</release>
-       <build>2</build>
-</osversion>
-
-<associationitem1>
-       <name>View this Picture</name>
-       <filetype>jpg,bmp,gif</filetype>
-       <parameter>­view</parameter>
-</associationitem1>
-
-<associationitem2>
-       <name>Convert this Picture</name>
-       <filetype>jpg,bmp,gif</filetype>
-       <parameter>­convert</parameter>
-</associationitem2>
-
-<associationitem3>
-       <name>Watch This Movie</name>
-       <filetype>mpg,avi,wmv</filetype>
-       <parameter>­convert</parameter>
-</associationitem3>
-
-<clockspeed>600</clockspeed>
-
-<background>Yes</background>
-
-<startdir>../differentdir</startdir>
+  <clockspeed frequency="600"/><!--Frequency in Hz-->
 
+  <configuration for="gmenupandora">......kfujl........</configuration><!--random data, this is for specific menus-->
+  <configuration for="anothermenu">......qwe......fwer.....</configuration>
 </PXML>
-
index 23b75c0..d3891db 100644 (file)
Binary files a/testdata/pndsample/x86_echo.pnd and b/testdata/pndsample/x86_echo.pnd differ
index 8523743..a0b8351 100644 (file)
@@ -1,24 +1,12 @@
-<?xml version="1.0"?>
-<PXML>
-<title>
-       <en>x86 echo</en>
-       <de>Program Title in German Language</de>
-       <fr>Program Title in French Language</fr>
-       <it>Program Title in Italian Language</it>
-</title>
+<?xml version="1.0" encoding="UTF-8"?>
+<PXML xmlns="http://openpandora.org/namespaces/PXML" 
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="jeff.sample.pnd.winkydink123" xsi:noNamespaceSchemaLocation="PXML_schema.xsd">
+  <title lang="en_US">PND Echo</title>
+  <title lang="de_DE">PND Echo - German</title>
 
-<unique_id>123456x86echo</unique_id>
+  <exec background="true" startdir="." standalone="true" command="my_echo"/>
 
-<standalone>Yes</standalone>
-
-<exec>my_echo</exec>
-
-<category>
-       <main>Main category</main>
-       <subcategory1>Subcategory 1</subcategory1>
-       <subcategory2>Subcategory 2</subcategory2>
-</category>
-
-<clockspeed>200</clockspeed>
+  <description lang="en_US">This is the English Description of the file.</description>
+  <description lang="de_DE">This would be the German description.</description>
 
 </PXML>
index 2fd9cc5..1cc6c85 100644 (file)
Binary files a/testdata/pndsample/x86_ls.pnd and b/testdata/pndsample/x86_ls.pnd differ
index 7a77137..f59cc4c 100644 (file)
@@ -1,86 +1,14 @@
-<?xml version="1.0"?>
-<PXML>
-<title>
-       <en>x86 ls</en>
-       <de>Program Title in German Language</de>
-       <fr>Program Title in French Language</fr>
-       <it>Program Title in Italian Language</it>
-</title>
+<?xml version="1.0" encoding="UTF-8"?>
+<PXML xmlns="http://openpandora.org/namespaces/PXML" 
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="jeff.sample.pnd.ls.hooha" xsi:noNamespaceSchemaLocation="PXML_schema.xsd">
+  <title lang="en_US">PND ls</title>
+  <title lang="de_DE">PND ls - German</title>
 
-<unique_id>123456x86ls</unique_id>
+  <exec background="true" startdir="." standalone="true" command="my_ls"/>
 
-<standalone>Yes</standalone>
+  <icon src="zeldaicon.png"/>
 
-<icon>zeldaicon.png</icon>
-
-<description>
-       <en>This is the [b]English Description[/b] of the file.
-            Can use [i]multiple lines[/i] and BBCode.</en>
-       <de>The German Description</de>
-       <it>The Italian Description</it>
-       <fr>The French Description</fr>
-</description>
-
-<previewpic>
-       <pic1>./preview/pic1.jpg</pic1>
-       <pic2>./preview/pic2.jpg</pic2>
-</previewpic>
-
-<author>
-       <name>EvilDragon</name>
-       <website>http://www.openpandora.org</website>
-</author>
-
-<version>
-       <major>1</major>
-       <minor>1</minor>
-       <release>1</release>
-       <build>2</build>
-</version>
-
-<exec>./my_ls</exec>
-
-<category>
-       <main>Main category</main>
-       <subcategory1>Subcategory 1</subcategory1>
-       <subcategory2>Subcategory 2</subcategory2>
-</category>
-
-<altcategory>
-       <main>Alternate category</main>
-       <subcategory1>Alternate Subcategory 1</subcategory1>
-       <subcategory2>Alternate Subcategory 2</subcategory2>
-</altcategory>
-
-<osversion> 
-       <major>1</major>
-       <minor>1</minor>
-       <release>1</release>
-       <build>2</build>
-</osversion>
-
-<associationitem1>
-       <name>View this Picture</name>
-       <filetype>jpg,bmp,gif</filetype>
-       <parameter>­view</parameter>
-</associationitem1>
-
-<associationitem2>
-       <name>Convert this Picture</name>
-       <filetype>jpg,bmp,gif</filetype>
-       <parameter>­convert</parameter>
-</associationitem2>
-
-<associationitem3>
-       <name>Watch This Movie</name>
-       <filetype>mpg,avi,wmv</filetype>
-       <parameter>­convert</parameter>
-</associationitem3>
-
-<clockspeed>600</clockspeed>
-
-<background>Yes</background>
-
-<startdir>../differentdir</startdir>
+  <description lang="en_US">This is the English Description of the file.</description>
+  <description lang="de_DE">This would be the German description.</description>
 
 </PXML>