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