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