--- /dev/null
+
+# Open Pandora
+# dotdesktop configuration
+
+# this config file maps 'PXML' categories to free-desktop standard categories
+# ie: category 'Foo' could map to more standard 'Utility', thus making .desktop file
+# emitting a more useful thing
+
+# the standard listing of categories is:
+# http://standards.freedesktop.org/menu-spec/latest/apa.html
+
+# note that 'map' section in the config is _required_ for a match to be found; this
+# is done to separate categories from (future) top-level directives
+
+default Application;Utility;Network;
+
+[map]
+Development Development
+Education Education
+Games Game
+Graphics Graphics
+Internet Network
+Multimedia AudioVideo
+Office Office
+Settings Settings
+System System
+Utilities Utility
pnd_conf_apps, // provides application search-path, pxml override location, etc.
pnd_conf_startup, // provides list of startup applications, basic shell application, etc.
pnd_conf_desktop, // provides settings for the launchers
+ pnd_conf_categories, // provides mapping from PXML category to dot-desktop category
} pnd_conf_filename_e;
typedef struct {
* config file accessor functions public API
*/
-/* get_as_char() will attempt to locate the specified key string (of format section,key) in the
+/* get_as_char() will attempt to locate the specified key string (of format section.key) in the
* provided config handle. Do not free up this value, it is considered read only.
* Returns NULL on error, otherwise a READ ONLY char* reference to the value.
*/
// to the given directory; returns 1 on sucess, otherwise is a fail.
unsigned char pnd_emit_icon ( char *targetpath, pnd_disco_t *p );
+// pnd_map_dotdesktop_categories() will attempt to find an appropriate standard .desktop category(s) based
+// on the provided PXML-style category.
+// In essence, the PXML top-level (and alternate) category will be used, but if (for example) the top
+// level primary cat is no good, then it will descend into the alternates for that to find the mapping.
+// NOTE: PXML has a prime and alt category, with sub-category; the standard only supports a flat list of
+// categories to show an entry in (though any number of 'alternates.' so the formats are not directly
+// compatible.
+// Pass in the PXML handle, and the target buffer will be filled up
+// Returns the number of successful mappings on success, or -1 for error (0 for no matches of course.)
+// QUESTION: It possible makes sense to just copy over verbatim any categories that are unmapped, as a 'best guess'
+// scenario, but it currently is not coded like that.
+int pnd_map_dotdesktop_categories ( pnd_conf_handle c, char *target_buffer, unsigned short int len, pnd_disco_t *d ); // <---
+char *pnd_map_dotdesktop_category ( pnd_conf_handle c, char *single_category ); // not likely needed by anyone
+// this default is only used if the conf file's "default" key cannot be found, and the category cannot be mapped
+#define PND_DOTDESKTOP_DEFAULT_CATEGORY "Application;Utility;"
#ifdef __cplusplus
} /* "C" */
char *object_path; // directory containing pnd or PXML.xml (does not include filename)
char *object_filename; // filename within object_path of the app: the PXML.xml or awesomeapp.pnd file itself
unsigned int pnd_icon_pos; // offset to the byte after end of PXML in a pnd file (should be icon if present)
- // strdup'd from PXML
+ // strdup'd from PXML -- hey, who was the idiot who thought it was a reat idea not to just re-use the pxml-struct?
char *title_en;
char *unique_id;
char *icon;
char *exec;
- char *main_category;
char *clockspeed;
char *startdir;
char *option_no_x11;
+ char *main_category;
+ char *main_category1;
+ char *main_category2;
+ char *alt_category;
+ char *alt_category1;
+ char *alt_category2;
} pnd_disco_t;
void pnd_disco_destroy ( pnd_disco_t *p ); // a function name that simply could not be avoided
{ pnd_conf_apps, "apps" },
{ pnd_conf_startup, "startup" },
{ pnd_conf_desktop, "desktop" },
+ { pnd_conf_categories, "categories" },
{ pnd_conf_nil, NULL },
};
#include <stdio.h> /* for FILE etc */
#include <string.h>
#include <unistd.h> /* for unlink */
+#include <stdlib.h> /* for free */
#include "pnd_apps.h"
#include "pnd_container.h"
#include "pnd_pxml.h"
#include "pnd_discovery.h"
#include "pnd_pndfiles.h"
+#include "pnd_conf.h"
+#include "pnd_desktop.h"
unsigned char pnd_emit_dotdesktop ( char *targetpath, char *pndrun, pnd_disco_t *p ) {
char filename [ FILENAME_MAX ];
fprintf ( f, "%s", buffer );
}
-#if 1 // categories
- fprintf ( f, "%s\n", "Categories=Application;Network;" );
-#endif
+ // categories
+ {
+ char cats [ 512 ] = "";
+ int n;
+ pnd_conf_handle c;
+ char *confpath;
+
+ // uuuuh, defaults?
+ // "Application" used to be in the standard and is commonly supported still
+ // Utility and Network should ensure the app is visible 'somewhere' :/
+ char *defaults = PND_DOTDESKTOP_DEFAULT_CATEGORY;
+
+ // determine searchpath (for conf, not for apps)
+ confpath = pnd_conf_query_searchpath();
+
+ // inhale the conf file
+ c = pnd_conf_fetch_by_id ( pnd_conf_categories, confpath );
+
+ // if we can find a default category set, pull it in; otherwise assume
+ // the hardcoded one
+ if ( pnd_conf_get_as_char ( c, "default" ) ) {
+ defaults = pnd_conf_get_as_char ( c, "default" );
+ }
+
+ // ditch the confpath
+ free ( confpath );
+
+ // attempt mapping
+ if ( c ) {
+
+ n = pnd_map_dotdesktop_categories ( c, cats, 511, p );
+
+ if ( n ) {
+ fprintf ( f, "Categories=%s\n", cats );
+ } else {
+ fprintf ( f, "Categories=%s\n", defaults );
+ }
+
+ } else {
+ fprintf ( f, "Categories=%s\n", defaults );
+ }
+
+ }
fprintf ( f, "%s\n", PND_DOTDESKTOP_SOURCE ); // should we need to know 'who' created the file during trimming
return ( 1 );
}
+
+//int pnd_map_dotdesktop_categories ( pnd_conf_handle c, char *target_buffer, unsigned short int len, pnd_pxml_handle h ) {
+int pnd_map_dotdesktop_categories ( pnd_conf_handle c, char *target_buffer, unsigned short int len, pnd_disco_t *d ) {
+ unsigned short int n = 0; // no. matches
+ char *t;
+ char *match;
+
+ // clear target so we can easily append
+ memset ( target_buffer, '\0', len );
+
+ /* attempt primary category chain
+ */
+ match = NULL;
+
+ if ( ( t = d -> main_category ) ) {
+ match = pnd_map_dotdesktop_category ( c, t );
+ }
+
+ if ( ( ! match ) &&
+ ( t = d -> main_category1 ) )
+ {
+ match = pnd_map_dotdesktop_category ( c, t );
+ }
+
+ if ( ( ! match ) &&
+ ( t = d -> main_category2 ) )
+ {
+ match = pnd_map_dotdesktop_category ( c, t );
+ }
+
+ if ( match ) {
+ strncat ( target_buffer, match, len );
+ len -= strlen ( target_buffer );
+ n += 1;
+ }
+
+ /* attempt secondary category chain
+ */
+ match = NULL;
+
+ if ( ( t = d -> alt_category ) ) {
+ match = pnd_map_dotdesktop_category ( c, t );
+ }
+
+ if ( ( ! match ) &&
+ ( t = d -> alt_category1 ) )
+ {
+ match = pnd_map_dotdesktop_category ( c, t );
+ }
+
+ if ( ( ! match ) &&
+ ( t = d -> alt_category2 ) )
+ {
+ match = pnd_map_dotdesktop_category ( c, t );
+ }
+
+ if ( match ) {
+ if ( target_buffer [ 0 ] != '\0' && len > 0 ) {
+ strcat ( target_buffer, ";" );
+ len -= 1;
+ }
+ strncat ( target_buffer, match, len );
+ len -= strlen ( target_buffer );
+ n += 1;
+ }
+
+#if 0 // doh, originally I was using pxml-t till I realized I pre-boned myself on that one
+ match = NULL;
+
+ if ( ( t = pnd_pxml_get_main_category ( h ) ) ) {
+ match = pnd_map_dotdesktop_category ( c, t );
+ }
+
+ if ( ( ! match ) &&
+ ( t = pnd_pxml_get_subcategory1 ( h ) ) )
+ {
+ match = pnd_map_dotdesktop_category ( c, t );
+ }
+
+ if ( ( ! match ) &&
+ ( t = pnd_pxml_get_subcategory2 ( h ) ) )
+ {
+ match = pnd_map_dotdesktop_category ( c, t );
+ }
+
+ if ( match ) {
+ strncat ( target_buffer, match, len );
+ len -= strlen ( target_buffer );
+ n += 1;
+ }
+
+ /* attempt secondary category chain
+ */
+ match = NULL;
+
+ if ( ( t = pnd_pxml_get_altcategory ( h ) ) ) {
+ match = pnd_map_dotdesktop_category ( c, t );
+ }
+
+ if ( ( ! match ) &&
+ ( t = pnd_pxml_get_altsubcategory1 ( h ) ) )
+ {
+ match = pnd_map_dotdesktop_category ( c, t );
+ }
+
+ if ( ( ! match ) &&
+ ( t = pnd_pxml_get_altsubcategory2 ( h ) ) )
+ {
+ match = pnd_map_dotdesktop_category ( c, t );
+ }
+
+ if ( match ) {
+ if ( target_buffer [ 0 ] != '\0' && len > 0 ) {
+ strcat ( target_buffer, ";" );
+ len -= 1;
+ }
+ strncat ( target_buffer, match, len );
+ len -= strlen ( target_buffer );
+ n += 1;
+ }
+#endif
+
+ if ( n && len ) {
+ strcat ( target_buffer, ";" );
+ }
+
+ return ( n );
+}
+
+// given category 'foo', look it up in the provided config map. return the char* reference, or NULL
+char *pnd_map_dotdesktop_category ( pnd_conf_handle c, char *single_category ) {
+ char *key;
+
+ key = malloc ( strlen ( single_category ) + 4 + 1 );
+
+ sprintf ( key, "map.%s", single_category );
+
+ return ( pnd_conf_get_as_char ( c, key ) );
+}
void pnd_disco_destroy ( pnd_disco_t *p ) {
- if ( p -> title_en ) {
- free ( p -> title_en );
- }
-
- if ( p -> icon ) {
- free ( p -> icon );
- }
-
- if ( p -> exec ) {
- free ( p -> exec );
- }
-
- if ( p -> unique_id ) {
- free ( p -> unique_id );
- }
-
- if ( p -> main_category ) {
- free ( p -> main_category );
- }
-
- if ( p -> clockspeed ) {
- free ( p -> clockspeed );
- }
+ if ( p -> title_en ) { free ( p -> title_en ); }
+ if ( p -> unique_id ) { free ( p -> unique_id ); }
+ if ( p -> icon ) { free ( p -> icon ); }
+ if ( p -> exec ) { free ( p -> exec ); }
+ if ( p -> clockspeed ) { free ( p -> clockspeed ); }
+ if ( p -> startdir ) { free ( p -> startdir ); }
+ if ( p -> option_no_x11 ) { free ( p -> option_no_x11 ); }
+ if ( p -> main_category ) { free ( p -> main_category ); }
+ if ( p -> main_category1 ) { free ( p -> main_category1 ); }
+ if ( p -> main_category2 ) { free ( p -> main_category2 ); }
+ if ( p -> alt_category ) { free ( p -> alt_category ); }
+ if ( p -> alt_category1 ) { free ( p -> alt_category1 ); }
+ if ( p -> alt_category2 ) { free ( p -> alt_category2 ); }
return;
}
if ( pnd_pxml_get_unique_id ( pxmlh ) ) {
p -> unique_id = strdup ( pnd_pxml_get_unique_id ( pxmlh ) );
}
- if ( pnd_pxml_get_main_category ( pxmlh ) ) {
- p -> main_category = strdup ( pnd_pxml_get_main_category ( pxmlh ) );
- }
if ( pnd_pxml_get_clockspeed ( pxmlh ) ) {
p -> clockspeed = strdup ( pnd_pxml_get_clockspeed ( pxmlh ) );
}
if ( pnd_pxml_get_startdir ( pxmlh ) ) {
p -> startdir = strdup ( pnd_pxml_get_startdir ( pxmlh ) );
}
+ // category kruft
+ if ( pnd_pxml_get_main_category ( pxmlh ) ) {
+ p -> main_category = strdup ( pnd_pxml_get_main_category ( pxmlh ) );
+ }
+ if ( pnd_pxml_get_subcategory1 ( pxmlh ) ) {
+ p -> main_category1 = strdup ( pnd_pxml_get_subcategory1 ( pxmlh ) );
+ }
+ if ( pnd_pxml_get_subcategory2 ( pxmlh ) ) {
+ p -> main_category2 = strdup ( pnd_pxml_get_subcategory2 ( pxmlh ) );
+ }
+ if ( pnd_pxml_get_altcategory ( pxmlh ) ) {
+ p -> alt_category = strdup ( pnd_pxml_get_altcategory ( pxmlh ) );
+ }
+ if ( pnd_pxml_get_altsubcategory1 ( pxmlh ) ) {
+ p -> alt_category1 = strdup ( pnd_pxml_get_altsubcategory1 ( pxmlh ) );
+ }
+ if ( pnd_pxml_get_altsubcategory2 ( pxmlh ) ) {
+ p -> alt_category2 = strdup ( pnd_pxml_get_altsubcategory2 ( pxmlh ) );
+ }
} else {
//printf ( "Invalid PXML; skipping.\n" );
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))
+ switch (j | (i << 1))
{
case 0:
app->subcategory1 = subcat;
<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 name="MainCategory"><!--category like "Games", "Graphics", "Internet" etc-->
+ <subcategory name="Subcategory1"/><!--subcategory, like "Board Games", "Strategy", "First Person Shooters"-->
+ <subcategory name="Subcategory2"/>
</category>
- <category name="Alternative category">
- <subcategory name="Alternative Subcategory 1"/>
+ <category name="AlternativeCategory">
+ <subcategory name="AlternativeSubcategory1"/>
</category>
</categories>
--- /dev/null
+
+# Open Pandora
+# dotdesktop configuration
+
+# this config file maps 'PXML' categories to free-desktop standard categories
+# ie: category 'Foo' could map to more standard 'Utility', thus making .desktop file
+# emitting a more useful thing
+
+# the standard listing of categories is:
+# http://standards.freedesktop.org/menu-spec/latest/apa.html
+
+# note that 'map' section in the config is _required_ for a match to be found; this
+# is done to separate categories from (future) top-level directives
+
+default Application;Utility;Network;
+
+[map]
+Subcategory1 Graphics
+Development Development
+Education Education
+Games Game
+Graphics Graphics
+Internet Network
+Multimedia AudioVideo
+Office Office
+Settings Settings
+System System
+Utilities Utility