X-Git-Url: http://git.openpandora.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=minimenu%2Fmmui.c;h=25a9f3baf8a1d0a92f17d38f540e1f176b0d639a;hb=4b7531ad98d318b8071d595ce3e0d4113ee06f93;hp=94d2e9bc94cc917e763c54cf00642533b6b3e011;hpb=0864e067f728cc5a0c8cf894833b629175534123;p=pandora-libraries.git diff --git a/minimenu/mmui.c b/minimenu/mmui.c index 94d2e9b..25a9f3b 100644 --- a/minimenu/mmui.c +++ b/minimenu/mmui.c @@ -41,6 +41,7 @@ #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 */ @@ -153,7 +154,7 @@ unsigned char ui_setup ( void ) { #endif // key repeat - SDL_EnableKeyRepeat ( 500, 150 ); + SDL_EnableKeyRepeat ( 500, 125 /* 150 */ ); // images //IMG_Init ( IMG_INIT_JPG | IMG_INIT_PNG ); @@ -239,12 +240,15 @@ mm_imgcache_t g_imagecache [ IMG_TRUEMAX ] = { { IMG_HOURGLASS, "graphics.IMG_HOURGLASS", }, { IMG_FOLDER, "graphics.IMG_FOLDER", }, { IMG_EXECBIN, "graphics.IMG_EXECBIN", }, + { IMG_SUBCATFOLDER, "graphics.IMG_SUBCATFOLDER", "graphics.IMG_FOLDER", }, + { IMG_DOTDOTFOLDER, "graphics.IMG_DOTDOTFOLDER", "graphics.IMG_FOLDER", }, { IMG_MAX, NULL }, }; unsigned char ui_imagecache ( char *basepath ) { unsigned int i; char fullpath [ PATH_MAX ]; + unsigned char try; // loaded @@ -255,23 +259,39 @@ unsigned char ui_imagecache ( char *basepath ) { exit ( -1 ); } - char *filename = pnd_conf_get_as_char ( g_conf, g_imagecache [ i ].confname ); + for ( try = 0; try < 2; try++ ) { - if ( ! filename ) { - pnd_log ( pndn_error, "ERROR: Missing filename in conf for key: %s\n", g_imagecache [ i ].confname ); - return ( 0 ); - } + char *filename; - if ( filename [ 0 ] == '/' ) { - strncpy ( fullpath, filename, PATH_MAX ); - } else { - sprintf ( fullpath, "%s/%s", basepath, filename ); - } + if ( try == 0 ) { + filename = pnd_conf_get_as_char ( g_conf, g_imagecache [ i ].confname ); + } else { + if ( g_imagecache [ i ].alt_confname ) { + filename = pnd_conf_get_as_char ( g_conf, g_imagecache [ i ].alt_confname ); + } else { + return ( 0 ); + } + } - if ( ! ( g_imagecache [ i ].i = IMG_Load ( fullpath ) ) ) { - pnd_log ( pndn_error, "ERROR: Couldn't load static cache image: %s\n", fullpath ); - return ( 0 ); - } + if ( ! filename ) { + pnd_log ( pndn_error, "ERROR: (Try %u) Missing filename in conf for key: %s\n", try + 1, g_imagecache [ i ].confname ); + if ( try == 0 ) { continue; } else { return ( 0 ); } + } + + if ( filename [ 0 ] == '/' ) { + strncpy ( fullpath, filename, PATH_MAX ); + } else { + sprintf ( fullpath, "%s/%s", basepath, filename ); + } + + if ( ( g_imagecache [ i ].i = IMG_Load ( fullpath ) ) ) { + break; // no retry needed + } else { + pnd_log ( pndn_error, "ERROR: (Try %u) Couldn't load static cache image: %s\n", try + 1, fullpath ); + if ( try == 0 ) { continue; } else { return ( 0 ); } + } + + } // try twice } // for @@ -370,17 +390,25 @@ void ui_render ( void ) { // ensure selection is visible if ( ui_selected ) { - int index = ui_selected_index(); - int topleft = c -> col_max * ui_rows_scrolled_down; - int botright = ( c -> col_max * ( ui_rows_scrolled_down + c -> row_max ) - 1 ); + unsigned char autoscrolled = 1; + while ( autoscrolled ) { + autoscrolled = 0; + + int index = ui_selected_index(); + int topleft = c -> col_max * ui_rows_scrolled_down; + int botright = ( c -> col_max * ( ui_rows_scrolled_down + c -> row_max ) - 1 ); + + if ( index < topleft ) { + ui_rows_scrolled_down -= pnd_conf_get_as_int_d ( g_conf, "grid.scroll_increment", 1 ); + render_jobs_b |= R_ALL; + autoscrolled = 1; + } else if ( index > botright ) { + ui_rows_scrolled_down += pnd_conf_get_as_int_d ( g_conf, "grid.scroll_increment", 1 ); + render_jobs_b |= R_ALL; + autoscrolled = 1; + } - if ( index < topleft ) { - ui_rows_scrolled_down -= pnd_conf_get_as_int_d ( g_conf, "grid.scroll_increment", 1 ); - render_jobs_b |= R_ALL; - } else if ( index > botright ) { - ui_rows_scrolled_down += pnd_conf_get_as_int_d ( g_conf, "grid.scroll_increment", 1 ); - render_jobs_b |= R_ALL; - } + } // while autoscrolling if ( ui_rows_scrolled_down < 0 ) { ui_rows_scrolled_down = 0; @@ -695,7 +723,17 @@ void ui_render ( void ) { // filesystem (file or directory icon) if ( appiter -> ref -> object_flags & PND_DISCO_GENERATED ) { if ( appiter -> ref -> object_type == pnd_object_type_directory ) { - iconsurface = g_imagecache [ IMG_FOLDER ].i; + + // is this a subcat, a .., or a filesystem folder? + //iconsurface = g_imagecache [ IMG_FOLDER ].i; + if ( g_categories [ ui_category ] -> fspath ) { + iconsurface = g_imagecache [ IMG_FOLDER ].i; + } else if ( strcmp ( appiter -> ref -> title_en, ".." ) == 0 ) { + iconsurface = g_imagecache [ IMG_DOTDOTFOLDER ].i; + } else { + iconsurface = g_imagecache [ IMG_SUBCATFOLDER ].i; + } + } else { iconsurface = g_imagecache [ IMG_EXECBIN ].i; } @@ -1334,6 +1372,7 @@ void ui_process_input ( pnd_dbusnotify_handle dbh, pnd_notify_handle nh ) { "Reveal hidden category", "Shutdown Pandora", "Configure Minimenu", + "Manage custom app categories", "Rescan for applications", "Cache previews to SD now", "Run a terminal/console", @@ -1342,7 +1381,7 @@ void ui_process_input ( pnd_dbusnotify_handle dbh, pnd_notify_handle nh ) { "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 ) { @@ -1360,12 +1399,15 @@ void ui_process_input ( pnd_dbusnotify_handle dbh, pnd_notify_handle nh ) { 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; @@ -1388,7 +1430,7 @@ void ui_process_input ( pnd_dbusnotify_handle dbh, pnd_notify_handle nh ) { 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" ); @@ -1398,18 +1440,18 @@ void ui_process_input ( pnd_dbusnotify_handle dbh, pnd_notify_handle nh ) { 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 ); @@ -1431,7 +1473,7 @@ void ui_process_input ( pnd_dbusnotify_handle dbh, pnd_notify_handle nh ) { //fprintf ( stderr, "sel %s next %s\n", ui_selected -> ref -> title_en, ui_selected -> next -> ref -> title_en ); // are we already matching the same char? and next item is also same char? - if ( app && ui_selected && + if ( app && ui_selected && ui_selected -> next && ui_selected -> ref -> title_en && ui_selected -> next -> ref -> title_en && toupper ( ui_selected -> ref -> title_en [ 0 ] ) == toupper ( ui_selected -> next -> ref -> title_en [ 0 ] ) && toupper ( ui_selected -> ref -> title_en [ 0 ] ) == toupper ( event.key.keysym.sym ) @@ -1721,11 +1763,19 @@ void ui_push_backup ( void ) { // set to first cat! ui_category = 0; + // republish cats .. shoudl just be the one category_publish ( CFNORMAL, NULL ); if ( pcatname ) { ui_category = category_index ( pcatname ); + + // ensure tab visible? + unsigned int tab_width = pnd_conf_get_as_int ( g_conf, "tabs.tab_width" ); + if ( ui_category > ui_catshift + ( ui_display_context.screen_width / tab_width ) - 1 ) { + ui_catshift = ui_category - ( ui_display_context.screen_width / tab_width ) + 1; + } + } } // dir or subcat? @@ -1762,6 +1812,8 @@ void ui_push_exec ( void ) { // set to first cat! ui_category = 0; + ui_catshift = 0; + // republish cats .. shoudl just be the one category_publish ( CFBYNAME, ui_selected -> ref -> object_path ); @@ -3098,11 +3150,13 @@ void ui_revealscreen ( void ) { if ( sel >= 0 ) { // fix up category name, if its been hacked +#if 0 // prepending and .. wtf crap is this if ( strchr ( g_categories [ sel ] -> catname, '.' ) ) { char *t = g_categories [ sel ] -> catname; g_categories [ sel ] -> catname = strdup ( strchr ( g_categories [ sel ] -> catname, '.' ) + 1 ); free ( t ); } +#endif // reflag this guy to be visible g_categories [ sel ] -> catflags = CFNORMAL; @@ -3123,13 +3177,13 @@ void ui_revealscreen ( void ) { ui_catshift = ui_category - ( screen_width / tab_width ) + 1; } - // redraw tabs - render_mask |= CHANGED_CATEGORY; } - for ( i = 0; i < g_categorycount; i++ ) { - free ( labels [ i ] ); - } + // republish categories + category_publish ( CFNORMAL, NULL ); + + // redraw tabs + render_mask |= CHANGED_CATEGORY; return; } @@ -3256,6 +3310,9 @@ void ui_menu_context ( mm_appref_t *a ) { context_app_rename, context_app_cpuspeed, context_app_run, + context_app_notes1, + context_app_notes2, + context_app_notes3, context_menu_max }; @@ -3269,7 +3326,10 @@ void ui_menu_context ( mm_appref_t *a ) { "Recategorize subcategory", // recategorize "Change displayed title", // rename "Set CPU speed for launch", // cpuspeed - "Run application" // run + "Run application", // run + "Edit notes line 1", // notes1 + "Edit notes line 2", // notes2 + "Edit notes line 3", // notes3 }; unsigned short int menu [ context_menu_max ]; @@ -3285,13 +3345,21 @@ void ui_menu_context ( mm_appref_t *a ) { menu [ menumax ] = context_file_info; menustring [ menumax++ ] = verbiage [ context_file_info ]; menu [ menumax ] = context_file_delete; menustring [ menumax++ ] = verbiage [ context_file_delete ]; } else { + + if ( a -> ref -> object_type == pnd_object_type_directory ) { + return; // don't do anything if the guy is a subcat-as-folder + } + //menu [ menumax ] = context_app_info; menustring [ menumax++ ] = verbiage [ context_app_info ]; + menu [ menumax ] = context_app_run; menustring [ menumax++ ] = verbiage [ context_app_run ]; menu [ menumax ] = context_app_hide; menustring [ menumax++ ] = verbiage [ context_app_hide ]; menu [ menumax ] = context_app_recategorize; menustring [ menumax++ ] = verbiage [ context_app_recategorize ]; menu [ menumax ] = context_app_recategorize_sub; menustring [ menumax++ ] = verbiage [ context_app_recategorize_sub ]; menu [ menumax ] = context_app_rename; menustring [ menumax++ ] = verbiage [ context_app_rename ]; menu [ menumax ] = context_app_cpuspeed; menustring [ menumax++ ] = verbiage [ context_app_cpuspeed ]; - menu [ menumax ] = context_app_run; menustring [ menumax++ ] = verbiage [ context_app_run ]; + menu [ menumax ] = context_app_notes1; menustring [ menumax++ ] = verbiage [ context_app_notes1 ]; + menu [ menumax ] = context_app_notes2; menustring [ menumax++ ] = verbiage [ context_app_notes2 ]; + menu [ menumax ] = context_app_notes3; menustring [ menumax++ ] = verbiage [ context_app_notes3 ]; } // operate the menu @@ -3332,12 +3400,41 @@ void ui_menu_context ( mm_appref_t *a ) { // 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 } - + break; case context_app_recategorize: @@ -3346,7 +3443,19 @@ void ui_menu_context ( mm_appref_t *a ) { unsigned char optmax = 0; unsigned char i; - i = 0; + // 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 ) { if ( ! freedesktop_complete [ i ].cat ) { @@ -3360,6 +3469,7 @@ void ui_menu_context ( mm_appref_t *a ) { i++; } // while + // picker char prompt [ 101 ]; snprintf ( prompt, 100, "Pick category [%s]", a -> ref -> main_category ? a -> ref -> main_category : "NoParentCategory" ); @@ -3372,10 +3482,16 @@ void ui_menu_context ( mm_appref_t *a ) { if ( ui_menu_twoby ( confirm, "B/enter; other to cancel", "Confirm categorization", "Do not set category" ) == 1 ) { ovr_replace_or_add ( a, "maincategory", opts [ sel ] ); rescan_apps++; + // when changing main cat, reset subcat, otherwise you go from Game/Emu to Network/Emu and get sent to Other right away + ovr_replace_or_add ( a, "maincategorysub1", freedesktop_complete [ 2 ].cat ); } } + if ( mmcustom_is_ready() ) { + mmcustom_shutdown(); + } + } break; @@ -3383,16 +3499,40 @@ void ui_menu_context ( mm_appref_t *a ) { { 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; + } + + // 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; + } + } + + } - i = 0; + // add FD categories while ( 1 ) { if ( ! freedesktop_complete [ i ].cat ) { break; } - if ( freedesktop_complete [ i ].parent_cat ) { + if ( ( freedesktop_complete [ i ].parent_cat ) && + ( strcasecmp ( freedesktop_complete [ i ].parent_cat, whichparentarewe ) == 0 ) + ) + { opts [ optmax++ ] = freedesktop_complete [ i ].cat; } @@ -3400,7 +3540,8 @@ void ui_menu_context ( mm_appref_t *a ) { } // 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." ); @@ -3415,6 +3556,10 @@ void ui_menu_context ( mm_appref_t *a ) { } + if ( mmcustom_is_ready() ) { + mmcustom_shutdown(); + } + } break; @@ -3468,6 +3613,48 @@ void ui_menu_context ( mm_appref_t *a ) { ui_push_exec(); break; + case context_app_notes1: + case context_app_notes2: + case context_app_notes3: + { + char namebuf [ 101 ] = ""; + + char key [ 501 ]; + unsigned char notenum; + + // which note line? + if ( menu [ sel ] == context_app_notes1 ) { + notenum = 1; + } else if ( menu [ sel ] == context_app_notes2 ) { + notenum = 2; + } else if ( menu [ sel ] == context_app_notes3 ) { + notenum = 3; + } + + // figure out key for looking up existing, and for storing replacement + snprintf ( key, 500, "Application-%u.note-%u", a -> ref -> subapp_number, notenum ); + + // do we have existing value? + if ( a -> ovrh ) { + char *existing = pnd_conf_get_as_char ( a -> ovrh, key ); + if ( existing ) { + strncpy ( namebuf, existing, 100 ); + } + } + + unsigned char changed; + + changed = ui_menu_get_text_line ( "Enter replacement note", "Use keyboard; Enter when done.", + namebuf, namebuf, 30, 0 /* not-numeric-forced */ ); + + if ( changed ) { + ovr_replace_or_add ( a, strchr ( key, '.' ) + 1, namebuf ); + rescan_apps++; + } + + } + break; + default: return; @@ -3486,6 +3673,16 @@ void ui_menu_context ( mm_appref_t *a ) { 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; @@ -3511,7 +3708,11 @@ unsigned char ui_menu_get_text_line ( char *title, char *footer, char *initialva bzero ( rects, sizeof(SDL_Rect) * 40 ); if ( initialvalue ) { - strncpy ( r_buffer, initialvalue, maxlen ); + if ( initialvalue == r_buffer ) { + // already good to go + } else { + strncpy ( r_buffer, initialvalue, maxlen ); + } } else { bzero ( r_buffer, maxlen ); } @@ -3598,10 +3799,20 @@ unsigned char ui_menu_get_text_line ( char *title, char *footer, char *initialva case SDL_KEYDOWN: if ( event.key.keysym.sym == SDLK_LEFT || event.key.keysym.sym == SDLK_BACKSPACE ) { - char *eol = strchr ( r_buffer, '\0' ); - *( eol - 1 ) = '\0'; + if ( strlen ( r_buffer ) > 0 ) { + 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 ); + // on Enter/Return or B, if the buffer has 1 or more chars, we return it as valid.. otherwise, invalid. + if ( strlen ( r_buffer ) > 0 ) { + return ( 1 ); + } + return ( 0 ); } else if ( event.key.keysym.sym == SDLK_LSHIFT || event.key.keysym.sym == SDLK_RSHIFT ) { shifted = 1; @@ -3651,12 +3862,12 @@ unsigned char ui_menu_get_text_line ( char *title, char *footer, char *initialva } // while waiting for input } // while - + return ( 0 ); } 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 ]; @@ -3665,7 +3876,7 @@ unsigned char ovr_replace_or_add ( mm_appref_t *a, char *keybase, char *newvalue 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 ); } @@ -3705,3 +3916,317 @@ unsigned char ovr_replace_or_add ( mm_appref_t *a, char *keybase, char *newvalue 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 + ui_pick_custom_category ( 0 ); + break; + + case 1: // list custom sub + if ( mmcustom_count ) { + + char *maincat = ui_pick_custom_category ( 2 ); + + 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 ( 1 /*mmcustom_count -- we allow FD cats now, so this isn't applicable error */ ) { + + 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 ( 2 ); + + 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; +} + +// mode 0 == custom main only; 1 == custom main + FD main; 2 == custom main + FD mains-with-custom-subs +char *ui_pick_custom_category ( unsigned char mode ) { + char **list; + int i; + unsigned int counter = 0; + + // alloc space for list, depending on scope + if ( mode > 0 ) { + list = malloc ( (mmcustom_count+freedesktop_count()) * sizeof(char*) ); + } else { + list = malloc ( mmcustom_count * sizeof(char*) ); + } + + // add custom mains + for ( i = 0; i < mmcustom_count; i++ ) { + if ( mmcustom_complete [ i ].parent_cat == NULL ) { + list [ counter++ ] = mmcustom_complete [ i ].cat; + } + } + + // add FD if needed + if ( mode > 0 ) { + i = 3; + + while ( 1 ) { + + if ( ! freedesktop_complete [ i ].cat ) { + break; + } + + // if FD main cat + if ( freedesktop_complete [ i ].parent_cat == NULL ) { + + // mode 1 == include them all + // mode 2 == include them if they have a custom subcat + if ( ( mode == 1 ) || + ( mmcustom_subcount ( freedesktop_complete [ i ].cat ) ) ) + { + list [ counter++ ] = freedesktop_complete [ i ].cat; + } + + } // if parent cat + + i++; + } // while + + } // if + + // we actually showing anything? + if ( ! counter ) { + ui_menu_oneby ( "Warning", "B/Enter to accept", "There are none registered." ); + return ( NULL ); + } + + // do it + int sel = ui_modal_single_menu ( list, counter, "Custom Categories", "Any button to exit." ); + + if ( sel < 0 ) { + free ( list ); + return ( NULL ); + } + + char *foo = list [ sel ]; + free ( list ); + + return ( foo ); +}