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