1: /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.00/RCS/ed.inputl.c,v 3.0 1991/07/04 21:49:28 christos Exp $ */
   2: /*
   3:  * ed.inputl.c: Input line handling.
   4:  */
   5: /*-
   6:  * Copyright (c) 1980, 1991 The Regents of the University of California.
   7:  * All rights reserved.
   8:  *
   9:  * Redistribution and use in source and binary forms, with or without
  10:  * modification, are permitted provided that the following conditions
  11:  * are met:
  12:  * 1. Redistributions of source code must retain the above copyright
  13:  *    notice, this list of conditions and the following disclaimer.
  14:  * 2. Redistributions in binary form must reproduce the above copyright
  15:  *    notice, this list of conditions and the following disclaimer in the
  16:  *    documentation and/or other materials provided with the distribution.
  17:  * 3. All advertising materials mentioning features or use of this software
  18:  *    must display the following acknowledgement:
  19:  *	This product includes software developed by the University of
  20:  *	California, Berkeley and its contributors.
  21:  * 4. Neither the name of the University nor the names of its contributors
  22:  *    may be used to endorse or promote products derived from this software
  23:  *    without specific prior written permission.
  24:  *
  25:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35:  * SUCH DAMAGE.
  36:  */
  37: #include "config.h"
  38: #if !defined(lint) && !defined(pdp11)
  39: static char *rcsid()
  40:     { return "$Id: ed.inputl.c,v 3.0 1991/07/04 21:49:28 christos Exp $"; }
  41: #endif
  42: 
  43: #include "sh.h"
  44: #include "ed.h"
  45: #include "ed.defns.h"       /* for the function names */
  46: #include "tw.h"         /* for twenex stuff */
  47: 
  48: #define OKCMD (INBUFSIZ+INBUFSIZ)
  49: extern CCRETVAL e_up_hist();
  50: extern CCRETVAL e_ex_history();
  51: 
  52: /* ed.inputl -- routines to get a single line from the input. */
  53: 
  54: extern bool tellwhat;
  55: extern bool MapsAreInited;
  56: extern bool Tty_raw_mode;
  57: 
  58: /* mismatched first character */
  59: static Char mismatch[] = {'!', '\\', '^', '-', '%', '\0'};
  60: 
  61: static  int G_N_Command __P((KEYCMD *, Char *));
  62: static  int SpellLine   __P((int));
  63: 
  64: /* CCRETVAL */
  65: int
  66: Inputl()
  67: {
  68:     CCRETVAL retval;
  69:     KEYCMD  cmdnum = 0;
  70:     extern KEYCMD NumFuns;
  71:     unsigned char tch;      /* the place where read() goes */
  72:     Char    ch;
  73:     int     num;        /* how many chars we have read at NL */
  74:     struct varent *crct = adrof(STRcorrect);
  75:     struct varent *matchbeep = adrof(STRmatchbeep);
  76:     Char   *SaveChar, *CorrChar;
  77:     Char    Origin[INBUFSIZ], Change[INBUFSIZ];
  78:     int     matchval;       /* from tenematch() */
  79: 
  80:     if (!MapsAreInited)     /* double extra just in case */
  81:     ed_IMaps();
  82: 
  83:     ClearDisp();        /* reset the display stuff */
  84:     ResetInLine();      /* reset the input pointers */
  85:     if (GettingInput)
  86:     MacroLvl = -1;      /* editor was interrupted during input */
  87: 
  88: #ifdef FIONREAD
  89:     if (!Tty_raw_mode && MacroLvl < 0) {
  90:     long    chrs = 0;
  91: 
  92:     (void) ioctl(SHIN, FIONREAD, (ioctl_t) & chrs);
  93:     if (chrs == 0) {
  94:         if (Rawmode() < 0)
  95:         return 0;
  96:     }
  97:     }
  98: #endif
  99: 
 100:     GettingInput = 1;
 101:     NeedsRedraw = 0;
 102: 
 103:     if (tellwhat) {
 104:     copyn(InputBuf, WhichBuf, INBUFSIZ);
 105:     LastChar = InputBuf + (LastWhich - WhichBuf);
 106:     Cursor = InputBuf + (CursWhich - WhichBuf);
 107:     tellwhat = 0;
 108:     Hist_num = HistWhich;
 109:     }
 110:     if (Expand) {
 111:     (void) e_up_hist();
 112:     Expand = 0;
 113:     }
 114:     Refresh();          /* print the prompt */
 115: 
 116:     for (num = OKCMD; num == OKCMD;) {  /* while still editing this line */
 117: #ifdef DEBUG_EDIT
 118:     if (Cursor > LastChar)
 119:         xprintf("Cursor > LastChar\r\n");
 120:     if (Cursor < InputBuf)
 121:         xprintf("Cursor < InputBuf\r\n");
 122:     if (Cursor > InputLim)
 123:         xprintf("Cursor > InputLim\r\n");
 124:     if (LastChar > InputLim)
 125:         xprintf("LastChar > InputLim\r\n");
 126:     if (InputLim != &InputBuf[INBUFSIZ - 2])
 127:         xprintf("InputLim != &InputBuf[INBUFSIZ-2]\r\n");
 128:     if ((!DoingArg) && (Argument != 1))
 129:         xprintf("(!DoingArg) && (Argument != 1)\r\n");
 130:     if (CcKeyMap[0] == 0)
 131:         xprintf("CcKeyMap[0] == 0 (maybe not inited)\r\n");
 132: #endif
 133: 
 134:     /* if EOF or error */
 135:     if ((num = G_N_Command(&cmdnum, &ch)) != OKCMD) {
 136:         break;
 137:     }
 138: 
 139:     if (cmdnum >= NumFuns) {/* BUG CHECK command */
 140: #ifdef DEBUG_EDIT
 141:         xprintf("ERROR: illegal command from key 0%o\r\n", ch);
 142: #endif
 143:         continue;       /* try again */
 144:     }
 145: 
 146:     /* now do the real command */
 147:     retval = (*CcFuncTbl[cmdnum]) (ch);
 148: 
 149:     /* save the last command here */
 150:     LastCmd = cmdnum;
 151: 
 152:     /* use any return value */
 153:     switch (retval) {
 154: 
 155:     case CC_REFRESH:
 156:         Refresh();
 157:         /* fall through */
 158:     case CC_NORM:       /* normal char */
 159:         Argument = 1;
 160:         DoingArg = 0;
 161:         /* fall through */
 162:     case CC_ARGHACK:    /* Suggested by Rich Salz */
 163:         /* <rsalz@pineapple.bbn.com> */
 164:         break;      /* keep going... */
 165: 
 166:     case CC_EOF:        /* end of file typed */
 167: #ifdef notdef
 168:         PromptBuf[0] = '\0';
 169: #endif
 170:         num = 0;
 171:         break;
 172: 
 173:     case CC_WHICH:      /* tell what this command does */
 174:         tellwhat = 1;
 175:         copyn(WhichBuf, InputBuf, INBUFSIZ);
 176:         LastWhich = WhichBuf + (LastChar - InputBuf);
 177:         CursWhich = WhichBuf + (Cursor - InputBuf);
 178:         *LastChar++ = '\n'; /* for the benifit of CSH */
 179:         HistWhich = Hist_num;
 180:         Hist_num = 0;   /* for the history commands */
 181:         num = LastChar - InputBuf;  /* number characters read */
 182: #ifdef notdef
 183:         ResetInLine();  /* reset the input pointers */
 184: #endif
 185:         break;
 186: 
 187:     case CC_NEWLINE:    /* normal end of line */
 188:         if (crct && (!Strcmp(*(crct->vec), STRcmd) ||
 189:              !Strcmp(*(crct->vec), STRall))) {
 190:         (void) Strcpy(Origin, InputBuf);
 191:         SaveChar = LastChar;
 192:         if (SpellLine(!Strcmp(*(crct->vec), STRcmd)) == 1) {
 193:             (void) Strcpy(Change, InputBuf);
 194:             *Strchr(Change, '\n') = '\0';
 195:             CorrChar = LastChar;    /* Save the corrected end */
 196:             LastChar = InputBuf;    /* Null the current line */
 197:             Beep();
 198:             printprompt(2, Change);
 199:             Refresh();
 200:             (void) read(SHIN, (char *) &tch, 1);
 201:             ch = tch;
 202:             if (ch != 'y' && ch != ' ') {
 203:             (void) Strcpy(InputBuf, Origin);
 204:             LastChar = SaveChar;
 205:             xprintf("no\n");
 206:             }
 207:             else {
 208:             LastChar = CorrChar;    /* Restore the corrected end */
 209:             xprintf("yes\n");
 210:             }
 211:             flush();
 212:         }
 213:         }           /* end CORRECT code */
 214:         tellwhat = 0;   /* just in case */
 215:         Hist_num = 0;   /* for the history commands */
 216:         num = LastChar - InputBuf;  /* return the number of chars read */
 217:         /*
 218: 	     * For continuation lines, we set the prompt to prompt 2
 219: 	     */
 220:         printprompt(1, NULL);
 221: #ifdef notdef
 222:         ResetInLine();  /* reset the input pointers */
 223:         PromptBuf[0] = '\0';
 224: #endif
 225:         break;
 226: 
 227:     case CC_CORRECT:
 228:         if (tenematch(InputBuf, INBUFSIZ, Cursor - InputBuf,
 229:               SPELL) < 0)
 230:         Beep();     /* Beep = No match/ambiguous */
 231:         if (NeedsRedraw) {
 232:         ClearLines();
 233:         ClearDisp();
 234:         NeedsRedraw = 0;
 235:         }
 236:         Refresh();
 237:         Argument = 1;
 238:         DoingArg = 0;
 239:         break;
 240: 
 241:     case CC_CORRECT_L:
 242:         if (SpellLine(FALSE) < 0)
 243:         Beep();     /* Beep = No match/ambiguous */
 244:         if (NeedsRedraw) {
 245:         ClearLines();
 246:         ClearDisp();
 247:         NeedsRedraw = 0;
 248:         }
 249:         Refresh();
 250:         Argument = 1;
 251:         DoingArg = 0;
 252:         break;
 253: 
 254: 
 255:     case CC_COMPLETE:
 256:         if (adrof(STRa_expand))
 257:         (void) e_ex_history();
 258:         /*
 259: 	     * Modified by Martin Boyer (gamin@ireq-robot.hydro.qc.ca):
 260: 	     * A separate variable now controls beeping after
 261: 	     * completion, independently of autolisting.
 262: 	     */
 263:         switch (matchval =
 264:             tenematch(InputBuf, INBUFSIZ, Cursor-InputBuf, RECOGNIZE)) {
 265:         case 1:
 266:         if (non_unique_match && matchbeep &&
 267:             (Strcmp(*(matchbeep->vec), STRnotunique) == 0))
 268:             Beep();
 269:         break;
 270:         case 0:
 271:         if (matchbeep) {
 272:             if (Strcmp(*(matchbeep->vec), STRnomatch) == 0 ||
 273:             Strcmp(*(matchbeep->vec), STRambiguous) == 0 ||
 274:             Strcmp(*(matchbeep->vec), STRnotunique) == 0)
 275:             Beep();
 276:         }
 277:         else
 278:             Beep();
 279:         break;
 280:         default:
 281:         if (matchval < 0)   /* Error from tenematch */
 282:             Beep();
 283:         else if (matchbeep) {
 284:             if ((Strcmp(*(matchbeep->vec), STRambiguous) == 0 ||
 285:              Strcmp(*(matchbeep->vec), STRnotunique) == 0))
 286:             Beep();
 287:         }
 288:         else
 289:             Beep();
 290:         /*
 291: 		 * Addition by David C Lawrence <tale@pawl.rpi.edu>: If an
 292: 		 * attempted completion is ambiguous, list the choices.
 293: 		 * (PWP: this is the best feature addition to tcsh I have
 294: 		 * seen in many months.)
 295: 		 */
 296:         if (adrof(STRa_list)) {
 297:             PastBottom();
 298:             (void) tenematch(InputBuf, INBUFSIZ, Cursor-InputBuf, LIST);
 299:         }
 300:         break;
 301:         }
 302:         if (NeedsRedraw) {
 303:         PastBottom();
 304:         ClearLines();
 305:         ClearDisp();
 306:         NeedsRedraw = 0;
 307:         }
 308:         Refresh();
 309:         Argument = 1;
 310:         DoingArg = 0;
 311:         break;
 312: 
 313:     case CC_LIST_CHOICES:
 314:         /* should catch ^C here... */
 315:         (void) tenematch(InputBuf, INBUFSIZ, Cursor - InputBuf, LIST);
 316:         Refresh();
 317:         Argument = 1;
 318:         DoingArg = 0;
 319:         break;
 320: 
 321:     case CC_LIST_GLOB:
 322:         (void) tenematch(InputBuf, INBUFSIZ, Cursor - InputBuf, GLOB);
 323:         Refresh();
 324:         Argument = 1;
 325:         DoingArg = 0;
 326:         break;
 327: 
 328:     case CC_EXPAND_GLOB:
 329:         if (tenematch(InputBuf, INBUFSIZ, Cursor - InputBuf,
 330:               GLOB_EXPAND) <= 0)
 331:         Beep();     /* Beep = No match */
 332:         if (NeedsRedraw) {
 333:         ClearLines();
 334:         ClearDisp();
 335:         NeedsRedraw = 0;
 336:         }
 337:         Refresh();
 338:         Argument = 1;
 339:         DoingArg = 0;
 340:         break;
 341: 
 342:     case CC_EXPAND_VARS:
 343:         if (tenematch(InputBuf, INBUFSIZ, Cursor - InputBuf,
 344:               VARS_EXPAND) <= 0)
 345:         Beep();     /* Beep = No match */
 346:         if (NeedsRedraw) {
 347:         ClearLines();
 348:         ClearDisp();
 349:         NeedsRedraw = 0;
 350:         }
 351:         Refresh();
 352:         Argument = 1;
 353:         DoingArg = 0;
 354:         break;
 355: 
 356:     case CC_HELPME:
 357:         xputchar('\n');
 358:         /* should catch ^C here... */
 359:         (void) tenematch(InputBuf, INBUFSIZ, LastChar - InputBuf,
 360:                  PRINT_HELP);
 361:         Refresh();
 362:         Argument = 1;
 363:         DoingArg = 0;
 364:         break;
 365: 
 366:     case CC_FATAL:      /* fatal error, reset to known state */
 367: #ifdef DEBUG_EDIT
 368:         xprintf("*** editor fatal ERROR ***\r\n\n");
 369: #endif				/* DEBUG_EDIT */
 370:         /* put (real) cursor in a known place */
 371:         ClearDisp();    /* reset the display stuff */
 372:         ResetInLine();  /* reset the input pointers */
 373:         Refresh();      /* print the prompt again */
 374:         Argument = 1;
 375:         DoingArg = 0;
 376:         break;
 377: 
 378:     case CC_ERROR:
 379:     default:        /* functions we don't know about */
 380:         DoingArg = 0;
 381:         Argument = 1;
 382:         Beep();
 383:         flush();
 384:         break;
 385:     }
 386:     }
 387:     (void) Cookedmode();    /* make sure the tty is set up correctly */
 388:     GettingInput = 0;
 389:     flush();            /* flush any buffered output */
 390:     return num;
 391: }
 392: 
 393: void
 394: PushMacro(str)
 395:     Char   *str;
 396: {
 397:     if (str != NULL && MacroLvl + 1 < MAXMACROLEVELS) {
 398:     MacroLvl++;
 399:     KeyMacro[MacroLvl] = str;
 400:     }
 401:     else {
 402:     Beep();
 403:     flush();
 404:     }
 405: }
 406: 
 407: static int
 408: G_N_Command(cmdnum, ch)
 409:     KEYCMD *cmdnum;
 410:     register Char *ch;
 411: {
 412:     KEYCMD  cmd = 0;
 413:     int     num;
 414:     Char   *str;
 415: 
 416:     for (; cmd == 0 || cmd == F_XKEY;) {
 417:     if ((num = G_N_Char(ch)) != 1) {    /* if EOF or error */
 418:         return num;
 419:     }
 420: #ifdef  KANJI
 421:     if (*ch & META) {
 422:         MetaNext = 0;
 423:         cmd = CcViMap[' '];
 424:         break;
 425:     }
 426:     else
 427: #endif				/* KANJI */
 428:     if (MetaNext) {
 429:         MetaNext = 0;
 430:         *ch |= META;
 431:     }
 432:     cmd = Cur_KeyMap[(unsigned char) *ch];
 433:     if (cmd == F_XKEY) {
 434:         if (GetXkey(ch, &str))
 435:         cmd = (KEYCMD) * str;
 436:         else
 437:         PushMacro(str);
 438:     }
 439:     if (!AltKeyMap) {
 440:         Cur_KeyMap = CcKeyMap;
 441:     }
 442:     }
 443:     *cmdnum = cmd;
 444:     return OKCMD;
 445: }
 446: 
 447: int
 448: G_N_Char(cp)
 449:     register Char *cp;
 450: {
 451:     register int num_read;
 452: 
 453: #if defined(EWOULDBLOCK) || (defined(POSIX) && defined(EAGAIN))
 454: # if defined(FIONBIO) || (defined(F_SETFL) && defined(O_NDELAY))
 455: #  define TRY_AGAIN
 456:     int     tried = 0;
 457: 
 458: # endif				/* FIONBIO || (F_SETFL && O_NDELAY) */
 459: #endif				/* EWOULDBLOCK || (POSIX && EAGAIN) */
 460:     unsigned char tcp;
 461: 
 462:     for (;;) {
 463:     if (MacroLvl < 0) {
 464:         if (!Load_input_line())
 465:         break;
 466:     }
 467:     if (*KeyMacro[MacroLvl] == 0) {
 468:         MacroLvl--;
 469:         continue;
 470:     }
 471:     *cp = *KeyMacro[MacroLvl]++ & CHAR;
 472:     if (*KeyMacro[MacroLvl] == 0) { /* Needed for QMode On */
 473:         MacroLvl--;
 474:     }
 475:     return (1);
 476:     }
 477: 
 478:     if (Rawmode() < 0)      /* make sure the tty is set up correctly */
 479:     return 0;       /* oops: SHIN was closed */
 480: 
 481:     while ((num_read = read(SHIN, (char *) &tcp, 1)) == -1)
 482:     switch (errno) {
 483:         /*
 484: 	     * Someone might have set our file descriptor to non blocking From
 485: 	     * Gray Watson (gray%antr.uucp@med.pitt.edu), Thanks!!!
 486: 	     */
 487: #ifdef EWOULDBLOCK
 488:     case EWOULDBLOCK:
 489: #endif				/* EWOULDBLOCK */
 490: #if defined(POSIX) && defined(EAGAIN)
 491: # if defined(EWOULDBLOCK) && EAGAIN != EWOULDBLOCK
 492:     case EAGAIN:
 493: # endif				/* EWOULDBLOCK && EAGAIN != EWOULDBLOCK */
 494: #endif				/* POSIX && EAGAIN */
 495: #ifdef TRY_AGAIN
 496:         if (!tried) {
 497: # if defined(F_SETFL) && defined(O_NDELAY)
 498:         (void) fcntl(SHIN, F_SETFL,
 499:                  fcntl(SHIN, F_GETFL, 0) & ~O_NDELAY);
 500: # endif				/* F_SETFL && O_NDELAY */
 501: # ifdef FIONBIO
 502:         (void) ioctl(SHIN, FIONBIO, (ioctl_t) & tried);
 503: # endif				/* FIONBIO */
 504:         tried = 1;
 505:         break;
 506:         }
 507: #endif
 508:         *cp = tcp;
 509:         return (num_read);
 510: #ifdef _SEQUENT_
 511:     case EBADF:
 512: #endif				/* _SEQUENT_ */
 513:     case EINTR:
 514:         break;
 515:     default:
 516:         xprintf("G_N_Char(): errno == %d\n", errno);
 517:         *cp = tcp;
 518:         return num_read;
 519:     }
 520:     *cp = tcp;
 521:     return num_read;
 522: }
 523: 
 524: /*
 525:  * SpellLine - do spelling correction on the entire command line
 526:  * (which may have trailing newline).
 527:  * If cmdonly is set, only check spelling of command words.
 528:  * Return value:
 529:  * -1: Something was incorrectible, and nothing was corrected
 530:  *  0: Everything was correct
 531:  *  1: Something was corrected
 532:  */
 533: static int
 534: SpellLine(cmdonly)
 535:     int     cmdonly;
 536: {
 537:     int     endflag, matchval;
 538:     Char   *argptr, *OldCursor, *OldLastChar;
 539: 
 540:     OldLastChar = LastChar;
 541:     OldCursor = Cursor;
 542:     argptr = InputBuf;
 543:     endflag = 1;
 544:     matchval = 0;
 545:     do {
 546:     while (ismeta(*argptr) || iscmdmeta(*argptr))
 547:         argptr++;
 548:     for (Cursor = argptr;
 549:          *Cursor != '\0' && !ismeta(*Cursor) && !iscmdmeta(*Cursor);
 550:          Cursor++);
 551:     if (*Cursor == '\0') {
 552:         Cursor = LastChar;
 553:         if (LastChar[-1] == '\n')
 554:         Cursor--;
 555:         endflag = 0;
 556:     }
 557:     if (!Strchr(mismatch, *argptr) &&
 558:         (!cmdonly || starting_a_command(argptr, InputBuf))) {
 559:         switch (tenematch(InputBuf, INBUFSIZ, Cursor - InputBuf, SPELL)) {
 560:         case 1:     /* corrected */
 561:         matchval = 1;
 562:         break;
 563:         case -1:        /* couldn't be corrected */
 564:         if (!matchval)
 565:             matchval = -1;
 566:         break;
 567:         default:        /* was correct */
 568:         break;
 569:         }
 570:         if (LastChar != OldLastChar) {
 571:         if (argptr < OldCursor)
 572:             OldCursor += (LastChar - OldLastChar);
 573:         OldLastChar = LastChar;
 574:         }
 575:     }
 576:     argptr = Cursor;
 577:     } while (endflag);
 578:     Cursor = OldCursor;
 579:     return matchval;
 580: }

Defined functions

G_N_Char defined in line 447; used 3 times
G_N_Command defined in line 407; used 1 times
Inputl defined in line 65; used 1 times
PushMacro defined in line 393; used 3 times
SpellLine defined in line 533; used 2 times
rcsid defined in line 39; never used

Defined variables

mismatch defined in line 59; used 1 times

Defined macros

OKCMD defined in line 48; used 4 times
TRY_AGAIN defined in line 455; used 1 times
Last modified: 1991-08-21
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3539
Valid CSS Valid XHTML 1.0 Strict