OSDN Git Service

[Refactor] #40413 Separated command-repeater.c/h from util.c/h
[hengbandforosx/hengbandosx.git] / src / core / asking-player.c
1 #include "core/asking-player.h"
2 #include "cmd-io/macro-util.h"
3 #include "core/stuff-handler.h"
4 #include "game-option/input-options.h"
5 #include "io/command-repeater.h"
6 #include "io/input-key-acceptor.h"
7 #include "io/input-key-requester.h" // todo 相互依存している、後で何とかする.
8 #include "main/sound-of-music.h"
9 #include "term/screen-processor.h"
10 #include "term/term-color-types.h"
11 #include "view/display-messages.h"
12
13 /*
14  * Get some string input at the cursor location.
15  * Assume the buffer is initialized to a default string.
16  *
17  * The default buffer is in Overwrite mode and displayed in yellow at
18  * first.  Normal chars clear the yellow text and append the char in
19  * white text.
20  *
21  * LEFT (^B) and RIGHT (^F) movement keys move the cursor position.
22  * If the text is still displayed in yellow (Overwite mode), it will
23  * turns into white (Insert mode) when cursor moves.
24  *
25  * DELETE (^D) deletes a char at the cursor position.
26  * BACKSPACE (^H) deletes a char at the left of cursor position.
27  * ESCAPE clears the buffer and the window and returns FALSE.
28  * RETURN accepts the current buffer contents and returns TRUE.
29  */
30 bool askfor_aux(char *buf, int len, bool numpad_cursor)
31 {
32     /*
33      * Text color
34      * TERM_YELLOW : Overwrite mode
35      * TERM_WHITE : Insert mode
36      */
37     byte color = TERM_YELLOW;
38
39     int y, x;
40     Term_locate(&x, &y);
41     if (len < 1)
42         len = 1;
43     if ((x < 0) || (x >= 80))
44         x = 0;
45     if (x + len > 80)
46         len = 80 - x;
47
48     buf[len] = '\0';
49
50     int pos = 0;
51     while (TRUE) {
52         Term_erase(x, y, len);
53         Term_putstr(x, y, -1, color, buf);
54
55         Term_gotoxy(x + pos, y);
56         int skey = inkey_special(numpad_cursor);
57
58         switch (skey) {
59         case SKEY_LEFT:
60         case KTRL('b'): {
61             int i = 0;
62             color = TERM_WHITE;
63
64             if (0 == pos)
65                 break;
66             while (TRUE) {
67                 int next_pos = i + 1;
68 #ifdef JP
69                 if (iskanji(buf[i]))
70                     next_pos++;
71 #endif
72                 if (next_pos >= pos)
73                     break;
74
75                 i = next_pos;
76             }
77
78             pos = i;
79             break;
80         }
81
82         case SKEY_RIGHT:
83         case KTRL('f'):
84             color = TERM_WHITE;
85             if ('\0' == buf[pos])
86                 break;
87
88 #ifdef JP
89             if (iskanji(buf[pos]))
90                 pos += 2;
91             else
92                 pos++;
93 #else
94             pos++;
95 #endif
96             break;
97
98         case ESCAPE:
99             buf[0] = '\0';
100             return FALSE;
101
102         case '\n':
103         case '\r':
104             return TRUE;
105
106         case '\010': {
107             int i = 0;
108             color = TERM_WHITE;
109             if (0 == pos)
110                 break;
111             while (TRUE) {
112                 int next_pos = i + 1;
113 #ifdef JP
114                 if (iskanji(buf[i]))
115                     next_pos++;
116 #endif
117                 if (next_pos >= pos)
118                     break;
119
120                 i = next_pos;
121             }
122
123             pos = i;
124         }
125             /* Fall through */
126
127         case 0x7F:
128         case KTRL('d'): {
129             color = TERM_WHITE;
130             if ('\0' == buf[pos])
131                 break;
132             int src = pos + 1;
133 #ifdef JP
134             if (iskanji(buf[pos]))
135                 src++;
136 #endif
137
138             int dst = pos;
139             while ('\0' != (buf[dst++] = buf[src++]))
140                 ;
141             break;
142         }
143
144         default: {
145             char tmp[100];
146             if (skey & SKEY_MASK)
147                 break;
148             char c = (char)skey;
149
150             if (color == TERM_YELLOW) {
151                 buf[0] = '\0';
152                 color = TERM_WHITE;
153             }
154
155             strcpy(tmp, buf + pos);
156 #ifdef JP
157             if (iskanji(c)) {
158                 inkey_base = TRUE;
159                 char next = inkey();
160                 if (pos + 1 < len) {
161                     buf[pos++] = c;
162                     buf[pos++] = next;
163                 } else {
164                     bell();
165                 }
166             } else
167 #endif
168             {
169 #ifdef JP
170                 if (pos < len && (isprint(c) || iskana(c)))
171 #else
172                 if (pos < len && isprint(c))
173 #endif
174                 {
175                     buf[pos++] = c;
176                 } else {
177                     bell();
178                 }
179             }
180
181             buf[pos] = '\0';
182             angband_strcat(buf, tmp, len + 1);
183
184             break;
185         }
186         }
187     }
188 }
189
190 /*
191  * Get some string input at the cursor location.
192  *
193  * Allow to use numpad keys as cursor keys.
194  */
195 bool askfor(char *buf, int len) { return askfor_aux(buf, len, TRUE); }
196
197 /*
198  * Get a string from the user
199  *
200  * The "prompt" should take the form "Prompt: "
201  *
202  * Note that the initial contents of the string is used as
203  * the default response, so be sure to "clear" it if needed.
204  *
205  * We clear the input, and return FALSE, on "ESCAPE".
206  */
207 bool get_string(concptr prompt, char *buf, int len)
208 {
209     bool res;
210     msg_print(NULL);
211     prt(prompt, 0, 0);
212     res = askfor(buf, len);
213     prt("", 0, 0);
214     return (res);
215 }
216
217 /*
218  * Verify something with the user
219  *
220  * The "prompt" should take the form "Query? "
221  *
222  * Note that "[y/n]" is appended to the prompt.
223  */
224 bool get_check(concptr prompt) { return get_check_strict(p_ptr, prompt, 0); }
225
226 /*
227  * Verify something with the user strictly
228  *
229  * mode & CHECK_OKAY_CANCEL : force user to answer 'O'kay or 'C'ancel
230  * mode & CHECK_NO_ESCAPE   : don't allow ESCAPE key
231  * mode & CHECK_NO_HISTORY  : no message_add
232  * mode & CHECK_DEFAULT_Y   : accept any key as y, except n and Esc.
233  */
234 bool get_check_strict(player_type *player_ptr, concptr prompt, BIT_FLAGS mode)
235 {
236     char buf[80];
237     if (auto_more) {
238         player_ptr->window |= PW_MESSAGE;
239         handle_stuff(player_ptr);
240         num_more = 0;
241     }
242
243     msg_print(NULL);
244     if (!rogue_like_commands)
245         mode &= ~CHECK_OKAY_CANCEL;
246
247     if (mode & CHECK_OKAY_CANCEL) {
248         angband_strcpy(buf, prompt, sizeof(buf) - 15);
249         strcat(buf, "[(O)k/(C)ancel]");
250     } else if (mode & CHECK_DEFAULT_Y) {
251         angband_strcpy(buf, prompt, sizeof(buf) - 5);
252         strcat(buf, "[Y/n]");
253     } else {
254         angband_strcpy(buf, prompt, sizeof(buf) - 5);
255         strcat(buf, "[y/n]");
256     }
257
258     prt(buf, 0, 0);
259     if (!(mode & CHECK_NO_HISTORY) && player_ptr->playing) {
260         message_add(buf);
261         player_ptr->window |= (PW_MESSAGE);
262         handle_stuff(player_ptr);
263     }
264
265     bool flag = FALSE;
266     while (TRUE) {
267         int i = inkey();
268
269         if (!(mode & CHECK_NO_ESCAPE)) {
270             if (i == ESCAPE) {
271                 flag = FALSE;
272                 break;
273             }
274         }
275
276         if (mode & CHECK_OKAY_CANCEL) {
277             if (i == 'o' || i == 'O') {
278                 flag = TRUE;
279                 break;
280             } else if (i == 'c' || i == 'C') {
281                 flag = FALSE;
282                 break;
283             }
284         } else {
285             if (i == 'y' || i == 'Y') {
286                 flag = TRUE;
287                 break;
288             } else if (i == 'n' || i == 'N') {
289                 flag = FALSE;
290                 break;
291             }
292         }
293
294         if (mode & CHECK_DEFAULT_Y) {
295             flag = TRUE;
296             break;
297         }
298
299         bell();
300     }
301
302     prt("", 0, 0);
303     return flag;
304 }
305
306 /*
307  * Prompts for a keypress
308  *
309  * The "prompt" should take the form "Command: "
310  *
311  * Returns TRUE unless the character is "Escape"
312  */
313 bool get_com(concptr prompt, char *command, bool z_escape)
314 {
315     msg_print(NULL);
316     prt(prompt, 0, 0);
317     if (get_com_no_macros)
318         *command = (char)inkey_special(FALSE);
319     else
320         *command = inkey();
321
322     prt("", 0, 0);
323     if (*command == ESCAPE)
324         return FALSE;
325     if (z_escape && ((*command == 'z') || (*command == 'Z')))
326         return FALSE;
327
328     return TRUE;
329 }
330
331 /*
332  * Request a "quantity" from the user
333  *
334  * Hack -- allow "command_arg" to specify a quantity
335  */
336 QUANTITY get_quantity(concptr prompt, QUANTITY max)
337 {
338     bool res;
339     char tmp[80];
340     char buf[80];
341
342     QUANTITY amt;
343     if (command_arg) {
344         amt = command_arg;
345         command_arg = 0;
346         if (amt > max)
347             amt = max;
348
349         return (amt);
350     }
351
352     COMMAND_CODE code;
353     bool result = repeat_pull(&code);
354     amt = (QUANTITY)code;
355     if ((max != 1) && result) {
356         if (amt > max)
357             amt = max;
358         if (amt < 0)
359             amt = 0;
360
361         return (amt);
362     }
363
364     if (!prompt) {
365         sprintf(tmp, _("いくつですか (1-%d): ", "Quantity (1-%d): "), max);
366         prompt = tmp;
367     }
368
369     msg_print(NULL);
370     prt(prompt, 0, 0);
371     amt = 1;
372     sprintf(buf, "%d", amt);
373
374     /*
375      * Ask for a quantity
376      * Don't allow to use numpad as cursor key.
377      */
378     res = askfor_aux(buf, 6, FALSE);
379
380     prt("", 0, 0);
381     if (!res)
382         return 0;
383
384     amt = (COMMAND_CODE)atoi(buf);
385     if (isalpha(buf[0]))
386         amt = max;
387     if (amt > max)
388         amt = max;
389     if (amt < 0)
390         amt = 0;
391     if (amt)
392         repeat_push((COMMAND_CODE)amt);
393
394     return (amt);
395 }
396
397 /*
398  * Pause for user response
399  */
400 void pause_line(int row)
401 {
402     prt("", row, 0);
403     put_str(_("[ 何かキーを押して下さい ]", "[Press any key to continue]"), row, _(26, 23));
404
405     (void)inkey();
406     prt("", row, 0);
407 }