xref: /freebsd/contrib/tcsh/ed.inputl.c (revision 45e5710bbb3676c9d945e9df78019b2c58930a59)
145e5710bSMark Peek /* $Header: /p/tcsh/cvsroot/tcsh/ed.inputl.c,v 3.66 2006/11/29 22:32:24 christos Exp $ */
2c80476e4SDavid E. O'Brien /*
3c80476e4SDavid E. O'Brien  * ed.inputl.c: Input line handling.
4c80476e4SDavid E. O'Brien  */
5c80476e4SDavid E. O'Brien /*-
6c80476e4SDavid E. O'Brien  * Copyright (c) 1980, 1991 The Regents of the University of California.
7c80476e4SDavid E. O'Brien  * All rights reserved.
8c80476e4SDavid E. O'Brien  *
9c80476e4SDavid E. O'Brien  * Redistribution and use in source and binary forms, with or without
10c80476e4SDavid E. O'Brien  * modification, are permitted provided that the following conditions
11c80476e4SDavid E. O'Brien  * are met:
12c80476e4SDavid E. O'Brien  * 1. Redistributions of source code must retain the above copyright
13c80476e4SDavid E. O'Brien  *    notice, this list of conditions and the following disclaimer.
14c80476e4SDavid E. O'Brien  * 2. Redistributions in binary form must reproduce the above copyright
15c80476e4SDavid E. O'Brien  *    notice, this list of conditions and the following disclaimer in the
16c80476e4SDavid E. O'Brien  *    documentation and/or other materials provided with the distribution.
1729301572SMark Peek  * 3. Neither the name of the University nor the names of its contributors
18c80476e4SDavid E. O'Brien  *    may be used to endorse or promote products derived from this software
19c80476e4SDavid E. O'Brien  *    without specific prior written permission.
20c80476e4SDavid E. O'Brien  *
21c80476e4SDavid E. O'Brien  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22c80476e4SDavid E. O'Brien  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23c80476e4SDavid E. O'Brien  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24c80476e4SDavid E. O'Brien  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25c80476e4SDavid E. O'Brien  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26c80476e4SDavid E. O'Brien  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27c80476e4SDavid E. O'Brien  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28c80476e4SDavid E. O'Brien  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29c80476e4SDavid E. O'Brien  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30c80476e4SDavid E. O'Brien  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31c80476e4SDavid E. O'Brien  * SUCH DAMAGE.
32c80476e4SDavid E. O'Brien  */
33c80476e4SDavid E. O'Brien #include "sh.h"
34c80476e4SDavid E. O'Brien 
3545e5710bSMark Peek RCSID("$tcsh: ed.inputl.c,v 3.66 2006/11/29 22:32:24 christos Exp $")
36c80476e4SDavid E. O'Brien 
37c80476e4SDavid E. O'Brien #include "ed.h"
38c80476e4SDavid E. O'Brien #include "ed.defns.h"		/* for the function names */
39c80476e4SDavid E. O'Brien #include "tw.h"			/* for twenex stuff */
40c80476e4SDavid E. O'Brien 
4145e5710bSMark Peek #define OKCMD INT_MAX
42c80476e4SDavid E. O'Brien 
43c80476e4SDavid E. O'Brien /* ed.inputl -- routines to get a single line from the input. */
44c80476e4SDavid E. O'Brien 
4523338178SMark Peek extern int MapsAreInited;
46c80476e4SDavid E. O'Brien 
47c80476e4SDavid E. O'Brien /* mismatched first character */
48c80476e4SDavid E. O'Brien static Char mismatch[] =
49c80476e4SDavid E. O'Brien     {'!', '^' , '\\', '-', '%', '\0', '"', '\'', '`', '\0' };
50c80476e4SDavid E. O'Brien 
5145e5710bSMark Peek static	int	Repair		(void);
5245e5710bSMark Peek static	int	GetNextCommand	(KEYCMD *, Char *);
5345e5710bSMark Peek static	int	SpellLine	(int);
5445e5710bSMark Peek static	int	CompleteLine	(void);
5545e5710bSMark Peek static	void	RunCommand	(Char *);
5645e5710bSMark Peek static  void 	doeval1		(Char **);
57c80476e4SDavid E. O'Brien 
5823338178SMark Peek static int rotate = 0;
59c80476e4SDavid E. O'Brien 
60c80476e4SDavid E. O'Brien 
61c80476e4SDavid E. O'Brien static int
6245e5710bSMark Peek Repair(void)
63c80476e4SDavid E. O'Brien {
64c80476e4SDavid E. O'Brien     if (NeedsRedraw) {
65c80476e4SDavid E. O'Brien 	ClearLines();
66c80476e4SDavid E. O'Brien 	ClearDisp();
67c80476e4SDavid E. O'Brien 	NeedsRedraw = 0;
68c80476e4SDavid E. O'Brien     }
69c80476e4SDavid E. O'Brien     Refresh();
70c80476e4SDavid E. O'Brien     Argument = 1;
71c80476e4SDavid E. O'Brien     DoingArg = 0;
72c80476e4SDavid E. O'Brien     curchoice = -1;
73c80476e4SDavid E. O'Brien     return (int) (LastChar - InputBuf);
74c80476e4SDavid E. O'Brien }
75c80476e4SDavid E. O'Brien 
76c80476e4SDavid E. O'Brien /* CCRETVAL */
77c80476e4SDavid E. O'Brien int
7845e5710bSMark Peek Inputl(void)
79c80476e4SDavid E. O'Brien {
80c80476e4SDavid E. O'Brien     CCRETVAL retval;
81c80476e4SDavid E. O'Brien     KEYCMD  cmdnum = 0;
82c80476e4SDavid E. O'Brien     unsigned char tch;		/* the place where read() goes */
83c80476e4SDavid E. O'Brien     Char    ch;
84c80476e4SDavid E. O'Brien     int     num;		/* how many chars we have read at NL */
85c80476e4SDavid E. O'Brien     int	    expnum;
86c80476e4SDavid E. O'Brien     struct varent *crct = inheredoc ? NULL : adrof(STRcorrect);
87c80476e4SDavid E. O'Brien     struct varent *autol = adrof(STRautolist);
88c80476e4SDavid E. O'Brien     struct varent *matchbeep = adrof(STRmatchbeep);
89c80476e4SDavid E. O'Brien     struct varent *imode = adrof(STRinputmode);
90c80476e4SDavid E. O'Brien     Char   *SaveChar, *CorrChar;
91c80476e4SDavid E. O'Brien     int     matchval;		/* from tenematch() */
92c80476e4SDavid E. O'Brien     COMMAND fn;
93c80476e4SDavid E. O'Brien     int curlen = 0;
94c80476e4SDavid E. O'Brien     int newlen;
95c80476e4SDavid E. O'Brien     int idx;
96c80476e4SDavid E. O'Brien 
97c80476e4SDavid E. O'Brien     if (!MapsAreInited)		/* double extra just in case */
98c80476e4SDavid E. O'Brien 	ed_InitMaps();
99c80476e4SDavid E. O'Brien 
100c80476e4SDavid E. O'Brien     ClearDisp();		/* reset the display stuff */
101c80476e4SDavid E. O'Brien     ResetInLine(0);		/* reset the input pointers */
102c80476e4SDavid E. O'Brien     if (GettingInput)
103c80476e4SDavid E. O'Brien 	MacroLvl = -1;		/* editor was interrupted during input */
104c80476e4SDavid E. O'Brien 
10529301572SMark Peek     if (imode && imode->vec != NULL) {
106c80476e4SDavid E. O'Brien 	if (!Strcmp(*(imode->vec), STRinsert))
107c80476e4SDavid E. O'Brien 	    inputmode = MODE_INSERT;
108c80476e4SDavid E. O'Brien 	else if (!Strcmp(*(imode->vec), STRoverwrite))
109c80476e4SDavid E. O'Brien 	    inputmode = MODE_REPLACE;
110c80476e4SDavid E. O'Brien     }
111c80476e4SDavid E. O'Brien 
112c80476e4SDavid E. O'Brien #if defined(FIONREAD) && !defined(OREO)
113c80476e4SDavid E. O'Brien     if (!Tty_raw_mode && MacroLvl < 0) {
114c80476e4SDavid E. O'Brien # ifdef SUNOS4
115c80476e4SDavid E. O'Brien 	long chrs = 0;
116c80476e4SDavid E. O'Brien # else /* !SUNOS4 */
117c80476e4SDavid E. O'Brien 	/*
118c80476e4SDavid E. O'Brien 	 * *Everyone* else has an int, but SunOS wants long!
119c80476e4SDavid E. O'Brien 	 * This breaks where int != long (alpha)
120c80476e4SDavid E. O'Brien 	 */
121c80476e4SDavid E. O'Brien 	int chrs = 0;
122c80476e4SDavid E. O'Brien # endif /* SUNOS4 */
123c80476e4SDavid E. O'Brien 
124c80476e4SDavid E. O'Brien 	(void) ioctl(SHIN, FIONREAD, (ioctl_t) & chrs);
125c80476e4SDavid E. O'Brien 	if (chrs == 0) {
126c80476e4SDavid E. O'Brien 	    if (Rawmode() < 0)
127c80476e4SDavid E. O'Brien 		return 0;
128c80476e4SDavid E. O'Brien 	}
129c80476e4SDavid E. O'Brien     }
130c80476e4SDavid E. O'Brien #endif /* FIONREAD && !OREO */
131c80476e4SDavid E. O'Brien 
132c80476e4SDavid E. O'Brien     GettingInput = 1;
133c80476e4SDavid E. O'Brien     NeedsRedraw = 0;
134c80476e4SDavid E. O'Brien     tellwhat = 0;
13545e5710bSMark Peek 
13645e5710bSMark Peek     if (RestoreSaved) {
13745e5710bSMark Peek 	copyn(InputBuf, SavedBuf.s, INBUFSIZE);/*FIXBUF*/
13845e5710bSMark Peek 	LastChar = InputBuf + LastSaved;
13945e5710bSMark Peek 	Cursor = InputBuf + CursSaved;
14045e5710bSMark Peek 	Hist_num = HistSaved;
14145e5710bSMark Peek 	HistSaved = 0;
14245e5710bSMark Peek 	RestoreSaved = 0;
14345e5710bSMark Peek     }
14445e5710bSMark Peek     if (HistSaved) {
14545e5710bSMark Peek 	Hist_num = HistSaved;
14645e5710bSMark Peek 	GetHistLine();
14745e5710bSMark Peek 	HistSaved = 0;
148c80476e4SDavid E. O'Brien     }
149c80476e4SDavid E. O'Brien     if (Expand) {
150c80476e4SDavid E. O'Brien 	(void) e_up_hist(0);
151c80476e4SDavid E. O'Brien 	Expand = 0;
152c80476e4SDavid E. O'Brien     }
153c80476e4SDavid E. O'Brien     Refresh();			/* print the prompt */
154c80476e4SDavid E. O'Brien 
155c80476e4SDavid E. O'Brien     for (num = OKCMD; num == OKCMD;) {	/* while still editing this line */
156c80476e4SDavid E. O'Brien #ifdef DEBUG_EDIT
157c80476e4SDavid E. O'Brien 	if (Cursor > LastChar)
158c80476e4SDavid E. O'Brien 	    xprintf("Cursor > LastChar\r\n");
159c80476e4SDavid E. O'Brien 	if (Cursor < InputBuf)
160c80476e4SDavid E. O'Brien 	    xprintf("Cursor < InputBuf\r\n");
161c80476e4SDavid E. O'Brien 	if (Cursor > InputLim)
162c80476e4SDavid E. O'Brien 	    xprintf("Cursor > InputLim\r\n");
163c80476e4SDavid E. O'Brien 	if (LastChar > InputLim)
164c80476e4SDavid E. O'Brien 	    xprintf("LastChar > InputLim\r\n");
16545e5710bSMark Peek 	if (InputLim != &InputBuf[INBUFSIZE - 2])/*FIXBUF*/
166c80476e4SDavid E. O'Brien 	    xprintf("InputLim != &InputBuf[INBUFSIZE-2]\r\n");
167c80476e4SDavid E. O'Brien 	if ((!DoingArg) && (Argument != 1))
168c80476e4SDavid E. O'Brien 	    xprintf("(!DoingArg) && (Argument != 1)\r\n");
169c80476e4SDavid E. O'Brien 	if (CcKeyMap[0] == 0)
170c80476e4SDavid E. O'Brien 	    xprintf("CcKeyMap[0] == 0 (maybe not inited)\r\n");
171c80476e4SDavid E. O'Brien #endif
172c80476e4SDavid E. O'Brien 
173c80476e4SDavid E. O'Brien 	/* if EOF or error */
174c80476e4SDavid E. O'Brien 	if ((num = GetNextCommand(&cmdnum, &ch)) != OKCMD) {
175c80476e4SDavid E. O'Brien 	    break;
176c80476e4SDavid E. O'Brien 	}
177c80476e4SDavid E. O'Brien 
178c80476e4SDavid E. O'Brien 	if (cmdnum >= NumFuns) {/* BUG CHECK command */
179c80476e4SDavid E. O'Brien #ifdef DEBUG_EDIT
180c80476e4SDavid E. O'Brien 	    xprintf(CGETS(6, 1, "ERROR: illegal command from key 0%o\r\n"), ch);
181c80476e4SDavid E. O'Brien #endif
182c80476e4SDavid E. O'Brien 	    continue;		/* try again */
183c80476e4SDavid E. O'Brien 	}
184c80476e4SDavid E. O'Brien 
185c80476e4SDavid E. O'Brien 	/* now do the real command */
186c80476e4SDavid E. O'Brien 	retval = (*CcFuncTbl[cmdnum]) (ch);
187c80476e4SDavid E. O'Brien 
188c80476e4SDavid E. O'Brien 	/* save the last command here */
189c80476e4SDavid E. O'Brien 	LastCmd = cmdnum;
190c80476e4SDavid E. O'Brien 
191c80476e4SDavid E. O'Brien 	/* make sure fn is initialized */
192c80476e4SDavid E. O'Brien 	fn = (retval == CC_COMPLETE_ALL) ? LIST_ALL : LIST;
193c80476e4SDavid E. O'Brien 
194c80476e4SDavid E. O'Brien 	/* use any return value */
195c80476e4SDavid E. O'Brien 	switch (retval) {
196c80476e4SDavid E. O'Brien 
197c80476e4SDavid E. O'Brien 	case CC_REFRESH:
198c80476e4SDavid E. O'Brien 	    Refresh();
199c80476e4SDavid E. O'Brien 	    /*FALLTHROUGH*/
200c80476e4SDavid E. O'Brien 	case CC_NORM:		/* normal char */
201c80476e4SDavid E. O'Brien 	    Argument = 1;
202c80476e4SDavid E. O'Brien 	    DoingArg = 0;
203c80476e4SDavid E. O'Brien 	    /*FALLTHROUGH*/
204c80476e4SDavid E. O'Brien 	case CC_ARGHACK:	/* Suggested by Rich Salz */
205c80476e4SDavid E. O'Brien 	    /* <rsalz@pineapple.bbn.com> */
206c80476e4SDavid E. O'Brien 	    curchoice = -1;
207c80476e4SDavid E. O'Brien 	    curlen = (int) (LastChar - InputBuf);
208c80476e4SDavid E. O'Brien 	    break;		/* keep going... */
209c80476e4SDavid E. O'Brien 
210c80476e4SDavid E. O'Brien 	case CC_EOF:		/* end of file typed */
211c80476e4SDavid E. O'Brien 	    curchoice = -1;
212c80476e4SDavid E. O'Brien 	    curlen = (int) (LastChar - InputBuf);
213c80476e4SDavid E. O'Brien 	    num = 0;
214c80476e4SDavid E. O'Brien 	    break;
215c80476e4SDavid E. O'Brien 
216c80476e4SDavid E. O'Brien 	case CC_WHICH:		/* tell what this command does */
217c80476e4SDavid E. O'Brien 	    tellwhat = 1;
218c80476e4SDavid E. O'Brien 	    *LastChar++ = '\n';	/* for the benifit of CSH */
219c80476e4SDavid E. O'Brien 	    num = (int) (LastChar - InputBuf);	/* number characters read */
220c80476e4SDavid E. O'Brien 	    break;
221c80476e4SDavid E. O'Brien 
222c80476e4SDavid E. O'Brien 	case CC_NEWLINE:	/* normal end of line */
223c80476e4SDavid E. O'Brien 	    curlen = 0;
224c80476e4SDavid E. O'Brien 	    curchoice = -1;
225c80476e4SDavid E. O'Brien 	    matchval = 1;
22629301572SMark Peek 	    if (crct && crct->vec != NULL && (!Strcmp(*(crct->vec), STRcmd) ||
227c80476e4SDavid E. O'Brien 			 !Strcmp(*(crct->vec), STRall))) {
22845e5710bSMark Peek 		Char *Origin;
22945e5710bSMark Peek 
230c80476e4SDavid E. O'Brien                 PastBottom();
23145e5710bSMark Peek 		Origin = Strsave(InputBuf);
23245e5710bSMark Peek 		cleanup_push(Origin, xfree);
233c80476e4SDavid E. O'Brien 		SaveChar = LastChar;
234c80476e4SDavid E. O'Brien 		if (SpellLine(!Strcmp(*(crct->vec), STRcmd)) == 1) {
23545e5710bSMark Peek 		    Char *Change;
23645e5710bSMark Peek 
237c80476e4SDavid E. O'Brien                     PastBottom();
23845e5710bSMark Peek 		    Change = Strsave(InputBuf);
23945e5710bSMark Peek 		    cleanup_push(Change, xfree);
240c80476e4SDavid E. O'Brien 		    *Strchr(Change, '\n') = '\0';
241c80476e4SDavid E. O'Brien 		    CorrChar = LastChar;	/* Save the corrected end */
242c80476e4SDavid E. O'Brien 		    LastChar = InputBuf;	/* Null the current line */
243c80476e4SDavid E. O'Brien 		    SoundBeep();
244c80476e4SDavid E. O'Brien 		    printprompt(2, short2str(Change));
24545e5710bSMark Peek 		    cleanup_until(Change);
246c80476e4SDavid E. O'Brien 		    Refresh();
24745e5710bSMark Peek 		    if (xread(SHIN, &tch, 1) < 0) {
248c80476e4SDavid E. O'Brien #ifdef convex
249c80476e4SDavid E. O'Brien 		        /*
250c80476e4SDavid E. O'Brien 			 * need to print error message in case file
251c80476e4SDavid E. O'Brien 			 * is migrated
252c80476e4SDavid E. O'Brien 			 */
25345e5710bSMark Peek                         if (errno)
254c80476e4SDavid E. O'Brien                             stderror(ERR_SYSTEM, progname, strerror(errno));
255c80476e4SDavid E. O'Brien #else
25645e5710bSMark Peek 			cleanup_until(Origin);
257c80476e4SDavid E. O'Brien 			break;
258c80476e4SDavid E. O'Brien #endif
25945e5710bSMark Peek 		    }
260c80476e4SDavid E. O'Brien 		    ch = tch;
261c80476e4SDavid E. O'Brien 		    if (ch == 'y' || ch == ' ') {
262c80476e4SDavid E. O'Brien 			LastChar = CorrChar;	/* Restore the corrected end */
263c80476e4SDavid E. O'Brien 			xprintf(CGETS(6, 2, "yes\n"));
264c80476e4SDavid E. O'Brien 		    }
265c80476e4SDavid E. O'Brien 		    else {
26645e5710bSMark Peek 			Strcpy(InputBuf, Origin);
267c80476e4SDavid E. O'Brien 			LastChar = SaveChar;
268c80476e4SDavid E. O'Brien 			if (ch == 'e') {
269c80476e4SDavid E. O'Brien 			    xprintf(CGETS(6, 3, "edit\n"));
270c80476e4SDavid E. O'Brien 			    *LastChar-- = '\0';
271c80476e4SDavid E. O'Brien 			    Cursor = LastChar;
272c80476e4SDavid E. O'Brien 			    printprompt(3, NULL);
273c80476e4SDavid E. O'Brien 			    ClearLines();
274c80476e4SDavid E. O'Brien 			    ClearDisp();
275c80476e4SDavid E. O'Brien 			    Refresh();
27645e5710bSMark Peek 			    cleanup_until(Origin);
277c80476e4SDavid E. O'Brien 			    break;
278c80476e4SDavid E. O'Brien 			}
279c80476e4SDavid E. O'Brien 			else if (ch == 'a') {
280c80476e4SDavid E. O'Brien 			    xprintf(CGETS(6, 4, "abort\n"));
281c80476e4SDavid E. O'Brien 		            LastChar = InputBuf;   /* Null the current line */
282c80476e4SDavid E. O'Brien 			    Cursor = LastChar;
283c80476e4SDavid E. O'Brien 			    printprompt(0, NULL);
284c80476e4SDavid E. O'Brien 			    Refresh();
28545e5710bSMark Peek 			    cleanup_until(Origin);
286c80476e4SDavid E. O'Brien 			    break;
287c80476e4SDavid E. O'Brien 			}
288c80476e4SDavid E. O'Brien 			xprintf(CGETS(6, 5, "no\n"));
289c80476e4SDavid E. O'Brien 		    }
290c80476e4SDavid E. O'Brien 		    flush();
291c80476e4SDavid E. O'Brien 		}
29245e5710bSMark Peek 		cleanup_until(Origin);
29329301572SMark Peek 	    } else if (crct && crct->vec != NULL &&
29429301572SMark Peek 		!Strcmp(*(crct->vec), STRcomplete)) {
295c80476e4SDavid E. O'Brien                 if (LastChar > InputBuf && LastChar[-1] == '\n') {
296c80476e4SDavid E. O'Brien                     LastChar[-1] = '\0';
297c80476e4SDavid E. O'Brien                     LastChar--;
298c80476e4SDavid E. O'Brien                     Cursor = LastChar;
299c80476e4SDavid E. O'Brien                 }
300c80476e4SDavid E. O'Brien                 match_unique_match = 1;  /* match unique matches */
301c80476e4SDavid E. O'Brien 		matchval = CompleteLine();
302c80476e4SDavid E. O'Brien                 match_unique_match = 0;
303c80476e4SDavid E. O'Brien         	curlen = (int) (LastChar - InputBuf);
304c80476e4SDavid E. O'Brien 		if (matchval != 1) {
305c80476e4SDavid E. O'Brien                     PastBottom();
306c80476e4SDavid E. O'Brien 		}
307c80476e4SDavid E. O'Brien 		if (matchval == 0) {
308c80476e4SDavid E. O'Brien 		    xprintf(CGETS(6, 6, "No matching command\n"));
309c80476e4SDavid E. O'Brien 		} else if (matchval == 2) {
310c80476e4SDavid E. O'Brien 		    xprintf(CGETS(6, 7, "Ambiguous command\n"));
311c80476e4SDavid E. O'Brien 		}
312c80476e4SDavid E. O'Brien 	        if (NeedsRedraw) {
313c80476e4SDavid E. O'Brien 		    ClearLines();
314c80476e4SDavid E. O'Brien 		    ClearDisp();
315c80476e4SDavid E. O'Brien 		    NeedsRedraw = 0;
316c80476e4SDavid E. O'Brien 	        }
317c80476e4SDavid E. O'Brien 	        Refresh();
318c80476e4SDavid E. O'Brien 	        Argument = 1;
319c80476e4SDavid E. O'Brien 	        DoingArg = 0;
320c80476e4SDavid E. O'Brien 		if (matchval == 1) {
321c80476e4SDavid E. O'Brien                     PastBottom();
322c80476e4SDavid E. O'Brien                     *LastChar++ = '\n';
323c80476e4SDavid E. O'Brien                     *LastChar = '\0';
324c80476e4SDavid E. O'Brien 		}
325c80476e4SDavid E. O'Brien         	curlen = (int) (LastChar - InputBuf);
326c80476e4SDavid E. O'Brien             }
327c80476e4SDavid E. O'Brien 	    else
328c80476e4SDavid E. O'Brien 		PastBottom();
329c80476e4SDavid E. O'Brien 
330c80476e4SDavid E. O'Brien 	    if (matchval == 1) {
331c80476e4SDavid E. O'Brien 	        tellwhat = 0;	/* just in case */
332c80476e4SDavid E. O'Brien 	        Hist_num = 0;	/* for the history commands */
333c80476e4SDavid E. O'Brien 		/* return the number of chars read */
334c80476e4SDavid E. O'Brien 	        num = (int) (LastChar - InputBuf);
335c80476e4SDavid E. O'Brien 	        /*
336c80476e4SDavid E. O'Brien 	         * For continuation lines, we set the prompt to prompt 2
337c80476e4SDavid E. O'Brien 	         */
338c80476e4SDavid E. O'Brien 	        printprompt(1, NULL);
339c80476e4SDavid E. O'Brien 	    }
340c80476e4SDavid E. O'Brien 	    break;
341c80476e4SDavid E. O'Brien 
342c80476e4SDavid E. O'Brien 	case CC_CORRECT:
343c80476e4SDavid E. O'Brien 	    if (tenematch(InputBuf, Cursor - InputBuf, SPELL) < 0)
344c80476e4SDavid E. O'Brien 		SoundBeep();		/* Beep = No match/ambiguous */
345c80476e4SDavid E. O'Brien 	    curlen = Repair();
346c80476e4SDavid E. O'Brien 	    break;
347c80476e4SDavid E. O'Brien 
348c80476e4SDavid E. O'Brien 	case CC_CORRECT_L:
349c80476e4SDavid E. O'Brien 	    if (SpellLine(FALSE) < 0)
350c80476e4SDavid E. O'Brien 		SoundBeep();		/* Beep = No match/ambiguous */
351c80476e4SDavid E. O'Brien 	    curlen = Repair();
352c80476e4SDavid E. O'Brien 	    break;
353c80476e4SDavid E. O'Brien 
354c80476e4SDavid E. O'Brien 
355c80476e4SDavid E. O'Brien 	case CC_COMPLETE:
356c80476e4SDavid E. O'Brien 	case CC_COMPLETE_ALL:
357c80476e4SDavid E. O'Brien 	case CC_COMPLETE_FWD:
358c80476e4SDavid E. O'Brien 	case CC_COMPLETE_BACK:
359c80476e4SDavid E. O'Brien 	    switch (retval) {
360c80476e4SDavid E. O'Brien 	    case CC_COMPLETE:
361c80476e4SDavid E. O'Brien 		fn = RECOGNIZE;
362c80476e4SDavid E. O'Brien 		curlen = (int) (LastChar - InputBuf);
363c80476e4SDavid E. O'Brien 		curchoice = -1;
364c80476e4SDavid E. O'Brien 		rotate = 0;
365c80476e4SDavid E. O'Brien 		break;
366c80476e4SDavid E. O'Brien 	    case CC_COMPLETE_ALL:
367c80476e4SDavid E. O'Brien 		fn = RECOGNIZE_ALL;
368c80476e4SDavid E. O'Brien 		curlen = (int) (LastChar - InputBuf);
369c80476e4SDavid E. O'Brien 		curchoice = -1;
370c80476e4SDavid E. O'Brien 		rotate = 0;
371c80476e4SDavid E. O'Brien 		break;
372c80476e4SDavid E. O'Brien 	    case CC_COMPLETE_FWD:
373c80476e4SDavid E. O'Brien 		fn = RECOGNIZE_SCROLL;
374c80476e4SDavid E. O'Brien 		curchoice++;
375c80476e4SDavid E. O'Brien 		rotate = 1;
376c80476e4SDavid E. O'Brien 		break;
377c80476e4SDavid E. O'Brien 	    case CC_COMPLETE_BACK:
378c80476e4SDavid E. O'Brien 		fn = RECOGNIZE_SCROLL;
379c80476e4SDavid E. O'Brien 		curchoice--;
380c80476e4SDavid E. O'Brien 		rotate = 1;
381c80476e4SDavid E. O'Brien 		break;
382c80476e4SDavid E. O'Brien 	    default:
383c80476e4SDavid E. O'Brien 		abort();
384c80476e4SDavid E. O'Brien 	    }
385c80476e4SDavid E. O'Brien 	    if (InputBuf[curlen] && rotate) {
386c80476e4SDavid E. O'Brien 		newlen = (int) (LastChar - InputBuf);
387c80476e4SDavid E. O'Brien 		for (idx = (int) (Cursor - InputBuf);
388c80476e4SDavid E. O'Brien 		     idx <= newlen; idx++)
389c80476e4SDavid E. O'Brien 			InputBuf[idx - newlen + curlen] =
390c80476e4SDavid E. O'Brien 			InputBuf[idx];
391c80476e4SDavid E. O'Brien 		LastChar = InputBuf + curlen;
392c80476e4SDavid E. O'Brien 		Cursor = Cursor - newlen + curlen;
393c80476e4SDavid E. O'Brien 	    }
394c80476e4SDavid E. O'Brien 	    curlen = (int) (LastChar - InputBuf);
395c80476e4SDavid E. O'Brien 
396c80476e4SDavid E. O'Brien 
397c80476e4SDavid E. O'Brien 	    if (adrof(STRautoexpand))
398c80476e4SDavid E. O'Brien 		(void) e_expand_history(0);
399c80476e4SDavid E. O'Brien 	    /*
400c80476e4SDavid E. O'Brien 	     * Modified by Martin Boyer (gamin@ireq-robot.hydro.qc.ca):
401c80476e4SDavid E. O'Brien 	     * A separate variable now controls beeping after
402c80476e4SDavid E. O'Brien 	     * completion, independently of autolisting.
403c80476e4SDavid E. O'Brien 	     */
404c80476e4SDavid E. O'Brien 	    expnum = (int) (Cursor - InputBuf);
405c80476e4SDavid E. O'Brien 	    switch (matchval = tenematch(InputBuf, Cursor-InputBuf, fn)){
406c80476e4SDavid E. O'Brien 	    case 1:
40729301572SMark Peek 		if (non_unique_match && matchbeep && matchbeep->vec != NULL &&
408c80476e4SDavid E. O'Brien 		    (Strcmp(*(matchbeep->vec), STRnotunique) == 0))
409c80476e4SDavid E. O'Brien 		    SoundBeep();
410c80476e4SDavid E. O'Brien 		break;
411c80476e4SDavid E. O'Brien 	    case 0:
41229301572SMark Peek 		if (matchbeep && matchbeep->vec != NULL) {
413c80476e4SDavid E. O'Brien 		    if (Strcmp(*(matchbeep->vec), STRnomatch) == 0 ||
414c80476e4SDavid E. O'Brien 			Strcmp(*(matchbeep->vec), STRambiguous) == 0 ||
415c80476e4SDavid E. O'Brien 			Strcmp(*(matchbeep->vec), STRnotunique) == 0)
416c80476e4SDavid E. O'Brien 			SoundBeep();
417c80476e4SDavid E. O'Brien 		}
418c80476e4SDavid E. O'Brien 		else
419c80476e4SDavid E. O'Brien 		    SoundBeep();
420c80476e4SDavid E. O'Brien 		break;
421c80476e4SDavid E. O'Brien 	    default:
422c80476e4SDavid E. O'Brien 		if (matchval < 0) {	/* Error from tenematch */
423c80476e4SDavid E. O'Brien 		    curchoice = -1;
424c80476e4SDavid E. O'Brien 		    SoundBeep();
425c80476e4SDavid E. O'Brien 		    break;
426c80476e4SDavid E. O'Brien 		}
42729301572SMark Peek 		if (matchbeep && matchbeep->vec != NULL) {
428c80476e4SDavid E. O'Brien 		    if ((Strcmp(*(matchbeep->vec), STRambiguous) == 0 ||
429c80476e4SDavid E. O'Brien 			 Strcmp(*(matchbeep->vec), STRnotunique) == 0))
430c80476e4SDavid E. O'Brien 			SoundBeep();
431c80476e4SDavid E. O'Brien 		}
432c80476e4SDavid E. O'Brien 		else
433c80476e4SDavid E. O'Brien 		    SoundBeep();
434c80476e4SDavid E. O'Brien 		/*
435c80476e4SDavid E. O'Brien 		 * Addition by David C Lawrence <tale@pawl.rpi.edu>: If an
436c80476e4SDavid E. O'Brien 		 * attempted completion is ambiguous, list the choices.
437c80476e4SDavid E. O'Brien 		 * (PWP: this is the best feature addition to tcsh I have
438c80476e4SDavid E. O'Brien 		 * seen in many months.)
439c80476e4SDavid E. O'Brien 		 */
44029301572SMark Peek 		if (autol && autol->vec != NULL &&
44129301572SMark Peek 		    (Strcmp(*(autol->vec), STRambiguous) != 0 ||
442c80476e4SDavid E. O'Brien 				     expnum == Cursor - InputBuf)) {
44345e5710bSMark Peek 		    if (adrof(STRhighlight) && MarkIsSet) {
44445e5710bSMark Peek 			/* clear highlighting before showing completions */
44545e5710bSMark Peek 			MarkIsSet = 0;
44645e5710bSMark Peek 			ClearLines();
44745e5710bSMark Peek 			ClearDisp();
44845e5710bSMark Peek 			Refresh();
44945e5710bSMark Peek 			MarkIsSet = 1;
45045e5710bSMark Peek 		    }
451c80476e4SDavid E. O'Brien 		    PastBottom();
452c80476e4SDavid E. O'Brien 		    fn = (retval == CC_COMPLETE_ALL) ? LIST_ALL : LIST;
453c80476e4SDavid E. O'Brien 		    (void) tenematch(InputBuf, Cursor-InputBuf, fn);
454c80476e4SDavid E. O'Brien 		}
455c80476e4SDavid E. O'Brien 		break;
456c80476e4SDavid E. O'Brien 	    }
457c80476e4SDavid E. O'Brien 	    if (NeedsRedraw) {
458c80476e4SDavid E. O'Brien 		PastBottom();
459c80476e4SDavid E. O'Brien 		ClearLines();
460c80476e4SDavid E. O'Brien 		ClearDisp();
461c80476e4SDavid E. O'Brien 		NeedsRedraw = 0;
462c80476e4SDavid E. O'Brien 	    }
463c80476e4SDavid E. O'Brien 	    Refresh();
464c80476e4SDavid E. O'Brien 	    Argument = 1;
465c80476e4SDavid E. O'Brien 	    DoingArg = 0;
466c80476e4SDavid E. O'Brien 	    break;
467c80476e4SDavid E. O'Brien 
468c80476e4SDavid E. O'Brien 	case CC_LIST_CHOICES:
469c80476e4SDavid E. O'Brien 	case CC_LIST_ALL:
470c80476e4SDavid E. O'Brien 	    if (InputBuf[curlen] && rotate) {
471c80476e4SDavid E. O'Brien 		newlen = (int) (LastChar - InputBuf);
472c80476e4SDavid E. O'Brien 		for (idx = (int) (Cursor - InputBuf);
473c80476e4SDavid E. O'Brien 		     idx <= newlen; idx++)
474c80476e4SDavid E. O'Brien 			InputBuf[idx - newlen + curlen] =
475c80476e4SDavid E. O'Brien 			InputBuf[idx];
476c80476e4SDavid E. O'Brien 		LastChar = InputBuf + curlen;
477c80476e4SDavid E. O'Brien 		Cursor = Cursor - newlen + curlen;
478c80476e4SDavid E. O'Brien 	    }
479c80476e4SDavid E. O'Brien 	    curlen = (int) (LastChar - InputBuf);
480c80476e4SDavid E. O'Brien 	    if (curchoice >= 0)
481c80476e4SDavid E. O'Brien 		curchoice--;
482c80476e4SDavid E. O'Brien 
483c80476e4SDavid E. O'Brien 	    fn = (retval == CC_LIST_ALL) ? LIST_ALL : LIST;
484c80476e4SDavid E. O'Brien 	    /* should catch ^C here... */
485c80476e4SDavid E. O'Brien 	    if (tenematch(InputBuf, Cursor - InputBuf, fn) < 0)
486c80476e4SDavid E. O'Brien 		SoundBeep();
487c80476e4SDavid E. O'Brien 	    Refresh();
488c80476e4SDavid E. O'Brien 	    Argument = 1;
489c80476e4SDavid E. O'Brien 	    DoingArg = 0;
490c80476e4SDavid E. O'Brien 	    break;
491c80476e4SDavid E. O'Brien 
492c80476e4SDavid E. O'Brien 
493c80476e4SDavid E. O'Brien 	case CC_LIST_GLOB:
494c80476e4SDavid E. O'Brien 	    if (tenematch(InputBuf, Cursor - InputBuf, GLOB) < 0)
495c80476e4SDavid E. O'Brien 		SoundBeep();
496c80476e4SDavid E. O'Brien 	    curlen = Repair();
497c80476e4SDavid E. O'Brien 	    break;
498c80476e4SDavid E. O'Brien 
499c80476e4SDavid E. O'Brien 	case CC_EXPAND_GLOB:
500c80476e4SDavid E. O'Brien 	    if (tenematch(InputBuf, Cursor - InputBuf, GLOB_EXPAND) <= 0)
501c80476e4SDavid E. O'Brien 		SoundBeep();		/* Beep = No match */
502c80476e4SDavid E. O'Brien 	    curlen = Repair();
503c80476e4SDavid E. O'Brien 	    break;
504c80476e4SDavid E. O'Brien 
505c80476e4SDavid E. O'Brien 	case CC_NORMALIZE_PATH:
506c80476e4SDavid E. O'Brien 	    if (tenematch(InputBuf, Cursor - InputBuf, PATH_NORMALIZE) <= 0)
507c80476e4SDavid E. O'Brien 		SoundBeep();		/* Beep = No match */
508c80476e4SDavid E. O'Brien 	    curlen = Repair();
509c80476e4SDavid E. O'Brien 	    break;
510c80476e4SDavid E. O'Brien 
511c80476e4SDavid E. O'Brien 	case CC_EXPAND_VARS:
512c80476e4SDavid E. O'Brien 	    if (tenematch(InputBuf, Cursor - InputBuf, VARS_EXPAND) <= 0)
513c80476e4SDavid E. O'Brien 		SoundBeep();		/* Beep = No match */
514c80476e4SDavid E. O'Brien 	    curlen = Repair();
515c80476e4SDavid E. O'Brien 	    break;
516c80476e4SDavid E. O'Brien 
517c80476e4SDavid E. O'Brien 	case CC_NORMALIZE_COMMAND:
518c80476e4SDavid E. O'Brien 	    if (tenematch(InputBuf, Cursor - InputBuf, COMMAND_NORMALIZE) <= 0)
519c80476e4SDavid E. O'Brien 		SoundBeep();		/* Beep = No match */
520c80476e4SDavid E. O'Brien 	    curlen = Repair();
521c80476e4SDavid E. O'Brien 	    break;
522c80476e4SDavid E. O'Brien 
523c80476e4SDavid E. O'Brien 	case CC_HELPME:
524c80476e4SDavid E. O'Brien 	    xputchar('\n');
525c80476e4SDavid E. O'Brien 	    /* should catch ^C here... */
526c80476e4SDavid E. O'Brien 	    (void) tenematch(InputBuf, LastChar - InputBuf, PRINT_HELP);
527c80476e4SDavid E. O'Brien 	    Refresh();
528c80476e4SDavid E. O'Brien 	    Argument = 1;
529c80476e4SDavid E. O'Brien 	    DoingArg = 0;
530c80476e4SDavid E. O'Brien 	    curchoice = -1;
531c80476e4SDavid E. O'Brien 	    curlen = (int) (LastChar - InputBuf);
532c80476e4SDavid E. O'Brien 	    break;
533c80476e4SDavid E. O'Brien 
534c80476e4SDavid E. O'Brien 	case CC_FATAL:		/* fatal error, reset to known state */
535c80476e4SDavid E. O'Brien #ifdef DEBUG_EDIT
536c80476e4SDavid E. O'Brien 	    xprintf(CGETS(7, 8, "*** editor fatal ERROR ***\r\n\n"));
537c80476e4SDavid E. O'Brien #endif				/* DEBUG_EDIT */
538c80476e4SDavid E. O'Brien 	    /* put (real) cursor in a known place */
539c80476e4SDavid E. O'Brien 	    ClearDisp();	/* reset the display stuff */
540c80476e4SDavid E. O'Brien 	    ResetInLine(1);	/* reset the input pointers */
541c80476e4SDavid E. O'Brien 	    Refresh();		/* print the prompt again */
542c80476e4SDavid E. O'Brien 	    Argument = 1;
543c80476e4SDavid E. O'Brien 	    DoingArg = 0;
544c80476e4SDavid E. O'Brien 	    curchoice = -1;
545c80476e4SDavid E. O'Brien 	    curlen = (int) (LastChar - InputBuf);
546c80476e4SDavid E. O'Brien 	    break;
547c80476e4SDavid E. O'Brien 
548c80476e4SDavid E. O'Brien 	case CC_ERROR:
549c80476e4SDavid E. O'Brien 	default:		/* functions we don't know about */
55045e5710bSMark Peek 	    if (adrof(STRhighlight)) {
55145e5710bSMark Peek 		ClearLines();
55245e5710bSMark Peek 		ClearDisp();
55345e5710bSMark Peek 		Refresh();
55445e5710bSMark Peek 	    }
555c80476e4SDavid E. O'Brien 	    DoingArg = 0;
556c80476e4SDavid E. O'Brien 	    Argument = 1;
557c80476e4SDavid E. O'Brien 	    SoundBeep();
558c80476e4SDavid E. O'Brien 	    flush();
559c80476e4SDavid E. O'Brien 	    curchoice = -1;
560c80476e4SDavid E. O'Brien 	    curlen = (int) (LastChar - InputBuf);
561c80476e4SDavid E. O'Brien 	    break;
562c80476e4SDavid E. O'Brien 	}
563c80476e4SDavid E. O'Brien     }
564c80476e4SDavid E. O'Brien     (void) Cookedmode();	/* make sure the tty is set up correctly */
565c80476e4SDavid E. O'Brien     GettingInput = 0;
566c80476e4SDavid E. O'Brien     flush();			/* flush any buffered output */
567c80476e4SDavid E. O'Brien     return num;
568c80476e4SDavid E. O'Brien }
569c80476e4SDavid E. O'Brien 
570c80476e4SDavid E. O'Brien void
57145e5710bSMark Peek PushMacro(Char *str)
572c80476e4SDavid E. O'Brien {
573c80476e4SDavid E. O'Brien     if (str != NULL && MacroLvl + 1 < MAXMACROLEVELS) {
574c80476e4SDavid E. O'Brien 	MacroLvl++;
575c80476e4SDavid E. O'Brien 	KeyMacro[MacroLvl] = str;
576c80476e4SDavid E. O'Brien     }
577c80476e4SDavid E. O'Brien     else {
578c80476e4SDavid E. O'Brien 	SoundBeep();
579c80476e4SDavid E. O'Brien 	flush();
580c80476e4SDavid E. O'Brien     }
581c80476e4SDavid E. O'Brien }
582c80476e4SDavid E. O'Brien 
58345e5710bSMark Peek struct eval1_state
58445e5710bSMark Peek {
58545e5710bSMark Peek     Char **evalvec, *evalp;
58645e5710bSMark Peek };
58745e5710bSMark Peek 
58845e5710bSMark Peek static void
58945e5710bSMark Peek eval1_cleanup(void *xstate)
59045e5710bSMark Peek {
59145e5710bSMark Peek     struct eval1_state *state;
59245e5710bSMark Peek 
59345e5710bSMark Peek     state = xstate;
59445e5710bSMark Peek     evalvec = state->evalvec;
59545e5710bSMark Peek     evalp = state->evalp;
59645e5710bSMark Peek     doneinp = 0;
59745e5710bSMark Peek }
59845e5710bSMark Peek 
599c80476e4SDavid E. O'Brien /*
600c80476e4SDavid E. O'Brien  * Like eval, only using the current file descriptors
601c80476e4SDavid E. O'Brien  */
602c80476e4SDavid E. O'Brien static void
60345e5710bSMark Peek doeval1(Char **v)
604c80476e4SDavid E. O'Brien {
60545e5710bSMark Peek     struct eval1_state state;
60645e5710bSMark Peek     Char  **gv;
60745e5710bSMark Peek     int gflag;
608c80476e4SDavid E. O'Brien 
60945e5710bSMark Peek     gflag = tglob(v);
610c80476e4SDavid E. O'Brien     if (gflag) {
61145e5710bSMark Peek 	gv = v = globall(v, gflag);
61245e5710bSMark Peek 	if (v == 0)
613c80476e4SDavid E. O'Brien 	    stderror(ERR_NOMATCH);
61445e5710bSMark Peek 	v = copyblk(v);
615c80476e4SDavid E. O'Brien     }
616c80476e4SDavid E. O'Brien     else {
617c80476e4SDavid E. O'Brien 	gv = NULL;
61845e5710bSMark Peek 	v = copyblk(v);
61945e5710bSMark Peek 	trim(v);
620c80476e4SDavid E. O'Brien     }
621c80476e4SDavid E. O'Brien     if (gv)
62245e5710bSMark Peek 	cleanup_push(gv, blk_cleanup);
623c80476e4SDavid E. O'Brien 
62445e5710bSMark Peek     state.evalvec = evalvec;
62545e5710bSMark Peek     state.evalp = evalp;
62645e5710bSMark Peek     evalvec = v;
62745e5710bSMark Peek     evalp = 0;
62845e5710bSMark Peek     cleanup_push(&state, eval1_cleanup);
62945e5710bSMark Peek     process(0);
63045e5710bSMark Peek     cleanup_until(&state);
63145e5710bSMark Peek     if (gv)
63245e5710bSMark Peek 	cleanup_until(gv);
633c80476e4SDavid E. O'Brien }
634c80476e4SDavid E. O'Brien 
635c80476e4SDavid E. O'Brien static void
63645e5710bSMark Peek RunCommand(Char *str)
637c80476e4SDavid E. O'Brien {
638c80476e4SDavid E. O'Brien     Char *cmd[2];
639c80476e4SDavid E. O'Brien 
640c80476e4SDavid E. O'Brien     xputchar('\n');	/* Start on a clean line */
641c80476e4SDavid E. O'Brien 
642c80476e4SDavid E. O'Brien     cmd[0] = str;
643c80476e4SDavid E. O'Brien     cmd[1] = NULL;
644c80476e4SDavid E. O'Brien 
645c80476e4SDavid E. O'Brien     (void) Cookedmode();
646c80476e4SDavid E. O'Brien     GettingInput = 0;
647c80476e4SDavid E. O'Brien 
648c80476e4SDavid E. O'Brien     doeval1(cmd);
649c80476e4SDavid E. O'Brien 
650c80476e4SDavid E. O'Brien     (void) Rawmode();
651c80476e4SDavid E. O'Brien     GettingInput = 1;
652c80476e4SDavid E. O'Brien 
653c80476e4SDavid E. O'Brien     ClearLines();
654c80476e4SDavid E. O'Brien     ClearDisp();
655c80476e4SDavid E. O'Brien     NeedsRedraw = 0;
656c80476e4SDavid E. O'Brien     Refresh();
657c80476e4SDavid E. O'Brien }
658c80476e4SDavid E. O'Brien 
659c80476e4SDavid E. O'Brien static int
66045e5710bSMark Peek GetNextCommand(KEYCMD *cmdnum, Char *ch)
661c80476e4SDavid E. O'Brien {
662c80476e4SDavid E. O'Brien     KEYCMD  cmd = 0;
663c80476e4SDavid E. O'Brien     int     num;
664c80476e4SDavid E. O'Brien 
665c80476e4SDavid E. O'Brien     while (cmd == 0 || cmd == F_XKEY) {
666c80476e4SDavid E. O'Brien 	if ((num = GetNextChar(ch)) != 1) {	/* if EOF or error */
667c80476e4SDavid E. O'Brien 	    return num;
668c80476e4SDavid E. O'Brien 	}
669c80476e4SDavid E. O'Brien #ifdef	KANJI
67000c801edSDavid E. O'Brien 	if (
67100c801edSDavid E. O'Brien #ifdef DSPMBYTE
67200c801edSDavid E. O'Brien 	     _enable_mbdisp &&
67323338178SMark Peek #else
67423338178SMark Peek 	     MB_LEN_MAX == 1 &&
67500c801edSDavid E. O'Brien #endif
67600c801edSDavid E. O'Brien 	     !adrof(STRnokanji) && (*ch & META)) {
677c80476e4SDavid E. O'Brien 	    MetaNext = 0;
678c80476e4SDavid E. O'Brien 	    cmd = F_INSERT;
679c80476e4SDavid E. O'Brien 	    break;
680c80476e4SDavid E. O'Brien 	}
681c80476e4SDavid E. O'Brien 	else
682c80476e4SDavid E. O'Brien #endif /* KANJI */
683c80476e4SDavid E. O'Brien 	if (MetaNext) {
684c80476e4SDavid E. O'Brien 	    MetaNext = 0;
685c80476e4SDavid E. O'Brien 	    *ch |= META;
686c80476e4SDavid E. O'Brien 	}
687c80476e4SDavid E. O'Brien 	/* XXX: This needs to be fixed so that we don't just truncate
688c80476e4SDavid E. O'Brien 	 * the character, we unquote it.
689c80476e4SDavid E. O'Brien 	 */
690c80476e4SDavid E. O'Brien 	if (*ch < NT_NUM_KEYS)
691c80476e4SDavid E. O'Brien 	    cmd = CurrentKeyMap[*ch];
692c80476e4SDavid E. O'Brien 	else
69323338178SMark Peek #ifdef WINNT_NATIVE
694c80476e4SDavid E. O'Brien 	    cmd = CurrentKeyMap[(unsigned char) *ch];
69523338178SMark Peek #else
69623338178SMark Peek 	    cmd = F_INSERT;
69723338178SMark Peek #endif
698c80476e4SDavid E. O'Brien 	if (cmd == F_XKEY) {
699c80476e4SDavid E. O'Brien 	    XmapVal val;
700c80476e4SDavid E. O'Brien 	    CStr cstr;
701c80476e4SDavid E. O'Brien 	    cstr.buf = ch;
70245e5710bSMark Peek 	    cstr.len = 1;
703c80476e4SDavid E. O'Brien 	    switch (GetXkey(&cstr, &val)) {
704c80476e4SDavid E. O'Brien 	    case XK_CMD:
705c80476e4SDavid E. O'Brien 		cmd = val.cmd;
706c80476e4SDavid E. O'Brien 		break;
707c80476e4SDavid E. O'Brien 	    case XK_STR:
708c80476e4SDavid E. O'Brien 		PushMacro(val.str.buf);
709c80476e4SDavid E. O'Brien 		break;
710c80476e4SDavid E. O'Brien 	    case XK_EXE:
711c80476e4SDavid E. O'Brien 		RunCommand(val.str.buf);
712c80476e4SDavid E. O'Brien 		break;
713c80476e4SDavid E. O'Brien 	    default:
714c80476e4SDavid E. O'Brien 		abort();
715c80476e4SDavid E. O'Brien 		break;
716c80476e4SDavid E. O'Brien 	    }
717c80476e4SDavid E. O'Brien 	}
718c80476e4SDavid E. O'Brien 	if (!AltKeyMap)
719c80476e4SDavid E. O'Brien 	    CurrentKeyMap = CcKeyMap;
720c80476e4SDavid E. O'Brien     }
721c80476e4SDavid E. O'Brien     *cmdnum = cmd;
722c80476e4SDavid E. O'Brien     return OKCMD;
723c80476e4SDavid E. O'Brien }
724c80476e4SDavid E. O'Brien 
72523338178SMark Peek static Char ungetchar;
72623338178SMark Peek static int haveungetchar;
72723338178SMark Peek 
72823338178SMark Peek void
72923338178SMark Peek UngetNextChar(Char cp)
73023338178SMark Peek {
73123338178SMark Peek     ungetchar = cp;
73223338178SMark Peek     haveungetchar = 1;
73323338178SMark Peek }
73423338178SMark Peek 
735c80476e4SDavid E. O'Brien int
73645e5710bSMark Peek GetNextChar(Char *cp)
737c80476e4SDavid E. O'Brien {
73823338178SMark Peek     int num_read;
739c80476e4SDavid E. O'Brien     int     tried = 0;
74023338178SMark Peek     char cbuf[MB_LEN_MAX];
74123338178SMark Peek     size_t cbp;
742c80476e4SDavid E. O'Brien 
74323338178SMark Peek     if (haveungetchar) {
74423338178SMark Peek 	haveungetchar = 0;
74523338178SMark Peek 	*cp = ungetchar;
74623338178SMark Peek 	return 1;
74723338178SMark Peek     }
748c80476e4SDavid E. O'Brien     for (;;) {
749c80476e4SDavid E. O'Brien 	if (MacroLvl < 0) {
750c80476e4SDavid E. O'Brien 	    if (!Load_input_line())
751c80476e4SDavid E. O'Brien 		break;
752c80476e4SDavid E. O'Brien 	}
753c80476e4SDavid E. O'Brien 	if (*KeyMacro[MacroLvl] == 0) {
754c80476e4SDavid E. O'Brien 	    MacroLvl--;
755c80476e4SDavid E. O'Brien 	    continue;
756c80476e4SDavid E. O'Brien 	}
757c80476e4SDavid E. O'Brien 	*cp = *KeyMacro[MacroLvl]++ & CHAR;
758c80476e4SDavid E. O'Brien 	if (*KeyMacro[MacroLvl] == 0) {	/* Needed for QuoteMode On */
759c80476e4SDavid E. O'Brien 	    MacroLvl--;
760c80476e4SDavid E. O'Brien 	}
761c80476e4SDavid E. O'Brien 	return (1);
762c80476e4SDavid E. O'Brien     }
763c80476e4SDavid E. O'Brien 
764c80476e4SDavid E. O'Brien     if (Rawmode() < 0)		/* make sure the tty is set up correctly */
765c80476e4SDavid E. O'Brien 	return 0;		/* oops: SHIN was closed */
766c80476e4SDavid E. O'Brien 
7673b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE
768c80476e4SDavid E. O'Brien     __nt_want_vcode = 1;
7693b6eaa7bSAndrey A. Chernov #endif /* WINNT_NATIVE */
77023338178SMark Peek #ifdef SIG_WINDOW
77123338178SMark Peek     if (windowchg)
77223338178SMark Peek 	(void) check_window_size(0);	/* for window systems */
77323338178SMark Peek #endif /* SIG_WINDOW */
77423338178SMark Peek     cbp = 0;
77523338178SMark Peek     for (;;) {
77645e5710bSMark Peek 	while ((num_read = xread(SHIN, cbuf + cbp, 1)) == -1) {
777c80476e4SDavid E. O'Brien 	    if (!tried && fixio(SHIN, errno) != -1)
778c80476e4SDavid E. O'Brien 		tried = 1;
779c80476e4SDavid E. O'Brien 	    else {
780c80476e4SDavid E. O'Brien # ifdef convex
781c80476e4SDavid E. O'Brien 		/* need to print error message in case the file is migrated */
782c80476e4SDavid E. O'Brien 		stderror(ERR_SYSTEM, progname, strerror(errno));
783c80476e4SDavid E. O'Brien # endif  /* convex */
7843b6eaa7bSAndrey A. Chernov # ifdef WINNT_NATIVE
785c80476e4SDavid E. O'Brien 		__nt_want_vcode = 0;
7863b6eaa7bSAndrey A. Chernov # endif /* WINNT_NATIVE */
78723338178SMark Peek 		*cp = '\0'; /* Loses possible partial character */
788c80476e4SDavid E. O'Brien 		return -1;
789c80476e4SDavid E. O'Brien 	    }
790c80476e4SDavid E. O'Brien 	}
79145e5710bSMark Peek 	if (AsciiOnly) {
79245e5710bSMark Peek 	    *cp = (unsigned char)*cbuf;
79345e5710bSMark Peek 	} else {
79423338178SMark Peek 	    cbp++;
79523338178SMark Peek 	    if (normal_mbtowc(cp, cbuf, cbp) == -1) {
79623338178SMark Peek 		reset_mbtowc();
79745e5710bSMark Peek 		if (cbp < MB_CUR_MAX)
79823338178SMark Peek 		    continue; /* Maybe a partial character */
79923338178SMark Peek 		/* And drop the following bytes, if any */
80023338178SMark Peek 		*cp = (unsigned char)*cbuf | INVALID_BYTE;
80123338178SMark Peek 	    }
80245e5710bSMark Peek 	}
80323338178SMark Peek 	break;
80423338178SMark Peek     }
8053b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE
80623338178SMark Peek     /* This is the part that doesn't work with WIDE_STRINGS */
807c80476e4SDavid E. O'Brien     if (__nt_want_vcode == 2)
808c80476e4SDavid E. O'Brien 	*cp = __nt_vcode;
809c80476e4SDavid E. O'Brien     __nt_want_vcode = 0;
8103b6eaa7bSAndrey A. Chernov #endif /* WINNT_NATIVE */
811c80476e4SDavid E. O'Brien     return num_read;
812c80476e4SDavid E. O'Brien }
813c80476e4SDavid E. O'Brien 
814c80476e4SDavid E. O'Brien /*
815c80476e4SDavid E. O'Brien  * SpellLine - do spelling correction on the entire command line
816c80476e4SDavid E. O'Brien  * (which may have trailing newline).
817c80476e4SDavid E. O'Brien  * If cmdonly is set, only check spelling of command words.
818c80476e4SDavid E. O'Brien  * Return value:
819c80476e4SDavid E. O'Brien  * -1: Something was incorrectible, and nothing was corrected
820c80476e4SDavid E. O'Brien  *  0: Everything was correct
821c80476e4SDavid E. O'Brien  *  1: Something was corrected
822c80476e4SDavid E. O'Brien  */
823c80476e4SDavid E. O'Brien static int
82445e5710bSMark Peek SpellLine(int cmdonly)
825c80476e4SDavid E. O'Brien {
826c80476e4SDavid E. O'Brien     int     endflag, matchval;
827c80476e4SDavid E. O'Brien     Char   *argptr, *OldCursor, *OldLastChar;
828c80476e4SDavid E. O'Brien 
829c80476e4SDavid E. O'Brien     OldLastChar = LastChar;
830c80476e4SDavid E. O'Brien     OldCursor = Cursor;
831c80476e4SDavid E. O'Brien     argptr = InputBuf;
832c80476e4SDavid E. O'Brien     endflag = 1;
833c80476e4SDavid E. O'Brien     matchval = 0;
834c80476e4SDavid E. O'Brien     do {
835c80476e4SDavid E. O'Brien 	while (ismetahash(*argptr) || iscmdmeta(*argptr))
836c80476e4SDavid E. O'Brien 	    argptr++;
837c80476e4SDavid E. O'Brien 	for (Cursor = argptr;
838c80476e4SDavid E. O'Brien 	     *Cursor != '\0' && ((Cursor != argptr && Cursor[-1] == '\\') ||
839c80476e4SDavid E. O'Brien 				 (!ismetahash(*Cursor) && !iscmdmeta(*Cursor)));
840c80476e4SDavid E. O'Brien 	     Cursor++)
841c80476e4SDavid E. O'Brien 	     continue;
842c80476e4SDavid E. O'Brien 	if (*Cursor == '\0') {
843c80476e4SDavid E. O'Brien 	    Cursor = LastChar;
844c80476e4SDavid E. O'Brien 	    if (LastChar[-1] == '\n')
845c80476e4SDavid E. O'Brien 		Cursor--;
846c80476e4SDavid E. O'Brien 	    endflag = 0;
847c80476e4SDavid E. O'Brien 	}
848c80476e4SDavid E. O'Brien 	/* Obey current history character settings */
849c80476e4SDavid E. O'Brien 	mismatch[0] = HIST;
850c80476e4SDavid E. O'Brien 	mismatch[1] = HISTSUB;
851c80476e4SDavid E. O'Brien 	if (!Strchr(mismatch, *argptr) &&
852c80476e4SDavid E. O'Brien 	    (!cmdonly || starting_a_command(argptr, InputBuf))) {
8533b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE
854c80476e4SDavid E. O'Brien 	    /*
855c80476e4SDavid E. O'Brien 	     * This hack avoids correcting drive letter changes
856c80476e4SDavid E. O'Brien 	     */
857c80476e4SDavid E. O'Brien 	    if((Cursor - InputBuf) != 2 || (char)InputBuf[1] != ':')
8583b6eaa7bSAndrey A. Chernov #endif /* WINNT_NATIVE */
859c80476e4SDavid E. O'Brien 	    {
860c80476e4SDavid E. O'Brien #ifdef HASH_SPELL_CHECK
861c80476e4SDavid E. O'Brien 		Char save;
862c80476e4SDavid E. O'Brien 		size_t len = Cursor - InputBuf;
863c80476e4SDavid E. O'Brien 
864c80476e4SDavid E. O'Brien 		save = InputBuf[len];
865c80476e4SDavid E. O'Brien 		InputBuf[len] = '\0';
866c80476e4SDavid E. O'Brien 		if (find_cmd(InputBuf, 0) != 0) {
867c80476e4SDavid E. O'Brien 		    InputBuf[len] = save;
868c80476e4SDavid E. O'Brien 		    argptr = Cursor;
869c80476e4SDavid E. O'Brien 		    continue;
870c80476e4SDavid E. O'Brien 		}
871c80476e4SDavid E. O'Brien 		InputBuf[len] = save;
872c80476e4SDavid E. O'Brien #endif /* HASH_SPELL_CHECK */
873c80476e4SDavid E. O'Brien 		switch (tenematch(InputBuf, Cursor - InputBuf, SPELL)) {
874c80476e4SDavid E. O'Brien 		case 1:		/* corrected */
875c80476e4SDavid E. O'Brien 		    matchval = 1;
876c80476e4SDavid E. O'Brien 		    break;
877c80476e4SDavid E. O'Brien 		case -1:		/* couldn't be corrected */
878c80476e4SDavid E. O'Brien 		    if (!matchval)
879c80476e4SDavid E. O'Brien 			matchval = -1;
880c80476e4SDavid E. O'Brien 		    break;
881c80476e4SDavid E. O'Brien 		default:		/* was correct */
882c80476e4SDavid E. O'Brien 		    break;
883c80476e4SDavid E. O'Brien 		}
884c80476e4SDavid E. O'Brien 	    }
885c80476e4SDavid E. O'Brien 	    if (LastChar != OldLastChar) {
886c80476e4SDavid E. O'Brien 		if (argptr < OldCursor)
887c80476e4SDavid E. O'Brien 		    OldCursor += (LastChar - OldLastChar);
888c80476e4SDavid E. O'Brien 		OldLastChar = LastChar;
889c80476e4SDavid E. O'Brien 	    }
890c80476e4SDavid E. O'Brien 	}
891c80476e4SDavid E. O'Brien 	argptr = Cursor;
892c80476e4SDavid E. O'Brien     } while (endflag);
893c80476e4SDavid E. O'Brien     Cursor = OldCursor;
894c80476e4SDavid E. O'Brien     return matchval;
895c80476e4SDavid E. O'Brien }
896c80476e4SDavid E. O'Brien 
897c80476e4SDavid E. O'Brien /*
898c80476e4SDavid E. O'Brien  * CompleteLine - do command completion on the entire command line
899c80476e4SDavid E. O'Brien  * (which may have trailing newline).
900c80476e4SDavid E. O'Brien  * Return value:
901c80476e4SDavid E. O'Brien  *  0: No command matched or failure
902c80476e4SDavid E. O'Brien  *  1: One command matched
903c80476e4SDavid E. O'Brien  *  2: Several commands matched
904c80476e4SDavid E. O'Brien  */
905c80476e4SDavid E. O'Brien static int
90645e5710bSMark Peek CompleteLine(void)
907c80476e4SDavid E. O'Brien {
908c80476e4SDavid E. O'Brien     int     endflag, tmatch;
909c80476e4SDavid E. O'Brien     Char   *argptr, *OldCursor, *OldLastChar;
910c80476e4SDavid E. O'Brien 
911c80476e4SDavid E. O'Brien     OldLastChar = LastChar;
912c80476e4SDavid E. O'Brien     OldCursor = Cursor;
913c80476e4SDavid E. O'Brien     argptr = InputBuf;
914c80476e4SDavid E. O'Brien     endflag = 1;
915c80476e4SDavid E. O'Brien     do {
916c80476e4SDavid E. O'Brien 	while (ismetahash(*argptr) || iscmdmeta(*argptr))
917c80476e4SDavid E. O'Brien 	    argptr++;
918c80476e4SDavid E. O'Brien 	for (Cursor = argptr;
919c80476e4SDavid E. O'Brien 	     *Cursor != '\0' && ((Cursor != argptr && Cursor[-1] == '\\') ||
920c80476e4SDavid E. O'Brien 				 (!ismetahash(*Cursor) && !iscmdmeta(*Cursor)));
921c80476e4SDavid E. O'Brien 	     Cursor++)
922c80476e4SDavid E. O'Brien 	     continue;
923c80476e4SDavid E. O'Brien 	if (*Cursor == '\0') {
924c80476e4SDavid E. O'Brien 	    Cursor = LastChar;
925c80476e4SDavid E. O'Brien 	    if (LastChar[-1] == '\n')
926c80476e4SDavid E. O'Brien 		Cursor--;
927c80476e4SDavid E. O'Brien 	    endflag = 0;
928c80476e4SDavid E. O'Brien 	}
929c80476e4SDavid E. O'Brien 	if (!Strchr(mismatch, *argptr) && starting_a_command(argptr, InputBuf)) {
930c80476e4SDavid E. O'Brien 	    tmatch = tenematch(InputBuf, Cursor - InputBuf, RECOGNIZE);
931c80476e4SDavid E. O'Brien 	    if (tmatch <= 0) {
932c80476e4SDavid E. O'Brien                 return 0;
933c80476e4SDavid E. O'Brien             } else if (tmatch > 1) {
934c80476e4SDavid E. O'Brien                 return 2;
935c80476e4SDavid E. O'Brien 	    }
936c80476e4SDavid E. O'Brien 	    if (LastChar != OldLastChar) {
937c80476e4SDavid E. O'Brien 		if (argptr < OldCursor)
938c80476e4SDavid E. O'Brien 		    OldCursor += (LastChar - OldLastChar);
939c80476e4SDavid E. O'Brien 		OldLastChar = LastChar;
940c80476e4SDavid E. O'Brien 	    }
941c80476e4SDavid E. O'Brien 	}
942c80476e4SDavid E. O'Brien 	argptr = Cursor;
943c80476e4SDavid E. O'Brien     } while (endflag);
944c80476e4SDavid E. O'Brien     Cursor = OldCursor;
945c80476e4SDavid E. O'Brien     return 1;
946c80476e4SDavid E. O'Brien }
947c80476e4SDavid E. O'Brien 
948