OSDN Git Service

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