X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=menu.c;h=6c6392afc6e34a7ac66c0fa79e323dd4b1289f56;hb=de24250ab5038797e8f5ff8754d34a3219943134;hp=b40a5dfba1ba3850207e11f6e4d97d69160228e5;hpb=9fec8a91c9b19856ac0b51de53b847b38ed8dc61;p=libpicofe.git diff --git a/menu.c b/menu.c index b40a5df..6c6392a 100644 --- a/menu.c +++ b/menu.c @@ -24,15 +24,28 @@ #include "plat.h" #include "posix.h" +#if defined(__GNUC__) && __GNUC__ >= 7 +#pragma GCC diagnostic ignored "-Wformat-truncation" +#endif + static char static_buff[64]; static int menu_error_time = 0; char menu_error_msg[64] = { 0, }; +// g_menuscreen is the current output buffer the menu is rendered to. void *g_menuscreen_ptr; -void *g_menubg_src_ptr; +// g_menubg is the menu background and has the same w/h as g_menuscreen, but +// pp=w. It is filled on menu entry from file or from g_menubg_src if available. void *g_menubg_ptr; +// g_menubg_src points to a buffer containing a bg image. This is usually either +// the emulator screen buffer or the host frame buffer. +void *g_menubg_src_ptr; int g_menuscreen_w; int g_menuscreen_h; +int g_menuscreen_pp; +int g_menubg_src_w; +int g_menubg_src_h; +int g_menubg_src_pp; int g_autostateld_opt; @@ -53,11 +66,17 @@ static int g_menu_filter_off; static int g_border_style; static int border_left, border_right, border_top, border_bottom; +void menuscreen_memset_lines(unsigned short *dst, int c, int l) +{ + for (; l > 0; l--, dst += g_menuscreen_pp) + memset(dst, c, g_menuscreen_w * 2); +} + // draws text to current bbp16 screen static void text_out16_(int x, int y, const char *text, int color) { int i, lh, tr, tg, tb, len; - unsigned short *dest = (unsigned short *)g_menuscreen_ptr + x + y * g_menuscreen_w; + unsigned short *dest = (unsigned short *)g_menuscreen_ptr + x + y * g_menuscreen_pp; tr = (color & 0xf800) >> 8; tg = (color & 0x07e0) >> 3; tb = (color & 0x001f) << 3; @@ -86,7 +105,7 @@ static void text_out16_(int x, int y, const char *text, int color) unsigned short *dst = dest; int u, l; - for (l = 0; l < lh; l++, dst += g_menuscreen_w - me_mfont_w) + for (l = 0; l < lh; l++, dst += g_menuscreen_pp - me_mfont_w) { for (u = me_mfont_w / 2; u > 0; u--, src++) { @@ -159,7 +178,7 @@ static void smalltext_out16_(int x, int y, const char *texto, int color) break; src = fontdata6x8[c]; - dst = (unsigned short *)g_menuscreen_ptr + x + y * g_menuscreen_w; + dst = (unsigned short *)g_menuscreen_ptr + x + y * g_menuscreen_pp; while (h--) { @@ -174,7 +193,7 @@ static void smalltext_out16_(int x, int y, const char *texto, int color) dst += multiplier; } - dst += g_menuscreen_w - me_sfont_w; + dst += g_menuscreen_pp - me_sfont_w; } src++; } @@ -207,13 +226,13 @@ static void menu_draw_selection(int x, int y, int w) if (menu_sel_color < 0) return; // no selection hilight if (y > 0) y--; - dest = (unsigned short *)g_menuscreen_ptr + x + y * g_menuscreen_w + me_mfont_w * 2 - 2; + dest = (unsigned short *)g_menuscreen_ptr + x + y * g_menuscreen_pp + me_mfont_w * 2 - 2; for (h = me_mfont_h + 1; h > 0; h--) { dst = dest; for (i = w - (me_mfont_w * 2 - 2); i > 0; i--) *dst++ = menu_sel_color; - dest += g_menuscreen_w; + dest += g_menuscreen_pp; } } @@ -257,14 +276,14 @@ void menu_init_base(void) for (l = 0; l < 8; l++) { unsigned char fd8x8 = fontdata8x8[c*8+l]; - if (fd8x8&0x80) *fd = 0xf0; - if (fd8x8&0x40) *fd |= 0x0f; fd++; - if (fd8x8&0x20) *fd = 0xf0; - if (fd8x8&0x10) *fd |= 0x0f; fd++; - if (fd8x8&0x08) *fd = 0xf0; - if (fd8x8&0x04) *fd |= 0x0f; fd++; - if (fd8x8&0x02) *fd = 0xf0; - if (fd8x8&0x01) *fd |= 0x0f; fd++; + if (fd8x8&0x80) { *fd = 0xf0; } + if (fd8x8&0x40) { *fd |= 0x0f; }; fd++; + if (fd8x8&0x20) { *fd = 0xf0; } + if (fd8x8&0x10) { *fd |= 0x0f; }; fd++; + if (fd8x8&0x08) { *fd = 0xf0; } + if (fd8x8&0x04) { *fd |= 0x0f; }; fd++; + if (fd8x8&0x02) { *fd = 0xf0; } + if (fd8x8&0x01) { *fd |= 0x0f; }; fd++; } fd += 8*2/2; // 2 empty lines } @@ -381,10 +400,10 @@ static void menu_darken_text_bg(void) ymax = g_menuscreen_h - 1; for (x = xmin; x <= xmax; x++) - screen[y * g_menuscreen_w + x] = 0xa514; + screen[y * g_menuscreen_pp + x] = 0xa514; for (y++; y < ymax; y++) { - ls = y * g_menuscreen_w; + ls = y * g_menuscreen_pp; screen[ls + xmin] = 0xffff; for (x = xmin + 1; x < xmax; x++) { @@ -394,7 +413,7 @@ static void menu_darken_text_bg(void) } screen[ls + xmax] = 0xffff; } - ls = y * g_menuscreen_w; + ls = y * g_menuscreen_pp; for (x = xmin; x <= xmax; x++) screen[ls + x] = 0xffff; } @@ -411,6 +430,8 @@ static void menu_reset_borders(void) static void menu_draw_begin(int need_bg, int no_borders) { + int y; + plat_video_menu_begin(); menu_reset_borders(); @@ -418,12 +439,14 @@ static void menu_draw_begin(int need_bg, int no_borders) if (need_bg) { if (g_border_style && no_borders) { - menu_darken_bg(g_menuscreen_ptr, g_menubg_ptr, - g_menuscreen_w * g_menuscreen_h, 1); + for (y = 0; y < g_menuscreen_h; y++) + menu_darken_bg((short *)g_menuscreen_ptr + g_menuscreen_pp * y, + (short *)g_menubg_ptr + g_menuscreen_w * y, g_menuscreen_w, 1); } else { - memcpy(g_menuscreen_ptr, g_menubg_ptr, - g_menuscreen_w * g_menuscreen_h * 2); + for (y = 0; y < g_menuscreen_h; y++) + memcpy((short *)g_menuscreen_ptr + g_menuscreen_pp * y, + (short *)g_menubg_ptr + g_menuscreen_w * y, g_menuscreen_w * 2); } } } @@ -471,24 +494,12 @@ static int me_count(const menu_entry *ent) static unsigned int me_read_onoff(const menu_entry *ent) { - // guess var size based on mask to avoid reading too much - if (ent->mask & 0xffff0000) - return *(unsigned int *)ent->var & ent->mask; - else if (ent->mask & 0xff00) - return *(unsigned short *)ent->var & ent->mask; - else - return *(unsigned char *)ent->var & ent->mask; + return *(unsigned int *)ent->var & ent->mask; } static void me_toggle_onoff(menu_entry *ent) { - // guess var size based on mask to avoid reading too much - if (ent->mask & 0xffff0000) - *(unsigned int *)ent->var ^= ent->mask; - else if (ent->mask & 0xff00) - *(unsigned short *)ent->var ^= ent->mask; - else - *(unsigned char *)ent->var ^= ent->mask; + *(unsigned int *)ent->var ^= ent->mask; } static void me_draw(const menu_entry *entries, int sel, void (*draw_more)(void)) @@ -619,10 +630,10 @@ static void me_draw(const menu_entry *entries, int sel, void (*draw_more)(void)) offs = x + col2_offs; len = strlen(names[i]); if (len > 10) - offs += (10 - len - 2) * me_mfont_w; + offs += (10 - len) * me_mfont_w; if (offs < leftname_end) offs = leftname_end; - if (i == *(unsigned char *)ent->var) { + if (i == *(int *)ent->var) { text_out16(offs, y, "%s", names[i]); break; } @@ -687,11 +698,11 @@ static int me_process(menu_entry *entry, int is_next, int is_lr) names = (const char **)entry->data; for (c = 0; names[c] != NULL; c++) ; - *(signed char *)entry->var += is_next ? 1 : -1; - if (*(signed char *)entry->var < 0) - *(signed char *)entry->var = 0; - if (*(signed char *)entry->var >= c) - *(signed char *)entry->var = c - 1; + *(int *)entry->var += is_next ? 1 : -1; + if (*(int *)entry->var < 0) + *(int *)entry->var = 0; + if (*(int *)entry->var >= c) + *(int *)entry->var = c - 1; return 1; default: return 0; @@ -864,15 +875,14 @@ static void draw_dirlist(char *curdir, struct dirent **namelist, max_cnt = g_menuscreen_h / me_sfont_h; start = max_cnt / 2 - sel; - n--; // exclude current dir (".") menu_draw_begin(1, 1); // if (!rom_loaded) // menu_darken_bg(gp2x_screen, 320*240, 0); - darken_ptr = (short *)g_menuscreen_ptr + g_menuscreen_w * max_cnt/2 * me_sfont_h; - menu_darken_bg(darken_ptr, darken_ptr, g_menuscreen_w * me_sfont_h * 8 / 10, 0); + darken_ptr = (short *)g_menuscreen_ptr + g_menuscreen_pp * max_cnt/2 * me_sfont_h; + menu_darken_bg(darken_ptr, darken_ptr, g_menuscreen_pp * me_sfont_h * 8 / 10, 0); x = 5 + me_mfont_w + 1; if (start - 2 >= 0) @@ -881,21 +891,21 @@ static void draw_dirlist(char *curdir, struct dirent **namelist, pos = start + i; if (pos < 0) continue; if (pos >= max_cnt) break; - if (namelist[i+1]->d_type == DT_DIR) { + if (namelist[i]->d_type == DT_DIR) { smalltext_out16(x, pos * me_sfont_h, "/", 0xfff6); - smalltext_out16(x + me_sfont_w, pos * me_sfont_h, namelist[i+1]->d_name, 0xfff6); + smalltext_out16(x + me_sfont_w, pos * me_sfont_h, namelist[i]->d_name, 0xfff6); } else { - unsigned short color = fname2color(namelist[i+1]->d_name); - smalltext_out16(x, pos * me_sfont_h, namelist[i+1]->d_name, color); + unsigned short color = fname2color(namelist[i]->d_name); + smalltext_out16(x, pos * me_sfont_h, namelist[i]->d_name, color); } } smalltext_out16(5, max_cnt/2 * me_sfont_h, ">", 0xffff); if (show_help) { darken_ptr = (short *)g_menuscreen_ptr - + g_menuscreen_w * (g_menuscreen_h - me_sfont_h * 5 / 2); + + g_menuscreen_pp * (g_menuscreen_h - me_sfont_h * 5 / 2); menu_darken_bg(darken_ptr, darken_ptr, - g_menuscreen_w * (me_sfont_h * 5 / 2), 1); + g_menuscreen_pp * (me_sfont_h * 5 / 2), 1); snprintf(buff, sizeof(buff), "%s - select, %s - back", in_get_key_name(-1, -PBTN_MOK), in_get_key_name(-1, -PBTN_MBACK)); @@ -919,10 +929,15 @@ static int scandir_cmp(const void *p1, const void *p2) { const struct dirent **d1 = (const struct dirent **)p1; const struct dirent **d2 = (const struct dirent **)p2; + const char *p; + if ((p = (*d1)->d_name)[0] == '.' && p[1] == '.' && p[2] == 0) + return -1; // ".." first + if ((p = (*d2)->d_name)[0] == '.' && p[1] == '.' && p[2] == 0) + return 1; if ((*d1)->d_type == (*d2)->d_type) return alphasort(d1, d2); if ((*d1)->d_type == DT_DIR) - return -1; // put before + return -1; // directories before files/links if ((*d2)->d_type == DT_DIR) return 1; @@ -937,12 +952,13 @@ static int scandir_filter(const struct dirent *ent) const char *ext; int i; - if (ent == NULL || ent->d_name == NULL) + if (ent == NULL) return 0; switch (ent->d_type) { case DT_DIR: - return 1; + // leave out useless reference to current directory + return strcmp(ent->d_name, ".") != 0; case DT_LNK: case DT_UNKNOWN: // could be a dir, deal with it later.. @@ -991,7 +1007,6 @@ static const char *menu_loop_romsel(char *curr_path, int len, int n = 0, inp = 0, sel = 0, show_help = 0; char *curr_path_restore = NULL; const char *ret = NULL; - int changed; char cinp; int r, i; @@ -1025,13 +1040,10 @@ rescan: n = scandir(curr_path, &namelist, filter, (void *)scandir_cmp); if (n < 0) { - char *t; lprintf("menu_loop_romsel failed, dir: %s\n", curr_path); - // try root - t = getcwd(curr_path, len); - if (t == NULL) - plat_get_root_dir(curr_path, len); + // try data root + plat_get_data_dir(curr_path, len); n = scandir(curr_path, &namelist, filter, (void *)scandir_cmp); if (n < 0) { // oops, we failed @@ -1041,43 +1053,40 @@ rescan: } // try to resolve DT_UNKNOWN and symlinks - changed = 0; for (i = 0; i < n; i++) { struct stat st; + char *slash; if (namelist[i]->d_type == DT_REG || namelist[i]->d_type == DT_DIR) continue; + r = strlen(curr_path); + slash = (r && curr_path[r-1] == '/') ? "" : "/"; snprintf(rom_fname_reload, sizeof(rom_fname_reload), - "%s/%s", curr_path, namelist[i]->d_name); + "%s%s%s", curr_path, slash, namelist[i]->d_name); r = stat(rom_fname_reload, &st); if (r == 0) { - if (S_ISREG(st.st_mode)) { + if (S_ISREG(st.st_mode)) namelist[i]->d_type = DT_REG; - changed = 1; - } - else if (S_ISDIR(st.st_mode)) { + else if (S_ISDIR(st.st_mode)) namelist[i]->d_type = DT_DIR; - changed = 1; - } } } if (!g_menu_filter_off && extra_filter != NULL) n = extra_filter(namelist, n, curr_path); - if (n > 1 && changed) + if (n > 1) qsort(namelist, n, sizeof(namelist[0]), scandir_cmp); // try to find selected file - // note: we don't show '.' so sel is namelist index - 1 sel = 0; if (sel_fname[0] != 0) { - for (i = 1; i < n; i++) { + for (i = 0; i < n; i++) { char *dname = namelist[i]->d_name; if (dname[0] == sel_fname[0] && strcmp(dname, sel_fname) == 0) { - sel = i - 1; + sel = i; break; } } @@ -1097,52 +1106,54 @@ rescan: if (inp & PBTN_MA3) { g_menu_filter_off = !g_menu_filter_off; snprintf(sel_fname, sizeof(sel_fname), "%s", - namelist[sel+1]->d_name); + namelist[sel]->d_name); goto rescan; } - if (inp & PBTN_UP ) { sel--; if (sel < 0) sel = n-2; } - if (inp & PBTN_DOWN) { sel++; if (sel > n-2) sel = 0; } + if (inp & PBTN_UP ) { sel--; if (sel < 0) sel = n-1; } + if (inp & PBTN_DOWN) { sel++; if (sel > n-1) sel = 0; } if (inp & PBTN_LEFT) { sel-=10; if (sel < 0) sel = 0; } if (inp & PBTN_L) { sel-=24; if (sel < 0) sel = 0; } - if (inp & PBTN_RIGHT) { sel+=10; if (sel > n-2) sel = n-2; } - if (inp & PBTN_R) { sel+=24; if (sel > n-2) sel = n-2; } + if (inp & PBTN_RIGHT) { sel+=10; if (sel > n-1) sel = n-1; } + if (inp & PBTN_R) { sel+=24; if (sel > n-1) sel = n-1; } if ((inp & PBTN_MOK) || (inp & (PBTN_MENU|PBTN_MA2)) == (PBTN_MENU|PBTN_MA2)) { - if (namelist[sel+1]->d_type == DT_REG) + if (namelist[sel]->d_type == DT_REG) { + int l = strlen(curr_path); + char *slash = l && curr_path[l-1] == '/' ? "" : "/"; snprintf(rom_fname_reload, sizeof(rom_fname_reload), - "%s/%s", curr_path, namelist[sel+1]->d_name); + "%s%s%s", curr_path, slash, namelist[sel]->d_name); if (inp & PBTN_MOK) { // return sel ret = rom_fname_reload; break; } - do_delete(rom_fname_reload, namelist[sel+1]->d_name); + do_delete(rom_fname_reload, namelist[sel]->d_name); goto rescan; } - else if (namelist[sel+1]->d_type == DT_DIR) + else if (namelist[sel]->d_type == DT_DIR) { int newlen; char *p, *newdir; if (!(inp & PBTN_MOK)) continue; - newlen = strlen(curr_path) + strlen(namelist[sel+1]->d_name) + 2; + newlen = strlen(curr_path) + strlen(namelist[sel]->d_name) + 2; newdir = malloc(newlen); if (newdir == NULL) break; - if (strcmp(namelist[sel+1]->d_name, "..") == 0) { + if (strcmp(namelist[sel]->d_name, "..") == 0) { char *start = curr_path; p = start + strlen(start) - 1; while (*p == '/' && p > start) p--; while (*p != '/' && p > start) p--; - if (p <= start) strcpy(newdir, "/"); + if (p <= start) plat_get_data_dir(newdir, newlen); else { strncpy(newdir, start, p-start); newdir[p-start] = 0; } } else { strcpy(newdir, curr_path); p = newdir + strlen(newdir) - 1; while (*p == '/' && p >= newdir) *p-- = 0; strcat(newdir, "/"); - strcat(newdir, namelist[sel+1]->d_name); + strcat(newdir, namelist[sel]->d_name); } ret = menu_loop_romsel(newdir, newlen, filter_exts, extra_filter); free(newdir); @@ -1381,7 +1392,8 @@ static void draw_key_config(const me_bind_action *opts, int opt_cnt, int player_ y = (g_menuscreen_h - 4 * me_mfont_h) / 2 - (2 + opt_cnt) * me_mfont_h / 2; if (x < me_mfont_w * 2) x = me_mfont_w * 2; - + if (y < 0) + y = 0; menu_draw_begin(1, 0); if (player_idx >= 0) text_out16(x, y, "Player %i controls", player_idx + 1);