OSDN Git Service

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