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_is_ready ( void ) {
+ return ( loaded );
+}
+
+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;
+}
#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 );
// write conf, so it will take next time
conf_write ( g_conf, conf_determine_location ( g_conf ) );
- // request rescan and wrap up
- rescan_apps++;
+ // can we just 'hide' this guy without reloading all apps? (this is for you, EvilDragon)
+ if ( 0 ) {
+ //
+ // DOESN'T WORK YET; other parts of app are still hanging onto some values and blow up
+ //
+ char *uid = strdup ( a -> ref -> unique_id );
+ unsigned int i;
+ for ( i = 0; i < g_categorycount; i++ ) {
+ mm_appref_t *p = g_categories [ i ] -> refs;
+ mm_appref_t *n;
+ while ( p ) {
+ n = p -> next;
+
+ if ( strcmp ( p -> ref -> unique_id, uid ) == 0 ) {
+ free ( p );
+ if ( g_categories [ i ] -> refcount ) {
+ g_categories [ i ] -> refcount--;
+ }
+ }
+
+ p = n;
+ } // while for each appref
+ } // for each cat/tab
+
+ free ( uid );
+
+ } else {
+ // request rescan and wrap up
+ rescan_apps++;
+ }
+
context_alive = 0; // nolonger visible, so lets just get out
}
unsigned char optmax = 0;
unsigned char i;
+ // show custom categories
+ if ( mmcustom_setup() ) {
+
+ for ( i = 0; i < mmcustom_count; i++ ) {
+ if ( mmcustom_complete [ i ].parent_cat == NULL ) {
+ opts [ optmax++ ] = mmcustom_complete [ i ].cat;
+ }
+ }
+
+ }
+
+ // show FD categories
i = 2; // skip first two - Other and NoParentCategory
while ( 1 ) {
i++;
} // while
+ // picker
char prompt [ 101 ];
snprintf ( prompt, 100, "Pick category [%s]", a -> ref -> main_category ? a -> ref -> main_category : "NoParentCategory" );
}
+ if ( mmcustom_is_ready() ) {
+ mmcustom_shutdown();
+ }
+
}
break;
{
char *opts [ 250 ];
unsigned char optmax = 0;
- unsigned char i;
+ unsigned char i = 0;
+
+ char *whichparentarewe;
+ if ( g_categories [ ui_category ] -> parent_catname ) {
+ whichparentarewe = g_categories [ ui_category ] -> parent_catname;
+ } else {
+ whichparentarewe = g_categories [ ui_category ] -> catname;
+ }
- i = 0;
+ // add NoSubcategory magic one
opts [ optmax++ ] = freedesktop_complete [ 2 ].cat;
+ // add custom categories
+ if ( mmcustom_setup() ) {
+
+ for ( i = 0; i < mmcustom_count; i++ ) {
+ if ( mmcustom_complete [ i ].parent_cat && strcmp ( mmcustom_complete [ i ].parent_cat, whichparentarewe ) == 0 ) {
+ opts [ optmax++ ] = mmcustom_complete [ i ].cat;
+ }
+ }
+
+ }
+
+ // add FD categories
while ( 1 ) {
if ( ! freedesktop_complete [ i ].cat ) {
break;
}
- char *whichparentarewe;
- if ( g_categories [ ui_category ] -> parent_catname ) {
- whichparentarewe = g_categories [ ui_category ] -> parent_catname;
- } else {
- whichparentarewe = g_categories [ ui_category ] -> catname;
- }
-
if ( ( freedesktop_complete [ i ].parent_cat ) &&
( strcasecmp ( freedesktop_complete [ i ].parent_cat, whichparentarewe ) == 0 )
)
} // while
char prompt [ 101 ];
- snprintf ( prompt, 100, "Pick subcategory [%s]", a -> ref -> main_category1 ? a -> ref -> main_category1 : "NoSubcategory" );
+ //snprintf ( prompt, 100, "Currently: %s", a -> ref -> main_category1 ? a -> ref -> main_category1 : "NoSubcategory" );
+ snprintf ( prompt, 100, "%s [%s]", a -> ref -> main_category1 ? a -> ref -> main_category1 : "NoSubcategory", whichparentarewe );
int sel = ui_modal_single_menu ( opts, optmax, prompt /*"Select subcategory"*/, "Enter to select; other to skip." );
}
+ if ( mmcustom_is_ready() ) {
+ mmcustom_shutdown();
+ }
+
}
break;
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 );
}
unsigned char ovr_replace_or_add ( mm_appref_t *a, char *keybase, char *newvalue ) {
- printf ( "setting %s:%u - '%s' to '%s' - %s/%s\n", a -> ref -> title_en, a -> ref -> subapp_number, keybase, newvalue, a -> ref -> object_path, a -> ref -> object_filename );
+ //printf ( "setting %s:%u - '%s' to '%s' - %s/%s\n", a -> ref -> title_en, a -> ref -> subapp_number, keybase, newvalue, a -> ref -> object_path, a -> ref -> object_filename );
char fullpath [ PATH_MAX ];
if ( dot ) {
sprintf ( dot, PXML_SAMEPATH_OVERRIDE_FILEEXT );
} else {
- fprintf ( stderr, "ERROR: Bad pnd-path in disco_t! %s\n", fullpath );
+ pnd_log ( pndn_error, "ERROR: Bad pnd-path in disco_t! %s\n", fullpath );
return ( 0 );
}
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 ( 0 );
+ } else {
+ ui_menu_oneby ( "Warning", "B/Enter to accept", "There are none registered." );
+ }
+ break;
+
+ case 1: // list custom sub
+ if ( mmcustom_count ) {
+
+ char *maincat = ui_pick_custom_category ( 0 );
+
+ if ( maincat ) {
+ unsigned int subcount = mmcustom_count_subcats ( maincat );
+ char titlebuf [ 201 ];
+
+ snprintf ( titlebuf, 200, "Category: %s", maincat );
+
+ 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, maincat ) == 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 ) {
+
+ char *maincat = ui_pick_custom_category ( 1 /* include FD */ );
+
+ if ( maincat ) {
+ char titlebuf [ 201 ];
+
+ snprintf ( titlebuf, 200, "Subcat of: %s", maincat );
+
+ 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, maincat ) ) {
+ ui_menu_oneby ( "Warning", "B/Enter to accept", "Already a subcategory." );
+ } else if ( freedesktop_category_query ( namebuf, maincat ) ) {
+ ui_menu_oneby ( "Warning", "B/Enter to accept", "Already a Standard subcategory." );
+ } else {
+
+ char confirm [ 1001 ];
+ snprintf ( confirm, 1000, "Confirm: %s [%s]", namebuf, maincat );
+
+ 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, maincat );
+ 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 ) {
+ char *maincat = ui_pick_custom_category ( 0 );
+
+ if ( maincat ) {
+ char confirm [ 1001 ];
+ snprintf ( confirm, 1000, "Confirm remove: %s", maincat );
+
+ if ( ui_menu_twoby ( confirm, "B/enter; other to cancel", "Confirm unregister", "Do not unregister" ) == 1 ) {
+ // register, save, recycle the current list
+ mmcustom_unregister ( maincat, 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 ) {
+ char *maincat = ui_pick_custom_category ( 0 );
+
+ if ( maincat ) {
+ unsigned int subcount = mmcustom_count_subcats ( maincat );
+ char titlebuf [ 201 ];
+
+ snprintf ( titlebuf, 200, "Category: %s", maincat );
+
+ 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, maincat ) == 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 ], maincat );
+ 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;
+}
+
+char *ui_pick_custom_category ( unsigned char include_fd ) {
+ char **list;
+ int i;
+ unsigned int counter = 0;
+
+ if ( include_fd ) {
+ list = malloc ( (mmcustom_count+freedesktop_count()) * sizeof(char*) );
+ } else {
+ list = malloc ( mmcustom_count * sizeof(char*) );
+ }
+
+ // add custom
+ for ( i = 0; i < mmcustom_count; i++ ) {
+ if ( mmcustom_complete [ i ].parent_cat == NULL ) {
+ list [ counter++ ] = mmcustom_complete [ i ].cat;
+ }
+ }
+
+ // add FD
+ if ( include_fd ) {
+ i = 3;
+ while ( 1 ) {
+
+ if ( ! freedesktop_complete [ i ].cat ) {
+ break;
+ }
+
+ if ( freedesktop_complete [ i ].parent_cat == NULL ) {
+ list [ counter++ ] = freedesktop_complete [ i ].cat;
+ }
+
+ i++;
+ } // while
+ } // if
+
+ int sel = ui_modal_single_menu ( list, counter, "Custom Main Categories", "Any button to exit." );
+
+ if ( sel < 0 ) {
+ free ( list );
+ return ( NULL );
+ }
+
+ char *foo = list [ sel ];
+ free ( list );
+
+ return ( foo );
+}