OSDN Git Service

import nethack-3.6.0
[jnethack/source.git] / win / tty / getline.c
1 /* NetHack 3.6  getline.c       $NHDT-Date: 1432512813 2015/05/25 00:13:33 $  $NHDT-Branch: master $:$NHDT-Revision: 1.28 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed.  See license for details. */
4
5 #include "hack.h"
6
7 #ifdef TTY_GRAPHICS
8
9 #if !defined(MAC)
10 #define NEWAUTOCOMP
11 #endif
12
13 #include "wintty.h"
14 #include "func_tab.h"
15
16 char morc = 0; /* tell the outside world what char you chose */
17 STATIC_DCL boolean FDECL(ext_cmd_getlin_hook, (char *));
18
19 typedef boolean FDECL((*getlin_hook_proc), (char *));
20
21 STATIC_DCL void FDECL(hooked_tty_getlin,
22                       (const char *, char *, getlin_hook_proc));
23 extern int NDECL(extcmd_via_menu); /* cmd.c */
24
25 extern char erase_char, kill_char; /* from appropriate tty.c file */
26
27 /*
28  * Read a line closed with '\n' into the array char bufp[BUFSZ].
29  * (The '\n' is not stored. The string is closed with a '\0'.)
30  * Reading can be interrupted by an escape ('\033') - now the
31  * resulting string is "\033".
32  */
33 void
34 tty_getlin(query, bufp)
35 const char *query;
36 register char *bufp;
37 {
38     hooked_tty_getlin(query, bufp, (getlin_hook_proc) 0);
39 }
40
41 STATIC_OVL void
42 hooked_tty_getlin(query, bufp, hook)
43 const char *query;
44 register char *bufp;
45 getlin_hook_proc hook;
46 {
47     register char *obufp = bufp;
48     register int c;
49     struct WinDesc *cw = wins[WIN_MESSAGE];
50     boolean doprev = 0;
51
52     if (ttyDisplay->toplin == 1 && !(cw->flags & WIN_STOP))
53         more();
54     cw->flags &= ~WIN_STOP;
55     ttyDisplay->toplin = 3; /* special prompt state */
56     ttyDisplay->inread++;
57     pline("%s ", query);
58     *obufp = 0;
59     for (;;) {
60         (void) fflush(stdout);
61         Strcat(strcat(strcpy(toplines, query), " "), obufp);
62         c = pgetchar();
63         if (c == '\033' || c == EOF) {
64             if (c == '\033' && obufp[0] != '\0') {
65                 obufp[0] = '\0';
66                 bufp = obufp;
67                 tty_clear_nhwindow(WIN_MESSAGE);
68                 cw->maxcol = cw->maxrow;
69                 addtopl(query);
70                 addtopl(" ");
71                 addtopl(obufp);
72             } else {
73                 obufp[0] = '\033';
74                 obufp[1] = '\0';
75                 break;
76             }
77         }
78         if (ttyDisplay->intr) {
79             ttyDisplay->intr--;
80             *bufp = 0;
81         }
82         if (c == '\020') { /* ctrl-P */
83             if (iflags.prevmsg_window != 's') {
84                 int sav = ttyDisplay->inread;
85                 ttyDisplay->inread = 0;
86                 (void) tty_doprev_message();
87                 ttyDisplay->inread = sav;
88                 tty_clear_nhwindow(WIN_MESSAGE);
89                 cw->maxcol = cw->maxrow;
90                 addtopl(query);
91                 addtopl(" ");
92                 *bufp = 0;
93                 addtopl(obufp);
94             } else {
95                 if (!doprev)
96                     (void) tty_doprev_message(); /* need two initially */
97                 (void) tty_doprev_message();
98                 doprev = 1;
99                 continue;
100             }
101         } else if (doprev && iflags.prevmsg_window == 's') {
102             tty_clear_nhwindow(WIN_MESSAGE);
103             cw->maxcol = cw->maxrow;
104             doprev = 0;
105             addtopl(query);
106             addtopl(" ");
107             *bufp = 0;
108             addtopl(obufp);
109         }
110         if (c == erase_char || c == '\b') {
111             if (bufp != obufp) {
112 #ifdef NEWAUTOCOMP
113                 char *i;
114
115 #endif /* NEWAUTOCOMP */
116                 bufp--;
117 #ifndef NEWAUTOCOMP
118                 putsyms("\b \b"); /* putsym converts \b */
119 #else                             /* NEWAUTOCOMP */
120                 putsyms("\b");
121                 for (i = bufp; *i; ++i)
122                     putsyms(" ");
123                 for (; i > bufp; --i)
124                     putsyms("\b");
125                 *bufp = 0;
126 #endif                            /* NEWAUTOCOMP */
127             } else
128                 tty_nhbell();
129 #if defined(apollo)
130         } else if (c == '\n' || c == '\r') {
131 #else
132         } else if (c == '\n') {
133 #endif
134 #ifndef NEWAUTOCOMP
135             *bufp = 0;
136 #endif /* not NEWAUTOCOMP */
137             break;
138         } else if (' ' <= (unsigned char) c && c != '\177'
139                    && (bufp - obufp < BUFSZ - 1 && bufp - obufp < COLNO)) {
140 /* avoid isprint() - some people don't have it
141    ' ' is not always a printing char */
142 #ifdef NEWAUTOCOMP
143             char *i = eos(bufp);
144
145 #endif /* NEWAUTOCOMP */
146             *bufp = c;
147             bufp[1] = 0;
148             putsyms(bufp);
149             bufp++;
150             if (hook && (*hook)(obufp)) {
151                 putsyms(bufp);
152 #ifndef NEWAUTOCOMP
153                 bufp = eos(bufp);
154 #else  /* NEWAUTOCOMP */
155                 /* pointer and cursor left where they were */
156                 for (i = bufp; *i; ++i)
157                     putsyms("\b");
158             } else if (i > bufp) {
159                 char *s = i;
160
161                 /* erase rest of prior guess */
162                 for (; i > bufp; --i)
163                     putsyms(" ");
164                 for (; s > bufp; --s)
165                     putsyms("\b");
166 #endif /* NEWAUTOCOMP */
167             }
168         } else if (c == kill_char || c == '\177') { /* Robert Viduya */
169 /* this test last - @ might be the kill_char */
170 #ifndef NEWAUTOCOMP
171             while (bufp != obufp) {
172                 bufp--;
173                 putsyms("\b \b");
174             }
175 #else  /* NEWAUTOCOMP */
176             for (; *bufp; ++bufp)
177                 putsyms(" ");
178             for (; bufp != obufp; --bufp)
179                 putsyms("\b \b");
180             *bufp = 0;
181 #endif /* NEWAUTOCOMP */
182         } else
183             tty_nhbell();
184     }
185     ttyDisplay->toplin = 2; /* nonempty, no --More-- required */
186     ttyDisplay->inread--;
187     clear_nhwindow(WIN_MESSAGE); /* clean up after ourselves */
188 }
189
190 void
191 xwaitforspace(s)
192 register const char *s; /* chars allowed besides return */
193 {
194     register int c, x = ttyDisplay ? (int) ttyDisplay->dismiss_more : '\n';
195
196     morc = 0;
197     while (
198 #ifdef HANGUPHANDLING
199         !program_state.done_hup &&
200 #endif
201         (c = tty_nhgetch()) != EOF) {
202         if (c == '\n')
203             break;
204
205         if (iflags.cbreak) {
206             if (c == '\033') {
207                 if (ttyDisplay)
208                     ttyDisplay->dismiss_more = 1;
209                 morc = '\033';
210                 break;
211             }
212             if ((s && index(s, c)) || c == x) {
213                 morc = (char) c;
214                 break;
215             }
216             tty_nhbell();
217         }
218     }
219 }
220
221 /*
222  * Implement extended command completion by using this hook into
223  * tty_getlin.  Check the characters already typed, if they uniquely
224  * identify an extended command, expand the string to the whole
225  * command.
226  *
227  * Return TRUE if we've extended the string at base.  Otherwise return FALSE.
228  * Assumptions:
229  *
230  *      + we don't change the characters that are already in base
231  *      + base has enough room to hold our string
232  */
233 STATIC_OVL boolean
234 ext_cmd_getlin_hook(base)
235 char *base;
236 {
237     int oindex, com_index;
238
239     com_index = -1;
240     for (oindex = 0; extcmdlist[oindex].ef_txt != (char *) 0; oindex++) {
241         if (!strncmpi(base, extcmdlist[oindex].ef_txt, strlen(base))) {
242             if (com_index == -1) /* no matches yet */
243                 com_index = oindex;
244             else /* more than 1 match */
245                 return FALSE;
246         }
247     }
248     if (com_index >= 0) {
249         Strcpy(base, extcmdlist[com_index].ef_txt);
250         return TRUE;
251     }
252
253     return FALSE; /* didn't match anything */
254 }
255
256 /*
257  * Read in an extended command, doing command line completion.  We
258  * stop when we have found enough characters to make a unique command.
259  */
260 int
261 tty_get_ext_cmd()
262 {
263     int i;
264     char buf[BUFSZ];
265
266     if (iflags.extmenu)
267         return extcmd_via_menu();
268     /* maybe a runtime option? */
269     /* hooked_tty_getlin("#", buf, flags.cmd_comp ? ext_cmd_getlin_hook :
270      * (getlin_hook_proc) 0); */
271     hooked_tty_getlin("#", buf, in_doagain ? (getlin_hook_proc) 0
272                                            : ext_cmd_getlin_hook);
273     (void) mungspaces(buf);
274     if (buf[0] == 0 || buf[0] == '\033')
275         return -1;
276
277     for (i = 0; extcmdlist[i].ef_txt != (char *) 0; i++)
278         if (!strcmpi(buf, extcmdlist[i].ef_txt))
279             break;
280
281     if (!in_doagain) {
282         int j;
283         for (j = 0; buf[j]; j++)
284             savech(buf[j]);
285         savech('\n');
286     }
287
288     if (extcmdlist[i].ef_txt == (char *) 0) {
289         pline("%s: unknown extended command.", buf);
290         i = -1;
291     }
292
293     return i;
294 }
295
296 #endif /* TTY_GRAPHICS */
297
298 /*getline.c*/