/* * Handle special request. */ static errr Term_xtra_vm(int n, int v) { int i, j; char tmp; /* Analyze the request */ switch (n) { /* Make a noise */ case TERM_XTRA_NOISE: /* No noises here! :) */ return (0); /* Wait for a single event */ case TERM_XTRA_EVENT: /* No wait key press check */ if (!v && !kbhit()) return (1); /* Wait for a keypress */ i = getkey(); /* Save keypress */ Term_keypress(i); /* Success */ return (0); case TERM_XTRA_CLEAR: ScreenClear(); return (0); #if 0 case TERM_XTRA_FROSH: ScreenUpdateLine(VirtualScreen + (cols*v), v); return (0); #endif case TERM_XTRA_FLUSH: /* Flush keys */ while (1) { tmp=getkeybuf(); if (!tmp) break; Term_keypress(tmp); } /* Success */ return (0); } /* Unknown request */ return (1); }
/** * Handle user input from a command menu */ static bool show_action(menu_type * menu, const ui_event_data * e, int oid) { /* Handle enter and mouse */ if (e->type == EVT_SELECT) { cmd_insert(comm_code[oid]); if (comm_code[oid] == CMD_NULL) Term_keypress(comm[oid]); } return TRUE; }
/* * Process an event, wait if requested */ static errr Term_xtra_sla_event(int v) { /* Do not wait unless requested */ if (!v && (SLang_input_pending(0) == 0)) return (1); /* Get and enqueue the key */ Term_keypress(SLang_getkey ()); /* Success */ return 0; }
/** * Handle user input from a command menu */ static bool show_action(menu_type * menu, const ui_event * e, int oid) { /* Handle enter and mouse */ if (e->type == EVT_SELECT) { cmd_insert(comm_code[oid]); if (comm_code[oid] == CMD_NULL) Term_keypress(comm[oid],0); cmd_set_arg_item(cmd_get_top(), 0, item); } return FALSE; }
/* * Check for events -- called by "Term_scan_emx()" */ static errr CheckEvents(int returnImmediately) { /* Get key - Macro triggers are generated by emx_read_kbd() */ int k=emx_read_kbd(((termWindow*)Term)->instance, returnImmediately?0:1); /* Nothing ready */ if (k < 0) return (1); /* Enqueue the key */ Term_keypress(k); /* Success */ return (0); }
/* * Check for "events" * If block, then busy-loop waiting for event, else check once and exit. */ static errr CheckEvents(int block) { int k = 0; if (block) { k = vga_getkey(); if (k < 1) return (1); } else { k = vga_getch(); } Term_keypress(k); return (0); }
/* * Process events (with optional wait) */ static errr Term_xtra_gcu_event(int v) { int i, k; char buf[2]; /* Wait */ if (v) { /* Wait for one byte */ i = read(0, buf, 1); /* Hack -- Handle bizarre "errors" */ if ((i <= 0) && (errno != EINTR)) exit_game_panic(); } /* Do not wait */ else { /* Get the current flags for stdin */ k = fcntl(0, F_GETFL, 0); /* Oops */ if (k < 0) return (1); /* Tell stdin not to block */ if (fcntl(0, F_SETFL, k | O_NDELAY) < 0) return (1); /* Read one byte, if possible */ i = read(0, buf, 1); /* Replace the flags for stdin */ if (fcntl(0, F_SETFL, k)) return (1); } /* Ignore "invalid" keys */ if ((i != 1) || (!buf[0])) return (1); /* Enqueue the keypress */ Term_keypress(buf[0]); /* Success */ return (0); }
/* * Process events, with optional wait */ static errr Term_xtra_gcu_event(int v) { int i, k; /* Wait */ if (v) { /* Paranoia -- Wait for it */ nodelay(stdscr, FALSE); /* Get a keypress */ i = getch(); /* Mega-Hack -- allow graceful "suspend" */ for (k = 0; (k < 10) && (i == ERR); k++) i = getch(); /* Broken input is special */ if (i == ERR) exit_game_panic(); if (i == EOF) exit_game_panic(); } /* Do not wait */ else { /* Do not wait for it */ nodelay(stdscr, TRUE); /* Check for keypresses */ i = getch(); /* Wait for it next time */ nodelay(stdscr, FALSE); /* None ready */ if (i == ERR) return (1); if (i == EOF) return (1); } /* Enqueue the keypress */ Term_keypress(i); /* Success */ return (0); }
/** * Get a command count, with the '0' key. */ static int textui_get_count(void) { int count = 0; while (1) { struct keypress ke; prt(format("Repeat: %d", count), 0, 0); ke = inkey(); if (ke.code == ESCAPE) return -1; /* Simple editing (delete or backspace) */ else if (ke.code == KC_DELETE || ke.code == KC_BACKSPACE) count = count / 10; /* Actual numeric data */ else if (isdigit((unsigned char) ke.code)) { count = count * 10 + D2I(ke.code); if (count >= 9999) { bell("Invalid repeat count!"); count = 9999; } } /* Anything non-numeric passes straight to command input */ else { /* XXX nasty hardcoding of action menu key */ if (ke.code != KC_ENTER) Term_keypress(ke.code, ke.mods); break; } } return count; }
/* * Process an event */ static errr Term_xtra_cap_event(int v) { int i, arg; char buf[2]; /* Wait */ if (v) { /* Wait for one byte */ i = read(0, buf, 1); /* Hack -- Handle "errors" */ if ((i <= 0) && (errno != EINTR)) exit_game_panic(); } /* Do not wait */ else { /* Get the current flags for stdin */ if ((arg = fcntl(0, F_GETFL, 0)) < 1) return (1); /* Tell stdin not to block */ if (fcntl(0, F_SETFL, arg | O_NDELAY) < 0) return (1); /* Read one byte, if possible */ i = read(0, buf, 1); /* Replace the flags for stdin */ if (fcntl(0, F_SETFL, arg)) return (1); } /* No keys ready */ if ((i != 1) || (!buf[0])) return (1); /* Enqueue the keypress */ Term_keypress(buf[0]); /* Success */ return (0); }
/* * Init the tk port */ int init_tnb(int argc, cptr *argv) { /* Hack -ignore parameter */ (void) argc; /* Save the "tk" directory */ path_make(ANGBAND_DIR_TK, ANGBAND_DIR_SCRIPT, "tk"); /* Use graphics */ pick_graphics(GRAPHICS_ADAM_BOLT, &tnb_tile_x, &tnb_tile_y, tnb_tile_file); /* Try the "16x16.bmp" file */ path_make(tnb_font_file, ANGBAND_DIR_XTRA, "font/16x16.txt"); /* Use the "16x16.bmp" file if it exists */ if (fd_close(fd_open(tnb_font_file, O_RDONLY))) { quit("Could not initialise font metrics!"); } /* Always 16x16 for now */ tnb_font_size = 16; /* Prepare the windows */ init_windows(); /* Activate hooks */ quit_aux = hook_quit; core_aux = hook_quit; /* Hack - TclTk_Init doesn't fail gracefully, so check manually for X11 */ if (!XOpenDisplay("")) return (1); /* Initialize Tcl and Tk. */ g_interp = TclTk_Init(argv); /* Paranoia */ if (!g_interp) return(1); /* Set the memory-allocation hooks */ rnfree_aux = my_tcl_free; ralloc_aux = my_tcl_alloc; /* Initialize */ angtk_init(); /* Catch nasty signals */ signals_init(); /* Initialize */ init_angband(); /* Program is intialized */ angtk_angband_initialized(); /* Init colours */ Term_xtra_tnb_react(); #if 0 while (TRUE) { while (Tcl_DoOneEvent(TRUE) != 0) ; } #endif /* 0 */ /* Press a key for the player */ Term_keypress(' '); /* Paranoia */ return (0); }
/* * Process a keypress event * * Also appears in "main-x11.c". */ static void react_keypress(XKeyEvent *xev) { int i, n, mc, ms, mo, mx; uint ks1; XKeyEvent *ev = (XKeyEvent*)(xev); KeySym ks; char buf[128]; char msg[128]; /* Check for "normal" keypresses */ n = XLookupString(ev, buf, 125, &ks, NULL); /* Terminate */ buf[n] = '\0'; /* Hack -- Ignore "modifier keys" */ if (IsModifierKey(ks)) return; /* Hack -- convert into an unsigned int */ ks1 = (uint)(ks); /* Extract four "modifier flags" */ mc = (ev->state & ControlMask) ? TRUE : FALSE; ms = (ev->state & ShiftMask) ? TRUE : FALSE; mo = (ev->state & Mod1Mask) ? TRUE : FALSE; mx = (ev->state & Mod2Mask) ? TRUE : FALSE; /* Normal keys with no modifiers */ if (n && !mo && !mx && !IsSpecialKey(ks)) { /* Enqueue the normal key(s) */ for (i = 0; buf[i]; i++) Term_keypress(buf[i]); /* All done */ return; } /* Handle a few standard keys (bypass modifiers) XXX XXX XXX */ switch (ks1) { case XK_Escape: { Term_keypress(ESCAPE); return; } case XK_Return: { Term_keypress('\r'); return; } case XK_Tab: { Term_keypress('\t'); return; } case XK_Delete: case XK_BackSpace: { Term_keypress('\010'); return; } } /* Hack -- Use the KeySym */ if (ks) { sprintf(msg, "%c%s%s%s%s_%lX%c", 31, mc ? "N" : "", ms ? "S" : "", mo ? "O" : "", mx ? "M" : "", (unsigned long)(ks), 13); } /* Hack -- Use the Keycode */ else { sprintf(msg, "%c%s%s%s%sK_%X%c", 31, mc ? "N" : "", ms ? "S" : "", mo ? "O" : "", mx ? "M" : "", ev->keycode, 13); } /* Enqueue the "macro trigger" string */ for (i = 0; msg[i]; i++) Term_keypress(msg[i]); /* Hack -- auto-define macros as needed */ if (n && (macro_find_exact(msg) < 0)) { /* Create a macro */ macro_add(msg, buf); } }
/** * Process events, with optional wait */ static errr Term_xtra_gcu_event(int v) { int i, j, k, mods=0; if (v) { /* Wait for a keypress; use halfdelay(1) so if the user takes more */ /* than 0.2 seconds we get a chance to do updates. */ halfdelay(2); i = getch(); while (i == ERR) { i = getch(); idle_update(); } cbreak(); } else { /* Do not wait for it */ nodelay(stdscr, TRUE); /* Check for keypresses */ i = getch(); /* Wait for it next time */ nodelay(stdscr, FALSE); /* None ready */ if (i == ERR) return (1); if (i == EOF) return (1); } /* Not sure if this is portable to non-ncurses platforms */ #ifdef USE_NCURSES if (i == KEY_RESIZE) { /* wait until we go one second (10 deci-seconds) before actually * doing the resizing. users often end up triggering multiple * KEY_RESIZE events while changing window size. */ halfdelay(10); do { i = getch(); } while (i == KEY_RESIZE); cbreak(); do_gcu_resize(); if (i == ERR) return (1); } #endif /* uncomment to debug keycode issues */ #if 0 printw("key %d", i); wrefresh(stdscr); #endif /* This might be a bad idea, but... * * Here we try to second-guess ncurses. In some cases, keypad() mode will * fail to translate multi-byte escape sequences into things like number- * pad actions, function keys, etc. So we can hardcode a small list of some * of the most common sequences here, just in case. * * Notice that we turn nodelay() on. This means, that we won't accidentally * interpret sequences as valid unless all the bytes are immediately * available; this seems like an acceptable risk to fix problems associated * with various terminal emulators (I'm looking at you PuTTY). */ if (i == 27) { /* ESC */ nodelay(stdscr, TRUE); j = getch(); switch (j) { case 'O': { k = getch(); switch (k) { /* PuTTY number pad */ case 'q': i = '1'; break; case 'r': i = '2'; break; case 's': i = '3'; break; case 't': i = '4'; break; case 'u': i = '5'; break; case 'v': i = '6'; break; case 'w': i = '7'; break; case 'x': i = '8'; break; case 'y': i = '9'; break; /* no match */ case ERR: break; default: ungetch(k); ungetch(j); } break; } /* no match */ case ERR: break; default: ungetch(j); } nodelay(stdscr, FALSE); } #ifdef KEY_DOWN /* Handle arrow keys */ switch (i) { case KEY_DOWN: i = ARROW_DOWN; break; case KEY_UP: i = ARROW_UP; break; case KEY_LEFT: i = ARROW_LEFT; break; case KEY_RIGHT: i = ARROW_RIGHT; break; case KEY_DC: i = KC_DELETE; break; case KEY_BACKSPACE: i = KC_BACKSPACE; break; case KEY_ENTER: i = KC_ENTER; mods |= KC_MOD_KEYPAD; break; case 9: i = KC_TAB; break; case 13: i = KC_ENTER; break; case 27: i = ESCAPE; break; /* keypad keys */ case 0xFC: i = '0'; break; case 0xFD: i = '.'; break; case 0xC0: i = '\b'; break; case 0xDF: i = '1'; break; case 0xF5: i = '3'; break; case 0xE9: i = '5'; break; case 0xC1: i = '7'; break; case 0xF4: i = '9'; break; default: { if (i < KEY_MIN) break; /* Mega-Hack -- Fold, spindle, and mutilate * the keys to fit in 7 bits. */ if (i >= 252) i = KEY_F(63) - (i - 252); if (i >= ARROW_DOWN) i += 4; i = 128 + (i & 127); break; } } #endif /* Enqueue the keypress */ Term_keypress(i, mods); /* Success */ return (0); }
/** * Deal with events on the get_item menu */ bool get_item_action(menu_type *menu, const ui_event *event, int oid) { bool refresh = FALSE; struct object_menu_data *choice = menu_priv(menu); char key = event->key.code; int i, k; char *selections = (char *) menu->selections; if (event->type == EVT_SELECT) { selection = choice[oid].key; return FALSE; } if (event->type == EVT_KBRD) { if (key == '/') { /* Toggle to inventory */ if ((item_mode & USE_INVEN) && (p_ptr->command_wrk != USE_INVEN)) { p_ptr->command_wrk = USE_INVEN; build_obj_list(0, i2, NULL, olist_mode); refresh = TRUE; } /* Toggle to equipment */ else if ((item_mode & USE_EQUIP) && (p_ptr->command_wrk != USE_EQUIP)) { p_ptr->command_wrk = USE_EQUIP; build_obj_list(INVEN_WIELD, e2, NULL, olist_mode); refresh = TRUE; } /* No toggle allowed */ else { bell("Cannot switch item selector!"); } } else if (key == '-') { /* No toggle allowed */ if (f1 > f2) { bell("Cannot select floor!"); } /* Toggle to floor */ else { p_ptr->command_wrk = (USE_FLOOR); build_obj_list(0, f2, floor_list, olist_mode); refresh = TRUE; } } else if ((key >= '0') && (key <= '9')) { /* Look up the tag */ if (!get_tag(&k, key, item_cmd, item_mode & QUIVER_TAGS)) { bell("Illegal object choice (tag)!"); return TRUE; } /* Match the item */ for (i = 0; i < menu->count; i++) { if (choice[i].object == &p_ptr->inventory[k]) { Term_keypress(choice[i].key, 0); return TRUE; } } } if (refresh) { /* Load screen */ screen_load(); Term_fresh(); /* Save screen */ screen_save(); /* Show the prompt */ item_prompt(item_mode); menu_setpriv(menu, num_obj, items); for (i = 0; i < num_obj; i++) selections[i] = items[i].key; area.page_rows = menu->count + 1; menu_layout(menu, &area); menu_refresh(menu, TRUE); redraw_stuff(p_ptr); } return FALSE; } return TRUE; }
/* * Process events, with optional wait */ static errr Term_xtra_gcu_event(int v) { int i, k; /* Wait */ if (v) { /* Paranoia -- Wait for it */ nodelay(stdscr, FALSE); /* Get a keypress */ i = getch(); /* Mega-Hack -- allow graceful "suspend" */ for (k = 0; (k < 10) && (i == ERR); k++) i = getch(); /* Broken input is special */ if (i == ERR) exit_game_panic(); if (i == EOF) exit_game_panic(); } /* Do not wait */ else { /* Do not wait for it */ nodelay(stdscr, TRUE); /* Check for keypresses */ i = getch(); /* Wait for it next time */ nodelay(stdscr, FALSE); /* None ready */ if (i == ERR) return (1); if (i == EOF) return (1); } /* Issue: Currently, we map curses escape sequences via the macro processing system (see pref-gcu.prf). * If you don't already know, this is required for things like arrow keys and the numpad and what not. * The advantage of this approach is that users can (theoretically) edit the pref file themselves in * the event that their terminal is sending a different escape sequence for some reason. All good, right? * Well, except for those places in the code that *disable* macro processing! This includes all user prompts, * the store UI (TODO) and the autopicker. Now, it's rather disconcerting if arrow keys aren't available in * a text editor or if the user can't correct typos with backspace! * * The idea of translating here is from current Vanilla * TODO */ /* Backspace */ if (i == 0x7F) i = '\b'; if (i == 27) /* \e is not ansi c */ { /* char buf[255]; int cb = _getstr(buf, 255); if (cb > 0) { if (strcmp(buf, "[3~") == 0) i = '.'; else if (strcmp(buf, "[2~") == 0) i = '0'; else if (strcmp(buf, "[4~") == 0) i = '1'; else if (strcmp(buf, "[F") == 0) i = '1'; else if (strcmp(buf, "[B") == 0) i = '2'; ... else _ungetstr(buf, cb); } CTK: Actually, I'm not so sure this is going to work. Arrow keys need to be known as such by the game engine not translated to numbers. And looking at what main-win.c and main-x11.c do to get this working is ... uh, a bit overwhelming. So this is on hold for now ... */ } /* Enqueue the keypress */ Term_keypress(i); /* Success */ return (0); }
int context_menu_player_2(int mx, int my) { menu_type *m; rect_region r; int selected; char *labels; m = menu_dynamic_new(); if (!m) { return 0; } labels = (char*)string_make(lower_case); m->selections = labels; menu_dynamic_add_label(m, "Knowledge", '~', 1, labels); menu_dynamic_add_label(m, "Show Map", 'M', 2, labels); menu_dynamic_add_label(m, "^Show Messages", 'P', 3, labels); menu_dynamic_add_label(m, "Show Monster List", '[', 9, labels); menu_dynamic_add_label(m, "Show Object List", ']', 10, labels); menu_dynamic_add_label(m, "Toggle Searching", 'S', 4, labels); if (player_has_pets()) { menu_dynamic_add_label(m, "Pet Commands", 'p', 5, labels); } menu_dynamic_add_label(m, "Destroy an item", 'k', 6, labels); menu_dynamic_add_label(m, "Options", '=', 8, labels); menu_dynamic_add_label(m, "Commands", '?', 7, labels); menu_dynamic_add_label(m, "Back", ' ', 11, labels); /* work out display region */ r.width = menu_dynamic_longest_entry(m) + 3 + 2; /* +3 for tag, 2 for pad */ if (mx > Term->wid - r.width - 1) { r.col = Term->wid - r.width - 1; } else { r.col = mx + 1; } r.page_rows = m->count; if (my > Term->hgt - r.page_rows - 1) { if (my - r.page_rows - 1 <= 0) { /* menu has too many items, so put in upper right corner */ r.row = 1; r.col = Term->wid - r.width - 1; } else { r.row = Term->hgt - r.page_rows - 1; } } else { r.row = my + 1; } /* Hack -- no flush needed */ msg_flag = FALSE; screen_save(); button_backup_all(TRUE); menu_layout(m, &r); rect_region_erase_bordered(&r); prtf(0, 0, "($UEnter to select$Y\n$V, $UESC$Y%c$V) Command:", ESCAPE); selected = menu_dynamic_select(m); menu_dynamic_free(m); string_free(labels); button_restore(); screen_load(); if (selected == 1) { /* show knowledge screen */ Term_keypress('~');//,0); } else if (selected == 2) { /* Toggle show map */ p_ptr->cmd.cmd = 'M'; repeat_check(); do_cmd_view_map(); } else if (selected == 3) { /* Toggle show messages */ Term_keypress(KTRL('p'));//,0);/*XXX should be ('p', KC_MOD_CONTROL);*/ } else if (selected == 4) { /* Toggle search mode */ Term_keypress('S');//,0); } else if (selected == 5) { /* show pet menu */ p_ptr->cmd.cmd = 'p'; repeat_check(); do_cmd_pet(); } else if (selected == 6) { /* destroy/squelch an item */ Term_keypress('k');//,0); } else if (selected == 7) { /* show the commands */ context_menu_command(mx,my); } else if (selected == 8) { /* show options screen */ Term_keypress('=');//,0); } else if (selected == 9) { /* show the monster list */ p_ptr->cmd.dir = 5; do_cmd_list_monster(0); //Term_keypress('[');//,0); } else if (selected == 10) { /* show the object list */ p_ptr->cmd.dir = 5; do_cmd_list_object(0); //Term_keypress(']');//,0); } else if (selected == 11) { /* show the previous menu again */ return 2; } return 1; }
/* pick the context menu options appropiate for a store */ int context_menu_store(struct store *store, const int oid, int mx, int my) { menu_type *m; rect_region r; int selected; char *labels; object_type *o_ptr; m = menu_dynamic_new(); if (!m || !store) { return 0; } /* Get the actual object */ o_ptr = &store->stock[oid]; labels = string_make(lower_case); m->selections = labels; menu_dynamic_add_label(m, "Inspect Inventory", 'I', 1, labels); if (store->sidx == STORE_HOME) { /*menu_dynamic_add(m, "Stash One", 2);*/ menu_dynamic_add_label(m, "Stash", 'd', 3, labels); menu_dynamic_add_label(m, "Examine", 'x', 4, labels); menu_dynamic_add_label(m, "Take", 'p', 6, labels); if (o_ptr->number > 1) { menu_dynamic_add_label(m, "Take One", 'o', 5, labels); } } else { /*menu_dynamic_add(m, "Sell One", 2);*/ menu_dynamic_add_label(m, "Sell", 'd', 3, labels); menu_dynamic_add_label(m, "Examine", 'x', 4, labels); menu_dynamic_add_label(m, "Buy", 'p', 6, labels); if (o_ptr->number > 1) { menu_dynamic_add_label(m, "Buy One", 'o', 5, labels); } } menu_dynamic_add_label(m, "Exit", '`', 7, labels); /* work out display region */ r.width = menu_dynamic_longest_entry(m) + 3 + 2; /* +3 for tag, 2 for pad */ if (mx > Term->wid - r.width - 1) { r.col = Term->wid - r.width - 1; } else { r.col = mx + 1; } r.page_rows = m->count; if (my > Term->hgt - r.page_rows - 1) { if (my - r.page_rows - 1 <= 0) { /* menu has too many items, so put in upper right corner */ r.row = 1; r.col = Term->wid - r.width - 1; } else { r.row = Term->hgt - r.page_rows - 1; } } else { r.row = my + 1; } /* Hack -- no flush needed */ msg_flag = FALSE; screen_save(); button_backup_all(TRUE); menu_layout(m, &r); region_erase_bordered(&r); prt("(Enter to select, ESC) Command:", 0, 0); selected = menu_dynamic_select(m); menu_dynamic_free(m); string_free(labels); button_restore(); screen_load(); if (selected == 1) { Term_keypress('I', 0); } else if (selected == 2) { Term_keypress('s', 0); /* oid is store item we do not know item we want to sell here */ /*if (store->sidx == STORE_HOME) { cmd_insert(CMD_STASH); } else { cmd_insert(CMD_SELL); } cmd_set_arg_item(cmd_get_top(), 0, oid); cmd_set_arg_number(cmd_get_top(), 1, 1);*/ } else if (selected == 3) { Term_keypress('s', 0); } else if (selected == 4) { Term_keypress('x', 0); } else if (selected == 5) { if (store->sidx == STORE_HOME) { cmd_insert(CMD_RETRIEVE); } else { cmd_insert(CMD_BUY); } cmd_set_arg_choice(cmd_get_top(), 0, oid); cmd_set_arg_number(cmd_get_top(), 1, 1); } else if (selected == 6) { Term_keypress('p', 0); } else if (selected == 7) { Term_keypress(ESCAPE, 0); } return 1; }
/* * Check for events -- called by "Term_scan_emx()" * * Note -- this is probably NOT the most efficient way * to "wait" for a keypress (TERM_XTRA_EVENT). * * * This code was ripped from "main-ibm.c" -- consult it to * figure out what's going on. * * See "main-ibm.c" for more information about "macro encoding". * * * The following documentation was cut&pasted from * the OS/2 Programming Reference, PRCP.INF * <ftp://hobbes.nmsu.edu/pub/os2/dev/16-bit/inf16bit.zip> ------------------------------------------------------------------------------- This call returns a character data record from the keyboard. KbdCharIn (CharData, IOWait, KbdHandle) CharData (PKBDKEYINFO) - output Address of the character data structure: asciicharcode (UCHAR) ASCII character code. The scan code received from the keyboard is translated to the ASCII character code. scancode (UCHAR) Code received from the keyboard. The scan code received from the keyboard is translated to the ASCII character code. status (UCHAR) State of the keystroke event: Bit Description 7-6 00 = Undefined 01 = Final character, interim character flag off 10 = Interim character 11 = Final character, interim character flag on. 5 1 = Immediate conversion requested. 4-2 Reserved. 1 0 = Scan code is a character. 1 = Scan code is not a character; is an extended key code from the keyboard. 0 1 = Shift status returned without character. reserved (UCHAR) NLS shift status. Reserved, set to zero. shiftkeystat (USHORT) Shift key status. Bit Description 15 SysReq key down 14 CapsLock key down 13 NumLock key down 12 ScrollLock key down 11 Right Alt key down 10 Right Ctrl key down 9 Left Alt key down 8 Left Ctrl key down 7 Insert on 6 CapsLock on 5 NumLock on 4 ScrollLock on 3 Either Alt key down 2 Either Ctrl key down 1 Left Shift key down 0 Right Shift key down time (ULONG) Time stamp indicating when a key was pressed. It is specified in milliseconds from the time the system was started. IOWait (USHORT) - input Wait if a character is not available. Value Definition 0 Requestor waits for a character if one is not available. 1 Requestor gets an immediate return if no character is available. KbdHandle (HKBD) - input Default keyboard or the logical keyboard. rc (USHORT) - return Return code descriptions are: 0 NO_ERROR 375 ERROR_KBD_INVALID_IOWAIT 439 ERROR_KBD_INVALID_HANDLE 445 ERROR_KBD_FOCUS_REQUIRED 447 ERROR_KBD_KEYBOARD_BUSY 464 ERROR_KBD_DETACHED 504 ERROR_KBD_EXTENDED_SG Remarks On an enhanced keyboard, the secondary enter key returns the normal character 0DH and a scan code of E0H. Double-byte character codes (DBCS) require two function calls to obtain the entire code. If shift report is set with KbdSetStatus, the CharData record returned reflects changed shift information only. Extended ASCII codes are identified with the status byte, bit 1 on and the ASCII character code being either 00H or E0H. Both conditions must be satisfied for the character to be an extended keystroke. For extended ASCII codes, the scan code byte returned is the second code (extended code). Usually the extended ASCII code is the scan code of the primary key that was pressed. A thread in the foreground session that repeatedly polls the keyboard with KbdCharIn (with no wait), can prevent all regular priority class threads from executing. If polling must be used and a minimal amount of other processing is being performed, the thread should periodically yield to the CPU by issuing a DosSleep call for an interval of at least 5 milliseconds. Family API Considerations Some options operate differently in the DOS mode than in the OS /2 mode. Therefore, the following restrictions apply to KbdCharIn when coding in the DOS mode: o The CharData structure includes everything except the time stamp. o Interim character is not supported o Status can be 0 or 40H o KbdHandle is ignored. ------------------------------------------------------------------------------- typedef struct _KBDKEYINFO { / * kbci * / UCHAR chChar; / * ASCII character code * / UCHAR chScan; / * Scan Code * / UCHAR fbStatus; / * State of the character * / UCHAR bNlsShift; / * Reserved (set to zero) * / USHORT fsState; / * State of the shift keys * / ULONG time; / * Time stamp of keystroke (ms since ipl) * / }KBDKEYINFO; #define INCL_KBD USHORT rc = KbdCharIn(CharData, IOWait, KbdHandle); PKBDKEYINFO CharData; / * Buffer for data * / USHORT IOWait; / * Indicate if wait * / HKBD KbdHandle; / * Keyboard handle * / USHORT rc; / * return code * / ------------------------------------------------------------------------------- * */ static errr CheckEvents(int returnImmediately) { int i, k, s; bool mc = FALSE; bool ms = FALSE; bool ma = FALSE; /* start OS/2 specific section */ struct _KBDKEYINFO keyinfo; /* see structure description above */ /* Check (and possibly wait) for a keypress */ /* see function description above */ KbdCharIn( &keyinfo, returnImmediately, (HKBD)0 ); #if 0 printf("AC:%x SC:%x ST:%x R1:%x SH:%x TI:%ld\n", /* OS/2 debug */ keyinfo.chChar, keyinfo.chScan, keyinfo.fbStatus, keyinfo.bNlsShift, keyinfo.fsState, keyinfo.time ); #endif /* If there wasn't a key, leave now. */ if ((keyinfo.fbStatus & 0xC0) == 0) return(1); /* by a set of lucky coincidences, the data maps directly over. */ k = keyinfo.chChar; s = keyinfo.chScan; i = (keyinfo.fsState & 0xFF); /* end OS/2 specific section */ /* Process "normal" keys */ if ( k != 0 && ((s <= 58) || (s == 0xE0)) ) /* Tweak: allow for ALT-keys */ { /* Enqueue it */ Term_keypress(k); /* Success */ return (0); } /* Extract the modifier flags */ if (i & (1 << K_CTRL)) mc = TRUE; if (i & (1 << K_LSHIFT)) ms = TRUE; if (i & (1 << K_RSHIFT)) ms = TRUE; if (i & (1 << K_ALT)) ma = TRUE; /* Begin a "macro trigger" */ Term_keypress(31); /* Hack -- Send the modifiers */ if (mc) Term_keypress('C'); if (ms) Term_keypress('S'); if (ma) Term_keypress('A'); /* Introduce the hexidecimal scan code */ Term_keypress('x'); /* Encode the hexidecimal scan code */ Term_keypress(hexsym[s/16]); Term_keypress(hexsym[s%16]); /* End the "macro trigger" */ Term_keypress(13); /* Success */ return (0); }
/** * Handle a textui mouseclick. */ static void textui_process_click(ui_event e) { int x, y; if (!OPT(mouse_movement)) return; y = KEY_GRID_Y(e); x = KEY_GRID_X(e); /* Check for a valid location */ if (!cave_in_bounds_fully(cave, y, x)) return; /* XXX show context menu here */ if ((p_ptr->py == y) && (p_ptr->px == x)) { if (e.mouse.mods & KC_MOD_SHIFT) { /* shift-click - cast magic */ if (e.mouse.button == 1) { textui_obj_cast(); } else if (e.mouse.button == 2) { Term_keypress('i',0); } } else if (e.mouse.mods & KC_MOD_CONTROL) { /* ctrl-click - use feature / use inventory item */ /* switch with default */ if (e.mouse.button == 1) { if (cave_isupstairs(cave, p_ptr->py, p_ptr->px)) cmd_insert(CMD_GO_UP); else if (cave_isdownstairs(cave, p_ptr->py, p_ptr->px)) cmd_insert(CMD_GO_DOWN); } else if (e.mouse.button == 2) { cmd_insert(CMD_USE_UNAIMED); } } else if (e.mouse.mods & KC_MOD_ALT) { /* alt-click - Search or show char screen */ /* XXX call a platform specific hook */ if (e.mouse.button == 1) { cmd_insert(CMD_SEARCH); } else if (e.mouse.button == 2) { Term_keypress('C',0); } } else { if (e.mouse.button == 1) { if (cave->o_idx[y][x]) { cmd_insert(CMD_PICKUP); } else { cmd_insert(CMD_HOLD); } } else if (e.mouse.button == 2) { // show a context menu context_menu_player(e.mouse.x, e.mouse.y); } } } else if (e.mouse.button == 1) { if (p_ptr->timed[TMD_CONFUSED]) { cmd_insert(CMD_WALK); } else { if (e.mouse.mods & KC_MOD_SHIFT) { /* shift-click - run */ cmd_insert(CMD_RUN); cmd_set_arg_direction(cmd_get_top(), 0, coords_to_dir(y,x)); /*if ((y-p_ptr->py >= -1) && (y-p_ptr->py <= 1) && (x-p_ptr->px >= -1) && (x-p_ptr->px <= 1)) { cmd_insert(CMD_JUMP); cmd_set_arg_direction(cmd_get_top(), 0, coords_to_dir(y,x)); } else { cmd_insert(CMD_RUN); cmd_set_arg_direction(cmd_get_top(), 0, coords_to_dir(y,x)); }*/ } else if (e.mouse.mods & KC_MOD_CONTROL) { /* control-click - alter */ cmd_insert(CMD_ALTER); cmd_set_arg_direction(cmd_get_top(), 0, coords_to_dir(y,x)); } else if (e.mouse.mods & KC_MOD_ALT) { /* alt-click - look */ if (target_set_interactive(TARGET_LOOK, x, y)) { msg("Target Selected."); } //cmd_insert(CMD_LOOK); //cmd_set_arg_point(cmd_get_top(), 0, y, x); } else { /* pathfind does not work well on trap detection borders, * so if the click is next to the player, force a walk step */ if ((y-p_ptr->py >= -1) && (y-p_ptr->py <= 1) && (x-p_ptr->px >= -1) && (x-p_ptr->px <= 1)) { cmd_insert(CMD_WALK); cmd_set_arg_direction(cmd_get_top(), 0, coords_to_dir(y,x)); } else { cmd_insert(CMD_PATHFIND); cmd_set_arg_point(cmd_get_top(), 0, y, x); } } } } else if (e.mouse.button == 2) { struct monster *m = cave_monster_at(cave, y, x); if (m && target_able(m)) { /* Set up target information */ monster_race_track(m->race); health_track(p_ptr, m); target_set_monster(m); } else { target_set_location(y,x); } if (e.mouse.mods & KC_MOD_SHIFT) { /* shift-click - cast spell at target */ if (textui_obj_cast_ret() >= 0) { cmd_set_arg_target(cmd_get_top(), 1, DIR_TARGET); } } else if (e.mouse.mods & KC_MOD_CONTROL) { /* control-click - fire at target */ cmd_insert(CMD_USE_AIMED); cmd_set_arg_target(cmd_get_top(), 1, DIR_TARGET); } else if (e.mouse.mods & KC_MOD_ALT) { /* alt-click - throw at target */ cmd_insert(CMD_THROW); cmd_set_arg_target(cmd_get_top(), 1, DIR_TARGET); } else { //msg("Target set."); /* see if the click was adjacent to the player */ if ((y-p_ptr->py >= -1) && (y-p_ptr->py <= 1) && (x-p_ptr->px >= -1) && (x-p_ptr->px <= 1)) { context_menu_cave(cave,y,x,1,e.mouse.x, e.mouse.y); } else { context_menu_cave(cave,y,x,0,e.mouse.x, e.mouse.y); } } } }
static int show_command_list(struct cmd_info cmd_list[], int size, int mx, int my) { menu_type *m; region r; int selected; int i; char cmd_name[80]; char key[3]; int mode = OPT(rogue_like_commands) ? KEYMAP_MODE_ROGUE : KEYMAP_MODE_ORIG; m = menu_dynamic_new(); if (!m) { return 0; } m->selections = lower_case; key[2] = '\0'; for (i=0; i < size; ++i) { if (KTRL(cmd_list[i].key[mode]) == cmd_list[i].key[mode]) { key[0] = '^'; key[1] = UN_KTRL(cmd_list[i].key[mode]); } else { key[0] = cmd_list[i].key[mode]; key[1] = '\0'; } strnfmt(cmd_name, 80, "%s (%s)", cmd_list[i].desc, key[mode]); menu_dynamic_add(m, cmd_name, i+1); } /* work out display region */ r.width = menu_dynamic_longest_entry(m) + 3 + 2; /* +3 for tag, 2 for pad */ if (mx > Term->wid - r.width - 1) { r.col = Term->wid - r.width - 1; } else { r.col = mx + 1; } r.page_rows = m->count; if (my > Term->hgt - r.page_rows - 1) { if (my - r.page_rows - 1 <= 0) { /* menu has too many items, so put in upper right corner */ r.row = 1; r.col = Term->wid - r.width - 1; } else { r.row = Term->hgt - r.page_rows - 1; } } else { r.row = my + 1; } screen_save(); menu_layout(m, &r); region_erase_bordered(&r); prt("(Enter to select, ESC) Command:", 0, 0); selected = menu_dynamic_select(m); menu_dynamic_free(m); screen_load(); if ((selected > 0) && (selected < size+1)) { /* execute the command */ Term_keypress(cmd_list[selected-1].key[mode], 0); } return 1; }
/* pick the context menu options appropiate for an item available in a store */ int context_menu_store_item(struct store *store, const int oid, int mx, int my) { menu_type *m; rect_region r; int selected; char *labels; object_type *o_ptr; char header[120]; /* Get the actual object */ o_ptr = &store->stock[oid]; m = menu_dynamic_new(); if (!m || !store) { return 0; } object_desc(header, sizeof(header), o_ptr, ODESC_PREFIX | ODESC_BASE); labels = string_make(lower_case); m->selections = labels; menu_dynamic_add_label(m, "Examine", 'x', 4, labels); if (store->sidx == STORE_HOME) { menu_dynamic_add_label(m, "Take", 'p', 6, labels); if (o_ptr->number > 1) { menu_dynamic_add_label(m, "Take One", 'o', 5, labels); } } else { menu_dynamic_add_label(m, "Buy", 'p', 6, labels); if (o_ptr->number > 1) { menu_dynamic_add_label(m, "Buy One", 'o', 5, labels); } } /* work out display region */ r.width = menu_dynamic_longest_entry(m) + 3 + 2; /* +3 for tag, 2 for pad */ if (mx > Term->wid - r.width - 1) { r.col = Term->wid - r.width - 1; } else { r.col = mx + 1; } r.page_rows = m->count; if (my > Term->hgt - r.page_rows - 1) { if (my - r.page_rows - 1 <= 0) { /* menu has too many items, so put in upper right corner */ r.row = 1; r.col = Term->wid - r.width - 1; } else { r.row = Term->hgt - r.page_rows - 1; } } else { r.row = my + 1; } /* Hack -- no flush needed */ msg_flag = FALSE; screen_save(); button_backup_all(TRUE); menu_layout(m, &r); region_erase_bordered(&r); prt(format("(Enter to select, ESC) Command for %s:", header), 0, 0); selected = menu_dynamic_select(m); menu_dynamic_free(m); string_free(labels); button_restore(); screen_load(); if (selected == 4) { Term_keypress('x', 0); } else if (selected == 5) { if (store->sidx == STORE_HOME) { cmd_insert(CMD_RETRIEVE); } else { cmd_insert(CMD_BUY); } cmd_set_arg_choice(cmd_get_top(), 0, oid); cmd_set_arg_number(cmd_get_top(), 1, 1); } else if (selected == 6) { Term_keypress('p', 0); } return 1; }
int context_menu_player(int mx, int my) { menu_type *m; region r; int selected; char *labels; bool allowed = TRUE; int mode = OPT(rogue_like_commands) ? KEYMAP_MODE_ROGUE : KEYMAP_MODE_ORIG; unsigned char cmdkey; m = menu_dynamic_new(); if (!m) { return 0; } labels = string_make(lower_case); m->selections = labels; ADD_LABEL("Use", CMD_USE_ANY, MN_ROW_VALID); /* if player can cast, add casting option */ if (player_can_cast(p_ptr, FALSE)) { ADD_LABEL("Cast", CMD_CAST, MN_ROW_VALID); } /* if player is on stairs add option to use them */ if (cave_isupstairs(cave, p_ptr->py, p_ptr->px)) { ADD_LABEL("Go Up", CMD_GO_UP, MN_ROW_VALID); } else if (cave_isdownstairs(cave, p_ptr->py, p_ptr->px)) { ADD_LABEL("Go Down", CMD_GO_DOWN, MN_ROW_VALID); } ADD_LABEL("Search", CMD_SEARCH, MN_ROW_VALID); /* Looking has different keys, but we don't have a way to look them up (see cmd-process.c). */ cmdkey = (mode == KEYMAP_MODE_ORIG) ? 'l' : 'x'; menu_dynamic_add_label(m, "Look", cmdkey, MENU_VALUE_LOOK, labels); /* 'R' is used for resting in both keymaps. */ menu_dynamic_add_label(m, "Rest", 'R', MENU_VALUE_REST, labels); /* 'i' is used for inventory in both keymaps. */ menu_dynamic_add_label(m, "Inventory", 'i', MENU_VALUE_INVENTORY, labels); /* if object under player add pickup option */ if (cave->o_idx[p_ptr->py][p_ptr->px]) { object_type *o_ptr = object_byid(cave->o_idx[p_ptr->py][p_ptr->px]); if (!squelch_item_ok(o_ptr)) { menu_row_validity_t valid; /* 'f' isn't in rogue keymap, so we can use it here. */ menu_dynamic_add_label(m, "Floor", 'f', MENU_VALUE_FLOOR, labels); valid = (inven_carry_okay(o_ptr)) ? MN_ROW_VALID : MN_ROW_INVALID; ADD_LABEL("Pick up", CMD_PICKUP, valid); } } /* 'C' is used for the character sheet in both keymaps. */ menu_dynamic_add_label(m, "Character", 'C', MENU_VALUE_CHARACTER, labels); /* XXX Don't show the keymap line until the keymap list is implemented, to * avoid confusion as to what should be there */ /*menu_dynamic_add(m, "Keymaps", 10);*/ if (!OPT(center_player)) { menu_dynamic_add_label(m, "^Center Map", 'L', MENU_VALUE_CENTER_MAP, labels); } menu_dynamic_add_label(m, "Other", ' ', MENU_VALUE_OTHER, labels); /* work out display region */ r.width = (int)menu_dynamic_longest_entry(m) + 3 + 2; /* +3 for tag, 2 for pad */ if (mx > Term->wid - r.width - 1) { r.col = Term->wid - r.width - 1; } else { r.col = mx + 1; } r.page_rows = m->count; if (my > Term->hgt - r.page_rows - 1) { if (my - r.page_rows - 1 <= 0) { /* menu has too many items, so put in upper right corner */ r.row = 1; r.col = Term->wid - r.width - 1; } else { r.row = Term->hgt - r.page_rows - 1; } } else { r.row = my + 1; } /* Hack -- no flush needed */ msg_flag = FALSE; screen_save(); menu_layout(m, &r); region_erase_bordered(&r); prt("(Enter to select, ESC) Command:", 0, 0); selected = menu_dynamic_select(m); menu_dynamic_free(m); string_free(labels); screen_load(); cmdkey = cmd_lookup_key(selected, mode); /* Check the command to see if it is allowed. */ switch(selected) { case -1: /* User cancelled the menu. */ return 3; case CMD_USE_ANY: case CMD_CAST: case CMD_SEARCH: case CMD_GO_UP: case CMD_GO_DOWN: case CMD_PICKUP: /* Only check for ^ inscriptions, since we don't have an object selected (if we need one). */ allowed = key_confirm_command(cmdkey); break; case MENU_VALUE_REST: allowed = key_confirm_command('R'); break; case MENU_VALUE_INVENTORY: case MENU_VALUE_LOOK: case MENU_VALUE_CHARACTER: case MENU_VALUE_OTHER: case MENU_VALUE_FLOOR: case MENU_VALUE_CENTER_MAP: allowed = TRUE; break; default: /* Invalid command; prevent anything from happening. */ bell("Invalid context menu command."); allowed = FALSE; break; } if (!allowed) return 1; /* Perform the command. */ switch(selected) { case CMD_USE_ANY: case CMD_CAST: cmdkey = cmd_lookup_key(selected, mode); Term_keypress(cmdkey, 0); break; case CMD_SEARCH: case CMD_GO_UP: case CMD_GO_DOWN: case CMD_PICKUP: cmd_insert(selected); break; case MENU_VALUE_REST: Term_keypress('R', 0); break; case MENU_VALUE_INVENTORY: Term_keypress('i', 0); break; case MENU_VALUE_LOOK: if (target_set_interactive(TARGET_LOOK, p_ptr->px, p_ptr->py)) { msg("Target Selected."); } break; case MENU_VALUE_CHARACTER: Term_keypress('C', 0); break; case MENU_VALUE_OTHER: context_menu_player_2(mx, my); break; case MENU_VALUE_FLOOR: context_menu_player_display_floor(); break; case MENU_VALUE_CENTER_MAP: do_cmd_center_map(); break; default: break; } return 1; }
int context_menu_player(int mx, int my) { menu_type *m; rect_region r; int selected; char *labels; cave_type *c_ptr = area(p_ptr->px,p_ptr->py); pcave_type *pc_ptr = parea(p_ptr->px,p_ptr->py); feature_type *feat; m = menu_dynamic_new(); if (!m) { return 0; } labels = (char*)string_make(lower_case); m->selections = labels; feat = &(f_info[c_ptr->feat]); menu_dynamic_add_label(m, "Use Item", 'u', 1, labels); /* if player can cast, add casting option */ if (player_is_caster()) { if (player_can_cast()) { menu_dynamic_add_label(m, "Cast", 'm', 2, labels); } else { menu_dynamic_add_label(m, "$Cast", 'm', 2, labels); } } /* if player can use racial powers or mutations, add option */ if (player_has_power()) { if (player_can_use_power()) { menu_dynamic_add_label(m, "Use Power", 'U', 16, labels); } else { menu_dynamic_add_label(m, "$Use Power", 'U', 16, labels); } } /* if player is on stairs add option to use them */ if (feat->flags & FF_EXIT_UP) { menu_dynamic_add_label(m, "Go Up", '<', 11, labels); } if (feat->flags & FF_EXIT_DOWN) { menu_dynamic_add_label(m, "Go Down", '>', 12, labels); } menu_dynamic_add_label(m, "Search", 's', 3, labels); menu_dynamic_add_label(m, "Look", 'l', 6, labels); menu_dynamic_add_label(m, "Rest", 'R', 4, labels); menu_dynamic_add_label(m, "Inventory", 'i', 5, labels); /* if object under player add pickup option */ if (c_ptr->o_idx) { object_type *o_ptr = &(o_list[c_ptr->o_idx]); //if (!squelch_item_ok(o_ptr)) { menu_dynamic_add_label(m, "Floor", 'i', 13, labels); if (inven_carry_okay(o_ptr)) { menu_dynamic_add_label(m, "Pickup", 'g', 14, labels); } else { menu_dynamic_add_label(m, "$Pickup", 'g', 14, labels); } //} } menu_dynamic_add_label(m, "Character", 'C', 7, labels); /* XXX Don't show the keymap line until the keymap list is implemented, to * avoid confusion as to what should be there */ /*menu_dynamic_add(m, "Keymaps", 10);*/ if (!OPT(center_player)) { menu_dynamic_add_label(m, "^Center Map", 'L', 15, labels); } menu_dynamic_add_label(m, "Other", ' ', 9, labels); /* work out display region */ r.width = menu_dynamic_longest_entry(m) + 3 + 2; /* +3 for tag, 2 for pad */ if (mx > Term->wid - r.width - 1) { r.col = Term->wid - r.width - 1; } else { r.col = mx + 1; } r.page_rows = m->count; if (my > Term->hgt - r.page_rows - 1) { if (my - r.page_rows - 1 <= 0) { /* menu has too many items, so put in upper right corner */ r.row = 1; r.col = Term->wid - r.width - 1; } else { r.row = Term->hgt - r.page_rows - 1; } } else { r.row = my + 1; } /* Hack -- no flush needed */ msg_flag = FALSE; screen_save(); button_backup_all(TRUE); menu_layout(m, &r); rect_region_erase_bordered(&r); prtf(0, 0, "($UEnter to select$Y\n$V, $UESC$Y%c$V) Command:", ESCAPE); selected = menu_dynamic_select(m); menu_dynamic_free(m); string_free(labels); button_restore(); screen_load(); switch(selected) { case 1: { /* use an item */ p_ptr->cmd.cmd = 'u'; repeat_check(); do_cmd_use(); } break; case 2: { /* Cast a spell */ p_ptr->cmd.cmd = 'm'; repeat_check(); do_cmd_cast_wrapper(); } break; case 3: { /* search */ p_ptr->cmd.cmd = 's'; repeat_check(); do_cmd_search(); } break; case 4: { /* rest */ p_ptr->cmd.cmd = 'R'; repeat_check(); do_cmd_rest(); } break; case 5: { /* show inventory screen */ Term_keypress('i');//,0); } break; case 6: { /* look mode */ if (target_set(TARGET_LOOK)) { //if (target_set_interactive(TARGET_LOOK, p_ptr->px, p_ptr->py)) { msgf("Target Selected."); } } break; case 7: { /* show character screen */ do_cmd_character(); } break; case 9: { /* show another layer of menu options screen */ int res; while ((res = context_menu_player_2(mx,my)) == 3); if (res == 2) return 3; } break; case 10: { /* show the commands */ int res; while ((res = context_menu_command(mx,my)) == 3); if (res == 2) return 3; } break; case 11: { /* go up stairs */ p_ptr->cmd.cmd = '<'; repeat_check(); do_cmd_go_up(); } break; case 12: { /* go down stairs */ p_ptr->cmd.cmd = '>'; repeat_check(); do_cmd_go_down(); } break; case 13: { if (c_ptr->o_idx) { object_type *o_ptr = &(o_list[c_ptr->o_idx]); /* there is an item on the floor, show the inventory screen starting * from the floor */ if (o_ptr->next_o_idx) { do_cmd_inven_floor(); } else { /* if we only have one item, show the context menu directly */ if (o_ptr->k_idx) { /* Track the object kind */ object_kind_track(o_ptr->k_idx); while (context_menu_object(o_ptr) == 2); } } } } break; case 14: { /* pick the item up */ //cmd_insert(CMD_PICKUP); //cmd_set_arg_item(cmd_get_top(), 0, -1); carry(TRUE); } break; case 15: { /* center the map on the player */ /*panel_center(p_ptr->px, p_ptr->py);*/ do_cmd_center_map(); } break; case 16: { /* use character powers */ p_ptr->cmd.cmd = 'U'; repeat_check(); do_cmd_racial_power(); } break; } return 1; }
static int context_menu_player_2(int mx, int my) { menu_type *m; region r; int selected; char *labels; bool allowed = TRUE; int mode = OPT(rogue_like_commands) ? KEYMAP_MODE_ROGUE : KEYMAP_MODE_ORIG; unsigned char cmdkey; m = menu_dynamic_new(); if (!m) { return 0; } labels = string_make(lower_case); m->selections = labels; menu_dynamic_add_label(m, "Knowledge", '~', MENU_VALUE_KNOWLEDGE, labels); menu_dynamic_add_label(m, "Show Map", 'M', MENU_VALUE_MAP, labels); menu_dynamic_add_label(m, "^Show Messages", 'P', MENU_VALUE_MESSAGES, labels); menu_dynamic_add_label(m, "Show Monster List", '[', MENU_VALUE_MONSTERS, labels); menu_dynamic_add_label(m, "Show Object List", ']', MENU_VALUE_OBJECTS, labels); ADD_LABEL("Toggle Searching", CMD_TOGGLE_SEARCH, MN_ROW_VALID); /* Squelch toggle has different keys, but we don't have a way to look them up (see cmd-process.c). */ cmdkey = (mode == KEYMAP_MODE_ORIG) ? 'K' : 'O'; menu_dynamic_add_label(m, "Toggle Squelched", cmdkey, MENU_VALUE_TOGGLE_SQUELCHED, labels); ADD_LABEL("Squelch an item", CMD_DESTROY, MN_ROW_VALID); menu_dynamic_add_label(m, "Options", '=', MENU_VALUE_OPTIONS, labels); menu_dynamic_add_label(m, "Commands", '?', MENU_VALUE_HELP, labels); /* work out display region */ r.width = (int)menu_dynamic_longest_entry(m) + 3 + 2; /* +3 for tag, 2 for pad */ if (mx > Term->wid - r.width - 1) { r.col = Term->wid - r.width - 1; } else { r.col = mx + 1; } r.page_rows = m->count; if (my > Term->hgt - r.page_rows - 1) { if (my - r.page_rows - 1 <= 0) { /* menu has too many items, so put in upper right corner */ r.row = 1; r.col = Term->wid - r.width - 1; } else { r.row = Term->hgt - r.page_rows - 1; } } else { r.row = my + 1; } /* Hack -- no flush needed */ msg_flag = FALSE; screen_save(); menu_layout(m, &r); region_erase_bordered(&r); prt("(Enter to select, ESC) Command:", 0, 0); selected = menu_dynamic_select(m); menu_dynamic_free(m); string_free(labels); screen_load(); /* Check the command to see if it is allowed. */ switch (selected) { case -1: /* User cancelled the menu. */ return 3; case MENU_VALUE_KNOWLEDGE: case MENU_VALUE_MAP: case MENU_VALUE_MESSAGES: case MENU_VALUE_TOGGLE_SQUELCHED: case MENU_VALUE_HELP: case MENU_VALUE_MONSTERS: case MENU_VALUE_OBJECTS: case MENU_VALUE_OPTIONS: case CMD_TOGGLE_SEARCH: allowed = TRUE; break; case CMD_DESTROY: cmdkey = cmd_lookup_key(selected, mode); allowed = key_confirm_command(cmdkey); break; default: /* Invalid command; prevent anything from happening. */ bell("Invalid context menu command."); allowed = FALSE; break; } if (!allowed) return 1; /* Perform the command. */ switch (selected) { case MENU_VALUE_KNOWLEDGE: Term_keypress('~', 0); break; case MENU_VALUE_MAP: Term_keypress('M', 0); break; case MENU_VALUE_MESSAGES: Term_keypress(KTRL('p'), 0); break; case CMD_DESTROY: case CMD_TOGGLE_SEARCH: cmdkey = cmd_lookup_key(selected, mode); Term_keypress(cmdkey, 0); break; case MENU_VALUE_TOGGLE_SQUELCHED: /* Squelch toggle has different keys, but we don't have a way to look them up (see cmd-process.c). */ cmdkey = (mode == KEYMAP_MODE_ORIG) ? 'K' : 'O'; Term_keypress(cmdkey, 0); break; case MENU_VALUE_HELP: context_menu_command(mx, my); break; case MENU_VALUE_MONSTERS: Term_keypress('[', 0); break; case MENU_VALUE_OBJECTS: Term_keypress(']', 0); break; case MENU_VALUE_OPTIONS: Term_keypress('=', 0); break; default: break; } return 1; }