1c80476e4SDavid E. O'Brien /*
2c80476e4SDavid E. O'Brien * ed.inputl.c: Input line handling.
3c80476e4SDavid E. O'Brien */
4c80476e4SDavid E. O'Brien /*-
5c80476e4SDavid E. O'Brien * Copyright (c) 1980, 1991 The Regents of the University of California.
6c80476e4SDavid E. O'Brien * All rights reserved.
7c80476e4SDavid E. O'Brien *
8c80476e4SDavid E. O'Brien * Redistribution and use in source and binary forms, with or without
9c80476e4SDavid E. O'Brien * modification, are permitted provided that the following conditions
10c80476e4SDavid E. O'Brien * are met:
11c80476e4SDavid E. O'Brien * 1. Redistributions of source code must retain the above copyright
12c80476e4SDavid E. O'Brien * notice, this list of conditions and the following disclaimer.
13c80476e4SDavid E. O'Brien * 2. Redistributions in binary form must reproduce the above copyright
14c80476e4SDavid E. O'Brien * notice, this list of conditions and the following disclaimer in the
15c80476e4SDavid E. O'Brien * documentation and/or other materials provided with the distribution.
1629301572SMark Peek * 3. Neither the name of the University nor the names of its contributors
17c80476e4SDavid E. O'Brien * may be used to endorse or promote products derived from this software
18c80476e4SDavid E. O'Brien * without specific prior written permission.
19c80476e4SDavid E. O'Brien *
20c80476e4SDavid E. O'Brien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21c80476e4SDavid E. O'Brien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22c80476e4SDavid E. O'Brien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23c80476e4SDavid E. O'Brien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24c80476e4SDavid E. O'Brien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25c80476e4SDavid E. O'Brien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26c80476e4SDavid E. O'Brien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27c80476e4SDavid E. O'Brien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28c80476e4SDavid E. O'Brien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29c80476e4SDavid E. O'Brien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30c80476e4SDavid E. O'Brien * SUCH DAMAGE.
31c80476e4SDavid E. O'Brien */
32c80476e4SDavid E. O'Brien #include "sh.h"
33c80476e4SDavid E. O'Brien #include "ed.h"
34c80476e4SDavid E. O'Brien #include "ed.defns.h" /* for the function names */
35c80476e4SDavid E. O'Brien #include "tw.h" /* for twenex stuff */
36c80476e4SDavid E. O'Brien
3745e5710bSMark Peek #define OKCMD INT_MAX
38c80476e4SDavid E. O'Brien
39c80476e4SDavid E. O'Brien /* ed.inputl -- routines to get a single line from the input. */
40c80476e4SDavid E. O'Brien
4123338178SMark Peek extern int MapsAreInited;
42c80476e4SDavid E. O'Brien
43c80476e4SDavid E. O'Brien /* mismatched first character */
44a15e6f9aSMark Peek static Char mismatch[] = { '\\', '-', '%', '\0' };
45a15e6f9aSMark Peek /* don't Strchr() for '\0', obey current history character settings */
46a15e6f9aSMark Peek #define MISMATCH(c) ((c) == '\0' || (c) == HIST || (c) == HISTSUB || \
47a15e6f9aSMark Peek Strchr(mismatch, (c)))
48c80476e4SDavid E. O'Brien
4945e5710bSMark Peek static int Repair (void);
5045e5710bSMark Peek static int GetNextCommand (KEYCMD *, Char *);
5145e5710bSMark Peek static int SpellLine (int);
5245e5710bSMark Peek static int CompleteLine (void);
5345e5710bSMark Peek static void RunCommand (Char *);
5445e5710bSMark Peek static void doeval1 (Char **);
55c80476e4SDavid E. O'Brien
5623338178SMark Peek static int rotate = 0;
57c80476e4SDavid E. O'Brien
58c80476e4SDavid E. O'Brien
59c80476e4SDavid E. O'Brien static int
Repair(void)6045e5710bSMark Peek Repair(void)
61c80476e4SDavid E. O'Brien {
62c80476e4SDavid E. O'Brien if (NeedsRedraw) {
63c80476e4SDavid E. O'Brien ClearLines();
64c80476e4SDavid E. O'Brien ClearDisp();
65c80476e4SDavid E. O'Brien NeedsRedraw = 0;
66c80476e4SDavid E. O'Brien }
67c80476e4SDavid E. O'Brien Refresh();
68c80476e4SDavid E. O'Brien Argument = 1;
69c80476e4SDavid E. O'Brien DoingArg = 0;
70c80476e4SDavid E. O'Brien curchoice = -1;
71c80476e4SDavid E. O'Brien return (int) (LastChar - InputBuf);
72c80476e4SDavid E. O'Brien }
73c80476e4SDavid E. O'Brien
74c80476e4SDavid E. O'Brien /* CCRETVAL */
75c80476e4SDavid E. O'Brien int
Inputl(void)7645e5710bSMark Peek Inputl(void)
77c80476e4SDavid E. O'Brien {
78c80476e4SDavid E. O'Brien CCRETVAL retval;
79c80476e4SDavid E. O'Brien KEYCMD cmdnum = 0;
80c80476e4SDavid E. O'Brien unsigned char tch; /* the place where read() goes */
81c80476e4SDavid E. O'Brien Char ch;
82c80476e4SDavid E. O'Brien int num; /* how many chars we have read at NL */
83c80476e4SDavid E. O'Brien int expnum;
84c80476e4SDavid E. O'Brien struct varent *crct = inheredoc ? NULL : adrof(STRcorrect);
85c80476e4SDavid E. O'Brien struct varent *autol = adrof(STRautolist);
86c80476e4SDavid E. O'Brien struct varent *matchbeep = adrof(STRmatchbeep);
87c80476e4SDavid E. O'Brien struct varent *imode = adrof(STRinputmode);
88c80476e4SDavid E. O'Brien Char *SaveChar, *CorrChar;
89c80476e4SDavid E. O'Brien int matchval; /* from tenematch() */
90a15e6f9aSMark Peek int nr_history_exp; /* number of (attempted) history expansions */
91c80476e4SDavid E. O'Brien COMMAND fn;
92c80476e4SDavid E. O'Brien int curlen = 0;
93c80476e4SDavid E. O'Brien int newlen;
94c80476e4SDavid E. O'Brien int idx;
95a15e6f9aSMark Peek Char *autoexpand;
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 */
263a15e6f9aSMark Peek xprintf("%s", 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') {
269a15e6f9aSMark Peek xprintf("%s", 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') {
280a15e6f9aSMark Peek xprintf("%s", 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 }
288a15e6f9aSMark Peek xprintf("%s", 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) {
308a15e6f9aSMark Peek xprintf("%s", CGETS(6, 6, "No matching command\n"));
309c80476e4SDavid E. O'Brien } else if (matchval == 2) {
310a15e6f9aSMark Peek xprintf("%s", 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
397a15e6f9aSMark Peek nr_history_exp = 0;
398a15e6f9aSMark Peek autoexpand = varval(STRautoexpand);
399a15e6f9aSMark Peek if (autoexpand != STRNULL)
400a15e6f9aSMark Peek nr_history_exp += ExpandHistory();
401a15e6f9aSMark Peek
402a15e6f9aSMark Peek /* try normal expansion only if no history references were found */
403a15e6f9aSMark Peek if (nr_history_exp == 0 ||
404a15e6f9aSMark Peek Strcmp(autoexpand, STRonlyhistory) != 0) {
405c80476e4SDavid E. O'Brien /*
406c80476e4SDavid E. O'Brien * Modified by Martin Boyer (gamin@ireq-robot.hydro.qc.ca):
407c80476e4SDavid E. O'Brien * A separate variable now controls beeping after
408c80476e4SDavid E. O'Brien * completion, independently of autolisting.
409c80476e4SDavid E. O'Brien */
410c80476e4SDavid E. O'Brien expnum = (int) (Cursor - InputBuf);
411c80476e4SDavid E. O'Brien switch (matchval = tenematch(InputBuf, Cursor-InputBuf, fn)){
412c80476e4SDavid E. O'Brien case 1:
413a15e6f9aSMark Peek if (non_unique_match && matchbeep &&
414a15e6f9aSMark Peek matchbeep->vec != NULL &&
415c80476e4SDavid E. O'Brien (Strcmp(*(matchbeep->vec), STRnotunique) == 0))
416c80476e4SDavid E. O'Brien SoundBeep();
417c80476e4SDavid E. O'Brien break;
418c80476e4SDavid E. O'Brien case 0:
41929301572SMark Peek if (matchbeep && matchbeep->vec != NULL) {
420c80476e4SDavid E. O'Brien if (Strcmp(*(matchbeep->vec), STRnomatch) == 0 ||
421c80476e4SDavid E. O'Brien Strcmp(*(matchbeep->vec), STRambiguous) == 0 ||
422c80476e4SDavid E. O'Brien Strcmp(*(matchbeep->vec), STRnotunique) == 0)
423c80476e4SDavid E. O'Brien SoundBeep();
424c80476e4SDavid E. O'Brien }
425c80476e4SDavid E. O'Brien else
426c80476e4SDavid E. O'Brien SoundBeep();
427c80476e4SDavid E. O'Brien break;
428c80476e4SDavid E. O'Brien default:
429c80476e4SDavid E. O'Brien if (matchval < 0) { /* Error from tenematch */
430c80476e4SDavid E. O'Brien curchoice = -1;
431c80476e4SDavid E. O'Brien SoundBeep();
432c80476e4SDavid E. O'Brien break;
433c80476e4SDavid E. O'Brien }
43429301572SMark Peek if (matchbeep && matchbeep->vec != NULL) {
435c80476e4SDavid E. O'Brien if ((Strcmp(*(matchbeep->vec), STRambiguous) == 0 ||
436c80476e4SDavid E. O'Brien Strcmp(*(matchbeep->vec), STRnotunique) == 0))
437c80476e4SDavid E. O'Brien SoundBeep();
438c80476e4SDavid E. O'Brien }
439c80476e4SDavid E. O'Brien else
440c80476e4SDavid E. O'Brien SoundBeep();
441c80476e4SDavid E. O'Brien /*
442c80476e4SDavid E. O'Brien * Addition by David C Lawrence <tale@pawl.rpi.edu>: If an
443c80476e4SDavid E. O'Brien * attempted completion is ambiguous, list the choices.
444c80476e4SDavid E. O'Brien * (PWP: this is the best feature addition to tcsh I have
445c80476e4SDavid E. O'Brien * seen in many months.)
446c80476e4SDavid E. O'Brien */
44729301572SMark Peek if (autol && autol->vec != NULL &&
44829301572SMark Peek (Strcmp(*(autol->vec), STRambiguous) != 0 ||
449c80476e4SDavid E. O'Brien expnum == Cursor - InputBuf)) {
45045e5710bSMark Peek if (adrof(STRhighlight) && MarkIsSet) {
45145e5710bSMark Peek /* clear highlighting before showing completions */
45245e5710bSMark Peek MarkIsSet = 0;
45345e5710bSMark Peek ClearLines();
45445e5710bSMark Peek ClearDisp();
45545e5710bSMark Peek Refresh();
45645e5710bSMark Peek MarkIsSet = 1;
45745e5710bSMark Peek }
458c80476e4SDavid E. O'Brien PastBottom();
459c80476e4SDavid E. O'Brien fn = (retval == CC_COMPLETE_ALL) ? LIST_ALL : LIST;
460c80476e4SDavid E. O'Brien (void) tenematch(InputBuf, Cursor-InputBuf, fn);
461c80476e4SDavid E. O'Brien }
462c80476e4SDavid E. O'Brien break;
463c80476e4SDavid E. O'Brien }
464a15e6f9aSMark Peek }
465c80476e4SDavid E. O'Brien if (NeedsRedraw) {
466c80476e4SDavid E. O'Brien PastBottom();
467c80476e4SDavid E. O'Brien ClearLines();
468c80476e4SDavid E. O'Brien ClearDisp();
469c80476e4SDavid E. O'Brien NeedsRedraw = 0;
470c80476e4SDavid E. O'Brien }
471c80476e4SDavid E. O'Brien Refresh();
472c80476e4SDavid E. O'Brien Argument = 1;
473c80476e4SDavid E. O'Brien DoingArg = 0;
474c80476e4SDavid E. O'Brien break;
475c80476e4SDavid E. O'Brien
476c80476e4SDavid E. O'Brien case CC_LIST_CHOICES:
477c80476e4SDavid E. O'Brien case CC_LIST_ALL:
478c80476e4SDavid E. O'Brien if (InputBuf[curlen] && rotate) {
479c80476e4SDavid E. O'Brien newlen = (int) (LastChar - InputBuf);
480c80476e4SDavid E. O'Brien for (idx = (int) (Cursor - InputBuf);
481c80476e4SDavid E. O'Brien idx <= newlen; idx++)
482c80476e4SDavid E. O'Brien InputBuf[idx - newlen + curlen] =
483c80476e4SDavid E. O'Brien InputBuf[idx];
484c80476e4SDavid E. O'Brien LastChar = InputBuf + curlen;
485c80476e4SDavid E. O'Brien Cursor = Cursor - newlen + curlen;
486c80476e4SDavid E. O'Brien }
487c80476e4SDavid E. O'Brien curlen = (int) (LastChar - InputBuf);
488c80476e4SDavid E. O'Brien if (curchoice >= 0)
489c80476e4SDavid E. O'Brien curchoice--;
490c80476e4SDavid E. O'Brien
491c80476e4SDavid E. O'Brien fn = (retval == CC_LIST_ALL) ? LIST_ALL : LIST;
492c80476e4SDavid E. O'Brien /* should catch ^C here... */
493c80476e4SDavid E. O'Brien if (tenematch(InputBuf, Cursor - InputBuf, fn) < 0)
494c80476e4SDavid E. O'Brien SoundBeep();
495c80476e4SDavid E. O'Brien Refresh();
496c80476e4SDavid E. O'Brien Argument = 1;
497c80476e4SDavid E. O'Brien DoingArg = 0;
498c80476e4SDavid E. O'Brien break;
499c80476e4SDavid E. O'Brien
500c80476e4SDavid E. O'Brien
501c80476e4SDavid E. O'Brien case CC_LIST_GLOB:
502c80476e4SDavid E. O'Brien if (tenematch(InputBuf, Cursor - InputBuf, GLOB) < 0)
503c80476e4SDavid E. O'Brien SoundBeep();
504c80476e4SDavid E. O'Brien curlen = Repair();
505c80476e4SDavid E. O'Brien break;
506c80476e4SDavid E. O'Brien
507c80476e4SDavid E. O'Brien case CC_EXPAND_GLOB:
508c80476e4SDavid E. O'Brien if (tenematch(InputBuf, Cursor - InputBuf, GLOB_EXPAND) <= 0)
509c80476e4SDavid E. O'Brien SoundBeep(); /* Beep = No match */
510c80476e4SDavid E. O'Brien curlen = Repair();
511c80476e4SDavid E. O'Brien break;
512c80476e4SDavid E. O'Brien
513c80476e4SDavid E. O'Brien case CC_NORMALIZE_PATH:
514c80476e4SDavid E. O'Brien if (tenematch(InputBuf, Cursor - InputBuf, PATH_NORMALIZE) <= 0)
515c80476e4SDavid E. O'Brien SoundBeep(); /* Beep = No match */
516c80476e4SDavid E. O'Brien curlen = Repair();
517c80476e4SDavid E. O'Brien break;
518c80476e4SDavid E. O'Brien
519c80476e4SDavid E. O'Brien case CC_EXPAND_VARS:
520c80476e4SDavid E. O'Brien if (tenematch(InputBuf, Cursor - InputBuf, VARS_EXPAND) <= 0)
521c80476e4SDavid E. O'Brien SoundBeep(); /* Beep = No match */
522c80476e4SDavid E. O'Brien curlen = Repair();
523c80476e4SDavid E. O'Brien break;
524c80476e4SDavid E. O'Brien
525c80476e4SDavid E. O'Brien case CC_NORMALIZE_COMMAND:
526c80476e4SDavid E. O'Brien if (tenematch(InputBuf, Cursor - InputBuf, COMMAND_NORMALIZE) <= 0)
527c80476e4SDavid E. O'Brien SoundBeep(); /* Beep = No match */
528c80476e4SDavid E. O'Brien curlen = Repair();
529c80476e4SDavid E. O'Brien break;
530c80476e4SDavid E. O'Brien
531c80476e4SDavid E. O'Brien case CC_HELPME:
532c80476e4SDavid E. O'Brien xputchar('\n');
533c80476e4SDavid E. O'Brien /* should catch ^C here... */
534c80476e4SDavid E. O'Brien (void) tenematch(InputBuf, LastChar - InputBuf, PRINT_HELP);
535c80476e4SDavid E. O'Brien Refresh();
536c80476e4SDavid E. O'Brien Argument = 1;
537c80476e4SDavid E. O'Brien DoingArg = 0;
538c80476e4SDavid E. O'Brien curchoice = -1;
539c80476e4SDavid E. O'Brien curlen = (int) (LastChar - InputBuf);
540c80476e4SDavid E. O'Brien break;
541c80476e4SDavid E. O'Brien
542c80476e4SDavid E. O'Brien case CC_FATAL: /* fatal error, reset to known state */
543c80476e4SDavid E. O'Brien #ifdef DEBUG_EDIT
544c80476e4SDavid E. O'Brien xprintf(CGETS(7, 8, "*** editor fatal ERROR ***\r\n\n"));
545c80476e4SDavid E. O'Brien #endif /* DEBUG_EDIT */
546c80476e4SDavid E. O'Brien /* put (real) cursor in a known place */
547c80476e4SDavid E. O'Brien ClearDisp(); /* reset the display stuff */
548c80476e4SDavid E. O'Brien ResetInLine(1); /* reset the input pointers */
549c80476e4SDavid E. O'Brien Refresh(); /* print the prompt again */
550c80476e4SDavid E. O'Brien Argument = 1;
551c80476e4SDavid E. O'Brien DoingArg = 0;
552c80476e4SDavid E. O'Brien curchoice = -1;
553c80476e4SDavid E. O'Brien curlen = (int) (LastChar - InputBuf);
554c80476e4SDavid E. O'Brien break;
555c80476e4SDavid E. O'Brien
556c80476e4SDavid E. O'Brien case CC_ERROR:
557c80476e4SDavid E. O'Brien default: /* functions we don't know about */
55845e5710bSMark Peek if (adrof(STRhighlight)) {
55945e5710bSMark Peek ClearLines();
56045e5710bSMark Peek ClearDisp();
56145e5710bSMark Peek Refresh();
56245e5710bSMark Peek }
563c80476e4SDavid E. O'Brien DoingArg = 0;
564c80476e4SDavid E. O'Brien Argument = 1;
565c80476e4SDavid E. O'Brien SoundBeep();
566c80476e4SDavid E. O'Brien flush();
567c80476e4SDavid E. O'Brien curchoice = -1;
568c80476e4SDavid E. O'Brien curlen = (int) (LastChar - InputBuf);
569c80476e4SDavid E. O'Brien break;
570c80476e4SDavid E. O'Brien }
571c80476e4SDavid E. O'Brien }
572c80476e4SDavid E. O'Brien (void) Cookedmode(); /* make sure the tty is set up correctly */
573c80476e4SDavid E. O'Brien GettingInput = 0;
574c80476e4SDavid E. O'Brien flush(); /* flush any buffered output */
575c80476e4SDavid E. O'Brien return num;
576c80476e4SDavid E. O'Brien }
577c80476e4SDavid E. O'Brien
578c80476e4SDavid E. O'Brien void
PushMacro(Char * str)57945e5710bSMark Peek PushMacro(Char *str)
580c80476e4SDavid E. O'Brien {
581c80476e4SDavid E. O'Brien if (str != NULL && MacroLvl + 1 < MAXMACROLEVELS) {
582c80476e4SDavid E. O'Brien MacroLvl++;
583c80476e4SDavid E. O'Brien KeyMacro[MacroLvl] = str;
584c80476e4SDavid E. O'Brien }
585c80476e4SDavid E. O'Brien else {
586c80476e4SDavid E. O'Brien SoundBeep();
587c80476e4SDavid E. O'Brien flush();
588c80476e4SDavid E. O'Brien }
589c80476e4SDavid E. O'Brien }
590c80476e4SDavid E. O'Brien
59145e5710bSMark Peek struct eval1_state
59245e5710bSMark Peek {
59345e5710bSMark Peek Char **evalvec, *evalp;
59445e5710bSMark Peek };
59545e5710bSMark Peek
59645e5710bSMark Peek static void
eval1_cleanup(void * xstate)59745e5710bSMark Peek eval1_cleanup(void *xstate)
59845e5710bSMark Peek {
59945e5710bSMark Peek struct eval1_state *state;
60045e5710bSMark Peek
60145e5710bSMark Peek state = xstate;
60245e5710bSMark Peek evalvec = state->evalvec;
60345e5710bSMark Peek evalp = state->evalp;
60445e5710bSMark Peek doneinp = 0;
60545e5710bSMark Peek }
60645e5710bSMark Peek
607c80476e4SDavid E. O'Brien /*
608c80476e4SDavid E. O'Brien * Like eval, only using the current file descriptors
609c80476e4SDavid E. O'Brien */
610c80476e4SDavid E. O'Brien static void
doeval1(Char ** v)61145e5710bSMark Peek doeval1(Char **v)
612c80476e4SDavid E. O'Brien {
61345e5710bSMark Peek struct eval1_state state;
61445e5710bSMark Peek Char **gv;
61545e5710bSMark Peek int gflag;
616c80476e4SDavid E. O'Brien
61745e5710bSMark Peek gflag = tglob(v);
618c80476e4SDavid E. O'Brien if (gflag) {
61945e5710bSMark Peek gv = v = globall(v, gflag);
62045e5710bSMark Peek if (v == 0)
621c80476e4SDavid E. O'Brien stderror(ERR_NOMATCH);
62245e5710bSMark Peek v = copyblk(v);
623c80476e4SDavid E. O'Brien }
624c80476e4SDavid E. O'Brien else {
625c80476e4SDavid E. O'Brien gv = NULL;
62645e5710bSMark Peek v = copyblk(v);
62745e5710bSMark Peek trim(v);
628c80476e4SDavid E. O'Brien }
629c80476e4SDavid E. O'Brien if (gv)
63045e5710bSMark Peek cleanup_push(gv, blk_cleanup);
631c80476e4SDavid E. O'Brien
63245e5710bSMark Peek state.evalvec = evalvec;
63345e5710bSMark Peek state.evalp = evalp;
63445e5710bSMark Peek evalvec = v;
63545e5710bSMark Peek evalp = 0;
63645e5710bSMark Peek cleanup_push(&state, eval1_cleanup);
63745e5710bSMark Peek process(0);
63845e5710bSMark Peek cleanup_until(&state);
63945e5710bSMark Peek if (gv)
64045e5710bSMark Peek cleanup_until(gv);
641c80476e4SDavid E. O'Brien }
642c80476e4SDavid E. O'Brien
643c80476e4SDavid E. O'Brien static void
RunCommand(Char * str)64445e5710bSMark Peek RunCommand(Char *str)
645c80476e4SDavid E. O'Brien {
646c80476e4SDavid E. O'Brien Char *cmd[2];
647c80476e4SDavid E. O'Brien
648c80476e4SDavid E. O'Brien xputchar('\n'); /* Start on a clean line */
649c80476e4SDavid E. O'Brien
650c80476e4SDavid E. O'Brien cmd[0] = str;
651c80476e4SDavid E. O'Brien cmd[1] = NULL;
652c80476e4SDavid E. O'Brien
653c80476e4SDavid E. O'Brien (void) Cookedmode();
654c80476e4SDavid E. O'Brien GettingInput = 0;
655c80476e4SDavid E. O'Brien
656c80476e4SDavid E. O'Brien doeval1(cmd);
657c80476e4SDavid E. O'Brien
658c80476e4SDavid E. O'Brien (void) Rawmode();
659c80476e4SDavid E. O'Brien GettingInput = 1;
660c80476e4SDavid E. O'Brien
661c80476e4SDavid E. O'Brien ClearLines();
662c80476e4SDavid E. O'Brien ClearDisp();
663c80476e4SDavid E. O'Brien NeedsRedraw = 0;
664c80476e4SDavid E. O'Brien Refresh();
665c80476e4SDavid E. O'Brien }
666c80476e4SDavid E. O'Brien
667*cc698b49SBrooks Davis int
GetCmdChar(Char ch)668*cc698b49SBrooks Davis GetCmdChar(Char ch)
669*cc698b49SBrooks Davis {
670*cc698b49SBrooks Davis #ifndef WINNT_NATIVE // We use more than 256 for various extended keys
671*cc698b49SBrooks Davis wint_t c = ch & CHAR;
672*cc698b49SBrooks Davis #else
673*cc698b49SBrooks Davis wint_t c = ch;
674*cc698b49SBrooks Davis #endif
675*cc698b49SBrooks Davis return c < NT_NUM_KEYS ? CurrentKeyMap[c] : F_INSERT;
676*cc698b49SBrooks Davis }
677*cc698b49SBrooks Davis
678c80476e4SDavid E. O'Brien static int
GetNextCommand(KEYCMD * cmdnum,Char * ch)67945e5710bSMark Peek GetNextCommand(KEYCMD *cmdnum, Char *ch)
680c80476e4SDavid E. O'Brien {
681c80476e4SDavid E. O'Brien KEYCMD cmd = 0;
682c80476e4SDavid E. O'Brien int num;
683c80476e4SDavid E. O'Brien
684c80476e4SDavid E. O'Brien while (cmd == 0 || cmd == F_XKEY) {
685c80476e4SDavid E. O'Brien if ((num = GetNextChar(ch)) != 1) { /* if EOF or error */
686c80476e4SDavid E. O'Brien return num;
687c80476e4SDavid E. O'Brien }
688c80476e4SDavid E. O'Brien #ifdef KANJI
68900c801edSDavid E. O'Brien if (
69000c801edSDavid E. O'Brien #ifdef DSPMBYTE
69100c801edSDavid E. O'Brien _enable_mbdisp &&
69223338178SMark Peek #else
69319d2e3deSDmitry Chagin MB_LEN_MAX == 1 &&
69400c801edSDavid E. O'Brien #endif
69500c801edSDavid E. O'Brien !adrof(STRnokanji) && (*ch & META)) {
696c80476e4SDavid E. O'Brien MetaNext = 0;
697c80476e4SDavid E. O'Brien cmd = F_INSERT;
698c80476e4SDavid E. O'Brien break;
699c80476e4SDavid E. O'Brien }
700c80476e4SDavid E. O'Brien else
701c80476e4SDavid E. O'Brien #endif /* KANJI */
702c80476e4SDavid E. O'Brien if (MetaNext) {
703c80476e4SDavid E. O'Brien MetaNext = 0;
704c80476e4SDavid E. O'Brien *ch |= META;
705c80476e4SDavid E. O'Brien }
706*cc698b49SBrooks Davis
707*cc698b49SBrooks Davis cmd = GetCmdChar(*ch);
708c80476e4SDavid E. O'Brien if (cmd == F_XKEY) {
709c80476e4SDavid E. O'Brien XmapVal val;
710c80476e4SDavid E. O'Brien CStr cstr;
711c80476e4SDavid E. O'Brien cstr.buf = ch;
71245e5710bSMark Peek cstr.len = 1;
713c80476e4SDavid E. O'Brien switch (GetXkey(&cstr, &val)) {
714c80476e4SDavid E. O'Brien case XK_CMD:
715c80476e4SDavid E. O'Brien cmd = val.cmd;
716c80476e4SDavid E. O'Brien break;
717c80476e4SDavid E. O'Brien case XK_STR:
718c80476e4SDavid E. O'Brien PushMacro(val.str.buf);
719c80476e4SDavid E. O'Brien break;
720c80476e4SDavid E. O'Brien case XK_EXE:
721c80476e4SDavid E. O'Brien RunCommand(val.str.buf);
722c80476e4SDavid E. O'Brien break;
723c80476e4SDavid E. O'Brien default:
724c80476e4SDavid E. O'Brien abort();
725c80476e4SDavid E. O'Brien break;
726c80476e4SDavid E. O'Brien }
727c80476e4SDavid E. O'Brien }
728c80476e4SDavid E. O'Brien if (!AltKeyMap)
729c80476e4SDavid E. O'Brien CurrentKeyMap = CcKeyMap;
730c80476e4SDavid E. O'Brien }
731c80476e4SDavid E. O'Brien *cmdnum = cmd;
732c80476e4SDavid E. O'Brien return OKCMD;
733c80476e4SDavid E. O'Brien }
734c80476e4SDavid E. O'Brien
73523338178SMark Peek static Char ungetchar;
73623338178SMark Peek static int haveungetchar;
73723338178SMark Peek
73823338178SMark Peek void
UngetNextChar(Char cp)73923338178SMark Peek UngetNextChar(Char cp)
74023338178SMark Peek {
74123338178SMark Peek ungetchar = cp;
74223338178SMark Peek haveungetchar = 1;
74323338178SMark Peek }
74423338178SMark Peek
745c80476e4SDavid E. O'Brien int
GetNextChar(Char * cp)74645e5710bSMark Peek GetNextChar(Char *cp)
747c80476e4SDavid E. O'Brien {
74823338178SMark Peek int num_read;
749c80476e4SDavid E. O'Brien int tried = 0;
75023338178SMark Peek char cbuf[MB_LEN_MAX];
75123338178SMark Peek size_t cbp;
752c80476e4SDavid E. O'Brien
75323338178SMark Peek if (haveungetchar) {
75423338178SMark Peek haveungetchar = 0;
75523338178SMark Peek *cp = ungetchar;
75623338178SMark Peek return 1;
75723338178SMark Peek }
758c80476e4SDavid E. O'Brien for (;;) {
759c80476e4SDavid E. O'Brien if (MacroLvl < 0) {
760c80476e4SDavid E. O'Brien if (!Load_input_line())
761c80476e4SDavid E. O'Brien break;
762c80476e4SDavid E. O'Brien }
763c80476e4SDavid E. O'Brien if (*KeyMacro[MacroLvl] == 0) {
764c80476e4SDavid E. O'Brien MacroLvl--;
765c80476e4SDavid E. O'Brien continue;
766c80476e4SDavid E. O'Brien }
767c80476e4SDavid E. O'Brien *cp = *KeyMacro[MacroLvl]++ & CHAR;
768c80476e4SDavid E. O'Brien if (*KeyMacro[MacroLvl] == 0) { /* Needed for QuoteMode On */
769c80476e4SDavid E. O'Brien MacroLvl--;
770c80476e4SDavid E. O'Brien }
771c80476e4SDavid E. O'Brien return (1);
772c80476e4SDavid E. O'Brien }
773c80476e4SDavid E. O'Brien
774c80476e4SDavid E. O'Brien if (Rawmode() < 0) /* make sure the tty is set up correctly */
775c80476e4SDavid E. O'Brien return 0; /* oops: SHIN was closed */
776c80476e4SDavid E. O'Brien
7773b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE
778c80476e4SDavid E. O'Brien __nt_want_vcode = 1;
7793b6eaa7bSAndrey A. Chernov #endif /* WINNT_NATIVE */
78023338178SMark Peek #ifdef SIG_WINDOW
78123338178SMark Peek if (windowchg)
78223338178SMark Peek (void) check_window_size(0); /* for window systems */
78323338178SMark Peek #endif /* SIG_WINDOW */
78423338178SMark Peek cbp = 0;
78523338178SMark Peek for (;;) {
78645e5710bSMark Peek while ((num_read = xread(SHIN, cbuf + cbp, 1)) == -1) {
787c80476e4SDavid E. O'Brien if (!tried && fixio(SHIN, errno) != -1)
788c80476e4SDavid E. O'Brien tried = 1;
789c80476e4SDavid E. O'Brien else {
790c80476e4SDavid E. O'Brien # ifdef convex
791c80476e4SDavid E. O'Brien /* need to print error message in case the file is migrated */
792c80476e4SDavid E. O'Brien stderror(ERR_SYSTEM, progname, strerror(errno));
793c80476e4SDavid E. O'Brien # endif /* convex */
7943b6eaa7bSAndrey A. Chernov # ifdef WINNT_NATIVE
795c80476e4SDavid E. O'Brien __nt_want_vcode = 0;
7963b6eaa7bSAndrey A. Chernov # endif /* WINNT_NATIVE */
79723338178SMark Peek *cp = '\0'; /* Loses possible partial character */
798c80476e4SDavid E. O'Brien return -1;
799c80476e4SDavid E. O'Brien }
800c80476e4SDavid E. O'Brien }
801*cc698b49SBrooks Davis if (cbp == 0 /* && *cbuf < NT_NUM_KEYS */
802*cc698b49SBrooks Davis && CurrentKeyMap[(unsigned char)*cbuf] == F_XKEY) {
803*cc698b49SBrooks Davis *cp = (unsigned char)*cbuf;
804*cc698b49SBrooks Davis } else {
80523338178SMark Peek cbp++;
80623338178SMark Peek if (normal_mbtowc(cp, cbuf, cbp) == -1) {
80723338178SMark Peek reset_mbtowc();
80845e5710bSMark Peek if (cbp < MB_CUR_MAX)
80923338178SMark Peek continue; /* Maybe a partial character */
81023338178SMark Peek /* And drop the following bytes, if any */
81123338178SMark Peek *cp = (unsigned char)*cbuf | INVALID_BYTE;
81223338178SMark Peek }
813*cc698b49SBrooks Davis }
81423338178SMark Peek break;
81523338178SMark Peek }
8163b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE
81723338178SMark Peek /* This is the part that doesn't work with WIDE_STRINGS */
818c80476e4SDavid E. O'Brien if (__nt_want_vcode == 2)
819c80476e4SDavid E. O'Brien *cp = __nt_vcode;
820c80476e4SDavid E. O'Brien __nt_want_vcode = 0;
8213b6eaa7bSAndrey A. Chernov #endif /* WINNT_NATIVE */
822c80476e4SDavid E. O'Brien return num_read;
823c80476e4SDavid E. O'Brien }
824c80476e4SDavid E. O'Brien
825c80476e4SDavid E. O'Brien /*
826c80476e4SDavid E. O'Brien * SpellLine - do spelling correction on the entire command line
827c80476e4SDavid E. O'Brien * (which may have trailing newline).
828c80476e4SDavid E. O'Brien * If cmdonly is set, only check spelling of command words.
829c80476e4SDavid E. O'Brien * Return value:
830c80476e4SDavid E. O'Brien * -1: Something was incorrectible, and nothing was corrected
831c80476e4SDavid E. O'Brien * 0: Everything was correct
832c80476e4SDavid E. O'Brien * 1: Something was corrected
833c80476e4SDavid E. O'Brien */
834c80476e4SDavid E. O'Brien static int
SpellLine(int cmdonly)83545e5710bSMark Peek SpellLine(int cmdonly)
836c80476e4SDavid E. O'Brien {
837c80476e4SDavid E. O'Brien int endflag, matchval;
838c80476e4SDavid E. O'Brien Char *argptr, *OldCursor, *OldLastChar;
839c80476e4SDavid E. O'Brien
840c80476e4SDavid E. O'Brien OldLastChar = LastChar;
841c80476e4SDavid E. O'Brien OldCursor = Cursor;
842c80476e4SDavid E. O'Brien argptr = InputBuf;
843c80476e4SDavid E. O'Brien endflag = 1;
844c80476e4SDavid E. O'Brien matchval = 0;
845c80476e4SDavid E. O'Brien do {
846c80476e4SDavid E. O'Brien while (ismetahash(*argptr) || iscmdmeta(*argptr))
847c80476e4SDavid E. O'Brien argptr++;
848c80476e4SDavid E. O'Brien for (Cursor = argptr;
849c80476e4SDavid E. O'Brien *Cursor != '\0' && ((Cursor != argptr && Cursor[-1] == '\\') ||
850c80476e4SDavid E. O'Brien (!ismetahash(*Cursor) && !iscmdmeta(*Cursor)));
851c80476e4SDavid E. O'Brien Cursor++)
852c80476e4SDavid E. O'Brien continue;
853c80476e4SDavid E. O'Brien if (*Cursor == '\0') {
854c80476e4SDavid E. O'Brien Cursor = LastChar;
855c80476e4SDavid E. O'Brien if (LastChar[-1] == '\n')
856c80476e4SDavid E. O'Brien Cursor--;
857c80476e4SDavid E. O'Brien endflag = 0;
858c80476e4SDavid E. O'Brien }
859a15e6f9aSMark Peek if (!MISMATCH(*argptr) &&
860c80476e4SDavid E. O'Brien (!cmdonly || starting_a_command(argptr, InputBuf))) {
8613b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE
862c80476e4SDavid E. O'Brien /*
863c80476e4SDavid E. O'Brien * This hack avoids correcting drive letter changes
864c80476e4SDavid E. O'Brien */
865c80476e4SDavid E. O'Brien if ((Cursor - InputBuf) != 2 || (char)InputBuf[1] != ':')
8663b6eaa7bSAndrey A. Chernov #endif /* WINNT_NATIVE */
867c80476e4SDavid E. O'Brien {
868c80476e4SDavid E. O'Brien #ifdef HASH_SPELL_CHECK
869c80476e4SDavid E. O'Brien Char save;
870c80476e4SDavid E. O'Brien size_t len = Cursor - InputBuf;
871c80476e4SDavid E. O'Brien
872c80476e4SDavid E. O'Brien save = InputBuf[len];
873c80476e4SDavid E. O'Brien InputBuf[len] = '\0';
874c80476e4SDavid E. O'Brien if (find_cmd(InputBuf, 0) != 0) {
875c80476e4SDavid E. O'Brien InputBuf[len] = save;
876c80476e4SDavid E. O'Brien argptr = Cursor;
877c80476e4SDavid E. O'Brien continue;
878c80476e4SDavid E. O'Brien }
879c80476e4SDavid E. O'Brien InputBuf[len] = save;
880c80476e4SDavid E. O'Brien #endif /* HASH_SPELL_CHECK */
881c80476e4SDavid E. O'Brien switch (tenematch(InputBuf, Cursor - InputBuf, SPELL)) {
882c80476e4SDavid E. O'Brien case 1: /* corrected */
883c80476e4SDavid E. O'Brien matchval = 1;
884c80476e4SDavid E. O'Brien break;
885c80476e4SDavid E. O'Brien case -1: /* couldn't be corrected */
886c80476e4SDavid E. O'Brien if (!matchval)
887c80476e4SDavid E. O'Brien matchval = -1;
888c80476e4SDavid E. O'Brien break;
889c80476e4SDavid E. O'Brien default: /* was correct */
890c80476e4SDavid E. O'Brien break;
891c80476e4SDavid E. O'Brien }
892c80476e4SDavid E. O'Brien }
893c80476e4SDavid E. O'Brien if (LastChar != OldLastChar) {
894c80476e4SDavid E. O'Brien if (argptr < OldCursor)
895c80476e4SDavid E. O'Brien OldCursor += (LastChar - OldLastChar);
896c80476e4SDavid E. O'Brien OldLastChar = LastChar;
897c80476e4SDavid E. O'Brien }
898c80476e4SDavid E. O'Brien }
899c80476e4SDavid E. O'Brien argptr = Cursor;
900c80476e4SDavid E. O'Brien } while (endflag);
901c80476e4SDavid E. O'Brien Cursor = OldCursor;
902c80476e4SDavid E. O'Brien return matchval;
903c80476e4SDavid E. O'Brien }
904c80476e4SDavid E. O'Brien
905c80476e4SDavid E. O'Brien /*
906c80476e4SDavid E. O'Brien * CompleteLine - do command completion on the entire command line
907c80476e4SDavid E. O'Brien * (which may have trailing newline).
908c80476e4SDavid E. O'Brien * Return value:
909c80476e4SDavid E. O'Brien * 0: No command matched or failure
910c80476e4SDavid E. O'Brien * 1: One command matched
911c80476e4SDavid E. O'Brien * 2: Several commands matched
912c80476e4SDavid E. O'Brien */
913c80476e4SDavid E. O'Brien static int
CompleteLine(void)91445e5710bSMark Peek CompleteLine(void)
915c80476e4SDavid E. O'Brien {
916c80476e4SDavid E. O'Brien int endflag, tmatch;
917c80476e4SDavid E. O'Brien Char *argptr, *OldCursor, *OldLastChar;
918c80476e4SDavid E. O'Brien
919c80476e4SDavid E. O'Brien OldLastChar = LastChar;
920c80476e4SDavid E. O'Brien OldCursor = Cursor;
921c80476e4SDavid E. O'Brien argptr = InputBuf;
922c80476e4SDavid E. O'Brien endflag = 1;
923c80476e4SDavid E. O'Brien do {
924c80476e4SDavid E. O'Brien while (ismetahash(*argptr) || iscmdmeta(*argptr))
925c80476e4SDavid E. O'Brien argptr++;
926c80476e4SDavid E. O'Brien for (Cursor = argptr;
927c80476e4SDavid E. O'Brien *Cursor != '\0' && ((Cursor != argptr && Cursor[-1] == '\\') ||
928c80476e4SDavid E. O'Brien (!ismetahash(*Cursor) && !iscmdmeta(*Cursor)));
929c80476e4SDavid E. O'Brien Cursor++)
930c80476e4SDavid E. O'Brien continue;
931c80476e4SDavid E. O'Brien if (*Cursor == '\0') {
932c80476e4SDavid E. O'Brien Cursor = LastChar;
933c80476e4SDavid E. O'Brien if (LastChar[-1] == '\n')
934c80476e4SDavid E. O'Brien Cursor--;
935c80476e4SDavid E. O'Brien endflag = 0;
936c80476e4SDavid E. O'Brien }
937a15e6f9aSMark Peek if (!MISMATCH(*argptr) && starting_a_command(argptr, InputBuf)) {
938c80476e4SDavid E. O'Brien tmatch = tenematch(InputBuf, Cursor - InputBuf, RECOGNIZE);
939c80476e4SDavid E. O'Brien if (tmatch <= 0) {
940c80476e4SDavid E. O'Brien return 0;
941c80476e4SDavid E. O'Brien } else if (tmatch > 1) {
942c80476e4SDavid E. O'Brien return 2;
943c80476e4SDavid E. O'Brien }
944c80476e4SDavid E. O'Brien if (LastChar != OldLastChar) {
945c80476e4SDavid E. O'Brien if (argptr < OldCursor)
946c80476e4SDavid E. O'Brien OldCursor += (LastChar - OldLastChar);
947c80476e4SDavid E. O'Brien OldLastChar = LastChar;
948c80476e4SDavid E. O'Brien }
949c80476e4SDavid E. O'Brien }
950c80476e4SDavid E. O'Brien argptr = Cursor;
951c80476e4SDavid E. O'Brien } while (endflag);
952c80476e4SDavid E. O'Brien Cursor = OldCursor;
953c80476e4SDavid E. O'Brien return 1;
954c80476e4SDavid E. O'Brien }
955c80476e4SDavid E. O'Brien
956