OSDN Git Service

upgrade to 3.6.2
[jnethack/source.git] / win / tty / getline.c
1 /* NetHack 3.6  getline.c       $NHDT-Date: 1543830347 2018/12/03 09:45:47 $  $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.37 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Michael Allison, 2006. */
4 /* NetHack may be freely redistributed.  See license for details. */
5
6 /*
7 **      Japanese version Copyright
8 **      For 3.4+, Copyright (c) Kentaro Shirakata, 2002-2015
9 **      JNetHack may be freely redistributed.  See license for details. 
10 */
11
12 #include "hack.h"
13
14 #ifdef TTY_GRAPHICS
15
16 #if !defined(MAC)
17 #define NEWAUTOCOMP
18 #endif
19
20 #include "wintty.h"
21 #include "func_tab.h"
22
23 char morc = 0; /* tell the outside world what char you chose */
24 STATIC_VAR boolean suppress_history;
25 STATIC_DCL boolean FDECL(ext_cmd_getlin_hook, (char *));
26
27 typedef boolean FDECL((*getlin_hook_proc), (char *));
28
29 STATIC_DCL void FDECL(hooked_tty_getlin,
30                       (const char *, char *, getlin_hook_proc));
31 extern int NDECL(extcmd_via_menu); /* cmd.c */
32
33 extern char erase_char, kill_char; /* from appropriate tty.c file */
34
35 /*
36  * Read a line closed with '\n' into the array char bufp[BUFSZ].
37  * (The '\n' is not stored. The string is closed with a '\0'.)
38  * Reading can be interrupted by an escape ('\033') - now the
39  * resulting string is "\033".
40  */
41 void
42 tty_getlin(query, bufp)
43 const char *query;
44 register char *bufp;
45 {
46     suppress_history = FALSE;
47     hooked_tty_getlin(query, bufp, (getlin_hook_proc) 0);
48 }
49
50 STATIC_OVL void
51 /*JP
52 hooked_tty_getlin(query, bufp, hook)
53 */
54 hooked_tty_getlin(query, bfp, hook)
55 const char *query;
56 /*JP
57 register char *bufp;
58 */
59 register char *bfp;
60 getlin_hook_proc hook;
61 {
62 #if 1 /*JP*/
63     char tmp[BUFSZ];
64     char *bufp = tmp;
65 #endif
66     register char *obufp = bufp;
67 /*JP
68     register int c;
69 */
70     int c;
71     struct WinDesc *cw = wins[WIN_MESSAGE];
72     boolean doprev = 0;
73 #if 1 /*JP*/
74     unsigned int uc;
75 #endif
76
77     if (ttyDisplay->toplin == 1 && !(cw->flags & WIN_STOP))
78         more();
79     cw->flags &= ~WIN_STOP;
80     ttyDisplay->toplin = 3; /* special prompt state */
81     ttyDisplay->inread++;
82
83     /* issue the prompt */
84     custompline(OVERRIDE_MSGTYPE | SUPPRESS_HISTORY, "%s ", query);
85 #ifdef EDIT_GETLIN
86     /* bufp is input/output; treat current contents (presumed to be from
87        previous getlin()) as default input */
88     addtopl(obufp);
89     bufp = eos(obufp);
90 #else
91     /* !EDIT_GETLIN: bufp is output only; init it to empty */
92     *bufp = '\0';
93 #endif
94
95     for (;;) {
96         (void) fflush(stdout);
97         Strcat(strcat(strcpy(toplines, query), " "), obufp);
98         c = pgetchar();
99 #if 1 /*JP*/
100         uc = (*((unsigned int *)&c));
101         uc &= 0377;
102 #endif
103         if (c == '\033' || c == EOF) {
104             if (c == '\033' && obufp[0] != '\0') {
105                 obufp[0] = '\0';
106                 bufp = obufp;
107                 tty_clear_nhwindow(WIN_MESSAGE);
108                 cw->maxcol = cw->maxrow;
109                 addtopl(query);
110                 addtopl(" ");
111                 addtopl(obufp);
112             } else {
113                 obufp[0] = '\033';
114                 obufp[1] = '\0';
115                 break;
116             }
117         }
118         if (ttyDisplay->intr) {
119             ttyDisplay->intr--;
120             *bufp = 0;
121         }
122         if (c == '\020') { /* ctrl-P */
123             if (iflags.prevmsg_window != 's') {
124                 int sav = ttyDisplay->inread;
125
126                 ttyDisplay->inread = 0;
127                 (void) tty_doprev_message();
128                 ttyDisplay->inread = sav;
129                 tty_clear_nhwindow(WIN_MESSAGE);
130                 cw->maxcol = cw->maxrow;
131                 addtopl(query);
132                 addtopl(" ");
133                 *bufp = 0;
134                 addtopl(obufp);
135             } else {
136                 if (!doprev)
137                     (void) tty_doprev_message(); /* need two initially */
138                 (void) tty_doprev_message();
139                 doprev = 1;
140                 continue;
141             }
142         } else if (doprev && iflags.prevmsg_window == 's') {
143             tty_clear_nhwindow(WIN_MESSAGE);
144             cw->maxcol = cw->maxrow;
145             doprev = 0;
146             addtopl(query);
147             addtopl(" ");
148             *bufp = 0;
149             addtopl(obufp);
150         }
151         if (c == erase_char || c == '\b') {
152 #if 1 /*JP*/
153         moreback:
154 #endif
155             if (bufp != obufp) {
156 #ifdef NEWAUTOCOMP
157                 char *i;
158
159 #endif /* NEWAUTOCOMP */
160                 bufp--;
161 #ifndef NEWAUTOCOMP
162                 putsyms("\b \b"); /* putsym converts \b */
163 #else                             /* NEWAUTOCOMP */
164                 putsyms("\b");
165                 for (i = bufp; *i; ++i)
166                     putsyms(" ");
167                 for (; i > bufp; --i)
168                     putsyms("\b");
169                 *bufp = 0;
170 #endif                            /* NEWAUTOCOMP */
171             } else
172                 tty_nhbell();
173 #if 1 /*JP*/
174             {
175                 int n;
176                 n = offset_in_kanji((unsigned char *)tmp, bufp - tmp);
177                 if (n > 0) {
178                     /* \8cã\82Å1\83o\83C\83g\88ø\82©\82ê\82é\82Ì\82Å\82»\82Ì\95ª\82Í\82±\82±\82Å\82Í\88ø\82©\82È\82¢ */
179                     bufp = bufp - (n - 1);
180                     goto moreback;
181                 }
182             }
183 #endif
184         } else if (c == '\n' || c == '\r') {
185 #ifndef NEWAUTOCOMP
186             *bufp = 0;
187 #endif /* not NEWAUTOCOMP */
188             break;
189 #if 0 /*JP*/
190         } else if (' ' <= (unsigned char) c && c != '\177'
191 #else
192         } else if (' ' <= uc && uc < 255
193 #endif
194                    /* avoid isprint() - some people don't have it
195                       ' ' is not always a printing char */
196                    && (bufp - obufp < BUFSZ - 1 && bufp - obufp < COLNO)) {
197 #ifdef NEWAUTOCOMP
198             char *i = eos(bufp);
199
200 #endif /* NEWAUTOCOMP */
201             *bufp = c;
202             bufp[1] = 0;
203 #if 0 /*JP*/
204             putsyms(bufp);
205 #else
206             raw_putsyms(bufp);
207 #endif
208             bufp++;
209             if (hook && (*hook)(obufp)) {
210 #if 0 /*JP*/
211                 putsyms(bufp);
212 #else
213                 raw_putsyms(bufp);
214 #endif
215 #ifndef NEWAUTOCOMP
216                 bufp = eos(bufp);
217 #else  /* NEWAUTOCOMP */
218                 /* pointer and cursor left where they were */
219                 for (i = bufp; *i; ++i)
220                     putsyms("\b");
221             } else if (i > bufp) {
222                 char *s = i;
223
224                 /* erase rest of prior guess */
225                 for (; i > bufp; --i)
226                     putsyms(" ");
227                 for (; s > bufp; --s)
228                     putsyms("\b");
229 #endif /* NEWAUTOCOMP */
230             }
231         } else if (c == kill_char || c == '\177') { /* Robert Viduya */
232             /* this test last - @ might be the kill_char */
233 #ifndef NEWAUTOCOMP
234             while (bufp != obufp) {
235                 bufp--;
236                 putsyms("\b \b");
237             }
238 #else  /* NEWAUTOCOMP */
239             for (; *bufp; ++bufp)
240                 putsyms(" ");
241             for (; bufp != obufp; --bufp)
242                 putsyms("\b \b");
243             *bufp = 0;
244 #endif /* NEWAUTOCOMP */
245         } else
246             tty_nhbell();
247     }
248     ttyDisplay->toplin = 2; /* nonempty, no --More-- required */
249     ttyDisplay->inread--;
250     clear_nhwindow(WIN_MESSAGE); /* clean up after ourselves */
251 #if 1 /*JP*/
252     Strcpy(bfp, str2ic(tmp));
253 #endif
254
255     if (suppress_history) {
256         /* prevent next message from pushing current query+answer into
257            tty message history */
258         *toplines = '\0';
259 #ifdef DUMPLOG
260     } else {
261         /* needed because we've bypassed pline() */
262         dumplogmsg(toplines);
263 #endif
264     }
265 }
266
267 void
268 xwaitforspace(s)
269 register const char *s; /* chars allowed besides return */
270 {
271     register int c, x = ttyDisplay ? (int) ttyDisplay->dismiss_more : '\n';
272
273     morc = 0;
274     while (
275 #ifdef HANGUPHANDLING
276         !program_state.done_hup &&
277 #endif
278         (c = tty_nhgetch()) != EOF) {
279         if (c == '\n' || c == '\r')
280             break;
281
282         if (iflags.cbreak) {
283             if (c == '\033') {
284                 if (ttyDisplay)
285                     ttyDisplay->dismiss_more = 1;
286                 morc = '\033';
287                 break;
288             }
289             if ((s && index(s, c)) || c == x || (x == '\n' && c == '\r')) {
290                 morc = (char) c;
291                 break;
292             }
293             tty_nhbell();
294         }
295     }
296 }
297
298 /*
299  * Implement extended command completion by using this hook into
300  * tty_getlin.  Check the characters already typed, if they uniquely
301  * identify an extended command, expand the string to the whole
302  * command.
303  *
304  * Return TRUE if we've extended the string at base.  Otherwise return FALSE.
305  * Assumptions:
306  *
307  *      + we don't change the characters that are already in base
308  *      + base has enough room to hold our string
309  */
310 STATIC_OVL boolean
311 ext_cmd_getlin_hook(base)
312 char *base;
313 {
314     int oindex, com_index;
315
316     com_index = -1;
317     for (oindex = 0; extcmdlist[oindex].ef_txt != (char *) 0; oindex++) {
318         if (extcmdlist[oindex].flags & CMD_NOT_AVAILABLE)
319             continue;
320         if ((extcmdlist[oindex].flags & AUTOCOMPLETE)
321             && !(!wizard && (extcmdlist[oindex].flags & WIZMODECMD))
322             && !strncmpi(base, extcmdlist[oindex].ef_txt, strlen(base))) {
323             if (com_index == -1) /* no matches yet */
324                 com_index = oindex;
325             else /* more than 1 match */
326                 return FALSE;
327         }
328     }
329     if (com_index >= 0) {
330         Strcpy(base, extcmdlist[com_index].ef_txt);
331         return TRUE;
332     }
333
334     return FALSE; /* didn't match anything */
335 }
336
337 /*
338  * Read in an extended command, doing command line completion.  We
339  * stop when we have found enough characters to make a unique command.
340  */
341 int
342 tty_get_ext_cmd()
343 {
344     int i;
345     char buf[BUFSZ];
346
347     if (iflags.extmenu)
348         return extcmd_via_menu();
349
350     suppress_history = TRUE;
351     /* maybe a runtime option?
352      * hooked_tty_getlin("#", buf,
353      *                   (flags.cmd_comp && !in_doagain)
354      *                      ? ext_cmd_getlin_hook
355      *                      : (getlin_hook_proc) 0);
356      */
357     buf[0] = '\0';
358     hooked_tty_getlin("#", buf, in_doagain ? (getlin_hook_proc) 0
359                                            : ext_cmd_getlin_hook);
360     (void) mungspaces(buf);
361     if (buf[0] == 0 || buf[0] == '\033')
362         return -1;
363
364     for (i = 0; extcmdlist[i].ef_txt != (char *) 0; i++)
365         if (!strcmpi(buf, extcmdlist[i].ef_txt))
366             break;
367
368     if (!in_doagain) {
369         int j;
370         for (j = 0; buf[j]; j++)
371             savech(buf[j]);
372         savech('\n');
373     }
374
375     if (extcmdlist[i].ef_txt == (char *) 0) {
376 /*JP
377         pline("%s: unknown extended command.", buf);
378 */
379         pline("%s:\8ag\92£\83R\83}\83\93\83h\83G\83\89\81[", buf);
380         i = -1;
381     }
382
383     return i;
384 }
385
386 #endif /* TTY_GRAPHICS */
387
388 /*getline.c*/