X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-libraries.git;a=blobdiff_plain;f=minimenu%2Fmmui.c;h=32b73ffffee67042839c5dfdfca602ef993a4548;hp=4b61f78f8c4952a0954fad410f9b01078b89e721;hb=d53e58a30480ca4e5eeec0eb28a72e7642df3dc3;hpb=89504728b8c1181f6f4481c80cb63b559db1932e diff --git a/minimenu/mmui.c b/minimenu/mmui.c index 4b61f78..32b73ff 100644 --- a/minimenu/mmui.c +++ b/minimenu/mmui.c @@ -45,6 +45,8 @@ #define CHANGED_EVERYTHING (1<<4) /* redraw it all! */ unsigned int render_mask = CHANGED_EVERYTHING; +#define MIMETYPE_EXE "/usr/bin/file" /* check for file type prior to invocation */ + /* SDL */ SDL_Surface *sdl_realscreen = NULL; @@ -79,11 +81,6 @@ ui_context_t ui_display_context; // display paramaters: see mmui_context. unsigned char ui_detail_hidden = 0; // if >0, detail panel is hidden // FUTURE: If multiple panels can be shown/hidden, convert ui_detail_hidden to a bitmask -extern mm_category_t *g_categories; -extern unsigned char g_categorycount; -extern mm_category_t _categories_invis [ MAX_CATS ]; -extern unsigned char _categories_inviscount; - static SDL_Surface *ui_scale_image ( SDL_Surface *s, unsigned int maxwidth, int maxheight ); // height -1 means ignore static int ui_selected_index ( void ); @@ -342,15 +339,19 @@ void ui_render ( void ) { ui_context_t *c = &ui_display_context; // for convenience and shorthand // how many total rows do we need? - icon_rows = g_categories [ ui_category ].refcount / c -> col_max; - if ( g_categories [ ui_category ].refcount % c -> col_max > 0 ) { - icon_rows++; + if ( g_categorycount ) { + icon_rows = g_categories [ ui_category ] -> refcount / c -> col_max; + if ( g_categories [ ui_category ] -> refcount % c -> col_max > 0 ) { + icon_rows++; + } + } else { + icon_rows = 0; } #if 1 // if no selected app yet, select the first one if ( ! ui_selected && pnd_conf_get_as_int_d ( g_conf, "minimenu.start_selected", 0 ) ) { - ui_selected = g_categories [ ui_category ].refs; + ui_selected = g_categories [ ui_category ] -> refs; } #endif @@ -516,7 +517,7 @@ void ui_render ( void ) { // draw text SDL_Surface *rtext; - rtext = TTF_RenderText_Blended ( g_tab_font, g_categories [ col ].catname, c -> fontcolor ); + rtext = TTF_RenderText_Blended ( g_tab_font, g_categories [ col ] -> catname, c -> fontcolor ); src.x = 0; src.y = 0; src.w = rtext -> w < text_width ? rtext -> w : text_width; @@ -625,7 +626,7 @@ void ui_render ( void ) { } // r_details // anything to render? - if ( render_jobs_b & R_GRID ) { + if ( render_jobs_b & R_GRID && g_categorycount ) { // if just rendering grid, and nothing else, better clear it first if ( ! ( render_jobs_b & R_BG ) ) { @@ -644,9 +645,9 @@ void ui_render ( void ) { } } - if ( g_categories [ ui_category ].refs ) { + if ( g_categories [ ui_category ] -> refs ) { - appiter = g_categories [ ui_category ].refs; + appiter = g_categories [ ui_category ] -> refs; row = 0; displayrow = 0; @@ -1048,6 +1049,10 @@ void ui_process_input ( unsigned char block_p ) { // timer went off, time to load something if ( pnd_conf_get_as_int_d ( g_conf, "minimenu.load_previews_later", 0 ) ) { + if ( ! ui_selected ) { + break; + } + // load the preview pics now! pnd_disco_t *iter = ui_selected -> ref; @@ -1224,10 +1229,10 @@ void ui_process_input ( unsigned char block_p ) { ui_detail_hidden = 0; } ui_event++; - } else if ( event.key.keysym.sym == SDLK_RSHIFT ) { // left trigger + } else if ( event.key.keysym.sym == SDLK_RSHIFT || event.key.keysym.sym == SDLK_COMMA ) { // left trigger or comma ui_push_ltrigger(); ui_event++; - } else if ( event.key.keysym.sym == SDLK_RCTRL ) { // right trigger + } else if ( event.key.keysym.sym == SDLK_RCTRL || event.key.keysym.sym == SDLK_PERIOD ) { // right trigger or period ui_push_rtrigger(); ui_event++; } else if ( event.key.keysym.sym == SDLK_PAGEUP ) { // Y @@ -1337,8 +1342,8 @@ void ui_process_input ( unsigned char block_p ) { // many SDLK_keycodes map to ASCII ("a" is ascii(a)), so try to jump to a filename of that name, in this category? // and if already there, try to jump to next, maybe? // future: look for sequence typing? ie: user types 'm' then 'a', look for 'ma*' instead of 'm' then 'a' matching - if ( isalpha ( event.key.keysym.sym ) && g_categories [ ui_category ].refcount > 0 ) { - mm_appref_t *app = g_categories [ ui_category ].refs; + if ( isalpha ( event.key.keysym.sym ) && g_categories [ ui_category ] -> refcount > 0 ) { + mm_appref_t *app = g_categories [ ui_category ] -> refs; //fprintf ( stderr, "sel %s next %s\n", ui_selected -> ref -> title_en, ui_selected -> next -> ref -> title_en ); @@ -1441,12 +1446,12 @@ void ui_push_left ( unsigned char forcecoil ) { i--; } - } else if ( g_categories [ ui_category ].refs == ui_selected ) { + } else if ( g_categories [ ui_category ] -> refs == ui_selected ) { // can't go any more left, we're at the head } else { // figure out the previous item; yay for singly linked list :/ - mm_appref_t *i = g_categories [ ui_category ].refs; + mm_appref_t *i = g_categories [ ui_category ] -> refs; while ( i ) { if ( i -> next == ui_selected ) { ui_selected = i; @@ -1493,7 +1498,7 @@ void ui_push_right ( unsigned char forcecoil ) { } } else { - ui_selected = g_categories [ ui_category ].refs; + ui_selected = g_categories [ ui_category ] -> refs; } ui_set_selected ( ui_selected ); @@ -1519,7 +1524,7 @@ void ui_push_up ( void ) { unsigned int col = ui_determine_screen_col ( ui_selected ); // go to end - ui_selected = g_categories [ ui_category ].refs; + ui_selected = g_categories [ ui_category ] -> refs; while ( ui_selected -> next ) { ui_selected = ui_selected -> next; } @@ -1562,8 +1567,8 @@ void ui_push_down ( void ) { unsigned int row = ui_determine_row ( ui_selected ); // max rows? - unsigned int icon_rows = g_categories [ ui_category ].refcount / col_max; - if ( g_categories [ ui_category ].refcount % col_max > 0 ) { + unsigned int icon_rows = g_categories [ ui_category ] -> refcount / col_max; + if ( g_categories [ ui_category ] -> refcount % col_max > 0 ) { icon_rows++; } @@ -1574,7 +1579,7 @@ void ui_push_down ( void ) { unsigned char col = ui_determine_screen_col ( ui_selected ); - ui_selected = g_categories [ ui_category ].refs; + ui_selected = g_categories [ ui_category ] -> refs; while ( col ) { ui_selected = ui_selected -> next; @@ -1622,7 +1627,7 @@ void ui_push_exec ( void ) { char *c; // lop off last word; if the thing ends with /, lop that one, then the next word. - while ( ( c = strrchr ( g_categories [ ui_category].fspath, '/' ) ) ) { + while ( ( c = strrchr ( g_categories [ ui_category] -> fspath, '/' ) ) ) { *c = '\0'; // lop off the last hunk if ( *(c+1) != '\0' ) { break; @@ -1630,23 +1635,26 @@ void ui_push_exec ( void ) { } // while // nothing left? - if ( g_categories [ ui_category].fspath [ 0 ] == '\0' ) { - strcpy ( g_categories [ ui_category].fspath, "/" ); + if ( g_categories [ ui_category] -> fspath [ 0 ] == '\0' ) { + free ( g_categories [ ui_category] -> fspath ); + g_categories [ ui_category] -> fspath = strdup ( "/" ); } } else { // go down - strcat ( g_categories [ ui_category].fspath, "/" ); - strcat ( g_categories [ ui_category].fspath, ui_selected -> ref -> title_en ); + char *temp = malloc ( strlen ( g_categories [ ui_category] -> fspath ) + strlen ( ui_selected -> ref -> title_en ) + 1 + 1 ); + sprintf ( temp, "%s/%s", g_categories [ ui_category] -> fspath, ui_selected -> ref -> title_en ); + free ( g_categories [ ui_category] -> fspath ); + g_categories [ ui_category] -> fspath = temp; } - pnd_log ( pndn_debug, "Cat %s is now in path %s\n", g_categories [ ui_category ].catname, g_categories [ ui_category ].fspath ); + pnd_log ( pndn_debug, "Cat %s is now in path %s\n", g_categories [ ui_category ] -> catname, g_categories [ ui_category ]-> fspath ); - // rescan the dir - category_fs_restock ( &(g_categories [ ui_category]) ); // forget the selection, nolonger applies ui_selected = NULL; ui_set_selected ( ui_selected ); + // rescan the dir + category_fs_restock ( g_categories [ ui_category ] ); // redraw the grid render_mask |= CHANGED_SELECTION; @@ -1672,16 +1680,73 @@ void ui_push_exec ( void ) { } else { // random bin file + + // is it even executable? if we don't have handlers for non-executables yet (Jan 2011 we don't), + // then don't even try to run things not-flagged as executable.. but wait most people are on + // FAT filesystems, what a drag, we can't tell at the fs level. + // ... but we can still invoke 'file' and grep out the good bits, at least. + // + // open a stream reading 'file /path/to/file' and check output for 'executable' + // -- not checking for "ARM" so it can pick up x86 (or whatever native) executables in build environment + unsigned char is_executable = 0; + + // popen test + { + char popenbuf [ FILENAME_MAX ]; + snprintf ( popenbuf, FILENAME_MAX, "%s %s/%s", MIMETYPE_EXE, g_categories [ ui_category ] -> fspath, ui_selected -> ref -> title_en ); + + FILE *marceau; + if ( ! ( marceau = popen ( popenbuf, "r" ) ) ) { + return; // error, we need some useful error handling and dialog boxes here + } + + if ( fgets ( popenbuf, FILENAME_MAX, marceau ) ) { + //printf ( "File test returns: %s\n", popenbuf ); + if ( strstr ( popenbuf, "executable" ) != NULL ) { + is_executable = 1; + } + } + + pclose ( marceau ); + + } // popen test + + if ( ! is_executable ) { + fprintf ( stderr, "ERROR: File to invoke is not executable, skipping. (%s)\n", ui_selected -> ref -> title_en ); + return; // need some error handling here + } + +#if 0 // eat up any pending SDL events and toss 'em? + { + SDL_PumpEvents(); + SDL_Event e; + while ( SDL_PeepEvents ( &e, 1, SDL_GETEVENT, SDL_ALLEVENTS ) > 0 ) { + // spin + } + } +#endif + #if 1 + // just exec it + // + + // get CWD so we can restore it on return char cwd [ PATH_MAX ]; getcwd ( cwd, PATH_MAX ); - chdir ( g_categories [ ui_category ].fspath ); - pnd_exec_no_wait_1 ( ui_selected -> ref -> title_en, NULL ); + // full path to executable so we don't rely on implicit "./" + char execbuf [ FILENAME_MAX ]; + snprintf ( execbuf, FILENAME_MAX, "%s/%s", g_categories [ ui_category ] -> fspath, ui_selected -> ref -> title_en ); + + // do it! + chdir ( g_categories [ ui_category ] -> fspath ); + exec_raw_binary ( execbuf /*ui_selected -> ref -> title_en*/ ); chdir ( cwd ); #else + // DEPRECATED / NOT TESTED + // get mmwrapper to run it char buffer [ PATH_MAX ]; - sprintf ( buffer, "%s %s/%s\n", MM_RUN, g_categories [ ui_category ].fspath, ui_selected -> ref -> title_en ); + sprintf ( buffer, "%s %s/%s\n", MM_RUN, g_categories [ ui_category ] -> fspath, ui_selected -> ref -> title_en ); if ( pnd_conf_get_as_int_d ( g_conf, "minimenu.live_on_run", 0 ) == 0 ) { emit_and_quit ( buffer ); } else { @@ -1730,7 +1795,7 @@ void ui_push_ltrigger ( void ) { if ( ui_category > 0 ) { ui_category--; - category_fs_restock ( &(g_categories [ ui_category ]) ); + category_fs_restock ( g_categories [ ui_category ] ); } else { if ( pnd_conf_get_as_int_d ( g_conf, "tabs.wraparound", 0 ) > 0 ) { ui_category = g_categorycount - 1; @@ -1738,7 +1803,7 @@ void ui_push_ltrigger ( void ) { if ( ui_category >= ( screen_width / tab_width ) ) { ui_catshift = ui_category - ( screen_width / tab_width ) + 1; } - category_fs_restock ( &(g_categories [ ui_category ]) ); + category_fs_restock ( g_categories [ ui_category ] ); } } @@ -1772,12 +1837,12 @@ void ui_push_rtrigger ( void ) { if ( ui_category < ( g_categorycount - 1 ) ) { ui_category++; - category_fs_restock ( &(g_categories [ ui_category ]) ); + category_fs_restock ( g_categories [ ui_category ] ); } else { if ( pnd_conf_get_as_int_d ( g_conf, "tabs.wraparound", 0 ) > 0 ) { ui_category = 0; ui_catshift = 0; - category_fs_restock ( &(g_categories [ ui_category ]) ); + category_fs_restock ( g_categories [ ui_category ] ); } } @@ -1983,7 +2048,7 @@ int ui_selected_index ( void ) { return ( -1 ); // no index } - mm_appref_t *r = g_categories [ ui_category ].refs; + mm_appref_t *r = g_categories [ ui_category ] -> refs; int counter = 0; while ( r ) { if ( r == ui_selected ) { @@ -2190,7 +2255,7 @@ int ui_modal_single_menu ( char *argv[], unsigned int argc, char *title, char *f unsigned char ui_determine_row ( mm_appref_t *a ) { unsigned int row = 0; - mm_appref_t *i = g_categories [ ui_category ].refs; + mm_appref_t *i = g_categories [ ui_category ] -> refs; while ( i != a ) { i = i -> next; row++; @@ -2207,7 +2272,7 @@ unsigned char ui_determine_screen_row ( mm_appref_t *a ) { unsigned char ui_determine_screen_col ( mm_appref_t *a ) { unsigned int col = 0; - mm_appref_t *i = g_categories [ ui_category ].refs; + mm_appref_t *i = g_categories [ ui_category ] -> refs; while ( i != a ) { i = i -> next; col++; @@ -2367,6 +2432,8 @@ void ui_touch_act ( unsigned int x, unsigned int y ) { } ui_category = t -> catnum; render_mask |= CHANGED_CATEGORY; + // rescan the dir + category_fs_restock ( g_categories [ ui_category ] ); } break; @@ -2446,7 +2513,7 @@ void ui_post_scan ( void ) { // default behaviour will pick first cat (ie: usually All) unsigned int i; for ( i = 0; i < g_categorycount; i++ ) { - if ( strcasecmp ( g_categories [ i ].catname, dc ) == 0 ) { + if ( strcasecmp ( g_categories [ i ] -> catname, dc ) == 0 ) { ui_category = i; // ensure visibility unsigned int screen_width = ui_display_context.screen_width; @@ -2464,6 +2531,12 @@ void ui_post_scan ( void ) { } // default cat + // if we're sent right to a dirbrowser tab, restock it now (normally we restock on entry) + if ( g_categories [ ui_category ] -> fspath ) { + printf ( "Restock on start: '%s'\n", g_categories [ ui_category ] -> fspath ); + category_fs_restock ( g_categories [ ui_category ] ); + } + // redraw all render_mask |= CHANGED_EVERYTHING; @@ -2825,40 +2898,43 @@ void ui_revealscreen ( void ) { unsigned int labelmax = 0; unsigned int i; - if ( ! _categories_inviscount ) { + if ( ! category_count ( CFHIDDEN ) ) { return; // nothing to do } - for ( i = 0; i < _categories_inviscount; i++ ) { - labels [ labelmax++ ] = _categories_invis [ i ].catname; + // switch to hidden categories + category_publish ( CFHIDDEN, NULL ); + + // build up labels to show in menu + for ( i = 0; i < g_categorycount; i++ ) { + labels [ labelmax++ ] = g_categories [ i ] -> catname; } + // show menu int sel = ui_modal_single_menu ( labels, labelmax, "Temporary Category Reveal", "Enter to select; other to return." ); + // if selected, try to set this guy to visible if ( sel >= 0 ) { - if ( category_query ( _categories_invis [ sel ].catname ) ) { - // already present - return; - } - // fix up category name, if its been hacked - if ( strchr ( _categories_invis [ sel ].catname, '.' ) ) { - char *t = _categories_invis [ sel ].catname; - _categories_invis [ sel ].catname = strdup ( strchr ( _categories_invis [ sel ].catname, '.' ) + 1 ); + 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 ); } - // copy invisi-cat into live-cat - memmove ( &(g_categories [ g_categorycount ]), &(_categories_invis [ sel ]), sizeof(mm_category_t) ); - g_categorycount++; - // move subsequent invisi-cats up, so the selected invisi-cat is nolonger existing in invisi-list at - // all (avoid double-free() later) - memmove ( &(_categories_invis [ sel ]), &(_categories_invis [ sel + 1 ]), sizeof(mm_category_t) * ( _categories_inviscount - sel - 1 ) ); - _categories_inviscount--; - - // switch to the new category - ui_category = g_categorycount - 1; + + // reflag this guy to be visible + g_categories [ sel ] -> catflags = CFNORMAL; + + // switch to the new category.. cache name. + char *switch_to_name = g_categories [ sel ] -> catname; + + // republish categories + category_publish ( CFNORMAL, NULL ); + + // switch to the new category.. with the cached name! + ui_category = category_index ( switch_to_name ); // ensure visibility unsigned int screen_width = ui_display_context.screen_width;