diff options
Diffstat (limited to 'contrib/tcsh/ed.inputl.c')
-rw-r--r-- | contrib/tcsh/ed.inputl.c | 903 |
1 files changed, 903 insertions, 0 deletions
diff --git a/contrib/tcsh/ed.inputl.c b/contrib/tcsh/ed.inputl.c new file mode 100644 index 0000000..2842d7d --- /dev/null +++ b/contrib/tcsh/ed.inputl.c @@ -0,0 +1,903 @@ +/* $Header: /src/pub/tcsh/ed.inputl.c,v 3.47 1999/04/20 07:48:39 christos Exp $ */ +/* + * ed.inputl.c: Input line handling. + */ +/*- + * Copyright (c) 1980, 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include "sh.h" + +RCSID("$Id: ed.inputl.c,v 3.47 1999/04/20 07:48:39 christos Exp $") + +#include "ed.h" +#include "ed.defns.h" /* for the function names */ +#include "tw.h" /* for twenex stuff */ + +#define OKCMD (INBUFSIZE+INBUFSIZE) + +/* ed.inputl -- routines to get a single line from the input. */ + +extern bool tellwhat; +extern bool MapsAreInited; +extern bool Tty_raw_mode; + +/* mismatched first character */ +static Char mismatch[] = + {'!', '^' , '\\', '-', '%', '\0', '"', '\'', '`', '\0' }; + +static int Repair __P((void)); +static int GetNextCommand __P((KEYCMD *, Char *)); +static int SpellLine __P((int)); +static int CompleteLine __P((void)); +static void RunCommand __P((Char *)); +static void doeval1 __P((Char **)); + +static bool rotate = 0; + + +static int +Repair() +{ + if (NeedsRedraw) { + ClearLines(); + ClearDisp(); + NeedsRedraw = 0; + } + Refresh(); + Argument = 1; + DoingArg = 0; + curchoice = -1; + return (int) (LastChar - InputBuf); +} + +/* CCRETVAL */ +int +Inputl() +{ + CCRETVAL retval; + KEYCMD cmdnum = 0; + extern KEYCMD NumFuns; + unsigned char tch; /* the place where read() goes */ + Char ch; + int num; /* how many chars we have read at NL */ + int expnum; + struct varent *crct = inheredoc ? NULL : adrof(STRcorrect); + struct varent *autol = adrof(STRautolist); + struct varent *matchbeep = adrof(STRmatchbeep); + struct varent *imode = adrof(STRinputmode); + Char *SaveChar, *CorrChar; + Char Origin[INBUFSIZE], Change[INBUFSIZE]; + int matchval; /* from tenematch() */ + COMMAND fn; + int curlen = 0; + int newlen; + int idx; + + if (!MapsAreInited) /* double extra just in case */ + ed_InitMaps(); + + ClearDisp(); /* reset the display stuff */ + ResetInLine(0); /* reset the input pointers */ + if (GettingInput) + MacroLvl = -1; /* editor was interrupted during input */ + + if (imode) { + if (!Strcmp(*(imode->vec), STRinsert)) + inputmode = MODE_INSERT; + else if (!Strcmp(*(imode->vec), STRoverwrite)) + inputmode = MODE_REPLACE; + } + +#if defined(FIONREAD) && !defined(OREO) + if (!Tty_raw_mode && MacroLvl < 0) { +# ifdef SUNOS4 + long chrs = 0; +# else /* !SUNOS4 */ + /* + * *Everyone* else has an int, but SunOS wants long! + * This breaks where int != long (alpha) + */ + int chrs = 0; +# endif /* SUNOS4 */ + + (void) ioctl(SHIN, FIONREAD, (ioctl_t) & chrs); + if (chrs == 0) { + if (Rawmode() < 0) + return 0; + } + } +#endif /* FIONREAD && !OREO */ + + GettingInput = 1; + NeedsRedraw = 0; + + if (tellwhat) { + copyn(InputBuf, WhichBuf, INBUFSIZE); + LastChar = InputBuf + (LastWhich - WhichBuf); + Cursor = InputBuf + (CursWhich - WhichBuf); + tellwhat = 0; + Hist_num = HistWhich; + } + if (Expand) { + (void) e_up_hist(0); + Expand = 0; + } + Refresh(); /* print the prompt */ + + for (num = OKCMD; num == OKCMD;) { /* while still editing this line */ +#ifdef DEBUG_EDIT + if (Cursor > LastChar) + xprintf("Cursor > LastChar\r\n"); + if (Cursor < InputBuf) + xprintf("Cursor < InputBuf\r\n"); + if (Cursor > InputLim) + xprintf("Cursor > InputLim\r\n"); + if (LastChar > InputLim) + xprintf("LastChar > InputLim\r\n"); + if (InputLim != &InputBuf[INBUFSIZE - 2]) + xprintf("InputLim != &InputBuf[INBUFSIZE-2]\r\n"); + if ((!DoingArg) && (Argument != 1)) + xprintf("(!DoingArg) && (Argument != 1)\r\n"); + if (CcKeyMap[0] == 0) + xprintf("CcKeyMap[0] == 0 (maybe not inited)\r\n"); +#endif + + /* if EOF or error */ + if ((num = GetNextCommand(&cmdnum, &ch)) != OKCMD) { + break; + } + + if (cmdnum >= NumFuns) {/* BUG CHECK command */ +#ifdef DEBUG_EDIT + xprintf(CGETS(6, 1, "ERROR: illegal command from key 0%o\r\n"), ch); +#endif + continue; /* try again */ + } + + /* now do the real command */ + retval = (*CcFuncTbl[cmdnum]) (ch); + + /* save the last command here */ + LastCmd = cmdnum; + + /* make sure fn is initialized */ + fn = (retval == CC_COMPLETE_ALL) ? LIST_ALL : LIST; + + /* use any return value */ + switch (retval) { + + case CC_REFRESH: + Refresh(); + /*FALLTHROUGH*/ + case CC_NORM: /* normal char */ + Argument = 1; + DoingArg = 0; + /*FALLTHROUGH*/ + case CC_ARGHACK: /* Suggested by Rich Salz */ + /* <rsalz@pineapple.bbn.com> */ + curchoice = -1; + curlen = (int) (LastChar - InputBuf); + break; /* keep going... */ + + case CC_EOF: /* end of file typed */ + curchoice = -1; + curlen = (int) (LastChar - InputBuf); + num = 0; + break; + + case CC_WHICH: /* tell what this command does */ + tellwhat = 1; + copyn(WhichBuf, InputBuf, INBUFSIZE); + LastWhich = WhichBuf + (LastChar - InputBuf); + CursWhich = WhichBuf + (Cursor - InputBuf); + *LastChar++ = '\n'; /* for the benifit of CSH */ + HistWhich = Hist_num; + Hist_num = 0; /* for the history commands */ + num = (int) (LastChar - InputBuf); /* number characters read */ + break; + + case CC_NEWLINE: /* normal end of line */ + curlen = 0; + curchoice = -1; + matchval = 1; + if (crct && (!Strcmp(*(crct->vec), STRcmd) || + !Strcmp(*(crct->vec), STRall))) { + PastBottom(); + copyn(Origin, InputBuf, INBUFSIZE); + SaveChar = LastChar; + if (SpellLine(!Strcmp(*(crct->vec), STRcmd)) == 1) { + PastBottom(); + copyn(Change, InputBuf, INBUFSIZE); + *Strchr(Change, '\n') = '\0'; + CorrChar = LastChar; /* Save the corrected end */ + LastChar = InputBuf; /* Null the current line */ + SoundBeep(); + printprompt(2, short2str(Change)); + Refresh(); + if (read(SHIN, (char *) &tch, 1) < 0) +#ifdef convex + /* + * need to print error message in case file + * is migrated + */ + if (errno && errno != EINTR) + stderror(ERR_SYSTEM, progname, strerror(errno)); +#else + break; +#endif + ch = tch; + if (ch == 'y' || ch == ' ') { + LastChar = CorrChar; /* Restore the corrected end */ + xprintf(CGETS(6, 2, "yes\n")); + } + else { + copyn(InputBuf, Origin, INBUFSIZE); + LastChar = SaveChar; + if (ch == 'e') { + xprintf(CGETS(6, 3, "edit\n")); + *LastChar-- = '\0'; + Cursor = LastChar; + printprompt(3, NULL); + ClearLines(); + ClearDisp(); + Refresh(); + break; + } + else if (ch == 'a') { + xprintf(CGETS(6, 4, "abort\n")); + LastChar = InputBuf; /* Null the current line */ + Cursor = LastChar; + printprompt(0, NULL); + Refresh(); + break; + } + xprintf(CGETS(6, 5, "no\n")); + } + flush(); + } + } else if (crct && !Strcmp(*(crct->vec), STRcomplete)) { + if (LastChar > InputBuf && LastChar[-1] == '\n') { + LastChar[-1] = '\0'; + LastChar--; + Cursor = LastChar; + } + match_unique_match = 1; /* match unique matches */ + matchval = CompleteLine(); + match_unique_match = 0; + curlen = (int) (LastChar - InputBuf); + if (matchval != 1) { + PastBottom(); + } + if (matchval == 0) { + xprintf(CGETS(6, 6, "No matching command\n")); + } else if (matchval == 2) { + xprintf(CGETS(6, 7, "Ambiguous command\n")); + } + if (NeedsRedraw) { + ClearLines(); + ClearDisp(); + NeedsRedraw = 0; + } + Refresh(); + Argument = 1; + DoingArg = 0; + if (matchval == 1) { + PastBottom(); + *LastChar++ = '\n'; + *LastChar = '\0'; + } + curlen = (int) (LastChar - InputBuf); + } + else + PastBottom(); + + if (matchval == 1) { + tellwhat = 0; /* just in case */ + Hist_num = 0; /* for the history commands */ + /* return the number of chars read */ + num = (int) (LastChar - InputBuf); + /* + * For continuation lines, we set the prompt to prompt 2 + */ + printprompt(1, NULL); + } + break; + + case CC_CORRECT: + if (tenematch(InputBuf, Cursor - InputBuf, SPELL) < 0) + SoundBeep(); /* Beep = No match/ambiguous */ + curlen = Repair(); + break; + + case CC_CORRECT_L: + if (SpellLine(FALSE) < 0) + SoundBeep(); /* Beep = No match/ambiguous */ + curlen = Repair(); + break; + + + case CC_COMPLETE: + case CC_COMPLETE_ALL: + case CC_COMPLETE_FWD: + case CC_COMPLETE_BACK: + switch (retval) { + case CC_COMPLETE: + fn = RECOGNIZE; + curlen = (int) (LastChar - InputBuf); + curchoice = -1; + rotate = 0; + break; + case CC_COMPLETE_ALL: + fn = RECOGNIZE_ALL; + curlen = (int) (LastChar - InputBuf); + curchoice = -1; + rotate = 0; + break; + case CC_COMPLETE_FWD: + fn = RECOGNIZE_SCROLL; + curchoice++; + rotate = 1; + break; + case CC_COMPLETE_BACK: + fn = RECOGNIZE_SCROLL; + curchoice--; + rotate = 1; + break; + default: + abort(); + } + if (InputBuf[curlen] && rotate) { + newlen = (int) (LastChar - InputBuf); + for (idx = (int) (Cursor - InputBuf); + idx <= newlen; idx++) + InputBuf[idx - newlen + curlen] = + InputBuf[idx]; + LastChar = InputBuf + curlen; + Cursor = Cursor - newlen + curlen; + } + curlen = (int) (LastChar - InputBuf); + + + if (adrof(STRautoexpand)) + (void) e_expand_history(0); + /* + * Modified by Martin Boyer (gamin@ireq-robot.hydro.qc.ca): + * A separate variable now controls beeping after + * completion, independently of autolisting. + */ + expnum = (int) (Cursor - InputBuf); + switch (matchval = tenematch(InputBuf, Cursor-InputBuf, fn)){ + case 1: + if (non_unique_match && matchbeep && + (Strcmp(*(matchbeep->vec), STRnotunique) == 0)) + SoundBeep(); + break; + case 0: + if (matchbeep) { + if (Strcmp(*(matchbeep->vec), STRnomatch) == 0 || + Strcmp(*(matchbeep->vec), STRambiguous) == 0 || + Strcmp(*(matchbeep->vec), STRnotunique) == 0) + SoundBeep(); + } + else + SoundBeep(); + break; + default: + if (matchval < 0) { /* Error from tenematch */ + curchoice = -1; + SoundBeep(); + break; + } + if (matchbeep) { + if ((Strcmp(*(matchbeep->vec), STRambiguous) == 0 || + Strcmp(*(matchbeep->vec), STRnotunique) == 0)) + SoundBeep(); + } + else + SoundBeep(); + /* + * Addition by David C Lawrence <tale@pawl.rpi.edu>: If an + * attempted completion is ambiguous, list the choices. + * (PWP: this is the best feature addition to tcsh I have + * seen in many months.) + */ + if (autol && (Strcmp(*(autol->vec), STRambiguous) != 0 || + expnum == Cursor - InputBuf)) { + PastBottom(); + fn = (retval == CC_COMPLETE_ALL) ? LIST_ALL : LIST; + (void) tenematch(InputBuf, Cursor-InputBuf, fn); + } + break; + } + if (NeedsRedraw) { + PastBottom(); + ClearLines(); + ClearDisp(); + NeedsRedraw = 0; + } + Refresh(); + Argument = 1; + DoingArg = 0; + break; + + case CC_LIST_CHOICES: + case CC_LIST_ALL: + if (InputBuf[curlen] && rotate) { + newlen = (int) (LastChar - InputBuf); + for (idx = (int) (Cursor - InputBuf); + idx <= newlen; idx++) + InputBuf[idx - newlen + curlen] = + InputBuf[idx]; + LastChar = InputBuf + curlen; + Cursor = Cursor - newlen + curlen; + } + curlen = (int) (LastChar - InputBuf); + if (curchoice >= 0) + curchoice--; + + fn = (retval == CC_LIST_ALL) ? LIST_ALL : LIST; + /* should catch ^C here... */ + if (tenematch(InputBuf, Cursor - InputBuf, fn) < 0) + SoundBeep(); + Refresh(); + Argument = 1; + DoingArg = 0; + break; + + + case CC_LIST_GLOB: + if (tenematch(InputBuf, Cursor - InputBuf, GLOB) < 0) + SoundBeep(); + curlen = Repair(); + break; + + case CC_EXPAND_GLOB: + if (tenematch(InputBuf, Cursor - InputBuf, GLOB_EXPAND) <= 0) + SoundBeep(); /* Beep = No match */ + curlen = Repair(); + break; + + case CC_NORMALIZE_PATH: + if (tenematch(InputBuf, Cursor - InputBuf, PATH_NORMALIZE) <= 0) + SoundBeep(); /* Beep = No match */ + curlen = Repair(); + break; + + case CC_EXPAND_VARS: + if (tenematch(InputBuf, Cursor - InputBuf, VARS_EXPAND) <= 0) + SoundBeep(); /* Beep = No match */ + curlen = Repair(); + break; + + case CC_NORMALIZE_COMMAND: + if (tenematch(InputBuf, Cursor - InputBuf, COMMAND_NORMALIZE) <= 0) + SoundBeep(); /* Beep = No match */ + curlen = Repair(); + break; + + case CC_HELPME: + xputchar('\n'); + /* should catch ^C here... */ + (void) tenematch(InputBuf, LastChar - InputBuf, PRINT_HELP); + Refresh(); + Argument = 1; + DoingArg = 0; + curchoice = -1; + curlen = (int) (LastChar - InputBuf); + break; + + case CC_FATAL: /* fatal error, reset to known state */ +#ifdef DEBUG_EDIT + xprintf(CGETS(7, 8, "*** editor fatal ERROR ***\r\n\n")); +#endif /* DEBUG_EDIT */ + /* put (real) cursor in a known place */ + ClearDisp(); /* reset the display stuff */ + ResetInLine(1); /* reset the input pointers */ + Refresh(); /* print the prompt again */ + Argument = 1; + DoingArg = 0; + curchoice = -1; + curlen = (int) (LastChar - InputBuf); + break; + + case CC_ERROR: + default: /* functions we don't know about */ + DoingArg = 0; + Argument = 1; + SoundBeep(); + flush(); + curchoice = -1; + curlen = (int) (LastChar - InputBuf); + break; + } + } + (void) Cookedmode(); /* make sure the tty is set up correctly */ + GettingInput = 0; + flush(); /* flush any buffered output */ + return num; +} + +void +PushMacro(str) + Char *str; +{ + if (str != NULL && MacroLvl + 1 < MAXMACROLEVELS) { + MacroLvl++; + KeyMacro[MacroLvl] = str; + } + else { + SoundBeep(); + flush(); + } +} + +/* + * Like eval, only using the current file descriptors + */ +static Char **gv = NULL, **gav = NULL; + +static void +doeval1(v) + Char **v; +{ + Char **oevalvec; + Char *oevalp; + int my_reenter; + Char **savegv; + jmp_buf_t osetexit; + + oevalvec = evalvec; + oevalp = evalp; + savegv = gv; + gav = v; + + + gflag = 0, tglob(gav); + if (gflag) { + gv = gav = globall(gav); + gargv = 0; + if (gav == 0) + stderror(ERR_NOMATCH); + gav = copyblk(gav); + } + else { + gv = NULL; + gav = copyblk(gav); + trim(gav); + } + + getexit(osetexit); + + /* PWP: setjmp/longjmp bugfix for optimizing compilers */ +#ifdef cray + my_reenter = 1; /* assume non-zero return val */ + if (setexit() == 0) { + my_reenter = 0; /* Oh well, we were wrong */ +#else /* !cray */ + if ((my_reenter = setexit()) == 0) { +#endif /* cray */ + evalvec = gav; + evalp = 0; + process(0); + } + + evalvec = oevalvec; + evalp = oevalp; + doneinp = 0; + + if (gv) + blkfree(gv); + + gv = savegv; + resexit(osetexit); + if (my_reenter) + stderror(ERR_SILENT); +} + +static void +RunCommand(str) + Char *str; +{ + Char *cmd[2]; + + xputchar('\n'); /* Start on a clean line */ + + cmd[0] = str; + cmd[1] = NULL; + + (void) Cookedmode(); + GettingInput = 0; + + doeval1(cmd); + + (void) Rawmode(); + GettingInput = 1; + + ClearLines(); + ClearDisp(); + NeedsRedraw = 0; + Refresh(); +} + +static int +GetNextCommand(cmdnum, ch) + KEYCMD *cmdnum; + register Char *ch; +{ + KEYCMD cmd = 0; + int num; + + while (cmd == 0 || cmd == F_XKEY) { + if ((num = GetNextChar(ch)) != 1) { /* if EOF or error */ + return num; + } +#ifdef KANJI + if (!adrof(STRnokanji) && (*ch & META)) { + MetaNext = 0; + cmd = F_INSERT; + break; + } + else +#endif /* KANJI */ + if (MetaNext) { + MetaNext = 0; + *ch |= META; + } + /* XXX: This needs to be fixed so that we don't just truncate + * the character, we unquote it. + */ + if (*ch < NT_NUM_KEYS) + cmd = CurrentKeyMap[*ch]; + else + cmd = CurrentKeyMap[(unsigned char) *ch]; + if (cmd == F_XKEY) { + XmapVal val; + CStr cstr; + cstr.buf = ch; + cstr.len = Strlen(ch); + switch (GetXkey(&cstr, &val)) { + case XK_CMD: + cmd = val.cmd; + break; + case XK_STR: + PushMacro(val.str.buf); + break; + case XK_EXE: + RunCommand(val.str.buf); + break; + default: + abort(); + break; + } + } + if (!AltKeyMap) + CurrentKeyMap = CcKeyMap; + } + *cmdnum = cmd; + return OKCMD; +} + +int +GetNextChar(cp) + register Char *cp; +{ + register int num_read; + int tried = 0; + unsigned char tcp; + + for (;;) { + if (MacroLvl < 0) { + if (!Load_input_line()) + break; + } + if (*KeyMacro[MacroLvl] == 0) { + MacroLvl--; + continue; + } + *cp = *KeyMacro[MacroLvl]++ & CHAR; + if (*KeyMacro[MacroLvl] == 0) { /* Needed for QuoteMode On */ + MacroLvl--; + } + return (1); + } + + if (Rawmode() < 0) /* make sure the tty is set up correctly */ + return 0; /* oops: SHIN was closed */ + +#ifdef WINNT + __nt_want_vcode = 1; +#endif /* WINNT */ + while ((num_read = read(SHIN, (char *) &tcp, 1)) == -1) { + if (errno == EINTR) + continue; + if (!tried && fixio(SHIN, errno) != -1) + tried = 1; + else { +#ifdef convex + /* need to print error message in case the file is migrated */ + if (errno != EINTR) + stderror(ERR_SYSTEM, progname, strerror(errno)); +#endif /* convex */ +#ifdef WINNT + __nt_want_vcode = 0; +#endif /* WINNT */ + *cp = '\0'; + return -1; + } + } +#ifdef WINNT + if (__nt_want_vcode == 2) + *cp = __nt_vcode; + else + *cp = tcp; + __nt_want_vcode = 0; +#else + *cp = tcp; +#endif /* WINNT */ + return num_read; +} + +/* + * SpellLine - do spelling correction on the entire command line + * (which may have trailing newline). + * If cmdonly is set, only check spelling of command words. + * Return value: + * -1: Something was incorrectible, and nothing was corrected + * 0: Everything was correct + * 1: Something was corrected + */ +static int +SpellLine(cmdonly) + int cmdonly; +{ + int endflag, matchval; + Char *argptr, *OldCursor, *OldLastChar; + + OldLastChar = LastChar; + OldCursor = Cursor; + argptr = InputBuf; + endflag = 1; + matchval = 0; + do { + while (ismetahash(*argptr) || iscmdmeta(*argptr)) + argptr++; + for (Cursor = argptr; + *Cursor != '\0' && ((Cursor != argptr && Cursor[-1] == '\\') || + (!ismetahash(*Cursor) && !iscmdmeta(*Cursor))); + Cursor++) + continue; + if (*Cursor == '\0') { + Cursor = LastChar; + if (LastChar[-1] == '\n') + Cursor--; + endflag = 0; + } + /* Obey current history character settings */ + mismatch[0] = HIST; + mismatch[1] = HISTSUB; + if (!Strchr(mismatch, *argptr) && + (!cmdonly || starting_a_command(argptr, InputBuf))) { +#ifdef WINNT + /* + * This hack avoids correcting drive letter changes + */ + if((Cursor - InputBuf) != 2 || (char)InputBuf[1] != ':') +#endif /* WINNT */ + { +#ifdef HASH_SPELL_CHECK + Char save; + size_t len = Cursor - InputBuf; + + save = InputBuf[len]; + InputBuf[len] = '\0'; + if (find_cmd(InputBuf, 0) != 0) { + InputBuf[len] = save; + argptr = Cursor; + continue; + } + InputBuf[len] = save; +#endif /* HASH_SPELL_CHECK */ + switch (tenematch(InputBuf, Cursor - InputBuf, SPELL)) { + case 1: /* corrected */ + matchval = 1; + break; + case -1: /* couldn't be corrected */ + if (!matchval) + matchval = -1; + break; + default: /* was correct */ + break; + } + } + if (LastChar != OldLastChar) { + if (argptr < OldCursor) + OldCursor += (LastChar - OldLastChar); + OldLastChar = LastChar; + } + } + argptr = Cursor; + } while (endflag); + Cursor = OldCursor; + return matchval; +} + +/* + * CompleteLine - do command completion on the entire command line + * (which may have trailing newline). + * Return value: + * 0: No command matched or failure + * 1: One command matched + * 2: Several commands matched + */ +static int +CompleteLine() +{ + int endflag, tmatch; + Char *argptr, *OldCursor, *OldLastChar; + + OldLastChar = LastChar; + OldCursor = Cursor; + argptr = InputBuf; + endflag = 1; + do { + while (ismetahash(*argptr) || iscmdmeta(*argptr)) + argptr++; + for (Cursor = argptr; + *Cursor != '\0' && ((Cursor != argptr && Cursor[-1] == '\\') || + (!ismetahash(*Cursor) && !iscmdmeta(*Cursor))); + Cursor++) + continue; + if (*Cursor == '\0') { + Cursor = LastChar; + if (LastChar[-1] == '\n') + Cursor--; + endflag = 0; + } + if (!Strchr(mismatch, *argptr) && starting_a_command(argptr, InputBuf)) { + tmatch = tenematch(InputBuf, Cursor - InputBuf, RECOGNIZE); + if (tmatch <= 0) { + return 0; + } else if (tmatch > 1) { + return 2; + } + if (LastChar != OldLastChar) { + if (argptr < OldCursor) + OldCursor += (LastChar - OldLastChar); + OldLastChar = LastChar; + } + } + argptr = Cursor; + } while (endflag); + Cursor = OldCursor; + return 1; +} + |