Kernel part of bluetooth stack ported by Dmitry Komissaroff. Very much work
[dragonfly.git] / contrib / tcsh / ed.inputl.c
blob68da69dd23b27aabdbe295f5a327f4a5dbf9b226
1 /* $Header: /src/pub/tcsh/ed.inputl.c,v 3.51 2002/06/25 19:02:11 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.
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. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
33 #include "sh.h"
35 RCSID("$Id: ed.inputl.c,v 3.51 2002/06/25 19:02:11 christos Exp $")
37 #include "ed.h"
38 #include "ed.defns.h" /* for the function names */
39 #include "tw.h" /* for twenex stuff */
41 #define OKCMD (INBUFSIZE+INBUFSIZE)
43 /* ed.inputl -- routines to get a single line from the input. */
45 extern bool tellwhat;
46 extern bool MapsAreInited;
47 extern bool Tty_raw_mode;
49 /* mismatched first character */
50 static Char mismatch[] =
51 {'!', '^' , '\\', '-', '%', '\0', '"', '\'', '`', '\0' };
53 static int Repair __P((void));
54 static int GetNextCommand __P((KEYCMD *, Char *));
55 static int SpellLine __P((int));
56 static int CompleteLine __P((void));
57 static void RunCommand __P((Char *));
58 static void doeval1 __P((Char **));
60 static bool rotate = 0;
63 static int
64 Repair()
66 if (NeedsRedraw) {
67 ClearLines();
68 ClearDisp();
69 NeedsRedraw = 0;
71 Refresh();
72 Argument = 1;
73 DoingArg = 0;
74 curchoice = -1;
75 return (int) (LastChar - InputBuf);
78 /* CCRETVAL */
79 int
80 Inputl()
82 CCRETVAL retval;
83 KEYCMD cmdnum = 0;
84 extern KEYCMD NumFuns;
85 unsigned char tch; /* the place where read() goes */
86 Char ch;
87 int num; /* how many chars we have read at NL */
88 int expnum;
89 struct varent *crct = inheredoc ? NULL : adrof(STRcorrect);
90 struct varent *autol = adrof(STRautolist);
91 struct varent *matchbeep = adrof(STRmatchbeep);
92 struct varent *imode = adrof(STRinputmode);
93 Char *SaveChar, *CorrChar;
94 Char Origin[INBUFSIZE], Change[INBUFSIZE];
95 int matchval; /* from tenematch() */
96 COMMAND fn;
97 int curlen = 0;
98 int newlen;
99 int idx;
101 if (!MapsAreInited) /* double extra just in case */
102 ed_InitMaps();
104 ClearDisp(); /* reset the display stuff */
105 ResetInLine(0); /* reset the input pointers */
106 if (GettingInput)
107 MacroLvl = -1; /* editor was interrupted during input */
109 if (imode && imode->vec != NULL) {
110 if (!Strcmp(*(imode->vec), STRinsert))
111 inputmode = MODE_INSERT;
112 else if (!Strcmp(*(imode->vec), STRoverwrite))
113 inputmode = MODE_REPLACE;
116 #if defined(FIONREAD) && !defined(OREO)
117 if (!Tty_raw_mode && MacroLvl < 0) {
118 # ifdef SUNOS4
119 long chrs = 0;
120 # else /* !SUNOS4 */
122 * *Everyone* else has an int, but SunOS wants long!
123 * This breaks where int != long (alpha)
125 int chrs = 0;
126 # endif /* SUNOS4 */
128 (void) ioctl(SHIN, FIONREAD, (ioctl_t) & chrs);
129 if (chrs == 0) {
130 if (Rawmode() < 0)
131 return 0;
134 #endif /* FIONREAD && !OREO */
136 GettingInput = 1;
137 NeedsRedraw = 0;
139 if (tellwhat) {
140 copyn(InputBuf, WhichBuf, INBUFSIZE);
141 LastChar = InputBuf + (LastWhich - WhichBuf);
142 Cursor = InputBuf + (CursWhich - WhichBuf);
143 tellwhat = 0;
144 Hist_num = HistWhich;
146 if (Expand) {
147 (void) e_up_hist(0);
148 Expand = 0;
150 Refresh(); /* print the prompt */
152 for (num = OKCMD; num == OKCMD;) { /* while still editing this line */
153 #ifdef DEBUG_EDIT
154 if (Cursor > LastChar)
155 xprintf("Cursor > LastChar\r\n");
156 if (Cursor < InputBuf)
157 xprintf("Cursor < InputBuf\r\n");
158 if (Cursor > InputLim)
159 xprintf("Cursor > InputLim\r\n");
160 if (LastChar > InputLim)
161 xprintf("LastChar > InputLim\r\n");
162 if (InputLim != &InputBuf[INBUFSIZE - 2])
163 xprintf("InputLim != &InputBuf[INBUFSIZE-2]\r\n");
164 if ((!DoingArg) && (Argument != 1))
165 xprintf("(!DoingArg) && (Argument != 1)\r\n");
166 if (CcKeyMap[0] == 0)
167 xprintf("CcKeyMap[0] == 0 (maybe not inited)\r\n");
168 #endif
170 /* if EOF or error */
171 if ((num = GetNextCommand(&cmdnum, &ch)) != OKCMD) {
172 break;
175 if (cmdnum >= NumFuns) {/* BUG CHECK command */
176 #ifdef DEBUG_EDIT
177 xprintf(CGETS(6, 1, "ERROR: illegal command from key 0%o\r\n"), ch);
178 #endif
179 continue; /* try again */
182 /* now do the real command */
183 retval = (*CcFuncTbl[cmdnum]) (ch);
185 /* save the last command here */
186 LastCmd = cmdnum;
188 /* make sure fn is initialized */
189 fn = (retval == CC_COMPLETE_ALL) ? LIST_ALL : LIST;
191 /* use any return value */
192 switch (retval) {
194 case CC_REFRESH:
195 Refresh();
196 /*FALLTHROUGH*/
197 case CC_NORM: /* normal char */
198 Argument = 1;
199 DoingArg = 0;
200 /*FALLTHROUGH*/
201 case CC_ARGHACK: /* Suggested by Rich Salz */
202 /* <rsalz@pineapple.bbn.com> */
203 curchoice = -1;
204 curlen = (int) (LastChar - InputBuf);
205 break; /* keep going... */
207 case CC_EOF: /* end of file typed */
208 curchoice = -1;
209 curlen = (int) (LastChar - InputBuf);
210 num = 0;
211 break;
213 case CC_WHICH: /* tell what this command does */
214 tellwhat = 1;
215 copyn(WhichBuf, InputBuf, INBUFSIZE);
216 LastWhich = WhichBuf + (LastChar - InputBuf);
217 CursWhich = WhichBuf + (Cursor - InputBuf);
218 *LastChar++ = '\n'; /* for the benifit of CSH */
219 HistWhich = Hist_num;
220 Hist_num = 0; /* for the history commands */
221 num = (int) (LastChar - InputBuf); /* number characters read */
222 break;
224 case CC_NEWLINE: /* normal end of line */
225 curlen = 0;
226 curchoice = -1;
227 matchval = 1;
228 if (crct && crct->vec != NULL && (!Strcmp(*(crct->vec), STRcmd) ||
229 !Strcmp(*(crct->vec), STRall))) {
230 PastBottom();
231 copyn(Origin, InputBuf, INBUFSIZE);
232 SaveChar = LastChar;
233 if (SpellLine(!Strcmp(*(crct->vec), STRcmd)) == 1) {
234 PastBottom();
235 copyn(Change, InputBuf, INBUFSIZE);
236 *Strchr(Change, '\n') = '\0';
237 CorrChar = LastChar; /* Save the corrected end */
238 LastChar = InputBuf; /* Null the current line */
239 SoundBeep();
240 printprompt(2, short2str(Change));
241 Refresh();
242 if (read(SHIN, (char *) &tch, 1) < 0)
243 #ifdef convex
245 * need to print error message in case file
246 * is migrated
248 if (errno && errno != EINTR)
249 stderror(ERR_SYSTEM, progname, strerror(errno));
250 #else
251 break;
252 #endif
253 ch = tch;
254 if (ch == 'y' || ch == ' ') {
255 LastChar = CorrChar; /* Restore the corrected end */
256 xprintf(CGETS(6, 2, "yes\n"));
258 else {
259 copyn(InputBuf, Origin, INBUFSIZE);
260 LastChar = SaveChar;
261 if (ch == 'e') {
262 xprintf(CGETS(6, 3, "edit\n"));
263 *LastChar-- = '\0';
264 Cursor = LastChar;
265 printprompt(3, NULL);
266 ClearLines();
267 ClearDisp();
268 Refresh();
269 break;
271 else if (ch == 'a') {
272 xprintf(CGETS(6, 4, "abort\n"));
273 LastChar = InputBuf; /* Null the current line */
274 Cursor = LastChar;
275 printprompt(0, NULL);
276 Refresh();
277 break;
279 xprintf(CGETS(6, 5, "no\n"));
281 flush();
283 } else if (crct && crct->vec != NULL &&
284 !Strcmp(*(crct->vec), STRcomplete)) {
285 if (LastChar > InputBuf && LastChar[-1] == '\n') {
286 LastChar[-1] = '\0';
287 LastChar--;
288 Cursor = LastChar;
290 match_unique_match = 1; /* match unique matches */
291 matchval = CompleteLine();
292 match_unique_match = 0;
293 curlen = (int) (LastChar - InputBuf);
294 if (matchval != 1) {
295 PastBottom();
297 if (matchval == 0) {
298 xprintf(CGETS(6, 6, "No matching command\n"));
299 } else if (matchval == 2) {
300 xprintf(CGETS(6, 7, "Ambiguous command\n"));
302 if (NeedsRedraw) {
303 ClearLines();
304 ClearDisp();
305 NeedsRedraw = 0;
307 Refresh();
308 Argument = 1;
309 DoingArg = 0;
310 if (matchval == 1) {
311 PastBottom();
312 *LastChar++ = '\n';
313 *LastChar = '\0';
315 curlen = (int) (LastChar - InputBuf);
317 else
318 PastBottom();
320 if (matchval == 1) {
321 tellwhat = 0; /* just in case */
322 Hist_num = 0; /* for the history commands */
323 /* return the number of chars read */
324 num = (int) (LastChar - InputBuf);
326 * For continuation lines, we set the prompt to prompt 2
328 printprompt(1, NULL);
330 break;
332 case CC_CORRECT:
333 if (tenematch(InputBuf, Cursor - InputBuf, SPELL) < 0)
334 SoundBeep(); /* Beep = No match/ambiguous */
335 curlen = Repair();
336 break;
338 case CC_CORRECT_L:
339 if (SpellLine(FALSE) < 0)
340 SoundBeep(); /* Beep = No match/ambiguous */
341 curlen = Repair();
342 break;
345 case CC_COMPLETE:
346 case CC_COMPLETE_ALL:
347 case CC_COMPLETE_FWD:
348 case CC_COMPLETE_BACK:
349 switch (retval) {
350 case CC_COMPLETE:
351 fn = RECOGNIZE;
352 curlen = (int) (LastChar - InputBuf);
353 curchoice = -1;
354 rotate = 0;
355 break;
356 case CC_COMPLETE_ALL:
357 fn = RECOGNIZE_ALL;
358 curlen = (int) (LastChar - InputBuf);
359 curchoice = -1;
360 rotate = 0;
361 break;
362 case CC_COMPLETE_FWD:
363 fn = RECOGNIZE_SCROLL;
364 curchoice++;
365 rotate = 1;
366 break;
367 case CC_COMPLETE_BACK:
368 fn = RECOGNIZE_SCROLL;
369 curchoice--;
370 rotate = 1;
371 break;
372 default:
373 abort();
375 if (InputBuf[curlen] && rotate) {
376 newlen = (int) (LastChar - InputBuf);
377 for (idx = (int) (Cursor - InputBuf);
378 idx <= newlen; idx++)
379 InputBuf[idx - newlen + curlen] =
380 InputBuf[idx];
381 LastChar = InputBuf + curlen;
382 Cursor = Cursor - newlen + curlen;
384 curlen = (int) (LastChar - InputBuf);
387 if (adrof(STRautoexpand))
388 (void) e_expand_history(0);
390 * Modified by Martin Boyer (gamin@ireq-robot.hydro.qc.ca):
391 * A separate variable now controls beeping after
392 * completion, independently of autolisting.
394 expnum = (int) (Cursor - InputBuf);
395 switch (matchval = tenematch(InputBuf, Cursor-InputBuf, fn)){
396 case 1:
397 if (non_unique_match && matchbeep && matchbeep->vec != NULL &&
398 (Strcmp(*(matchbeep->vec), STRnotunique) == 0))
399 SoundBeep();
400 break;
401 case 0:
402 if (matchbeep && matchbeep->vec != NULL) {
403 if (Strcmp(*(matchbeep->vec), STRnomatch) == 0 ||
404 Strcmp(*(matchbeep->vec), STRambiguous) == 0 ||
405 Strcmp(*(matchbeep->vec), STRnotunique) == 0)
406 SoundBeep();
408 else
409 SoundBeep();
410 break;
411 default:
412 if (matchval < 0) { /* Error from tenematch */
413 curchoice = -1;
414 SoundBeep();
415 break;
417 if (matchbeep && matchbeep->vec != NULL) {
418 if ((Strcmp(*(matchbeep->vec), STRambiguous) == 0 ||
419 Strcmp(*(matchbeep->vec), STRnotunique) == 0))
420 SoundBeep();
422 else
423 SoundBeep();
425 * Addition by David C Lawrence <tale@pawl.rpi.edu>: If an
426 * attempted completion is ambiguous, list the choices.
427 * (PWP: this is the best feature addition to tcsh I have
428 * seen in many months.)
430 if (autol && autol->vec != NULL &&
431 (Strcmp(*(autol->vec), STRambiguous) != 0 ||
432 expnum == Cursor - InputBuf)) {
433 PastBottom();
434 fn = (retval == CC_COMPLETE_ALL) ? LIST_ALL : LIST;
435 (void) tenematch(InputBuf, Cursor-InputBuf, fn);
437 break;
439 if (NeedsRedraw) {
440 PastBottom();
441 ClearLines();
442 ClearDisp();
443 NeedsRedraw = 0;
445 Refresh();
446 Argument = 1;
447 DoingArg = 0;
448 break;
450 case CC_LIST_CHOICES:
451 case CC_LIST_ALL:
452 if (InputBuf[curlen] && rotate) {
453 newlen = (int) (LastChar - InputBuf);
454 for (idx = (int) (Cursor - InputBuf);
455 idx <= newlen; idx++)
456 InputBuf[idx - newlen + curlen] =
457 InputBuf[idx];
458 LastChar = InputBuf + curlen;
459 Cursor = Cursor - newlen + curlen;
461 curlen = (int) (LastChar - InputBuf);
462 if (curchoice >= 0)
463 curchoice--;
465 fn = (retval == CC_LIST_ALL) ? LIST_ALL : LIST;
466 /* should catch ^C here... */
467 if (tenematch(InputBuf, Cursor - InputBuf, fn) < 0)
468 SoundBeep();
469 Refresh();
470 Argument = 1;
471 DoingArg = 0;
472 break;
475 case CC_LIST_GLOB:
476 if (tenematch(InputBuf, Cursor - InputBuf, GLOB) < 0)
477 SoundBeep();
478 curlen = Repair();
479 break;
481 case CC_EXPAND_GLOB:
482 if (tenematch(InputBuf, Cursor - InputBuf, GLOB_EXPAND) <= 0)
483 SoundBeep(); /* Beep = No match */
484 curlen = Repair();
485 break;
487 case CC_NORMALIZE_PATH:
488 if (tenematch(InputBuf, Cursor - InputBuf, PATH_NORMALIZE) <= 0)
489 SoundBeep(); /* Beep = No match */
490 curlen = Repair();
491 break;
493 case CC_EXPAND_VARS:
494 if (tenematch(InputBuf, Cursor - InputBuf, VARS_EXPAND) <= 0)
495 SoundBeep(); /* Beep = No match */
496 curlen = Repair();
497 break;
499 case CC_NORMALIZE_COMMAND:
500 if (tenematch(InputBuf, Cursor - InputBuf, COMMAND_NORMALIZE) <= 0)
501 SoundBeep(); /* Beep = No match */
502 curlen = Repair();
503 break;
505 case CC_HELPME:
506 xputchar('\n');
507 /* should catch ^C here... */
508 (void) tenematch(InputBuf, LastChar - InputBuf, PRINT_HELP);
509 Refresh();
510 Argument = 1;
511 DoingArg = 0;
512 curchoice = -1;
513 curlen = (int) (LastChar - InputBuf);
514 break;
516 case CC_FATAL: /* fatal error, reset to known state */
517 #ifdef DEBUG_EDIT
518 xprintf(CGETS(7, 8, "*** editor fatal ERROR ***\r\n\n"));
519 #endif /* DEBUG_EDIT */
520 /* put (real) cursor in a known place */
521 ClearDisp(); /* reset the display stuff */
522 ResetInLine(1); /* reset the input pointers */
523 Refresh(); /* print the prompt again */
524 Argument = 1;
525 DoingArg = 0;
526 curchoice = -1;
527 curlen = (int) (LastChar - InputBuf);
528 break;
530 case CC_ERROR:
531 default: /* functions we don't know about */
532 DoingArg = 0;
533 Argument = 1;
534 SoundBeep();
535 flush();
536 curchoice = -1;
537 curlen = (int) (LastChar - InputBuf);
538 break;
541 (void) Cookedmode(); /* make sure the tty is set up correctly */
542 GettingInput = 0;
543 flush(); /* flush any buffered output */
544 return num;
547 void
548 PushMacro(str)
549 Char *str;
551 if (str != NULL && MacroLvl + 1 < MAXMACROLEVELS) {
552 MacroLvl++;
553 KeyMacro[MacroLvl] = str;
555 else {
556 SoundBeep();
557 flush();
562 * Like eval, only using the current file descriptors
564 static Char **gv = NULL, **gav = NULL;
566 static void
567 doeval1(v)
568 Char **v;
570 Char **oevalvec;
571 Char *oevalp;
572 int my_reenter;
573 Char **savegv;
574 jmp_buf_t osetexit;
576 oevalvec = evalvec;
577 oevalp = evalp;
578 savegv = gv;
579 gav = v;
582 gflag = 0, tglob(gav);
583 if (gflag) {
584 gv = gav = globall(gav);
585 gargv = 0;
586 if (gav == 0)
587 stderror(ERR_NOMATCH);
588 gav = copyblk(gav);
590 else {
591 gv = NULL;
592 gav = copyblk(gav);
593 trim(gav);
596 getexit(osetexit);
598 /* PWP: setjmp/longjmp bugfix for optimizing compilers */
599 #ifdef cray
600 my_reenter = 1; /* assume non-zero return val */
601 if (setexit() == 0) {
602 my_reenter = 0; /* Oh well, we were wrong */
603 #else /* !cray */
604 if ((my_reenter = setexit()) == 0) {
605 #endif /* cray */
606 evalvec = gav;
607 evalp = 0;
608 process(0);
611 evalvec = oevalvec;
612 evalp = oevalp;
613 doneinp = 0;
615 if (gv)
616 blkfree(gv);
618 gv = savegv;
619 resexit(osetexit);
620 if (my_reenter)
621 stderror(ERR_SILENT);
624 static void
625 RunCommand(str)
626 Char *str;
628 Char *cmd[2];
630 xputchar('\n'); /* Start on a clean line */
632 cmd[0] = str;
633 cmd[1] = NULL;
635 (void) Cookedmode();
636 GettingInput = 0;
638 doeval1(cmd);
640 (void) Rawmode();
641 GettingInput = 1;
643 ClearLines();
644 ClearDisp();
645 NeedsRedraw = 0;
646 Refresh();
649 static int
650 GetNextCommand(cmdnum, ch)
651 KEYCMD *cmdnum;
652 register Char *ch;
654 KEYCMD cmd = 0;
655 int num;
657 while (cmd == 0 || cmd == F_XKEY) {
658 if ((num = GetNextChar(ch)) != 1) { /* if EOF or error */
659 return num;
661 #ifdef KANJI
662 if (
663 #ifdef DSPMBYTE
664 _enable_mbdisp &&
665 #endif
666 !adrof(STRnokanji) && (*ch & META)) {
667 MetaNext = 0;
668 cmd = F_INSERT;
669 break;
671 else
672 #endif /* KANJI */
673 if (MetaNext) {
674 MetaNext = 0;
675 *ch |= META;
677 /* XXX: This needs to be fixed so that we don't just truncate
678 * the character, we unquote it.
680 if (*ch < NT_NUM_KEYS)
681 cmd = CurrentKeyMap[*ch];
682 else
683 cmd = CurrentKeyMap[(unsigned char) *ch];
684 if (cmd == F_XKEY) {
685 XmapVal val;
686 CStr cstr;
687 cstr.buf = ch;
688 cstr.len = Strlen(ch);
689 switch (GetXkey(&cstr, &val)) {
690 case XK_CMD:
691 cmd = val.cmd;
692 break;
693 case XK_STR:
694 PushMacro(val.str.buf);
695 break;
696 case XK_EXE:
697 RunCommand(val.str.buf);
698 break;
699 default:
700 abort();
701 break;
704 if (!AltKeyMap)
705 CurrentKeyMap = CcKeyMap;
707 *cmdnum = cmd;
708 return OKCMD;
712 GetNextChar(cp)
713 register Char *cp;
715 register int num_read;
716 int tried = 0;
717 unsigned char tcp;
719 for (;;) {
720 if (MacroLvl < 0) {
721 if (!Load_input_line())
722 break;
724 if (*KeyMacro[MacroLvl] == 0) {
725 MacroLvl--;
726 continue;
728 *cp = *KeyMacro[MacroLvl]++ & CHAR;
729 if (*KeyMacro[MacroLvl] == 0) { /* Needed for QuoteMode On */
730 MacroLvl--;
732 return (1);
735 if (Rawmode() < 0) /* make sure the tty is set up correctly */
736 return 0; /* oops: SHIN was closed */
738 #ifdef WINNT_NATIVE
739 __nt_want_vcode = 1;
740 #endif /* WINNT_NATIVE */
741 while ((num_read = read(SHIN, (char *) &tcp, 1)) == -1) {
742 if (errno == EINTR)
743 continue;
744 if (!tried && fixio(SHIN, errno) != -1)
745 tried = 1;
746 else {
747 #ifdef convex
748 /* need to print error message in case the file is migrated */
749 if (errno != EINTR)
750 stderror(ERR_SYSTEM, progname, strerror(errno));
751 #endif /* convex */
752 #ifdef WINNT_NATIVE
753 __nt_want_vcode = 0;
754 #endif /* WINNT_NATIVE */
755 *cp = '\0';
756 return -1;
759 #ifdef WINNT_NATIVE
760 if (__nt_want_vcode == 2)
761 *cp = __nt_vcode;
762 else
763 *cp = tcp;
764 __nt_want_vcode = 0;
765 #else
766 *cp = tcp;
767 #endif /* WINNT_NATIVE */
768 return num_read;
772 * SpellLine - do spelling correction on the entire command line
773 * (which may have trailing newline).
774 * If cmdonly is set, only check spelling of command words.
775 * Return value:
776 * -1: Something was incorrectible, and nothing was corrected
777 * 0: Everything was correct
778 * 1: Something was corrected
780 static int
781 SpellLine(cmdonly)
782 int cmdonly;
784 int endflag, matchval;
785 Char *argptr, *OldCursor, *OldLastChar;
787 OldLastChar = LastChar;
788 OldCursor = Cursor;
789 argptr = InputBuf;
790 endflag = 1;
791 matchval = 0;
792 do {
793 while (ismetahash(*argptr) || iscmdmeta(*argptr))
794 argptr++;
795 for (Cursor = argptr;
796 *Cursor != '\0' && ((Cursor != argptr && Cursor[-1] == '\\') ||
797 (!ismetahash(*Cursor) && !iscmdmeta(*Cursor)));
798 Cursor++)
799 continue;
800 if (*Cursor == '\0') {
801 Cursor = LastChar;
802 if (LastChar[-1] == '\n')
803 Cursor--;
804 endflag = 0;
806 /* Obey current history character settings */
807 mismatch[0] = HIST;
808 mismatch[1] = HISTSUB;
809 if (!Strchr(mismatch, *argptr) &&
810 (!cmdonly || starting_a_command(argptr, InputBuf))) {
811 #ifdef WINNT_NATIVE
813 * This hack avoids correcting drive letter changes
815 if((Cursor - InputBuf) != 2 || (char)InputBuf[1] != ':')
816 #endif /* WINNT_NATIVE */
818 #ifdef HASH_SPELL_CHECK
819 Char save;
820 size_t len = Cursor - InputBuf;
822 save = InputBuf[len];
823 InputBuf[len] = '\0';
824 if (find_cmd(InputBuf, 0) != 0) {
825 InputBuf[len] = save;
826 argptr = Cursor;
827 continue;
829 InputBuf[len] = save;
830 #endif /* HASH_SPELL_CHECK */
831 switch (tenematch(InputBuf, Cursor - InputBuf, SPELL)) {
832 case 1: /* corrected */
833 matchval = 1;
834 break;
835 case -1: /* couldn't be corrected */
836 if (!matchval)
837 matchval = -1;
838 break;
839 default: /* was correct */
840 break;
843 if (LastChar != OldLastChar) {
844 if (argptr < OldCursor)
845 OldCursor += (LastChar - OldLastChar);
846 OldLastChar = LastChar;
849 argptr = Cursor;
850 } while (endflag);
851 Cursor = OldCursor;
852 return matchval;
856 * CompleteLine - do command completion on the entire command line
857 * (which may have trailing newline).
858 * Return value:
859 * 0: No command matched or failure
860 * 1: One command matched
861 * 2: Several commands matched
863 static int
864 CompleteLine()
866 int endflag, tmatch;
867 Char *argptr, *OldCursor, *OldLastChar;
869 OldLastChar = LastChar;
870 OldCursor = Cursor;
871 argptr = InputBuf;
872 endflag = 1;
873 do {
874 while (ismetahash(*argptr) || iscmdmeta(*argptr))
875 argptr++;
876 for (Cursor = argptr;
877 *Cursor != '\0' && ((Cursor != argptr && Cursor[-1] == '\\') ||
878 (!ismetahash(*Cursor) && !iscmdmeta(*Cursor)));
879 Cursor++)
880 continue;
881 if (*Cursor == '\0') {
882 Cursor = LastChar;
883 if (LastChar[-1] == '\n')
884 Cursor--;
885 endflag = 0;
887 if (!Strchr(mismatch, *argptr) && starting_a_command(argptr, InputBuf)) {
888 tmatch = tenematch(InputBuf, Cursor - InputBuf, RECOGNIZE);
889 if (tmatch <= 0) {
890 return 0;
891 } else if (tmatch > 1) {
892 return 2;
894 if (LastChar != OldLastChar) {
895 if (argptr < OldCursor)
896 OldCursor += (LastChar - OldLastChar);
897 OldLastChar = LastChar;
900 argptr = Cursor;
901 } while (endflag);
902 Cursor = OldCursor;
903 return 1;