OSDN Git Service

[Refactor] #40483 Moved print_map(), display_map() and set_term_color() from display...
[hengband/hengband.git] / src / io / input-key-requester.c
1 #include "io/input-key-requester.h"
2 #include "cmd-io/cmd-menu-content-table.h"
3 #include "cmd-io/macro-util.h"
4 #include "core/asking-player.h" // todo 相互依存している、後で何とかする.
5 #include "floor/floor.h"
6 #include "game-option/input-options.h"
7 #include "io/input-key-acceptor.h"
8 #include "main/sound-of-music.h"
9 #include "term/screen-processor.h" // todo 相互依存している、後で何とかする.
10 #include "util/int-char-converter.h"
11 #include "util/quarks.h"
12 #include "util/string-processor.h"
13 #include "view/display-main-window.h" // todo move_cursor_relative() が依存している。後で移設を検討する.
14 #include "view/display-messages.h"
15 #include "view/main-window-util.h"
16
17 /*
18  * Keymaps for each "mode" associated with each keypress.
19  */
20 concptr keymap_act[KEYMAP_MODES][256];
21
22 bool use_menu;
23
24 s16b command_cmd; /* Current "Angband Command" */
25 COMMAND_ARG command_arg; /*!< 各種コマンドの汎用的な引数として扱う / Gives argument of current command */
26 COMMAND_NUM command_rep; /*!< 各種コマンドの汎用的なリピート数として扱う / Gives repetition of current command */
27 DIRECTION command_dir; /*!< 各種コマンドの汎用的な方向値処理として扱う/ Gives direction of current command */
28 s16b command_see; /* アイテム使用時等にリストを表示させるかどうか (ゲームオプションの他、様々なタイミングでONになったりOFFになったりする模様……) */
29 s16b command_wrk; /* アイテムの使用許可状況 (ex. 装備品のみ、床上もOK等) */
30 TERM_LEN command_gap = 999; /* アイテムの表示に使う (詳細未調査) */
31 s16b command_new; /* Command chaining from inven/equip view */
32
33 /*
34  * Hack -- special buffer to hold the action of the current keymap
35  */
36 static char request_command_buffer[256];
37
38 static char inkey_from_menu(player_type *player_ptr)
39 {
40     char cmd;
41     int basey, basex;
42     int num = 0, max_num, old_num = 0;
43     int menu = 0;
44     bool kisuu;
45
46     if (player_ptr->y - panel_row_min > 10)
47         basey = 2;
48     else
49         basey = 13;
50     basex = 15;
51
52     prt("", 0, 0);
53     screen_save();
54
55     floor_type *floor_ptr = player_ptr->current_floor_ptr;
56     while (TRUE) {
57         int i;
58         char sub_cmd;
59         concptr menu_name;
60         if (!menu)
61             old_num = num;
62         put_str("+----------------------------------------------------+", basey, basex);
63         put_str("|                                                    |", basey + 1, basex);
64         put_str("|                                                    |", basey + 2, basex);
65         put_str("|                                                    |", basey + 3, basex);
66         put_str("|                                                    |", basey + 4, basex);
67         put_str("|                                                    |", basey + 5, basex);
68         put_str("+----------------------------------------------------+", basey + 6, basex);
69
70         for (i = 0; i < 10; i++) {
71             int hoge;
72             if (!menu_info[menu][i].cmd)
73                 break;
74             menu_name = menu_info[menu][i].name;
75             for (hoge = 0;; hoge++) {
76                 if (!special_menu_info[hoge].name[0])
77                     break;
78                 if ((menu != special_menu_info[hoge].window) || (i != special_menu_info[hoge].number))
79                     continue;
80                 switch (special_menu_info[hoge].jouken) {
81                 case MENU_CLASS:
82                     if (player_ptr->pclass == special_menu_info[hoge].jouken_naiyou)
83                         menu_name = special_menu_info[hoge].name;
84                     break;
85                 case MENU_WILD:
86                     if (!floor_ptr->dun_level && !floor_ptr->inside_arena && !floor_ptr->inside_quest) {
87                         if ((byte)player_ptr->wild_mode == special_menu_info[hoge].jouken_naiyou)
88                             menu_name = special_menu_info[hoge].name;
89                     }
90                     break;
91                 default:
92                     break;
93                 }
94             }
95
96             put_str(menu_name, basey + 1 + i / 2, basex + 4 + (i % 2) * 24);
97         }
98
99         max_num = i;
100         kisuu = max_num % 2;
101         put_str(_("》", "> "), basey + 1 + num / 2, basex + 2 + (num % 2) * 24);
102
103         move_cursor_relative(player_ptr->y, player_ptr->x);
104         sub_cmd = inkey();
105         if ((sub_cmd == ' ') || (sub_cmd == 'x') || (sub_cmd == 'X') || (sub_cmd == '\r') || (sub_cmd == '\n')) {
106             if (menu_info[menu][num].fin) {
107                 cmd = menu_info[menu][num].cmd;
108                 use_menu = TRUE;
109                 break;
110             } else {
111                 menu = menu_info[menu][num].cmd;
112                 num = 0;
113                 basey += 2;
114                 basex += 8;
115             }
116         } else if ((sub_cmd == ESCAPE) || (sub_cmd == 'z') || (sub_cmd == 'Z') || (sub_cmd == '0')) {
117             if (!menu) {
118                 cmd = ESCAPE;
119                 break;
120             } else {
121                 menu = 0;
122                 num = old_num;
123                 basey -= 2;
124                 basex -= 8;
125                 screen_load();
126                 screen_save();
127             }
128         } else if ((sub_cmd == '2') || (sub_cmd == 'j') || (sub_cmd == 'J')) {
129             if (kisuu) {
130                 if (num % 2)
131                     num = (num + 2) % (max_num - 1);
132                 else
133                     num = (num + 2) % (max_num + 1);
134             } else
135                 num = (num + 2) % max_num;
136         } else if ((sub_cmd == '8') || (sub_cmd == 'k') || (sub_cmd == 'K')) {
137             if (kisuu) {
138                 if (num % 2)
139                     num = (num + max_num - 3) % (max_num - 1);
140                 else
141                     num = (num + max_num - 1) % (max_num + 1);
142             } else
143                 num = (num + max_num - 2) % max_num;
144         } else if ((sub_cmd == '4') || (sub_cmd == '6') || (sub_cmd == 'h') || (sub_cmd == 'H') || (sub_cmd == 'l') || (sub_cmd == 'L')) {
145             if ((num % 2) || (num == max_num - 1)) {
146                 num--;
147             } else if (num < max_num - 1) {
148                 num++;
149             }
150         }
151     }
152
153     screen_load();
154     if (!inkey_next)
155         inkey_next = "";
156
157     return (cmd);
158 }
159
160 /*
161  * Request a command from the user.
162  *
163  * Sets player_ptr->command_cmd, player_ptr->command_dir, player_ptr->command_rep,
164  * player_ptr->command_arg.  May modify player_ptr->command_new.
165  *
166  * Note that "caret" ("^") is treated specially, and is used to
167  * allow manual input of control characters.  This can be used
168  * on many machines to request repeated tunneling (Ctrl-H) and
169  * on the Macintosh to request "Control-Caret".
170  *
171  * Note that "backslash" is treated specially, and is used to bypass any
172  * keymap entry for the following character.  This is useful for macros.
173  *
174  * Note that this command is used both in the dungeon and in
175  * stores, and must be careful to work in both situations.
176  *
177  * Note that "player_ptr->command_new" may not work any more.
178  */
179 void request_command(player_type *player_ptr, int shopping)
180 {
181     s16b cmd;
182     int mode;
183
184     concptr act;
185
186 #ifdef JP
187     int caretcmd = 0;
188 #endif
189     if (rogue_like_commands) {
190         mode = KEYMAP_MODE_ROGUE;
191     } else {
192         mode = KEYMAP_MODE_ORIG;
193     }
194
195     command_cmd = 0;
196     command_arg = 0;
197     command_dir = 0;
198     use_menu = FALSE;
199
200     while (TRUE) {
201         if (command_new) {
202             msg_erase();
203             cmd = command_new;
204             command_new = 0;
205         } else {
206             msg_flag = FALSE;
207             num_more = 0;
208             inkey_flag = TRUE;
209             cmd = inkey();
210             if (!shopping && command_menu && ((cmd == '\r') || (cmd == '\n') || (cmd == 'x') || (cmd == 'X')) && !keymap_act[mode][(byte)(cmd)])
211                 cmd = inkey_from_menu(player_ptr);
212         }
213
214         prt("", 0, 0);
215         if (cmd == '0') {
216             COMMAND_ARG old_arg = command_arg;
217             command_arg = 0;
218             prt(_("回数: ", "Count: "), 0, 0);
219             while (TRUE) {
220                 cmd = inkey();
221                 if ((cmd == 0x7F) || (cmd == KTRL('H'))) {
222                     command_arg = command_arg / 10;
223                     prt(format(_("回数: %d", "Count: %d"), command_arg), 0, 0);
224                 } else if (cmd >= '0' && cmd <= '9') {
225                     if (command_arg >= 1000) {
226                         bell();
227                         command_arg = 9999;
228                     } else {
229                         command_arg = command_arg * 10 + D2I(cmd);
230                     }
231
232                     prt(format(_("回数: %d", "Count: %d"), command_arg), 0, 0);
233                 } else {
234                     break;
235                 }
236             }
237
238             if (command_arg == 0) {
239                 command_arg = 99;
240                 prt(format(_("回数: %d", "Count: %d"), command_arg), 0, 0);
241             }
242
243             if (old_arg != 0) {
244                 command_arg = old_arg;
245                 prt(format(_("回数: %d", "Count: %d"), command_arg), 0, 0);
246             }
247
248             if ((cmd == ' ') || (cmd == '\n') || (cmd == '\r')) {
249                 if (!get_com(_("コマンド: ", "Command: "), (char *)&cmd, FALSE)) {
250                     command_arg = 0;
251                     continue;
252                 }
253             }
254         }
255
256         if (cmd == '\\') {
257             (void)get_com(_("コマンド: ", "Command: "), (char *)&cmd, FALSE);
258             if (!inkey_next)
259                 inkey_next = "";
260         }
261
262         if (cmd == '^') {
263             if (get_com(_("CTRL: ", "Control: "), (char *)&cmd, FALSE))
264                 cmd = KTRL(cmd);
265         }
266
267         act = keymap_act[mode][(byte)(cmd)];
268         if (act && !inkey_next) {
269             (void)strnfmt(request_command_buffer, 256, "%s", act);
270             inkey_next = request_command_buffer;
271             continue;
272         }
273
274         if (!cmd)
275             continue;
276
277         command_cmd = (byte)cmd;
278         break;
279     }
280
281     if (always_repeat && (command_arg <= 0)) {
282         if (angband_strchr("TBDoc+", (char)command_cmd)) {
283             command_arg = 99;
284         }
285     }
286
287     if (shopping == 1) {
288         switch (command_cmd) {
289         case 'p':
290             command_cmd = 'g';
291             break;
292
293         case 'm':
294             command_cmd = 'g';
295             break;
296
297         case 's':
298             command_cmd = 'd';
299             break;
300         }
301     }
302
303 #ifdef JP
304     for (int i = 0; i < 256; i++) {
305         concptr s;
306         if ((s = keymap_act[mode][i]) != NULL) {
307             if (*s == command_cmd && *(s + 1) == 0) {
308                 caretcmd = i;
309                 break;
310             }
311         }
312     }
313
314     if (!caretcmd)
315         caretcmd = command_cmd;
316 #endif
317
318     for (int i = INVEN_RARM; i < INVEN_TOTAL; i++) {
319         object_type *o_ptr = &player_ptr->inventory_list[i];
320         if (!o_ptr->k_idx)
321             continue;
322
323         if (!o_ptr->inscription)
324             continue;
325
326         concptr s = quark_str(o_ptr->inscription);
327         s = angband_strchr(s, '^');
328         while (s) {
329 #ifdef JP
330             if ((s[1] == caretcmd) || (s[1] == '*'))
331 #else
332             if ((s[1] == command_cmd) || (s[1] == '*'))
333 #endif
334             {
335                 if (!get_check(_("本当ですか? ", "Are you sure? "))) {
336                     command_cmd = ' ';
337                 }
338             }
339
340             s = angband_strchr(s + 1, '^');
341         }
342     }
343
344     prt("", 0, 0);
345 }