source: trunk/third/tcsh/ed.inputl.c @ 12039

Revision 12039, 21.6 KB checked in by danw, 26 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r12038, which included commits to RCS files with non-trunk default branches.
Line 
1/* $Header: /afs/dev.mit.edu/source/repository/third/tcsh/ed.inputl.c,v 1.1.1.2 1998-10-03 21:09:46 danw 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 "sh.h"
38
39RCSID("$Id: ed.inputl.c,v 1.1.1.2 1998-10-03 21:09:46 danw Exp $")
40
41#include "ed.h"
42#include "ed.defns.h"           /* for the function names */
43#include "tw.h"                 /* for twenex stuff */
44
45#define OKCMD (INBUFSIZE+INBUFSIZE)
46
47/* ed.inputl -- routines to get a single line from the input. */
48
49extern bool tellwhat;
50extern bool MapsAreInited;
51extern bool Tty_raw_mode;
52
53/* mismatched first character */
54static Char mismatch[] =
55    {'!', '^' , '\\', '-', '%', '\0', '"', '\'', '`', '\0' };
56
57static  int     Repair          __P((void));
58static  int     GetNextCommand  __P((KEYCMD *, Char *));
59static  int     SpellLine       __P((int));
60static  int     CompleteLine    __P((void));
61static  void    RunCommand      __P((Char *));
62static  void    doeval1         __P((Char **));
63
64static bool rotate = 0;
65
66
67static int
68Repair()
69{
70    if (NeedsRedraw) {
71        ClearLines();
72        ClearDisp();
73        NeedsRedraw = 0;
74    }
75    Refresh();
76    Argument = 1;
77    DoingArg = 0;
78    curchoice = -1;
79    return LastChar - InputBuf;
80}
81
82/* CCRETVAL */
83int
84Inputl()
85{
86    CCRETVAL retval;
87    KEYCMD  cmdnum = 0;
88    extern KEYCMD NumFuns;
89    unsigned char tch;          /* the place where read() goes */
90    Char    ch;
91    int     num;                /* how many chars we have read at NL */
92    int     expnum;
93    struct varent *crct = inheredoc ? NULL : adrof(STRcorrect);
94    struct varent *autol = adrof(STRautolist);
95    struct varent *matchbeep = adrof(STRmatchbeep);
96    struct varent *imode = adrof(STRinputmode);
97    Char   *SaveChar, *CorrChar;
98    Char    Origin[INBUFSIZE], Change[INBUFSIZE];
99    int     matchval;           /* from tenematch() */
100    COMMAND fn;
101    int curlen = 0;
102    int newlen;
103    int idx;
104
105    if (!MapsAreInited)         /* double extra just in case */
106        ed_InitMaps();
107
108    ClearDisp();                /* reset the display stuff */
109    ResetInLine(0);             /* reset the input pointers */
110    if (GettingInput)
111        MacroLvl = -1;          /* editor was interrupted during input */
112
113    if (imode) {
114        if (!Strcmp(*(imode->vec), STRinsert))
115            inputmode = MODE_INSERT;
116        else if (!Strcmp(*(imode->vec), STRoverwrite))
117            inputmode = MODE_REPLACE;
118    }
119
120#if defined(FIONREAD) && !defined(OREO)
121    if (!Tty_raw_mode && MacroLvl < 0) {
122# ifdef SUNOS4
123        long chrs = 0;
124# else /* !SUNOS4 */
125        /*
126         * *Everyone* else has an int, but SunOS wants long!
127         * This breaks where int != long (alpha)
128         */
129        int chrs = 0;
130# endif /* SUNOS4 */
131
132        (void) ioctl(SHIN, FIONREAD, (ioctl_t) & chrs);
133        if (chrs == 0) {
134            if (Rawmode() < 0)
135                return 0;
136        }
137    }
138#endif /* FIONREAD && !OREO */
139
140    GettingInput = 1;
141    NeedsRedraw = 0;
142
143    if (tellwhat) {
144        copyn(InputBuf, WhichBuf, INBUFSIZE);
145        LastChar = InputBuf + (LastWhich - WhichBuf);
146        Cursor = InputBuf + (CursWhich - WhichBuf);
147        tellwhat = 0;
148        Hist_num = HistWhich;
149    }
150    if (Expand) {
151        (void) e_up_hist(0);
152        Expand = 0;
153    }
154    Refresh();                  /* print the prompt */
155
156    for (num = OKCMD; num == OKCMD;) {  /* while still editing this line */
157#ifdef DEBUG_EDIT
158        if (Cursor > LastChar)
159            xprintf("Cursor > LastChar\r\n");
160        if (Cursor < InputBuf)
161            xprintf("Cursor < InputBuf\r\n");
162        if (Cursor > InputLim)
163            xprintf("Cursor > InputLim\r\n");
164        if (LastChar > InputLim)
165            xprintf("LastChar > InputLim\r\n");
166        if (InputLim != &InputBuf[INBUFSIZE - 2])
167            xprintf("InputLim != &InputBuf[INBUFSIZE-2]\r\n");
168        if ((!DoingArg) && (Argument != 1))
169            xprintf("(!DoingArg) && (Argument != 1)\r\n");
170        if (CcKeyMap[0] == 0)
171            xprintf("CcKeyMap[0] == 0 (maybe not inited)\r\n");
172#endif
173
174        /* if EOF or error */
175        if ((num = GetNextCommand(&cmdnum, &ch)) != OKCMD) {
176            break;
177        }
178
179        if (cmdnum >= NumFuns) {/* BUG CHECK command */
180#ifdef DEBUG_EDIT
181            xprintf(CGETS(6, 1, "ERROR: illegal command from key 0%o\r\n"), ch);
182#endif
183            continue;           /* try again */
184        }
185
186        /* now do the real command */
187        retval = (*CcFuncTbl[cmdnum]) (ch);
188
189        /* save the last command here */
190        LastCmd = cmdnum;
191
192        /* make sure fn is initialized */
193        fn = (retval == CC_COMPLETE_ALL) ? LIST_ALL : LIST;
194
195        /* use any return value */
196        switch (retval) {
197
198        case CC_REFRESH:
199            Refresh();
200            /*FALLTHROUGH*/
201        case CC_NORM:           /* normal char */
202            Argument = 1;
203            DoingArg = 0;
204            /*FALLTHROUGH*/
205        case CC_ARGHACK:        /* Suggested by Rich Salz */
206            /* <rsalz@pineapple.bbn.com> */
207            curchoice = -1;
208            curlen = LastChar - InputBuf;
209            break;              /* keep going... */
210
211        case CC_EOF:            /* end of file typed */
212            curchoice = -1;
213            curlen = LastChar - InputBuf;
214            num = 0;
215            break;
216
217        case CC_WHICH:          /* tell what this command does */
218            tellwhat = 1;
219            copyn(WhichBuf, InputBuf, INBUFSIZE);
220            LastWhich = WhichBuf + (LastChar - InputBuf);
221            CursWhich = WhichBuf + (Cursor - InputBuf);
222            *LastChar++ = '\n'; /* for the benifit of CSH */
223            HistWhich = Hist_num;
224            Hist_num = 0;       /* for the history commands */
225            num = LastChar - InputBuf;  /* number characters read */
226            break;
227
228        case CC_NEWLINE:        /* normal end of line */
229            curlen = 0;
230            curchoice = -1;
231            matchval = 1;
232            if (crct && (!Strcmp(*(crct->vec), STRcmd) ||
233                         !Strcmp(*(crct->vec), STRall))) {
234                PastBottom();
235                copyn(Origin, InputBuf, INBUFSIZE);
236                SaveChar = LastChar;
237                if (SpellLine(!Strcmp(*(crct->vec), STRcmd)) == 1) {
238                    PastBottom();
239                    copyn(Change, InputBuf, INBUFSIZE);
240                    *Strchr(Change, '\n') = '\0';
241                    CorrChar = LastChar;        /* Save the corrected end */
242                    LastChar = InputBuf;        /* Null the current line */
243                    SoundBeep();
244                    printprompt(2, short2str(Change));
245                    Refresh();
246                    if (read(SHIN, (char *) &tch, 1) < 0)
247#ifdef convex
248                        /*
249                         * need to print error message in case file
250                         * is migrated
251                         */
252                        if (errno && errno != EINTR)
253                            stderror(ERR_SYSTEM, progname, strerror(errno));
254#else
255                        break;
256#endif
257                    ch = tch;
258                    if (ch == 'y' || ch == ' ') {
259                        LastChar = CorrChar;    /* Restore the corrected end */
260                        xprintf(CGETS(6, 2, "yes\n"));
261                    }
262                    else {
263                        copyn(InputBuf, Origin, INBUFSIZE);
264                        LastChar = SaveChar;
265                        if (ch == 'e') {
266                            xprintf(CGETS(6, 3, "edit\n"));
267                            *LastChar-- = '\0';
268                            Cursor = LastChar;
269                            printprompt(3, NULL);
270                            ClearLines();
271                            ClearDisp();
272                            Refresh();
273                            break;
274                        }
275                        else if (ch == 'a') {
276                            xprintf(CGETS(6, 4, "abort\n"));
277                            LastChar = InputBuf;   /* Null the current line */
278                            Cursor = LastChar;
279                            printprompt(0, NULL);
280                            Refresh();
281                            break;
282                        }
283                        xprintf(CGETS(6, 5, "no\n"));
284                    }
285                    flush();
286                }
287            } else if (crct && !Strcmp(*(crct->vec), STRcomplete)) {
288                if (LastChar > InputBuf && LastChar[-1] == '\n') {
289                    LastChar[-1] = '\0';
290                    LastChar--;
291                    Cursor = LastChar;
292                }
293                match_unique_match = 1;  /* match unique matches */
294                matchval = CompleteLine();
295                match_unique_match = 0;
296                curlen = LastChar - InputBuf;
297                if (matchval != 1) {
298                    PastBottom();
299                }
300                if (matchval == 0) {
301                    xprintf(CGETS(6, 6, "No matching command\n"));
302                } else if (matchval == 2) {
303                    xprintf(CGETS(6, 7, "Ambiguous command\n"));
304                }
305                if (NeedsRedraw) {
306                    ClearLines();
307                    ClearDisp();
308                    NeedsRedraw = 0;
309                }
310                Refresh();
311                Argument = 1;
312                DoingArg = 0;
313                if (matchval == 1) {
314                    PastBottom();
315                    *LastChar++ = '\n';
316                    *LastChar = '\0';
317                }
318                curlen = LastChar - InputBuf;
319            }
320            else
321                PastBottom();
322
323            if (matchval == 1) {
324                tellwhat = 0;   /* just in case */
325                Hist_num = 0;   /* for the history commands */
326                /* return the number of chars read */
327                num = LastChar - InputBuf;
328                /*
329                 * For continuation lines, we set the prompt to prompt 2
330                 */
331                printprompt(1, NULL);
332            }
333            break;
334
335        case CC_CORRECT:
336            if (tenematch(InputBuf, Cursor - InputBuf, SPELL) < 0)
337                SoundBeep();            /* Beep = No match/ambiguous */
338            curlen = Repair();
339            break;
340
341        case CC_CORRECT_L:
342            if (SpellLine(FALSE) < 0)
343                SoundBeep();            /* Beep = No match/ambiguous */
344            curlen = Repair();
345            break;
346
347
348        case CC_COMPLETE:
349        case CC_COMPLETE_ALL:
350        case CC_COMPLETE_FWD:
351        case CC_COMPLETE_BACK:
352            switch (retval) {
353            case CC_COMPLETE:
354                fn = RECOGNIZE;
355                curlen = LastChar - InputBuf;
356                curchoice = -1;
357                rotate = 0;
358                break;
359            case CC_COMPLETE_ALL:
360                fn = RECOGNIZE_ALL;
361                curlen = LastChar - InputBuf;
362                curchoice = -1;
363                rotate = 0;
364                break;
365            case CC_COMPLETE_FWD:
366                fn = RECOGNIZE_SCROLL;
367                curchoice++;
368                rotate = 1;
369                break;
370            case CC_COMPLETE_BACK:
371                fn = RECOGNIZE_SCROLL;
372                curchoice--;
373                rotate = 1;
374                break;
375            default:
376                abort();
377            }
378            if (InputBuf[curlen] && rotate) {
379                newlen = LastChar - InputBuf;
380                for (idx = (Cursor - InputBuf);
381                     idx <= newlen; idx++)
382                        InputBuf[idx - newlen + curlen] =
383                        InputBuf[idx];
384                LastChar = InputBuf + curlen;
385                Cursor = Cursor - newlen + curlen;
386            }
387            curlen = LastChar - InputBuf;
388
389
390            if (adrof(STRautoexpand))
391                (void) e_expand_history(0);
392            /*
393             * Modified by Martin Boyer (gamin@ireq-robot.hydro.qc.ca):
394             * A separate variable now controls beeping after
395             * completion, independently of autolisting.
396             */
397            expnum = Cursor - InputBuf;
398            switch (matchval = tenematch(InputBuf, Cursor-InputBuf, fn)){
399            case 1:
400                if (non_unique_match && matchbeep &&
401                    (Strcmp(*(matchbeep->vec), STRnotunique) == 0))
402                    SoundBeep();
403                break;
404            case 0:
405                if (matchbeep) {
406                    if (Strcmp(*(matchbeep->vec), STRnomatch) == 0 ||
407                        Strcmp(*(matchbeep->vec), STRambiguous) == 0 ||
408                        Strcmp(*(matchbeep->vec), STRnotunique) == 0)
409                        SoundBeep();
410                }
411                else
412                    SoundBeep();
413                break;
414            default:
415                if (matchval < 0) {     /* Error from tenematch */
416                    curchoice = -1;
417                    SoundBeep();
418                    break;
419                }
420                if (matchbeep) {
421                    if ((Strcmp(*(matchbeep->vec), STRambiguous) == 0 ||
422                         Strcmp(*(matchbeep->vec), STRnotunique) == 0))
423                        SoundBeep();
424                }
425                else
426                    SoundBeep();
427                /*
428                 * Addition by David C Lawrence <tale@pawl.rpi.edu>: If an
429                 * attempted completion is ambiguous, list the choices. 
430                 * (PWP: this is the best feature addition to tcsh I have
431                 * seen in many months.)
432                 */
433                if (autol && (Strcmp(*(autol->vec), STRambiguous) != 0 ||
434                                     expnum == Cursor - InputBuf)) {
435                    PastBottom();
436                    fn = (retval == CC_COMPLETE_ALL) ? LIST_ALL : LIST;
437                    (void) tenematch(InputBuf, Cursor-InputBuf, fn);
438                }
439                break;
440            }
441            if (NeedsRedraw) {
442                PastBottom();
443                ClearLines();
444                ClearDisp();
445                NeedsRedraw = 0;
446            }
447            Refresh();
448            Argument = 1;
449            DoingArg = 0;
450            break;
451
452        case CC_LIST_CHOICES:
453        case CC_LIST_ALL:
454            if (InputBuf[curlen] && rotate) {
455                newlen = LastChar - InputBuf;
456                for (idx = (Cursor - InputBuf);
457                     idx <= newlen; idx++)
458                        InputBuf[idx - newlen + curlen] =
459                        InputBuf[idx];
460                LastChar = InputBuf + curlen;
461                Cursor = Cursor - newlen + curlen;
462            }
463            curlen = LastChar - InputBuf;
464            if (curchoice >= 0)
465                curchoice--;
466
467            fn = (retval == CC_LIST_ALL) ? LIST_ALL : LIST;
468            /* should catch ^C here... */
469            if (tenematch(InputBuf, Cursor - InputBuf, fn) < 0)
470                SoundBeep();
471            Refresh();
472            Argument = 1;
473            DoingArg = 0;
474            break;
475
476
477        case CC_LIST_GLOB:
478            if (tenematch(InputBuf, Cursor - InputBuf, GLOB) < 0)
479                SoundBeep();
480            curlen = Repair();
481            break;
482
483        case CC_EXPAND_GLOB:
484            if (tenematch(InputBuf, Cursor - InputBuf, GLOB_EXPAND) <= 0)
485                SoundBeep();            /* Beep = No match */
486            curlen = Repair();
487            break;
488
489        case CC_NORMALIZE_PATH:
490            if (tenematch(InputBuf, Cursor - InputBuf, PATH_NORMALIZE) <= 0)
491                SoundBeep();            /* Beep = No match */
492            curlen = Repair();
493            break;
494
495        case CC_EXPAND_VARS:
496            if (tenematch(InputBuf, Cursor - InputBuf, VARS_EXPAND) <= 0)
497                SoundBeep();            /* Beep = No match */
498            curlen = Repair();
499            break;
500
501        case CC_NORMALIZE_COMMAND:
502            if (tenematch(InputBuf, Cursor - InputBuf, COMMAND_NORMALIZE) <= 0)
503                SoundBeep();            /* Beep = No match */
504            curlen = Repair();
505            break;
506
507        case CC_HELPME:
508            xputchar('\n');
509            /* should catch ^C here... */
510            (void) tenematch(InputBuf, LastChar - InputBuf, PRINT_HELP);
511            Refresh();
512            Argument = 1;
513            DoingArg = 0;
514            curchoice = -1;
515            curlen = LastChar - InputBuf;
516            break;
517
518        case CC_FATAL:          /* fatal error, reset to known state */
519#ifdef DEBUG_EDIT
520            xprintf(CGETS(7, 8, "*** editor fatal ERROR ***\r\n\n"));
521#endif                          /* DEBUG_EDIT */
522            /* put (real) cursor in a known place */
523            ClearDisp();        /* reset the display stuff */
524            ResetInLine(1);     /* reset the input pointers */
525            Refresh();          /* print the prompt again */
526            Argument = 1;
527            DoingArg = 0;
528            curchoice = -1;
529            curlen = LastChar - InputBuf;
530            break;
531
532        case CC_ERROR:
533        default:                /* functions we don't know about */
534            DoingArg = 0;
535            Argument = 1;
536            SoundBeep();
537            flush();
538            curchoice = -1;
539            curlen = LastChar - InputBuf;
540            break;
541        }
542    }
543    (void) Cookedmode();        /* make sure the tty is set up correctly */
544    GettingInput = 0;
545    flush();                    /* flush any buffered output */
546    return num;
547}
548
549void
550PushMacro(str)
551    Char   *str;
552{
553    if (str != NULL && MacroLvl + 1 < MAXMACROLEVELS) {
554        MacroLvl++;
555        KeyMacro[MacroLvl] = str;
556    }
557    else {
558        SoundBeep();
559        flush();
560    }
561}
562
563/*
564 * Like eval, only using the current file descriptors
565 */
566static Char **gv = NULL, **gav = NULL;
567
568static void
569doeval1(v)
570    Char **v;
571{
572    Char  **oevalvec;
573    Char   *oevalp;
574    int     my_reenter;
575    Char  **savegv;
576    jmp_buf_t osetexit;
577
578    oevalvec = evalvec;
579    oevalp = evalp;
580    savegv = gv;
581    gav = v;
582
583
584    gflag = 0, tglob(gav);
585    if (gflag) {
586        gv = gav = globall(gav);
587        gargv = 0;
588        if (gav == 0)
589            stderror(ERR_NOMATCH);
590        gav = copyblk(gav);
591    }
592    else {
593        gv = NULL;
594        gav = copyblk(gav);
595        trim(gav);
596    }
597
598    getexit(osetexit);
599
600    /* PWP: setjmp/longjmp bugfix for optimizing compilers */
601#ifdef cray
602    my_reenter = 1;             /* assume non-zero return val */
603    if (setexit() == 0) {
604        my_reenter = 0;         /* Oh well, we were wrong */
605#else /* !cray */
606    if ((my_reenter = setexit()) == 0) {
607#endif /* cray */
608        evalvec = gav;
609        evalp = 0;
610        process(0);
611    }
612
613    evalvec = oevalvec;
614    evalp = oevalp;
615    doneinp = 0;
616
617    if (gv)
618        blkfree(gv);
619
620    gv = savegv;
621    resexit(osetexit);
622    if (my_reenter)
623        stderror(ERR_SILENT);
624}
625
626static void
627RunCommand(str)
628    Char *str;
629{
630    Char *cmd[2];
631
632    xputchar('\n');     /* Start on a clean line */
633
634    cmd[0] = str;
635    cmd[1] = NULL;
636
637    (void) Cookedmode();
638    GettingInput = 0;
639
640    doeval1(cmd);
641   
642    (void) Rawmode();
643    GettingInput = 1;
644
645    ClearLines();
646    ClearDisp();
647    NeedsRedraw = 0;
648    Refresh();
649}
650
651static int
652GetNextCommand(cmdnum, ch)
653    KEYCMD *cmdnum;
654    register Char *ch;
655{
656    KEYCMD  cmd = 0;
657    int     num;
658
659    while (cmd == 0 || cmd == F_XKEY) {
660        if ((num = GetNextChar(ch)) != 1) {     /* if EOF or error */
661            return num;
662        }
663#ifdef  KANJI
664        if (!adrof(STRnokanji) && (*ch & META)) {
665            MetaNext = 0;
666            cmd = F_INSERT;
667            break;
668        }
669        else
670#endif /* KANJI */
671        if (MetaNext) {
672            MetaNext = 0;
673            *ch |= META;
674        }
675        /* XXX: This needs to be fixed so that we don't just truncate
676         * the character, we unquote it.
677         */
678        if (*ch < NT_NUM_KEYS)
679            cmd = CurrentKeyMap[*ch];
680        else
681            cmd = CurrentKeyMap[(unsigned char) *ch];
682        if (cmd == F_XKEY) {
683            XmapVal val;
684            CStr cstr;
685            cstr.buf = ch;
686            cstr.len = Strlen(ch);
687            switch (GetXkey(&cstr, &val)) {
688            case XK_CMD:
689                cmd = val.cmd;
690                break;
691            case XK_STR:
692                PushMacro(val.str.buf);
693                break;
694            case XK_EXE:
695                RunCommand(val.str.buf);
696                break;
697            default:
698                abort();
699                break;
700            }
701        }
702        if (!AltKeyMap)
703            CurrentKeyMap = CcKeyMap;
704    }
705    *cmdnum = cmd;
706    return OKCMD;
707}
708
709int
710GetNextChar(cp)
711    register Char *cp;
712{
713    register int num_read;
714    int     tried = 0;
715    unsigned char tcp;
716
717    for (;;) {
718        if (MacroLvl < 0) {
719            if (!Load_input_line())
720                break;
721        }
722        if (*KeyMacro[MacroLvl] == 0) {
723            MacroLvl--;
724            continue;
725        }
726        *cp = *KeyMacro[MacroLvl]++ & CHAR;
727        if (*KeyMacro[MacroLvl] == 0) { /* Needed for QuoteMode On */
728            MacroLvl--;
729        }
730        return (1);
731    }
732
733    if (Rawmode() < 0)          /* make sure the tty is set up correctly */
734        return 0;               /* oops: SHIN was closed */
735
736#ifdef WINNT
737    __nt_want_vcode = 1;
738#endif /* WINNT */
739    while ((num_read = read(SHIN, (char *) &tcp, 1)) == -1) {
740        if (errno == EINTR)
741            continue;
742        if (!tried && fixio(SHIN, errno) != -1)
743            tried = 1;
744        else {
745#ifdef convex
746            /* need to print error message in case the file is migrated */
747            if (errno != EINTR)
748                stderror(ERR_SYSTEM, progname, strerror(errno));
749#endif  /* convex */
750#ifdef WINNT
751            __nt_want_vcode = 0;
752#endif /* WINNT */
753            *cp = '\0';
754            return -1;
755        }
756    }
757#ifdef WINNT
758    if (__nt_want_vcode == 2)
759        *cp = __nt_vcode;
760    else
761        *cp = tcp;
762    __nt_want_vcode = 0;
763#else
764    *cp = tcp;
765#endif /* WINNT */
766    return num_read;
767}
768
769/*
770 * SpellLine - do spelling correction on the entire command line
771 * (which may have trailing newline).
772 * If cmdonly is set, only check spelling of command words.
773 * Return value:
774 * -1: Something was incorrectible, and nothing was corrected
775 *  0: Everything was correct
776 *  1: Something was corrected
777 */
778static int
779SpellLine(cmdonly)
780    int     cmdonly;
781{
782    int     endflag, matchval;
783    Char   *argptr, *OldCursor, *OldLastChar;
784
785    OldLastChar = LastChar;
786    OldCursor = Cursor;
787    argptr = InputBuf;
788    endflag = 1;
789    matchval = 0;
790    do {
791        while (ismetahash(*argptr) || iscmdmeta(*argptr))
792            argptr++;
793        for (Cursor = argptr;
794             *Cursor != '\0' && ((Cursor != argptr && Cursor[-1] == '\\') ||
795                                 (!ismetahash(*Cursor) && !iscmdmeta(*Cursor)));
796             Cursor++)
797             continue;
798        if (*Cursor == '\0') {
799            Cursor = LastChar;
800            if (LastChar[-1] == '\n')
801                Cursor--;
802            endflag = 0;
803        }
804        /* Obey current history character settings */
805        mismatch[0] = HIST;
806        mismatch[1] = HISTSUB;
807        if (!Strchr(mismatch, *argptr) &&
808            (!cmdonly || starting_a_command(argptr, InputBuf))) {
809#ifdef WINNT
810            /*
811             * This hack avoids correcting drive letter changes
812             */
813            if((Cursor - InputBuf) != 2 || (char)InputBuf[1] != ':')
814#endif /* WINNT */
815                switch (tenematch(InputBuf, Cursor - InputBuf, SPELL)) {
816                case 1:         /* corrected */
817                    matchval = 1;
818                    break;
819                case -1:                /* couldn't be corrected */
820                    if (!matchval)
821                        matchval = -1;
822                    break;
823                default:                /* was correct */
824                    break;
825                }
826
827            if (LastChar != OldLastChar) {
828                if (argptr < OldCursor)
829                    OldCursor += (LastChar - OldLastChar);
830                OldLastChar = LastChar;
831            }
832        }
833        argptr = Cursor;
834    } while (endflag);
835    Cursor = OldCursor;
836    return matchval;
837}
838
839/*
840 * CompleteLine - do command completion on the entire command line
841 * (which may have trailing newline).
842 * Return value:
843 *  0: No command matched or failure
844 *  1: One command matched
845 *  2: Several commands matched
846 */
847static int
848CompleteLine()
849{
850    int     endflag, tmatch;
851    Char   *argptr, *OldCursor, *OldLastChar;
852
853    OldLastChar = LastChar;
854    OldCursor = Cursor;
855    argptr = InputBuf;
856    endflag = 1;
857    do {
858        while (ismetahash(*argptr) || iscmdmeta(*argptr))
859            argptr++;
860        for (Cursor = argptr;
861             *Cursor != '\0' && ((Cursor != argptr && Cursor[-1] == '\\') ||
862                                 (!ismetahash(*Cursor) && !iscmdmeta(*Cursor)));
863             Cursor++)
864             continue;
865        if (*Cursor == '\0') {
866            Cursor = LastChar;
867            if (LastChar[-1] == '\n')
868                Cursor--;
869            endflag = 0;
870        }
871        if (!Strchr(mismatch, *argptr) && starting_a_command(argptr, InputBuf)) {
872            tmatch = tenematch(InputBuf, Cursor - InputBuf, RECOGNIZE);
873            if (tmatch <= 0) {
874                return 0;
875            } else if (tmatch > 1) {
876                return 2;
877            }
878            if (LastChar != OldLastChar) {
879                if (argptr < OldCursor)
880                    OldCursor += (LastChar - OldLastChar);
881                OldLastChar = LastChar;
882            }
883        }
884        argptr = Cursor;
885    } while (endflag);
886    Cursor = OldCursor;
887    return 1;
888}
889
Note: See TracBrowser for help on using the repository browser.