xref: /freebsd/contrib/tcsh/ed.chared.c (revision 6780ab54325a71e7e70112b11657973edde8655e)
1 /* $Header: /src/pub/tcsh/ed.chared.c,v 3.71 2002/03/08 17:36:45 christos Exp $ */
2 /*
3  * ed.chared.c: Character editing functions.
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. 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.
20  *
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.
32  */
33 /*
34   Bjorn Knutsson @ Thu Jun 24 19:02:17 1999
35 
36   e_dabbrev_expand() did not do proper completion if quoted spaces were present
37   in the string being completed. Exemple:
38 
39   # echo hello\ world
40   hello world
41   # echo h<press key bound to dabbrev-expande>
42   # echo hello\<cursor>
43 
44   Correct behavior is:
45   # echo h<press key bound to dabbrev-expande>
46   # echo hello\ world<cursor>
47 
48   The same problem occured if spaces were present in a string withing quotation
49   marks. Example:
50 
51   # echo "hello world"
52   hello world
53   # echo "h<press key bound to dabbrev-expande>
54   # echo "hello<cursor>
55 
56   The former problem could be solved with minor modifications of c_preword()
57   and c_endword(). The latter, however, required a significant rewrite of
58   c_preword(), since quoted strings must be parsed from start to end to
59   determine if a given character is inside or outside the quotation marks.
60 
61   Compare the following two strings:
62 
63   # echo \"" 'foo \' bar\"
64   " 'foo \' bar\
65   # echo '\"" 'foo \' bar\"
66   \"" foo ' bar"
67 
68   The only difference between the two echo lines is in the first character
69   after the echo command. The result is either one or three arguments.
70 
71  */
72 
73 #include "sh.h"
74 
75 RCSID("$Id: ed.chared.c,v 3.71 2002/03/08 17:36:45 christos Exp $")
76 
77 #include "ed.h"
78 #include "tw.h"
79 #include "ed.defns.h"
80 
81 /* #define SDEBUG */
82 
83 #define TCSHOP_NOP    	  0x00
84 #define TCSHOP_DELETE 	  0x01
85 #define TCSHOP_INSERT 	  0x02
86 #define TCSHOP_CHANGE 	  0x04
87 
88 #define CHAR_FWD	0
89 #define CHAR_BACK	1
90 
91 /*
92  * vi word treatment
93  * from: Gert-Jan Vons <vons@cesar.crbca1.sinet.slb.com>
94  */
95 #define C_CLASS_WHITE	1
96 #define C_CLASS_ALNUM	2
97 #define C_CLASS_OTHER	3
98 
99 static Char *InsertPos = InputBuf; /* Where insertion starts */
100 static Char *ActionPos = 0;	   /* Where action begins  */
101 static int  ActionFlag = TCSHOP_NOP;	   /* What delayed action to take */
102 /*
103  * Word search state
104  */
105 static int  searchdir = F_UP_SEARCH_HIST; 	/* Direction of last search */
106 static Char patbuf[INBUFSIZE];			/* Search target */
107 static int patlen = 0;
108 /*
109  * Char search state
110  */
111 static int  srch_dir = CHAR_FWD;		/* Direction of last search */
112 static Char srch_char = 0;			/* Search target */
113 
114 /* all routines that start with c_ are private to this set of routines */
115 static	void	 c_alternativ_key_map	__P((int));
116 void	 c_insert		__P((int));
117 void	 c_delafter		__P((int));
118 void	 c_delbefore		__P((int));
119 static 	int	 c_to_class		__P((int));
120 static	Char	*c_prev_word		__P((Char *, Char *, int));
121 static	Char	*c_next_word		__P((Char *, Char *, int));
122 static	Char	*c_number		__P((Char *, int *, int));
123 static	Char	*c_expand		__P((Char *));
124 static	void	 c_excl			__P((Char *));
125 static	void	 c_substitute		__P((void));
126 static	void	 c_delfini		__P((void));
127 static	int	 c_hmatch		__P((Char *));
128 static	void	 c_hsetpat		__P((void));
129 #ifdef COMMENT
130 static	void	 c_get_word		__P((Char **, Char **));
131 #endif
132 static	Char	*c_preword		__P((Char *, Char *, int, Char *));
133 static	Char	*c_nexword		__P((Char *, Char *, int));
134 static	Char	*c_endword		__P((Char *, Char *, int, Char *));
135 static	Char	*c_eword		__P((Char *, Char *, int));
136 static	void	 c_push_kill		__P((Char *, Char *));
137 static  CCRETVAL c_get_histline		__P((void));
138 static  CCRETVAL c_search_line		__P((Char *, int));
139 static  CCRETVAL v_repeat_srch		__P((int));
140 static	CCRETVAL e_inc_search		__P((int));
141 static	CCRETVAL v_search		__P((int));
142 static	CCRETVAL v_csearch_fwd		__P((int, int, int));
143 static	CCRETVAL v_action		__P((int));
144 static	CCRETVAL v_csearch_back		__P((int, int, int));
145 
146 #if defined(DSPMBYTE)
147 static	void 	 e_charfwd_mbyte	__P((int));
148 static	void 	 e_charback_mbyte	__P((int));
149 static  int extdel;
150 static  int extins = 0;
151 #endif
152 
153 static void
154 c_alternativ_key_map(state)
155     int     state;
156 {
157     switch (state) {
158     case 0:
159 	CurrentKeyMap = CcKeyMap;
160 	break;
161     case 1:
162 	CurrentKeyMap = CcAltMap;
163 	break;
164     default:
165 	return;
166     }
167 
168     AltKeyMap = (Char) state;
169 }
170 
171 void
172 c_insert(num)
173     int num;
174 {
175     Char *cp;
176 
177     if (LastChar + num >= InputLim)
178 	return;			/* can't go past end of buffer */
179 
180     if (Cursor < LastChar) {	/* if I must move chars */
181 	for (cp = LastChar; cp >= Cursor; cp--)
182 	    cp[num] = *cp;
183     }
184     LastChar += num;
185 }
186 
187 void
188 c_delafter(num)
189     int num;
190 {
191     Char *cp, *kp = NULL;
192 
193 #if defined(DSPMBYTE)
194     Char *wkcp;
195 
196     extdel = 0;
197 #endif
198 
199     if (num > LastChar - Cursor)
200 	num = (int) (LastChar - Cursor);	/* bounds check */
201 
202     if (num > 0) {			/* if I can delete anything */
203 #if defined(DSPMBYTE)
204 	/* check for code of deleted character */
205 	if (_enable_mbdisp) {
206 	    for (wkcp = Cursor ; wkcp < Cursor + num; wkcp++) {
207 		if (extdel == 0)
208 		    extdel = Ismbyte1(*wkcp); /* check to 1st. byte */
209 		else
210 		    extdel = 0;	/* if 2nd. byte, force set to 0 */
211 	    }
212 	}
213 #endif
214 	if (VImode) {
215 	    kp = UndoBuf;		/* Set Up for VI undo command */
216 	    UndoAction = TCSHOP_INSERT;
217 	    UndoSize = num;
218 	    UndoPtr  = Cursor;
219 	    for (cp = Cursor; cp <= LastChar; cp++) {
220 		*kp++ = *cp;	/* Save deleted chars into undobuf */
221 		*cp = cp[num];
222 	    }
223 	}
224 	else
225 	    for (cp = Cursor; cp <= LastChar; cp++)
226 		*cp = cp[num];
227 	LastChar -= num;
228 #if defined(DSPMBYTE)
229 	if (_enable_mbdisp && extdel && Ismbyte2(*Cursor)) {
230 	    if( VImode ) {
231 		UndoSize++;
232 		*kp++ = *Cursor; /* Save deleted chars into undobuf */
233 	    }
234 	    for (cp = Cursor; cp <= LastChar; cp++)
235 		*cp = cp[1];
236 	    LastChar--;
237 	    e_redisp( 1 );
238 	}
239 	else
240 	    extdel = 0;
241 #endif
242     }
243 #ifdef notdef
244     else {
245 	/*
246 	 * XXX: We don't want to do that. In emacs mode overwrite should be
247 	 * sticky. I am not sure how that affects vi mode
248 	 */
249 	inputmode = MODE_INSERT;
250     }
251 #endif /* notdef */
252 }
253 
254 void
255 c_delbefore(num)		/* delete before dot, with bounds checking */
256     int num;
257 {
258     Char *cp, *kp = NULL;
259 
260 #if defined(DSPMBYTE)
261     Char *nowcur, *wkcp;
262     Char delc;
263 
264     extdel = 0;
265 #endif
266 
267     if (num > Cursor - InputBuf)
268 	num = (int) (Cursor - InputBuf);	/* bounds check */
269 
270     if (num > 0) {			/* if I can delete anything */
271 #if defined(DSPMBYTE)
272 	nowcur = Cursor - num;
273 	delc = *nowcur;
274 #endif
275 	if (VImode) {
276 	    kp = UndoBuf;		/* Set Up for VI undo command */
277 	    UndoAction = TCSHOP_INSERT;
278 	    UndoSize = num;
279 	    UndoPtr  = Cursor - num;
280 	    for (cp = Cursor - num; cp <= LastChar; cp++) {
281 		*kp++ = *cp;
282 		*cp = cp[num];
283 	    }
284 	}
285 	else
286 	    for (cp = Cursor - num; cp <= LastChar; cp++)
287 		*cp = cp[num];
288 	LastChar -= num;
289 #if defined(DSPMBYTE)
290 	if (_enable_mbdisp) {
291 	    for (wkcp = InputBuf; wkcp < nowcur; wkcp++) {
292 		if(extdel == 0)
293 		    extdel = Ismbyte1(*wkcp); /* check to 1st. byte */
294 		else
295 		    extdel = 0;	/* if 2nd. byte, force set to 0 */
296 	    }
297 	    if (extdel && Ismbyte2(delc)) {
298 		if( VImode ) {
299 		    UndoSize++;
300 		    UndoPtr--;
301 		    *kp++ = *(nowcur-1);
302 				/* Save deleted chars into undobuf */
303 		}
304 		for (cp = nowcur - 1; cp <= LastChar; cp++)
305 		    *cp = cp[1];
306 		LastChar--;
307 	    }
308 	}
309 	else
310 	    extdel = 0;
311 #endif
312     }
313 }
314 
315 static Char *
316 c_preword(p, low, n, delim)
317     Char *p, *low, *delim;
318     int n;
319 {
320   while (n--) {
321     Char *prev = low;
322     Char *new;
323 
324     while (prev < p) {		/* Skip initial non-word chars */
325       if (!Strchr(delim, *prev) || *(prev-1) == (Char)'\\')
326 	break;
327       prev++;
328     }
329 
330     new = prev;
331 
332     while (new < p) {
333       prev = new;
334       new = c_endword(prev-1, p, 1, delim); /* Skip to next non-word char */
335       new++;			/* Step away from end of word */
336       while (new <= p) {	/* Skip trailing non-word chars */
337 	if (!Strchr(delim, *new) || *(new-1) == (Char)'\\')
338 	  break;
339 	new++;
340       }
341     }
342 
343     p = prev;			/* Set to previous word start */
344 
345   }
346   if (p < low)
347     p = low;
348   return (p);
349 }
350 
351 /*
352  * c_to_class() returns the class of the given character.
353  *
354  * This is used to make the c_prev_word() and c_next_word() functions
355  * work like vi's, which classify characters. A word is a sequence of
356  * characters belonging to the same class, classes being defined as
357  * follows:
358  *
359  *	1/ whitespace
360  *	2/ alphanumeric chars, + underscore
361  *	3/ others
362  */
363 static int
364 c_to_class(ch)
365 int  ch;
366 {
367     if (Isspace(ch))
368         return C_CLASS_WHITE;
369 
370     if (Isdigit(ch) || Isalpha(ch) || ch == '_')
371         return C_CLASS_ALNUM;
372 
373     return C_CLASS_OTHER;
374 }
375 
376 static Char *
377 c_prev_word(p, low, n)
378     Char *p, *low;
379     int n;
380 {
381     p--;
382 
383     if (!VImode) {
384 	while (n--) {
385 	    while ((p >= low) && !isword(*p))
386 		p--;
387 	    while ((p >= low) && isword(*p))
388 		p--;
389 	}
390 
391 	/* cp now points to one character before the word */
392 	p++;
393 	if (p < low)
394 	    p = low;
395 	/* cp now points where we want it */
396 	return(p);
397     }
398 
399     while (n--) {
400         int  c_class;
401 
402         if (p < low)
403             break;
404 
405         /* scan until beginning of current word (may be all whitespace!) */
406         c_class = c_to_class(*p);
407         while ((p >= low) && c_class == c_to_class(*p))
408             p--;
409 
410         /* if this was a non_whitespace word, we're ready */
411         if (c_class != C_CLASS_WHITE)
412             continue;
413 
414         /* otherwise, move back to beginning of the word just found */
415         c_class = c_to_class(*p);
416         while ((p >= low) && c_class == c_to_class(*p))
417             p--;
418     }
419 
420     p++;                        /* correct overshoot */
421 
422     return (p);
423 }
424 
425 static Char *
426 c_next_word(p, high, n)
427     Char *p, *high;
428     int n;
429 {
430     if (!VImode) {
431 	while (n--) {
432 	    while ((p < high) && !isword(*p))
433 		p++;
434 	    while ((p < high) && isword(*p))
435 		p++;
436 	}
437 	if (p > high)
438 	    p = high;
439 	/* p now points where we want it */
440 	return(p);
441     }
442 
443     while (n--) {
444         int  c_class;
445 
446         if (p >= high)
447             break;
448 
449         /* scan until end of current word (may be all whitespace!) */
450         c_class = c_to_class(*p);
451         while ((p < high) && c_class == c_to_class(*p))
452             p++;
453 
454         /* if this was all whitespace, we're ready */
455         if (c_class == C_CLASS_WHITE)
456             continue;
457 
458 	/* if we've found white-space at the end of the word, skip it */
459         while ((p < high) && c_to_class(*p) == C_CLASS_WHITE)
460             p++;
461     }
462 
463     p--;                        /* correct overshoot */
464 
465     return (p);
466 }
467 
468 static Char *
469 c_nexword(p, high, n)
470     Char *p, *high;
471     int n;
472 {
473     while (n--) {
474 	while ((p < high) && !Isspace(*p))
475 	    p++;
476 	while ((p < high) && Isspace(*p))
477 	    p++;
478     }
479 
480     if (p > high)
481 	p = high;
482     /* p now points where we want it */
483     return(p);
484 }
485 
486 /*
487  * Expand-History (originally "Magic-Space") code added by
488  * Ray Moody <ray@gibbs.physics.purdue.edu>
489  * this is a neat, but odd, addition.
490  */
491 
492 /*
493  * c_number: Ignore character p points to, return number appearing after that.
494  * A '$' by itself means a big number; "$-" is for negative; '^' means 1.
495  * Return p pointing to last char used.
496  */
497 
498 /*
499  * dval is the number to subtract from for things like $-3
500  */
501 
502 static Char *
503 c_number(p, num, dval)
504     Char *p;
505     int *num;
506     int dval;
507 {
508     int i;
509     int sign = 1;
510 
511     if (*++p == '^') {
512 	*num = 1;
513 	return(p);
514     }
515     if (*p == '$') {
516 	if (*++p != '-') {
517 	    *num = NCARGS;	/* Handle $ */
518 	    return(--p);
519 	}
520 	sign = -1;		/* Handle $- */
521 	++p;
522     }
523     for (i = 0; *p >= '0' && *p <= '9'; i = 10 * i + *p++ - '0')
524 	continue;
525     *num = (sign < 0 ? dval - i : i);
526     return(--p);
527 }
528 
529 /*
530  * excl_expand: There is an excl to be expanded to p -- do the right thing
531  * with it and return a version of p advanced over the expanded stuff.  Also,
532  * update tsh_cur and related things as appropriate...
533  */
534 
535 static Char *
536 c_expand(p)
537     Char *p;
538 {
539     Char *q;
540     struct Hist *h = Histlist.Hnext;
541     struct wordent *l;
542     int     i, from, to, dval;
543     bool    all_dig;
544     bool    been_once = 0;
545     Char   *op = p;
546     Char    buf[INBUFSIZE];
547     Char   *bend = buf;
548     Char   *modbuf, *omodbuf;
549 
550     if (!h)
551 	goto excl_err;
552 excl_sw:
553     switch (*(q = p + 1)) {
554 
555     case '^':
556 	bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 1, 1);
557 	break;
558 
559     case '$':
560 	if ((l = (h->Hlex).prev) != 0)
561 	    bend = expand_lex(buf, INBUFSIZE, l->prev->prev, 0, 0);
562 	break;
563 
564     case '*':
565 	bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 1, NCARGS);
566 	break;
567 
568     default:
569 	if (been_once) {	/* unknown argument */
570 	    /* assume it's a modifier, e.g. !foo:h, and get whole cmd */
571 	    bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 0, NCARGS);
572 	    q -= 2;
573 	    break;
574 	}
575 	been_once = 1;
576 
577 	if (*q == ':')		/* short form: !:arg */
578 	    --q;
579 
580 	if (*q != HIST) {
581 	    /*
582 	     * Search for a space, tab, or colon.  See if we have a number (as
583 	     * in !1234:xyz).  Remember the number.
584 	     */
585 	    for (i = 0, all_dig = 1;
586 		 *q != ' ' && *q != '\t' && *q != ':' && q < Cursor; q++) {
587 		/*
588 		 * PWP: !-4 is a valid history argument too, therefore the test
589 		 * is if not a digit, or not a - as the first character.
590 		 */
591 		if ((*q < '0' || *q > '9') && (*q != '-' || q != p + 1))
592 		    all_dig = 0;
593 		else if (*q == '-')
594 		    all_dig = 2;/* we are sneeky about this */
595 		else
596 		    i = 10 * i + *q - '0';
597 	    }
598 	    --q;
599 
600 	    /*
601 	     * If we have a number, search for event i.  Otherwise, search for
602 	     * a named event (as in !foo).  (In this case, I is the length of
603 	     * the named event).
604 	     */
605 	    if (all_dig) {
606 		if (all_dig == 2)
607 		    i = -i;	/* make it negitive */
608 		if (i < 0)	/* if !-4 (for example) */
609 		    i = eventno + 1 + i;	/* remember: i is < 0 */
610 		for (; h; h = h->Hnext) {
611 		    if (h->Hnum == i)
612 			break;
613 		}
614 	    }
615 	    else {
616 		for (i = (int) (q - p); h; h = h->Hnext) {
617 		    if ((l = &h->Hlex) != 0) {
618 			if (!Strncmp(p + 1, l->next->word, (size_t) i))
619 			    break;
620 		    }
621 		}
622 	    }
623 	}
624 	if (!h)
625 	    goto excl_err;
626 	if (q[1] == ':' || q[1] == '-' || q[1] == '*' ||
627 	    q[1] == '$' || q[1] == '^') {	/* get some args */
628 	    p = q[1] == ':' ? ++q : q;
629 	    /*
630 	     * Go handle !foo:*
631 	     */
632 	    if ((q[1] < '0' || q[1] > '9') &&
633 		q[1] != '-' && q[1] != '$' && q[1] != '^')
634 		goto excl_sw;
635 	    /*
636 	     * Go handle !foo:$
637 	     */
638 	    if (q[1] == '$' && (q[2] != '-' || q[3] < '0' || q[3] > '9'))
639 		goto excl_sw;
640 	    /*
641 	     * Count up the number of words in this event.  Store it in dval.
642 	     * Dval will be fed to number.
643 	     */
644 	    dval = 0;
645 	    if ((l = h->Hlex.prev) != 0) {
646 		for (l = l->prev; l != h->Hlex.next; l = l->prev, dval++)
647 		    continue;
648 	    }
649 	    if (!dval)
650 		goto excl_err;
651 	    if (q[1] == '-')
652 		from = 0;
653 	    else
654 		q = c_number(q, &from, dval);
655 	    if (q[1] == '-') {
656 		++q;
657 		if ((q[1] < '0' || q[1] > '9') && q[1] != '$')
658 		    to = dval - 1;
659 		else
660 		    q = c_number(q, &to, dval);
661 	    }
662 	    else if (q[1] == '*') {
663 		++q;
664 		to = NCARGS;
665 	    }
666 	    else {
667 		to = from;
668 	    }
669 	    if (from < 0 || to < from)
670 		goto excl_err;
671 	    bend = expand_lex(buf, INBUFSIZE, &h->Hlex, from, to);
672 	}
673 	else {			/* get whole cmd */
674 	    bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 0, NCARGS);
675 	}
676 	break;
677     }
678 
679     /*
680      * Apply modifiers, if any.
681      */
682     if (q[1] == ':') {
683 	*bend = '\0';
684 	modbuf = omodbuf = buf;
685 	while (q[1] == ':' && modbuf != NULL) {
686 	    switch (q[2]) {
687 	    case 'r':
688 	    case 'e':
689 	    case 'h':
690 	    case 't':
691 	    case 'q':
692 	    case 'x':
693 	    case 'u':
694 	    case 'l':
695 		if ((modbuf = domod(omodbuf, (int) q[2])) != NULL) {
696 		    if (omodbuf != buf)
697 			xfree((ptr_t) omodbuf);
698 		    omodbuf = modbuf;
699 		}
700 		++q;
701 		break;
702 
703 	    case 'a':
704 	    case 'g':
705 		/* Not implemented; this needs to be done before expanding
706 		 * lex. We don't have the words available to us anymore.
707 		 */
708 		++q;
709 		break;
710 
711 	    case 'p':
712 		/* Ok */
713 		++q;
714 		break;
715 
716 	    case '\0':
717 		break;
718 
719 	    default:
720 		++q;
721 		break;
722 	    }
723 	    if (q[1])
724 		++q;
725 	}
726 	if (omodbuf != buf) {
727 	    (void) Strcpy(buf, omodbuf);
728 	    xfree((ptr_t) omodbuf);
729 	    bend = Strend(buf);
730 	}
731     }
732 
733     /*
734      * Now replace the text from op to q inclusive with the text from buf to
735      * bend.
736      */
737     q++;
738 
739     /*
740      * Now replace text non-inclusively like a real CS major!
741      */
742     if (LastChar + (bend - buf) - (q - op) >= InputLim)
743 	goto excl_err;
744     (void) memmove((ptr_t) (q + (bend - buf) - (q - op)), (ptr_t) q,
745 		   (size_t) ((LastChar - q) * sizeof(Char)));
746     LastChar += (bend - buf) - (q - op);
747     Cursor += (bend - buf) - (q - op);
748     (void) memmove((ptr_t) op, (ptr_t) buf,
749 		   (size_t) ((bend - buf) * sizeof(Char)));
750     *LastChar = '\0';
751     return(op + (bend - buf));
752 excl_err:
753     SoundBeep();
754     return(op + 1);
755 }
756 
757 /*
758  * c_excl: An excl has been found at point p -- back up and find some white
759  * space (or the beginning of the buffer) and properly expand all the excl's
760  * from there up to the current cursor position. We also avoid (trying to)
761  * expanding '>!'
762  */
763 
764 static void
765 c_excl(p)
766     Char *p;
767 {
768     int i;
769     Char *q;
770 
771     /*
772      * if />[SPC TAB]*![SPC TAB]/, back up p to just after the >. otherwise,
773      * back p up to just before the current word.
774      */
775     if ((p[1] == ' ' || p[1] == '\t') &&
776 	(p[-1] == ' ' || p[-1] == '\t' || p[-1] == '>')) {
777 	for (q = p - 1; q > InputBuf && (*q == ' ' || *q == '\t'); --q)
778 	    continue;
779 	if (*q == '>')
780 	    ++p;
781     }
782     else {
783 	while (*p != ' ' && *p != '\t' && p > InputBuf)
784 	    --p;
785     }
786 
787     /*
788      * Forever: Look for history char.  (Stop looking when we find the cursor.)
789      * Count backslashes.  Of odd, skip history char. Return if all done.
790      * Expand if even number of backslashes.
791      */
792     for (;;) {
793 	while (*p != HIST && p < Cursor)
794 	    ++p;
795 	for (i = 1; (p - i) >= InputBuf && p[-i] == '\\'; i++)
796 	    continue;
797 	if (i % 2 == 0)
798 	    ++p;
799 	if (p >= Cursor)
800 	    return;
801 	if (i % 2 == 1)
802 	    p = c_expand(p);
803     }
804 }
805 
806 
807 static void
808 c_substitute()
809 {
810     Char *p;
811 
812     /*
813      * Start p out one character before the cursor.  Move it backwards looking
814      * for white space, the beginning of the line, or a history character.
815      */
816     for (p = Cursor - 1;
817 	 p > InputBuf && *p != ' ' && *p != '\t' && *p != HIST; --p)
818 	continue;
819 
820     /*
821      * If we found a history character, go expand it.
822      */
823     if (*p == HIST)
824 	c_excl(p);
825     Refresh();
826 }
827 
828 static void
829 c_delfini()		/* Finish up delete action */
830 {
831     int Size;
832 
833     if (ActionFlag & TCSHOP_INSERT)
834 	c_alternativ_key_map(0);
835 
836     ActionFlag = TCSHOP_NOP;
837 
838     if (ActionPos == 0)
839 	return;
840 
841     UndoAction = TCSHOP_INSERT;
842 
843     if (Cursor > ActionPos) {
844 	Size = (int) (Cursor-ActionPos);
845 	c_delbefore(Size);
846 	Cursor = ActionPos;
847 #if defined(DSPMBYTE)
848 	if (_enable_mbdisp && extdel) {
849 	    Cursor--;
850 	    e_redisp(1);
851 	}
852 #endif
853 	RefCursor();
854     }
855     else if (Cursor < ActionPos) {
856 	Size = (int)(ActionPos-Cursor);
857 	c_delafter(Size);
858     }
859     else  {
860 	Size = 1;
861 	c_delafter(Size);
862     }
863     UndoPtr = Cursor;
864     UndoSize = Size;
865 }
866 
867 static Char *
868 c_endword(p, high, n, delim)
869     Char *p, *high, *delim;
870     int n;
871 {
872     int inquote = 0;
873     p++;
874 
875     while (n--) {
876         while (p < high) {	/* Skip non-word chars */
877 	  if (!Strchr(delim, *p) || *(p-1) == (Char)'\\')
878 	    break;
879 	  p++;
880         }
881 	while (p < high) {	/* Skip string */
882 	  if ((*p == (Char)'\'' || *p == (Char)'"')) { /* Quotation marks? */
883 	    if (inquote || *(p-1) != (Char)'\\') { /* Should it be honored? */
884 	      if (inquote == 0) inquote = *p;
885 	      else if (inquote == *p) inquote = 0;
886 	    }
887 	  }
888 	  /* Break if unquoted non-word char */
889 	  if (!inquote && Strchr(delim, *p) && *(p-1) != (Char)'\\')
890 	    break;
891 	  p++;
892 	}
893     }
894 
895     p--;
896     return(p);
897 }
898 
899 
900 static Char *
901 c_eword(p, high, n)
902     Char *p, *high;
903     int n;
904 {
905     p++;
906 
907     while (n--) {
908 	while ((p < high) && Isspace(*p))
909 	    p++;
910 
911 	if (Isalnum(*p))
912 	    while ((p < high) && Isalnum(*p))
913 		p++;
914 	else
915 	    while ((p < high) && !(Isspace(*p) || Isalnum(*p)))
916 		p++;
917     }
918 
919     p--;
920     return(p);
921 }
922 
923 /* Set the max length of the kill ring */
924 void
925 SetKillRing(max)
926     int max;
927 {
928     CStr *new;
929     int count, i, j;
930 
931     if (max < 1)
932 	max = 1;		/* no ring, but always one buffer */
933     if (max == KillRingMax)
934 	return;
935     new = (CStr *)xcalloc((size_t) max, sizeof(CStr));
936     if (KillRing != NULL) {
937 	if (KillRingLen != 0) {
938 	    if (max >= KillRingLen) {
939 		count = KillRingLen;
940 		j = KillPos;
941 	    } else {
942 		count = max;
943 		j = (KillPos - count + KillRingLen) % KillRingLen;
944 	    }
945 	    for (i = 0; i < KillRingLen; i++) {
946 		if (i < count)	/* copy latest */
947 		    new[i] = KillRing[j];
948 		else		/* free the others */
949 		    xfree(KillRing[j].buf);
950 		j = (j + 1) % KillRingLen;
951 	    }
952 	    KillRingLen = count;
953 	    KillPos = count % max;
954 	    YankPos = count - 1;
955 	}
956 	xfree(KillRing);
957     }
958     KillRing = new;
959     KillRingMax = max;
960 }
961 
962 /* Push string from start upto (but not including) end onto kill ring */
963 static void
964 c_push_kill(start, end)
965     Char *start, *end;
966 {
967     CStr save, *pos;
968     Char *dp, *cp, *kp;
969     int len = end - start, i, j, k;
970 
971     /* Check for duplicates? */
972     if (KillRingLen > 0 && (dp = varval(STRkilldup)) != STRNULL) {
973 	YankPos = (KillPos - 1 + KillRingLen) % KillRingLen;
974 	if (eq(dp, STRerase)) {	/* erase earlier one (actually move up) */
975 	    j = YankPos;
976 	    for (i = 0; i < KillRingLen; i++) {
977 		if (Strncmp(KillRing[j].buf, start, (size_t) len) == 0 &&
978 		    KillRing[j].buf[len] == '\0') {
979 		    save = KillRing[j];
980 		    for ( ; i > 0; i--) {
981 			k = j;
982 			j = (j + 1) % KillRingLen;
983 			KillRing[k] = KillRing[j];
984 		    }
985 		    KillRing[j] = save;
986 		    return;
987 		}
988 		j = (j - 1 + KillRingLen) % KillRingLen;
989 	    }
990 	} else if (eq(dp, STRall)) { /* skip if any earlier */
991 	    for (i = 0; i < KillRingLen; i++)
992 		if (Strncmp(KillRing[i].buf, start, (size_t) len) == 0 &&
993 		    KillRing[i].buf[len] == '\0')
994 		    return;
995 	} else if (eq(dp, STRprev)) { /* skip if immediately previous */
996 	    j = YankPos;
997 	    if (Strncmp(KillRing[j].buf, start, (size_t) len) == 0 &&
998 		KillRing[j].buf[len] == '\0')
999 		return;
1000 	}
1001     }
1002 
1003     /* No duplicate, go ahead and push */
1004     len++;			/* need space for '\0' */
1005     YankPos = KillPos;
1006     if (KillRingLen < KillRingMax)
1007 	KillRingLen++;
1008     pos = &KillRing[KillPos];
1009     KillPos = (KillPos + 1) % KillRingMax;
1010     if (pos->len < len) {
1011 	if (pos->buf == NULL)
1012 	    pos->buf = (Char *) xmalloc(len * sizeof(Char));
1013 	else
1014 	    pos->buf = (Char *) xrealloc((ptr_t) pos->buf, len * sizeof(Char));
1015 	pos->len = len;
1016     }
1017     cp = start;
1018     kp = pos->buf;
1019     while (cp < end)
1020 	*kp++ = *cp++;
1021     *kp = '\0';
1022 }
1023 
1024 static CCRETVAL
1025 c_get_histline()
1026 {
1027     struct Hist *hp;
1028     int     h;
1029 
1030     if (Hist_num == 0) {	/* if really the current line */
1031 	copyn(InputBuf, HistBuf, INBUFSIZE);
1032 	LastChar = InputBuf + (LastHist - HistBuf);
1033 
1034 #ifdef KSHVI
1035     if (VImode)
1036 	Cursor = InputBuf;
1037     else
1038 #endif /* KSHVI */
1039 	Cursor = LastChar;
1040 
1041 	return(CC_REFRESH);
1042     }
1043 
1044     hp = Histlist.Hnext;
1045     if (hp == NULL)
1046 	return(CC_ERROR);
1047 
1048     for (h = 1; h < Hist_num; h++) {
1049 	if ((hp->Hnext) == NULL) {
1050 	    Hist_num = h;
1051 	    return(CC_ERROR);
1052 	}
1053 	hp = hp->Hnext;
1054     }
1055 
1056     if (HistLit && hp->histline) {
1057 	copyn(InputBuf, hp->histline, INBUFSIZE);
1058 	CurrentHistLit = 1;
1059     }
1060     else {
1061 	(void) sprlex(InputBuf, sizeof(InputBuf) / sizeof(Char), &hp->Hlex);
1062 	CurrentHistLit = 0;
1063     }
1064     LastChar = InputBuf + Strlen(InputBuf);
1065 
1066     if (LastChar > InputBuf) {
1067 	if (LastChar[-1] == '\n')
1068 	    LastChar--;
1069 #if 0
1070 	if (LastChar[-1] == ' ')
1071 	    LastChar--;
1072 #endif
1073 	if (LastChar < InputBuf)
1074 	    LastChar = InputBuf;
1075     }
1076 
1077 #ifdef KSHVI
1078     if (VImode)
1079 	Cursor = InputBuf;
1080     else
1081 #endif /* KSHVI */
1082 	Cursor = LastChar;
1083 
1084     return(CC_REFRESH);
1085 }
1086 
1087 static CCRETVAL
1088 c_search_line(pattern, dir)
1089 Char *pattern;
1090 int dir;
1091 {
1092     Char *cp;
1093     int len;
1094 
1095     len = (int) Strlen(pattern);
1096 
1097     if (dir == F_UP_SEARCH_HIST) {
1098 	for (cp = Cursor; cp >= InputBuf; cp--)
1099 	    if (Strncmp(cp, pattern, (size_t) len) == 0 ||
1100 		Gmatch(cp, pattern)) {
1101 		Cursor = cp;
1102 		return(CC_NORM);
1103 	    }
1104 	return(CC_ERROR);
1105     } else {
1106 	for (cp = Cursor; *cp != '\0' && cp < InputLim; cp++)
1107 	    if (Strncmp(cp, pattern, (size_t) len) == 0 ||
1108 		Gmatch(cp, pattern)) {
1109 		Cursor = cp;
1110 		return(CC_NORM);
1111 	    }
1112 	return(CC_ERROR);
1113     }
1114 }
1115 
1116 static CCRETVAL
1117 e_inc_search(dir)
1118     int dir;
1119 {
1120     static Char STRfwd[] = { 'f', 'w', 'd', '\0' },
1121 		STRbck[] = { 'b', 'c', 'k', '\0' };
1122     static Char pchar = ':';	/* ':' = normal, '?' = failed */
1123     static Char endcmd[2];
1124     Char ch, *cp,
1125 	*oldCursor = Cursor,
1126 	oldpchar = pchar;
1127     CCRETVAL ret = CC_NORM;
1128     int oldHist_num = Hist_num,
1129 	oldpatlen = patlen,
1130 	newdir = dir,
1131         done, redo;
1132 
1133     if (LastChar + sizeof(STRfwd)/sizeof(Char) + 2 + patlen >= InputLim)
1134 	return(CC_ERROR);
1135 
1136     for (;;) {
1137 
1138 	if (patlen == 0) {	/* first round */
1139 	    pchar = ':';
1140 	    patbuf[patlen++] = '*';
1141 	}
1142 	done = redo = 0;
1143 	*LastChar++ = '\n';
1144 	for (cp = newdir == F_UP_SEARCH_HIST ? STRbck : STRfwd;
1145 	     *cp; *LastChar++ = *cp++)
1146 	    continue;
1147 	*LastChar++ = pchar;
1148 	for (cp = &patbuf[1]; cp < &patbuf[patlen]; *LastChar++ = *cp++)
1149 	    continue;
1150 	*LastChar = '\0';
1151 	Refresh();
1152 
1153 	if (GetNextChar(&ch) != 1)
1154 	    return(e_send_eof(0));
1155 
1156 	switch (CurrentKeyMap[(unsigned char) ch]) {
1157 	case F_INSERT:
1158 	case F_DIGIT:
1159 	case F_MAGIC_SPACE:
1160 	    if (patlen > INBUFSIZE - 3)
1161 		SoundBeep();
1162 	    else {
1163 		patbuf[patlen++] = ch;
1164 		*LastChar++ = ch;
1165 		*LastChar = '\0';
1166 		Refresh();
1167 	    }
1168 	    break;
1169 
1170 	case F_INC_FWD:
1171 	    newdir = F_DOWN_SEARCH_HIST;
1172 	    redo++;
1173 	    break;
1174 
1175 	case F_INC_BACK:
1176 	    newdir = F_UP_SEARCH_HIST;
1177 	    redo++;
1178 	    break;
1179 
1180 	case F_DELPREV:
1181 	    if (patlen > 1)
1182 		done++;
1183 	    else
1184 		SoundBeep();
1185 	    break;
1186 
1187 	default:
1188 	    switch (ch) {
1189 	    case 0007:		/* ^G: Abort */
1190 		ret = CC_ERROR;
1191 		done++;
1192 		break;
1193 
1194 	    case 0027:		/* ^W: Append word */
1195 		/* No can do if globbing characters in pattern */
1196 		for (cp = &patbuf[1]; ; cp++)
1197 		    if (cp >= &patbuf[patlen]) {
1198 			Cursor += patlen - 1;
1199 			cp = c_next_word(Cursor, LastChar, 1);
1200 			while (Cursor < cp && *Cursor != '\n') {
1201 			    if (patlen > INBUFSIZE - 3) {
1202 				SoundBeep();
1203 				break;
1204 			    }
1205 			    patbuf[patlen++] = *Cursor;
1206 			    *LastChar++ = *Cursor++;
1207 			}
1208 			Cursor = oldCursor;
1209 			*LastChar = '\0';
1210 			Refresh();
1211 			break;
1212 		    } else if (isglob(*cp)) {
1213 			SoundBeep();
1214 			break;
1215 		    }
1216 		break;
1217 
1218 	    default:		/* Terminate and execute cmd */
1219 		endcmd[0] = ch;
1220 		PushMacro(endcmd);
1221 		/*FALLTHROUGH*/
1222 
1223 	    case 0033:		/* ESC: Terminate */
1224 		ret = CC_REFRESH;
1225 		done++;
1226 		break;
1227 	    }
1228 	    break;
1229 	}
1230 
1231 	while (LastChar > InputBuf && *LastChar != '\n')
1232 	    *LastChar-- = '\0';
1233 	*LastChar = '\0';
1234 
1235 	if (!done) {
1236 
1237 	    /* Can't search if unmatched '[' */
1238 	    for (cp = &patbuf[patlen - 1], ch = ']'; cp > patbuf; cp--)
1239 		if (*cp == '[' || *cp == ']') {
1240 		    ch = *cp;
1241 		    break;
1242 		}
1243 
1244 	    if (patlen > 1 && ch != '[') {
1245 		if (redo && newdir == dir) {
1246 		    if (pchar == '?') {	/* wrap around */
1247 			Hist_num = newdir == F_UP_SEARCH_HIST ? 0 : 0x7fffffff;
1248 			if (c_get_histline() == CC_ERROR)
1249 			    /* Hist_num was fixed by first call */
1250 			    (void) c_get_histline();
1251 			Cursor = newdir == F_UP_SEARCH_HIST ?
1252 			    LastChar : InputBuf;
1253 		    } else
1254 			Cursor += newdir == F_UP_SEARCH_HIST ? -1 : 1;
1255 		}
1256 		patbuf[patlen++] = '*';
1257 		patbuf[patlen] = '\0';
1258 		if (Cursor < InputBuf || Cursor > LastChar ||
1259 		    (ret = c_search_line(&patbuf[1], newdir)) == CC_ERROR) {
1260 		    LastCmd = (KEYCMD) newdir; /* avoid c_hsetpat */
1261 		    ret = newdir == F_UP_SEARCH_HIST ?
1262 			e_up_search_hist(0) : e_down_search_hist(0);
1263 		    if (ret != CC_ERROR) {
1264 			Cursor = newdir == F_UP_SEARCH_HIST ?
1265 			    LastChar : InputBuf;
1266 			(void) c_search_line(&patbuf[1], newdir);
1267 		    }
1268 		}
1269 		patbuf[--patlen] = '\0';
1270 		if (ret == CC_ERROR) {
1271 		    SoundBeep();
1272 		    if (Hist_num != oldHist_num) {
1273 			Hist_num = oldHist_num;
1274 			if (c_get_histline() == CC_ERROR)
1275 			    return(CC_ERROR);
1276 		    }
1277 		    Cursor = oldCursor;
1278 		    pchar = '?';
1279 		} else {
1280 		    pchar = ':';
1281 		}
1282 	    }
1283 
1284 	    ret = e_inc_search(newdir);
1285 
1286 	    if (ret == CC_ERROR && pchar == '?' && oldpchar == ':') {
1287 		/* break abort of failed search at last non-failed */
1288 		ret = CC_NORM;
1289 	    }
1290 
1291 	}
1292 
1293 	if (ret == CC_NORM || (ret == CC_ERROR && oldpatlen == 0)) {
1294 	    /* restore on normal return or error exit */
1295 	    pchar = oldpchar;
1296 	    patlen = oldpatlen;
1297 	    if (Hist_num != oldHist_num) {
1298 		Hist_num = oldHist_num;
1299 		if (c_get_histline() == CC_ERROR)
1300 		    return(CC_ERROR);
1301 	    }
1302 	    Cursor = oldCursor;
1303 	    if (ret == CC_ERROR)
1304 		Refresh();
1305 	}
1306 	if (done || ret != CC_NORM)
1307 	    return(ret);
1308 
1309     }
1310 
1311 }
1312 
1313 static CCRETVAL
1314 v_search(dir)
1315     int dir;
1316 {
1317     Char ch;
1318     Char tmpbuf[INBUFSIZE];
1319     Char oldbuf[INBUFSIZE];
1320     Char *oldlc, *oldc;
1321     int tmplen;
1322 
1323     copyn(oldbuf, InputBuf, INBUFSIZE);
1324     oldlc = LastChar;
1325     oldc = Cursor;
1326     tmplen = 0;
1327     tmpbuf[tmplen++] = '*';
1328 
1329     InputBuf[0] = '\0';
1330     LastChar = InputBuf;
1331     Cursor = InputBuf;
1332     searchdir = dir;
1333 
1334     c_insert(2);	/* prompt + '\n' */
1335     *Cursor++ = '\n';
1336     *Cursor++ = dir == F_UP_SEARCH_HIST ? '?' : '/';
1337     Refresh();
1338     for (ch = 0;ch == 0;) {
1339 	if (GetNextChar(&ch) != 1)
1340 	    return(e_send_eof(0));
1341 	switch (ASC(ch)) {
1342 	case 0010:	/* Delete and backspace */
1343 	case 0177:
1344 	    if (tmplen > 1) {
1345 		*Cursor-- = '\0';
1346 		LastChar = Cursor;
1347 		tmpbuf[tmplen--] = '\0';
1348 	    }
1349 	    else {
1350 		copyn(InputBuf, oldbuf, INBUFSIZE);
1351 		LastChar = oldlc;
1352 		Cursor = oldc;
1353 		return(CC_REFRESH);
1354 	    }
1355 	    Refresh();
1356 	    ch = 0;
1357 	    break;
1358 
1359 	case 0033:	/* ESC */
1360 #ifdef IS_ASCII
1361 	case '\r':	/* Newline */
1362 	case '\n':
1363 #else
1364 	case '\012':    /* ASCII Line feed */
1365 	case '\015':    /* ASCII (or EBCDIC) Return */
1366 #endif
1367 	    break;
1368 
1369 	default:
1370 	    if (tmplen >= INBUFSIZE)
1371 		SoundBeep();
1372 	    else {
1373 		tmpbuf[tmplen++] = ch;
1374 		*Cursor++ = ch;
1375 		LastChar = Cursor;
1376 	    }
1377 	    Refresh();
1378 	    ch = 0;
1379 	    break;
1380 	}
1381     }
1382 
1383     if (tmplen == 1) {
1384 	/*
1385 	 * Use the old pattern, but wild-card it.
1386 	 */
1387 	if (patlen == 0) {
1388 	    InputBuf[0] = '\0';
1389 	    LastChar = InputBuf;
1390 	    Cursor = InputBuf;
1391 	    Refresh();
1392 	    return(CC_ERROR);
1393 	}
1394 	if (patbuf[0] != '*') {
1395 	    (void) Strcpy(tmpbuf, patbuf);
1396 	    patbuf[0] = '*';
1397 	    (void) Strcpy(&patbuf[1], tmpbuf);
1398 	    patlen++;
1399 	    patbuf[patlen++] = '*';
1400 	    patbuf[patlen] = '\0';
1401 	}
1402     }
1403     else {
1404 	tmpbuf[tmplen++] = '*';
1405 	tmpbuf[tmplen] = '\0';
1406 	(void) Strcpy(patbuf, tmpbuf);
1407 	patlen = tmplen;
1408     }
1409     LastCmd = (KEYCMD) dir; /* avoid c_hsetpat */
1410     Cursor = LastChar = InputBuf;
1411     if ((dir == F_UP_SEARCH_HIST ? e_up_search_hist(0) :
1412 				   e_down_search_hist(0)) == CC_ERROR) {
1413 	Refresh();
1414 	return(CC_ERROR);
1415     }
1416     else {
1417 	if (ch == 0033) {
1418 	    Refresh();
1419 	    *LastChar++ = '\n';
1420 	    *LastChar = '\0';
1421 	    PastBottom();
1422 	    return(CC_NEWLINE);
1423 	}
1424 	else
1425 	    return(CC_REFRESH);
1426     }
1427 }
1428 
1429 /*
1430  * semi-PUBLIC routines.  Any routine that is of type CCRETVAL is an
1431  * entry point, called from the CcKeyMap indirected into the
1432  * CcFuncTbl array.
1433  */
1434 
1435 /*ARGSUSED*/
1436 CCRETVAL
1437 v_cmd_mode(c)
1438     int c;
1439 {
1440     USE(c);
1441     InsertPos = 0;
1442     ActionFlag = TCSHOP_NOP;	/* [Esc] cancels pending action */
1443     ActionPos = 0;
1444     DoingArg = 0;
1445     if (UndoPtr > Cursor)
1446 	UndoSize = (int)(UndoPtr - Cursor);
1447     else
1448 	UndoSize = (int)(Cursor - UndoPtr);
1449 
1450     inputmode = MODE_INSERT;
1451     c_alternativ_key_map(1);
1452 #ifdef notdef
1453     /*
1454      * We don't want to move the cursor, because all the editing
1455      * commands don't include the character under the cursor.
1456      */
1457     if (Cursor > InputBuf)
1458 	Cursor--;
1459 #endif
1460     RefCursor();
1461     return(CC_NORM);
1462 }
1463 
1464 /*ARGSUSED*/
1465 CCRETVAL
1466 e_unassigned(c)
1467     int c;
1468 {				/* bound to keys that arn't really assigned */
1469     USE(c);
1470     SoundBeep();
1471     flush();
1472     return(CC_NORM);
1473 }
1474 
1475 CCRETVAL
1476 e_insert(c)
1477     int c;
1478 {
1479     int i;
1480 #if defined(DSPMBYTE)
1481     CCRETVAL ret;
1482     static Char savec;
1483     static int exterr = 0;
1484 #endif
1485 #ifndef SHORT_STRINGS
1486     c &= ASCII;			/* no meta chars ever */
1487 #endif
1488 #if defined(DSPMBYTE)
1489     ret = (CCRETVAL) CC_NORM;
1490 #endif
1491 
1492     if (!c)
1493 	return(CC_ERROR);	/* no NULs in the input ever!! */
1494 
1495     if (LastChar + Argument >= InputLim)
1496 	return(CC_ERROR);	/* end of buffer space */
1497 
1498     if (Argument == 1) {  	/* How was this optimized ???? */
1499 
1500 #if defined(DSPMBYTE)
1501 	if(_enable_mbdisp && extins && exterr && Ismbyte2(c)) {
1502 	    extins = 0;
1503 	    exterr = 0;
1504 	    return(CC_ERROR);
1505 	}
1506 #endif
1507 	if (inputmode != MODE_INSERT) {
1508 	    UndoBuf[UndoSize++] = *Cursor;
1509 	    UndoBuf[UndoSize] = '\0';
1510 	    c_delafter(1);   /* Do NOT use the saving ONE */
1511     	}
1512 
1513         c_insert(1);
1514 
1515 #if defined(DSPMBYTE)
1516 	/* 1st. byte is store to special buffer, and replace space */
1517 	if(_enable_mbdisp && extins == 0 && Ismbyte1(c)) {
1518 	    extins++;
1519 	    savec = (Char) c;
1520 	    *Cursor++ = (Char) ' ';
1521 	}
1522 	else if (_enable_mbdisp && extins && Ismbyte2(c)) {
1523 	    *(Cursor-1) = savec;
1524 	    *Cursor++ = (Char) c;
1525 	    extins = 0;
1526 	    e_redisp(1);
1527 	    Refresh();
1528 	    ret = CC_REFRESH;
1529 	}
1530 	else
1531 	    *Cursor++ = (Char) c;
1532 	DoingArg = 0;		/* just in case */
1533 	if (ret != CC_REFRESH)
1534 	    RefPlusOne();	/* fast refresh for one char. */
1535 #else
1536 	*Cursor++ = (Char) c;
1537 	DoingArg = 0;		/* just in case */
1538 	RefPlusOne();		/* fast refresh for one char. */
1539 #endif
1540     }
1541     else {
1542 #if defined(DSPMBYTE)
1543 	/* Cannot use ESC-(number) for multi-byte */
1544 	if (_enable_mbdisp && extins == 0 && Ismbyte1(c)) {
1545 	    extins++;
1546 	    exterr++;
1547 	    return(CC_ERROR);
1548 	}
1549 	else if (_enable_mbdisp && extins && exterr && Ismbyte2(c))
1550 	{
1551 	    extins = 0;
1552 	    exterr = 0;
1553 	    return(CC_ERROR);
1554 	}
1555 #endif
1556 	if (inputmode != MODE_INSERT) {
1557 
1558 	    for(i=0;i<Argument;i++)
1559 		UndoBuf[UndoSize++] = *(Cursor+i);
1560 
1561 	    UndoBuf[UndoSize] = '\0';
1562 	    c_delafter(Argument);   /* Do NOT use the saving ONE */
1563     	}
1564 
1565         c_insert(Argument);
1566 
1567 	while (Argument--)
1568 	    *Cursor++ = (Char) c;
1569 	Refresh();
1570     }
1571 
1572     if (inputmode == MODE_REPLACE_1)
1573 	(void) v_cmd_mode(0);
1574 
1575 #if defined(DSPMBYTE)
1576     return(ret);
1577 #else
1578     return(CC_NORM);
1579 #endif
1580 }
1581 
1582 int
1583 InsertStr(s)			/* insert ASCIZ s at cursor (for complete) */
1584     Char   *s;
1585 {
1586     int len;
1587 
1588     if ((len = (int) Strlen(s)) <= 0)
1589 	return -1;
1590     if (LastChar + len >= InputLim)
1591 	return -1;		/* end of buffer space */
1592 
1593     c_insert(len);
1594     while (len--)
1595 	*Cursor++ = *s++;
1596     return 0;
1597 }
1598 
1599 void
1600 DeleteBack(n)			/* delete the n characters before . */
1601     int     n;
1602 {
1603     if (n <= 0)
1604 	return;
1605     if (Cursor >= &InputBuf[n]) {
1606 	c_delbefore(n);		/* delete before dot */
1607 	if (n > Cursor - InputBuf)
1608 	    Cursor = InputBuf;	/* bounds check */
1609 	else
1610 	    Cursor -= n;
1611 #if defined(DSPMBYTE)
1612 	if(_enable_mbdisp && extdel && Cursor > InputBuf) {
1613 	    Cursor--;
1614 	    e_redisp(1);
1615 	}
1616 #endif
1617     }
1618 }
1619 
1620 CCRETVAL
1621 e_digit(c)			/* gray magic here */
1622     int c;
1623 {
1624     if (!Isdigit(c))
1625 	return(CC_ERROR);	/* no NULs in the input ever!! */
1626 
1627     if (DoingArg) {		/* if doing an arg, add this in... */
1628 	if (LastCmd == F_ARGFOUR)	/* if last command was ^U */
1629 	    Argument = c - '0';
1630 	else {
1631 	    if (Argument > 1000000)
1632 		return CC_ERROR;
1633 	    Argument = (Argument * 10) + (c - '0');
1634 	}
1635 	return(CC_ARGHACK);
1636     }
1637     else {
1638 	if (LastChar + 1 >= InputLim)
1639 	    return CC_ERROR;	/* end of buffer space */
1640 
1641 	if (inputmode != MODE_INSERT) {
1642 	    UndoBuf[UndoSize++] = *Cursor;
1643 	    UndoBuf[UndoSize] = '\0';
1644 	    c_delafter(1);   /* Do NOT use the saving ONE */
1645     	}
1646 	c_insert(1);
1647 	*Cursor++ = (Char) c;
1648 	DoingArg = 0;		/* just in case */
1649 	RefPlusOne();		/* fast refresh for one char. */
1650     }
1651     return(CC_NORM);
1652 }
1653 
1654 CCRETVAL
1655 e_argdigit(c)			/* for ESC-n */
1656     int c;
1657 {
1658     c &= ASCII;
1659 
1660     if (!Isdigit(c))
1661 	return(CC_ERROR);	/* no NULs in the input ever!! */
1662 
1663     if (DoingArg) {		/* if doing an arg, add this in... */
1664 	if (Argument > 1000000)
1665 	    return CC_ERROR;
1666 	Argument = (Argument * 10) + (c - '0');
1667     }
1668     else {			/* else starting an argument */
1669 	Argument = c - '0';
1670 	DoingArg = 1;
1671     }
1672     return(CC_ARGHACK);
1673 }
1674 
1675 CCRETVAL
1676 v_zero(c)			/* command mode 0 for vi */
1677     int c;
1678 {
1679     if (DoingArg) {		/* if doing an arg, add this in... */
1680 	if (Argument > 1000000)
1681 	    return CC_ERROR;
1682 	Argument = (Argument * 10) + (c - '0');
1683 	return(CC_ARGHACK);
1684     }
1685     else {			/* else starting an argument */
1686 	Cursor = InputBuf;
1687 	if (ActionFlag & TCSHOP_DELETE) {
1688 	   c_delfini();
1689 	   return(CC_REFRESH);
1690         }
1691 	RefCursor();		/* move the cursor */
1692 	return(CC_NORM);
1693     }
1694 }
1695 
1696 /*ARGSUSED*/
1697 CCRETVAL
1698 e_newline(c)
1699     int c;
1700 {				/* always ignore argument */
1701     USE(c);
1702   /*  PastBottom();  NOW done in ed.inputl.c */
1703     *LastChar++ = '\n';		/* for the benefit of CSH */
1704     *LastChar = '\0';		/* just in case */
1705     if (VImode)
1706 	InsertPos = InputBuf;	/* Reset editing position */
1707     return(CC_NEWLINE);
1708 }
1709 
1710 /*ARGSUSED*/
1711 CCRETVAL
1712 e_send_eof(c)
1713     int c;
1714 {				/* for when ^D is ONLY send-eof */
1715     USE(c);
1716     PastBottom();
1717     *LastChar = '\0';		/* just in case */
1718     return(CC_EOF);
1719 }
1720 
1721 /*ARGSUSED*/
1722 CCRETVAL
1723 e_complete(c)
1724     int c;
1725 {
1726     USE(c);
1727     *LastChar = '\0';		/* just in case */
1728     return(CC_COMPLETE);
1729 }
1730 
1731 /*ARGSUSED*/
1732 CCRETVAL
1733 e_complete_back(c)
1734     int c;
1735 {
1736     USE(c);
1737     *LastChar = '\0';		/* just in case */
1738     return(CC_COMPLETE_BACK);
1739 }
1740 
1741 /*ARGSUSED*/
1742 CCRETVAL
1743 e_complete_fwd(c)
1744     int c;
1745 {
1746     USE(c);
1747     *LastChar = '\0';		/* just in case */
1748     return(CC_COMPLETE_FWD);
1749 }
1750 
1751 /*ARGSUSED*/
1752 CCRETVAL
1753 e_complete_all(c)
1754     int c;
1755 {
1756     USE(c);
1757     *LastChar = '\0';		/* just in case */
1758     return(CC_COMPLETE_ALL);
1759 }
1760 
1761 /*ARGSUSED*/
1762 CCRETVAL
1763 v_cm_complete(c)
1764     int c;
1765 {
1766     USE(c);
1767     if (Cursor < LastChar)
1768 	Cursor++;
1769     *LastChar = '\0';		/* just in case */
1770     return(CC_COMPLETE);
1771 }
1772 
1773 /*ARGSUSED*/
1774 CCRETVAL
1775 e_toggle_hist(c)
1776     int c;
1777 {
1778     struct Hist *hp;
1779     int     h;
1780 
1781     USE(c);
1782     *LastChar = '\0';		/* just in case */
1783 
1784     if (Hist_num <= 0) {
1785 	return CC_ERROR;
1786     }
1787 
1788     hp = Histlist.Hnext;
1789     if (hp == NULL) {	/* this is only if no history */
1790 	return(CC_ERROR);
1791     }
1792 
1793     for (h = 1; h < Hist_num; h++)
1794 	hp = hp->Hnext;
1795 
1796     if (!CurrentHistLit) {
1797 	if (hp->histline) {
1798 	    copyn(InputBuf, hp->histline, INBUFSIZE);
1799 	    CurrentHistLit = 1;
1800 	}
1801 	else {
1802 	    return CC_ERROR;
1803 	}
1804     }
1805     else {
1806 	(void) sprlex(InputBuf, sizeof(InputBuf) / sizeof(Char), &hp->Hlex);
1807 	CurrentHistLit = 0;
1808     }
1809 
1810     LastChar = InputBuf + Strlen(InputBuf);
1811     if (LastChar > InputBuf) {
1812 	if (LastChar[-1] == '\n')
1813 	    LastChar--;
1814 	if (LastChar[-1] == ' ')
1815 	    LastChar--;
1816 	if (LastChar < InputBuf)
1817 	    LastChar = InputBuf;
1818     }
1819 
1820 #ifdef KSHVI
1821     if (VImode)
1822 	Cursor = InputBuf;
1823     else
1824 #endif /* KSHVI */
1825 	Cursor = LastChar;
1826 
1827     return(CC_REFRESH);
1828 }
1829 
1830 /*ARGSUSED*/
1831 CCRETVAL
1832 e_up_hist(c)
1833     int c;
1834 {
1835     Char    beep = 0;
1836 
1837     USE(c);
1838     UndoAction = TCSHOP_NOP;
1839     *LastChar = '\0';		/* just in case */
1840 
1841     if (Hist_num == 0) {	/* save the current buffer away */
1842 	copyn(HistBuf, InputBuf, INBUFSIZE);
1843 	LastHist = HistBuf + (LastChar - InputBuf);
1844     }
1845 
1846     Hist_num += Argument;
1847 
1848     if (c_get_histline() == CC_ERROR) {
1849 	beep = 1;
1850 	(void) c_get_histline(); /* Hist_num was fixed by first call */
1851     }
1852 
1853     Refresh();
1854     if (beep)
1855 	return(CC_ERROR);
1856     else
1857 	return(CC_NORM);	/* was CC_UP_HIST */
1858 }
1859 
1860 /*ARGSUSED*/
1861 CCRETVAL
1862 e_down_hist(c)
1863     int c;
1864 {
1865     USE(c);
1866     UndoAction = TCSHOP_NOP;
1867     *LastChar = '\0';		/* just in case */
1868 
1869     Hist_num -= Argument;
1870 
1871     if (Hist_num < 0) {
1872 	Hist_num = 0;
1873 	return(CC_ERROR);	/* make it beep */
1874     }
1875 
1876     return(c_get_histline());
1877 }
1878 
1879 
1880 
1881 /*
1882  * c_hmatch() return True if the pattern matches the prefix
1883  */
1884 static int
1885 c_hmatch(str)
1886 Char *str;
1887 {
1888     if (Strncmp(patbuf, str, (size_t) patlen) == 0)
1889 	return 1;
1890     return Gmatch(str, patbuf);
1891 }
1892 
1893 /*
1894  * c_hsetpat(): Set the history seatch pattern
1895  */
1896 static void
1897 c_hsetpat()
1898 {
1899     if (LastCmd != F_UP_SEARCH_HIST && LastCmd != F_DOWN_SEARCH_HIST) {
1900 	patlen = (int) (Cursor - InputBuf);
1901 	if (patlen >= INBUFSIZE) patlen = INBUFSIZE -1;
1902 	if (patlen >= 0)  {
1903 	    (void) Strncpy(patbuf, InputBuf, (size_t) patlen);
1904 	    patbuf[patlen] = '\0';
1905 	}
1906 	else
1907 	    patlen = (int) Strlen(patbuf);
1908     }
1909 #ifdef SDEBUG
1910     xprintf("\nHist_num = %d\n", Hist_num);
1911     xprintf("patlen = %d\n", patlen);
1912     xprintf("patbuf = \"%S\"\n", patbuf);
1913     xprintf("Cursor %d LastChar %d\n", Cursor - InputBuf, LastChar - InputBuf);
1914 #endif
1915 }
1916 
1917 /*ARGSUSED*/
1918 CCRETVAL
1919 e_up_search_hist(c)
1920     int c;
1921 {
1922     struct Hist *hp;
1923     int h;
1924     bool    found = 0;
1925 
1926     USE(c);
1927     ActionFlag = TCSHOP_NOP;
1928     UndoAction = TCSHOP_NOP;
1929     *LastChar = '\0';		/* just in case */
1930     if (Hist_num < 0) {
1931 #ifdef DEBUG_EDIT
1932 	xprintf("%s: e_up_search_hist(): Hist_num < 0; resetting.\n", progname);
1933 #endif
1934 	Hist_num = 0;
1935 	return(CC_ERROR);
1936     }
1937 
1938     if (Hist_num == 0)
1939     {
1940 	copyn(HistBuf, InputBuf, INBUFSIZE);
1941 	LastHist = HistBuf + (LastChar - InputBuf);
1942     }
1943 
1944 
1945     hp = Histlist.Hnext;
1946     if (hp == NULL)
1947 	return(CC_ERROR);
1948 
1949     c_hsetpat();		/* Set search pattern !! */
1950 
1951     for (h = 1; h <= Hist_num; h++)
1952 	hp = hp->Hnext;
1953 
1954     while (hp != NULL) {
1955 	Char sbuf[INBUFSIZE], *hl;
1956 	if (hp->histline == NULL) {
1957 	    hp->histline = Strsave(sprlex(sbuf, sizeof(sbuf) / sizeof(Char),
1958 				   &hp->Hlex));
1959 	}
1960 	hl = HistLit ? hp->histline : sprlex(sbuf, sizeof(sbuf) / sizeof(Char),
1961 					     &hp->Hlex);
1962 #ifdef SDEBUG
1963 	xprintf("Comparing with \"%S\"\n", hl);
1964 #endif
1965 	if ((Strncmp(hl, InputBuf, (size_t) (LastChar - InputBuf)) ||
1966 	     hl[LastChar-InputBuf]) && c_hmatch(hl)) {
1967 	    found++;
1968 	    break;
1969 	}
1970 	h++;
1971 	hp = hp->Hnext;
1972     }
1973 
1974     if (!found) {
1975 #ifdef SDEBUG
1976 	xprintf("not found\n");
1977 #endif
1978 	return(CC_ERROR);
1979     }
1980 
1981     Hist_num = h;
1982 
1983     return(c_get_histline());
1984 }
1985 
1986 /*ARGSUSED*/
1987 CCRETVAL
1988 e_down_search_hist(c)
1989     int c;
1990 {
1991     struct Hist *hp;
1992     int h;
1993     bool    found = 0;
1994 
1995     USE(c);
1996     ActionFlag = TCSHOP_NOP;
1997     UndoAction = TCSHOP_NOP;
1998     *LastChar = '\0';		/* just in case */
1999 
2000     if (Hist_num == 0)
2001 	return(CC_ERROR);
2002 
2003     hp = Histlist.Hnext;
2004     if (hp == 0)
2005 	return(CC_ERROR);
2006 
2007     c_hsetpat();		/* Set search pattern !! */
2008 
2009     for (h = 1; h < Hist_num && hp; h++) {
2010 	Char sbuf[INBUFSIZE], *hl;
2011 	if (hp->histline == NULL) {
2012 	    hp->histline = Strsave(sprlex(sbuf, sizeof(sbuf) / sizeof(Char),
2013 				   &hp->Hlex));
2014 	}
2015 	hl = HistLit ? hp->histline : sprlex(sbuf, sizeof(sbuf) / sizeof(Char),
2016 					     &hp->Hlex);
2017 #ifdef SDEBUG
2018 	xprintf("Comparing with \"%S\"\n", hl);
2019 #endif
2020 	if ((Strncmp(hl, InputBuf, (size_t) (LastChar - InputBuf)) ||
2021 	     hl[LastChar-InputBuf]) && c_hmatch(hl))
2022 	    found = h;
2023 	hp = hp->Hnext;
2024     }
2025 
2026     if (!found) {		/* is it the current history number? */
2027 	if (!c_hmatch(HistBuf)) {
2028 #ifdef SDEBUG
2029 	    xprintf("not found\n");
2030 #endif
2031 	    return(CC_ERROR);
2032 	}
2033     }
2034 
2035     Hist_num = found;
2036 
2037     return(c_get_histline());
2038 }
2039 
2040 /*ARGSUSED*/
2041 CCRETVAL
2042 e_helpme(c)
2043     int c;
2044 {
2045     USE(c);
2046     PastBottom();
2047     *LastChar = '\0';		/* just in case */
2048     return(CC_HELPME);
2049 }
2050 
2051 /*ARGSUSED*/
2052 CCRETVAL
2053 e_correct(c)
2054     int c;
2055 {
2056     USE(c);
2057     *LastChar = '\0';		/* just in case */
2058     return(CC_CORRECT);
2059 }
2060 
2061 /*ARGSUSED*/
2062 CCRETVAL
2063 e_correctl(c)
2064     int c;
2065 {
2066     USE(c);
2067     *LastChar = '\0';		/* just in case */
2068     return(CC_CORRECT_L);
2069 }
2070 
2071 /*ARGSUSED*/
2072 CCRETVAL
2073 e_run_fg_editor(c)
2074     int c;
2075 {
2076     struct process *pp;
2077     extern bool tellwhat;
2078 
2079     USE(c);
2080     if ((pp = find_stop_ed()) != NULL) {
2081 	/* save our editor state so we can restore it */
2082 	tellwhat = 1;
2083 	copyn(WhichBuf, InputBuf, INBUFSIZE);
2084 	LastWhich = WhichBuf + (LastChar - InputBuf);
2085 	CursWhich = WhichBuf + (Cursor - InputBuf);
2086 	HistWhich = Hist_num;
2087 	Hist_num = 0;		/* for the history commands */
2088 
2089 	/* put the tty in a sane mode */
2090 	PastBottom();
2091 	(void) Cookedmode();	/* make sure the tty is set up correctly */
2092 
2093 	/* do it! */
2094 	fg_proc_entry(pp);
2095 
2096 	(void) Rawmode();	/* go on */
2097 	Refresh();
2098 	tellwhat = 0;
2099     }
2100     return(CC_NORM);
2101 }
2102 
2103 /*ARGSUSED*/
2104 CCRETVAL
2105 e_list_choices(c)
2106     int c;
2107 {
2108     USE(c);
2109     PastBottom();
2110     *LastChar = '\0';		/* just in case */
2111     return(CC_LIST_CHOICES);
2112 }
2113 
2114 /*ARGSUSED*/
2115 CCRETVAL
2116 e_list_all(c)
2117     int c;
2118 {
2119     USE(c);
2120     PastBottom();
2121     *LastChar = '\0';		/* just in case */
2122     return(CC_LIST_ALL);
2123 }
2124 
2125 /*ARGSUSED*/
2126 CCRETVAL
2127 e_list_glob(c)
2128     int c;
2129 {
2130     USE(c);
2131     PastBottom();
2132     *LastChar = '\0';		/* just in case */
2133     return(CC_LIST_GLOB);
2134 }
2135 
2136 /*ARGSUSED*/
2137 CCRETVAL
2138 e_expand_glob(c)
2139     int c;
2140 {
2141     USE(c);
2142     *LastChar = '\0';		/* just in case */
2143     return(CC_EXPAND_GLOB);
2144 }
2145 
2146 /*ARGSUSED*/
2147 CCRETVAL
2148 e_normalize_path(c)
2149     int c;
2150 {
2151     USE(c);
2152     *LastChar = '\0';		/* just in case */
2153     return(CC_NORMALIZE_PATH);
2154 }
2155 
2156 /*ARGSUSED*/
2157 CCRETVAL
2158 e_normalize_command(c)
2159     int c;
2160 {
2161     USE(c);
2162     *LastChar = '\0';		/* just in case */
2163     return(CC_NORMALIZE_COMMAND);
2164 }
2165 
2166 /*ARGSUSED*/
2167 CCRETVAL
2168 e_expand_vars(c)
2169     int c;
2170 {
2171     USE(c);
2172     *LastChar = '\0';		/* just in case */
2173     return(CC_EXPAND_VARS);
2174 }
2175 
2176 /*ARGSUSED*/
2177 CCRETVAL
2178 e_which(c)
2179     int c;
2180 {				/* do a fast command line which(1) */
2181     USE(c);
2182     PastBottom();
2183     *LastChar = '\0';		/* just in case */
2184     return(CC_WHICH);
2185 }
2186 
2187 /*ARGSUSED*/
2188 CCRETVAL
2189 e_last_item(c)
2190     int c;
2191 {				/* insert the last element of the prev. cmd */
2192     Char *cp;
2193     struct Hist *hp;
2194     struct wordent *wp, *firstp;
2195     int i;
2196     Char buf[INBUFSIZE];
2197 
2198     USE(c);
2199     if (Argument <= 0)
2200 	return(CC_ERROR);
2201 
2202     hp = Histlist.Hnext;
2203     if (hp == NULL) {	/* this is only if no history */
2204 	return(CC_ERROR);
2205     }
2206 
2207     wp = (hp->Hlex).prev;
2208 
2209     if (wp->prev == (struct wordent *) NULL)
2210 	return(CC_ERROR);	/* an empty history entry */
2211 
2212     firstp = (hp->Hlex).next;
2213 
2214     /* back up arg words in lex */
2215     for (i = 0; i < Argument && wp != firstp; i++) {
2216 	wp = wp->prev;
2217     }
2218 
2219     cp = expand_lex(buf, INBUFSIZE, wp->prev, 0, i - 1);
2220     *cp = '\0';
2221     if (InsertStr(buf))
2222 	return(CC_ERROR);
2223 
2224     return(CC_REFRESH);
2225 }
2226 
2227 /*ARGSUSED*/
2228 CCRETVAL
2229 e_dabbrev_expand(c)
2230     int c;
2231 {				/* expand to preceding word matching prefix */
2232     Char *cp, *ncp, *bp;
2233     struct Hist *hp;
2234     int arg = 0, len = 0, i; /* len = 0 to shut up gcc -Wall */
2235     bool found = 0;
2236     Char hbuf[INBUFSIZE];
2237     static int oldevent, hist, word;
2238     static Char *start, *oldcursor;
2239 
2240     USE(c);
2241     if (Argument <= 0)
2242 	return(CC_ERROR);
2243 
2244     cp = c_preword(Cursor, InputBuf, 1, STRshwordsep);
2245     if (cp == Cursor || Isspace(*cp))
2246 	return(CC_ERROR);
2247 
2248     hp = Histlist.Hnext;
2249     bp = InputBuf;
2250     if (Argument == 1 && eventno == oldevent && cp == start &&
2251 	Cursor == oldcursor && patlen > 0 && Strncmp(patbuf, cp, patlen) == 0){
2252 	/* continue previous search - go to last match (hist/word) */
2253 	if (hist != 0) {		/* need to move up history */
2254 	    for (i = 1; i < hist && hp != NULL; i++)
2255 		hp = hp->Hnext;
2256 	    if (hp == NULL)	/* "can't happen" */
2257 		return(CC_ERROR);
2258 	    cp = expand_lex(hbuf, INBUFSIZE, &hp->Hlex, 0, NCARGS);
2259 	    *cp = '\0';
2260 	    bp = hbuf;
2261 	    hp = hp->Hnext;
2262 	}
2263 	cp = c_preword(cp, bp, word, STRshwordsep);
2264     } else {			/* starting new search */
2265 	oldevent = eventno;
2266 	start = cp;
2267 	patlen = (int) (Cursor - cp);
2268 	(void) Strncpy(patbuf, cp, patlen);
2269 	hist = 0;
2270 	word = 0;
2271     }
2272 
2273     while (!found) {
2274 	ncp = c_preword(cp, bp, 1, STRshwordsep);
2275 	if (ncp == cp || Isspace(*ncp)) { /* beginning of line */
2276 	    hist++;
2277 	    word = 0;
2278 	    if (hp == NULL)
2279 		return(CC_ERROR);
2280 	    cp = expand_lex(hbuf, INBUFSIZE, &hp->Hlex, 0, NCARGS);
2281 	    *cp = '\0';
2282 	    bp = hbuf;
2283 	    hp = hp->Hnext;
2284 	    continue;
2285 	} else {
2286 	    word++;
2287 	    len = (int) (c_endword(ncp-1, cp, 1, STRshwordsep) - ncp + 1);
2288 	    cp = ncp;
2289 	}
2290 	if (len > patlen && Strncmp(cp, patbuf, patlen) == 0) {
2291 	    /* We don't fully check distinct matches as Gnuemacs does: */
2292 	    if (Argument > 1) {	/* just count matches */
2293 		if (++arg >= Argument)
2294 		    found++;
2295 	    } else {		/* match if distinct from previous */
2296 		if (len != Cursor - start || Strncmp(cp, start, len) != 0)
2297 		    found++;
2298 	    }
2299 	}
2300     }
2301 
2302     if (LastChar + len - (Cursor - start) >= InputLim)
2303 	return(CC_ERROR);	/* no room */
2304     DeleteBack(Cursor - start);
2305     c_insert(len);
2306     while (len--)
2307 	*Cursor++ = *cp++;
2308     oldcursor = Cursor;
2309     return(CC_REFRESH);
2310 }
2311 
2312 /*ARGSUSED*/
2313 CCRETVAL
2314 e_yank_kill(c)
2315     int c;
2316 {				/* almost like GnuEmacs */
2317     int len;
2318     Char *kp, *cp;
2319 
2320     USE(c);
2321     if (KillRingLen == 0)	/* nothing killed */
2322 	return(CC_ERROR);
2323     len = Strlen(KillRing[YankPos].buf);
2324     if (LastChar + len >= InputLim)
2325 	return(CC_ERROR);	/* end of buffer space */
2326 
2327     /* else */
2328     cp = Cursor;		/* for speed */
2329 
2330     c_insert(len);		/* open the space, */
2331     for (kp = KillRing[YankPos].buf; *kp; kp++)	/* copy the chars */
2332 	*cp++ = *kp;
2333 
2334     if (Argument == 1) {	/* if no arg */
2335 	Mark = Cursor;		/* mark at beginning, cursor at end */
2336 	Cursor = cp;
2337     } else {
2338 	Mark = cp;		/* else cursor at beginning, mark at end */
2339     }
2340 
2341     return(CC_REFRESH);
2342 }
2343 
2344 /*ARGSUSED*/
2345 CCRETVAL
2346 e_yank_pop(c)
2347     int c;
2348 {				/* almost like GnuEmacs */
2349     int m_bef_c, del_len, ins_len;
2350     Char *kp, *cp;
2351 
2352     USE(c);
2353 
2354 #if 0
2355     /* XXX This "should" be here, but doesn't work, since LastCmd
2356        gets set on CC_ERROR and CC_ARGHACK, which it shouldn't(?).
2357        (But what about F_ARGFOUR?) I.e. if you hit M-y twice the
2358        second one will "succeed" even if the first one wasn't preceded
2359        by a yank, and giving an argument is impossible. Now we "succeed"
2360        regardless of previous command, which is wrong too of course. */
2361     if (LastCmd != F_YANK_KILL && LastCmd != F_YANK_POP)
2362 	return(CC_ERROR);
2363 #endif
2364 
2365     if (KillRingLen == 0)	/* nothing killed */
2366 	return(CC_ERROR);
2367     YankPos -= Argument;
2368     while (YankPos < 0)
2369 	YankPos += KillRingLen;
2370     YankPos %= KillRingLen;
2371 
2372     if (Cursor > Mark) {
2373 	del_len = Cursor - Mark;
2374 	m_bef_c = 1;
2375     } else {
2376 	del_len = Mark - Cursor;
2377 	m_bef_c = 0;
2378     }
2379     ins_len = Strlen(KillRing[YankPos].buf);
2380     if (LastChar + ins_len - del_len >= InputLim)
2381 	return(CC_ERROR);	/* end of buffer space */
2382 
2383     if (m_bef_c) {
2384 	c_delbefore(del_len);
2385 	Cursor = Mark;
2386     } else {
2387 	c_delafter(del_len);
2388     }
2389     cp = Cursor;		/* for speed */
2390 
2391     c_insert(ins_len);		/* open the space, */
2392     for (kp = KillRing[YankPos].buf; *kp; kp++)	/* copy the chars */
2393 	*cp++ = *kp;
2394 
2395     if (m_bef_c) {
2396 	Mark = Cursor;		/* mark at beginning, cursor at end */
2397 	Cursor = cp;
2398     } else {
2399 	Mark = cp;		/* else cursor at beginning, mark at end */
2400     }
2401 
2402     return(CC_REFRESH);
2403 }
2404 
2405 /*ARGSUSED*/
2406 CCRETVAL
2407 v_delprev(c) 		/* Backspace key in insert mode */
2408     int c;
2409 {
2410     int rc;
2411 
2412     USE(c);
2413     rc = CC_ERROR;
2414 
2415     if (InsertPos != 0) {
2416 	if (Argument <= Cursor - InsertPos) {
2417 	    c_delbefore(Argument);	/* delete before */
2418 	    Cursor -= Argument;
2419 #if defined(DSPMBYTE)
2420 	if (_enable_mbdisp && extdel) {
2421 	    Cursor--;
2422 	    e_redisp(c);
2423 	}
2424 #endif
2425 	    rc = CC_REFRESH;
2426 	}
2427     }
2428     return(rc);
2429 }   /* v_delprev  */
2430 
2431 /*ARGSUSED*/
2432 CCRETVAL
2433 e_delprev(c)
2434     int c;
2435 {
2436     USE(c);
2437     if (Cursor > InputBuf) {
2438 	c_delbefore(Argument);	/* delete before dot */
2439 	if (Argument > Cursor - InputBuf)
2440 	    Cursor = InputBuf;	/* bounds check */
2441 	else
2442 	    Cursor -= Argument;
2443 #if defined(DSPMBYTE)
2444 	if (_enable_mbdisp && extdel && Cursor > InputBuf) {
2445 	    Cursor--;
2446 	    e_redisp(c);
2447 	}
2448 #endif
2449 	return(CC_REFRESH);
2450     }
2451     else {
2452 	return(CC_ERROR);
2453     }
2454 }
2455 
2456 /*ARGSUSED*/
2457 CCRETVAL
2458 e_delwordprev(c)
2459     int c;
2460 {
2461     Char *cp;
2462 
2463     USE(c);
2464     if (Cursor == InputBuf)
2465 	return(CC_ERROR);
2466     /* else */
2467 
2468     cp = c_prev_word(Cursor, InputBuf, Argument);
2469 
2470     c_push_kill(cp, Cursor);	/* save the text */
2471 
2472     c_delbefore((int)(Cursor - cp));	/* delete before dot */
2473     Cursor = cp;
2474     if (Cursor < InputBuf)
2475 	Cursor = InputBuf;	/* bounds check */
2476     return(CC_REFRESH);
2477 }
2478 
2479 /* DCS <dcs@neutron.chem.yale.edu>, 9 Oct 93
2480  *
2481  * Changed the names of some of the ^D family of editor functions to
2482  * correspond to what they actually do and created new e_delnext_list
2483  * for completeness.
2484  *
2485  *   Old names:			New names:
2486  *
2487  *   delete-char		delete-char-or-eof
2488  *     F_DELNEXT		  F_DELNEXT_EOF
2489  *     e_delnext		  e_delnext_eof
2490  *     edelnxt			  edelnxteof
2491  *   delete-char-or-eof		delete-char
2492  *     F_DELNEXT_EOF		  F_DELNEXT
2493  *     e_delnext_eof		  e_delnext
2494  *     edelnxteof		  edelnxt
2495  *   delete-char-or-list	delete-char-or-list-or-eof
2496  *     F_LIST_DELNEXT		  F_DELNEXT_LIST_EOF
2497  *     e_list_delnext		  e_delnext_list_eof
2498  *   				  edellsteof
2499  *   (no old equivalent)	delete-char-or-list
2500  *   				  F_DELNEXT_LIST
2501  *   				  e_delnext_list
2502  *   				  e_delnxtlst
2503  */
2504 
2505 /* added by mtk@ari.ncl.omron.co.jp (920818) */
2506 /* rename e_delnext() -> e_delnext_eof() */
2507 /*ARGSUSED*/
2508 CCRETVAL
2509 e_delnext(c)
2510     int c;
2511 {
2512     USE(c);
2513     if (Cursor == LastChar) {/* if I'm at the end */
2514 	if (!VImode) {
2515 		return(CC_ERROR);
2516 	}
2517 	else {
2518 	    if (Cursor != InputBuf)
2519 		Cursor--;
2520 	    else
2521 		return(CC_ERROR);
2522 	}
2523     }
2524     c_delafter(Argument);	/* delete after dot */
2525     if (Cursor > LastChar)
2526 	Cursor = LastChar;	/* bounds check */
2527     return(CC_REFRESH);
2528 }
2529 
2530 
2531 /*ARGSUSED*/
2532 CCRETVAL
2533 e_delnext_eof(c)
2534     int c;
2535 {
2536     USE(c);
2537     if (Cursor == LastChar) {/* if I'm at the end */
2538 	if (!VImode) {
2539 	    if (Cursor == InputBuf) {
2540 		/* if I'm also at the beginning */
2541 		so_write(STReof, 4);/* then do a EOF */
2542 		flush();
2543 		return(CC_EOF);
2544 	    }
2545 	    else
2546 		return(CC_ERROR);
2547 	}
2548 	else {
2549 	    if (Cursor != InputBuf)
2550 		Cursor--;
2551 	    else
2552 		return(CC_ERROR);
2553 	}
2554     }
2555     c_delafter(Argument);	/* delete after dot */
2556     if (Cursor > LastChar)
2557 	Cursor = LastChar;	/* bounds check */
2558     return(CC_REFRESH);
2559 }
2560 
2561 /*ARGSUSED*/
2562 CCRETVAL
2563 e_delnext_list(c)
2564     int c;
2565 {
2566     USE(c);
2567     if (Cursor == LastChar) {	/* if I'm at the end */
2568 	PastBottom();
2569 	*LastChar = '\0';	/* just in case */
2570 	return(CC_LIST_CHOICES);
2571     }
2572     else {
2573 	c_delafter(Argument);	/* delete after dot */
2574 	if (Cursor > LastChar)
2575 	    Cursor = LastChar;	/* bounds check */
2576 	return(CC_REFRESH);
2577     }
2578 }
2579 
2580 /*ARGSUSED*/
2581 CCRETVAL
2582 e_delnext_list_eof(c)
2583     int c;
2584 {
2585     USE(c);
2586     if (Cursor == LastChar) {	/* if I'm at the end */
2587 	if (Cursor == InputBuf) {	/* if I'm also at the beginning */
2588 	    so_write(STReof, 4);/* then do a EOF */
2589 	    flush();
2590 	    return(CC_EOF);
2591 	}
2592 	else {
2593 	    PastBottom();
2594 	    *LastChar = '\0';	/* just in case */
2595 	    return(CC_LIST_CHOICES);
2596 	}
2597     }
2598     else {
2599 	c_delafter(Argument);	/* delete after dot */
2600 	if (Cursor > LastChar)
2601 	    Cursor = LastChar;	/* bounds check */
2602 	return(CC_REFRESH);
2603     }
2604 }
2605 
2606 /*ARGSUSED*/
2607 CCRETVAL
2608 e_list_eof(c)
2609     int c;
2610 {
2611     CCRETVAL rv;
2612 
2613     USE(c);
2614     if (Cursor == LastChar && Cursor == InputBuf) {
2615 	so_write(STReof, 4);	/* then do a EOF */
2616 	flush();
2617 	rv = CC_EOF;
2618     }
2619     else {
2620 	PastBottom();
2621 	*LastChar = '\0';	/* just in case */
2622 	rv = CC_LIST_CHOICES;
2623     }
2624     return rv;
2625 }
2626 
2627 /*ARGSUSED*/
2628 CCRETVAL
2629 e_delwordnext(c)
2630     int c;
2631 {
2632     Char *cp;
2633 
2634     USE(c);
2635     if (Cursor == LastChar)
2636 	return(CC_ERROR);
2637     /* else */
2638 
2639     cp = c_next_word(Cursor, LastChar, Argument);
2640 
2641     c_push_kill(Cursor, cp);	/* save the text */
2642 
2643     c_delafter((int)(cp - Cursor));	/* delete after dot */
2644     if (Cursor > LastChar)
2645 	Cursor = LastChar;	/* bounds check */
2646     return(CC_REFRESH);
2647 }
2648 
2649 /*ARGSUSED*/
2650 CCRETVAL
2651 e_toend(c)
2652     int c;
2653 {
2654     USE(c);
2655     Cursor = LastChar;
2656     if (VImode)
2657 	if (ActionFlag & TCSHOP_DELETE) {
2658 	    c_delfini();
2659 	    return(CC_REFRESH);
2660 	}
2661     RefCursor();		/* move the cursor */
2662     return(CC_NORM);
2663 }
2664 
2665 /*ARGSUSED*/
2666 CCRETVAL
2667 e_tobeg(c)
2668     int c;
2669 {
2670     USE(c);
2671     Cursor = InputBuf;
2672 
2673     if (VImode) {
2674        while (Isspace(*Cursor)) /* We want FIRST non space character */
2675 	Cursor++;
2676 	if (ActionFlag & TCSHOP_DELETE) {
2677 	    c_delfini();
2678 	    return(CC_REFRESH);
2679 	}
2680     }
2681 
2682     RefCursor();		/* move the cursor */
2683     return(CC_NORM);
2684 }
2685 
2686 /*ARGSUSED*/
2687 CCRETVAL
2688 e_killend(c)
2689     int c;
2690 {
2691     USE(c);
2692     c_push_kill(Cursor, LastChar); /* copy it */
2693     LastChar = Cursor;		/* zap! -- delete to end */
2694     return(CC_REFRESH);
2695 }
2696 
2697 
2698 /*ARGSUSED*/
2699 CCRETVAL
2700 e_killbeg(c)
2701     int c;
2702 {
2703     USE(c);
2704     c_push_kill(InputBuf, Cursor); /* copy it */
2705     c_delbefore((int)(Cursor - InputBuf));
2706     Cursor = InputBuf;		/* zap! */
2707     return(CC_REFRESH);
2708 }
2709 
2710 /*ARGSUSED*/
2711 CCRETVAL
2712 e_killall(c)
2713     int c;
2714 {
2715     USE(c);
2716     c_push_kill(InputBuf, LastChar); /* copy it */
2717     LastChar = InputBuf;	/* zap! -- delete all of it */
2718     Cursor = InputBuf;
2719     return(CC_REFRESH);
2720 }
2721 
2722 /*ARGSUSED*/
2723 CCRETVAL
2724 e_killregion(c)
2725     int c;
2726 {
2727     USE(c);
2728     if (!Mark)
2729 	return(CC_ERROR);
2730 
2731     if (Mark > Cursor) {
2732 	c_push_kill(Cursor, Mark); /* copy it */
2733 	c_delafter((int)(Mark - Cursor)); /* delete it - UNUSED BY VI mode */
2734 	Mark = Cursor;
2735     }
2736     else {			/* mark is before cursor */
2737 	c_push_kill(Mark, Cursor); /* copy it */
2738 	c_delbefore((int)(Cursor - Mark));
2739 	Cursor = Mark;
2740     }
2741     return(CC_REFRESH);
2742 }
2743 
2744 /*ARGSUSED*/
2745 CCRETVAL
2746 e_copyregion(c)
2747     int c;
2748 {
2749     USE(c);
2750     if (!Mark)
2751 	return(CC_ERROR);
2752 
2753     if (Mark > Cursor) {
2754 	c_push_kill(Cursor, Mark); /* copy it */
2755     }
2756     else {			/* mark is before cursor */
2757 	c_push_kill(Mark, Cursor); /* copy it */
2758     }
2759     return(CC_NORM);		/* don't even need to Refresh() */
2760 }
2761 
2762 /*ARGSUSED*/
2763 CCRETVAL
2764 e_charswitch(cc)
2765     int cc;
2766 {
2767     Char c;
2768 
2769     USE(cc);
2770 
2771     /* do nothing if we are at beginning of line or have only one char */
2772     if (Cursor == &InputBuf[0] || LastChar == &InputBuf[1]) {
2773 	return(CC_ERROR);
2774     }
2775 
2776     if (Cursor < LastChar) {
2777 	Cursor++;
2778     }
2779     c = Cursor[-2];
2780     Cursor[-2] = Cursor[-1];
2781     Cursor[-1] = c;
2782     return(CC_REFRESH);
2783 }
2784 
2785 /*ARGSUSED*/
2786 CCRETVAL
2787 e_gcharswitch(cc)
2788     int cc;
2789 {				/* gosmacs style ^T */
2790     Char c;
2791 
2792     USE(cc);
2793     if (Cursor > &InputBuf[1]) {/* must have at least two chars entered */
2794 	c = Cursor[-2];
2795 	Cursor[-2] = Cursor[-1];
2796 	Cursor[-1] = c;
2797 	return(CC_REFRESH);
2798     }
2799     else {
2800 	return(CC_ERROR);
2801     }
2802 }
2803 
2804 #if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */
2805 /*ARGSUSED*/
2806 static void
2807 e_charback_mbyte(argument)
2808      int argument;
2809 {
2810     if (!_enable_mbdisp) {
2811 	if (Argument > Cursor - InputBuf)
2812 	    Cursor = InputBuf;
2813 	else
2814 	    Cursor -= Argument;
2815     }
2816     else {
2817 	while (0 < argument && Cursor > InputBuf) {
2818 	    if (Cursor - 1 != InputBuf &&
2819 		Ismbyte1(*(Cursor - 2)) && Ismbyte2(*(Cursor - 1))) {
2820 		Cursor--;
2821 	    }
2822 	    Cursor--;
2823 	    argument--;
2824 	}
2825     }
2826 }
2827 #endif
2828 
2829 /*ARGSUSED*/
2830 CCRETVAL
2831 e_charback(c)
2832     int c;
2833 {
2834     USE(c);
2835     if (Cursor > InputBuf) {
2836 #if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */
2837 	e_charback_mbyte(Argument);
2838 #else
2839 	if (Argument > Cursor - InputBuf)
2840 	    Cursor = InputBuf;
2841 	else
2842 	    Cursor -= Argument;
2843 #endif
2844 
2845 	if (VImode)
2846 	    if (ActionFlag & TCSHOP_DELETE) {
2847 		c_delfini();
2848 		return(CC_REFRESH);
2849 	    }
2850 
2851 	RefCursor();
2852 	return(CC_NORM);
2853     }
2854     else {
2855 	return(CC_ERROR);
2856     }
2857 }
2858 
2859 /*ARGSUSED*/
2860 CCRETVAL
2861 v_wordback(c)
2862     int c;
2863 {
2864     USE(c);
2865     if (Cursor == InputBuf)
2866 	return(CC_ERROR);
2867     /* else */
2868 
2869     Cursor = c_preword(Cursor, InputBuf, Argument, STRshwspace); /* bounds check */
2870 
2871     if (ActionFlag & TCSHOP_DELETE) {
2872 	c_delfini();
2873 	return(CC_REFRESH);
2874     }
2875 
2876     RefCursor();
2877     return(CC_NORM);
2878 }
2879 
2880 /*ARGSUSED*/
2881 CCRETVAL
2882 e_wordback(c)
2883     int c;
2884 {
2885     USE(c);
2886     if (Cursor == InputBuf)
2887 	return(CC_ERROR);
2888     /* else */
2889 
2890     Cursor = c_prev_word(Cursor, InputBuf, Argument); /* bounds check */
2891 
2892     if (VImode)
2893 	if (ActionFlag & TCSHOP_DELETE) {
2894 	    c_delfini();
2895 	    return(CC_REFRESH);
2896 	}
2897 
2898     RefCursor();
2899     return(CC_NORM);
2900 }
2901 
2902 #if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */
2903 /*ARGSUSED*/
2904 static void
2905 e_charfwd_mbyte(argument)
2906      int argument;
2907 {
2908     if (!_enable_mbdisp)
2909 	Cursor += argument;
2910     else
2911 	while (0 < argument && Cursor < LastChar) {
2912 	    if (Cursor + 1 != LastChar &&
2913 		Ismbyte1(*Cursor) && Ismbyte2(*(Cursor + 1))) {
2914 		Cursor++;
2915 	    }
2916 	    Cursor++;
2917 	    argument--;
2918 	}
2919 }
2920 #endif
2921 
2922 /*ARGSUSED*/
2923 CCRETVAL
2924 e_charfwd(c)
2925     int c;
2926 {
2927     USE(c);
2928     if (Cursor < LastChar) {
2929 #if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */
2930 	e_charfwd_mbyte(Argument);
2931 #else
2932 	Cursor += Argument;
2933 #endif
2934 	if (Cursor > LastChar)
2935 	    Cursor = LastChar;
2936 
2937 	if (VImode)
2938 	    if (ActionFlag & TCSHOP_DELETE) {
2939 		c_delfini();
2940 		return(CC_REFRESH);
2941 	    }
2942 
2943 	RefCursor();
2944 	return(CC_NORM);
2945     }
2946     else {
2947 	return(CC_ERROR);
2948     }
2949 }
2950 
2951 /*ARGSUSED*/
2952 CCRETVAL
2953 e_wordfwd(c)
2954     int c;
2955 {
2956     USE(c);
2957     if (Cursor == LastChar)
2958 	return(CC_ERROR);
2959     /* else */
2960 
2961     Cursor = c_next_word(Cursor, LastChar, Argument);
2962 
2963     if (VImode)
2964 	if (ActionFlag & TCSHOP_DELETE) {
2965 	    c_delfini();
2966 	    return(CC_REFRESH);
2967 	}
2968 
2969     RefCursor();
2970     return(CC_NORM);
2971 }
2972 
2973 /*ARGSUSED*/
2974 CCRETVAL
2975 v_wordfwd(c)
2976     int c;
2977 {
2978     USE(c);
2979     if (Cursor == LastChar)
2980 	return(CC_ERROR);
2981     /* else */
2982 
2983     Cursor = c_nexword(Cursor, LastChar, Argument);
2984 
2985     if (VImode)
2986 	if (ActionFlag & TCSHOP_DELETE) {
2987 	    c_delfini();
2988 	    return(CC_REFRESH);
2989 	}
2990 
2991     RefCursor();
2992     return(CC_NORM);
2993 }
2994 
2995 /*ARGSUSED*/
2996 CCRETVAL
2997 v_wordbegnext(c)
2998     int c;
2999 {
3000     USE(c);
3001     if (Cursor == LastChar)
3002 	return(CC_ERROR);
3003     /* else */
3004 
3005     Cursor = c_next_word(Cursor, LastChar, Argument);
3006     if (Cursor < LastChar)
3007 	Cursor++;
3008 
3009     if (VImode)
3010 	if (ActionFlag & TCSHOP_DELETE) {
3011 	    c_delfini();
3012 	    return(CC_REFRESH);
3013 	}
3014 
3015     RefCursor();
3016     return(CC_NORM);
3017 }
3018 
3019 /*ARGSUSED*/
3020 static CCRETVAL
3021 v_repeat_srch(c)
3022     int c;
3023 {
3024     CCRETVAL rv = CC_ERROR;
3025 #ifdef SDEBUG
3026     xprintf("dir %d patlen %d patbuf %S\n",
3027 	    c, patlen, patbuf);
3028 #endif
3029 
3030     LastCmd = (KEYCMD) c;  /* Hack to stop c_hsetpat */
3031     LastChar = InputBuf;
3032     switch (c) {
3033     case F_DOWN_SEARCH_HIST:
3034 	rv = e_down_search_hist(0);
3035 	break;
3036     case F_UP_SEARCH_HIST:
3037 	rv = e_up_search_hist(0);
3038 	break;
3039     default:
3040 	break;
3041     }
3042     return rv;
3043 }
3044 
3045 static CCRETVAL
3046 v_csearch_back(ch, count, tflag)
3047     int ch, count, tflag;
3048 {
3049     Char *cp;
3050 
3051     cp = Cursor;
3052     while (count--) {
3053 	if (*cp == ch)
3054 	    cp--;
3055 	while (cp > InputBuf && *cp != ch)
3056 	    cp--;
3057     }
3058 
3059     if (cp < InputBuf || (cp == InputBuf && *cp != ch))
3060 	return(CC_ERROR);
3061 
3062     if (*cp == ch && tflag)
3063 	cp++;
3064 
3065     Cursor = cp;
3066 
3067     if (ActionFlag & TCSHOP_DELETE) {
3068 	Cursor++;
3069 	c_delfini();
3070 	return(CC_REFRESH);
3071     }
3072 
3073     RefCursor();
3074     return(CC_NORM);
3075 }
3076 
3077 static CCRETVAL
3078 v_csearch_fwd(ch, count, tflag)
3079     int ch, count, tflag;
3080 {
3081     Char *cp;
3082 
3083     cp = Cursor;
3084     while (count--) {
3085 	if(*cp == ch)
3086 	    cp++;
3087 	while (cp < LastChar && *cp != ch)
3088 	    cp++;
3089     }
3090 
3091     if (cp >= LastChar)
3092 	return(CC_ERROR);
3093 
3094     if (*cp == ch && tflag)
3095 	cp--;
3096 
3097     Cursor = cp;
3098 
3099     if (ActionFlag & TCSHOP_DELETE) {
3100 	Cursor++;
3101 	c_delfini();
3102 	return(CC_REFRESH);
3103     }
3104     RefCursor();
3105     return(CC_NORM);
3106 }
3107 
3108 /*ARGSUSED*/
3109 static CCRETVAL
3110 v_action(c)
3111     int c;
3112 {
3113     Char *cp, *kp;
3114 
3115     if (ActionFlag == TCSHOP_DELETE) {
3116 	ActionFlag = TCSHOP_NOP;
3117 	ActionPos = 0;
3118 
3119 	UndoSize = 0;
3120 	kp = UndoBuf;
3121 	for (cp = InputBuf; cp < LastChar; cp++) {
3122 	    *kp++ = *cp;
3123 	    UndoSize++;
3124 	}
3125 
3126 	UndoAction = TCSHOP_INSERT;
3127 	UndoPtr  = InputBuf;
3128 	LastChar = InputBuf;
3129 	Cursor   = InputBuf;
3130 	if (c & TCSHOP_INSERT)
3131 	    c_alternativ_key_map(0);
3132 
3133 	return(CC_REFRESH);
3134     }
3135 #ifdef notdef
3136     else if (ActionFlag == TCSHOP_NOP) {
3137 #endif
3138 	ActionPos = Cursor;
3139 	ActionFlag = c;
3140 	return(CC_ARGHACK);  /* Do NOT clear out argument */
3141 #ifdef notdef
3142     }
3143     else {
3144 	ActionFlag = 0;
3145 	ActionPos = 0;
3146 	return(CC_ERROR);
3147     }
3148 #endif
3149 }
3150 
3151 #ifdef COMMENT
3152 /* by: Brian Allison <uiucdcs!convex!allison@RUTGERS.EDU> */
3153 static void
3154 c_get_word(begin, end)
3155     Char  **begin;
3156     Char  **end;
3157 {
3158     Char   *cp;
3159 
3160     cp = &Cursor[0];
3161     while (Argument--) {
3162 	while ((cp <= LastChar) && (isword(*cp)))
3163 	    cp++;
3164 	*end = --cp;
3165 	while ((cp >= InputBuf) && (isword(*cp)))
3166 	    cp--;
3167 	*begin = ++cp;
3168     }
3169 }
3170 #endif /* COMMENT */
3171 
3172 /*ARGSUSED*/
3173 CCRETVAL
3174 e_uppercase(c)
3175     int c;
3176 {
3177     Char   *cp, *end;
3178 
3179     USE(c);
3180     end = c_next_word(Cursor, LastChar, Argument);
3181 
3182     for (cp = Cursor; cp < end; cp++)	/* PWP: was cp=begin */
3183 	if (Islower(*cp))
3184 	    *cp = Toupper(*cp);
3185 
3186     Cursor = end;
3187     if (Cursor > LastChar)
3188 	Cursor = LastChar;
3189     return(CC_REFRESH);
3190 }
3191 
3192 
3193 /*ARGSUSED*/
3194 CCRETVAL
3195 e_capitolcase(c)
3196     int c;
3197 {
3198     Char   *cp, *end;
3199 
3200     USE(c);
3201     end = c_next_word(Cursor, LastChar, Argument);
3202 
3203     cp = Cursor;
3204     for (; cp < end; cp++) {
3205 	if (Isalpha(*cp)) {
3206 	    if (Islower(*cp))
3207 		*cp = Toupper(*cp);
3208 	    cp++;
3209 	    break;
3210 	}
3211     }
3212     for (; cp < end; cp++)
3213 	if (Isupper(*cp))
3214 	    *cp = Tolower(*cp);
3215 
3216     Cursor = end;
3217     if (Cursor > LastChar)
3218 	Cursor = LastChar;
3219     return(CC_REFRESH);
3220 }
3221 
3222 /*ARGSUSED*/
3223 CCRETVAL
3224 e_lowercase(c)
3225     int c;
3226 {
3227     Char   *cp, *end;
3228 
3229     USE(c);
3230     end = c_next_word(Cursor, LastChar, Argument);
3231 
3232     for (cp = Cursor; cp < end; cp++)
3233 	if (Isupper(*cp))
3234 	    *cp = Tolower(*cp);
3235 
3236     Cursor = end;
3237     if (Cursor > LastChar)
3238 	Cursor = LastChar;
3239     return(CC_REFRESH);
3240 }
3241 
3242 
3243 /*ARGSUSED*/
3244 CCRETVAL
3245 e_set_mark(c)
3246     int c;
3247 {
3248     USE(c);
3249     Mark = Cursor;
3250     return(CC_NORM);
3251 }
3252 
3253 /*ARGSUSED*/
3254 CCRETVAL
3255 e_exchange_mark(c)
3256     int c;
3257 {
3258     Char *cp;
3259 
3260     USE(c);
3261     cp = Cursor;
3262     Cursor = Mark;
3263     Mark = cp;
3264     RefCursor();
3265     return(CC_NORM);
3266 }
3267 
3268 /*ARGSUSED*/
3269 CCRETVAL
3270 e_argfour(c)
3271     int c;
3272 {				/* multiply current argument by 4 */
3273     USE(c);
3274     if (Argument > 1000000)
3275 	return CC_ERROR;
3276     DoingArg = 1;
3277     Argument *= 4;
3278     return(CC_ARGHACK);
3279 }
3280 
3281 /*ARGSUSED*/
3282 CCRETVAL
3283 e_quote(c)
3284     int c;
3285 {
3286     Char    ch;
3287     int     num;
3288 
3289     USE(c);
3290     QuoteModeOn();
3291     num = GetNextChar(&ch);
3292     QuoteModeOff();
3293     if (num == 1)
3294 	return e_insert(ch);
3295     else
3296 	return e_send_eof(0);
3297 }
3298 
3299 /*ARGSUSED*/
3300 CCRETVAL
3301 e_metanext(c)
3302     int c;
3303 {
3304     USE(c);
3305     MetaNext = 1;
3306     return(CC_ARGHACK);	/* preserve argument */
3307 }
3308 
3309 #ifdef notdef
3310 /*ARGSUSED*/
3311 CCRETVAL
3312 e_extendnext(c)
3313     int c;
3314 {
3315     CurrentKeyMap = CcAltMap;
3316     return(CC_ARGHACK);	/* preserve argument */
3317 }
3318 
3319 #endif
3320 
3321 /*ARGSUSED*/
3322 CCRETVAL
3323 v_insbeg(c)
3324     int c;
3325 {				/* move to beginning of line and start vi
3326 				 * insert mode */
3327     USE(c);
3328     Cursor = InputBuf;
3329     InsertPos = Cursor;
3330 
3331     UndoPtr  = Cursor;
3332     UndoAction = TCSHOP_DELETE;
3333 
3334     RefCursor();		/* move the cursor */
3335     c_alternativ_key_map(0);
3336     return(CC_NORM);
3337 }
3338 
3339 /*ARGSUSED*/
3340 CCRETVAL
3341 v_replone(c)
3342     int c;
3343 {				/* vi mode overwrite one character */
3344     USE(c);
3345     c_alternativ_key_map(0);
3346     inputmode = MODE_REPLACE_1;
3347     UndoAction = TCSHOP_CHANGE;	/* Set Up for VI undo command */
3348     UndoPtr = Cursor;
3349     UndoSize = 0;
3350     return(CC_NORM);
3351 }
3352 
3353 /*ARGSUSED*/
3354 CCRETVAL
3355 v_replmode(c)
3356     int c;
3357 {				/* vi mode start overwriting */
3358     USE(c);
3359     c_alternativ_key_map(0);
3360     inputmode = MODE_REPLACE;
3361     UndoAction = TCSHOP_CHANGE;	/* Set Up for VI undo command */
3362     UndoPtr = Cursor;
3363     UndoSize = 0;
3364     return(CC_NORM);
3365 }
3366 
3367 /*ARGSUSED*/
3368 CCRETVAL
3369 v_substchar(c)
3370     int c;
3371 {				/* vi mode substitute for one char */
3372     USE(c);
3373     c_delafter(Argument);
3374     c_alternativ_key_map(0);
3375     return(CC_REFRESH);
3376 }
3377 
3378 /*ARGSUSED*/
3379 CCRETVAL
3380 v_substline(c)
3381     int c;
3382 {				/* vi mode replace whole line */
3383     USE(c);
3384     (void) e_killall(0);
3385     c_alternativ_key_map(0);
3386     return(CC_REFRESH);
3387 }
3388 
3389 /*ARGSUSED*/
3390 CCRETVAL
3391 v_chgtoend(c)
3392     int c;
3393 {				/* vi mode change to end of line */
3394     USE(c);
3395     (void) e_killend(0);
3396     c_alternativ_key_map(0);
3397     return(CC_REFRESH);
3398 }
3399 
3400 /*ARGSUSED*/
3401 CCRETVAL
3402 v_insert(c)
3403     int c;
3404 {				/* vi mode start inserting */
3405     USE(c);
3406     c_alternativ_key_map(0);
3407 
3408     InsertPos = Cursor;
3409     UndoPtr = Cursor;
3410     UndoAction = TCSHOP_DELETE;
3411 
3412     return(CC_NORM);
3413 }
3414 
3415 /*ARGSUSED*/
3416 CCRETVAL
3417 v_add(c)
3418     int c;
3419 {				/* vi mode start adding */
3420     USE(c);
3421     c_alternativ_key_map(0);
3422     if (Cursor < LastChar)
3423     {
3424 	Cursor++;
3425 	if (Cursor > LastChar)
3426 	    Cursor = LastChar;
3427 	RefCursor();
3428     }
3429 
3430     InsertPos = Cursor;
3431     UndoPtr = Cursor;
3432     UndoAction = TCSHOP_DELETE;
3433 
3434     return(CC_NORM);
3435 }
3436 
3437 /*ARGSUSED*/
3438 CCRETVAL
3439 v_addend(c)
3440     int c;
3441 {				/* vi mode to add at end of line */
3442     USE(c);
3443     c_alternativ_key_map(0);
3444     Cursor = LastChar;
3445 
3446     InsertPos = LastChar;	/* Mark where insertion begins */
3447     UndoPtr = LastChar;
3448     UndoAction = TCSHOP_DELETE;
3449 
3450     RefCursor();
3451     return(CC_NORM);
3452 }
3453 
3454 /*ARGSUSED*/
3455 CCRETVAL
3456 v_change_case(cc)
3457     int cc;
3458 {
3459     char    c;
3460 
3461     USE(cc);
3462     if (Cursor < LastChar) {
3463 #ifndef WINNT_NATIVE
3464 	c = *Cursor;
3465 #else
3466 	c = CHAR & *Cursor;
3467 #endif /* WINNT_NATIVE */
3468 	if (Isupper(c))
3469 	    *Cursor++ = Tolower(c);
3470 	else if (Islower(c))
3471 	    *Cursor++ = Toupper(c);
3472 	else
3473 	    Cursor++;
3474 	RefPlusOne();		/* fast refresh for one char */
3475 	return(CC_NORM);
3476     }
3477     return(CC_ERROR);
3478 }
3479 
3480 /*ARGSUSED*/
3481 CCRETVAL
3482 e_expand(c)
3483     int c;
3484 {
3485     Char *p;
3486     extern bool justpr;
3487 
3488     USE(c);
3489     for (p = InputBuf; Isspace(*p); p++)
3490 	continue;
3491     if (p == LastChar)
3492 	return(CC_ERROR);
3493 
3494     justpr++;
3495     Expand++;
3496     return(e_newline(0));
3497 }
3498 
3499 /*ARGSUSED*/
3500 CCRETVAL
3501 e_startover(c)
3502     int c;
3503 {				/* erase all of current line, start again */
3504     USE(c);
3505     ResetInLine(0);		/* reset the input pointers */
3506     return(CC_REFRESH);
3507 }
3508 
3509 /*ARGSUSED*/
3510 CCRETVAL
3511 e_redisp(c)
3512     int c;
3513 {
3514     USE(c);
3515     ClearLines();
3516     ClearDisp();
3517     return(CC_REFRESH);
3518 }
3519 
3520 /*ARGSUSED*/
3521 CCRETVAL
3522 e_cleardisp(c)
3523     int c;
3524 {
3525     USE(c);
3526     ClearScreen();		/* clear the whole real screen */
3527     ClearDisp();		/* reset everything */
3528     return(CC_REFRESH);
3529 }
3530 
3531 /*ARGSUSED*/
3532 CCRETVAL
3533 e_tty_int(c)
3534     int c;
3535 {
3536     USE(c);
3537 #if defined(_MINIX) || defined(WINNT_NATIVE)
3538     /* SAK PATCH: erase all of current line, start again */
3539     ResetInLine(0);		/* reset the input pointers */
3540     xputchar('\n');
3541     ClearDisp();
3542     return (CC_REFRESH);
3543 #else /* !_MINIX && !WINNT_NATIVE */
3544     /* do no editing */
3545     return (CC_NORM);
3546 #endif /* _MINIX || WINNT_NATIVE */
3547 }
3548 
3549 /*
3550  * From: ghazi@cesl.rutgers.edu (Kaveh R. Ghazi)
3551  * Function to send a character back to the input stream in cooked
3552  * mode. Only works if we have TIOCSTI
3553  */
3554 /*ARGSUSED*/
3555 CCRETVAL
3556 e_stuff_char(c)
3557      int c;
3558 {
3559 #ifdef TIOCSTI
3560      extern int Tty_raw_mode;
3561      int was_raw = Tty_raw_mode;
3562      char ch = (char) c;
3563 
3564      if (was_raw)
3565          (void) Cookedmode();
3566 
3567      (void) write(SHIN, "\n", 1);
3568      (void) ioctl(SHIN, TIOCSTI, (ioctl_t) &ch);
3569 
3570      if (was_raw)
3571          (void) Rawmode();
3572      return(e_redisp(c));
3573 #else /* !TIOCSTI */
3574      return(CC_ERROR);
3575 #endif /* !TIOCSTI */
3576 }
3577 
3578 /*ARGSUSED*/
3579 CCRETVAL
3580 e_insovr(c)
3581     int c;
3582 {
3583     USE(c);
3584     inputmode = (inputmode == MODE_INSERT ? MODE_REPLACE : MODE_INSERT);
3585     return(CC_NORM);
3586 }
3587 
3588 /*ARGSUSED*/
3589 CCRETVAL
3590 e_tty_dsusp(c)
3591     int c;
3592 {
3593     USE(c);
3594     /* do no editing */
3595     return(CC_NORM);
3596 }
3597 
3598 /*ARGSUSED*/
3599 CCRETVAL
3600 e_tty_flusho(c)
3601     int c;
3602 {
3603     USE(c);
3604     /* do no editing */
3605     return(CC_NORM);
3606 }
3607 
3608 /*ARGSUSED*/
3609 CCRETVAL
3610 e_tty_quit(c)
3611     int c;
3612 {
3613     USE(c);
3614     /* do no editing */
3615     return(CC_NORM);
3616 }
3617 
3618 /*ARGSUSED*/
3619 CCRETVAL
3620 e_tty_tsusp(c)
3621     int c;
3622 {
3623     USE(c);
3624     /* do no editing */
3625     return(CC_NORM);
3626 }
3627 
3628 /*ARGSUSED*/
3629 CCRETVAL
3630 e_tty_stopo(c)
3631     int c;
3632 {
3633     USE(c);
3634     /* do no editing */
3635     return(CC_NORM);
3636 }
3637 
3638 /*ARGSUSED*/
3639 CCRETVAL
3640 e_expand_history(c)
3641     int c;
3642 {
3643     USE(c);
3644     *LastChar = '\0';		/* just in case */
3645     c_substitute();
3646     return(CC_NORM);
3647 }
3648 
3649 /*ARGSUSED*/
3650 CCRETVAL
3651 e_magic_space(c)
3652     int c;
3653 {
3654     USE(c);
3655     *LastChar = '\0';		/* just in case */
3656     c_substitute();
3657     return(e_insert(' '));
3658 }
3659 
3660 /*ARGSUSED*/
3661 CCRETVAL
3662 e_inc_fwd(c)
3663     int c;
3664 {
3665     USE(c);
3666     patlen = 0;
3667     return e_inc_search(F_DOWN_SEARCH_HIST);
3668 }
3669 
3670 
3671 /*ARGSUSED*/
3672 CCRETVAL
3673 e_inc_back(c)
3674     int c;
3675 {
3676     USE(c);
3677     patlen = 0;
3678     return e_inc_search(F_UP_SEARCH_HIST);
3679 }
3680 
3681 /*ARGSUSED*/
3682 CCRETVAL
3683 e_copyprev(c)
3684     int c;
3685 {
3686     Char *cp, *oldc, *dp;
3687 
3688     USE(c);
3689     if (Cursor == InputBuf)
3690 	return(CC_ERROR);
3691     /* else */
3692 
3693     oldc = Cursor;
3694     /* does a bounds check */
3695     cp = c_prev_word(Cursor, InputBuf, Argument);
3696 
3697     c_insert((int)(oldc - cp));
3698     for (dp = oldc; cp < oldc && dp < LastChar; cp++)
3699 	*dp++ = *cp;
3700 
3701     Cursor = dp;		/* put cursor at end */
3702 
3703     return(CC_REFRESH);
3704 }
3705 
3706 /*ARGSUSED*/
3707 CCRETVAL
3708 e_tty_starto(c)
3709     int c;
3710 {
3711     USE(c);
3712     /* do no editing */
3713     return(CC_NORM);
3714 }
3715 
3716 /*ARGSUSED*/
3717 CCRETVAL
3718 e_load_average(c)
3719     int c;
3720 {
3721     USE(c);
3722     PastBottom();
3723 #ifdef TIOCSTAT
3724     /*
3725      * Here we pass &c to the ioctl because some os's (NetBSD) expect it
3726      * there even if they don't use it. (lukem@netbsd.org)
3727      */
3728     if (ioctl(SHIN, TIOCSTAT, (ioctl_t) &c) < 0)
3729 #endif
3730 	xprintf(CGETS(5, 1, "Load average unavailable\n"));
3731     return(CC_REFRESH);
3732 }
3733 
3734 /*ARGSUSED*/
3735 CCRETVAL
3736 v_chgmeta(c)
3737     int c;
3738 {
3739     USE(c);
3740     /*
3741      * Delete with insert == change: first we delete and then we leave in
3742      * insert mode.
3743      */
3744     return(v_action(TCSHOP_DELETE|TCSHOP_INSERT));
3745 }
3746 
3747 /*ARGSUSED*/
3748 CCRETVAL
3749 v_delmeta(c)
3750     int c;
3751 {
3752     USE(c);
3753     return(v_action(TCSHOP_DELETE));
3754 }
3755 
3756 
3757 /*ARGSUSED*/
3758 CCRETVAL
3759 v_endword(c)
3760     int c;
3761 {
3762     USE(c);
3763     if (Cursor == LastChar)
3764 	return(CC_ERROR);
3765     /* else */
3766 
3767     Cursor = c_endword(Cursor, LastChar, Argument, STRshwspace);
3768 
3769     if (ActionFlag & TCSHOP_DELETE)
3770     {
3771 	Cursor++;
3772 	c_delfini();
3773 	return(CC_REFRESH);
3774     }
3775 
3776     RefCursor();
3777     return(CC_NORM);
3778 }
3779 
3780 /*ARGSUSED*/
3781 CCRETVAL
3782 v_eword(c)
3783     int c;
3784 {
3785     USE(c);
3786     if (Cursor == LastChar)
3787 	return(CC_ERROR);
3788     /* else */
3789 
3790     Cursor = c_eword(Cursor, LastChar, Argument);
3791 
3792     if (ActionFlag & TCSHOP_DELETE) {
3793 	Cursor++;
3794 	c_delfini();
3795 	return(CC_REFRESH);
3796     }
3797 
3798     RefCursor();
3799     return(CC_NORM);
3800 }
3801 
3802 /*ARGSUSED*/
3803 CCRETVAL
3804 v_char_fwd(c)
3805     int c;
3806 {
3807     Char ch;
3808 
3809     USE(c);
3810     if (GetNextChar(&ch) != 1)
3811 	return e_send_eof(0);
3812 
3813     srch_dir = CHAR_FWD;
3814     srch_char = ch;
3815 
3816     return v_csearch_fwd(ch, Argument, 0);
3817 
3818 }
3819 
3820 /*ARGSUSED*/
3821 CCRETVAL
3822 v_char_back(c)
3823     int c;
3824 {
3825     Char ch;
3826 
3827     USE(c);
3828     if (GetNextChar(&ch) != 1)
3829 	return e_send_eof(0);
3830 
3831     srch_dir = CHAR_BACK;
3832     srch_char = ch;
3833 
3834     return v_csearch_back(ch, Argument, 0);
3835 }
3836 
3837 /*ARGSUSED*/
3838 CCRETVAL
3839 v_charto_fwd(c)
3840     int c;
3841 {
3842     Char ch;
3843 
3844     USE(c);
3845     if (GetNextChar(&ch) != 1)
3846 	return e_send_eof(0);
3847 
3848     return v_csearch_fwd(ch, Argument, 1);
3849 
3850 }
3851 
3852 /*ARGSUSED*/
3853 CCRETVAL
3854 v_charto_back(c)
3855     int c;
3856 {
3857     Char ch;
3858 
3859     USE(c);
3860     if (GetNextChar(&ch) != 1)
3861 	return e_send_eof(0);
3862 
3863     return v_csearch_back(ch, Argument, 1);
3864 }
3865 
3866 /*ARGSUSED*/
3867 CCRETVAL
3868 v_rchar_fwd(c)
3869     int c;
3870 {
3871     USE(c);
3872     if (srch_char == 0)
3873 	return CC_ERROR;
3874 
3875     return srch_dir == CHAR_FWD ? v_csearch_fwd(srch_char, Argument, 0) :
3876 			          v_csearch_back(srch_char, Argument, 0);
3877 }
3878 
3879 /*ARGSUSED*/
3880 CCRETVAL
3881 v_rchar_back(c)
3882     int c;
3883 {
3884     USE(c);
3885     if (srch_char == 0)
3886 	return CC_ERROR;
3887 
3888     return srch_dir == CHAR_BACK ? v_csearch_fwd(srch_char, Argument, 0) :
3889 			           v_csearch_back(srch_char, Argument, 0);
3890 }
3891 
3892 /*ARGSUSED*/
3893 CCRETVAL
3894 v_undo(c)
3895     int c;
3896 {
3897     int  loop;
3898     Char *kp, *cp;
3899     Char temp;
3900     int	 size;
3901 
3902     USE(c);
3903     switch (UndoAction) {
3904     case TCSHOP_DELETE|TCSHOP_INSERT:
3905     case TCSHOP_DELETE:
3906 	if (UndoSize == 0) return(CC_NORM);
3907 	cp = UndoPtr;
3908 	kp = UndoBuf;
3909 	for (loop=0; loop < UndoSize; loop++)	/* copy the chars */
3910 	    *kp++ = *cp++;			/* into UndoBuf   */
3911 
3912 	for (cp = UndoPtr; cp <= LastChar; cp++)
3913 	    *cp = cp[UndoSize];
3914 
3915 	LastChar -= UndoSize;
3916 	Cursor   =  UndoPtr;
3917 
3918 	UndoAction = TCSHOP_INSERT;
3919 	break;
3920 
3921     case TCSHOP_INSERT:
3922 	if (UndoSize == 0) return(CC_NORM);
3923 	cp = UndoPtr;
3924 	Cursor = UndoPtr;
3925 	kp = UndoBuf;
3926 	c_insert(UndoSize);		/* open the space, */
3927 	for (loop = 0; loop < UndoSize; loop++)	/* copy the chars */
3928 	    *cp++ = *kp++;
3929 
3930 	UndoAction = TCSHOP_DELETE;
3931 	break;
3932 
3933     case TCSHOP_CHANGE:
3934 	if (UndoSize == 0) return(CC_NORM);
3935 	cp = UndoPtr;
3936 	Cursor = UndoPtr;
3937 	kp = UndoBuf;
3938 	size = (int)(Cursor-LastChar); /*  NOT NSL independant */
3939 	if (size < UndoSize)
3940 	    size = UndoSize;
3941 	for(loop = 0; loop < size; loop++) {
3942 	    temp = *kp;
3943 	    *kp++ = *cp;
3944 	    *cp++ = temp;
3945 	}
3946 	break;
3947 
3948     default:
3949 	return(CC_ERROR);
3950     }
3951 
3952     return(CC_REFRESH);
3953 }
3954 
3955 /*ARGSUSED*/
3956 CCRETVAL
3957 v_ush_meta(c)
3958     int c;
3959 {
3960     USE(c);
3961     return v_search(F_UP_SEARCH_HIST);
3962 }
3963 
3964 /*ARGSUSED*/
3965 CCRETVAL
3966 v_dsh_meta(c)
3967     int c;
3968 {
3969     USE(c);
3970     return v_search(F_DOWN_SEARCH_HIST);
3971 }
3972 
3973 /*ARGSUSED*/
3974 CCRETVAL
3975 v_rsrch_fwd(c)
3976     int c;
3977 {
3978     USE(c);
3979     if (patlen == 0) return(CC_ERROR);
3980     return(v_repeat_srch(searchdir));
3981 }
3982 
3983 /*ARGSUSED*/
3984 CCRETVAL
3985 v_rsrch_back(c)
3986     int c;
3987 {
3988     USE(c);
3989     if (patlen == 0) return(CC_ERROR);
3990     return(v_repeat_srch(searchdir == F_UP_SEARCH_HIST ?
3991 			 F_DOWN_SEARCH_HIST : F_UP_SEARCH_HIST));
3992 }
3993 
3994 #ifndef WINNT_NATIVE
3995 /* Since ed.defns.h  is generated from ed.defns.c, these empty
3996    functions will keep the F_NUM_FNS consistent
3997  */
3998 CCRETVAL
3999 e_copy_to_clipboard(c)
4000     int c;
4001 {
4002     USE(c);
4003     return CC_ERROR;
4004 }
4005 
4006 CCRETVAL
4007 e_paste_from_clipboard(c)
4008     int c;
4009 {
4010     USE(c);
4011     return (CC_ERROR);
4012 }
4013 
4014 CCRETVAL
4015 e_dosify_next(c)
4016     int c;
4017 {
4018     USE(c);
4019     return (CC_ERROR);
4020 }
4021 CCRETVAL
4022 e_dosify_prev(c)
4023     int c;
4024 {
4025     USE(c);
4026     return (CC_ERROR);
4027 }
4028 CCRETVAL
4029 e_page_up(c)
4030     int c;
4031 {
4032     USE(c);
4033     return (CC_ERROR);
4034 }
4035 CCRETVAL
4036 e_page_down(c)
4037     int c;
4038 {
4039     USE(c);
4040     return (CC_ERROR);
4041 }
4042 #endif /* !WINNT_NATIVE */
4043 
4044 #ifdef notdef
4045 void
4046 MoveCursor(n)			/* move cursor + right - left char */
4047     int     n;
4048 {
4049     Cursor = Cursor + n;
4050     if (Cursor < InputBuf)
4051 	Cursor = InputBuf;
4052     if (Cursor > LastChar)
4053 	Cursor = LastChar;
4054     return;
4055 }
4056 
4057 Char *
4058 GetCursor()
4059 {
4060     return(Cursor);
4061 }
4062 
4063 int
4064 PutCursor(p)
4065     Char   *p;
4066 {
4067     if (p < InputBuf || p > LastChar)
4068 	return 1;		/* Error */
4069     Cursor = p;
4070     return 0;
4071 }
4072 #endif
4073