int handle_menuitem(const char **menu, int n, int *i, int x, int y, menuhandler *handlers, int keypr) { int j = *i; int m; keypr &= 0xFF; if (keypr == ESC) return 0; printmenuitem(menu[j], 1); if (handlers && handlers[j]) switch (m = handlers[j](keypr, i)) { case 0: break; case ESC: return 0; default: return m; } switch (keypr) { case STARTBTN: case A_BTN: return 2; case B_BTN: case '\b': return 0; case 'q': exit(0); case MVUP: if (!j) return 1; #if NO_MENU m = -1; #else m = -1-(*menu[j-1]=='-'); #endif break; case '\t': if (j == n-1) { m = -j; break; } case MVDOWN: if (j < n-1) { #if NO_MENU m = 1; #else m = 1+(*menu[j+1]=='-'); #endif break; } default: #ifndef NO_MENU if (m = find_firstletter(menu, n, j, keypr)) break; #endif return 1; } setcurs(x, y); printmenuitem(menu[j], 0); setcurs(x, y+m); printmenuitem(menu[*i+=m], 1); return 1; }
// Difference between this and regular menu, is that only // OPT_INVISIBLE, OPT_SEP are honoured void printradiomenu(pt_menu menu, int curr, char top, char left) { int x,row; // x = index, row = position from top int numitems,menuwidth; char fchar[5],lchar[5]; // The first and last char in for each entry const char *str; // and inbetween the item or a seperator is printed char *attr; // all in the attribute attr char sep[MENULEN];// and inbetween the item or a seperator is printed pt_menuitem ci; calc_visible(menu); numitems = menu->numvisible; menuwidth = menu->menuwidth+3; clearwindow(top,left-2, top+numitems+1, left+menuwidth+1, ms->menupage, ms->fillchar, ms->shadowattr); drawbox(top-1, left-3, top+numitems, left+menuwidth, ms->normalattr[NOHLITE], ms->menupage); memset(sep,HORIZ,menuwidth); // String containing the seperator string sep[menuwidth-1] = 0; // Menu title x = (menuwidth - strlen(menu->title) - 1) >> 1; gotoxy(top-1,left+x,ms->menupage); printmenuitem(menu->title,ms->normalattr); row = -1; // 1 less than inital value of x for (x=0; x < menu->numitems; x++) { ci = menu->items[x]; if (ci->action == OPT_INVISIBLE) continue; row++; // Setup the defaults now fchar[0] = RADIOUNSEL; fchar[1]='\0'; // Unselected ( ) lchar[0] = '\0'; // Nothing special after str = ci->item; // Pointer to item string attr = ms->normalattr; // Always same attribute fchar[0] = (x==curr ? RADIOSEL : RADIOUNSEL); switch (ci->action) // set up attr,str,fchar,lchar for everything { case OPT_INACTIVE: attr = ms->inactattr; break; case OPT_SEP: fchar[0] = '\b'; fchar[1] = LTRT; fchar[2] = HORIZ; fchar[3] = HORIZ; fchar[4] = 0; lchar[0] = HORIZ; lchar[1] = RTLT; lchar[3] = 0; str = sep; break; default: // To keep the compiler happy break; } gotoxy(top+row,left-2,ms->menupage); cprint(ms->spacechar,attr[NOHLITE],menuwidth+2,ms->menupage); // Wipe area with spaces gotoxy(top+row,left-2,ms->menupage); csprint(fchar,attr[NOHLITE]); // Print first part gotoxy(top+row,left,ms->menupage); printmenuitem(str,attr); // Print main part gotoxy(top+row,left+menuwidth-1,ms->menupage); // Last char if any csprint(lchar,attr[NOHLITE]); // Print last part } if (ms->handler) ms->handler(ms,menu->items[curr]); }
static void tetrom_colors_menu(int x, int y) { const char *menu[7] = {"I", "J", "L", "O", "S", "T", "Z"}; menuhandler handlers[7] = { op_tcolor, op_tcolor, op_tcolor, op_tcolor, op_tcolor_gt4, op_tcolor_gt4, op_tcolor_gt4 }; int i = 0; if (y+6 >= term_height) y -= 7; drawbox(x, y, 19, 6, (char *) 0); x++; y++; drawmenu(menu, 4, 0, x, y, handlers); drawmenu(menu+4, 3, -1, x+9, y, handlers+4); autorep_a_b_btns = 1; while (1) { setcurs(x, y+i%4); refreshwin(-1); switch (handle_menuitem_2cols(menu, 7, &i, 4, x, y+i%4, handlers, getkeypress_block(SINGLE_PL))) { case 0: case 2: autorep_a_b_btns = 0; if (i >= 4) x -= 9; clearbox(x-1, y-1, 19, 6); return; case 3: x += i>=4 ? 9 : -9; setcurs(x, y+i%4); printmenuitem(menu[i], 1); } } }
void drawmenu(const char **menu, int n, int pos, int x, int y, menuhandler *handlers) { int i; setcurs(x, y); for (i = 0; i < n; i++) { printmenuitem(menu[i], (i==pos)); if (handlers && handlers[i]) handlers[i](0, &i); newln(x); } }
int handle_menuitem_2cols(const char **menu, int n, int *i, int h, int x, int y, menuhandler *handlers, int keypr) { menuhandler *p; int j = *i; int m; keypr &= 0xFF; switch (keypr) { case MVUP: if (j == h) { m = -1; goto col; } break; case '\t': if (j == n-1) { m = -j; goto col; } case MVDOWN: if (j == h-1) { m = 1; goto col; } } if (j < h) { if (keypr == MVRIGHT && j+h < n) { m = h; goto col; } m = handle_menuitem(menu, h, i, x, y, handlers, keypr); } else { if (keypr == MVLEFT && j-h >= 0) { m = -h; goto col; } j = *i-h; p = NULL; if (handlers) p = handlers+h; m = handle_menuitem(menu+h, n-h, &j, x, y, p, keypr); *i = j+h; } return m; col: printmenuitem(menu[j], 0); *i += m; return 3; }
void inputsetup_box(int pl, int x, int y) { int h = 8; #ifdef JOYSTICK if (num_joyst) h++; #endif clearbox(x-1, y, 0, h+4); printhelp(x+2, y+h+2); setcurs(x, y); printmenuitem("Input Setup", 1); #ifdef TWOPLAYER if (!pl) printstr(" single"); printstr(" player"); if (pl) putch(pl+'0'); #endif drawbox(x, y+1, 31, h, NULL); inputsetup_menu(pl, x+1, y+2); clearbox(x, y, 0, h+4); }
/* Handle one menu */ pt_menuitem getmenuoption( pt_menu menu, char top, char left, char startopt) // Return item chosen or NULL if ESC was hit. { int curr,i; char asc,scan; char numitems; pt_menuitem ci; // Current item calc_visible(menu); numitems = menu->numvisible; // Setup status line gotoxy(ms->minrow+ms->statline,ms->mincol,ms->menupage); cprint(ms->spacechar,ms->statusattr[NOHLITE],ms->numcols,ms->menupage); // Initialise current menu item curr = next_visible(menu,startopt); gotoxy(ms->minrow+ms->statline,ms->mincol,ms->menupage); cprint(ms->spacechar,ms->statusattr[NOHLITE],ms->numcols,1); gotoxy(ms->minrow+ms->statline,ms->mincol,ms->menupage); printmenuitem(menu->items[curr]->status,ms->statusattr); while (1) // Forever { printmenu(menu,curr,top,left); ci = menu->items[curr]; asc = getch(&scan); switch (scan) { case HOMEKEY: curr = next_visible(menu,0); break; case ENDKEY: curr = prev_visible(menu,numitems-1); break; case PAGEDN: for (i=0; i < 5; i++) curr = next_visible(menu,curr+1); break; case PAGEUP: for (i=0; i < 5; i++) curr = prev_visible(menu,curr-1); break; case UPARROW: curr = prev_visible(menu,curr-1); break; case DNARROW: curr = next_visible(menu,curr+1); break; case LTARROW: case ESCAPE: return NULL; break; case RTARROW: case ENTERA: case ENTERB: if (ci->action == OPT_INACTIVE) break; if (ci->action == OPT_CHECKBOX) break; if (ci->action == OPT_SEP) break; if (ci->action == OPT_EXITMENU) return NULL; // As if we hit Esc return ci; break; case SPACEKEY: if (ci->action != OPT_CHECKBOX) break; ci->itemdata.checked = !ci->itemdata.checked; // Call handler to see it anything needs to be done if (ci->handler != NULL) ci->handler(ms,ci); break; default: // Check if this is a shortcut key if (((asc >= 'A') && (asc <= 'Z')) || ((asc >= 'a') && (asc <= 'z')) || ((asc >= '0') && (asc <= '9'))) curr = find_shortcut(menu,asc,curr); break; } // Update status line gotoxy(ms->minrow+ms->statline,ms->mincol,ms->menupage); cprint(ms->spacechar,ms->statusattr[NOHLITE],ms->numcols,ms->menupage); printmenuitem(menu->items[curr]->status,ms->statusattr); } return NULL; // Should never come here }
void inputsetup_menu(int pl, int x, int y) { const char *menu[11] = { " Up", "Dwn", "Lft", "Rgt", " A", " B", " Rotate ", " Rot cw ", NULL, "Harddrop", "Softdrop" }; char rot_acw[9] = " Rot acw"; int dev = 0; int i = 0; int xx, k; #ifdef JOYSTICK int devlist = num_joyst; if (devlist) { i = -1; setcurs(x, y); newln(x); y++; } #endif spellword(rot_acw+5); menu[8] = rot_acw; drawmenu(menu, 6, i, x, y, NULL); drawmenu(menu+6, 5, -1, x+12, y, NULL); #ifdef TWOPLAYER player_ = pl; #endif while (1) { #ifdef JOYSTICK if (devlist && i==-1) { if (!inp_devlist(&dev, x, y-1)) return; printmenuitem(menu[0], 1); i = 0; } #endif inp_printkeys(dev, x, y); xx = inp_setcurs(x, y, i); refreshwin(-1); k = setkeymapping(dev, inp_keypr(i)); #ifdef JOYSTICK if (devlist && (k==MVUP && !i || k=='\t' && i==10)) { printmenuitem(menu[i], 0); i = -1; continue; } #endif if (k==MVUP && !i) k = MVDOWN; else if (k==MVDOWN && i==10) { printmenuitem(menu[10], 0); inp_setcurs(x, y, i=0); printmenuitem(menu[0], 1); continue; } switch (handle_menuitem_2cols(menu, 11, &i, 6, xx, y+i%6, NULL, k)) { case 0: case 2: return; case 3: inp_setcurs(x, y, i); printmenuitem(menu[i], 1); } } }