1232633Smp/* $Header: /p/tcsh/cvsroot/tcsh/ed.chared.c,v 3.98 2010/05/08 00:37:39 christos Exp $ */
259243Sobrien/*
359243Sobrien * ed.chared.c: Character editing functions.
459243Sobrien */
559243Sobrien/*-
659243Sobrien * Copyright (c) 1980, 1991 The Regents of the University of California.
759243Sobrien * All rights reserved.
859243Sobrien *
959243Sobrien * Redistribution and use in source and binary forms, with or without
1059243Sobrien * modification, are permitted provided that the following conditions
1159243Sobrien * are met:
1259243Sobrien * 1. Redistributions of source code must retain the above copyright
1359243Sobrien *    notice, this list of conditions and the following disclaimer.
1459243Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1559243Sobrien *    notice, this list of conditions and the following disclaimer in the
1659243Sobrien *    documentation and/or other materials provided with the distribution.
17100616Smp * 3. Neither the name of the University nor the names of its contributors
1859243Sobrien *    may be used to endorse or promote products derived from this software
1959243Sobrien *    without specific prior written permission.
2059243Sobrien *
2159243Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2259243Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2359243Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2459243Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2559243Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2659243Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2759243Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2859243Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2959243Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3059243Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3159243Sobrien * SUCH DAMAGE.
3259243Sobrien */
3359243Sobrien/*
3459243Sobrien  Bjorn Knutsson @ Thu Jun 24 19:02:17 1999
3559243Sobrien
3659243Sobrien  e_dabbrev_expand() did not do proper completion if quoted spaces were present
3759243Sobrien  in the string being completed. Exemple:
3859243Sobrien
3959243Sobrien  # echo hello\ world
4059243Sobrien  hello world
4159243Sobrien  # echo h<press key bound to dabbrev-expande>
4259243Sobrien  # echo hello\<cursor>
4359243Sobrien
4459243Sobrien  Correct behavior is:
4559243Sobrien  # echo h<press key bound to dabbrev-expande>
4659243Sobrien  # echo hello\ world<cursor>
4759243Sobrien
4859243Sobrien  The same problem occured if spaces were present in a string withing quotation
4959243Sobrien  marks. Example:
5059243Sobrien
5159243Sobrien  # echo "hello world"
5259243Sobrien  hello world
5359243Sobrien  # echo "h<press key bound to dabbrev-expande>
5459243Sobrien  # echo "hello<cursor>
5559243Sobrien
5659243Sobrien  The former problem could be solved with minor modifications of c_preword()
5759243Sobrien  and c_endword(). The latter, however, required a significant rewrite of
5859243Sobrien  c_preword(), since quoted strings must be parsed from start to end to
5959243Sobrien  determine if a given character is inside or outside the quotation marks.
6059243Sobrien
6159243Sobrien  Compare the following two strings:
6259243Sobrien
6359243Sobrien  # echo \"" 'foo \' bar\"
6459243Sobrien  " 'foo \' bar\
6559243Sobrien  # echo '\"" 'foo \' bar\"
6659243Sobrien  \"" foo ' bar"
6759243Sobrien
6859243Sobrien  The only difference between the two echo lines is in the first character
6959243Sobrien  after the echo command. The result is either one or three arguments.
7059243Sobrien
7159243Sobrien */
7259243Sobrien
7359243Sobrien#include "sh.h"
7459243Sobrien
75232633SmpRCSID("$tcsh: ed.chared.c,v 3.98 2010/05/08 00:37:39 christos Exp $")
7659243Sobrien
7759243Sobrien#include "ed.h"
7859243Sobrien#include "tw.h"
7959243Sobrien#include "ed.defns.h"
8059243Sobrien
8159243Sobrien/* #define SDEBUG */
8259243Sobrien
8359243Sobrien#define TCSHOP_NOP    	  0x00
8459243Sobrien#define TCSHOP_DELETE 	  0x01
8559243Sobrien#define TCSHOP_INSERT 	  0x02
8659243Sobrien#define TCSHOP_CHANGE 	  0x04
8759243Sobrien
8859243Sobrien#define CHAR_FWD	0
8959243Sobrien#define CHAR_BACK	1
9059243Sobrien
9159243Sobrien/*
9259243Sobrien * vi word treatment
9359243Sobrien * from: Gert-Jan Vons <vons@cesar.crbca1.sinet.slb.com>
9459243Sobrien */
9559243Sobrien#define C_CLASS_WHITE	1
9659243Sobrien#define C_CLASS_ALNUM	2
9759243Sobrien#define C_CLASS_OTHER	3
9859243Sobrien
9959243Sobrienstatic Char *InsertPos = InputBuf; /* Where insertion starts */
10059243Sobrienstatic Char *ActionPos = 0;	   /* Where action begins  */
10159243Sobrienstatic int  ActionFlag = TCSHOP_NOP;	   /* What delayed action to take */
10259243Sobrien/*
10359243Sobrien * Word search state
10459243Sobrien */
10559243Sobrienstatic int  searchdir = F_UP_SEARCH_HIST; 	/* Direction of last search */
106167465Smpstatic struct Strbuf patbuf; /* = Strbuf_INIT; Search target */
10759243Sobrien/*
10859243Sobrien * Char search state
10959243Sobrien */
11059243Sobrienstatic int  srch_dir = CHAR_FWD;		/* Direction of last search */
11159243Sobrienstatic Char srch_char = 0;			/* Search target */
11259243Sobrien
11359243Sobrien/* all routines that start with c_ are private to this set of routines */
114167465Smpstatic	void	 c_alternativ_key_map	(int);
115167465Smpvoid	 c_insert		(int);
116167465Smpvoid	 c_delafter		(int);
117167465Smpvoid	 c_delbefore		(int);
118167465Smpstatic 	int	 c_to_class		(Char);
119167465Smpstatic	Char	*c_prev_word		(Char *, Char *, int);
120167465Smpstatic	Char	*c_next_word		(Char *, Char *, int);
121167465Smpstatic	Char	*c_number		(Char *, int *, int);
122167465Smpstatic	Char	*c_expand		(Char *);
123195609Smpstatic	int	 c_excl			(Char *);
124195609Smpstatic	int	 c_substitute		(void);
125167465Smpstatic	void	 c_delfini		(void);
126167465Smpstatic	int	 c_hmatch		(Char *);
127167465Smpstatic	void	 c_hsetpat		(void);
12859243Sobrien#ifdef COMMENT
129167465Smpstatic	void	 c_get_word		(Char **, Char **);
13059243Sobrien#endif
131167465Smpstatic	Char	*c_preword		(Char *, Char *, int, Char *);
132167465Smpstatic	Char	*c_nexword		(Char *, Char *, int);
133167465Smpstatic	Char	*c_endword		(Char *, Char *, int, Char *);
134167465Smpstatic	Char	*c_eword		(Char *, Char *, int);
135167465Smpstatic	void	 c_push_kill		(Char *, Char *);
136167465Smpstatic	void	 c_save_inputbuf	(void);
137167465Smpstatic  CCRETVAL c_search_line		(Char *, int);
138167465Smpstatic  CCRETVAL v_repeat_srch		(int);
139167465Smpstatic	CCRETVAL e_inc_search		(int);
140167465Smp#ifdef notyet
141167465Smpstatic  CCRETVAL e_insert_str		(Char *);
142167465Smp#endif
143167465Smpstatic	CCRETVAL v_search		(int);
144167465Smpstatic	CCRETVAL v_csearch_fwd		(Char, int, int);
145167465Smpstatic	CCRETVAL v_action		(int);
146167465Smpstatic	CCRETVAL v_csearch_back		(Char, int, int);
14759243Sobrien
14859243Sobrienstatic void
149167465Smpc_alternativ_key_map(int state)
15059243Sobrien{
15159243Sobrien    switch (state) {
15259243Sobrien    case 0:
15359243Sobrien	CurrentKeyMap = CcKeyMap;
15459243Sobrien	break;
15559243Sobrien    case 1:
15659243Sobrien	CurrentKeyMap = CcAltMap;
15759243Sobrien	break;
15859243Sobrien    default:
15959243Sobrien	return;
16059243Sobrien    }
16159243Sobrien
16259243Sobrien    AltKeyMap = (Char) state;
16359243Sobrien}
16459243Sobrien
16583098Smpvoid
166167465Smpc_insert(int num)
16759243Sobrien{
16883098Smp    Char *cp;
16959243Sobrien
17059243Sobrien    if (LastChar + num >= InputLim)
17159243Sobrien	return;			/* can't go past end of buffer */
17259243Sobrien
17359243Sobrien    if (Cursor < LastChar) {	/* if I must move chars */
17459243Sobrien	for (cp = LastChar; cp >= Cursor; cp--)
17559243Sobrien	    cp[num] = *cp;
176145479Smp	if (Mark && Mark > Cursor)
177145479Smp		Mark += num;
17859243Sobrien    }
17959243Sobrien    LastChar += num;
18059243Sobrien}
18159243Sobrien
18269408Sachevoid
183167465Smpc_delafter(int num)
18459243Sobrien{
18583098Smp    Char *cp, *kp = NULL;
18659243Sobrien
18759243Sobrien    if (num > LastChar - Cursor)
18859243Sobrien	num = (int) (LastChar - Cursor);	/* bounds check */
18959243Sobrien
19059243Sobrien    if (num > 0) {			/* if I can delete anything */
19159243Sobrien	if (VImode) {
19259243Sobrien	    kp = UndoBuf;		/* Set Up for VI undo command */
19359243Sobrien	    UndoAction = TCSHOP_INSERT;
19459243Sobrien	    UndoSize = num;
19559243Sobrien	    UndoPtr  = Cursor;
19659243Sobrien	    for (cp = Cursor; cp <= LastChar; cp++) {
19759243Sobrien		*kp++ = *cp;	/* Save deleted chars into undobuf */
19859243Sobrien		*cp = cp[num];
19959243Sobrien	    }
20059243Sobrien	}
20159243Sobrien	else
202145479Smp	    for (cp = Cursor; cp + num <= LastChar; cp++)
20359243Sobrien		*cp = cp[num];
20459243Sobrien	LastChar -= num;
205167465Smp	/* Mark was within the range of the deleted word? */
206167465Smp	if (Mark && Mark > Cursor && Mark <= Cursor+num)
207167465Smp		Mark = Cursor;
208167465Smp	/* Mark after the deleted word? */
209167465Smp	else if (Mark && Mark > Cursor)
210145479Smp		Mark -= num;
21159243Sobrien    }
21259243Sobrien#ifdef notdef
21359243Sobrien    else {
21459243Sobrien	/*
21559243Sobrien	 * XXX: We don't want to do that. In emacs mode overwrite should be
21659243Sobrien	 * sticky. I am not sure how that affects vi mode
21759243Sobrien	 */
21859243Sobrien	inputmode = MODE_INSERT;
21959243Sobrien    }
22059243Sobrien#endif /* notdef */
22159243Sobrien}
22259243Sobrien
22369408Sachevoid
224167465Smpc_delbefore(int num)		/* delete before dot, with bounds checking */
22559243Sobrien{
22683098Smp    Char *cp, *kp = NULL;
22759243Sobrien
22859243Sobrien    if (num > Cursor - InputBuf)
22959243Sobrien	num = (int) (Cursor - InputBuf);	/* bounds check */
23059243Sobrien
23159243Sobrien    if (num > 0) {			/* if I can delete anything */
23259243Sobrien	if (VImode) {
23359243Sobrien	    kp = UndoBuf;		/* Set Up for VI undo command */
23459243Sobrien	    UndoAction = TCSHOP_INSERT;
23559243Sobrien	    UndoSize = num;
23659243Sobrien	    UndoPtr  = Cursor - num;
23759243Sobrien	    for (cp = Cursor - num; cp <= LastChar; cp++) {
23859243Sobrien		*kp++ = *cp;
23959243Sobrien		*cp = cp[num];
24059243Sobrien	    }
24159243Sobrien	}
24259243Sobrien	else
243145479Smp	    for (cp = Cursor - num; cp + num <= LastChar; cp++)
24459243Sobrien		*cp = cp[num];
24559243Sobrien	LastChar -= num;
246145479Smp	Cursor -= num;
247167465Smp	/* Mark was within the range of the deleted word? */
248167465Smp	if (Mark && Mark > Cursor && Mark <= Cursor+num)
249167465Smp		Mark = Cursor;
250167465Smp	/* Mark after the deleted word? */
251167465Smp	else if (Mark && Mark > Cursor)
252145479Smp		Mark -= num;
25359243Sobrien    }
25459243Sobrien}
25559243Sobrien
25659243Sobrienstatic Char *
257167465Smpc_preword(Char *p, Char *low, int n, Char *delim)
25859243Sobrien{
25959243Sobrien  while (n--) {
26083098Smp    Char *prev = low;
26183098Smp    Char *new;
26259243Sobrien
26383098Smp    while (prev < p) {		/* Skip initial non-word chars */
26483098Smp      if (!Strchr(delim, *prev) || *(prev-1) == (Char)'\\')
26559243Sobrien	break;
26659243Sobrien      prev++;
26759243Sobrien    }
26859243Sobrien
26959243Sobrien    new = prev;
27059243Sobrien
27159243Sobrien    while (new < p) {
27259243Sobrien      prev = new;
27383098Smp      new = c_endword(prev-1, p, 1, delim); /* Skip to next non-word char */
27459243Sobrien      new++;			/* Step away from end of word */
27583098Smp      while (new <= p) {	/* Skip trailing non-word chars */
27683098Smp	if (!Strchr(delim, *new) || *(new-1) == (Char)'\\')
27759243Sobrien	  break;
27859243Sobrien	new++;
27959243Sobrien      }
28059243Sobrien    }
28159243Sobrien
28259243Sobrien    p = prev;			/* Set to previous word start */
28359243Sobrien
28459243Sobrien  }
28559243Sobrien  if (p < low)
28659243Sobrien    p = low;
28759243Sobrien  return (p);
28859243Sobrien}
28959243Sobrien
29059243Sobrien/*
29159243Sobrien * c_to_class() returns the class of the given character.
29259243Sobrien *
29359243Sobrien * This is used to make the c_prev_word() and c_next_word() functions
29459243Sobrien * work like vi's, which classify characters. A word is a sequence of
29559243Sobrien * characters belonging to the same class, classes being defined as
29659243Sobrien * follows:
29759243Sobrien *
29859243Sobrien *	1/ whitespace
29959243Sobrien *	2/ alphanumeric chars, + underscore
30059243Sobrien *	3/ others
30159243Sobrien */
30259243Sobrienstatic int
303167465Smpc_to_class(Char ch)
30459243Sobrien{
30559243Sobrien    if (Isspace(ch))
30659243Sobrien        return C_CLASS_WHITE;
30759243Sobrien
30859243Sobrien    if (Isdigit(ch) || Isalpha(ch) || ch == '_')
30959243Sobrien        return C_CLASS_ALNUM;
31059243Sobrien
31159243Sobrien    return C_CLASS_OTHER;
31259243Sobrien}
31359243Sobrien
31459243Sobrienstatic Char *
315167465Smpc_prev_word(Char *p, Char *low, int n)
31659243Sobrien{
31759243Sobrien    p--;
31859243Sobrien
31959243Sobrien    if (!VImode) {
32059243Sobrien	while (n--) {
32159243Sobrien	    while ((p >= low) && !isword(*p))
32259243Sobrien		p--;
32359243Sobrien	    while ((p >= low) && isword(*p))
32459243Sobrien		p--;
32559243Sobrien	}
32659243Sobrien
32759243Sobrien	/* cp now points to one character before the word */
32859243Sobrien	p++;
32959243Sobrien	if (p < low)
33059243Sobrien	    p = low;
33159243Sobrien	/* cp now points where we want it */
33259243Sobrien	return(p);
33359243Sobrien    }
33459243Sobrien
33559243Sobrien    while (n--) {
33683098Smp        int  c_class;
33759243Sobrien
33859243Sobrien        if (p < low)
33959243Sobrien            break;
34059243Sobrien
34159243Sobrien        /* scan until beginning of current word (may be all whitespace!) */
34259243Sobrien        c_class = c_to_class(*p);
34359243Sobrien        while ((p >= low) && c_class == c_to_class(*p))
34459243Sobrien            p--;
34559243Sobrien
34659243Sobrien        /* if this was a non_whitespace word, we're ready */
34759243Sobrien        if (c_class != C_CLASS_WHITE)
34859243Sobrien            continue;
34959243Sobrien
35059243Sobrien        /* otherwise, move back to beginning of the word just found */
35159243Sobrien        c_class = c_to_class(*p);
35259243Sobrien        while ((p >= low) && c_class == c_to_class(*p))
35359243Sobrien            p--;
35459243Sobrien    }
35559243Sobrien
35659243Sobrien    p++;                        /* correct overshoot */
35759243Sobrien
35859243Sobrien    return (p);
35959243Sobrien}
36059243Sobrien
36159243Sobrienstatic Char *
362167465Smpc_next_word(Char *p, Char *high, int n)
36359243Sobrien{
36459243Sobrien    if (!VImode) {
36559243Sobrien	while (n--) {
36659243Sobrien	    while ((p < high) && !isword(*p))
36759243Sobrien		p++;
36859243Sobrien	    while ((p < high) && isword(*p))
36959243Sobrien		p++;
37059243Sobrien	}
37159243Sobrien	if (p > high)
37259243Sobrien	    p = high;
37359243Sobrien	/* p now points where we want it */
37459243Sobrien	return(p);
37559243Sobrien    }
37659243Sobrien
37759243Sobrien    while (n--) {
37883098Smp        int  c_class;
37959243Sobrien
38059243Sobrien        if (p >= high)
38159243Sobrien            break;
38259243Sobrien
38359243Sobrien        /* scan until end of current word (may be all whitespace!) */
38459243Sobrien        c_class = c_to_class(*p);
38559243Sobrien        while ((p < high) && c_class == c_to_class(*p))
38659243Sobrien            p++;
38759243Sobrien
38859243Sobrien        /* if this was all whitespace, we're ready */
38959243Sobrien        if (c_class == C_CLASS_WHITE)
39059243Sobrien            continue;
39159243Sobrien
39259243Sobrien	/* if we've found white-space at the end of the word, skip it */
39359243Sobrien        while ((p < high) && c_to_class(*p) == C_CLASS_WHITE)
39459243Sobrien            p++;
39559243Sobrien    }
39659243Sobrien
39759243Sobrien    p--;                        /* correct overshoot */
39859243Sobrien
39959243Sobrien    return (p);
40059243Sobrien}
40159243Sobrien
40259243Sobrienstatic Char *
403167465Smpc_nexword(Char *p, Char *high, int n)
40459243Sobrien{
40559243Sobrien    while (n--) {
40659243Sobrien	while ((p < high) && !Isspace(*p))
40759243Sobrien	    p++;
40859243Sobrien	while ((p < high) && Isspace(*p))
40959243Sobrien	    p++;
41059243Sobrien    }
41159243Sobrien
41259243Sobrien    if (p > high)
41359243Sobrien	p = high;
41459243Sobrien    /* p now points where we want it */
41559243Sobrien    return(p);
41659243Sobrien}
41759243Sobrien
41859243Sobrien/*
41959243Sobrien * Expand-History (originally "Magic-Space") code added by
42059243Sobrien * Ray Moody <ray@gibbs.physics.purdue.edu>
42159243Sobrien * this is a neat, but odd, addition.
42259243Sobrien */
42359243Sobrien
42459243Sobrien/*
42559243Sobrien * c_number: Ignore character p points to, return number appearing after that.
42659243Sobrien * A '$' by itself means a big number; "$-" is for negative; '^' means 1.
42759243Sobrien * Return p pointing to last char used.
42859243Sobrien */
42959243Sobrien
43059243Sobrien/*
43159243Sobrien * dval is the number to subtract from for things like $-3
43259243Sobrien */
43359243Sobrien
43459243Sobrienstatic Char *
435167465Smpc_number(Char *p, int *num, int dval)
43659243Sobrien{
43783098Smp    int i;
43883098Smp    int sign = 1;
43959243Sobrien
44059243Sobrien    if (*++p == '^') {
44159243Sobrien	*num = 1;
44259243Sobrien	return(p);
44359243Sobrien    }
44459243Sobrien    if (*p == '$') {
44559243Sobrien	if (*++p != '-') {
446167465Smp	    *num = INT_MAX;	/* Handle $ */
44759243Sobrien	    return(--p);
44859243Sobrien	}
44959243Sobrien	sign = -1;		/* Handle $- */
45059243Sobrien	++p;
45159243Sobrien    }
45259243Sobrien    for (i = 0; *p >= '0' && *p <= '9'; i = 10 * i + *p++ - '0')
45359243Sobrien	continue;
45459243Sobrien    *num = (sign < 0 ? dval - i : i);
45559243Sobrien    return(--p);
45659243Sobrien}
45759243Sobrien
45859243Sobrien/*
45959243Sobrien * excl_expand: There is an excl to be expanded to p -- do the right thing
46059243Sobrien * with it and return a version of p advanced over the expanded stuff.  Also,
46159243Sobrien * update tsh_cur and related things as appropriate...
46259243Sobrien */
46359243Sobrien
46459243Sobrienstatic Char *
465167465Smpc_expand(Char *p)
46659243Sobrien{
46783098Smp    Char *q;
46883098Smp    struct Hist *h = Histlist.Hnext;
46983098Smp    struct wordent *l;
47059243Sobrien    int     i, from, to, dval;
471145479Smp    int    all_dig;
472145479Smp    int    been_once = 0;
47359243Sobrien    Char   *op = p;
474167465Smp    Char   *buf;
475167465Smp    size_t buf_len;
476167465Smp    Char   *modbuf;
47759243Sobrien
478167465Smp    buf = NULL;
47959243Sobrien    if (!h)
48059243Sobrien	goto excl_err;
48159243Sobrienexcl_sw:
48259243Sobrien    switch (*(q = p + 1)) {
48359243Sobrien
48459243Sobrien    case '^':
485167465Smp	buf = expand_lex(&h->Hlex, 1, 1);
48659243Sobrien	break;
48759243Sobrien
48859243Sobrien    case '$':
48959243Sobrien	if ((l = (h->Hlex).prev) != 0)
490167465Smp	    buf = expand_lex(l->prev->prev, 0, 0);
49159243Sobrien	break;
49259243Sobrien
49359243Sobrien    case '*':
494167465Smp	buf = expand_lex(&h->Hlex, 1, INT_MAX);
49559243Sobrien	break;
49659243Sobrien
49759243Sobrien    default:
49859243Sobrien	if (been_once) {	/* unknown argument */
49959243Sobrien	    /* assume it's a modifier, e.g. !foo:h, and get whole cmd */
500167465Smp	    buf = expand_lex(&h->Hlex, 0, INT_MAX);
50159243Sobrien	    q -= 2;
50259243Sobrien	    break;
50359243Sobrien	}
50459243Sobrien	been_once = 1;
50559243Sobrien
50659243Sobrien	if (*q == ':')		/* short form: !:arg */
50759243Sobrien	    --q;
50859243Sobrien
509232633Smp	if (HIST != '\0' && *q != HIST) {
51059243Sobrien	    /*
51159243Sobrien	     * Search for a space, tab, or colon.  See if we have a number (as
51259243Sobrien	     * in !1234:xyz).  Remember the number.
51359243Sobrien	     */
51459243Sobrien	    for (i = 0, all_dig = 1;
51559243Sobrien		 *q != ' ' && *q != '\t' && *q != ':' && q < Cursor; q++) {
51659243Sobrien		/*
51759243Sobrien		 * PWP: !-4 is a valid history argument too, therefore the test
51859243Sobrien		 * is if not a digit, or not a - as the first character.
51959243Sobrien		 */
52059243Sobrien		if ((*q < '0' || *q > '9') && (*q != '-' || q != p + 1))
52159243Sobrien		    all_dig = 0;
52259243Sobrien		else if (*q == '-')
52359243Sobrien		    all_dig = 2;/* we are sneeky about this */
52459243Sobrien		else
52559243Sobrien		    i = 10 * i + *q - '0';
52659243Sobrien	    }
52759243Sobrien	    --q;
52859243Sobrien
52959243Sobrien	    /*
53059243Sobrien	     * If we have a number, search for event i.  Otherwise, search for
53159243Sobrien	     * a named event (as in !foo).  (In this case, I is the length of
53259243Sobrien	     * the named event).
53359243Sobrien	     */
53459243Sobrien	    if (all_dig) {
53559243Sobrien		if (all_dig == 2)
53659243Sobrien		    i = -i;	/* make it negitive */
53759243Sobrien		if (i < 0)	/* if !-4 (for example) */
53859243Sobrien		    i = eventno + 1 + i;	/* remember: i is < 0 */
53959243Sobrien		for (; h; h = h->Hnext) {
54059243Sobrien		    if (h->Hnum == i)
54159243Sobrien			break;
54259243Sobrien		}
54359243Sobrien	    }
54459243Sobrien	    else {
54559243Sobrien		for (i = (int) (q - p); h; h = h->Hnext) {
54659243Sobrien		    if ((l = &h->Hlex) != 0) {
54759243Sobrien			if (!Strncmp(p + 1, l->next->word, (size_t) i))
54859243Sobrien			    break;
54959243Sobrien		    }
55059243Sobrien		}
55159243Sobrien	    }
55259243Sobrien	}
55359243Sobrien	if (!h)
55459243Sobrien	    goto excl_err;
55559243Sobrien	if (q[1] == ':' || q[1] == '-' || q[1] == '*' ||
55659243Sobrien	    q[1] == '$' || q[1] == '^') {	/* get some args */
55759243Sobrien	    p = q[1] == ':' ? ++q : q;
55859243Sobrien	    /*
55959243Sobrien	     * Go handle !foo:*
56059243Sobrien	     */
56159243Sobrien	    if ((q[1] < '0' || q[1] > '9') &&
56259243Sobrien		q[1] != '-' && q[1] != '$' && q[1] != '^')
56359243Sobrien		goto excl_sw;
56459243Sobrien	    /*
56559243Sobrien	     * Go handle !foo:$
56659243Sobrien	     */
56759243Sobrien	    if (q[1] == '$' && (q[2] != '-' || q[3] < '0' || q[3] > '9'))
56859243Sobrien		goto excl_sw;
56959243Sobrien	    /*
57059243Sobrien	     * Count up the number of words in this event.  Store it in dval.
57159243Sobrien	     * Dval will be fed to number.
57259243Sobrien	     */
57359243Sobrien	    dval = 0;
57459243Sobrien	    if ((l = h->Hlex.prev) != 0) {
57559243Sobrien		for (l = l->prev; l != h->Hlex.next; l = l->prev, dval++)
57659243Sobrien		    continue;
57759243Sobrien	    }
57859243Sobrien	    if (!dval)
57959243Sobrien		goto excl_err;
58059243Sobrien	    if (q[1] == '-')
58159243Sobrien		from = 0;
58259243Sobrien	    else
58359243Sobrien		q = c_number(q, &from, dval);
58459243Sobrien	    if (q[1] == '-') {
58559243Sobrien		++q;
58659243Sobrien		if ((q[1] < '0' || q[1] > '9') && q[1] != '$')
58759243Sobrien		    to = dval - 1;
58859243Sobrien		else
58959243Sobrien		    q = c_number(q, &to, dval);
59059243Sobrien	    }
59159243Sobrien	    else if (q[1] == '*') {
59259243Sobrien		++q;
593167465Smp		to = INT_MAX;
59459243Sobrien	    }
59559243Sobrien	    else {
59659243Sobrien		to = from;
59759243Sobrien	    }
59859243Sobrien	    if (from < 0 || to < from)
59959243Sobrien		goto excl_err;
600167465Smp	    buf = expand_lex(&h->Hlex, from, to);
60159243Sobrien	}
602167465Smp	else			/* get whole cmd */
603167465Smp	    buf = expand_lex(&h->Hlex, 0, INT_MAX);
60459243Sobrien	break;
60559243Sobrien    }
606167465Smp    if (buf == NULL)
607167465Smp	buf = SAVE("");
60859243Sobrien
60959243Sobrien    /*
61059243Sobrien     * Apply modifiers, if any.
61159243Sobrien     */
61259243Sobrien    if (q[1] == ':') {
613167465Smp	modbuf = buf;
61459243Sobrien	while (q[1] == ':' && modbuf != NULL) {
61559243Sobrien	    switch (q[2]) {
61659243Sobrien	    case 'r':
61759243Sobrien	    case 'e':
61859243Sobrien	    case 'h':
61959243Sobrien	    case 't':
62059243Sobrien	    case 'q':
62159243Sobrien	    case 'x':
62259243Sobrien	    case 'u':
62359243Sobrien	    case 'l':
624167465Smp		if ((modbuf = domod(buf, (int) q[2])) != NULL) {
625167465Smp		    xfree(buf);
626167465Smp		    buf = modbuf;
62759243Sobrien		}
62859243Sobrien		++q;
62959243Sobrien		break;
63059243Sobrien
63159243Sobrien	    case 'a':
63259243Sobrien	    case 'g':
63359243Sobrien		/* Not implemented; this needs to be done before expanding
63459243Sobrien		 * lex. We don't have the words available to us anymore.
63559243Sobrien		 */
63659243Sobrien		++q;
63759243Sobrien		break;
63859243Sobrien
63959243Sobrien	    case 'p':
64059243Sobrien		/* Ok */
64159243Sobrien		++q;
64259243Sobrien		break;
64359243Sobrien
64459243Sobrien	    case '\0':
64559243Sobrien		break;
64659243Sobrien
64759243Sobrien	    default:
64859243Sobrien		++q;
64959243Sobrien		break;
65059243Sobrien	    }
65159243Sobrien	    if (q[1])
65259243Sobrien		++q;
65359243Sobrien	}
65459243Sobrien    }
65559243Sobrien
656167465Smp    buf_len = Strlen(buf);
65759243Sobrien    /*
658167465Smp     * Now replace the text from op to q inclusive with the text from buf.
65959243Sobrien     */
66059243Sobrien    q++;
66159243Sobrien
66259243Sobrien    /*
66359243Sobrien     * Now replace text non-inclusively like a real CS major!
66459243Sobrien     */
665167465Smp    if (LastChar + buf_len - (q - op) >= InputLim)
66659243Sobrien	goto excl_err;
667167465Smp    (void) memmove(op + buf_len, q, (LastChar - q) * sizeof(Char));
668167465Smp    LastChar += buf_len - (q - op);
669167465Smp    Cursor += buf_len - (q - op);
670167465Smp    (void) memcpy(op, buf, buf_len * sizeof(Char));
67159243Sobrien    *LastChar = '\0';
672167465Smp    xfree(buf);
673167465Smp    return op + buf_len;
67459243Sobrienexcl_err:
675167465Smp    xfree(buf);
67659243Sobrien    SoundBeep();
67759243Sobrien    return(op + 1);
67859243Sobrien}
67959243Sobrien
68059243Sobrien/*
68159243Sobrien * c_excl: An excl has been found at point p -- back up and find some white
68259243Sobrien * space (or the beginning of the buffer) and properly expand all the excl's
68359243Sobrien * from there up to the current cursor position. We also avoid (trying to)
68459243Sobrien * expanding '>!'
685195609Smp * Returns number of expansions attempted (doesn't matter whether they succeeded
686195609Smp * or not).
68759243Sobrien */
68859243Sobrien
689195609Smpstatic int
690167465Smpc_excl(Char *p)
69159243Sobrien{
69283098Smp    int i;
69383098Smp    Char *q;
694195609Smp    int nr_exp;
69559243Sobrien
69659243Sobrien    /*
69759243Sobrien     * if />[SPC TAB]*![SPC TAB]/, back up p to just after the >. otherwise,
69859243Sobrien     * back p up to just before the current word.
69959243Sobrien     */
70059243Sobrien    if ((p[1] == ' ' || p[1] == '\t') &&
70159243Sobrien	(p[-1] == ' ' || p[-1] == '\t' || p[-1] == '>')) {
70259243Sobrien	for (q = p - 1; q > InputBuf && (*q == ' ' || *q == '\t'); --q)
70359243Sobrien	    continue;
70459243Sobrien	if (*q == '>')
70559243Sobrien	    ++p;
70659243Sobrien    }
70759243Sobrien    else {
70859243Sobrien	while (*p != ' ' && *p != '\t' && p > InputBuf)
70959243Sobrien	    --p;
71059243Sobrien    }
71159243Sobrien
71259243Sobrien    /*
71359243Sobrien     * Forever: Look for history char.  (Stop looking when we find the cursor.)
714195609Smp     * Count backslashes.  If odd, skip history char.  Expand if even number of
715195609Smp     * backslashes.
71659243Sobrien     */
717195609Smp    nr_exp = 0;
71859243Sobrien    for (;;) {
719232633Smp	if (HIST != '\0')
720232633Smp	    while (*p != HIST && p < Cursor)
721232633Smp		++p;
72259243Sobrien	for (i = 1; (p - i) >= InputBuf && p[-i] == '\\'; i++)
72359243Sobrien	    continue;
72459243Sobrien	if (i % 2 == 0)
72559243Sobrien	    ++p;
726195609Smp	if (p >= Cursor)   /* all done */
727195609Smp	    return nr_exp;
728195609Smp	if (i % 2 == 1) {
72959243Sobrien	    p = c_expand(p);
730195609Smp	    ++nr_exp;
731195609Smp	}
73259243Sobrien    }
73359243Sobrien}
73459243Sobrien
73559243Sobrien
736195609Smpstatic int
737167465Smpc_substitute(void)
73859243Sobrien{
73983098Smp    Char *p;
740195609Smp    int  nr_exp;
74159243Sobrien
74259243Sobrien    /*
74359243Sobrien     * Start p out one character before the cursor.  Move it backwards looking
74459243Sobrien     * for white space, the beginning of the line, or a history character.
74559243Sobrien     */
74659243Sobrien    for (p = Cursor - 1;
747232633Smp	 p > InputBuf && *p != ' ' && *p != '\t' && *p && *p != HIST; --p)
74859243Sobrien	continue;
74959243Sobrien
75059243Sobrien    /*
75159243Sobrien     * If we found a history character, go expand it.
75259243Sobrien     */
753232633Smp    if (HIST != '\0' && *p == HIST)
754195609Smp	nr_exp = c_excl(p);
755195609Smp    else
756195609Smp        nr_exp = 0;
75759243Sobrien    Refresh();
758195609Smp
759195609Smp    return nr_exp;
76059243Sobrien}
76159243Sobrien
76259243Sobrienstatic void
763167465Smpc_delfini(void)		/* Finish up delete action */
76459243Sobrien{
76583098Smp    int Size;
76659243Sobrien
76759243Sobrien    if (ActionFlag & TCSHOP_INSERT)
76859243Sobrien	c_alternativ_key_map(0);
76959243Sobrien
77059243Sobrien    ActionFlag = TCSHOP_NOP;
77159243Sobrien
77259243Sobrien    if (ActionPos == 0)
77359243Sobrien	return;
77459243Sobrien
77559243Sobrien    UndoAction = TCSHOP_INSERT;
77659243Sobrien
77759243Sobrien    if (Cursor > ActionPos) {
77859243Sobrien	Size = (int) (Cursor-ActionPos);
77959243Sobrien	c_delbefore(Size);
78059243Sobrien	RefCursor();
78159243Sobrien    }
78259243Sobrien    else if (Cursor < ActionPos) {
78359243Sobrien	Size = (int)(ActionPos-Cursor);
78459243Sobrien	c_delafter(Size);
78559243Sobrien    }
78659243Sobrien    else  {
78759243Sobrien	Size = 1;
78859243Sobrien	c_delafter(Size);
78959243Sobrien    }
79059243Sobrien    UndoPtr = Cursor;
79159243Sobrien    UndoSize = Size;
79259243Sobrien}
79359243Sobrien
79459243Sobrienstatic Char *
795167465Smpc_endword(Char *p, Char *high, int n, Char *delim)
79659243Sobrien{
797145479Smp    Char inquote = 0;
79859243Sobrien    p++;
79959243Sobrien
80059243Sobrien    while (n--) {
80183098Smp        while (p < high) {	/* Skip non-word chars */
80283098Smp	  if (!Strchr(delim, *p) || *(p-1) == (Char)'\\')
80359243Sobrien	    break;
80459243Sobrien	  p++;
80559243Sobrien        }
80659243Sobrien	while (p < high) {	/* Skip string */
80759243Sobrien	  if ((*p == (Char)'\'' || *p == (Char)'"')) { /* Quotation marks? */
80883098Smp	    if (inquote || *(p-1) != (Char)'\\') { /* Should it be honored? */
80959243Sobrien	      if (inquote == 0) inquote = *p;
81059243Sobrien	      else if (inquote == *p) inquote = 0;
81159243Sobrien	    }
81259243Sobrien	  }
81383098Smp	  /* Break if unquoted non-word char */
81483098Smp	  if (!inquote && Strchr(delim, *p) && *(p-1) != (Char)'\\')
81559243Sobrien	    break;
81659243Sobrien	  p++;
81759243Sobrien	}
81859243Sobrien    }
81959243Sobrien
82059243Sobrien    p--;
82159243Sobrien    return(p);
82259243Sobrien}
82359243Sobrien
82459243Sobrien
82559243Sobrienstatic Char *
826167465Smpc_eword(Char *p, Char *high, int n)
82759243Sobrien{
82859243Sobrien    p++;
82959243Sobrien
83059243Sobrien    while (n--) {
83159243Sobrien	while ((p < high) && Isspace(*p))
83259243Sobrien	    p++;
83359243Sobrien
834232633Smp	if (isword(*p))
835232633Smp	    while ((p < high) && isword(*p))
83659243Sobrien		p++;
83759243Sobrien	else
838232633Smp	    while ((p < high) && !(Isspace(*p) || isword(*p)))
83959243Sobrien		p++;
84059243Sobrien    }
84159243Sobrien
84259243Sobrien    p--;
84359243Sobrien    return(p);
84459243Sobrien}
84559243Sobrien
84683098Smp/* Set the max length of the kill ring */
84783098Smpvoid
848167465SmpSetKillRing(int max)
84983098Smp{
85083098Smp    CStr *new;
85183098Smp    int count, i, j;
85283098Smp
85383098Smp    if (max < 1)
85483098Smp	max = 1;		/* no ring, but always one buffer */
85583098Smp    if (max == KillRingMax)
85683098Smp	return;
857167465Smp    new = xcalloc(max, sizeof(CStr));
85883098Smp    if (KillRing != NULL) {
85983098Smp	if (KillRingLen != 0) {
86083098Smp	    if (max >= KillRingLen) {
86183098Smp		count = KillRingLen;
86283098Smp		j = KillPos;
86383098Smp	    } else {
86483098Smp		count = max;
86583098Smp		j = (KillPos - count + KillRingLen) % KillRingLen;
86683098Smp	    }
86783098Smp	    for (i = 0; i < KillRingLen; i++) {
86883098Smp		if (i < count)	/* copy latest */
86983098Smp		    new[i] = KillRing[j];
87083098Smp		else		/* free the others */
87183098Smp		    xfree(KillRing[j].buf);
87283098Smp		j = (j + 1) % KillRingLen;
87383098Smp	    }
87483098Smp	    KillRingLen = count;
87583098Smp	    KillPos = count % max;
87683098Smp	    YankPos = count - 1;
87783098Smp	}
87883098Smp	xfree(KillRing);
87983098Smp    }
88083098Smp    KillRing = new;
88183098Smp    KillRingMax = max;
88283098Smp}
88383098Smp
88483098Smp/* Push string from start upto (but not including) end onto kill ring */
88583098Smpstatic void
886167465Smpc_push_kill(Char *start, Char *end)
88783098Smp{
88883098Smp    CStr save, *pos;
88983098Smp    Char *dp, *cp, *kp;
89083098Smp    int len = end - start, i, j, k;
89183098Smp
89283098Smp    /* Check for duplicates? */
89383098Smp    if (KillRingLen > 0 && (dp = varval(STRkilldup)) != STRNULL) {
89483098Smp	YankPos = (KillPos - 1 + KillRingLen) % KillRingLen;
89583098Smp	if (eq(dp, STRerase)) {	/* erase earlier one (actually move up) */
89683098Smp	    j = YankPos;
89783098Smp	    for (i = 0; i < KillRingLen; i++) {
89883098Smp		if (Strncmp(KillRing[j].buf, start, (size_t) len) == 0 &&
89983098Smp		    KillRing[j].buf[len] == '\0') {
90083098Smp		    save = KillRing[j];
90183098Smp		    for ( ; i > 0; i--) {
90283098Smp			k = j;
90383098Smp			j = (j + 1) % KillRingLen;
90483098Smp			KillRing[k] = KillRing[j];
90583098Smp		    }
90683098Smp		    KillRing[j] = save;
90783098Smp		    return;
90883098Smp		}
90983098Smp		j = (j - 1 + KillRingLen) % KillRingLen;
91083098Smp	    }
91183098Smp	} else if (eq(dp, STRall)) { /* skip if any earlier */
91283098Smp	    for (i = 0; i < KillRingLen; i++)
91383098Smp		if (Strncmp(KillRing[i].buf, start, (size_t) len) == 0 &&
91483098Smp		    KillRing[i].buf[len] == '\0')
91583098Smp		    return;
91683098Smp	} else if (eq(dp, STRprev)) { /* skip if immediately previous */
91783098Smp	    j = YankPos;
91883098Smp	    if (Strncmp(KillRing[j].buf, start, (size_t) len) == 0 &&
91983098Smp		KillRing[j].buf[len] == '\0')
92083098Smp		return;
92183098Smp	}
92283098Smp    }
92383098Smp
92483098Smp    /* No duplicate, go ahead and push */
92583098Smp    len++;			/* need space for '\0' */
92683098Smp    YankPos = KillPos;
92783098Smp    if (KillRingLen < KillRingMax)
92883098Smp	KillRingLen++;
92983098Smp    pos = &KillRing[KillPos];
93083098Smp    KillPos = (KillPos + 1) % KillRingMax;
93183098Smp    if (pos->len < len) {
932167465Smp	pos->buf = xrealloc(pos->buf, len * sizeof(Char));
93383098Smp	pos->len = len;
93483098Smp    }
93583098Smp    cp = start;
93683098Smp    kp = pos->buf;
93783098Smp    while (cp < end)
93883098Smp	*kp++ = *cp++;
93983098Smp    *kp = '\0';
94083098Smp}
94183098Smp
942167465Smp/* Save InputBuf etc in SavedBuf etc for restore after cmd exec */
943167465Smpstatic void
944167465Smpc_save_inputbuf()
94559243Sobrien{
946167465Smp    SavedBuf.len = 0;
947167465Smp    Strbuf_append(&SavedBuf, InputBuf);
948167465Smp    Strbuf_terminate(&SavedBuf);
949167465Smp    LastSaved = LastChar - InputBuf;
950167465Smp    CursSaved = Cursor - InputBuf;
951167465Smp    HistSaved = Hist_num;
952167465Smp    RestoreSaved = 1;
953167465Smp}
954167465Smp
955167465SmpCCRETVAL
956167465SmpGetHistLine()
957167465Smp{
95859243Sobrien    struct Hist *hp;
95959243Sobrien    int     h;
96059243Sobrien
96159243Sobrien    if (Hist_num == 0) {	/* if really the current line */
962167465Smp	if (HistBuf.s != NULL)
963167465Smp	    copyn(InputBuf, HistBuf.s, INBUFSIZE);/*FIXBUF*/
964167465Smp	else
965167465Smp	    *InputBuf = '\0';
966167465Smp	LastChar = InputBuf + HistBuf.len;
96759243Sobrien
96859243Sobrien#ifdef KSHVI
96959243Sobrien    if (VImode)
97059243Sobrien	Cursor = InputBuf;
97159243Sobrien    else
97259243Sobrien#endif /* KSHVI */
97359243Sobrien	Cursor = LastChar;
97459243Sobrien
97559243Sobrien	return(CC_REFRESH);
97659243Sobrien    }
97759243Sobrien
97859243Sobrien    hp = Histlist.Hnext;
97959243Sobrien    if (hp == NULL)
98059243Sobrien	return(CC_ERROR);
98159243Sobrien
98259243Sobrien    for (h = 1; h < Hist_num; h++) {
98359243Sobrien	if ((hp->Hnext) == NULL) {
98459243Sobrien	    Hist_num = h;
98559243Sobrien	    return(CC_ERROR);
98659243Sobrien	}
98759243Sobrien	hp = hp->Hnext;
98859243Sobrien    }
98959243Sobrien
99059243Sobrien    if (HistLit && hp->histline) {
991167465Smp	copyn(InputBuf, hp->histline, INBUFSIZE);/*FIXBUF*/
99259243Sobrien	CurrentHistLit = 1;
99359243Sobrien    }
99459243Sobrien    else {
995167465Smp	Char *p;
996167465Smp
997167465Smp	p = sprlex(&hp->Hlex);
998167465Smp	copyn(InputBuf, p, sizeof(InputBuf) / sizeof(Char));/*FIXBUF*/
999167465Smp	xfree(p);
100059243Sobrien	CurrentHistLit = 0;
100159243Sobrien    }
1002167465Smp    LastChar = Strend(InputBuf);
100359243Sobrien
100459243Sobrien    if (LastChar > InputBuf) {
100559243Sobrien	if (LastChar[-1] == '\n')
100659243Sobrien	    LastChar--;
100759243Sobrien#if 0
100859243Sobrien	if (LastChar[-1] == ' ')
100959243Sobrien	    LastChar--;
101059243Sobrien#endif
101159243Sobrien	if (LastChar < InputBuf)
101259243Sobrien	    LastChar = InputBuf;
101359243Sobrien    }
1014145479Smp
101559243Sobrien#ifdef KSHVI
101659243Sobrien    if (VImode)
101759243Sobrien	Cursor = InputBuf;
101859243Sobrien    else
101959243Sobrien#endif /* KSHVI */
102059243Sobrien	Cursor = LastChar;
102159243Sobrien
102259243Sobrien    return(CC_REFRESH);
102359243Sobrien}
102459243Sobrien
102559243Sobrienstatic CCRETVAL
1026167465Smpc_search_line(Char *pattern, int dir)
102759243Sobrien{
102859243Sobrien    Char *cp;
1029167465Smp    size_t len;
103059243Sobrien
1031167465Smp    len = Strlen(pattern);
103259243Sobrien
103359243Sobrien    if (dir == F_UP_SEARCH_HIST) {
103459243Sobrien	for (cp = Cursor; cp >= InputBuf; cp--)
1035167465Smp	    if (Strncmp(cp, pattern, len) == 0 ||
103659243Sobrien		Gmatch(cp, pattern)) {
103759243Sobrien		Cursor = cp;
103859243Sobrien		return(CC_NORM);
103959243Sobrien	    }
104059243Sobrien	return(CC_ERROR);
104159243Sobrien    } else {
104259243Sobrien	for (cp = Cursor; *cp != '\0' && cp < InputLim; cp++)
1043167465Smp	    if (Strncmp(cp, pattern, len) == 0 ||
104459243Sobrien		Gmatch(cp, pattern)) {
104559243Sobrien		Cursor = cp;
104659243Sobrien		return(CC_NORM);
104759243Sobrien	    }
104859243Sobrien	return(CC_ERROR);
104959243Sobrien    }
105059243Sobrien}
105159243Sobrien
105259243Sobrienstatic CCRETVAL
1053167465Smpe_inc_search(int dir)
105459243Sobrien{
1055167465Smp    static const Char STRfwd[] = { 'f', 'w', 'd', '\0' },
1056167465Smp		      STRbck[] = { 'b', 'c', 'k', '\0' };
105759243Sobrien    static Char pchar = ':';	/* ':' = normal, '?' = failed */
105859243Sobrien    static Char endcmd[2];
1059167465Smp    const Char *cp;
1060167465Smp    Char ch,
106159243Sobrien	*oldCursor = Cursor,
106259243Sobrien	oldpchar = pchar;
106359243Sobrien    CCRETVAL ret = CC_NORM;
106459243Sobrien    int oldHist_num = Hist_num,
1065167465Smp	oldpatlen = patbuf.len,
106659243Sobrien	newdir = dir,
106759243Sobrien        done, redo;
106859243Sobrien
1069167465Smp    if (LastChar + sizeof(STRfwd)/sizeof(Char) + 2 + patbuf.len >= InputLim)
107059243Sobrien	return(CC_ERROR);
107159243Sobrien
107259243Sobrien    for (;;) {
107359243Sobrien
1074167465Smp	if (patbuf.len == 0) {	/* first round */
107559243Sobrien	    pchar = ':';
1076167465Smp	    Strbuf_append1(&patbuf, '*');
107759243Sobrien	}
107859243Sobrien	done = redo = 0;
107959243Sobrien	*LastChar++ = '\n';
108059243Sobrien	for (cp = newdir == F_UP_SEARCH_HIST ? STRbck : STRfwd;
108159243Sobrien	     *cp; *LastChar++ = *cp++)
108259243Sobrien	    continue;
108359243Sobrien	*LastChar++ = pchar;
1084167465Smp	for (cp = &patbuf.s[1]; cp < &patbuf.s[patbuf.len];
1085167465Smp	     *LastChar++ = *cp++)
108659243Sobrien	    continue;
108759243Sobrien	*LastChar = '\0';
1088167465Smp	if (adrof(STRhighlight) && pchar == ':') {
1089167465Smp	    /* if the no-glob-search patch is applied, remove the - 1 below */
1090167465Smp	    IncMatchLen = patbuf.len - 1;
1091167465Smp	    ClearLines();
1092167465Smp	    ClearDisp();
1093167465Smp	}
109459243Sobrien	Refresh();
109559243Sobrien
109659243Sobrien	if (GetNextChar(&ch) != 1)
109759243Sobrien	    return(e_send_eof(0));
109859243Sobrien
1099145479Smp	switch (ch > NT_NUM_KEYS
1100145479Smp		? F_INSERT : CurrentKeyMap[(unsigned char) ch]) {
110159243Sobrien	case F_INSERT:
110259243Sobrien	case F_DIGIT:
110359243Sobrien	case F_MAGIC_SPACE:
1104167465Smp	    if (LastChar + 1 >= InputLim) /*FIXBUF*/
110559243Sobrien		SoundBeep();
110659243Sobrien	    else {
1107167465Smp		Strbuf_append1(&patbuf, ch);
110859243Sobrien		*LastChar++ = ch;
110959243Sobrien		*LastChar = '\0';
111059243Sobrien		Refresh();
111159243Sobrien	    }
111259243Sobrien	    break;
111359243Sobrien
111459243Sobrien	case F_INC_FWD:
111559243Sobrien	    newdir = F_DOWN_SEARCH_HIST;
111659243Sobrien	    redo++;
111759243Sobrien	    break;
111859243Sobrien
111959243Sobrien	case F_INC_BACK:
112059243Sobrien	    newdir = F_UP_SEARCH_HIST;
112159243Sobrien	    redo++;
112259243Sobrien	    break;
112359243Sobrien
112459243Sobrien	case F_DELPREV:
1125167465Smp	    if (patbuf.len > 1)
112659243Sobrien		done++;
112759243Sobrien	    else
112859243Sobrien		SoundBeep();
112959243Sobrien	    break;
113059243Sobrien
113159243Sobrien	default:
1132167465Smp	    switch (ASC(ch)) {
113359243Sobrien	    case 0007:		/* ^G: Abort */
113459243Sobrien		ret = CC_ERROR;
113559243Sobrien		done++;
113659243Sobrien		break;
113759243Sobrien
113859243Sobrien	    case 0027:		/* ^W: Append word */
113959243Sobrien		/* No can do if globbing characters in pattern */
1140167465Smp		for (cp = &patbuf.s[1]; ; cp++)
1141167465Smp		    if (cp >= &patbuf.s[patbuf.len]) {
1142167465Smp			Cursor += patbuf.len - 1;
114359243Sobrien			cp = c_next_word(Cursor, LastChar, 1);
114459243Sobrien			while (Cursor < cp && *Cursor != '\n') {
1145167465Smp			    if (LastChar + 1 >= InputLim) {/*FIXBUF*/
114659243Sobrien				SoundBeep();
114759243Sobrien				break;
114859243Sobrien			    }
1149167465Smp			    Strbuf_append1(&patbuf, *Cursor);
115059243Sobrien			    *LastChar++ = *Cursor++;
115159243Sobrien			}
115259243Sobrien			Cursor = oldCursor;
115359243Sobrien			*LastChar = '\0';
115459243Sobrien			Refresh();
115559243Sobrien			break;
115659243Sobrien		    } else if (isglob(*cp)) {
115759243Sobrien			SoundBeep();
115859243Sobrien			break;
115959243Sobrien		    }
116059243Sobrien		break;
116159243Sobrien
116259243Sobrien	    default:		/* Terminate and execute cmd */
116359243Sobrien		endcmd[0] = ch;
116459243Sobrien		PushMacro(endcmd);
116559243Sobrien		/*FALLTHROUGH*/
116659243Sobrien
116759243Sobrien	    case 0033:		/* ESC: Terminate */
116859243Sobrien		ret = CC_REFRESH;
116959243Sobrien		done++;
117059243Sobrien		break;
117159243Sobrien	    }
117259243Sobrien	    break;
117359243Sobrien	}
117459243Sobrien
117559243Sobrien	while (LastChar > InputBuf && *LastChar != '\n')
117659243Sobrien	    *LastChar-- = '\0';
117759243Sobrien	*LastChar = '\0';
117859243Sobrien
117959243Sobrien	if (!done) {
118059243Sobrien
118159243Sobrien	    /* Can't search if unmatched '[' */
1182167465Smp	    for (cp = &patbuf.s[patbuf.len - 1], ch = ']'; cp > patbuf.s; cp--)
118359243Sobrien		if (*cp == '[' || *cp == ']') {
118459243Sobrien		    ch = *cp;
118559243Sobrien		    break;
118659243Sobrien		}
118759243Sobrien
1188167465Smp	    if (patbuf.len > 1 && ch != '[') {
118959243Sobrien		if (redo && newdir == dir) {
119059243Sobrien		    if (pchar == '?') {	/* wrap around */
1191167465Smp			Hist_num = newdir == F_UP_SEARCH_HIST ? 0 : INT_MAX;
1192167465Smp			if (GetHistLine() == CC_ERROR)
119359243Sobrien			    /* Hist_num was fixed by first call */
1194167465Smp			    (void) GetHistLine();
119559243Sobrien			Cursor = newdir == F_UP_SEARCH_HIST ?
119659243Sobrien			    LastChar : InputBuf;
119759243Sobrien		    } else
119859243Sobrien			Cursor += newdir == F_UP_SEARCH_HIST ? -1 : 1;
119959243Sobrien		}
1200167465Smp		Strbuf_append1(&patbuf, '*');
1201167465Smp		Strbuf_terminate(&patbuf);
120259243Sobrien		if (Cursor < InputBuf || Cursor > LastChar ||
1203167465Smp		    (ret = c_search_line(&patbuf.s[1], newdir)) == CC_ERROR) {
120459243Sobrien		    LastCmd = (KEYCMD) newdir; /* avoid c_hsetpat */
120559243Sobrien		    ret = newdir == F_UP_SEARCH_HIST ?
120659243Sobrien			e_up_search_hist(0) : e_down_search_hist(0);
120759243Sobrien		    if (ret != CC_ERROR) {
120859243Sobrien			Cursor = newdir == F_UP_SEARCH_HIST ?
120959243Sobrien			    LastChar : InputBuf;
1210167465Smp			(void) c_search_line(&patbuf.s[1], newdir);
121159243Sobrien		    }
121259243Sobrien		}
1213167465Smp		patbuf.s[--patbuf.len] = '\0';
121459243Sobrien		if (ret == CC_ERROR) {
121559243Sobrien		    SoundBeep();
121659243Sobrien		    if (Hist_num != oldHist_num) {
121759243Sobrien			Hist_num = oldHist_num;
1218167465Smp			if (GetHistLine() == CC_ERROR)
121959243Sobrien			    return(CC_ERROR);
122059243Sobrien		    }
122159243Sobrien		    Cursor = oldCursor;
122259243Sobrien		    pchar = '?';
122359243Sobrien		} else {
122459243Sobrien		    pchar = ':';
122559243Sobrien		}
122659243Sobrien	    }
122759243Sobrien
122859243Sobrien	    ret = e_inc_search(newdir);
122959243Sobrien
123059243Sobrien	    if (ret == CC_ERROR && pchar == '?' && oldpchar == ':') {
123159243Sobrien		/* break abort of failed search at last non-failed */
123259243Sobrien		ret = CC_NORM;
123359243Sobrien	    }
123459243Sobrien
123559243Sobrien	}
123659243Sobrien
123759243Sobrien	if (ret == CC_NORM || (ret == CC_ERROR && oldpatlen == 0)) {
123859243Sobrien	    /* restore on normal return or error exit */
123959243Sobrien	    pchar = oldpchar;
1240167465Smp	    patbuf.len = oldpatlen;
124159243Sobrien	    if (Hist_num != oldHist_num) {
124259243Sobrien		Hist_num = oldHist_num;
1243167465Smp		if (GetHistLine() == CC_ERROR)
124459243Sobrien		    return(CC_ERROR);
124559243Sobrien	    }
124659243Sobrien	    Cursor = oldCursor;
124759243Sobrien	    if (ret == CC_ERROR)
124859243Sobrien		Refresh();
124959243Sobrien	}
125059243Sobrien	if (done || ret != CC_NORM)
125159243Sobrien	    return(ret);
125259243Sobrien
125359243Sobrien    }
125459243Sobrien
125559243Sobrien}
125659243Sobrien
125759243Sobrienstatic CCRETVAL
1258167465Smpv_search(int dir)
125959243Sobrien{
1260167465Smp    struct Strbuf tmpbuf = Strbuf_INIT;
126159243Sobrien    Char ch;
1262167465Smp    Char *oldbuf;
126359243Sobrien    Char *oldlc, *oldc;
126459243Sobrien
1265167465Smp    cleanup_push(&tmpbuf, Strbuf_cleanup);
1266167465Smp    oldbuf = Strsave(InputBuf);
1267167465Smp    cleanup_push(oldbuf, xfree);
126859243Sobrien    oldlc = LastChar;
126959243Sobrien    oldc = Cursor;
1270167465Smp    Strbuf_append1(&tmpbuf, '*');
127159243Sobrien
127259243Sobrien    InputBuf[0] = '\0';
127359243Sobrien    LastChar = InputBuf;
127459243Sobrien    Cursor = InputBuf;
127559243Sobrien    searchdir = dir;
127659243Sobrien
127759243Sobrien    c_insert(2);	/* prompt + '\n' */
127859243Sobrien    *Cursor++ = '\n';
127959243Sobrien    *Cursor++ = dir == F_UP_SEARCH_HIST ? '?' : '/';
128059243Sobrien    Refresh();
128159243Sobrien    for (ch = 0;ch == 0;) {
1282167465Smp	if (GetNextChar(&ch) != 1) {
1283167465Smp	    cleanup_until(&tmpbuf);
128459243Sobrien	    return(e_send_eof(0));
1285167465Smp	}
128659243Sobrien	switch (ASC(ch)) {
128759243Sobrien	case 0010:	/* Delete and backspace */
128859243Sobrien	case 0177:
1289167465Smp	    if (tmpbuf.len > 1) {
129059243Sobrien		*Cursor-- = '\0';
129159243Sobrien		LastChar = Cursor;
1292167465Smp		tmpbuf.len--;
129359243Sobrien	    }
129459243Sobrien	    else {
1295167465Smp		copyn(InputBuf, oldbuf, INBUFSIZE);/*FIXBUF*/
129659243Sobrien		LastChar = oldlc;
129759243Sobrien		Cursor = oldc;
1298167465Smp		cleanup_until(&tmpbuf);
129959243Sobrien		return(CC_REFRESH);
130059243Sobrien	    }
130159243Sobrien	    Refresh();
130259243Sobrien	    ch = 0;
130359243Sobrien	    break;
130459243Sobrien
130559243Sobrien	case 0033:	/* ESC */
130669408Sache#ifdef IS_ASCII
130759243Sobrien	case '\r':	/* Newline */
130859243Sobrien	case '\n':
130959243Sobrien#else
131069408Sache	case '\012':    /* ASCII Line feed */
131169408Sache	case '\015':    /* ASCII (or EBCDIC) Return */
131259243Sobrien#endif
131359243Sobrien	    break;
131459243Sobrien
131559243Sobrien	default:
1316167465Smp	    Strbuf_append1(&tmpbuf, ch);
1317167465Smp	    *Cursor++ = ch;
1318167465Smp	    LastChar = Cursor;
131959243Sobrien	    Refresh();
132059243Sobrien	    ch = 0;
132159243Sobrien	    break;
132259243Sobrien	}
132359243Sobrien    }
1324167465Smp    cleanup_until(oldbuf);
132559243Sobrien
1326167465Smp    if (tmpbuf.len == 1) {
132759243Sobrien	/*
132859243Sobrien	 * Use the old pattern, but wild-card it.
132959243Sobrien	 */
1330167465Smp	if (patbuf.len == 0) {
133159243Sobrien	    InputBuf[0] = '\0';
133259243Sobrien	    LastChar = InputBuf;
133359243Sobrien	    Cursor = InputBuf;
133459243Sobrien	    Refresh();
1335167465Smp	    cleanup_until(&tmpbuf);
133659243Sobrien	    return(CC_ERROR);
133759243Sobrien	}
1338167465Smp	if (patbuf.s[0] != '*') {
1339167465Smp	    oldbuf = Strsave(patbuf.s);
1340167465Smp	    patbuf.len = 0;
1341167465Smp	    Strbuf_append1(&patbuf, '*');
1342167465Smp	    Strbuf_append(&patbuf, oldbuf);
1343167465Smp	    xfree(oldbuf);
1344167465Smp	    Strbuf_append1(&patbuf, '*');
1345167465Smp	    Strbuf_terminate(&patbuf);
134659243Sobrien	}
134759243Sobrien    }
134859243Sobrien    else {
1349167465Smp	Strbuf_append1(&tmpbuf, '*');
1350167465Smp	Strbuf_terminate(&tmpbuf);
1351167465Smp	patbuf.len = 0;
1352167465Smp	Strbuf_append(&patbuf, tmpbuf.s);
1353167465Smp	Strbuf_terminate(&patbuf);
135459243Sobrien    }
1355167465Smp    cleanup_until(&tmpbuf);
135659243Sobrien    LastCmd = (KEYCMD) dir; /* avoid c_hsetpat */
135759243Sobrien    Cursor = LastChar = InputBuf;
135859243Sobrien    if ((dir == F_UP_SEARCH_HIST ? e_up_search_hist(0) :
135959243Sobrien				   e_down_search_hist(0)) == CC_ERROR) {
136059243Sobrien	Refresh();
136159243Sobrien	return(CC_ERROR);
136259243Sobrien    }
136359243Sobrien    else {
1364167465Smp	if (ASC(ch) == 0033) {
136559243Sobrien	    Refresh();
136659243Sobrien	    *LastChar++ = '\n';
136759243Sobrien	    *LastChar = '\0';
136859243Sobrien	    PastBottom();
136959243Sobrien	    return(CC_NEWLINE);
137059243Sobrien	}
137159243Sobrien	else
137259243Sobrien	    return(CC_REFRESH);
137359243Sobrien    }
137459243Sobrien}
137559243Sobrien
137659243Sobrien/*
137759243Sobrien * semi-PUBLIC routines.  Any routine that is of type CCRETVAL is an
137859243Sobrien * entry point, called from the CcKeyMap indirected into the
137959243Sobrien * CcFuncTbl array.
138059243Sobrien */
138159243Sobrien
138259243Sobrien/*ARGSUSED*/
138359243SobrienCCRETVAL
1384167465Smpv_cmd_mode(Char c)
138559243Sobrien{
138659243Sobrien    USE(c);
138759243Sobrien    InsertPos = 0;
138859243Sobrien    ActionFlag = TCSHOP_NOP;	/* [Esc] cancels pending action */
138959243Sobrien    ActionPos = 0;
139059243Sobrien    DoingArg = 0;
139159243Sobrien    if (UndoPtr > Cursor)
139259243Sobrien	UndoSize = (int)(UndoPtr - Cursor);
139359243Sobrien    else
139459243Sobrien	UndoSize = (int)(Cursor - UndoPtr);
139559243Sobrien
139659243Sobrien    inputmode = MODE_INSERT;
139759243Sobrien    c_alternativ_key_map(1);
139859243Sobrien#ifdef notdef
139959243Sobrien    /*
140059243Sobrien     * We don't want to move the cursor, because all the editing
140159243Sobrien     * commands don't include the character under the cursor.
140259243Sobrien     */
140359243Sobrien    if (Cursor > InputBuf)
140459243Sobrien	Cursor--;
140559243Sobrien#endif
140659243Sobrien    RefCursor();
140759243Sobrien    return(CC_NORM);
140859243Sobrien}
140959243Sobrien
141059243Sobrien/*ARGSUSED*/
141159243SobrienCCRETVAL
1412167465Smpe_unassigned(Char c)
141359243Sobrien{				/* bound to keys that arn't really assigned */
141459243Sobrien    USE(c);
141559243Sobrien    SoundBeep();
141659243Sobrien    flush();
141759243Sobrien    return(CC_NORM);
141859243Sobrien}
141959243Sobrien
1420167465Smp#ifdef notyet
1421145479Smpstatic CCRETVAL
1422167465Smpe_insert_str(Char *c)
1423145479Smp{
1424145479Smp    int i, n;
1425145479Smp
1426145479Smp    n = Strlen(c);
1427145479Smp    if (LastChar + Argument * n >= InputLim)
1428145479Smp	return(CC_ERROR);	/* end of buffer space */
1429145479Smp    if (inputmode != MODE_INSERT) {
1430167465Smp	c_delafter(Argument * Strlen(c));
1431145479Smp    }
1432145479Smp    c_insert(Argument * n);
1433145479Smp    while (Argument--) {
1434145479Smp	for (i = 0; i < n; i++)
1435145479Smp	    *Cursor++ = c[i];
1436145479Smp    }
1437145479Smp    Refresh();
1438145479Smp    return(CC_NORM);
1439145479Smp}
1440167465Smp#endif
1441145479Smp
144259243SobrienCCRETVAL
1443167465Smpe_insert(Char c)
144459243Sobrien{
144559243Sobrien#ifndef SHORT_STRINGS
144659243Sobrien    c &= ASCII;			/* no meta chars ever */
144759243Sobrien#endif
144859243Sobrien
144959243Sobrien    if (!c)
145059243Sobrien	return(CC_ERROR);	/* no NULs in the input ever!! */
145159243Sobrien
145259243Sobrien    if (LastChar + Argument >= InputLim)
145359243Sobrien	return(CC_ERROR);	/* end of buffer space */
145459243Sobrien
145559243Sobrien    if (Argument == 1) {  	/* How was this optimized ???? */
145659243Sobrien
145759243Sobrien	if (inputmode != MODE_INSERT) {
145859243Sobrien	    UndoBuf[UndoSize++] = *Cursor;
145959243Sobrien	    UndoBuf[UndoSize] = '\0';
146059243Sobrien	    c_delafter(1);   /* Do NOT use the saving ONE */
146159243Sobrien    	}
146259243Sobrien
146359243Sobrien        c_insert(1);
146459243Sobrien	*Cursor++ = (Char) c;
146559243Sobrien	DoingArg = 0;		/* just in case */
1466145479Smp	RefPlusOne(1);		/* fast refresh for one char. */
146759243Sobrien    }
146859243Sobrien    else {
146959243Sobrien	if (inputmode != MODE_INSERT) {
1470145479Smp	    int i;
1471145479Smp	    for(i = 0; i < Argument; i++)
1472145479Smp		UndoBuf[UndoSize++] = *(Cursor + i);
147359243Sobrien
147459243Sobrien	    UndoBuf[UndoSize] = '\0';
147559243Sobrien	    c_delafter(Argument);   /* Do NOT use the saving ONE */
147659243Sobrien    	}
147759243Sobrien
147859243Sobrien        c_insert(Argument);
147959243Sobrien
148059243Sobrien	while (Argument--)
148159243Sobrien	    *Cursor++ = (Char) c;
148259243Sobrien	Refresh();
148359243Sobrien    }
148459243Sobrien
148559243Sobrien    if (inputmode == MODE_REPLACE_1)
148659243Sobrien	(void) v_cmd_mode(0);
148759243Sobrien
148859243Sobrien    return(CC_NORM);
148959243Sobrien}
149059243Sobrien
149159243Sobrienint
1492167465SmpInsertStr(Char *s)		/* insert ASCIZ s at cursor (for complete) */
149359243Sobrien{
149483098Smp    int len;
149559243Sobrien
149659243Sobrien    if ((len = (int) Strlen(s)) <= 0)
149759243Sobrien	return -1;
149859243Sobrien    if (LastChar + len >= InputLim)
149959243Sobrien	return -1;		/* end of buffer space */
150059243Sobrien
150159243Sobrien    c_insert(len);
150259243Sobrien    while (len--)
150359243Sobrien	*Cursor++ = *s++;
150459243Sobrien    return 0;
150559243Sobrien}
150659243Sobrien
150759243Sobrienvoid
1508167465SmpDeleteBack(int n)		/* delete the n characters before . */
150959243Sobrien{
151059243Sobrien    if (n <= 0)
151159243Sobrien	return;
151259243Sobrien    if (Cursor >= &InputBuf[n]) {
151359243Sobrien	c_delbefore(n);		/* delete before dot */
151459243Sobrien    }
151559243Sobrien}
151659243Sobrien
151759243SobrienCCRETVAL
1518167465Smpe_digit(Char c)			/* gray magic here */
151959243Sobrien{
152059243Sobrien    if (!Isdigit(c))
152159243Sobrien	return(CC_ERROR);	/* no NULs in the input ever!! */
152259243Sobrien
152359243Sobrien    if (DoingArg) {		/* if doing an arg, add this in... */
152459243Sobrien	if (LastCmd == F_ARGFOUR)	/* if last command was ^U */
152559243Sobrien	    Argument = c - '0';
152659243Sobrien	else {
152759243Sobrien	    if (Argument > 1000000)
152859243Sobrien		return CC_ERROR;
152959243Sobrien	    Argument = (Argument * 10) + (c - '0');
153059243Sobrien	}
153159243Sobrien	return(CC_ARGHACK);
153259243Sobrien    }
153359243Sobrien    else {
153459243Sobrien	if (LastChar + 1 >= InputLim)
153559243Sobrien	    return CC_ERROR;	/* end of buffer space */
153659243Sobrien
153759243Sobrien	if (inputmode != MODE_INSERT) {
153859243Sobrien	    UndoBuf[UndoSize++] = *Cursor;
153959243Sobrien	    UndoBuf[UndoSize] = '\0';
154059243Sobrien	    c_delafter(1);   /* Do NOT use the saving ONE */
154159243Sobrien    	}
154259243Sobrien	c_insert(1);
154359243Sobrien	*Cursor++ = (Char) c;
154459243Sobrien	DoingArg = 0;		/* just in case */
1545145479Smp	RefPlusOne(1);		/* fast refresh for one char. */
154659243Sobrien    }
154759243Sobrien    return(CC_NORM);
154859243Sobrien}
154959243Sobrien
155059243SobrienCCRETVAL
1551167465Smpe_argdigit(Char c)		/* for ESC-n */
155259243Sobrien{
1553167465Smp#ifdef IS_ASCII
155459243Sobrien    c &= ASCII;
1555167465Smp#else
1556167465Smp    c = CTL_ESC(ASC(c) & ASCII); /* stripping for EBCDIC done the ASCII way */
1557167465Smp#endif
155859243Sobrien
155959243Sobrien    if (!Isdigit(c))
156059243Sobrien	return(CC_ERROR);	/* no NULs in the input ever!! */
156159243Sobrien
156259243Sobrien    if (DoingArg) {		/* if doing an arg, add this in... */
156359243Sobrien	if (Argument > 1000000)
156459243Sobrien	    return CC_ERROR;
156559243Sobrien	Argument = (Argument * 10) + (c - '0');
156659243Sobrien    }
156759243Sobrien    else {			/* else starting an argument */
156859243Sobrien	Argument = c - '0';
156959243Sobrien	DoingArg = 1;
157059243Sobrien    }
157159243Sobrien    return(CC_ARGHACK);
157259243Sobrien}
157359243Sobrien
157459243SobrienCCRETVAL
1575167465Smpv_zero(Char c)			/* command mode 0 for vi */
157659243Sobrien{
157759243Sobrien    if (DoingArg) {		/* if doing an arg, add this in... */
157859243Sobrien	if (Argument > 1000000)
157959243Sobrien	    return CC_ERROR;
158059243Sobrien	Argument = (Argument * 10) + (c - '0');
158159243Sobrien	return(CC_ARGHACK);
158259243Sobrien    }
158359243Sobrien    else {			/* else starting an argument */
158459243Sobrien	Cursor = InputBuf;
158559243Sobrien	if (ActionFlag & TCSHOP_DELETE) {
158659243Sobrien	   c_delfini();
158759243Sobrien	   return(CC_REFRESH);
158859243Sobrien        }
158959243Sobrien	RefCursor();		/* move the cursor */
159059243Sobrien	return(CC_NORM);
159159243Sobrien    }
159259243Sobrien}
159359243Sobrien
159459243Sobrien/*ARGSUSED*/
159559243SobrienCCRETVAL
1596167465Smpe_newline(Char c)
159759243Sobrien{				/* always ignore argument */
159859243Sobrien    USE(c);
1599167465Smp    if (adrof(STRhighlight) && MarkIsSet) {
1600167465Smp	MarkIsSet = 0;
1601167465Smp	ClearLines();
1602167465Smp	ClearDisp();
1603167465Smp	Refresh();
1604167465Smp    }
1605167465Smp    MarkIsSet = 0;
1606167465Smp
160759243Sobrien  /*  PastBottom();  NOW done in ed.inputl.c */
160859243Sobrien    *LastChar++ = '\n';		/* for the benefit of CSH */
160959243Sobrien    *LastChar = '\0';		/* just in case */
161059243Sobrien    if (VImode)
161159243Sobrien	InsertPos = InputBuf;	/* Reset editing position */
161259243Sobrien    return(CC_NEWLINE);
161359243Sobrien}
161459243Sobrien
161559243Sobrien/*ARGSUSED*/
161659243SobrienCCRETVAL
1617167465Smpe_newline_hold(Char c)
1618167465Smp{
1619167465Smp    USE(c);
1620167465Smp    c_save_inputbuf();
1621167465Smp    HistSaved = 0;
1622167465Smp    *LastChar++ = '\n';		/* for the benefit of CSH */
1623167465Smp    *LastChar = '\0';		/* just in case */
1624167465Smp    return(CC_NEWLINE);
1625167465Smp}
1626167465Smp
1627167465Smp/*ARGSUSED*/
1628167465SmpCCRETVAL
1629167465Smpe_newline_down_hist(Char c)
1630167465Smp{
1631167465Smp    USE(c);
1632167465Smp    if (Hist_num > 1) {
1633167465Smp	HistSaved = Hist_num;
1634167465Smp    }
1635167465Smp    *LastChar++ = '\n';		/* for the benefit of CSH */
1636167465Smp    *LastChar = '\0';		/* just in case */
1637167465Smp    return(CC_NEWLINE);
1638167465Smp}
1639167465Smp
1640167465Smp/*ARGSUSED*/
1641167465SmpCCRETVAL
1642167465Smpe_send_eof(Char c)
164359243Sobrien{				/* for when ^D is ONLY send-eof */
164459243Sobrien    USE(c);
164559243Sobrien    PastBottom();
164659243Sobrien    *LastChar = '\0';		/* just in case */
164759243Sobrien    return(CC_EOF);
164859243Sobrien}
164959243Sobrien
165059243Sobrien/*ARGSUSED*/
165159243SobrienCCRETVAL
1652167465Smpe_complete(Char c)
165359243Sobrien{
165459243Sobrien    USE(c);
165559243Sobrien    *LastChar = '\0';		/* just in case */
165659243Sobrien    return(CC_COMPLETE);
165759243Sobrien}
165859243Sobrien
165959243Sobrien/*ARGSUSED*/
166059243SobrienCCRETVAL
1661167465Smpe_complete_back(Char c)
166259243Sobrien{
166359243Sobrien    USE(c);
166459243Sobrien    *LastChar = '\0';		/* just in case */
166559243Sobrien    return(CC_COMPLETE_BACK);
166659243Sobrien}
166759243Sobrien
166859243Sobrien/*ARGSUSED*/
166959243SobrienCCRETVAL
1670167465Smpe_complete_fwd(Char c)
167159243Sobrien{
167259243Sobrien    USE(c);
167359243Sobrien    *LastChar = '\0';		/* just in case */
167459243Sobrien    return(CC_COMPLETE_FWD);
167559243Sobrien}
167659243Sobrien
167759243Sobrien/*ARGSUSED*/
167859243SobrienCCRETVAL
1679167465Smpe_complete_all(Char c)
168059243Sobrien{
168159243Sobrien    USE(c);
168259243Sobrien    *LastChar = '\0';		/* just in case */
168359243Sobrien    return(CC_COMPLETE_ALL);
168459243Sobrien}
168559243Sobrien
168659243Sobrien/*ARGSUSED*/
168759243SobrienCCRETVAL
1688167465Smpv_cm_complete(Char c)
168959243Sobrien{
169059243Sobrien    USE(c);
169159243Sobrien    if (Cursor < LastChar)
169259243Sobrien	Cursor++;
169359243Sobrien    *LastChar = '\0';		/* just in case */
169459243Sobrien    return(CC_COMPLETE);
169559243Sobrien}
169659243Sobrien
169759243Sobrien/*ARGSUSED*/
169859243SobrienCCRETVAL
1699167465Smpe_toggle_hist(Char c)
170059243Sobrien{
170159243Sobrien    struct Hist *hp;
170259243Sobrien    int     h;
170359243Sobrien
170459243Sobrien    USE(c);
170559243Sobrien    *LastChar = '\0';		/* just in case */
170659243Sobrien
170759243Sobrien    if (Hist_num <= 0) {
170859243Sobrien	return CC_ERROR;
170959243Sobrien    }
171059243Sobrien
171159243Sobrien    hp = Histlist.Hnext;
171259243Sobrien    if (hp == NULL) {	/* this is only if no history */
171359243Sobrien	return(CC_ERROR);
171459243Sobrien    }
171559243Sobrien
171659243Sobrien    for (h = 1; h < Hist_num; h++)
171759243Sobrien	hp = hp->Hnext;
171859243Sobrien
171959243Sobrien    if (!CurrentHistLit) {
172059243Sobrien	if (hp->histline) {
1721167465Smp	    copyn(InputBuf, hp->histline, INBUFSIZE);/*FIXBUF*/
172259243Sobrien	    CurrentHistLit = 1;
172359243Sobrien	}
172459243Sobrien	else {
172559243Sobrien	    return CC_ERROR;
172659243Sobrien	}
172759243Sobrien    }
172859243Sobrien    else {
1729167465Smp	Char *p;
1730167465Smp
1731167465Smp	p = sprlex(&hp->Hlex);
1732167465Smp	copyn(InputBuf, p, sizeof(InputBuf) / sizeof(Char));/*FIXBUF*/
1733167465Smp	xfree(p);
173459243Sobrien	CurrentHistLit = 0;
173559243Sobrien    }
173659243Sobrien
1737167465Smp    LastChar = Strend(InputBuf);
173859243Sobrien    if (LastChar > InputBuf) {
173959243Sobrien	if (LastChar[-1] == '\n')
174059243Sobrien	    LastChar--;
174159243Sobrien	if (LastChar[-1] == ' ')
174259243Sobrien	    LastChar--;
174359243Sobrien	if (LastChar < InputBuf)
174459243Sobrien	    LastChar = InputBuf;
174559243Sobrien    }
174659243Sobrien
174759243Sobrien#ifdef KSHVI
174859243Sobrien    if (VImode)
174959243Sobrien	Cursor = InputBuf;
175059243Sobrien    else
175159243Sobrien#endif /* KSHVI */
175259243Sobrien	Cursor = LastChar;
175359243Sobrien
175459243Sobrien    return(CC_REFRESH);
175559243Sobrien}
175659243Sobrien
175759243Sobrien/*ARGSUSED*/
175859243SobrienCCRETVAL
1759167465Smpe_up_hist(Char c)
176059243Sobrien{
176159243Sobrien    Char    beep = 0;
176259243Sobrien
176359243Sobrien    USE(c);
176459243Sobrien    UndoAction = TCSHOP_NOP;
176559243Sobrien    *LastChar = '\0';		/* just in case */
176659243Sobrien
176759243Sobrien    if (Hist_num == 0) {	/* save the current buffer away */
1768167465Smp	HistBuf.len = 0;
1769167465Smp	Strbuf_append(&HistBuf, InputBuf);
1770167465Smp	Strbuf_terminate(&HistBuf);
177159243Sobrien    }
177259243Sobrien
177359243Sobrien    Hist_num += Argument;
177459243Sobrien
1775167465Smp    if (GetHistLine() == CC_ERROR) {
177659243Sobrien	beep = 1;
1777167465Smp	(void) GetHistLine(); /* Hist_num was fixed by first call */
177859243Sobrien    }
177959243Sobrien
178059243Sobrien    Refresh();
178159243Sobrien    if (beep)
178259243Sobrien	return(CC_ERROR);
178359243Sobrien    else
178459243Sobrien	return(CC_NORM);	/* was CC_UP_HIST */
178559243Sobrien}
178659243Sobrien
178759243Sobrien/*ARGSUSED*/
178859243SobrienCCRETVAL
1789167465Smpe_down_hist(Char c)
179059243Sobrien{
179159243Sobrien    USE(c);
179259243Sobrien    UndoAction = TCSHOP_NOP;
179359243Sobrien    *LastChar = '\0';		/* just in case */
179459243Sobrien
179559243Sobrien    Hist_num -= Argument;
179659243Sobrien
179759243Sobrien    if (Hist_num < 0) {
179859243Sobrien	Hist_num = 0;
179959243Sobrien	return(CC_ERROR);	/* make it beep */
180059243Sobrien    }
180159243Sobrien
1802167465Smp    return(GetHistLine());
180359243Sobrien}
180459243Sobrien
180559243Sobrien
180659243Sobrien
180759243Sobrien/*
180859243Sobrien * c_hmatch() return True if the pattern matches the prefix
180959243Sobrien */
181059243Sobrienstatic int
1811167465Smpc_hmatch(Char *str)
181259243Sobrien{
1813167465Smp    if (Strncmp(patbuf.s, str, patbuf.len) == 0)
181459243Sobrien	return 1;
1815167465Smp    return Gmatch(str, patbuf.s);
181659243Sobrien}
181759243Sobrien
181859243Sobrien/*
181959243Sobrien * c_hsetpat(): Set the history seatch pattern
182059243Sobrien */
182159243Sobrienstatic void
1822167465Smpc_hsetpat(void)
182359243Sobrien{
182459243Sobrien    if (LastCmd != F_UP_SEARCH_HIST && LastCmd != F_DOWN_SEARCH_HIST) {
1825167465Smp	patbuf.len = 0;
1826167465Smp	Strbuf_appendn(&patbuf, InputBuf, Cursor - InputBuf);
1827167465Smp	Strbuf_terminate(&patbuf);
182859243Sobrien    }
182959243Sobrien#ifdef SDEBUG
183059243Sobrien    xprintf("\nHist_num = %d\n", Hist_num);
1831167465Smp    xprintf("patlen = %d\n", (int)patbuf.len);
1832167465Smp    xprintf("patbuf = \"%S\"\n", patbuf.s);
183359243Sobrien    xprintf("Cursor %d LastChar %d\n", Cursor - InputBuf, LastChar - InputBuf);
183459243Sobrien#endif
183559243Sobrien}
183659243Sobrien
183759243Sobrien/*ARGSUSED*/
183859243SobrienCCRETVAL
1839167465Smpe_up_search_hist(Char c)
184059243Sobrien{
184159243Sobrien    struct Hist *hp;
184259243Sobrien    int h;
1843145479Smp    int    found = 0;
184459243Sobrien
184559243Sobrien    USE(c);
184659243Sobrien    ActionFlag = TCSHOP_NOP;
184759243Sobrien    UndoAction = TCSHOP_NOP;
184859243Sobrien    *LastChar = '\0';		/* just in case */
184959243Sobrien    if (Hist_num < 0) {
185059243Sobrien#ifdef DEBUG_EDIT
185159243Sobrien	xprintf("%s: e_up_search_hist(): Hist_num < 0; resetting.\n", progname);
185259243Sobrien#endif
185359243Sobrien	Hist_num = 0;
185459243Sobrien	return(CC_ERROR);
185559243Sobrien    }
185659243Sobrien
1857167465Smp    if (Hist_num == 0) {
1858167465Smp	HistBuf.len = 0;
1859167465Smp	Strbuf_append(&HistBuf, InputBuf);
1860167465Smp	Strbuf_terminate(&HistBuf);
186159243Sobrien    }
186259243Sobrien
186359243Sobrien
186459243Sobrien    hp = Histlist.Hnext;
186559243Sobrien    if (hp == NULL)
186659243Sobrien	return(CC_ERROR);
186759243Sobrien
186859243Sobrien    c_hsetpat();		/* Set search pattern !! */
186959243Sobrien
187059243Sobrien    for (h = 1; h <= Hist_num; h++)
187159243Sobrien	hp = hp->Hnext;
187259243Sobrien
187359243Sobrien    while (hp != NULL) {
1874167465Smp	Char *hl;
1875167465Smp	int matched;
1876167465Smp
1877167465Smp	if (hp->histline == NULL)
1878167465Smp	    hp->histline = sprlex(&hp->Hlex);
1879167465Smp	if (HistLit)
1880167465Smp	    hl = hp->histline;
1881167465Smp	else {
1882167465Smp	    hl = sprlex(&hp->Hlex);
1883167465Smp	    cleanup_push(hl, xfree);
188459243Sobrien	}
188559243Sobrien#ifdef SDEBUG
188659243Sobrien	xprintf("Comparing with \"%S\"\n", hl);
188759243Sobrien#endif
1888167465Smp	matched = (Strncmp(hl, InputBuf, (size_t) (LastChar - InputBuf)) ||
1889167465Smp		   hl[LastChar-InputBuf]) && c_hmatch(hl);
1890167465Smp	if (!HistLit)
1891167465Smp	    cleanup_until(hl);
1892167465Smp	if (matched) {
189359243Sobrien	    found++;
189459243Sobrien	    break;
189559243Sobrien	}
189659243Sobrien	h++;
189759243Sobrien	hp = hp->Hnext;
189859243Sobrien    }
189959243Sobrien
190059243Sobrien    if (!found) {
190159243Sobrien#ifdef SDEBUG
1902167465Smp	xprintf("not found\n");
190359243Sobrien#endif
190459243Sobrien	return(CC_ERROR);
190559243Sobrien    }
190659243Sobrien
190759243Sobrien    Hist_num = h;
190859243Sobrien
1909167465Smp    return(GetHistLine());
191059243Sobrien}
191159243Sobrien
191259243Sobrien/*ARGSUSED*/
191359243SobrienCCRETVAL
1914167465Smpe_down_search_hist(Char c)
191559243Sobrien{
191659243Sobrien    struct Hist *hp;
191759243Sobrien    int h;
1918145479Smp    int    found = 0;
191959243Sobrien
192059243Sobrien    USE(c);
192159243Sobrien    ActionFlag = TCSHOP_NOP;
192259243Sobrien    UndoAction = TCSHOP_NOP;
192359243Sobrien    *LastChar = '\0';		/* just in case */
192459243Sobrien
192559243Sobrien    if (Hist_num == 0)
192659243Sobrien	return(CC_ERROR);
192759243Sobrien
192859243Sobrien    hp = Histlist.Hnext;
192959243Sobrien    if (hp == 0)
193059243Sobrien	return(CC_ERROR);
193159243Sobrien
193259243Sobrien    c_hsetpat();		/* Set search pattern !! */
193359243Sobrien
193459243Sobrien    for (h = 1; h < Hist_num && hp; h++) {
1935167465Smp	Char *hl;
1936167465Smp	if (hp->histline == NULL)
1937167465Smp	    hp->histline = sprlex(&hp->Hlex);
1938167465Smp	if (HistLit)
1939167465Smp	    hl = hp->histline;
1940167465Smp	else {
1941167465Smp	    hl = sprlex(&hp->Hlex);
1942167465Smp	    cleanup_push(hl, xfree);
194359243Sobrien	}
194459243Sobrien#ifdef SDEBUG
194559243Sobrien	xprintf("Comparing with \"%S\"\n", hl);
194659243Sobrien#endif
194759243Sobrien	if ((Strncmp(hl, InputBuf, (size_t) (LastChar - InputBuf)) ||
194859243Sobrien	     hl[LastChar-InputBuf]) && c_hmatch(hl))
194959243Sobrien	    found = h;
1950167465Smp	if (!HistLit)
1951167465Smp	    cleanup_until(hl);
195259243Sobrien	hp = hp->Hnext;
195359243Sobrien    }
195459243Sobrien
195559243Sobrien    if (!found) {		/* is it the current history number? */
1956167465Smp	if (!c_hmatch(HistBuf.s)) {
195759243Sobrien#ifdef SDEBUG
1958167465Smp	    xprintf("not found\n");
195959243Sobrien#endif
196059243Sobrien	    return(CC_ERROR);
196159243Sobrien	}
196259243Sobrien    }
196359243Sobrien
196459243Sobrien    Hist_num = found;
196559243Sobrien
1966167465Smp    return(GetHistLine());
196759243Sobrien}
196859243Sobrien
196959243Sobrien/*ARGSUSED*/
197059243SobrienCCRETVAL
1971167465Smpe_helpme(Char c)
197259243Sobrien{
197359243Sobrien    USE(c);
197459243Sobrien    PastBottom();
197559243Sobrien    *LastChar = '\0';		/* just in case */
197659243Sobrien    return(CC_HELPME);
197759243Sobrien}
197859243Sobrien
197959243Sobrien/*ARGSUSED*/
198059243SobrienCCRETVAL
1981167465Smpe_correct(Char c)
198259243Sobrien{
198359243Sobrien    USE(c);
198459243Sobrien    *LastChar = '\0';		/* just in case */
198559243Sobrien    return(CC_CORRECT);
198659243Sobrien}
198759243Sobrien
198859243Sobrien/*ARGSUSED*/
198959243SobrienCCRETVAL
1990167465Smpe_correctl(Char c)
199159243Sobrien{
199259243Sobrien    USE(c);
199359243Sobrien    *LastChar = '\0';		/* just in case */
199459243Sobrien    return(CC_CORRECT_L);
199559243Sobrien}
199659243Sobrien
199759243Sobrien/*ARGSUSED*/
199859243SobrienCCRETVAL
1999167465Smpe_run_fg_editor(Char c)
200059243Sobrien{
200183098Smp    struct process *pp;
200259243Sobrien
200359243Sobrien    USE(c);
200459243Sobrien    if ((pp = find_stop_ed()) != NULL) {
200559243Sobrien	/* save our editor state so we can restore it */
2006167465Smp	c_save_inputbuf();
200759243Sobrien	Hist_num = 0;		/* for the history commands */
200859243Sobrien
200959243Sobrien	/* put the tty in a sane mode */
201059243Sobrien	PastBottom();
201159243Sobrien	(void) Cookedmode();	/* make sure the tty is set up correctly */
201259243Sobrien
201359243Sobrien	/* do it! */
201459243Sobrien	fg_proc_entry(pp);
201559243Sobrien
201659243Sobrien	(void) Rawmode();	/* go on */
201759243Sobrien	Refresh();
2018167465Smp	RestoreSaved = 0;
2019167465Smp	HistSaved = 0;
202059243Sobrien    }
202159243Sobrien    return(CC_NORM);
202259243Sobrien}
202359243Sobrien
202459243Sobrien/*ARGSUSED*/
202559243SobrienCCRETVAL
2026167465Smpe_list_choices(Char c)
202759243Sobrien{
202859243Sobrien    USE(c);
202959243Sobrien    PastBottom();
203059243Sobrien    *LastChar = '\0';		/* just in case */
203159243Sobrien    return(CC_LIST_CHOICES);
203259243Sobrien}
203359243Sobrien
203459243Sobrien/*ARGSUSED*/
203559243SobrienCCRETVAL
2036167465Smpe_list_all(Char c)
203759243Sobrien{
203859243Sobrien    USE(c);
203959243Sobrien    PastBottom();
204059243Sobrien    *LastChar = '\0';		/* just in case */
204159243Sobrien    return(CC_LIST_ALL);
204259243Sobrien}
204359243Sobrien
204459243Sobrien/*ARGSUSED*/
204559243SobrienCCRETVAL
2046167465Smpe_list_glob(Char c)
204759243Sobrien{
204859243Sobrien    USE(c);
204959243Sobrien    PastBottom();
205059243Sobrien    *LastChar = '\0';		/* just in case */
205159243Sobrien    return(CC_LIST_GLOB);
205259243Sobrien}
205359243Sobrien
205459243Sobrien/*ARGSUSED*/
205559243SobrienCCRETVAL
2056167465Smpe_expand_glob(Char c)
205759243Sobrien{
205859243Sobrien    USE(c);
205959243Sobrien    *LastChar = '\0';		/* just in case */
206059243Sobrien    return(CC_EXPAND_GLOB);
206159243Sobrien}
206259243Sobrien
206359243Sobrien/*ARGSUSED*/
206459243SobrienCCRETVAL
2065167465Smpe_normalize_path(Char c)
206659243Sobrien{
206759243Sobrien    USE(c);
206859243Sobrien    *LastChar = '\0';		/* just in case */
206959243Sobrien    return(CC_NORMALIZE_PATH);
207059243Sobrien}
207159243Sobrien
207259243Sobrien/*ARGSUSED*/
207359243SobrienCCRETVAL
2074167465Smpe_normalize_command(Char c)
207559243Sobrien{
207659243Sobrien    USE(c);
207759243Sobrien    *LastChar = '\0';		/* just in case */
207859243Sobrien    return(CC_NORMALIZE_COMMAND);
207959243Sobrien}
208059243Sobrien
208159243Sobrien/*ARGSUSED*/
208259243SobrienCCRETVAL
2083167465Smpe_expand_vars(Char c)
208459243Sobrien{
208559243Sobrien    USE(c);
208659243Sobrien    *LastChar = '\0';		/* just in case */
208759243Sobrien    return(CC_EXPAND_VARS);
208859243Sobrien}
208959243Sobrien
209059243Sobrien/*ARGSUSED*/
209159243SobrienCCRETVAL
2092167465Smpe_which(Char c)
209359243Sobrien{				/* do a fast command line which(1) */
209459243Sobrien    USE(c);
2095167465Smp    c_save_inputbuf();
2096167465Smp    Hist_num = 0;		/* for the history commands */
209759243Sobrien    PastBottom();
209859243Sobrien    *LastChar = '\0';		/* just in case */
209959243Sobrien    return(CC_WHICH);
210059243Sobrien}
210159243Sobrien
210259243Sobrien/*ARGSUSED*/
210359243SobrienCCRETVAL
2104167465Smpe_last_item(Char c)
210559243Sobrien{				/* insert the last element of the prev. cmd */
210683098Smp    struct Hist *hp;
210783098Smp    struct wordent *wp, *firstp;
210883098Smp    int i;
2109167465Smp    Char *expanded;
211059243Sobrien
211159243Sobrien    USE(c);
211259243Sobrien    if (Argument <= 0)
211359243Sobrien	return(CC_ERROR);
211459243Sobrien
211559243Sobrien    hp = Histlist.Hnext;
211659243Sobrien    if (hp == NULL) {	/* this is only if no history */
211759243Sobrien	return(CC_ERROR);
211859243Sobrien    }
211959243Sobrien
212059243Sobrien    wp = (hp->Hlex).prev;
212159243Sobrien
212259243Sobrien    if (wp->prev == (struct wordent *) NULL)
212359243Sobrien	return(CC_ERROR);	/* an empty history entry */
212459243Sobrien
212559243Sobrien    firstp = (hp->Hlex).next;
212659243Sobrien
212759243Sobrien    /* back up arg words in lex */
212859243Sobrien    for (i = 0; i < Argument && wp != firstp; i++) {
212959243Sobrien	wp = wp->prev;
213059243Sobrien    }
213159243Sobrien
2132167465Smp    expanded = expand_lex(wp->prev, 0, i - 1);
2133167465Smp    if (InsertStr(expanded)) {
2134167465Smp	xfree(expanded);
213559243Sobrien	return(CC_ERROR);
2136167465Smp    }
213759243Sobrien
2138167465Smp    xfree(expanded);
213959243Sobrien    return(CC_REFRESH);
214059243Sobrien}
214159243Sobrien
214259243Sobrien/*ARGSUSED*/
214359243SobrienCCRETVAL
2144167465Smpe_dabbrev_expand(Char c)
214559243Sobrien{				/* expand to preceding word matching prefix */
214683098Smp    Char *cp, *ncp, *bp;
214783098Smp    struct Hist *hp;
2148167465Smp    int arg = 0, i;
2149167465Smp    size_t len = 0;
2150145479Smp    int found = 0;
2151167465Smp    Char *hbuf;
215259243Sobrien    static int oldevent, hist, word;
215359243Sobrien    static Char *start, *oldcursor;
215459243Sobrien
215559243Sobrien    USE(c);
215659243Sobrien    if (Argument <= 0)
215759243Sobrien	return(CC_ERROR);
215859243Sobrien
215983098Smp    cp = c_preword(Cursor, InputBuf, 1, STRshwordsep);
216059243Sobrien    if (cp == Cursor || Isspace(*cp))
216159243Sobrien	return(CC_ERROR);
216259243Sobrien
2163167465Smp    hbuf = NULL;
216459243Sobrien    hp = Histlist.Hnext;
216559243Sobrien    bp = InputBuf;
216659243Sobrien    if (Argument == 1 && eventno == oldevent && cp == start &&
2167167465Smp	Cursor == oldcursor && patbuf.len > 0
2168167465Smp	&& Strncmp(patbuf.s, cp, patbuf.len) == 0){
216959243Sobrien	/* continue previous search - go to last match (hist/word) */
217059243Sobrien	if (hist != 0) {		/* need to move up history */
217159243Sobrien	    for (i = 1; i < hist && hp != NULL; i++)
217259243Sobrien		hp = hp->Hnext;
217359243Sobrien	    if (hp == NULL)	/* "can't happen" */
2174167465Smp		goto err_hbuf;
2175167465Smp	    hbuf = expand_lex(&hp->Hlex, 0, INT_MAX);
2176167465Smp	    cp = Strend(hbuf);
217759243Sobrien	    bp = hbuf;
217859243Sobrien	    hp = hp->Hnext;
217959243Sobrien	}
218083098Smp	cp = c_preword(cp, bp, word, STRshwordsep);
218159243Sobrien    } else {			/* starting new search */
218259243Sobrien	oldevent = eventno;
218359243Sobrien	start = cp;
2184167465Smp	patbuf.len = 0;
2185167465Smp	Strbuf_appendn(&patbuf, cp, Cursor - cp);
218659243Sobrien	hist = 0;
218759243Sobrien	word = 0;
218859243Sobrien    }
218959243Sobrien
219059243Sobrien    while (!found) {
219183098Smp	ncp = c_preword(cp, bp, 1, STRshwordsep);
219259243Sobrien	if (ncp == cp || Isspace(*ncp)) { /* beginning of line */
219359243Sobrien	    hist++;
219459243Sobrien	    word = 0;
219559243Sobrien	    if (hp == NULL)
2196167465Smp		goto err_hbuf;
2197167465Smp	    hbuf = expand_lex(&hp->Hlex, 0, INT_MAX);
2198167465Smp	    cp = Strend(hbuf);
219959243Sobrien	    bp = hbuf;
220059243Sobrien	    hp = hp->Hnext;
220159243Sobrien	    continue;
220259243Sobrien	} else {
220359243Sobrien	    word++;
2204167465Smp	    len = c_endword(ncp-1, cp, 1, STRshwordsep) - ncp + 1;
220559243Sobrien	    cp = ncp;
220659243Sobrien	}
2207167465Smp	if (len > patbuf.len && Strncmp(cp, patbuf.s, patbuf.len) == 0) {
220859243Sobrien	    /* We don't fully check distinct matches as Gnuemacs does: */
220959243Sobrien	    if (Argument > 1) {	/* just count matches */
221059243Sobrien		if (++arg >= Argument)
221159243Sobrien		    found++;
221259243Sobrien	    } else {		/* match if distinct from previous */
2213167465Smp		if (len != (size_t)(Cursor - start)
2214167465Smp		    || Strncmp(cp, start, len) != 0)
221559243Sobrien		    found++;
221659243Sobrien	    }
221759243Sobrien	}
221859243Sobrien    }
221959243Sobrien
222059243Sobrien    if (LastChar + len - (Cursor - start) >= InputLim)
2221167465Smp	goto err_hbuf;	/* no room */
222259243Sobrien    DeleteBack(Cursor - start);
222359243Sobrien    c_insert(len);
222459243Sobrien    while (len--)
222559243Sobrien	*Cursor++ = *cp++;
222659243Sobrien    oldcursor = Cursor;
2227167465Smp    xfree(hbuf);
222859243Sobrien    return(CC_REFRESH);
2229167465Smp
2230167465Smp err_hbuf:
2231167465Smp    xfree(hbuf);
2232167465Smp    return CC_ERROR;
223359243Sobrien}
223459243Sobrien
223559243Sobrien/*ARGSUSED*/
223659243SobrienCCRETVAL
2237167465Smpe_yank_kill(Char c)
223859243Sobrien{				/* almost like GnuEmacs */
223983098Smp    int len;
224083098Smp    Char *kp, *cp;
224159243Sobrien
224259243Sobrien    USE(c);
224383098Smp    if (KillRingLen == 0)	/* nothing killed */
224459243Sobrien	return(CC_ERROR);
224583098Smp    len = Strlen(KillRing[YankPos].buf);
224683098Smp    if (LastChar + len >= InputLim)
224759243Sobrien	return(CC_ERROR);	/* end of buffer space */
224859243Sobrien
224959243Sobrien    /* else */
225059243Sobrien    cp = Cursor;		/* for speed */
225159243Sobrien
225283098Smp    c_insert(len);		/* open the space, */
225383098Smp    for (kp = KillRing[YankPos].buf; *kp; kp++)	/* copy the chars */
225459243Sobrien	*cp++ = *kp;
225559243Sobrien
225683098Smp    if (Argument == 1) {	/* if no arg */
225783098Smp	Mark = Cursor;		/* mark at beginning, cursor at end */
225883098Smp	Cursor = cp;
225983098Smp    } else {
226083098Smp	Mark = cp;		/* else cursor at beginning, mark at end */
226183098Smp    }
226259243Sobrien
2263167465Smp    if (adrof(STRhighlight) && MarkIsSet) {
2264167465Smp	ClearLines();
2265167465Smp	ClearDisp();
2266167465Smp    }
2267167465Smp    MarkIsSet = 0;
226859243Sobrien    return(CC_REFRESH);
226959243Sobrien}
227059243Sobrien
227159243Sobrien/*ARGSUSED*/
227259243SobrienCCRETVAL
2273167465Smpe_yank_pop(Char c)
227483098Smp{				/* almost like GnuEmacs */
227583098Smp    int m_bef_c, del_len, ins_len;
227683098Smp    Char *kp, *cp;
227783098Smp
227883098Smp    USE(c);
227983098Smp
228083098Smp#if 0
228183098Smp    /* XXX This "should" be here, but doesn't work, since LastCmd
228283098Smp       gets set on CC_ERROR and CC_ARGHACK, which it shouldn't(?).
228383098Smp       (But what about F_ARGFOUR?) I.e. if you hit M-y twice the
228483098Smp       second one will "succeed" even if the first one wasn't preceded
228583098Smp       by a yank, and giving an argument is impossible. Now we "succeed"
228683098Smp       regardless of previous command, which is wrong too of course. */
228783098Smp    if (LastCmd != F_YANK_KILL && LastCmd != F_YANK_POP)
228883098Smp	return(CC_ERROR);
228983098Smp#endif
229083098Smp
229183098Smp    if (KillRingLen == 0)	/* nothing killed */
229283098Smp	return(CC_ERROR);
229383098Smp    YankPos -= Argument;
229483098Smp    while (YankPos < 0)
229583098Smp	YankPos += KillRingLen;
229683098Smp    YankPos %= KillRingLen;
229783098Smp
229883098Smp    if (Cursor > Mark) {
229983098Smp	del_len = Cursor - Mark;
230083098Smp	m_bef_c = 1;
230183098Smp    } else {
230283098Smp	del_len = Mark - Cursor;
230383098Smp	m_bef_c = 0;
230483098Smp    }
230583098Smp    ins_len = Strlen(KillRing[YankPos].buf);
230683098Smp    if (LastChar + ins_len - del_len >= InputLim)
230783098Smp	return(CC_ERROR);	/* end of buffer space */
230883098Smp
230983098Smp    if (m_bef_c) {
231083098Smp	c_delbefore(del_len);
231183098Smp    } else {
231283098Smp	c_delafter(del_len);
231383098Smp    }
231483098Smp    cp = Cursor;		/* for speed */
231583098Smp
231683098Smp    c_insert(ins_len);		/* open the space, */
231783098Smp    for (kp = KillRing[YankPos].buf; *kp; kp++)	/* copy the chars */
231883098Smp	*cp++ = *kp;
231983098Smp
232083098Smp    if (m_bef_c) {
232183098Smp	Mark = Cursor;		/* mark at beginning, cursor at end */
232283098Smp	Cursor = cp;
232383098Smp    } else {
232483098Smp	Mark = cp;		/* else cursor at beginning, mark at end */
232583098Smp    }
232683098Smp
2327167465Smp    if (adrof(STRhighlight) && MarkIsSet) {
2328167465Smp	ClearLines();
2329167465Smp	ClearDisp();
2330167465Smp    }
2331167465Smp    MarkIsSet = 0;
233283098Smp    return(CC_REFRESH);
233383098Smp}
233483098Smp
233583098Smp/*ARGSUSED*/
233683098SmpCCRETVAL
2337167465Smpv_delprev(Char c) 		/* Backspace key in insert mode */
233859243Sobrien{
233959243Sobrien    int rc;
234059243Sobrien
234159243Sobrien    USE(c);
234259243Sobrien    rc = CC_ERROR;
234359243Sobrien
234459243Sobrien    if (InsertPos != 0) {
234559243Sobrien	if (Argument <= Cursor - InsertPos) {
234659243Sobrien	    c_delbefore(Argument);	/* delete before */
234759243Sobrien	    rc = CC_REFRESH;
234859243Sobrien	}
234959243Sobrien    }
235059243Sobrien    return(rc);
235159243Sobrien}   /* v_delprev  */
235259243Sobrien
235359243Sobrien/*ARGSUSED*/
235459243SobrienCCRETVAL
2355167465Smpe_delprev(Char c)
235659243Sobrien{
235759243Sobrien    USE(c);
235859243Sobrien    if (Cursor > InputBuf) {
235959243Sobrien	c_delbefore(Argument);	/* delete before dot */
236059243Sobrien	return(CC_REFRESH);
236159243Sobrien    }
236259243Sobrien    else {
236359243Sobrien	return(CC_ERROR);
236459243Sobrien    }
236559243Sobrien}
236659243Sobrien
236759243Sobrien/*ARGSUSED*/
236859243SobrienCCRETVAL
2369167465Smpe_delwordprev(Char c)
237059243Sobrien{
237183098Smp    Char *cp;
237259243Sobrien
237359243Sobrien    USE(c);
237459243Sobrien    if (Cursor == InputBuf)
237559243Sobrien	return(CC_ERROR);
237659243Sobrien    /* else */
237759243Sobrien
237859243Sobrien    cp = c_prev_word(Cursor, InputBuf, Argument);
237959243Sobrien
238083098Smp    c_push_kill(cp, Cursor);	/* save the text */
238159243Sobrien
238259243Sobrien    c_delbefore((int)(Cursor - cp));	/* delete before dot */
238359243Sobrien    return(CC_REFRESH);
238459243Sobrien}
238559243Sobrien
238659243Sobrien/* DCS <dcs@neutron.chem.yale.edu>, 9 Oct 93
238759243Sobrien *
238859243Sobrien * Changed the names of some of the ^D family of editor functions to
238959243Sobrien * correspond to what they actually do and created new e_delnext_list
239059243Sobrien * for completeness.
239159243Sobrien *
239259243Sobrien *   Old names:			New names:
239359243Sobrien *
239459243Sobrien *   delete-char		delete-char-or-eof
239559243Sobrien *     F_DELNEXT		  F_DELNEXT_EOF
239659243Sobrien *     e_delnext		  e_delnext_eof
239759243Sobrien *     edelnxt			  edelnxteof
239859243Sobrien *   delete-char-or-eof		delete-char
239959243Sobrien *     F_DELNEXT_EOF		  F_DELNEXT
240059243Sobrien *     e_delnext_eof		  e_delnext
240159243Sobrien *     edelnxteof		  edelnxt
240259243Sobrien *   delete-char-or-list	delete-char-or-list-or-eof
240359243Sobrien *     F_LIST_DELNEXT		  F_DELNEXT_LIST_EOF
240459243Sobrien *     e_list_delnext		  e_delnext_list_eof
240559243Sobrien *   				  edellsteof
240659243Sobrien *   (no old equivalent)	delete-char-or-list
240759243Sobrien *   				  F_DELNEXT_LIST
240859243Sobrien *   				  e_delnext_list
240959243Sobrien *   				  e_delnxtlst
241059243Sobrien */
241159243Sobrien
241259243Sobrien/* added by mtk@ari.ncl.omron.co.jp (920818) */
241359243Sobrien/* rename e_delnext() -> e_delnext_eof() */
241459243Sobrien/*ARGSUSED*/
241559243SobrienCCRETVAL
2416167465Smpe_delnext(Char c)
241759243Sobrien{
241859243Sobrien    USE(c);
241959243Sobrien    if (Cursor == LastChar) {/* if I'm at the end */
242059243Sobrien	if (!VImode) {
242159243Sobrien		return(CC_ERROR);
242259243Sobrien	}
242359243Sobrien	else {
242459243Sobrien	    if (Cursor != InputBuf)
242559243Sobrien		Cursor--;
242659243Sobrien	    else
242759243Sobrien		return(CC_ERROR);
242859243Sobrien	}
242959243Sobrien    }
243059243Sobrien    c_delafter(Argument);	/* delete after dot */
243159243Sobrien    if (Cursor > LastChar)
243259243Sobrien	Cursor = LastChar;	/* bounds check */
243359243Sobrien    return(CC_REFRESH);
243459243Sobrien}
243559243Sobrien
243659243Sobrien
243759243Sobrien/*ARGSUSED*/
243859243SobrienCCRETVAL
2439167465Smpe_delnext_eof(Char c)
244059243Sobrien{
244159243Sobrien    USE(c);
244259243Sobrien    if (Cursor == LastChar) {/* if I'm at the end */
244359243Sobrien	if (!VImode) {
244459243Sobrien	    if (Cursor == InputBuf) {
244559243Sobrien		/* if I'm also at the beginning */
244659243Sobrien		so_write(STReof, 4);/* then do a EOF */
244759243Sobrien		flush();
244859243Sobrien		return(CC_EOF);
244959243Sobrien	    }
245059243Sobrien	    else
245159243Sobrien		return(CC_ERROR);
245259243Sobrien	}
245359243Sobrien	else {
245459243Sobrien	    if (Cursor != InputBuf)
245559243Sobrien		Cursor--;
245659243Sobrien	    else
245759243Sobrien		return(CC_ERROR);
245859243Sobrien	}
245959243Sobrien    }
246059243Sobrien    c_delafter(Argument);	/* delete after dot */
246159243Sobrien    if (Cursor > LastChar)
246259243Sobrien	Cursor = LastChar;	/* bounds check */
246359243Sobrien    return(CC_REFRESH);
246459243Sobrien}
246559243Sobrien
246659243Sobrien/*ARGSUSED*/
246759243SobrienCCRETVAL
2468167465Smpe_delnext_list(Char c)
246959243Sobrien{
247059243Sobrien    USE(c);
247159243Sobrien    if (Cursor == LastChar) {	/* if I'm at the end */
247259243Sobrien	PastBottom();
247359243Sobrien	*LastChar = '\0';	/* just in case */
247459243Sobrien	return(CC_LIST_CHOICES);
247559243Sobrien    }
247659243Sobrien    else {
247759243Sobrien	c_delafter(Argument);	/* delete after dot */
247859243Sobrien	if (Cursor > LastChar)
247959243Sobrien	    Cursor = LastChar;	/* bounds check */
248059243Sobrien	return(CC_REFRESH);
248159243Sobrien    }
248259243Sobrien}
248359243Sobrien
248459243Sobrien/*ARGSUSED*/
248559243SobrienCCRETVAL
2486167465Smpe_delnext_list_eof(Char c)
248759243Sobrien{
248859243Sobrien    USE(c);
248959243Sobrien    if (Cursor == LastChar) {	/* if I'm at the end */
249059243Sobrien	if (Cursor == InputBuf) {	/* if I'm also at the beginning */
249159243Sobrien	    so_write(STReof, 4);/* then do a EOF */
249259243Sobrien	    flush();
249359243Sobrien	    return(CC_EOF);
249459243Sobrien	}
249559243Sobrien	else {
249659243Sobrien	    PastBottom();
249759243Sobrien	    *LastChar = '\0';	/* just in case */
249859243Sobrien	    return(CC_LIST_CHOICES);
249959243Sobrien	}
250059243Sobrien    }
250159243Sobrien    else {
250259243Sobrien	c_delafter(Argument);	/* delete after dot */
250359243Sobrien	if (Cursor > LastChar)
250459243Sobrien	    Cursor = LastChar;	/* bounds check */
250559243Sobrien	return(CC_REFRESH);
250659243Sobrien    }
250759243Sobrien}
250859243Sobrien
250959243Sobrien/*ARGSUSED*/
251059243SobrienCCRETVAL
2511167465Smpe_list_eof(Char c)
251259243Sobrien{
251359243Sobrien    CCRETVAL rv;
251459243Sobrien
251559243Sobrien    USE(c);
251659243Sobrien    if (Cursor == LastChar && Cursor == InputBuf) {
251759243Sobrien	so_write(STReof, 4);	/* then do a EOF */
251859243Sobrien	flush();
251959243Sobrien	rv = CC_EOF;
252059243Sobrien    }
252159243Sobrien    else {
252259243Sobrien	PastBottom();
252359243Sobrien	*LastChar = '\0';	/* just in case */
252459243Sobrien	rv = CC_LIST_CHOICES;
252559243Sobrien    }
252659243Sobrien    return rv;
252759243Sobrien}
252859243Sobrien
252959243Sobrien/*ARGSUSED*/
253059243SobrienCCRETVAL
2531167465Smpe_delwordnext(Char c)
253259243Sobrien{
253383098Smp    Char *cp;
253459243Sobrien
253559243Sobrien    USE(c);
253659243Sobrien    if (Cursor == LastChar)
253759243Sobrien	return(CC_ERROR);
253859243Sobrien    /* else */
253959243Sobrien
254059243Sobrien    cp = c_next_word(Cursor, LastChar, Argument);
254159243Sobrien
254283098Smp    c_push_kill(Cursor, cp);	/* save the text */
254359243Sobrien
254459243Sobrien    c_delafter((int)(cp - Cursor));	/* delete after dot */
254559243Sobrien    if (Cursor > LastChar)
254659243Sobrien	Cursor = LastChar;	/* bounds check */
254759243Sobrien    return(CC_REFRESH);
254859243Sobrien}
254959243Sobrien
255059243Sobrien/*ARGSUSED*/
255159243SobrienCCRETVAL
2552167465Smpe_toend(Char c)
255359243Sobrien{
255459243Sobrien    USE(c);
255559243Sobrien    Cursor = LastChar;
255659243Sobrien    if (VImode)
255759243Sobrien	if (ActionFlag & TCSHOP_DELETE) {
255859243Sobrien	    c_delfini();
255959243Sobrien	    return(CC_REFRESH);
256059243Sobrien	}
256159243Sobrien    RefCursor();		/* move the cursor */
256259243Sobrien    return(CC_NORM);
256359243Sobrien}
256459243Sobrien
256559243Sobrien/*ARGSUSED*/
256659243SobrienCCRETVAL
2567167465Smpe_tobeg(Char c)
256859243Sobrien{
256959243Sobrien    USE(c);
257059243Sobrien    Cursor = InputBuf;
257159243Sobrien
257259243Sobrien    if (VImode) {
257359243Sobrien       while (Isspace(*Cursor)) /* We want FIRST non space character */
257459243Sobrien	Cursor++;
257559243Sobrien	if (ActionFlag & TCSHOP_DELETE) {
257659243Sobrien	    c_delfini();
257759243Sobrien	    return(CC_REFRESH);
257859243Sobrien	}
257959243Sobrien    }
258059243Sobrien
258159243Sobrien    RefCursor();		/* move the cursor */
258259243Sobrien    return(CC_NORM);
258359243Sobrien}
258459243Sobrien
258559243Sobrien/*ARGSUSED*/
258659243SobrienCCRETVAL
2587167465Smpe_killend(Char c)
258859243Sobrien{
258959243Sobrien    USE(c);
259083098Smp    c_push_kill(Cursor, LastChar); /* copy it */
2591167465Smp    LastChar = Cursor;		/* zap! -- delete to end */
2592167465Smp    if (Mark > Cursor)
2593167465Smp        Mark = Cursor;
2594167465Smp    MarkIsSet = 0;
259559243Sobrien    return(CC_REFRESH);
259659243Sobrien}
259759243Sobrien
259859243Sobrien
259959243Sobrien/*ARGSUSED*/
260059243SobrienCCRETVAL
2601167465Smpe_killbeg(Char c)
260259243Sobrien{
260359243Sobrien    USE(c);
260483098Smp    c_push_kill(InputBuf, Cursor); /* copy it */
260559243Sobrien    c_delbefore((int)(Cursor - InputBuf));
2606145479Smp    if (Mark && Mark > Cursor)
2607145479Smp        Mark -= Cursor-InputBuf;
260859243Sobrien    return(CC_REFRESH);
260959243Sobrien}
261059243Sobrien
261159243Sobrien/*ARGSUSED*/
261259243SobrienCCRETVAL
2613167465Smpe_killall(Char c)
261459243Sobrien{
261559243Sobrien    USE(c);
261683098Smp    c_push_kill(InputBuf, LastChar); /* copy it */
2617145479Smp    Cursor = Mark = LastChar = InputBuf;	/* zap! -- delete all of it */
2618167465Smp    MarkIsSet = 0;
261959243Sobrien    return(CC_REFRESH);
262059243Sobrien}
262159243Sobrien
262259243Sobrien/*ARGSUSED*/
262359243SobrienCCRETVAL
2624167465Smpe_killregion(Char c)
262559243Sobrien{
262659243Sobrien    USE(c);
262759243Sobrien    if (!Mark)
262859243Sobrien	return(CC_ERROR);
262959243Sobrien
263059243Sobrien    if (Mark > Cursor) {
263183098Smp	c_push_kill(Cursor, Mark); /* copy it */
263283098Smp	c_delafter((int)(Mark - Cursor)); /* delete it - UNUSED BY VI mode */
263383098Smp	Mark = Cursor;
263459243Sobrien    }
263559243Sobrien    else {			/* mark is before cursor */
263683098Smp	c_push_kill(Mark, Cursor); /* copy it */
263783098Smp	c_delbefore((int)(Cursor - Mark));
263859243Sobrien    }
2639167465Smp    if (adrof(STRhighlight) && MarkIsSet) {
2640167465Smp	ClearLines();
2641167465Smp	ClearDisp();
2642167465Smp    }
2643167465Smp    MarkIsSet = 0;
264459243Sobrien    return(CC_REFRESH);
264559243Sobrien}
264659243Sobrien
264759243Sobrien/*ARGSUSED*/
264859243SobrienCCRETVAL
2649167465Smpe_copyregion(Char c)
265059243Sobrien{
265159243Sobrien    USE(c);
265259243Sobrien    if (!Mark)
265359243Sobrien	return(CC_ERROR);
265459243Sobrien
265559243Sobrien    if (Mark > Cursor) {
265683098Smp	c_push_kill(Cursor, Mark); /* copy it */
265759243Sobrien    }
265859243Sobrien    else {			/* mark is before cursor */
265983098Smp	c_push_kill(Mark, Cursor); /* copy it */
266059243Sobrien    }
266159243Sobrien    return(CC_NORM);		/* don't even need to Refresh() */
266259243Sobrien}
266359243Sobrien
266459243Sobrien/*ARGSUSED*/
266559243SobrienCCRETVAL
2666167465Smpe_charswitch(Char cc)
266759243Sobrien{
266883098Smp    Char c;
266959243Sobrien
267059243Sobrien    USE(cc);
267159243Sobrien
267259243Sobrien    /* do nothing if we are at beginning of line or have only one char */
267359243Sobrien    if (Cursor == &InputBuf[0] || LastChar == &InputBuf[1]) {
267459243Sobrien	return(CC_ERROR);
267559243Sobrien    }
267659243Sobrien
267759243Sobrien    if (Cursor < LastChar) {
267859243Sobrien	Cursor++;
267959243Sobrien    }
268059243Sobrien    c = Cursor[-2];
268159243Sobrien    Cursor[-2] = Cursor[-1];
268259243Sobrien    Cursor[-1] = c;
268359243Sobrien    return(CC_REFRESH);
268459243Sobrien}
268559243Sobrien
268659243Sobrien/*ARGSUSED*/
268759243SobrienCCRETVAL
2688167465Smpe_gcharswitch(Char cc)
268959243Sobrien{				/* gosmacs style ^T */
269083098Smp    Char c;
269159243Sobrien
269259243Sobrien    USE(cc);
269359243Sobrien    if (Cursor > &InputBuf[1]) {/* must have at least two chars entered */
269459243Sobrien	c = Cursor[-2];
269559243Sobrien	Cursor[-2] = Cursor[-1];
269659243Sobrien	Cursor[-1] = c;
269759243Sobrien	return(CC_REFRESH);
269859243Sobrien    }
269959243Sobrien    else {
270059243Sobrien	return(CC_ERROR);
270159243Sobrien    }
270259243Sobrien}
270359243Sobrien
270459243Sobrien/*ARGSUSED*/
270559243SobrienCCRETVAL
2706167465Smpe_charback(Char c)
270759243Sobrien{
270859243Sobrien    USE(c);
270959243Sobrien    if (Cursor > InputBuf) {
2710167465Smp	if (Argument > Cursor - InputBuf)
271159243Sobrien	    Cursor = InputBuf;
271259243Sobrien	else
2713167465Smp	    Cursor -= Argument;
271459243Sobrien
271559243Sobrien	if (VImode)
271659243Sobrien	    if (ActionFlag & TCSHOP_DELETE) {
271759243Sobrien		c_delfini();
271859243Sobrien		return(CC_REFRESH);
271959243Sobrien	    }
272059243Sobrien
272159243Sobrien	RefCursor();
272259243Sobrien	return(CC_NORM);
272359243Sobrien    }
272459243Sobrien    else {
272559243Sobrien	return(CC_ERROR);
272659243Sobrien    }
272759243Sobrien}
272859243Sobrien
272959243Sobrien/*ARGSUSED*/
273059243SobrienCCRETVAL
2731167465Smpv_wordback(Char c)
273259243Sobrien{
273359243Sobrien    USE(c);
273459243Sobrien    if (Cursor == InputBuf)
273559243Sobrien	return(CC_ERROR);
273659243Sobrien    /* else */
273759243Sobrien
273883098Smp    Cursor = c_preword(Cursor, InputBuf, Argument, STRshwspace); /* bounds check */
273959243Sobrien
274059243Sobrien    if (ActionFlag & TCSHOP_DELETE) {
274159243Sobrien	c_delfini();
274259243Sobrien	return(CC_REFRESH);
274359243Sobrien    }
274459243Sobrien
274559243Sobrien    RefCursor();
274659243Sobrien    return(CC_NORM);
274759243Sobrien}
274859243Sobrien
274959243Sobrien/*ARGSUSED*/
275059243SobrienCCRETVAL
2751167465Smpe_wordback(Char c)
275259243Sobrien{
275359243Sobrien    USE(c);
275459243Sobrien    if (Cursor == InputBuf)
275559243Sobrien	return(CC_ERROR);
275659243Sobrien    /* else */
275759243Sobrien
275859243Sobrien    Cursor = c_prev_word(Cursor, InputBuf, Argument); /* bounds check */
275959243Sobrien
276059243Sobrien    if (VImode)
276159243Sobrien	if (ActionFlag & TCSHOP_DELETE) {
276259243Sobrien	    c_delfini();
276359243Sobrien	    return(CC_REFRESH);
276459243Sobrien	}
276559243Sobrien
276659243Sobrien    RefCursor();
276759243Sobrien    return(CC_NORM);
276859243Sobrien}
276959243Sobrien
277059243Sobrien/*ARGSUSED*/
277159243SobrienCCRETVAL
2772167465Smpe_charfwd(Char c)
277359243Sobrien{
277459243Sobrien    USE(c);
277559243Sobrien    if (Cursor < LastChar) {
2776167465Smp	Cursor += Argument;
277759243Sobrien	if (Cursor > LastChar)
277859243Sobrien	    Cursor = LastChar;
277959243Sobrien
278059243Sobrien	if (VImode)
278159243Sobrien	    if (ActionFlag & TCSHOP_DELETE) {
278259243Sobrien		c_delfini();
278359243Sobrien		return(CC_REFRESH);
278459243Sobrien	    }
278559243Sobrien
278659243Sobrien	RefCursor();
278759243Sobrien	return(CC_NORM);
278859243Sobrien    }
278959243Sobrien    else {
279059243Sobrien	return(CC_ERROR);
279159243Sobrien    }
279259243Sobrien}
279359243Sobrien
279459243Sobrien/*ARGSUSED*/
279559243SobrienCCRETVAL
2796167465Smpe_wordfwd(Char c)
279759243Sobrien{
279859243Sobrien    USE(c);
279959243Sobrien    if (Cursor == LastChar)
280059243Sobrien	return(CC_ERROR);
280159243Sobrien    /* else */
280259243Sobrien
280359243Sobrien    Cursor = c_next_word(Cursor, LastChar, Argument);
280459243Sobrien
280559243Sobrien    if (VImode)
280659243Sobrien	if (ActionFlag & TCSHOP_DELETE) {
280759243Sobrien	    c_delfini();
280859243Sobrien	    return(CC_REFRESH);
280959243Sobrien	}
281059243Sobrien
281159243Sobrien    RefCursor();
281259243Sobrien    return(CC_NORM);
281359243Sobrien}
281459243Sobrien
281559243Sobrien/*ARGSUSED*/
281659243SobrienCCRETVAL
2817167465Smpv_wordfwd(Char c)
281859243Sobrien{
281959243Sobrien    USE(c);
282059243Sobrien    if (Cursor == LastChar)
282159243Sobrien	return(CC_ERROR);
282259243Sobrien    /* else */
282359243Sobrien
282459243Sobrien    Cursor = c_nexword(Cursor, LastChar, Argument);
282559243Sobrien
282659243Sobrien    if (VImode)
282759243Sobrien	if (ActionFlag & TCSHOP_DELETE) {
282859243Sobrien	    c_delfini();
282959243Sobrien	    return(CC_REFRESH);
283059243Sobrien	}
283159243Sobrien
283259243Sobrien    RefCursor();
283359243Sobrien    return(CC_NORM);
283459243Sobrien}
283559243Sobrien
283659243Sobrien/*ARGSUSED*/
283759243SobrienCCRETVAL
2838167465Smpv_wordbegnext(Char c)
283959243Sobrien{
284059243Sobrien    USE(c);
284159243Sobrien    if (Cursor == LastChar)
284259243Sobrien	return(CC_ERROR);
284359243Sobrien    /* else */
284459243Sobrien
284559243Sobrien    Cursor = c_next_word(Cursor, LastChar, Argument);
284659243Sobrien    if (Cursor < LastChar)
284759243Sobrien	Cursor++;
284859243Sobrien
284959243Sobrien    if (VImode)
285059243Sobrien	if (ActionFlag & TCSHOP_DELETE) {
285159243Sobrien	    c_delfini();
285259243Sobrien	    return(CC_REFRESH);
285359243Sobrien	}
285459243Sobrien
285559243Sobrien    RefCursor();
285659243Sobrien    return(CC_NORM);
285759243Sobrien}
285859243Sobrien
285959243Sobrien/*ARGSUSED*/
286059243Sobrienstatic CCRETVAL
2861167465Smpv_repeat_srch(int c)
286259243Sobrien{
286359243Sobrien    CCRETVAL rv = CC_ERROR;
286459243Sobrien#ifdef SDEBUG
2865167465Smp    xprintf("dir %d patlen %d patbuf %S\n",
2866167465Smp	    c, (int)patbuf.len, patbuf.s);
286759243Sobrien#endif
286859243Sobrien
286959243Sobrien    LastCmd = (KEYCMD) c;  /* Hack to stop c_hsetpat */
287059243Sobrien    LastChar = InputBuf;
287159243Sobrien    switch (c) {
287259243Sobrien    case F_DOWN_SEARCH_HIST:
287359243Sobrien	rv = e_down_search_hist(0);
287459243Sobrien	break;
287559243Sobrien    case F_UP_SEARCH_HIST:
287659243Sobrien	rv = e_up_search_hist(0);
287759243Sobrien	break;
287859243Sobrien    default:
287959243Sobrien	break;
288059243Sobrien    }
288159243Sobrien    return rv;
288259243Sobrien}
288359243Sobrien
288459243Sobrienstatic CCRETVAL
2885167465Smpv_csearch_back(Char ch, int count, int tflag)
288659243Sobrien{
288759243Sobrien    Char *cp;
288859243Sobrien
288959243Sobrien    cp = Cursor;
289059243Sobrien    while (count--) {
289159243Sobrien	if (*cp == ch)
289259243Sobrien	    cp--;
289359243Sobrien	while (cp > InputBuf && *cp != ch)
289459243Sobrien	    cp--;
289559243Sobrien    }
289659243Sobrien
289759243Sobrien    if (cp < InputBuf || (cp == InputBuf && *cp != ch))
289859243Sobrien	return(CC_ERROR);
289959243Sobrien
290059243Sobrien    if (*cp == ch && tflag)
290159243Sobrien	cp++;
290259243Sobrien
290359243Sobrien    Cursor = cp;
290459243Sobrien
290559243Sobrien    if (ActionFlag & TCSHOP_DELETE) {
290659243Sobrien	Cursor++;
290759243Sobrien	c_delfini();
290859243Sobrien	return(CC_REFRESH);
290959243Sobrien    }
291059243Sobrien
291159243Sobrien    RefCursor();
291259243Sobrien    return(CC_NORM);
291359243Sobrien}
291459243Sobrien
291559243Sobrienstatic CCRETVAL
2916167465Smpv_csearch_fwd(Char ch, int count, int tflag)
291759243Sobrien{
291859243Sobrien    Char *cp;
291959243Sobrien
292059243Sobrien    cp = Cursor;
292159243Sobrien    while (count--) {
292259243Sobrien	if(*cp == ch)
292359243Sobrien	    cp++;
292459243Sobrien	while (cp < LastChar && *cp != ch)
292559243Sobrien	    cp++;
292659243Sobrien    }
292759243Sobrien
292859243Sobrien    if (cp >= LastChar)
292959243Sobrien	return(CC_ERROR);
293059243Sobrien
293159243Sobrien    if (*cp == ch && tflag)
293259243Sobrien	cp--;
293359243Sobrien
293459243Sobrien    Cursor = cp;
293559243Sobrien
293659243Sobrien    if (ActionFlag & TCSHOP_DELETE) {
293759243Sobrien	Cursor++;
293859243Sobrien	c_delfini();
293959243Sobrien	return(CC_REFRESH);
294059243Sobrien    }
294159243Sobrien    RefCursor();
294259243Sobrien    return(CC_NORM);
294359243Sobrien}
294459243Sobrien
294559243Sobrien/*ARGSUSED*/
294659243Sobrienstatic CCRETVAL
2947167465Smpv_action(int c)
294859243Sobrien{
294983098Smp    Char *cp, *kp;
295059243Sobrien
295159243Sobrien    if (ActionFlag == TCSHOP_DELETE) {
295259243Sobrien	ActionFlag = TCSHOP_NOP;
295359243Sobrien	ActionPos = 0;
295459243Sobrien
295559243Sobrien	UndoSize = 0;
295659243Sobrien	kp = UndoBuf;
295759243Sobrien	for (cp = InputBuf; cp < LastChar; cp++) {
295859243Sobrien	    *kp++ = *cp;
295959243Sobrien	    UndoSize++;
296059243Sobrien	}
296159243Sobrien
296259243Sobrien	UndoAction = TCSHOP_INSERT;
296359243Sobrien	UndoPtr  = InputBuf;
296459243Sobrien	LastChar = InputBuf;
296559243Sobrien	Cursor   = InputBuf;
296659243Sobrien	if (c & TCSHOP_INSERT)
296759243Sobrien	    c_alternativ_key_map(0);
296859243Sobrien
296959243Sobrien	return(CC_REFRESH);
297059243Sobrien    }
297159243Sobrien#ifdef notdef
297259243Sobrien    else if (ActionFlag == TCSHOP_NOP) {
297359243Sobrien#endif
297459243Sobrien	ActionPos = Cursor;
297559243Sobrien	ActionFlag = c;
297659243Sobrien	return(CC_ARGHACK);  /* Do NOT clear out argument */
297759243Sobrien#ifdef notdef
297859243Sobrien    }
297959243Sobrien    else {
298059243Sobrien	ActionFlag = 0;
298159243Sobrien	ActionPos = 0;
298259243Sobrien	return(CC_ERROR);
298359243Sobrien    }
298459243Sobrien#endif
298559243Sobrien}
298659243Sobrien
298759243Sobrien#ifdef COMMENT
298859243Sobrien/* by: Brian Allison <uiucdcs!convex!allison@RUTGERS.EDU> */
298959243Sobrienstatic void
2990167465Smpc_get_word(Char **begin, Char **end)
299159243Sobrien{
299259243Sobrien    Char   *cp;
299359243Sobrien
299459243Sobrien    cp = &Cursor[0];
299559243Sobrien    while (Argument--) {
299659243Sobrien	while ((cp <= LastChar) && (isword(*cp)))
299759243Sobrien	    cp++;
299859243Sobrien	*end = --cp;
299959243Sobrien	while ((cp >= InputBuf) && (isword(*cp)))
300059243Sobrien	    cp--;
300159243Sobrien	*begin = ++cp;
300259243Sobrien    }
300359243Sobrien}
300459243Sobrien#endif /* COMMENT */
300559243Sobrien
300659243Sobrien/*ARGSUSED*/
300759243SobrienCCRETVAL
3008167465Smpe_uppercase(Char c)
300959243Sobrien{
301059243Sobrien    Char   *cp, *end;
301159243Sobrien
301259243Sobrien    USE(c);
301359243Sobrien    end = c_next_word(Cursor, LastChar, Argument);
301459243Sobrien
301559243Sobrien    for (cp = Cursor; cp < end; cp++)	/* PWP: was cp=begin */
301659243Sobrien	if (Islower(*cp))
301759243Sobrien	    *cp = Toupper(*cp);
301859243Sobrien
301959243Sobrien    Cursor = end;
302059243Sobrien    if (Cursor > LastChar)
302159243Sobrien	Cursor = LastChar;
302259243Sobrien    return(CC_REFRESH);
302359243Sobrien}
302459243Sobrien
302559243Sobrien
302659243Sobrien/*ARGSUSED*/
302759243SobrienCCRETVAL
3028167465Smpe_capitolcase(Char c)
302959243Sobrien{
303059243Sobrien    Char   *cp, *end;
303159243Sobrien
303259243Sobrien    USE(c);
303359243Sobrien    end = c_next_word(Cursor, LastChar, Argument);
303459243Sobrien
303559243Sobrien    cp = Cursor;
303659243Sobrien    for (; cp < end; cp++) {
303759243Sobrien	if (Isalpha(*cp)) {
303859243Sobrien	    if (Islower(*cp))
303959243Sobrien		*cp = Toupper(*cp);
304059243Sobrien	    cp++;
304159243Sobrien	    break;
304259243Sobrien	}
304359243Sobrien    }
304459243Sobrien    for (; cp < end; cp++)
304559243Sobrien	if (Isupper(*cp))
304659243Sobrien	    *cp = Tolower(*cp);
304759243Sobrien
304859243Sobrien    Cursor = end;
304959243Sobrien    if (Cursor > LastChar)
305059243Sobrien	Cursor = LastChar;
305159243Sobrien    return(CC_REFRESH);
305259243Sobrien}
305359243Sobrien
305459243Sobrien/*ARGSUSED*/
305559243SobrienCCRETVAL
3056167465Smpe_lowercase(Char c)
305759243Sobrien{
305859243Sobrien    Char   *cp, *end;
305959243Sobrien
306059243Sobrien    USE(c);
306159243Sobrien    end = c_next_word(Cursor, LastChar, Argument);
306259243Sobrien
306359243Sobrien    for (cp = Cursor; cp < end; cp++)
306459243Sobrien	if (Isupper(*cp))
306559243Sobrien	    *cp = Tolower(*cp);
306659243Sobrien
306759243Sobrien    Cursor = end;
306859243Sobrien    if (Cursor > LastChar)
306959243Sobrien	Cursor = LastChar;
307059243Sobrien    return(CC_REFRESH);
307159243Sobrien}
307259243Sobrien
307359243Sobrien
307459243Sobrien/*ARGSUSED*/
307559243SobrienCCRETVAL
3076167465Smpe_set_mark(Char c)
307759243Sobrien{
307859243Sobrien    USE(c);
3079167465Smp    if (adrof(STRhighlight) && MarkIsSet && Mark != Cursor) {
3080167465Smp	ClearLines();
3081167465Smp	ClearDisp();
3082167465Smp	Refresh();
3083167465Smp    }
308459243Sobrien    Mark = Cursor;
3085167465Smp    MarkIsSet = 1;
308659243Sobrien    return(CC_NORM);
308759243Sobrien}
308859243Sobrien
308959243Sobrien/*ARGSUSED*/
309059243SobrienCCRETVAL
3091167465Smpe_exchange_mark(Char c)
309259243Sobrien{
309383098Smp    Char *cp;
309459243Sobrien
309559243Sobrien    USE(c);
309659243Sobrien    cp = Cursor;
309759243Sobrien    Cursor = Mark;
309859243Sobrien    Mark = cp;
309959243Sobrien    RefCursor();
310059243Sobrien    return(CC_NORM);
310159243Sobrien}
310259243Sobrien
310359243Sobrien/*ARGSUSED*/
310459243SobrienCCRETVAL
3105167465Smpe_argfour(Char c)
310659243Sobrien{				/* multiply current argument by 4 */
310759243Sobrien    USE(c);
310859243Sobrien    if (Argument > 1000000)
310959243Sobrien	return CC_ERROR;
311059243Sobrien    DoingArg = 1;
311159243Sobrien    Argument *= 4;
311259243Sobrien    return(CC_ARGHACK);
311359243Sobrien}
311459243Sobrien
3115167465Smpstatic void
3116167465Smpquote_mode_cleanup(void *unused)
3117167465Smp{
3118167465Smp    USE(unused);
3119167465Smp    QuoteModeOff();
3120167465Smp}
3121167465Smp
312259243Sobrien/*ARGSUSED*/
312359243SobrienCCRETVAL
3124167465Smpe_quote(Char c)
312559243Sobrien{
312659243Sobrien    Char    ch;
312759243Sobrien    int     num;
312859243Sobrien
312959243Sobrien    USE(c);
313059243Sobrien    QuoteModeOn();
3131167465Smp    cleanup_push(&c, quote_mode_cleanup); /* Using &c just as a mark */
313259243Sobrien    num = GetNextChar(&ch);
3133167465Smp    cleanup_until(&c);
313459243Sobrien    if (num == 1)
313559243Sobrien	return e_insert(ch);
313659243Sobrien    else
313759243Sobrien	return e_send_eof(0);
313859243Sobrien}
313959243Sobrien
314059243Sobrien/*ARGSUSED*/
314159243SobrienCCRETVAL
3142167465Smpe_metanext(Char c)
314359243Sobrien{
314459243Sobrien    USE(c);
314559243Sobrien    MetaNext = 1;
314659243Sobrien    return(CC_ARGHACK);	/* preserve argument */
314759243Sobrien}
314859243Sobrien
314959243Sobrien#ifdef notdef
315059243Sobrien/*ARGSUSED*/
315159243SobrienCCRETVAL
3152167465Smpe_extendnext(Char c)
315359243Sobrien{
315459243Sobrien    CurrentKeyMap = CcAltMap;
315559243Sobrien    return(CC_ARGHACK);	/* preserve argument */
315659243Sobrien}
315759243Sobrien
315859243Sobrien#endif
315959243Sobrien
316059243Sobrien/*ARGSUSED*/
316159243SobrienCCRETVAL
3162167465Smpv_insbeg(Char c)
316359243Sobrien{				/* move to beginning of line and start vi
316459243Sobrien				 * insert mode */
316559243Sobrien    USE(c);
316659243Sobrien    Cursor = InputBuf;
316759243Sobrien    InsertPos = Cursor;
316859243Sobrien
316959243Sobrien    UndoPtr  = Cursor;
317059243Sobrien    UndoAction = TCSHOP_DELETE;
317159243Sobrien
317259243Sobrien    RefCursor();		/* move the cursor */
317359243Sobrien    c_alternativ_key_map(0);
317459243Sobrien    return(CC_NORM);
317559243Sobrien}
317659243Sobrien
317759243Sobrien/*ARGSUSED*/
317859243SobrienCCRETVAL
3179167465Smpv_replone(Char c)
318059243Sobrien{				/* vi mode overwrite one character */
318159243Sobrien    USE(c);
318259243Sobrien    c_alternativ_key_map(0);
318359243Sobrien    inputmode = MODE_REPLACE_1;
318459243Sobrien    UndoAction = TCSHOP_CHANGE;	/* Set Up for VI undo command */
318559243Sobrien    UndoPtr = Cursor;
318659243Sobrien    UndoSize = 0;
318759243Sobrien    return(CC_NORM);
318859243Sobrien}
318959243Sobrien
319059243Sobrien/*ARGSUSED*/
319159243SobrienCCRETVAL
3192167465Smpv_replmode(Char c)
319359243Sobrien{				/* vi mode start overwriting */
319459243Sobrien    USE(c);
319559243Sobrien    c_alternativ_key_map(0);
319659243Sobrien    inputmode = MODE_REPLACE;
319759243Sobrien    UndoAction = TCSHOP_CHANGE;	/* Set Up for VI undo command */
319859243Sobrien    UndoPtr = Cursor;
319959243Sobrien    UndoSize = 0;
320059243Sobrien    return(CC_NORM);
320159243Sobrien}
320259243Sobrien
320359243Sobrien/*ARGSUSED*/
320459243SobrienCCRETVAL
3205167465Smpv_substchar(Char c)
320659243Sobrien{				/* vi mode substitute for one char */
320759243Sobrien    USE(c);
320859243Sobrien    c_delafter(Argument);
320959243Sobrien    c_alternativ_key_map(0);
321059243Sobrien    return(CC_REFRESH);
321159243Sobrien}
321259243Sobrien
321359243Sobrien/*ARGSUSED*/
321459243SobrienCCRETVAL
3215167465Smpv_substline(Char c)
321659243Sobrien{				/* vi mode replace whole line */
321759243Sobrien    USE(c);
321859243Sobrien    (void) e_killall(0);
321959243Sobrien    c_alternativ_key_map(0);
322059243Sobrien    return(CC_REFRESH);
322159243Sobrien}
322259243Sobrien
322359243Sobrien/*ARGSUSED*/
322459243SobrienCCRETVAL
3225167465Smpv_chgtoend(Char c)
322659243Sobrien{				/* vi mode change to end of line */
322759243Sobrien    USE(c);
322859243Sobrien    (void) e_killend(0);
322959243Sobrien    c_alternativ_key_map(0);
323059243Sobrien    return(CC_REFRESH);
323159243Sobrien}
323259243Sobrien
323359243Sobrien/*ARGSUSED*/
323459243SobrienCCRETVAL
3235167465Smpv_insert(Char c)
323659243Sobrien{				/* vi mode start inserting */
323759243Sobrien    USE(c);
323859243Sobrien    c_alternativ_key_map(0);
323959243Sobrien
324059243Sobrien    InsertPos = Cursor;
324159243Sobrien    UndoPtr = Cursor;
324259243Sobrien    UndoAction = TCSHOP_DELETE;
324359243Sobrien
324459243Sobrien    return(CC_NORM);
324559243Sobrien}
324659243Sobrien
324759243Sobrien/*ARGSUSED*/
324859243SobrienCCRETVAL
3249167465Smpv_add(Char c)
325059243Sobrien{				/* vi mode start adding */
325159243Sobrien    USE(c);
325259243Sobrien    c_alternativ_key_map(0);
325359243Sobrien    if (Cursor < LastChar)
325459243Sobrien    {
325559243Sobrien	Cursor++;
325659243Sobrien	if (Cursor > LastChar)
325759243Sobrien	    Cursor = LastChar;
325859243Sobrien	RefCursor();
325959243Sobrien    }
326059243Sobrien
326159243Sobrien    InsertPos = Cursor;
326259243Sobrien    UndoPtr = Cursor;
326359243Sobrien    UndoAction = TCSHOP_DELETE;
326459243Sobrien
326559243Sobrien    return(CC_NORM);
326659243Sobrien}
326759243Sobrien
326859243Sobrien/*ARGSUSED*/
326959243SobrienCCRETVAL
3270167465Smpv_addend(Char c)
327159243Sobrien{				/* vi mode to add at end of line */
327259243Sobrien    USE(c);
327359243Sobrien    c_alternativ_key_map(0);
327459243Sobrien    Cursor = LastChar;
327559243Sobrien
327659243Sobrien    InsertPos = LastChar;	/* Mark where insertion begins */
327759243Sobrien    UndoPtr = LastChar;
327859243Sobrien    UndoAction = TCSHOP_DELETE;
327959243Sobrien
328059243Sobrien    RefCursor();
328159243Sobrien    return(CC_NORM);
328259243Sobrien}
328359243Sobrien
328459243Sobrien/*ARGSUSED*/
328559243SobrienCCRETVAL
3286167465Smpv_change_case(Char cc)
328759243Sobrien{
3288145479Smp    Char    c;
328959243Sobrien
329059243Sobrien    USE(cc);
329159243Sobrien    if (Cursor < LastChar) {
329269408Sache#ifndef WINNT_NATIVE
329359243Sobrien	c = *Cursor;
329459243Sobrien#else
329559243Sobrien	c = CHAR & *Cursor;
329669408Sache#endif /* WINNT_NATIVE */
329759243Sobrien	if (Isupper(c))
329859243Sobrien	    *Cursor++ = Tolower(c);
329959243Sobrien	else if (Islower(c))
330059243Sobrien	    *Cursor++ = Toupper(c);
330159243Sobrien	else
330259243Sobrien	    Cursor++;
3303145479Smp	RefPlusOne(1);		/* fast refresh for one char */
330459243Sobrien	return(CC_NORM);
330559243Sobrien    }
330659243Sobrien    return(CC_ERROR);
330759243Sobrien}
330859243Sobrien
330959243Sobrien/*ARGSUSED*/
331059243SobrienCCRETVAL
3311167465Smpe_expand(Char c)
331259243Sobrien{
331383098Smp    Char *p;
331459243Sobrien
331559243Sobrien    USE(c);
331659243Sobrien    for (p = InputBuf; Isspace(*p); p++)
331759243Sobrien	continue;
331859243Sobrien    if (p == LastChar)
331959243Sobrien	return(CC_ERROR);
332059243Sobrien
332159243Sobrien    justpr++;
332259243Sobrien    Expand++;
332359243Sobrien    return(e_newline(0));
332459243Sobrien}
332559243Sobrien
332659243Sobrien/*ARGSUSED*/
332759243SobrienCCRETVAL
3328167465Smpe_startover(Char c)
332959243Sobrien{				/* erase all of current line, start again */
333059243Sobrien    USE(c);
333159243Sobrien    ResetInLine(0);		/* reset the input pointers */
333259243Sobrien    return(CC_REFRESH);
333359243Sobrien}
333459243Sobrien
333559243Sobrien/*ARGSUSED*/
333659243SobrienCCRETVAL
3337167465Smpe_redisp(Char c)
333859243Sobrien{
333959243Sobrien    USE(c);
334059243Sobrien    ClearLines();
334159243Sobrien    ClearDisp();
334259243Sobrien    return(CC_REFRESH);
334359243Sobrien}
334459243Sobrien
334559243Sobrien/*ARGSUSED*/
334659243SobrienCCRETVAL
3347167465Smpe_cleardisp(Char c)
334859243Sobrien{
334959243Sobrien    USE(c);
335059243Sobrien    ClearScreen();		/* clear the whole real screen */
335159243Sobrien    ClearDisp();		/* reset everything */
335259243Sobrien    return(CC_REFRESH);
335359243Sobrien}
335459243Sobrien
335559243Sobrien/*ARGSUSED*/
335659243SobrienCCRETVAL
3357167465Smpe_tty_int(Char c)
335859243Sobrien{
335959243Sobrien    USE(c);
336069408Sache#if defined(_MINIX) || defined(WINNT_NATIVE)
336159243Sobrien    /* SAK PATCH: erase all of current line, start again */
336259243Sobrien    ResetInLine(0);		/* reset the input pointers */
336359243Sobrien    xputchar('\n');
336459243Sobrien    ClearDisp();
336559243Sobrien    return (CC_REFRESH);
336669408Sache#else /* !_MINIX && !WINNT_NATIVE */
336759243Sobrien    /* do no editing */
336859243Sobrien    return (CC_NORM);
336969408Sache#endif /* _MINIX || WINNT_NATIVE */
337059243Sobrien}
337159243Sobrien
337259243Sobrien/*
337359243Sobrien * From: ghazi@cesl.rutgers.edu (Kaveh R. Ghazi)
337459243Sobrien * Function to send a character back to the input stream in cooked
337559243Sobrien * mode. Only works if we have TIOCSTI
337659243Sobrien */
337759243Sobrien/*ARGSUSED*/
337859243SobrienCCRETVAL
3379167465Smpe_stuff_char(Char c)
338059243Sobrien{
338159243Sobrien#ifdef TIOCSTI
338259243Sobrien     int was_raw = Tty_raw_mode;
3383145479Smp     char buf[MB_LEN_MAX];
3384145479Smp     size_t i, len;
338559243Sobrien
338659243Sobrien     if (was_raw)
338759243Sobrien         (void) Cookedmode();
338859243Sobrien
3389167465Smp     (void) xwrite(SHIN, "\n", 1);
3390145479Smp     len = one_wctomb(buf, c & CHAR);
3391145479Smp     for (i = 0; i < len; i++)
3392145479Smp	 (void) ioctl(SHIN, TIOCSTI, (ioctl_t) &buf[i]);
339359243Sobrien
339459243Sobrien     if (was_raw)
3395167465Smp	 (void) Rawmode();
339659243Sobrien     return(e_redisp(c));
339759243Sobrien#else /* !TIOCSTI */
339859243Sobrien     return(CC_ERROR);
339959243Sobrien#endif /* !TIOCSTI */
340059243Sobrien}
340159243Sobrien
340259243Sobrien/*ARGSUSED*/
340359243SobrienCCRETVAL
3404167465Smpe_insovr(Char c)
340559243Sobrien{
340659243Sobrien    USE(c);
340759243Sobrien    inputmode = (inputmode == MODE_INSERT ? MODE_REPLACE : MODE_INSERT);
340859243Sobrien    return(CC_NORM);
340959243Sobrien}
341059243Sobrien
341159243Sobrien/*ARGSUSED*/
341259243SobrienCCRETVAL
3413167465Smpe_tty_dsusp(Char c)
341459243Sobrien{
341559243Sobrien    USE(c);
341659243Sobrien    /* do no editing */
341759243Sobrien    return(CC_NORM);
341859243Sobrien}
341959243Sobrien
342059243Sobrien/*ARGSUSED*/
342159243SobrienCCRETVAL
3422167465Smpe_tty_flusho(Char c)
342359243Sobrien{
342459243Sobrien    USE(c);
342559243Sobrien    /* do no editing */
342659243Sobrien    return(CC_NORM);
342759243Sobrien}
342859243Sobrien
342959243Sobrien/*ARGSUSED*/
343059243SobrienCCRETVAL
3431167465Smpe_tty_quit(Char c)
343259243Sobrien{
343359243Sobrien    USE(c);
343459243Sobrien    /* do no editing */
343559243Sobrien    return(CC_NORM);
343659243Sobrien}
343759243Sobrien
343859243Sobrien/*ARGSUSED*/
343959243SobrienCCRETVAL
3440167465Smpe_tty_tsusp(Char c)
344159243Sobrien{
344259243Sobrien    USE(c);
344359243Sobrien    /* do no editing */
344459243Sobrien    return(CC_NORM);
344559243Sobrien}
344659243Sobrien
344759243Sobrien/*ARGSUSED*/
344859243SobrienCCRETVAL
3449167465Smpe_tty_stopo(Char c)
345059243Sobrien{
345159243Sobrien    USE(c);
345259243Sobrien    /* do no editing */
345359243Sobrien    return(CC_NORM);
345459243Sobrien}
345559243Sobrien
3456195609Smp/* returns the number of (attempted) expansions */
3457195609Smpint
3458195609SmpExpandHistory(void)
3459195609Smp{
3460195609Smp    *LastChar = '\0';		/* just in case */
3461195609Smp    return c_substitute();
3462195609Smp}
3463195609Smp
346459243Sobrien/*ARGSUSED*/
346559243SobrienCCRETVAL
3466167465Smpe_expand_history(Char c)
346759243Sobrien{
346859243Sobrien    USE(c);
3469195609Smp    (void)ExpandHistory();
347059243Sobrien    return(CC_NORM);
347159243Sobrien}
347259243Sobrien
347359243Sobrien/*ARGSUSED*/
347459243SobrienCCRETVAL
3475167465Smpe_magic_space(Char c)
347659243Sobrien{
347759243Sobrien    USE(c);
347859243Sobrien    *LastChar = '\0';		/* just in case */
3479195609Smp    (void)c_substitute();
348059243Sobrien    return(e_insert(' '));
348159243Sobrien}
348259243Sobrien
348359243Sobrien/*ARGSUSED*/
348459243SobrienCCRETVAL
3485167465Smpe_inc_fwd(Char c)
348659243Sobrien{
3487167465Smp    CCRETVAL ret;
3488167465Smp
348959243Sobrien    USE(c);
3490167465Smp    patbuf.len = 0;
3491167465Smp    MarkIsSet = 0;
3492167465Smp    ret = e_inc_search(F_DOWN_SEARCH_HIST);
3493167465Smp    if (adrof(STRhighlight) && IncMatchLen) {
3494167465Smp	IncMatchLen = 0;
3495167465Smp	ClearLines();
3496167465Smp	ClearDisp();
3497167465Smp	Refresh();
3498167465Smp    }
3499167465Smp    IncMatchLen = 0;
3500167465Smp    return ret;
350159243Sobrien}
350259243Sobrien
350359243Sobrien
350459243Sobrien/*ARGSUSED*/
350559243SobrienCCRETVAL
3506167465Smpe_inc_back(Char c)
350759243Sobrien{
3508167465Smp    CCRETVAL ret;
3509167465Smp
351059243Sobrien    USE(c);
3511167465Smp    patbuf.len = 0;
3512167465Smp    MarkIsSet = 0;
3513167465Smp    ret = e_inc_search(F_UP_SEARCH_HIST);
3514167465Smp    if (adrof(STRhighlight) && IncMatchLen) {
3515167465Smp	IncMatchLen = 0;
3516167465Smp	ClearLines();
3517167465Smp	ClearDisp();
3518167465Smp	Refresh();
3519167465Smp    }
3520167465Smp    IncMatchLen = 0;
3521167465Smp    return ret;
352259243Sobrien}
352359243Sobrien
352459243Sobrien/*ARGSUSED*/
352559243SobrienCCRETVAL
3526167465Smpe_copyprev(Char c)
352759243Sobrien{
352883098Smp    Char *cp, *oldc, *dp;
352959243Sobrien
353059243Sobrien    USE(c);
353159243Sobrien    if (Cursor == InputBuf)
353259243Sobrien	return(CC_ERROR);
353359243Sobrien    /* else */
353459243Sobrien
353559243Sobrien    oldc = Cursor;
353659243Sobrien    /* does a bounds check */
353759243Sobrien    cp = c_prev_word(Cursor, InputBuf, Argument);
353859243Sobrien
353959243Sobrien    c_insert((int)(oldc - cp));
354059243Sobrien    for (dp = oldc; cp < oldc && dp < LastChar; cp++)
354159243Sobrien	*dp++ = *cp;
354259243Sobrien
354359243Sobrien    Cursor = dp;		/* put cursor at end */
354459243Sobrien
354559243Sobrien    return(CC_REFRESH);
354659243Sobrien}
354759243Sobrien
354859243Sobrien/*ARGSUSED*/
354959243SobrienCCRETVAL
3550167465Smpe_tty_starto(Char c)
355159243Sobrien{
355259243Sobrien    USE(c);
355359243Sobrien    /* do no editing */
355459243Sobrien    return(CC_NORM);
355559243Sobrien}
355659243Sobrien
355759243Sobrien/*ARGSUSED*/
355859243SobrienCCRETVAL
3559167465Smpe_load_average(Char c)
356059243Sobrien{
356159243Sobrien    USE(c);
356259243Sobrien    PastBottom();
356359243Sobrien#ifdef TIOCSTAT
356459243Sobrien    /*
356559243Sobrien     * Here we pass &c to the ioctl because some os's (NetBSD) expect it
356659243Sobrien     * there even if they don't use it. (lukem@netbsd.org)
356759243Sobrien     */
356859243Sobrien    if (ioctl(SHIN, TIOCSTAT, (ioctl_t) &c) < 0)
356959243Sobrien#endif
3570195609Smp	xprintf("%s", CGETS(5, 1, "Load average unavailable\n"));
357159243Sobrien    return(CC_REFRESH);
357259243Sobrien}
357359243Sobrien
357459243Sobrien/*ARGSUSED*/
357559243SobrienCCRETVAL
3576167465Smpv_chgmeta(Char c)
357759243Sobrien{
357859243Sobrien    USE(c);
357959243Sobrien    /*
358059243Sobrien     * Delete with insert == change: first we delete and then we leave in
358159243Sobrien     * insert mode.
358259243Sobrien     */
358359243Sobrien    return(v_action(TCSHOP_DELETE|TCSHOP_INSERT));
358459243Sobrien}
358559243Sobrien
358659243Sobrien/*ARGSUSED*/
358759243SobrienCCRETVAL
3588167465Smpv_delmeta(Char c)
358959243Sobrien{
359059243Sobrien    USE(c);
359159243Sobrien    return(v_action(TCSHOP_DELETE));
359259243Sobrien}
359359243Sobrien
359459243Sobrien
359559243Sobrien/*ARGSUSED*/
359659243SobrienCCRETVAL
3597167465Smpv_endword(Char c)
359859243Sobrien{
359959243Sobrien    USE(c);
360059243Sobrien    if (Cursor == LastChar)
360159243Sobrien	return(CC_ERROR);
360259243Sobrien    /* else */
360359243Sobrien
360483098Smp    Cursor = c_endword(Cursor, LastChar, Argument, STRshwspace);
360559243Sobrien
360659243Sobrien    if (ActionFlag & TCSHOP_DELETE)
360759243Sobrien    {
360859243Sobrien	Cursor++;
360959243Sobrien	c_delfini();
361059243Sobrien	return(CC_REFRESH);
361159243Sobrien    }
361259243Sobrien
361359243Sobrien    RefCursor();
361459243Sobrien    return(CC_NORM);
361559243Sobrien}
361659243Sobrien
361759243Sobrien/*ARGSUSED*/
361859243SobrienCCRETVAL
3619167465Smpv_eword(Char c)
362059243Sobrien{
362159243Sobrien    USE(c);
362259243Sobrien    if (Cursor == LastChar)
362359243Sobrien	return(CC_ERROR);
362459243Sobrien    /* else */
362559243Sobrien
362659243Sobrien    Cursor = c_eword(Cursor, LastChar, Argument);
362759243Sobrien
362859243Sobrien    if (ActionFlag & TCSHOP_DELETE) {
362959243Sobrien	Cursor++;
363059243Sobrien	c_delfini();
363159243Sobrien	return(CC_REFRESH);
363259243Sobrien    }
363359243Sobrien
363459243Sobrien    RefCursor();
363559243Sobrien    return(CC_NORM);
363659243Sobrien}
363759243Sobrien
363859243Sobrien/*ARGSUSED*/
363959243SobrienCCRETVAL
3640167465Smpv_char_fwd(Char c)
364159243Sobrien{
364259243Sobrien    Char ch;
364359243Sobrien
364459243Sobrien    USE(c);
364559243Sobrien    if (GetNextChar(&ch) != 1)
364659243Sobrien	return e_send_eof(0);
364759243Sobrien
364859243Sobrien    srch_dir = CHAR_FWD;
364959243Sobrien    srch_char = ch;
365059243Sobrien
365159243Sobrien    return v_csearch_fwd(ch, Argument, 0);
365259243Sobrien
365359243Sobrien}
365459243Sobrien
365559243Sobrien/*ARGSUSED*/
365659243SobrienCCRETVAL
3657167465Smpv_char_back(Char c)
365859243Sobrien{
365959243Sobrien    Char ch;
366059243Sobrien
366159243Sobrien    USE(c);
366259243Sobrien    if (GetNextChar(&ch) != 1)
366359243Sobrien	return e_send_eof(0);
366459243Sobrien
366559243Sobrien    srch_dir = CHAR_BACK;
366659243Sobrien    srch_char = ch;
366759243Sobrien
366859243Sobrien    return v_csearch_back(ch, Argument, 0);
366959243Sobrien}
367059243Sobrien
367159243Sobrien/*ARGSUSED*/
367259243SobrienCCRETVAL
3673167465Smpv_charto_fwd(Char c)
367459243Sobrien{
367559243Sobrien    Char ch;
367659243Sobrien
367759243Sobrien    USE(c);
367859243Sobrien    if (GetNextChar(&ch) != 1)
367959243Sobrien	return e_send_eof(0);
368059243Sobrien
368159243Sobrien    return v_csearch_fwd(ch, Argument, 1);
368259243Sobrien
368359243Sobrien}
368459243Sobrien
368559243Sobrien/*ARGSUSED*/
368659243SobrienCCRETVAL
3687167465Smpv_charto_back(Char c)
368859243Sobrien{
368959243Sobrien    Char ch;
369059243Sobrien
369159243Sobrien    USE(c);
369259243Sobrien    if (GetNextChar(&ch) != 1)
369359243Sobrien	return e_send_eof(0);
369459243Sobrien
369559243Sobrien    return v_csearch_back(ch, Argument, 1);
369659243Sobrien}
369759243Sobrien
369859243Sobrien/*ARGSUSED*/
369959243SobrienCCRETVAL
3700167465Smpv_rchar_fwd(Char c)
370159243Sobrien{
370259243Sobrien    USE(c);
370359243Sobrien    if (srch_char == 0)
370459243Sobrien	return CC_ERROR;
370559243Sobrien
370659243Sobrien    return srch_dir == CHAR_FWD ? v_csearch_fwd(srch_char, Argument, 0) :
370759243Sobrien			          v_csearch_back(srch_char, Argument, 0);
370859243Sobrien}
370959243Sobrien
371059243Sobrien/*ARGSUSED*/
371159243SobrienCCRETVAL
3712167465Smpv_rchar_back(Char c)
371359243Sobrien{
371459243Sobrien    USE(c);
371559243Sobrien    if (srch_char == 0)
371659243Sobrien	return CC_ERROR;
371759243Sobrien
371859243Sobrien    return srch_dir == CHAR_BACK ? v_csearch_fwd(srch_char, Argument, 0) :
371959243Sobrien			           v_csearch_back(srch_char, Argument, 0);
372059243Sobrien}
372159243Sobrien
372259243Sobrien/*ARGSUSED*/
372359243SobrienCCRETVAL
3724167465Smpv_undo(Char c)
372559243Sobrien{
372683098Smp    int  loop;
372783098Smp    Char *kp, *cp;
372859243Sobrien    Char temp;
372959243Sobrien    int	 size;
373059243Sobrien
373159243Sobrien    USE(c);
373259243Sobrien    switch (UndoAction) {
373359243Sobrien    case TCSHOP_DELETE|TCSHOP_INSERT:
373459243Sobrien    case TCSHOP_DELETE:
373559243Sobrien	if (UndoSize == 0) return(CC_NORM);
373659243Sobrien	cp = UndoPtr;
373759243Sobrien	kp = UndoBuf;
373859243Sobrien	for (loop=0; loop < UndoSize; loop++)	/* copy the chars */
373959243Sobrien	    *kp++ = *cp++;			/* into UndoBuf   */
374059243Sobrien
374159243Sobrien	for (cp = UndoPtr; cp <= LastChar; cp++)
374259243Sobrien	    *cp = cp[UndoSize];
374359243Sobrien
374459243Sobrien	LastChar -= UndoSize;
374559243Sobrien	Cursor   =  UndoPtr;
374659243Sobrien
374759243Sobrien	UndoAction = TCSHOP_INSERT;
374859243Sobrien	break;
374959243Sobrien
375059243Sobrien    case TCSHOP_INSERT:
375159243Sobrien	if (UndoSize == 0) return(CC_NORM);
375259243Sobrien	cp = UndoPtr;
375359243Sobrien	Cursor = UndoPtr;
375459243Sobrien	kp = UndoBuf;
375559243Sobrien	c_insert(UndoSize);		/* open the space, */
375659243Sobrien	for (loop = 0; loop < UndoSize; loop++)	/* copy the chars */
375759243Sobrien	    *cp++ = *kp++;
375859243Sobrien
375959243Sobrien	UndoAction = TCSHOP_DELETE;
376059243Sobrien	break;
376159243Sobrien
376259243Sobrien    case TCSHOP_CHANGE:
376359243Sobrien	if (UndoSize == 0) return(CC_NORM);
376459243Sobrien	cp = UndoPtr;
376559243Sobrien	Cursor = UndoPtr;
376659243Sobrien	kp = UndoBuf;
376759243Sobrien	size = (int)(Cursor-LastChar); /*  NOT NSL independant */
376859243Sobrien	if (size < UndoSize)
376959243Sobrien	    size = UndoSize;
377059243Sobrien	for(loop = 0; loop < size; loop++) {
377159243Sobrien	    temp = *kp;
377259243Sobrien	    *kp++ = *cp;
377359243Sobrien	    *cp++ = temp;
377459243Sobrien	}
377559243Sobrien	break;
377659243Sobrien
377759243Sobrien    default:
377859243Sobrien	return(CC_ERROR);
377959243Sobrien    }
378059243Sobrien
378159243Sobrien    return(CC_REFRESH);
378259243Sobrien}
378359243Sobrien
378459243Sobrien/*ARGSUSED*/
378559243SobrienCCRETVAL
3786167465Smpv_ush_meta(Char c)
378759243Sobrien{
378859243Sobrien    USE(c);
378959243Sobrien    return v_search(F_UP_SEARCH_HIST);
379059243Sobrien}
379159243Sobrien
379259243Sobrien/*ARGSUSED*/
379359243SobrienCCRETVAL
3794167465Smpv_dsh_meta(Char c)
379559243Sobrien{
379659243Sobrien    USE(c);
379759243Sobrien    return v_search(F_DOWN_SEARCH_HIST);
379859243Sobrien}
379959243Sobrien
380059243Sobrien/*ARGSUSED*/
380159243SobrienCCRETVAL
3802167465Smpv_rsrch_fwd(Char c)
380359243Sobrien{
380459243Sobrien    USE(c);
3805167465Smp    if (patbuf.len == 0) return(CC_ERROR);
380659243Sobrien    return(v_repeat_srch(searchdir));
380759243Sobrien}
380859243Sobrien
380959243Sobrien/*ARGSUSED*/
381059243SobrienCCRETVAL
3811167465Smpv_rsrch_back(Char c)
381259243Sobrien{
381359243Sobrien    USE(c);
3814167465Smp    if (patbuf.len == 0) return(CC_ERROR);
381559243Sobrien    return(v_repeat_srch(searchdir == F_UP_SEARCH_HIST ?
381659243Sobrien			 F_DOWN_SEARCH_HIST : F_UP_SEARCH_HIST));
381759243Sobrien}
381859243Sobrien
381969408Sache#ifndef WINNT_NATIVE
382059243Sobrien/* Since ed.defns.h  is generated from ed.defns.c, these empty
382159243Sobrien   functions will keep the F_NUM_FNS consistent
382259243Sobrien */
382359243SobrienCCRETVAL
3824167465Smpe_copy_to_clipboard(Char c)
382559243Sobrien{
382659243Sobrien    USE(c);
382759243Sobrien    return CC_ERROR;
382859243Sobrien}
382959243Sobrien
383059243SobrienCCRETVAL
3831167465Smpe_paste_from_clipboard(Char c)
383259243Sobrien{
383359243Sobrien    USE(c);
383459243Sobrien    return (CC_ERROR);
383559243Sobrien}
383659243Sobrien
383759243SobrienCCRETVAL
3838167465Smpe_dosify_next(Char c)
383959243Sobrien{
384059243Sobrien    USE(c);
384159243Sobrien    return (CC_ERROR);
384259243Sobrien}
384359243SobrienCCRETVAL
3844167465Smpe_dosify_prev(Char c)
384559243Sobrien{
384659243Sobrien    USE(c);
384759243Sobrien    return (CC_ERROR);
384859243Sobrien}
384959243SobrienCCRETVAL
3850167465Smpe_page_up(Char c)
385159243Sobrien{
385259243Sobrien    USE(c);
385369408Sache    return (CC_ERROR);
385459243Sobrien}
385559243SobrienCCRETVAL
3856167465Smpe_page_down(Char c)
385759243Sobrien{
385859243Sobrien    USE(c);
385969408Sache    return (CC_ERROR);
386059243Sobrien}
386169408Sache#endif /* !WINNT_NATIVE */
386259243Sobrien
386359243Sobrien#ifdef notdef
386459243Sobrienvoid
3865167465SmpMoveCursor(int n)		/* move cursor + right - left char */
386659243Sobrien{
386759243Sobrien    Cursor = Cursor + n;
386859243Sobrien    if (Cursor < InputBuf)
386959243Sobrien	Cursor = InputBuf;
387059243Sobrien    if (Cursor > LastChar)
387159243Sobrien	Cursor = LastChar;
387259243Sobrien    return;
387359243Sobrien}
387459243Sobrien
387559243SobrienChar *
3876167465SmpGetCursor(void)
387759243Sobrien{
387859243Sobrien    return(Cursor);
387959243Sobrien}
388059243Sobrien
388159243Sobrienint
3882167465SmpPutCursor(Char *p)
388359243Sobrien{
388459243Sobrien    if (p < InputBuf || p > LastChar)
388559243Sobrien	return 1;		/* Error */
388659243Sobrien    Cursor = p;
388759243Sobrien    return 0;
388859243Sobrien}
388959243Sobrien#endif
3890