all: ${SOLIB} ${LIB} conftest discotest evdevtest notifytest pndnotifyd rawpxmltest pndvalidator loggertest dbusnotifytest pnd_run pndevmapperd pnd_info evtest mmenu mmwrapper
clean:
- ${RM} -f ${ALLOBJ} ${XMLOBJ} ${LIB} ${SOLIB1} locatetest.o bin/locatetest conftest.o bin/conftest discotest.o evdevtest.o bin/evdevtest bin/discotest dbusnotifytest.o bin/dbusnotifytest loggertest.o bin/loggertest bin/notifytest notifytest.o bin/rawpxmltest rawpxmltest.o bin/pnd_run pnd_run.o pnd_info.o bin/pnd_info bin/pndevmapperd pndevmapperd.o bin/pndnotifyd pndnotifyd.o ${SOLIB} testdata/dotdesktop/*.desktop testdata/menu/*.desktop testdata/apps/*.pnd testdata/dotdesktop/*.png deployment/usr/lib/libpnd* deployment/usr/bin/pndnotifyd deployment/usr/bin/pnd_run deployment/usr/bin/pnd_info deployment/usr/pandora/scripts/* deployment/etc/sudoers deployment/etc/init.d/pndnotifyd bin/pndvalidator pndvalidator.o deployment/usr/bin/pndevmapperd testdata/menuicons/* evtest.o bin/evtest bin/mmenu bin/mmwrapper mmenu.o mmwrapper.o deployment/usr/bin/mmenu deployment/usr/bin/mmwrapper mmcache.o mmui.o mmcat.o mmconf.o freedsktop_cats.o freedesktop_cats.o
+ ${RM} -f ${ALLOBJ} ${XMLOBJ} ${LIB} ${SOLIB1} locatetest.o bin/locatetest conftest.o bin/conftest discotest.o evdevtest.o bin/evdevtest bin/discotest dbusnotifytest.o bin/dbusnotifytest loggertest.o bin/loggertest bin/notifytest notifytest.o bin/rawpxmltest rawpxmltest.o bin/pnd_run pnd_run.o pnd_info.o bin/pnd_info bin/pndevmapperd pndevmapperd.o bin/pndnotifyd pndnotifyd.o ${SOLIB} testdata/dotdesktop/*.desktop testdata/menu/*.desktop testdata/apps/*.pnd testdata/dotdesktop/*.png deployment/usr/lib/libpnd* deployment/usr/bin/pndnotifyd deployment/usr/bin/pnd_run deployment/usr/bin/pnd_info deployment/usr/pandora/scripts/* deployment/etc/sudoers deployment/etc/init.d/pndnotifyd bin/pndvalidator pndvalidator.o deployment/usr/bin/pndevmapperd testdata/menuicons/* evtest.o bin/evtest bin/mmenu bin/mmwrapper mmenu.o mmwrapper.o deployment/usr/bin/mmenu deployment/usr/bin/mmwrapper mmcache.o mmui.o mmcat.o mmconf.o freedsktop_cats.o freedesktop_cats.o mmcustom_cats.o
${RM} -rf deployment/media deployment/etc/pandora/mmenu
find . -name "*~*" -exec rm {} \; -print
pndevmapperd: pndevmapperd.o ${SOLIB1}
${CC} -lstdc++ -o bin/pndevmapperd pndevmapperd.o ${SOLIB1}
-mmenu: mmenu.o mmui.o mmcache.o mmcat.o mmconf.o freedesktop_cats.o ${SOLIB1}
- ${CC} -lstdc++ -o bin/mmenu mmenu.o mmui.o mmcache.o mmcat.o mmconf.o freedesktop_cats.o ${SOLIB1} -L${PNDSTUFF}/usr/lib -lSDL -lSDL_image -lSDL_ttf -lSDL_gfx
+mmenu: mmenu.o mmui.o mmcache.o mmcat.o mmconf.o freedesktop_cats.o mmcustom_cats.o ${SOLIB1}
+ ${CC} -lstdc++ -o bin/mmenu mmenu.o mmui.o mmcache.o mmcat.o mmconf.o freedesktop_cats.o mmcustom_cats.o ${SOLIB1} -L${PNDSTUFF}/usr/lib -lSDL -lSDL_image -lSDL_ttf -lSDL_gfx
mmwrapper: mmwrapper.o ${SOLIB1}
${CC} -lstdc++ -o bin/mmwrapper mmwrapper.o ${SOLIB1}
if ( ! fdcat ) {
// requested cat is bad, send it to Other
cat_is_clean = 0;
- printf ( "PXML Fail %s: Cat request %s (parent %s) -> bad cat\n", app -> title_en ? app -> title_en : "no name?", catname, parentcatname ? parentcatname : "n/a" );
+ pnd_log ( pndn_warning, "PXML Fail %s: Cat request %s (parent %s) -> bad cat\n", app -> title_en ? app -> title_en : "no name?", catname, parentcatname ? parentcatname : "n/a" );
// do the Other substitution right away, so remaining code has something to look at in fdcat
fdcat = freedesktop_category_query ( BADCATNAME, NULL );
if ( ! fdpcat ) {
// requested cat is bad, send it to Other
cat_is_clean = 0;
- printf ( "PXML Fail %s: Cat request %s (parent %s) -> parent bad cat\n", app -> title_en ? app -> title_en : "no name?", catname, parentcatname ? parentcatname : "n/a" );
+ pnd_log ( pndn_warning, "PXML Fail %s: Cat request %s (parent %s) -> parent bad cat\n", app -> title_en ? app -> title_en : "no name?", catname, parentcatname ? parentcatname : "n/a" );
// fix immediately so code doesn't explode
parentcatname = NULL;
} else {
if ( fdcat -> parent_cat == NULL ) {
// but wait, catname is actually a parent cat...
cat_is_clean = 0;
- printf ( "PXML Fail %s: Cat request %s (parent %s) -> cat wants to be child, but FD says its a parent\n", app -> title_en ? app -> title_en : "no name?", catname, parentcatname ? parentcatname : "n/a" );
+ pnd_log ( pndn_warning, "PXML Fail %s: Cat request %s (parent %s) -> cat wants to be child, but FD says its a parent\n", app -> title_en ? app -> title_en : "no name?", catname, parentcatname ? parentcatname : "n/a" );
}
if ( fdpcat -> parent_cat ) {
// but wait, parent cat is actually a subcat!
cat_is_clean = 0;
- printf ( "PXML Fail %s: Cat request %s (parent %s) -> parent cat, FD says its a child\n", app -> title_en ? app -> title_en : "no name?", catname, parentcatname ? parentcatname : "n/a" );
+ pnd_log ( pndn_warning, "PXML Fail %s: Cat request %s (parent %s) -> parent cat, FD says its a child\n", app -> title_en ? app -> title_en : "no name?", catname, parentcatname ? parentcatname : "n/a" );
}
} else {
if ( fdcat -> parent_cat ) {
// but wait, cat actually has a parent!
cat_is_clean = 0;
- printf ( "PXML Fail %s: Cat request %s (parent %s) -> cat wants to be parent, FD says its a child\n", app -> title_en ? app -> title_en : "no name?", catname, parentcatname ? parentcatname : "n/a" );
+ pnd_log ( pndn_warning, "PXML Fail %s: Cat request %s (parent %s) -> cat wants to be parent, FD says its a child\n", app -> title_en ? app -> title_en : "no name?", catname, parentcatname ? parentcatname : "n/a" );
}
}
{
// child cat points to a different parent than requested parent!
cat_is_clean = 0;
- printf ( "PXML Fail %s: Cat request %s (parent %s) -> cat wants to be child of a cat which FD says is the wrong parent (1)\n", app -> title_en ? app -> title_en : "no name?", catname, parentcatname ? parentcatname : "n/a" );
+ pnd_log ( pndn_warning, "PXML Fail %s: Cat request %s (parent %s) -> cat wants to be child of a cat which FD says is the wrong parent (1)\n", app -> title_en ? app -> title_en : "no name?", catname, parentcatname ? parentcatname : "n/a" );
} else if ( strcasecmp ( fdcat -> parent_cat, fdpcat -> cat ) != 0 ) {
// child cat points to a different parent than requested parent!
cat_is_clean = 0;
- printf ( "PXML Fail %s: Cat request %s (parent %s) -> cat wants to be child of a cat which FD says is the wrong parent (2)\n", app -> title_en ? app -> title_en : "no name?", catname, parentcatname ? parentcatname : "n/a" );
+ pnd_log ( pndn_warning, "PXML Fail %s: Cat request %s (parent %s) -> cat wants to be child of a cat which FD says is the wrong parent (2)\n", app -> title_en ? app -> title_en : "no name?", catname, parentcatname ? parentcatname : "n/a" );
}
}
// is app already in the target cat? (ie: its being pushed twice due to cat mapping or Other'ing or something..)
if ( app ) {
if ( category_contains_app ( catname, parentcatname, app -> unique_id ) ) {
- printf ( "App Fail: app (%s %s) is already in cat %s\n", app -> title_en ? app -> title_en : "no name?", app -> unique_id, catname );
+ pnd_log ( pndn_warning, "App Fail: app (%s %s) is already in cat %s\n", app -> title_en ? app -> title_en : "no name?", app -> unique_id, catname );
return ( 1 ); // success, already there!
}
}
--- /dev/null
+
+#include <stdio.h>
+#include <limits.h> /* for PATH_MAX */
+#define __USE_GNU /* for strndup */
+#include <string.h> /* for strdup */
+#include <stdlib.h> /* getenv */
+
+#include "pnd_container.h"
+#include "pnd_conf.h"
+#include "pnd_discovery.h"
+#include "pnd_notify.h"
+#include "pnd_dbusnotify.h"
+#include "pnd_logger.h"
+
+#include "mmenu.h"
+#include "mmcustom_cats.h"
+
+mmcustom_cat_t mmcustom_complete [ MMCUSTOM_CATS_MAX ];
+unsigned int mmcustom_count = 0;
+
+pnd_conf_handle g_custom_h = 0;
+
+char *mmcustom_determine_path ( void ) {
+ char *home = getenv ( "HOME" );
+ static char path [ PATH_MAX ];
+ bzero ( path, PATH_MAX );
+
+ snprintf ( path, PATH_MAX - 1, "%s/%s", home ? home : ".", MMCUSTOM_CATS_PREF_FILENAME );
+
+ return ( path );
+}
+
+static unsigned char loaded = 0;
+unsigned char mmcustom_setup ( void ) {
+
+ if ( ! loaded ) {
+ loaded = 1;
+
+ // inhale conf file
+ char *path = mmcustom_determine_path();
+
+ g_custom_h = pnd_conf_fetch_by_path ( path );
+
+ if ( ! g_custom_h ) {
+ pnd_log ( pndn_rem, "Custom category conf file %s not found; is okay.\n", path );
+ return ( 1 ); // file does not exist most likely
+ }
+
+ // find its head; if no head (empty file), bail
+ char *iter = pnd_box_get_head ( g_custom_h );
+
+ if ( ! iter ) {
+ pnd_log ( pndn_rem, "Custom category conf file %s is empty. Fine.\n", path );
+ return ( 1 );
+ }
+
+ // walk the conf, plucking out the values
+ while ( iter ) {
+ char *k = pnd_box_get_key ( iter );
+
+ // does this entry look like it is a custom category?
+ if ( strncmp ( k, MMCUSTOM_CATS_SECTION, strlen ( MMCUSTOM_CATS_SECTION ) ) == 0 ) {
+ // determine the actual category name part
+ k += ( strlen ( MMCUSTOM_CATS_SECTION ) + 1 );
+
+ mmcustom_complete [ mmcustom_count ].cat = strdup ( k );
+ if ( iter && strcmp ( iter, MMCUSTOM_CATS_NOCAT ) != 0 ) {
+ mmcustom_complete [ mmcustom_count ].parent_cat = strdup ( iter );
+ } else {
+ mmcustom_complete [ mmcustom_count ].parent_cat = NULL;
+ }
+
+ mmcustom_count += 1;
+
+ }
+
+ // next!
+ iter = pnd_box_get_next ( iter );
+
+ } // while
+
+ pnd_log ( pndn_rem, "Found %u custom categories.\n", mmcustom_count );
+
+ } // loaded already?
+
+ return ( 1 );
+}
+
+void mmcustom_shutdown ( void ) {
+
+ bzero ( mmcustom_complete, sizeof(mmcustom_cat_t) * MMCUSTOM_CATS_MAX );
+ mmcustom_count = 0;
+ loaded = 0;
+
+ return;
+}
+
+unsigned char mmcustom_write ( char *fullpath /* if NULL, uses canonical location */ ) {
+
+ if ( ! fullpath ) {
+ fullpath = mmcustom_determine_path();
+ }
+
+ FILE *f = fopen ( fullpath, "w" );
+
+ if ( ! f ) {
+ return ( 0 );
+ }
+
+ int i;
+ for ( i = 0; i < mmcustom_count; i++ ) {
+ if ( mmcustom_complete [ i ].cat ) {
+ fprintf ( f, "%s.%s\t%s\n", MMCUSTOM_CATS_SECTION, mmcustom_complete [ i ].cat, mmcustom_complete [ i ].parent_cat ? mmcustom_complete [ i ].parent_cat : MMCUSTOM_CATS_NOCAT );
+ }
+ }
+
+ fclose ( f );
+
+ return ( 1 );
+}
+
+mmcustom_cat_t *mmcustom_query ( char *name, char *parentcatname ) {
+ int i;
+
+ // search for the cat/parent combination
+ for ( i = 0; i < mmcustom_count; i++ ) {
+ mmcustom_cat_t *p = &(mmcustom_complete [ i ]);
+
+ if ( strcasecmp ( p -> cat, name ) == 0 ) {
+
+ if ( parentcatname == NULL && p -> parent_cat == NULL ) {
+ return ( p );
+ } else if ( parentcatname && p -> parent_cat && strcasecmp ( p -> parent_cat, parentcatname ) == 0 ) {
+ return ( p );
+ }
+
+ }
+
+ } // for
+
+ return ( NULL );
+}
+
+mmcustom_cat_t *mmcustom_register ( char *catname, char *parentcatname ) {
+ mmcustom_complete [ mmcustom_count ].cat = strdup ( catname );
+ if ( parentcatname ) {
+ mmcustom_complete [ mmcustom_count ].parent_cat = strdup ( parentcatname );
+ }
+ mmcustom_count += 1;
+ return ( &(mmcustom_complete [ mmcustom_count - 1 ]) );
+}
+
+unsigned int mmcustom_count_subcats ( char *catname ) {
+ int i;
+ unsigned int counter = 0;
+
+ for ( i = 0; i < mmcustom_count; i++ ) {
+
+ if ( mmcustom_complete [ i ].parent_cat && strcasecmp ( mmcustom_complete [ i ].parent_cat, catname ) == 0 ) {
+ counter++;
+ }
+
+ }
+
+ return ( counter );
+}
+
+void mmcustom_unregister ( char *catname, char *parentcatname ) {
+ int i;
+ int parent_index = -1;
+
+ if ( parentcatname ) {
+ pnd_log ( pndn_warning, "Goal: Remove subcat %s of %s\n", catname, parentcatname );
+ } else {
+ pnd_log ( pndn_warning, "Goal: Remove parent cat %s and descendants\n", catname );
+ }
+
+ for ( i = 0; i < mmcustom_count; i++ ) {
+
+ // killing a parent cat, or just a subcat?
+ if ( parentcatname ) {
+
+ // killing a subcat, so match cat+subcat to kill
+ if ( mmcustom_complete [ i ].cat && strcmp ( mmcustom_complete [ i ].cat, catname ) == 0 &&
+ mmcustom_complete [ i ].parent_cat && strcasecmp ( mmcustom_complete [ i ].parent_cat, parentcatname ) == 0 )
+ {
+ pnd_log ( pndn_warning, " Removing subcat: %s of %s\n", catname, parentcatname );
+ free ( mmcustom_complete [ i ].cat );
+ mmcustom_complete [ i ].cat = NULL;
+ break;
+ }
+
+ } else {
+
+ // killing a parent cat, so kill it, and any children of it
+ if ( mmcustom_complete [ i ].parent_cat == NULL &&
+ mmcustom_complete [ i ].cat &&
+ strcmp ( mmcustom_complete [ i ].cat, catname ) == 0 )
+ {
+ // flag the prent for future death (we need its name for now, since the caller is using it)
+ parent_index = i;
+ }
+ else if ( mmcustom_complete [ i ].cat &&
+ mmcustom_complete [ i ].parent_cat &&
+ strcmp ( mmcustom_complete [ i ].parent_cat, catname ) == 0 )
+ {
+ // kill children of it
+ pnd_log ( pndn_warning, " Removing cascading subcat: %s of %s\n", mmcustom_complete [ i ].cat, mmcustom_complete [ i ].parent_cat );
+ free ( mmcustom_complete [ i ].cat );
+ mmcustom_complete [ i ].cat = NULL;
+ }
+
+ }
+
+ } // for
+
+ // kill the actual cat itself
+ if ( i >= 0 ) {
+ pnd_log ( pndn_warning, " Removing cat: %s\n", catname );
+ free ( mmcustom_complete [ i ].cat );
+ mmcustom_complete [ i ].cat = NULL;
+ }
+
+ return;
+}
--- /dev/null
+
+#ifndef h_mmcustom_cats_h
+#define h_mmcustom_cats_h
+
+#define MMCUSTOM_CATS_MAX 255
+#define MMCUSTOM_CATS_PREF_FILENAME ".mmcats.conf"
+
+#define MMCUSTOM_CATS_SECTION "custom_categories"
+
+#define MMCUSTOM_CATS_NOCAT "*parent*"
+
+typedef struct {
+ char *cat;
+ char *parent_cat;
+} mmcustom_cat_t;
+
+extern mmcustom_cat_t mmcustom_complete[];
+extern unsigned int mmcustom_count;
+
+unsigned char mmcustom_setup ( void ); // load
+void mmcustom_shutdown ( void ); // unload
+unsigned char mmcustom_write ( char *fullpath /* if NULL, uses canonical location */ ); // save
+char *mmcustom_determine_path ( void );
+
+mmcustom_cat_t *mmcustom_query ( char *catname, char *parentcatname ); // parentcatname NULL for parents
+
+mmcustom_cat_t *mmcustom_register ( char *catname, char *parentcatname );
+void mmcustom_unregister ( char *catname, char *parentcatname );
+
+unsigned int mmcustom_count_subcats ( char *catname );
+
+#endif
#include "mmconf.h"
#include "mmui_context.h"
#include "freedesktop_cats.h"
+#include "mmcustom_cats.h"
#define CHANGED_NOTHING (0)
#define CHANGED_CATEGORY (1<<0) /* changed to different category */
"Reveal hidden category",
"Shutdown Pandora",
"Configure Minimenu",
+ "Manage custom app categories",
"Rescan for applications",
"Cache previews to SD now",
"Run a terminal/console",
"Select a Minimenu skin",
"About Minimenu"
};
- int sel = ui_modal_single_menu ( opts, 10, "Minimenu", "Enter to select; other to return." );
+ int sel = ui_modal_single_menu ( opts, 11, "Minimenu", "Enter to select; other to return." );
char buffer [ 100 ];
if ( sel == 0 ) {
emit_and_quit ( MM_RESTART );
}
} else if ( sel == 3 ) {
+ // manage custom categories
+ ui_manage_categories();
+ } else if ( sel == 4 ) {
// rescan apps
pnd_log ( pndn_debug, "Freeing up applications\n" );
applications_free();
pnd_log ( pndn_debug, "Rescanning applications\n" );
applications_scan();
- } else if ( sel == 4 ) {
+ } else if ( sel == 5 ) {
// cache preview to SD now
extern pnd_box_handle g_active_apps;
pnd_box_handle h = g_active_apps;
iter = pnd_box_get_next ( iter );
} // while
- } else if ( sel == 5 ) {
+ } else if ( sel == 6 ) {
// run terminal
char *argv[5];
argv [ 0 ] = pnd_conf_get_as_char ( g_conf, "utility.terminal" );
ui_forkexec ( argv );
}
- } else if ( sel == 6 ) {
+ } else if ( sel == 7 ) {
char buffer [ PATH_MAX ];
sprintf ( buffer, "%s %s\n", MM_RUN, "/usr/pandora/scripts/op_switchgui.sh" );
emit_and_quit ( buffer );
- } else if ( sel == 7 ) {
- emit_and_quit ( MM_QUIT );
} else if ( sel == 8 ) {
+ emit_and_quit ( MM_QUIT );
+ } else if ( sel == 9 ) {
// select skin
if ( ui_pick_skin() ) {
emit_and_quit ( MM_RESTART );
}
- } else if ( sel == 9 ) {
+ } else if ( sel == 10 ) {
// about
char buffer [ PATH_MAX ];
sprintf ( buffer, "%s/about.txt", g_skinpath );
return;
}
+unsigned char ui_menu_oneby ( char *title, char *footer, char *one ) {
+ char *opts [ 2 ];
+ opts [ 0 ] = one;
+ int sel = ui_modal_single_menu ( opts, 1, title, footer );
+ if ( sel < 0 ) {
+ return ( 0 );
+ }
+ return ( sel + 1 );
+}
+
unsigned char ui_menu_twoby ( char *title, char *footer, char *one, char *two ) {
char *opts [ 3 ];
opts [ 0 ] = one;
char *eol = strchr ( r_buffer, '\0' );
*( eol - 1 ) = '\0';
}
+
+ } else if ( event.key.keysym.sym == SDLK_UP ) {
+ r_buffer [ 0 ] = '\0'; // truncate!
+
} else if ( event.key.keysym.sym == SDLK_RETURN || event.key.keysym.sym == SDLK_END ) { // return, or "B"
return ( 1 );
return ( 1 );
}
+
+void ui_manage_categories ( void ) {
+ unsigned char require_app_scan = 0;
+
+ if ( ! mmcustom_setup() ) {
+ return; // error
+ }
+
+ char *opts [ 20 ] = {
+ "List custom categories",
+ "List custom subcategories",
+ "Register custom category",
+ "Register custom subcategory",
+ "Unregister custom category",
+ "Unregister custom subcategory",
+ "Done"
+ };
+
+ while ( 1 ) {
+
+ int sel = ui_modal_single_menu ( opts, 7, "Custom Categories", "B to select; other to cancel." );
+
+ switch ( sel ) {
+
+ case 0: // list custom
+ if ( mmcustom_count ) {
+ ui_pick_custom_category();
+ } else {
+ ui_menu_oneby ( "Warning", "B/Enter to accept", "There are none registered." );
+ }
+ break;
+
+ case 1: // list custom sub
+ if ( mmcustom_count ) {
+
+ int maincat = ui_pick_custom_category();
+
+ if ( maincat >= 0 ) {
+ unsigned int subcount = mmcustom_count_subcats ( mmcustom_complete [ maincat ].cat );
+ char titlebuf [ 201 ];
+
+ snprintf ( titlebuf, 200, "Category: %s", mmcustom_complete [ maincat ].cat );
+
+ if ( subcount == 0 ) {
+ ui_menu_oneby ( titlebuf, "B/Enter to accept", "Category has no subcategories." );
+ } else {
+
+ char **list = malloc ( subcount * sizeof(char*) );
+ int i;
+ unsigned int counter = 0;
+
+ for ( i = 0; i < mmcustom_count; i++ ) {
+ if ( mmcustom_complete [ i ].parent_cat && strcasecmp ( mmcustom_complete [ i ].parent_cat, mmcustom_complete [ maincat ].cat ) == 0 ) {
+ list [ counter++ ] = mmcustom_complete [ i ].cat;
+ }
+ }
+
+ ui_modal_single_menu ( list, counter, titlebuf, "Any button to exit." );
+
+ free ( list );
+
+ } // more than 0 subcats?
+
+ } // user picked a main cat?
+
+ } else {
+ ui_menu_oneby ( "Warning", "B/Enter to accept", "There are none registered." );
+ }
+ break;
+
+ case 2: // register custom
+ {
+ unsigned char changed;
+ char namebuf [ 101 ] = "";
+
+ changed = ui_menu_get_text_line ( "Enter unique category name", "Use keyboard; Enter when done.",
+ "Pandora", namebuf, 30, 0 /* alphanumeric */ );
+
+ // did the user enter something?
+ if ( changed ) {
+
+ // and if so, is it existant already or not?
+ if ( mmcustom_query ( namebuf, NULL ) ) {
+ ui_menu_oneby ( "Warning", "B/Enter to accept", "Already a registered category." );
+ } else if ( freedesktop_category_query ( namebuf, NULL ) ) {
+ ui_menu_oneby ( "Warning", "B/Enter to accept", "Already a Standard category." );
+ } else {
+
+ char confirm [ 1001 ];
+ snprintf ( confirm, 1000, "Confirm: %s", namebuf );
+
+ if ( ui_menu_twoby ( confirm, "B/enter; other to cancel", "Confirm new category", "Do not register" ) == 1 ) {
+ // register, save, recycle the current list
+ mmcustom_register ( namebuf, NULL );
+ mmcustom_write ( NULL );
+ mmcustom_shutdown();
+ mmcustom_setup();
+ }
+
+ } // dupe?
+
+ } // entered something?
+
+ }
+ break;
+
+ case 3: // register custom sub
+ if ( mmcustom_count ) {
+
+ int maincat = ui_pick_custom_category();
+
+ if ( maincat >= 0 ) {
+ char titlebuf [ 201 ];
+
+ snprintf ( titlebuf, 200, "Subcat of: %s", mmcustom_complete [ maincat ].cat );
+
+ unsigned char changed;
+ char namebuf [ 101 ] = "";
+
+ changed = ui_menu_get_text_line ( titlebuf, "Use keyboard; Enter when done.", "Submarine", namebuf, 30, 0 /* alphanumeric */ );
+
+ // did the user enter something?
+ if ( changed ) {
+
+ // and if so, is it existant already or not?
+ if ( mmcustom_query ( namebuf, mmcustom_complete [ maincat ].cat ) ) {
+ ui_menu_oneby ( "Warning", "B/Enter to accept", "Already a subcategory." );
+ } else if ( freedesktop_category_query ( namebuf, mmcustom_complete [ maincat ].cat ) ) {
+ ui_menu_oneby ( "Warning", "B/Enter to accept", "Already a Standard subcategory." );
+ } else {
+
+ char confirm [ 1001 ];
+ snprintf ( confirm, 1000, "Confirm: %s [%s]", namebuf, mmcustom_complete [ maincat ].cat );
+
+ if ( ui_menu_twoby ( confirm, "B/enter; other to cancel", "Confirm new category", "Do not register" ) == 1 ) {
+ // register, save, recycle the current list
+ mmcustom_register ( namebuf, mmcustom_complete [ maincat ].cat );
+ mmcustom_write ( NULL );
+ mmcustom_shutdown();
+ mmcustom_setup();
+ }
+
+ } // dupe?
+
+ } // entered something?
+
+ } // selected parent cat?
+
+ } else {
+ ui_menu_oneby ( "Warning", "B/Enter to accept", "No categories registered." );
+ }
+ break;
+
+ case 4: // unreg custom
+ if ( mmcustom_count ) {
+ int maincat = ui_pick_custom_category();
+
+ if ( maincat >= 0 ) {
+ char confirm [ 1001 ];
+ snprintf ( confirm, 1000, "Confirm remove: %s", mmcustom_complete [ maincat ].cat );
+
+ if ( ui_menu_twoby ( confirm, "B/enter; other to cancel", "Confirm unregister", "Do not unregister" ) == 1 ) {
+ // register, save, recycle the current list
+ mmcustom_unregister ( mmcustom_complete [ maincat ].cat, NULL );
+ mmcustom_write ( NULL );
+ mmcustom_shutdown();
+ mmcustom_setup();
+ }
+
+ } // picked?
+
+ } else {
+ ui_menu_oneby ( "Warning", "B/Enter to accept", "There are none registered." );
+ }
+ break;
+
+ case 5: // unreg custom sub
+ if ( mmcustom_count ) {
+ int maincat = ui_pick_custom_category();
+
+ if ( maincat >= 0 ) {
+ unsigned int subcount = mmcustom_count_subcats ( mmcustom_complete [ maincat ].cat );
+ char titlebuf [ 201 ];
+
+ snprintf ( titlebuf, 200, "Category: %s", mmcustom_complete [ maincat ].cat );
+
+ if ( subcount == 0 ) {
+ ui_menu_oneby ( titlebuf, "B/Enter to accept", "Category has no subcategories." );
+ } else {
+
+ char **list = malloc ( subcount * sizeof(char*) );
+ int i;
+ unsigned int counter = 0;
+
+ for ( i = 0; i < mmcustom_count; i++ ) {
+ if ( mmcustom_complete [ i ].parent_cat && strcasecmp ( mmcustom_complete [ i ].parent_cat, mmcustom_complete [ maincat ].cat ) == 0 ) {
+ list [ counter++ ] = mmcustom_complete [ i ].cat;
+ }
+ }
+
+ int sel = ui_modal_single_menu ( list, counter, titlebuf, "B to selct; other to exit." );
+
+ if ( sel >= 0 ) {
+ char confirm [ 1001 ];
+ snprintf ( confirm, 1000, "Confirm remove: %s", list [ sel ] );
+
+ if ( ui_menu_twoby ( confirm, "B/enter; other to cancel", "Confirm unregister", "Do not unregister" ) == 1 ) {
+ // register, save, recycle the current list
+ mmcustom_unregister ( list [ sel ], mmcustom_complete [ maincat ].cat );
+ mmcustom_write ( NULL );
+ mmcustom_shutdown();
+ mmcustom_setup();
+ }
+
+ } // confirm kill?
+
+ free ( list );
+
+ } // more than 0 subcats?
+
+ } // user picked a main cat?
+
+ } else {
+ ui_menu_oneby ( "Warning", "B/Enter to accept", "There are none registered." );
+ }
+ break;
+
+ } // switch
+
+ // exeunt
+ if ( sel < 0 || sel > 5 ) {
+ break;
+ }
+
+ } // while running the menu
+
+ // shut down custom cats
+ mmcustom_shutdown();
+
+ // reload apps?
+ if ( require_app_scan ) {
+ applications_free();
+ applications_scan();
+ }
+
+ // redraw
+ render_mask |= CHANGED_EVERYTHING;
+
+ return;
+}
+
+int ui_pick_custom_category ( void ) {
+ char **list = malloc ( mmcustom_count * sizeof(char*) );
+ int i;
+ unsigned int counter = 0;
+
+ for ( i = 0; i < mmcustom_count; i++ ) {
+ if ( mmcustom_complete [ i ].parent_cat == NULL ) {
+ list [ counter++ ] = mmcustom_complete [ i ].cat;
+ }
+ }
+
+ int sel = ui_modal_single_menu ( list, counter, "Custom Main Categories", "Any button to exit." );
+
+ counter = 0;
+ for ( i = 0; i < mmcustom_count; i++ ) {
+ if ( mmcustom_complete [ i ].parent_cat == NULL ) {
+ if ( counter == sel ) {
+ free ( list );
+ return ( i );
+ }
+ counter ++;
+ }
+ }
+
+ free ( list );
+
+ return ( -1 );
+}
unsigned char ui_show_info ( char *pndrun, pnd_disco_t *p );
void ui_aboutscreen ( char *textpath );
void ui_revealscreen ( void );
+void ui_manage_categories ( void );
+int ui_pick_custom_category ( void );
/* internal functions follow
*/
// 'popup' 'context' menu
void ui_menu_context ( mm_appref_t *a );
+unsigned char ui_menu_oneby ( char *title, char *footer, char *one ); // return 0 (nada) or 1 (one) for they actually picked it
unsigned char ui_menu_twoby ( char *title, char *footer, char *one, char *two ); // return 0 (nada), 1 (one), 2 (two)
unsigned char ui_menu_get_text_line ( char *title, char *footer, char *initialvalue,
char *r_buffer, unsigned char maxlen, unsigned char numbersonlyp ); // populates r_buffer