X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-libraries.git;a=blobdiff_plain;f=minimenu%2Fmmui.c;h=3a0c175ac271f742bb6d1031308d1dad0a458f9a;hp=3602711b76e1bd81065f180232024ef93955fbcc;hb=fe972a52b37c845ec79cfcd66116aacee4284a43;hpb=a9b6c61a8632c8f43947303bf0787598f50ee014 diff --git a/minimenu/mmui.c b/minimenu/mmui.c index 3602711..3a0c175 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 ); @@ -370,17 +371,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; @@ -1334,6 +1343,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 +1352,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 +1370,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 +1401,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 +1411,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 ); @@ -3108,11 +3121,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; @@ -3133,13 +3148,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; } @@ -3266,6 +3281,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 }; @@ -3279,7 +3297,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 ]; @@ -3295,13 +3316,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 @@ -3342,8 +3371,37 @@ 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 } @@ -3356,7 +3414,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 ) { @@ -3370,6 +3440,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" ); @@ -3382,10 +3453,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; @@ -3393,16 +3470,40 @@ void ui_menu_context ( mm_appref_t *a ) { { char *opts [ 250 ]; unsigned char optmax = 0; - unsigned char i; + unsigned char i = 0; - 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; + } + } + + } + + // 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; } @@ -3410,7 +3511,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." ); @@ -3425,6 +3527,10 @@ void ui_menu_context ( mm_appref_t *a ) { } + if ( mmcustom_is_ready() ) { + mmcustom_shutdown(); + } + } break; @@ -3478,6 +3584,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; @@ -3496,6 +3644,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; @@ -3521,7 +3679,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 ); } @@ -3608,8 +3770,14 @@ 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 ); @@ -3666,7 +3834,7 @@ unsigned char ui_menu_get_text_line ( char *title, char *footer, char *initialva } 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 ]; @@ -3675,7 +3843,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 ); } @@ -3715,3 +3883,301 @@ 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 + 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 ); +}