OSDN Git Service

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