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