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