OSDN Git Service

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