xref: /illumos-gate/usr/src/contrib/ast/src/cmd/ksh93/edit/vi.c (revision b30d193948be5a7794d7ae3ba0ed9c2f72c88e0f)
1*b30d1939SAndy Fiddaman /***********************************************************************
2*b30d1939SAndy Fiddaman *                                                                      *
3*b30d1939SAndy Fiddaman *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1982-2012 AT&T Intellectual Property          *
5*b30d1939SAndy Fiddaman *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
7*b30d1939SAndy Fiddaman *                    by AT&T Intellectual Property                     *
8*b30d1939SAndy Fiddaman *                                                                      *
9*b30d1939SAndy Fiddaman *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12*b30d1939SAndy Fiddaman *                                                                      *
13*b30d1939SAndy Fiddaman *              Information and Software Systems Research               *
14*b30d1939SAndy Fiddaman *                            AT&T Research                             *
15*b30d1939SAndy Fiddaman *                           Florham Park NJ                            *
16*b30d1939SAndy Fiddaman *                                                                      *
17*b30d1939SAndy Fiddaman *                  David Korn <dgk@research.att.com>                   *
18*b30d1939SAndy Fiddaman *                                                                      *
19*b30d1939SAndy Fiddaman ***********************************************************************/
20*b30d1939SAndy Fiddaman #pragma prototyped
21*b30d1939SAndy Fiddaman /* Adapted for ksh by David Korn */
22*b30d1939SAndy Fiddaman /*+	VI.C			P.D. Sullivan
23*b30d1939SAndy Fiddaman  *
24*b30d1939SAndy Fiddaman  *	One line editor for the shell based on the vi editor.
25*b30d1939SAndy Fiddaman  *
26*b30d1939SAndy Fiddaman  *	Questions to:
27*b30d1939SAndy Fiddaman  *		P.D. Sullivan
28*b30d1939SAndy Fiddaman  *		cbosgd!pds
29*b30d1939SAndy Fiddaman -*/
30*b30d1939SAndy Fiddaman 
31*b30d1939SAndy Fiddaman 
32*b30d1939SAndy Fiddaman #if KSHELL
33*b30d1939SAndy Fiddaman #   include	"defs.h"
34*b30d1939SAndy Fiddaman #else
35*b30d1939SAndy Fiddaman #   include	<ast.h>
36*b30d1939SAndy Fiddaman #   include	"FEATURE/options"
37*b30d1939SAndy Fiddaman #   include	<ctype.h>
38*b30d1939SAndy Fiddaman #endif	/* KSHELL */
39*b30d1939SAndy Fiddaman #include	"io.h"
40*b30d1939SAndy Fiddaman 
41*b30d1939SAndy Fiddaman #include	"history.h"
42*b30d1939SAndy Fiddaman #include	"edit.h"
43*b30d1939SAndy Fiddaman #include	"terminal.h"
44*b30d1939SAndy Fiddaman #include	"FEATURE/time"
45*b30d1939SAndy Fiddaman 
46*b30d1939SAndy Fiddaman #ifdef ECHOCTL
47*b30d1939SAndy Fiddaman #   define echoctl	ECHOCTL
48*b30d1939SAndy Fiddaman #else
49*b30d1939SAndy Fiddaman #   define echoctl	0
50*b30d1939SAndy Fiddaman #endif /* ECHOCTL */
51*b30d1939SAndy Fiddaman 
52*b30d1939SAndy Fiddaman #ifndef FIORDCHK
53*b30d1939SAndy Fiddaman #   define NTICKS	5		/* number of ticks for typeahead */
54*b30d1939SAndy Fiddaman #endif /* FIORDCHK */
55*b30d1939SAndy Fiddaman 
56*b30d1939SAndy Fiddaman #define	MAXCHAR	MAXLINE-2		/* max char per line */
57*b30d1939SAndy Fiddaman 
58*b30d1939SAndy Fiddaman #if SHOPT_MULTIBYTE
59*b30d1939SAndy Fiddaman #   include	"lexstates.h"
60*b30d1939SAndy Fiddaman #   define gencpy(a,b)	ed_gencpy(a,b)
61*b30d1939SAndy Fiddaman #   define genncpy(a,b,n)	ed_genncpy(a,b,n)
62*b30d1939SAndy Fiddaman #   define genlen(str)	ed_genlen(str)
63*b30d1939SAndy Fiddaman #   define digit(c)	((c&~STRIP)==0 && isdigit(c))
64*b30d1939SAndy Fiddaman #   define is_print(c)	((c&~STRIP) || isprint(c))
65*b30d1939SAndy Fiddaman #   if !_lib_iswprint && !defined(iswprint)
66*b30d1939SAndy Fiddaman #	define iswprint(c)	((c&~0177) || isprint(c))
67*b30d1939SAndy Fiddaman #   endif
68*b30d1939SAndy Fiddaman     static int _isalph(int);
69*b30d1939SAndy Fiddaman     static int _ismetach(int);
70*b30d1939SAndy Fiddaman     static int _isblank(int);
71*b30d1939SAndy Fiddaman #   undef  isblank
72*b30d1939SAndy Fiddaman #   define isblank(v)	_isblank(virtual[v])
73*b30d1939SAndy Fiddaman #   define isalph(v)	_isalph(virtual[v])
74*b30d1939SAndy Fiddaman #   define ismetach(v)	_ismetach(virtual[v])
75*b30d1939SAndy Fiddaman #else
76*b30d1939SAndy Fiddaman     static genchar	_c;
77*b30d1939SAndy Fiddaman #   define gencpy(a,b)	strcpy((char*)(a),(char*)(b))
78*b30d1939SAndy Fiddaman #   define genncpy(a,b,n) strncpy((char*)(a),(char*)(b),n)
79*b30d1939SAndy Fiddaman #   define genlen(str)	strlen(str)
80*b30d1939SAndy Fiddaman #   define isalph(v)	((_c=virtual[v])=='_'||isalnum(_c))
81*b30d1939SAndy Fiddaman #   undef  isblank
82*b30d1939SAndy Fiddaman #   define isblank(v)	isspace(virtual[v])
83*b30d1939SAndy Fiddaman #   define ismetach(v)	ismeta(virtual[v])
84*b30d1939SAndy Fiddaman #   define digit(c)	isdigit(c)
85*b30d1939SAndy Fiddaman #   define is_print(c)	isprint(c)
86*b30d1939SAndy Fiddaman #endif	/* SHOPT_MULTIBYTE */
87*b30d1939SAndy Fiddaman 
88*b30d1939SAndy Fiddaman #if ( 'a' == 97) /* ASCII? */
89*b30d1939SAndy Fiddaman #   define fold(c)	((c)&~040)	/* lower and uppercase equivalent */
90*b30d1939SAndy Fiddaman #else
91*b30d1939SAndy Fiddaman #   define fold(c)	((c)|0100)	/* lower and uppercase equivalent */
92*b30d1939SAndy Fiddaman #endif
93*b30d1939SAndy Fiddaman 
94*b30d1939SAndy Fiddaman #ifndef iswascii
95*b30d1939SAndy Fiddaman #define iswascii(c)	(!((c)&(~0177)))
96*b30d1939SAndy Fiddaman #endif
97*b30d1939SAndy Fiddaman 
98*b30d1939SAndy Fiddaman typedef struct _vi_
99*b30d1939SAndy Fiddaman {
100*b30d1939SAndy Fiddaman 	int direction;
101*b30d1939SAndy Fiddaman 	int lastmacro;
102*b30d1939SAndy Fiddaman 	char addnl;		/* boolean - add newline flag */
103*b30d1939SAndy Fiddaman 	char last_find;		/* last find command */
104*b30d1939SAndy Fiddaman 	char last_cmd;		/* last command */
105*b30d1939SAndy Fiddaman 	char repeat_set;
106*b30d1939SAndy Fiddaman 	char nonewline;
107*b30d1939SAndy Fiddaman 	int findchar;		/* last find char */
108*b30d1939SAndy Fiddaman 	genchar *lastline;
109*b30d1939SAndy Fiddaman 	int first_wind;		/* first column of window */
110*b30d1939SAndy Fiddaman 	int last_wind;		/* last column in window */
111*b30d1939SAndy Fiddaman 	int lastmotion;		/* last motion */
112*b30d1939SAndy Fiddaman 	int long_char; 		/* line bigger than window */
113*b30d1939SAndy Fiddaman 	int long_line;		/* line bigger than window */
114*b30d1939SAndy Fiddaman 	int ocur_phys;		/* old current physical position */
115*b30d1939SAndy Fiddaman 	int ocur_virt;		/* old last virtual position */
116*b30d1939SAndy Fiddaman 	int ofirst_wind;	/* old window first col */
117*b30d1939SAndy Fiddaman 	int o_v_char;		/* prev virtual[ocur_virt] */
118*b30d1939SAndy Fiddaman 	int repeat;		/* repeat count for motion cmds */
119*b30d1939SAndy Fiddaman 	int lastrepeat;		/* last repeat count for motion cmds */
120*b30d1939SAndy Fiddaman 	int u_column;		/* undo current column */
121*b30d1939SAndy Fiddaman 	int U_saved;		/* original virtual saved */
122*b30d1939SAndy Fiddaman 	genchar *U_space;	/* used for U command */
123*b30d1939SAndy Fiddaman 	genchar *u_space;	/* used for u command */
124*b30d1939SAndy Fiddaman #ifdef FIORDCHK
125*b30d1939SAndy Fiddaman 	clock_t typeahead;	/* typeahead occurred */
126*b30d1939SAndy Fiddaman #else
127*b30d1939SAndy Fiddaman 	int typeahead;		/* typeahead occurred */
128*b30d1939SAndy Fiddaman #endif	/* FIORDCHK */
129*b30d1939SAndy Fiddaman #if SHOPT_MULTIBYTE
130*b30d1939SAndy Fiddaman 	int bigvi;
131*b30d1939SAndy Fiddaman #endif
132*b30d1939SAndy Fiddaman 	Edit_t	*ed;		/* pointer to edit data */
133*b30d1939SAndy Fiddaman } Vi_t;
134*b30d1939SAndy Fiddaman 
135*b30d1939SAndy Fiddaman #define editb	(*vp->ed)
136*b30d1939SAndy Fiddaman 
137*b30d1939SAndy Fiddaman #undef putchar
138*b30d1939SAndy Fiddaman #define putchar(c)	ed_putchar(vp->ed,c)
139*b30d1939SAndy Fiddaman 
140*b30d1939SAndy Fiddaman #define crallowed	editb.e_crlf
141*b30d1939SAndy Fiddaman #define cur_virt	editb.e_cur		/* current virtual column */
142*b30d1939SAndy Fiddaman #define cur_phys	editb.e_pcur	/* current phys column cursor is at */
143*b30d1939SAndy Fiddaman #define curhline	editb.e_hline		/* current history line */
144*b30d1939SAndy Fiddaman #define first_virt	editb.e_fcol		/* first allowable column */
145*b30d1939SAndy Fiddaman #define	globals		editb.e_globals		/* local global variables */
146*b30d1939SAndy Fiddaman #define histmin		editb.e_hismin
147*b30d1939SAndy Fiddaman #define histmax		editb.e_hismax
148*b30d1939SAndy Fiddaman #define last_phys	editb.e_peol		/* last column in physical */
149*b30d1939SAndy Fiddaman #define last_virt	editb.e_eol		/* last column */
150*b30d1939SAndy Fiddaman #define lsearch		editb.e_search		/* last search string */
151*b30d1939SAndy Fiddaman #define lookahead	editb.e_lookahead	/* characters in buffer */
152*b30d1939SAndy Fiddaman #define previous	editb.e_lbuf		/* lookahead buffer */
153*b30d1939SAndy Fiddaman #define max_col		editb.e_llimit		/* maximum column */
154*b30d1939SAndy Fiddaman #define Prompt		editb.e_prompt		/* pointer to prompt */
155*b30d1939SAndy Fiddaman #define plen		editb.e_plen		/* length of prompt */
156*b30d1939SAndy Fiddaman #define physical	editb.e_physbuf		/* physical image */
157*b30d1939SAndy Fiddaman #define usreof		editb.e_eof		/* user defined eof char */
158*b30d1939SAndy Fiddaman #define usrerase	editb.e_erase		/* user defined erase char */
159*b30d1939SAndy Fiddaman #define usrlnext	editb.e_lnext		/* user defined next literal */
160*b30d1939SAndy Fiddaman #define usrkill		editb.e_kill		/* user defined kill char */
161*b30d1939SAndy Fiddaman #define virtual		editb.e_inbuf	/* pointer to virtual image buffer */
162*b30d1939SAndy Fiddaman #define	window		editb.e_window		/* window buffer */
163*b30d1939SAndy Fiddaman #define	w_size		editb.e_wsize		/* window size */
164*b30d1939SAndy Fiddaman #define	inmacro		editb.e_inmacro		/* true when in macro */
165*b30d1939SAndy Fiddaman #define yankbuf		editb.e_killbuf		/* yank/delete buffer */
166*b30d1939SAndy Fiddaman 
167*b30d1939SAndy Fiddaman 
168*b30d1939SAndy Fiddaman #define	ABORT	-2			/* user abort */
169*b30d1939SAndy Fiddaman #define	APPEND	-10			/* append chars */
170*b30d1939SAndy Fiddaman #define	BAD	-1			/* failure flag */
171*b30d1939SAndy Fiddaman #define	BIGVI	-15			/* user wants real vi */
172*b30d1939SAndy Fiddaman #define	CONTROL	-20			/* control mode */
173*b30d1939SAndy Fiddaman #define	ENTER	-25			/* enter flag */
174*b30d1939SAndy Fiddaman #define	GOOD	0			/* success flag */
175*b30d1939SAndy Fiddaman #define	INPUT	-30			/* input mode */
176*b30d1939SAndy Fiddaman #define	INSERT	-35			/* insert mode */
177*b30d1939SAndy Fiddaman #define	REPLACE	-40			/* replace chars */
178*b30d1939SAndy Fiddaman #define	SEARCH	-45			/* search flag */
179*b30d1939SAndy Fiddaman #define	TRANSLATE	-50		/* translate virt to phys only */
180*b30d1939SAndy Fiddaman 
181*b30d1939SAndy Fiddaman #define	INVALID	(-1)			/* invalid column */
182*b30d1939SAndy Fiddaman 
183*b30d1939SAndy Fiddaman static const char paren_chars[] = "([{)]}";   /* for % command */
184*b30d1939SAndy Fiddaman 
185*b30d1939SAndy Fiddaman static void	cursor(Vi_t*, int);
186*b30d1939SAndy Fiddaman static void	del_line(Vi_t*,int);
187*b30d1939SAndy Fiddaman static int	getcount(Vi_t*,int);
188*b30d1939SAndy Fiddaman static void	getline(Vi_t*,int);
189*b30d1939SAndy Fiddaman static int	getrchar(Vi_t*);
190*b30d1939SAndy Fiddaman static int	mvcursor(Vi_t*,int);
191*b30d1939SAndy Fiddaman static void	pr_string(Vi_t*,const char*);
192*b30d1939SAndy Fiddaman static void	putstring(Vi_t*,int, int);
193*b30d1939SAndy Fiddaman static void	refresh(Vi_t*,int);
194*b30d1939SAndy Fiddaman static void	replace(Vi_t*,int, int);
195*b30d1939SAndy Fiddaman static void	restore_v(Vi_t*);
196*b30d1939SAndy Fiddaman static void	save_last(Vi_t*);
197*b30d1939SAndy Fiddaman static void	save_v(Vi_t*);
198*b30d1939SAndy Fiddaman static int	search(Vi_t*,int);
199*b30d1939SAndy Fiddaman static void	sync_cursor(Vi_t*);
200*b30d1939SAndy Fiddaman static int	textmod(Vi_t*,int,int);
201*b30d1939SAndy Fiddaman 
202*b30d1939SAndy Fiddaman /*+	VI_READ( fd, shbuf, nchar )
203*b30d1939SAndy Fiddaman  *
204*b30d1939SAndy Fiddaman  *	This routine implements a one line version of vi and is
205*b30d1939SAndy Fiddaman  * called by _filbuf.c
206*b30d1939SAndy Fiddaman  *
207*b30d1939SAndy Fiddaman -*/
208*b30d1939SAndy Fiddaman 
209*b30d1939SAndy Fiddaman /*
210*b30d1939SAndy Fiddaman  * if reedit is non-zero, initialize edit buffer with reedit chars
211*b30d1939SAndy Fiddaman  */
ed_viread(void * context,int fd,register char * shbuf,int nchar,int reedit)212*b30d1939SAndy Fiddaman int ed_viread(void *context, int fd, register char *shbuf, int nchar, int reedit)
213*b30d1939SAndy Fiddaman {
214*b30d1939SAndy Fiddaman 	Edit_t *ed = (Edit_t*)context;
215*b30d1939SAndy Fiddaman 	register int i;			/* general variable */
216*b30d1939SAndy Fiddaman 	register int term_char=0;	/* read() termination character */
217*b30d1939SAndy Fiddaman 	register Vi_t *vp = ed->e_vi;
218*b30d1939SAndy Fiddaman 	char prompt[PRSIZE+2];		/* prompt */
219*b30d1939SAndy Fiddaman 	genchar Physical[2*MAXLINE];	/* physical image */
220*b30d1939SAndy Fiddaman 	genchar Ubuf[MAXLINE];	/* used for U command */
221*b30d1939SAndy Fiddaman 	genchar ubuf[MAXLINE];	/* used for u command */
222*b30d1939SAndy Fiddaman 	genchar Window[MAXLINE];	/* window image */
223*b30d1939SAndy Fiddaman 	int Globals[9];			/* local global variables */
224*b30d1939SAndy Fiddaman 	int esc_or_hang=0;		/* <ESC> or hangup */
225*b30d1939SAndy Fiddaman 	char cntl_char=0;		/* TRUE if control character present */
226*b30d1939SAndy Fiddaman #if SHOPT_RAWONLY
227*b30d1939SAndy Fiddaman #   define viraw	1
228*b30d1939SAndy Fiddaman #else
229*b30d1939SAndy Fiddaman 	int viraw = (sh_isoption(SH_VIRAW) || ed->sh->st.trap[SH_KEYTRAP]);
230*b30d1939SAndy Fiddaman #   ifndef FIORDCHK
231*b30d1939SAndy Fiddaman 	clock_t oldtime, newtime;
232*b30d1939SAndy Fiddaman 	struct tms dummy;
233*b30d1939SAndy Fiddaman #   endif /* FIORDCHK */
234*b30d1939SAndy Fiddaman #endif /* SHOPT_RAWONLY */
235*b30d1939SAndy Fiddaman 	if(!vp)
236*b30d1939SAndy Fiddaman 	{
237*b30d1939SAndy Fiddaman 		ed->e_vi = vp =  newof(0,Vi_t,1,0);
238*b30d1939SAndy Fiddaman 		vp->lastline = (genchar*)malloc(MAXLINE*CHARSIZE);
239*b30d1939SAndy Fiddaman 		vp->direction = -1;
240*b30d1939SAndy Fiddaman 		vp->ed = ed;
241*b30d1939SAndy Fiddaman 	}
242*b30d1939SAndy Fiddaman 
243*b30d1939SAndy Fiddaman 	/*** setup prompt ***/
244*b30d1939SAndy Fiddaman 
245*b30d1939SAndy Fiddaman 	Prompt = prompt;
246*b30d1939SAndy Fiddaman 	ed_setup(vp->ed,fd, reedit);
247*b30d1939SAndy Fiddaman 	shbuf[reedit] = 0;
248*b30d1939SAndy Fiddaman 
249*b30d1939SAndy Fiddaman #if !SHOPT_RAWONLY
250*b30d1939SAndy Fiddaman 	if(!viraw)
251*b30d1939SAndy Fiddaman 	{
252*b30d1939SAndy Fiddaman 		/*** Change the eol characters to '\r' and eof  ***/
253*b30d1939SAndy Fiddaman 		/* in addition to '\n' and make eof an ESC	*/
254*b30d1939SAndy Fiddaman 		if(tty_alt(ERRIO) < 0)
255*b30d1939SAndy Fiddaman 			return(reexit?reedit:ed_read(context, fd, shbuf, nchar,0));
256*b30d1939SAndy Fiddaman 
257*b30d1939SAndy Fiddaman #ifdef FIORDCHK
258*b30d1939SAndy Fiddaman 		ioctl(fd,FIORDCHK,&vp->typeahead);
259*b30d1939SAndy Fiddaman #else
260*b30d1939SAndy Fiddaman 		/* time the current line to determine typeahead */
261*b30d1939SAndy Fiddaman 		oldtime = times(&dummy);
262*b30d1939SAndy Fiddaman #endif /* FIORDCHK */
263*b30d1939SAndy Fiddaman #if KSHELL
264*b30d1939SAndy Fiddaman 		/* abort of interrupt has occurred */
265*b30d1939SAndy Fiddaman 		if(ed->sh->trapnote&SH_SIGSET)
266*b30d1939SAndy Fiddaman 			i = -1;
267*b30d1939SAndy Fiddaman 		else
268*b30d1939SAndy Fiddaman #endif /* KSHELL */
269*b30d1939SAndy Fiddaman 		/*** Read the line ***/
270*b30d1939SAndy Fiddaman 		i = ed_read(context, fd, shbuf, nchar, 0);
271*b30d1939SAndy Fiddaman #ifndef FIORDCHK
272*b30d1939SAndy Fiddaman 		newtime = times(&dummy);
273*b30d1939SAndy Fiddaman 		vp->typeahead = ((newtime-oldtime) < NTICKS);
274*b30d1939SAndy Fiddaman #endif /* FIORDCHK */
275*b30d1939SAndy Fiddaman 	    if(echoctl)
276*b30d1939SAndy Fiddaman 	    {
277*b30d1939SAndy Fiddaman 		if( i <= 0 )
278*b30d1939SAndy Fiddaman 		{
279*b30d1939SAndy Fiddaman 			/*** read error or eof typed ***/
280*b30d1939SAndy Fiddaman 			tty_cooked(ERRIO);
281*b30d1939SAndy Fiddaman 			return(i);
282*b30d1939SAndy Fiddaman 		}
283*b30d1939SAndy Fiddaman 		term_char = shbuf[--i];
284*b30d1939SAndy Fiddaman 		if( term_char == '\r' )
285*b30d1939SAndy Fiddaman 			term_char = '\n';
286*b30d1939SAndy Fiddaman 		if( term_char=='\n' || term_char==ESC )
287*b30d1939SAndy Fiddaman 			shbuf[i--] = '\0';
288*b30d1939SAndy Fiddaman 		else
289*b30d1939SAndy Fiddaman 			shbuf[i+1] = '\0';
290*b30d1939SAndy Fiddaman 	    }
291*b30d1939SAndy Fiddaman 	    else
292*b30d1939SAndy Fiddaman 	    {
293*b30d1939SAndy Fiddaman 		register int c = shbuf[0];
294*b30d1939SAndy Fiddaman 
295*b30d1939SAndy Fiddaman 		/*** Save and remove the last character if its an eol, ***/
296*b30d1939SAndy Fiddaman 		/* changing '\r' to '\n' */
297*b30d1939SAndy Fiddaman 
298*b30d1939SAndy Fiddaman 		if( i == 0 )
299*b30d1939SAndy Fiddaman 		{
300*b30d1939SAndy Fiddaman 			/*** ESC was typed as first char of line ***/
301*b30d1939SAndy Fiddaman 			esc_or_hang = 1;
302*b30d1939SAndy Fiddaman 			term_char = ESC;
303*b30d1939SAndy Fiddaman 			shbuf[i--] = '\0';	/* null terminate line */
304*b30d1939SAndy Fiddaman 		}
305*b30d1939SAndy Fiddaman 		else if( i<0 || c==usreof )
306*b30d1939SAndy Fiddaman 		{
307*b30d1939SAndy Fiddaman 			/*** read error or eof typed ***/
308*b30d1939SAndy Fiddaman 			tty_cooked(ERRIO);
309*b30d1939SAndy Fiddaman 			if( c == usreof )
310*b30d1939SAndy Fiddaman 				i = 0;
311*b30d1939SAndy Fiddaman 			return(i);
312*b30d1939SAndy Fiddaman 		}
313*b30d1939SAndy Fiddaman 		else
314*b30d1939SAndy Fiddaman 		{
315*b30d1939SAndy Fiddaman 			term_char = shbuf[--i];
316*b30d1939SAndy Fiddaman 			if( term_char == '\r' )
317*b30d1939SAndy Fiddaman 				term_char = '\n';
318*b30d1939SAndy Fiddaman #if !defined(VEOL2) && !defined(ECHOCTL)
319*b30d1939SAndy Fiddaman 			if(term_char=='\n')
320*b30d1939SAndy Fiddaman 			{
321*b30d1939SAndy Fiddaman 				tty_cooked(ERRIO);
322*b30d1939SAndy Fiddaman 				return(i+1);
323*b30d1939SAndy Fiddaman 			}
324*b30d1939SAndy Fiddaman #endif
325*b30d1939SAndy Fiddaman 			if( term_char=='\n' || term_char==usreof )
326*b30d1939SAndy Fiddaman 			{
327*b30d1939SAndy Fiddaman 				/*** remove terminator & null terminate ***/
328*b30d1939SAndy Fiddaman 				shbuf[i--] = '\0';
329*b30d1939SAndy Fiddaman 			}
330*b30d1939SAndy Fiddaman 			else
331*b30d1939SAndy Fiddaman 			{
332*b30d1939SAndy Fiddaman 				/** terminator was ESC, which is not xmitted **/
333*b30d1939SAndy Fiddaman 				term_char = ESC;
334*b30d1939SAndy Fiddaman 				shbuf[i+1] = '\0';
335*b30d1939SAndy Fiddaman 			}
336*b30d1939SAndy Fiddaman 		}
337*b30d1939SAndy Fiddaman 	    }
338*b30d1939SAndy Fiddaman 	}
339*b30d1939SAndy Fiddaman 	else
340*b30d1939SAndy Fiddaman #endif /* SHOPT_RAWONLY */
341*b30d1939SAndy Fiddaman 	{
342*b30d1939SAndy Fiddaman 		/*** Set raw mode ***/
343*b30d1939SAndy Fiddaman 
344*b30d1939SAndy Fiddaman #if !SHOPT_RAWONLY
345*b30d1939SAndy Fiddaman 		if( editb.e_ttyspeed == 0 )
346*b30d1939SAndy Fiddaman 		{
347*b30d1939SAndy Fiddaman 			/*** never did TCGETA, so do it ***/
348*b30d1939SAndy Fiddaman 			/* avoids problem if user does 'sh -o viraw' */
349*b30d1939SAndy Fiddaman 			tty_alt(ERRIO);
350*b30d1939SAndy Fiddaman 		}
351*b30d1939SAndy Fiddaman #endif /* SHOPT_RAWONLY */
352*b30d1939SAndy Fiddaman 		if(tty_raw(ERRIO,0) < 0 )
353*b30d1939SAndy Fiddaman 			return(reedit?reedit:ed_read(context, fd, shbuf, nchar,0));
354*b30d1939SAndy Fiddaman 		i = last_virt-1;
355*b30d1939SAndy Fiddaman 	}
356*b30d1939SAndy Fiddaman 
357*b30d1939SAndy Fiddaman 	/*** Initialize some things ***/
358*b30d1939SAndy Fiddaman 
359*b30d1939SAndy Fiddaman 	virtual = (genchar*)shbuf;
360*b30d1939SAndy Fiddaman #if SHOPT_MULTIBYTE
361*b30d1939SAndy Fiddaman 	virtual = (genchar*)roundof((char*)virtual-(char*)0,sizeof(genchar));
362*b30d1939SAndy Fiddaman 	shbuf[i+1] = 0;
363*b30d1939SAndy Fiddaman 	i = ed_internal(shbuf,virtual)-1;
364*b30d1939SAndy Fiddaman #endif /* SHOPT_MULTIBYTE */
365*b30d1939SAndy Fiddaman 	globals = Globals;
366*b30d1939SAndy Fiddaman 	cur_phys = i + 1;
367*b30d1939SAndy Fiddaman 	cur_virt = i;
368*b30d1939SAndy Fiddaman 	first_virt = 0;
369*b30d1939SAndy Fiddaman 	vp->first_wind = 0;
370*b30d1939SAndy Fiddaman 	last_virt = i;
371*b30d1939SAndy Fiddaman 	last_phys = i;
372*b30d1939SAndy Fiddaman 	vp->last_wind = i;
373*b30d1939SAndy Fiddaman 	vp->long_line = ' ';
374*b30d1939SAndy Fiddaman 	vp->long_char = ' ';
375*b30d1939SAndy Fiddaman 	vp->o_v_char = '\0';
376*b30d1939SAndy Fiddaman 	vp->ocur_phys = 0;
377*b30d1939SAndy Fiddaman 	vp->ocur_virt = MAXCHAR;
378*b30d1939SAndy Fiddaman 	vp->ofirst_wind = 0;
379*b30d1939SAndy Fiddaman 	physical = Physical;
380*b30d1939SAndy Fiddaman 	vp->u_column = INVALID - 1;
381*b30d1939SAndy Fiddaman 	vp->U_space = Ubuf;
382*b30d1939SAndy Fiddaman 	vp->u_space = ubuf;
383*b30d1939SAndy Fiddaman 	window = Window;
384*b30d1939SAndy Fiddaman 	window[0] = '\0';
385*b30d1939SAndy Fiddaman 
386*b30d1939SAndy Fiddaman 	if(!yankbuf)
387*b30d1939SAndy Fiddaman 		yankbuf = (genchar*)malloc(MAXLINE*CHARSIZE);
388*b30d1939SAndy Fiddaman 	if( vp->last_cmd == '\0' )
389*b30d1939SAndy Fiddaman 	{
390*b30d1939SAndy Fiddaman 		/*** first time for this shell ***/
391*b30d1939SAndy Fiddaman 
392*b30d1939SAndy Fiddaman 		vp->last_cmd = 'i';
393*b30d1939SAndy Fiddaman 		vp->findchar = INVALID;
394*b30d1939SAndy Fiddaman 		vp->lastmotion = '\0';
395*b30d1939SAndy Fiddaman 		vp->lastrepeat = 1;
396*b30d1939SAndy Fiddaman 		vp->repeat = 1;
397*b30d1939SAndy Fiddaman 		*yankbuf = 0;
398*b30d1939SAndy Fiddaman 	}
399*b30d1939SAndy Fiddaman 
400*b30d1939SAndy Fiddaman 	/*** fiddle around with prompt length ***/
401*b30d1939SAndy Fiddaman 	if( nchar+plen > MAXCHAR )
402*b30d1939SAndy Fiddaman 		nchar = MAXCHAR - plen;
403*b30d1939SAndy Fiddaman 	max_col = nchar - 2;
404*b30d1939SAndy Fiddaman 
405*b30d1939SAndy Fiddaman 	if( !viraw )
406*b30d1939SAndy Fiddaman 	{
407*b30d1939SAndy Fiddaman 		int kill_erase = 0;
408*b30d1939SAndy Fiddaman 		for(i=(echoctl?last_virt:0); i<last_virt; ++i )
409*b30d1939SAndy Fiddaman 		{
410*b30d1939SAndy Fiddaman 			/*** change \r to \n, check for control characters, ***/
411*b30d1939SAndy Fiddaman 			/* delete appropriate ^Vs,			*/
412*b30d1939SAndy Fiddaman 			/* and estimate last physical column */
413*b30d1939SAndy Fiddaman 
414*b30d1939SAndy Fiddaman 			if( virtual[i] == '\r' )
415*b30d1939SAndy Fiddaman 				virtual[i] = '\n';
416*b30d1939SAndy Fiddaman 		    if(!echoctl)
417*b30d1939SAndy Fiddaman 		    {
418*b30d1939SAndy Fiddaman 			register int c = virtual[i];
419*b30d1939SAndy Fiddaman 			if( c<=usrerase)
420*b30d1939SAndy Fiddaman 			{
421*b30d1939SAndy Fiddaman 				/*** user typed escaped erase or kill char ***/
422*b30d1939SAndy Fiddaman 				cntl_char = 1;
423*b30d1939SAndy Fiddaman 				if(is_print(c))
424*b30d1939SAndy Fiddaman 					kill_erase++;
425*b30d1939SAndy Fiddaman 			}
426*b30d1939SAndy Fiddaman 			else if( !is_print(c) )
427*b30d1939SAndy Fiddaman 			{
428*b30d1939SAndy Fiddaman 				cntl_char = 1;
429*b30d1939SAndy Fiddaman 
430*b30d1939SAndy Fiddaman 				if( c == usrlnext )
431*b30d1939SAndy Fiddaman 				{
432*b30d1939SAndy Fiddaman 					if( i == last_virt )
433*b30d1939SAndy Fiddaman 					{
434*b30d1939SAndy Fiddaman 						/*** eol/eof was escaped ***/
435*b30d1939SAndy Fiddaman 						/* so replace ^V with it */
436*b30d1939SAndy Fiddaman 						virtual[i] = term_char;
437*b30d1939SAndy Fiddaman 						break;
438*b30d1939SAndy Fiddaman 					}
439*b30d1939SAndy Fiddaman 
440*b30d1939SAndy Fiddaman 					/*** delete ^V ***/
441*b30d1939SAndy Fiddaman 					gencpy((&virtual[i]), (&virtual[i+1]));
442*b30d1939SAndy Fiddaman 					--cur_virt;
443*b30d1939SAndy Fiddaman 					--last_virt;
444*b30d1939SAndy Fiddaman 				}
445*b30d1939SAndy Fiddaman 			}
446*b30d1939SAndy Fiddaman 		    }
447*b30d1939SAndy Fiddaman 		}
448*b30d1939SAndy Fiddaman 
449*b30d1939SAndy Fiddaman 		/*** copy virtual image to window ***/
450*b30d1939SAndy Fiddaman 		if(last_virt > 0)
451*b30d1939SAndy Fiddaman 			last_phys = ed_virt_to_phys(vp->ed,virtual,physical,last_virt,0,0);
452*b30d1939SAndy Fiddaman 		if( last_phys >= w_size )
453*b30d1939SAndy Fiddaman 		{
454*b30d1939SAndy Fiddaman 			/*** line longer than window ***/
455*b30d1939SAndy Fiddaman 			vp->last_wind = w_size - 1;
456*b30d1939SAndy Fiddaman 		}
457*b30d1939SAndy Fiddaman 		else
458*b30d1939SAndy Fiddaman 			vp->last_wind = last_phys;
459*b30d1939SAndy Fiddaman 		genncpy(window, virtual, vp->last_wind+1);
460*b30d1939SAndy Fiddaman 
461*b30d1939SAndy Fiddaman 		if( term_char!=ESC  && (last_virt==INVALID
462*b30d1939SAndy Fiddaman 			|| virtual[last_virt]!=term_char) )
463*b30d1939SAndy Fiddaman 		{
464*b30d1939SAndy Fiddaman 			/*** Line not terminated with ESC or escaped (^V) ***/
465*b30d1939SAndy Fiddaman 			/* eol, so return after doing a total update */
466*b30d1939SAndy Fiddaman 			/* if( (speed is greater or equal to 1200 */
467*b30d1939SAndy Fiddaman 			/* and something was typed) and */
468*b30d1939SAndy Fiddaman 			/* (control character present */
469*b30d1939SAndy Fiddaman 			/* or typeahead occurred) ) */
470*b30d1939SAndy Fiddaman 
471*b30d1939SAndy Fiddaman 			tty_cooked(ERRIO);
472*b30d1939SAndy Fiddaman 			if( editb.e_ttyspeed==FAST && last_virt!=INVALID
473*b30d1939SAndy Fiddaman 				&& (vp->typeahead || cntl_char) )
474*b30d1939SAndy Fiddaman 			{
475*b30d1939SAndy Fiddaman 				refresh(vp,TRANSLATE);
476*b30d1939SAndy Fiddaman 				pr_string(vp,Prompt);
477*b30d1939SAndy Fiddaman 				putstring(vp,0, last_phys+1);
478*b30d1939SAndy Fiddaman 				if(echoctl)
479*b30d1939SAndy Fiddaman 					ed_crlf(vp->ed);
480*b30d1939SAndy Fiddaman 				else
481*b30d1939SAndy Fiddaman 					while(kill_erase-- > 0)
482*b30d1939SAndy Fiddaman 						putchar(' ');
483*b30d1939SAndy Fiddaman 			}
484*b30d1939SAndy Fiddaman 
485*b30d1939SAndy Fiddaman 			if( term_char=='\n' )
486*b30d1939SAndy Fiddaman 			{
487*b30d1939SAndy Fiddaman 				if(!echoctl)
488*b30d1939SAndy Fiddaman 					ed_crlf(vp->ed);
489*b30d1939SAndy Fiddaman 				virtual[++last_virt] = '\n';
490*b30d1939SAndy Fiddaman 			}
491*b30d1939SAndy Fiddaman 			vp->last_cmd = 'i';
492*b30d1939SAndy Fiddaman 			save_last(vp);
493*b30d1939SAndy Fiddaman #if SHOPT_MULTIBYTE
494*b30d1939SAndy Fiddaman 			virtual[last_virt+1] = 0;
495*b30d1939SAndy Fiddaman 			last_virt = ed_external(virtual,shbuf);
496*b30d1939SAndy Fiddaman 			return(last_virt);
497*b30d1939SAndy Fiddaman #else
498*b30d1939SAndy Fiddaman 			return(++last_virt);
499*b30d1939SAndy Fiddaman #endif /* SHOPT_MULTIBYTE */
500*b30d1939SAndy Fiddaman 		}
501*b30d1939SAndy Fiddaman 
502*b30d1939SAndy Fiddaman 		/*** Line terminated with escape, or escaped eol/eof, ***/
503*b30d1939SAndy Fiddaman 		/*  so set raw mode */
504*b30d1939SAndy Fiddaman 
505*b30d1939SAndy Fiddaman 		if( tty_raw(ERRIO,0) < 0 )
506*b30d1939SAndy Fiddaman 		{
507*b30d1939SAndy Fiddaman 			tty_cooked(ERRIO);
508*b30d1939SAndy Fiddaman 			/*
509*b30d1939SAndy Fiddaman 			 * The following prevents drivers that return 0 on
510*b30d1939SAndy Fiddaman 			 * causing an infinite loop
511*b30d1939SAndy Fiddaman 			 */
512*b30d1939SAndy Fiddaman 			if(esc_or_hang)
513*b30d1939SAndy Fiddaman 				return(-1);
514*b30d1939SAndy Fiddaman 			virtual[++last_virt] = '\n';
515*b30d1939SAndy Fiddaman #if SHOPT_MULTIBYTE
516*b30d1939SAndy Fiddaman 			virtual[last_virt+1] = 0;
517*b30d1939SAndy Fiddaman 			last_virt = ed_external(virtual,shbuf);
518*b30d1939SAndy Fiddaman 			return(last_virt);
519*b30d1939SAndy Fiddaman #else
520*b30d1939SAndy Fiddaman 			return(++last_virt);
521*b30d1939SAndy Fiddaman #endif /* SHOPT_MULTIBYTE */
522*b30d1939SAndy Fiddaman 		}
523*b30d1939SAndy Fiddaman 
524*b30d1939SAndy Fiddaman 		if(echoctl) /*** for cntl-echo erase the ^[ ***/
525*b30d1939SAndy Fiddaman 			pr_string(vp,"\b\b\b\b      \b\b");
526*b30d1939SAndy Fiddaman 
527*b30d1939SAndy Fiddaman 
528*b30d1939SAndy Fiddaman 		if(crallowed)
529*b30d1939SAndy Fiddaman 		{
530*b30d1939SAndy Fiddaman 			/*** start over since there may be ***/
531*b30d1939SAndy Fiddaman 			/*** a control char, or cursor might not ***/
532*b30d1939SAndy Fiddaman 			/*** be at left margin (this lets us know ***/
533*b30d1939SAndy Fiddaman 			/*** where we are ***/
534*b30d1939SAndy Fiddaman 			cur_phys = 0;
535*b30d1939SAndy Fiddaman 			window[0] = '\0';
536*b30d1939SAndy Fiddaman 			pr_string(vp,Prompt);
537*b30d1939SAndy Fiddaman 			if( term_char==ESC && (last_virt<0 || virtual[last_virt]!=ESC))
538*b30d1939SAndy Fiddaman 				refresh(vp,CONTROL);
539*b30d1939SAndy Fiddaman 			else
540*b30d1939SAndy Fiddaman 				refresh(vp,INPUT);
541*b30d1939SAndy Fiddaman 		}
542*b30d1939SAndy Fiddaman 		else
543*b30d1939SAndy Fiddaman 		{
544*b30d1939SAndy Fiddaman 			/*** just update everything internally ***/
545*b30d1939SAndy Fiddaman 			refresh(vp,TRANSLATE);
546*b30d1939SAndy Fiddaman 		}
547*b30d1939SAndy Fiddaman 	}
548*b30d1939SAndy Fiddaman 
549*b30d1939SAndy Fiddaman 	/*** Handle usrintr, usrquit, or EOF ***/
550*b30d1939SAndy Fiddaman 
551*b30d1939SAndy Fiddaman 	i = sigsetjmp(editb.e_env,0);
552*b30d1939SAndy Fiddaman 	if( i != 0 )
553*b30d1939SAndy Fiddaman 	{
554*b30d1939SAndy Fiddaman 		if(vp->ed->e_multiline)
555*b30d1939SAndy Fiddaman 		{
556*b30d1939SAndy Fiddaman 			cur_virt = last_virt;
557*b30d1939SAndy Fiddaman 			sync_cursor(vp);
558*b30d1939SAndy Fiddaman 		}
559*b30d1939SAndy Fiddaman 		virtual[0] = '\0';
560*b30d1939SAndy Fiddaman 		tty_cooked(ERRIO);
561*b30d1939SAndy Fiddaman 
562*b30d1939SAndy Fiddaman 		switch(i)
563*b30d1939SAndy Fiddaman 		{
564*b30d1939SAndy Fiddaman 		case UEOF:
565*b30d1939SAndy Fiddaman 			/*** EOF ***/
566*b30d1939SAndy Fiddaman 			return(0);
567*b30d1939SAndy Fiddaman 
568*b30d1939SAndy Fiddaman 		case UINTR:
569*b30d1939SAndy Fiddaman 			/** interrupt **/
570*b30d1939SAndy Fiddaman 			return(-1);
571*b30d1939SAndy Fiddaman 		}
572*b30d1939SAndy Fiddaman 		return(-1);
573*b30d1939SAndy Fiddaman 	}
574*b30d1939SAndy Fiddaman 
575*b30d1939SAndy Fiddaman 	/*** Get a line from the terminal ***/
576*b30d1939SAndy Fiddaman 
577*b30d1939SAndy Fiddaman 	vp->U_saved = 0;
578*b30d1939SAndy Fiddaman 	if(reedit)
579*b30d1939SAndy Fiddaman 	{
580*b30d1939SAndy Fiddaman 		cur_phys = vp->first_wind;
581*b30d1939SAndy Fiddaman 		vp->ofirst_wind = INVALID;
582*b30d1939SAndy Fiddaman 		refresh(vp,INPUT);
583*b30d1939SAndy Fiddaman 	}
584*b30d1939SAndy Fiddaman 	if(viraw)
585*b30d1939SAndy Fiddaman 		getline(vp,APPEND);
586*b30d1939SAndy Fiddaman 	else if(last_virt>=0 && virtual[last_virt]==term_char)
587*b30d1939SAndy Fiddaman 		getline(vp,APPEND);
588*b30d1939SAndy Fiddaman 	else
589*b30d1939SAndy Fiddaman 		getline(vp,ESC);
590*b30d1939SAndy Fiddaman 	if(vp->ed->e_multiline)
591*b30d1939SAndy Fiddaman 		cursor(vp, last_phys);
592*b30d1939SAndy Fiddaman 	/*** add a new line if user typed unescaped \n ***/
593*b30d1939SAndy Fiddaman 	/* to cause the shell to process the line */
594*b30d1939SAndy Fiddaman 	tty_cooked(ERRIO);
595*b30d1939SAndy Fiddaman 	if(ed->e_nlist)
596*b30d1939SAndy Fiddaman 	{
597*b30d1939SAndy Fiddaman 		ed->e_nlist = 0;
598*b30d1939SAndy Fiddaman 		stakset(ed->e_stkptr,ed->e_stkoff);
599*b30d1939SAndy Fiddaman 	}
600*b30d1939SAndy Fiddaman 	if( vp->addnl )
601*b30d1939SAndy Fiddaman 	{
602*b30d1939SAndy Fiddaman 		virtual[++last_virt] = '\n';
603*b30d1939SAndy Fiddaman 		ed_crlf(vp->ed);
604*b30d1939SAndy Fiddaman 	}
605*b30d1939SAndy Fiddaman 	if( ++last_virt >= 0 )
606*b30d1939SAndy Fiddaman 	{
607*b30d1939SAndy Fiddaman #if SHOPT_MULTIBYTE
608*b30d1939SAndy Fiddaman 		if(vp->bigvi)
609*b30d1939SAndy Fiddaman 		{
610*b30d1939SAndy Fiddaman 			vp->bigvi = 0;
611*b30d1939SAndy Fiddaman 			shbuf[last_virt-1] = '\n';
612*b30d1939SAndy Fiddaman 		}
613*b30d1939SAndy Fiddaman 		else
614*b30d1939SAndy Fiddaman 		{
615*b30d1939SAndy Fiddaman 			virtual[last_virt] = 0;
616*b30d1939SAndy Fiddaman 			last_virt = ed_external(virtual,shbuf);
617*b30d1939SAndy Fiddaman 		}
618*b30d1939SAndy Fiddaman #endif /* SHOPT_MULTIBYTE */
619*b30d1939SAndy Fiddaman #if SHOPT_EDPREDICT
620*b30d1939SAndy Fiddaman 		if(vp->ed->nhlist)
621*b30d1939SAndy Fiddaman 			ed_histlist(vp->ed,0);
622*b30d1939SAndy Fiddaman #endif /* SHOPT_EDPREDICT */
623*b30d1939SAndy Fiddaman 		return(last_virt);
624*b30d1939SAndy Fiddaman 	}
625*b30d1939SAndy Fiddaman 	else
626*b30d1939SAndy Fiddaman 		return(-1);
627*b30d1939SAndy Fiddaman }
628*b30d1939SAndy Fiddaman 
629*b30d1939SAndy Fiddaman 
630*b30d1939SAndy Fiddaman /*{	APPEND( char, mode )
631*b30d1939SAndy Fiddaman  *
632*b30d1939SAndy Fiddaman  *	This routine will append char after cur_virt in the virtual image.
633*b30d1939SAndy Fiddaman  * mode	=	APPEND, shift chars right before appending
634*b30d1939SAndy Fiddaman  *		REPLACE, replace char if possible
635*b30d1939SAndy Fiddaman  *
636*b30d1939SAndy Fiddaman }*/
637*b30d1939SAndy Fiddaman 
append(Vi_t * vp,int c,int mode)638*b30d1939SAndy Fiddaman static void append(Vi_t *vp,int c, int mode)
639*b30d1939SAndy Fiddaman {
640*b30d1939SAndy Fiddaman 	register int i,j;
641*b30d1939SAndy Fiddaman 
642*b30d1939SAndy Fiddaman 	if( last_virt<max_col && last_phys<max_col )
643*b30d1939SAndy Fiddaman 	{
644*b30d1939SAndy Fiddaman 		if( mode==APPEND || (cur_virt==last_virt  && last_virt>=0))
645*b30d1939SAndy Fiddaman 		{
646*b30d1939SAndy Fiddaman 			j = (cur_virt>=0?cur_virt:0);
647*b30d1939SAndy Fiddaman 			for(i = ++last_virt;  i > j; --i)
648*b30d1939SAndy Fiddaman 				virtual[i] = virtual[i-1];
649*b30d1939SAndy Fiddaman 		}
650*b30d1939SAndy Fiddaman 		virtual[++cur_virt] = c;
651*b30d1939SAndy Fiddaman 	}
652*b30d1939SAndy Fiddaman 	else
653*b30d1939SAndy Fiddaman 		ed_ringbell();
654*b30d1939SAndy Fiddaman 	return;
655*b30d1939SAndy Fiddaman }
656*b30d1939SAndy Fiddaman 
657*b30d1939SAndy Fiddaman /*{	BACKWORD( nwords, cmd )
658*b30d1939SAndy Fiddaman  *
659*b30d1939SAndy Fiddaman  *	This routine will position cur_virt at the nth previous word.
660*b30d1939SAndy Fiddaman  *
661*b30d1939SAndy Fiddaman }*/
662*b30d1939SAndy Fiddaman 
backword(Vi_t * vp,int nwords,register int cmd)663*b30d1939SAndy Fiddaman static void backword(Vi_t *vp,int nwords, register int cmd)
664*b30d1939SAndy Fiddaman {
665*b30d1939SAndy Fiddaman 	register int tcur_virt = cur_virt;
666*b30d1939SAndy Fiddaman 	while( nwords-- && tcur_virt > first_virt )
667*b30d1939SAndy Fiddaman 	{
668*b30d1939SAndy Fiddaman 		if( !isblank(tcur_virt) && isblank(tcur_virt-1)
669*b30d1939SAndy Fiddaman 			&& tcur_virt>first_virt )
670*b30d1939SAndy Fiddaman 			--tcur_virt;
671*b30d1939SAndy Fiddaman 		else if(cmd != 'B')
672*b30d1939SAndy Fiddaman 		{
673*b30d1939SAndy Fiddaman 			register int last = isalph(tcur_virt-1);
674*b30d1939SAndy Fiddaman 			register int cur = isalph(tcur_virt);
675*b30d1939SAndy Fiddaman 			if((!cur && last) || (cur && !last))
676*b30d1939SAndy Fiddaman 				--tcur_virt;
677*b30d1939SAndy Fiddaman 		}
678*b30d1939SAndy Fiddaman 		while( isblank(tcur_virt) && tcur_virt>=first_virt )
679*b30d1939SAndy Fiddaman 			--tcur_virt;
680*b30d1939SAndy Fiddaman 		if( cmd == 'B' )
681*b30d1939SAndy Fiddaman 		{
682*b30d1939SAndy Fiddaman 			while( !isblank(tcur_virt) && tcur_virt>=first_virt )
683*b30d1939SAndy Fiddaman 				--tcur_virt;
684*b30d1939SAndy Fiddaman 		}
685*b30d1939SAndy Fiddaman 		else
686*b30d1939SAndy Fiddaman 		{
687*b30d1939SAndy Fiddaman 			if(isalph(tcur_virt))
688*b30d1939SAndy Fiddaman 				while( isalph(tcur_virt) && tcur_virt>=first_virt )
689*b30d1939SAndy Fiddaman 					--tcur_virt;
690*b30d1939SAndy Fiddaman 			else
691*b30d1939SAndy Fiddaman 				while( !isalph(tcur_virt) && !isblank(tcur_virt)
692*b30d1939SAndy Fiddaman 					&& tcur_virt>=first_virt )
693*b30d1939SAndy Fiddaman 					--tcur_virt;
694*b30d1939SAndy Fiddaman 		}
695*b30d1939SAndy Fiddaman 		cur_virt = ++tcur_virt;
696*b30d1939SAndy Fiddaman 	}
697*b30d1939SAndy Fiddaman 	return;
698*b30d1939SAndy Fiddaman }
699*b30d1939SAndy Fiddaman 
700*b30d1939SAndy Fiddaman /*{	CNTLMODE()
701*b30d1939SAndy Fiddaman  *
702*b30d1939SAndy Fiddaman  *	This routine implements the vi command subset.
703*b30d1939SAndy Fiddaman  *	The cursor will always be positioned at the char of interest.
704*b30d1939SAndy Fiddaman  *
705*b30d1939SAndy Fiddaman }*/
706*b30d1939SAndy Fiddaman 
cntlmode(Vi_t * vp)707*b30d1939SAndy Fiddaman static int cntlmode(Vi_t *vp)
708*b30d1939SAndy Fiddaman {
709*b30d1939SAndy Fiddaman 	register int c;
710*b30d1939SAndy Fiddaman 	register int i;
711*b30d1939SAndy Fiddaman 	genchar tmp_u_space[MAXLINE];	/* temporary u_space */
712*b30d1939SAndy Fiddaman 	genchar *real_u_space;		/* points to real u_space */
713*b30d1939SAndy Fiddaman 	int tmp_u_column = INVALID;	/* temporary u_column */
714*b30d1939SAndy Fiddaman 	int was_inmacro;
715*b30d1939SAndy Fiddaman 
716*b30d1939SAndy Fiddaman 	if(!vp->U_saved)
717*b30d1939SAndy Fiddaman 	{
718*b30d1939SAndy Fiddaman 		/*** save virtual image if never done before ***/
719*b30d1939SAndy Fiddaman 		virtual[last_virt+1] = '\0';
720*b30d1939SAndy Fiddaman 		gencpy(vp->U_space, virtual);
721*b30d1939SAndy Fiddaman 		vp->U_saved = 1;
722*b30d1939SAndy Fiddaman 	}
723*b30d1939SAndy Fiddaman 
724*b30d1939SAndy Fiddaman 	save_last(vp);
725*b30d1939SAndy Fiddaman 
726*b30d1939SAndy Fiddaman 	real_u_space = vp->u_space;
727*b30d1939SAndy Fiddaman 	curhline = histmax;
728*b30d1939SAndy Fiddaman 	first_virt = 0;
729*b30d1939SAndy Fiddaman 	vp->repeat = 1;
730*b30d1939SAndy Fiddaman 	if( cur_virt > INVALID )
731*b30d1939SAndy Fiddaman 	{
732*b30d1939SAndy Fiddaman 		/*** make sure cursor is at the last char ***/
733*b30d1939SAndy Fiddaman 		sync_cursor(vp);
734*b30d1939SAndy Fiddaman 	}
735*b30d1939SAndy Fiddaman 	else if(last_virt > INVALID )
736*b30d1939SAndy Fiddaman 		cur_virt++;
737*b30d1939SAndy Fiddaman 
738*b30d1939SAndy Fiddaman 	/*** Read control char until something happens to cause a ***/
739*b30d1939SAndy Fiddaman 	/* return to APPEND/REPLACE mode	*/
740*b30d1939SAndy Fiddaman 
741*b30d1939SAndy Fiddaman 	while( c=ed_getchar(vp->ed,-1) )
742*b30d1939SAndy Fiddaman 	{
743*b30d1939SAndy Fiddaman 		vp->repeat_set = 0;
744*b30d1939SAndy Fiddaman 		was_inmacro = inmacro;
745*b30d1939SAndy Fiddaman 		if( c == '0' )
746*b30d1939SAndy Fiddaman 		{
747*b30d1939SAndy Fiddaman 			/*** move to leftmost column ***/
748*b30d1939SAndy Fiddaman 			cur_virt = 0;
749*b30d1939SAndy Fiddaman 			sync_cursor(vp);
750*b30d1939SAndy Fiddaman 			continue;
751*b30d1939SAndy Fiddaman 		}
752*b30d1939SAndy Fiddaman 
753*b30d1939SAndy Fiddaman 		if( digit(c) )
754*b30d1939SAndy Fiddaman 		{
755*b30d1939SAndy Fiddaman 			c = getcount(vp,c);
756*b30d1939SAndy Fiddaman 			if( c == '.' )
757*b30d1939SAndy Fiddaman 				vp->lastrepeat = vp->repeat;
758*b30d1939SAndy Fiddaman 		}
759*b30d1939SAndy Fiddaman 
760*b30d1939SAndy Fiddaman 		/*** see if it's a move cursor command ***/
761*b30d1939SAndy Fiddaman 
762*b30d1939SAndy Fiddaman 		if(mvcursor(vp,c))
763*b30d1939SAndy Fiddaman 		{
764*b30d1939SAndy Fiddaman 			sync_cursor(vp);
765*b30d1939SAndy Fiddaman 			vp->repeat = 1;
766*b30d1939SAndy Fiddaman 			continue;
767*b30d1939SAndy Fiddaman 		}
768*b30d1939SAndy Fiddaman 
769*b30d1939SAndy Fiddaman 		/*** see if it's a repeat of the last command ***/
770*b30d1939SAndy Fiddaman 
771*b30d1939SAndy Fiddaman 		if( c == '.' )
772*b30d1939SAndy Fiddaman 		{
773*b30d1939SAndy Fiddaman 			c = vp->last_cmd;
774*b30d1939SAndy Fiddaman 			vp->repeat = vp->lastrepeat;
775*b30d1939SAndy Fiddaman 			i = textmod(vp,c, c);
776*b30d1939SAndy Fiddaman 		}
777*b30d1939SAndy Fiddaman 		else
778*b30d1939SAndy Fiddaman 		{
779*b30d1939SAndy Fiddaman 			i = textmod(vp,c, 0);
780*b30d1939SAndy Fiddaman 		}
781*b30d1939SAndy Fiddaman 
782*b30d1939SAndy Fiddaman 		/*** see if it's a text modification command ***/
783*b30d1939SAndy Fiddaman 
784*b30d1939SAndy Fiddaman 		switch(i)
785*b30d1939SAndy Fiddaman 		{
786*b30d1939SAndy Fiddaman 		case BAD:
787*b30d1939SAndy Fiddaman 			break;
788*b30d1939SAndy Fiddaman 
789*b30d1939SAndy Fiddaman 		default:		/** input mode **/
790*b30d1939SAndy Fiddaman 			if(!was_inmacro)
791*b30d1939SAndy Fiddaman 			{
792*b30d1939SAndy Fiddaman 				vp->last_cmd = c;
793*b30d1939SAndy Fiddaman 				vp->lastrepeat = vp->repeat;
794*b30d1939SAndy Fiddaman 			}
795*b30d1939SAndy Fiddaman 			vp->repeat = 1;
796*b30d1939SAndy Fiddaman 			if( i == GOOD )
797*b30d1939SAndy Fiddaman 				continue;
798*b30d1939SAndy Fiddaman 			return(i);
799*b30d1939SAndy Fiddaman 		}
800*b30d1939SAndy Fiddaman 
801*b30d1939SAndy Fiddaman 		switch( c )
802*b30d1939SAndy Fiddaman 		{
803*b30d1939SAndy Fiddaman 			/***** Other stuff *****/
804*b30d1939SAndy Fiddaman 
805*b30d1939SAndy Fiddaman 		case cntl('L'):		/** Redraw line **/
806*b30d1939SAndy Fiddaman 			/*** print the prompt and ***/
807*b30d1939SAndy Fiddaman 			/* force a total refresh */
808*b30d1939SAndy Fiddaman 			if(vp->nonewline==0 && !vp->ed->e_nocrnl)
809*b30d1939SAndy Fiddaman 				putchar('\n');
810*b30d1939SAndy Fiddaman 			vp->nonewline = 0;
811*b30d1939SAndy Fiddaman 			pr_string(vp,Prompt);
812*b30d1939SAndy Fiddaman 			window[0] = '\0';
813*b30d1939SAndy Fiddaman 			cur_phys = vp->first_wind;
814*b30d1939SAndy Fiddaman 			vp->ofirst_wind = INVALID;
815*b30d1939SAndy Fiddaman 			vp->long_line = ' ';
816*b30d1939SAndy Fiddaman 			break;
817*b30d1939SAndy Fiddaman 
818*b30d1939SAndy Fiddaman 		case cntl('V'):
819*b30d1939SAndy Fiddaman 		{
820*b30d1939SAndy Fiddaman 			register const char *p = fmtident(e_version);
821*b30d1939SAndy Fiddaman 			save_v(vp);
822*b30d1939SAndy Fiddaman 			del_line(vp,BAD);
823*b30d1939SAndy Fiddaman 			while(c = *p++)
824*b30d1939SAndy Fiddaman 				append(vp,c,APPEND);
825*b30d1939SAndy Fiddaman 			refresh(vp,CONTROL);
826*b30d1939SAndy Fiddaman 			ed_getchar(vp->ed,-1);
827*b30d1939SAndy Fiddaman 			restore_v(vp);
828*b30d1939SAndy Fiddaman 			ed_ungetchar(vp->ed,'a');
829*b30d1939SAndy Fiddaman 			break;
830*b30d1939SAndy Fiddaman 		}
831*b30d1939SAndy Fiddaman 
832*b30d1939SAndy Fiddaman 		case '/':		/** Search **/
833*b30d1939SAndy Fiddaman 		case '?':
834*b30d1939SAndy Fiddaman 		case 'N':
835*b30d1939SAndy Fiddaman 		case 'n':
836*b30d1939SAndy Fiddaman 			save_v(vp);
837*b30d1939SAndy Fiddaman 			switch( search(vp,c) )
838*b30d1939SAndy Fiddaman 			{
839*b30d1939SAndy Fiddaman 			case GOOD:
840*b30d1939SAndy Fiddaman 				/*** force a total refresh ***/
841*b30d1939SAndy Fiddaman 				window[0] = '\0';
842*b30d1939SAndy Fiddaman 				goto newhist;
843*b30d1939SAndy Fiddaman 
844*b30d1939SAndy Fiddaman 			case BAD:
845*b30d1939SAndy Fiddaman 				/*** no match ***/
846*b30d1939SAndy Fiddaman 					ed_ringbell();
847*b30d1939SAndy Fiddaman 				/* FALLTHROUGH */
848*b30d1939SAndy Fiddaman 
849*b30d1939SAndy Fiddaman 			default:
850*b30d1939SAndy Fiddaman 				if( vp->u_column == INVALID )
851*b30d1939SAndy Fiddaman 					del_line(vp,BAD);
852*b30d1939SAndy Fiddaman 				else
853*b30d1939SAndy Fiddaman 					restore_v(vp);
854*b30d1939SAndy Fiddaman 				break;
855*b30d1939SAndy Fiddaman 			}
856*b30d1939SAndy Fiddaman 			break;
857*b30d1939SAndy Fiddaman 
858*b30d1939SAndy Fiddaman 		case 'j':		/** get next command **/
859*b30d1939SAndy Fiddaman 		case '+':		/** get next command **/
860*b30d1939SAndy Fiddaman #if SHOPT_EDPREDICT
861*b30d1939SAndy Fiddaman 			if(vp->ed->hlist)
862*b30d1939SAndy Fiddaman 			{
863*b30d1939SAndy Fiddaman 				if(vp->ed->hoff >= vp->ed->hmax)
864*b30d1939SAndy Fiddaman 					goto ringbell;
865*b30d1939SAndy Fiddaman 				vp->ed->hoff++;
866*b30d1939SAndy Fiddaman 				goto hupdate;
867*b30d1939SAndy Fiddaman 			}
868*b30d1939SAndy Fiddaman #endif /* SHOPT_EDPREDICT */
869*b30d1939SAndy Fiddaman 			curhline += vp->repeat;
870*b30d1939SAndy Fiddaman 			if( curhline > histmax )
871*b30d1939SAndy Fiddaman 			{
872*b30d1939SAndy Fiddaman 				curhline = histmax;
873*b30d1939SAndy Fiddaman 				goto ringbell;
874*b30d1939SAndy Fiddaman 			}
875*b30d1939SAndy Fiddaman 			else if(curhline==histmax && tmp_u_column!=INVALID )
876*b30d1939SAndy Fiddaman 			{
877*b30d1939SAndy Fiddaman 				vp->u_space = tmp_u_space;
878*b30d1939SAndy Fiddaman 				vp->u_column = tmp_u_column;
879*b30d1939SAndy Fiddaman 				restore_v(vp);
880*b30d1939SAndy Fiddaman 				vp->u_space = real_u_space;
881*b30d1939SAndy Fiddaman 				break;
882*b30d1939SAndy Fiddaman 			}
883*b30d1939SAndy Fiddaman 			save_v(vp);
884*b30d1939SAndy Fiddaman 			cur_virt = INVALID;
885*b30d1939SAndy Fiddaman 			goto newhist;
886*b30d1939SAndy Fiddaman 
887*b30d1939SAndy Fiddaman 		case 'k':		/** get previous command **/
888*b30d1939SAndy Fiddaman 		case '-':		/** get previous command **/
889*b30d1939SAndy Fiddaman #if SHOPT_EDPREDICT
890*b30d1939SAndy Fiddaman 			if(vp->ed->hlist)
891*b30d1939SAndy Fiddaman 			{
892*b30d1939SAndy Fiddaman 				if(vp->ed->hoff == 0)
893*b30d1939SAndy Fiddaman 					goto ringbell;
894*b30d1939SAndy Fiddaman 				vp->ed->hoff--;
895*b30d1939SAndy Fiddaman 			 hupdate:
896*b30d1939SAndy Fiddaman 				ed_histlist(vp->ed,*vp->ed->hlist!=0);
897*b30d1939SAndy Fiddaman 				vp->nonewline++;
898*b30d1939SAndy Fiddaman 				ed_ungetchar(vp->ed,cntl('L'));
899*b30d1939SAndy Fiddaman 				continue;
900*b30d1939SAndy Fiddaman 			}
901*b30d1939SAndy Fiddaman #endif /* SHOPT_EDPREDICT */
902*b30d1939SAndy Fiddaman 			if( curhline == histmax )
903*b30d1939SAndy Fiddaman 			{
904*b30d1939SAndy Fiddaman 				vp->u_space = tmp_u_space;
905*b30d1939SAndy Fiddaman 				i = vp->u_column;
906*b30d1939SAndy Fiddaman 				save_v(vp);
907*b30d1939SAndy Fiddaman 				vp->u_space = real_u_space;
908*b30d1939SAndy Fiddaman 				tmp_u_column = vp->u_column;
909*b30d1939SAndy Fiddaman 				vp->u_column = i;
910*b30d1939SAndy Fiddaman 			}
911*b30d1939SAndy Fiddaman 
912*b30d1939SAndy Fiddaman 			curhline -= vp->repeat;
913*b30d1939SAndy Fiddaman 			if( curhline <= histmin )
914*b30d1939SAndy Fiddaman 			{
915*b30d1939SAndy Fiddaman 				curhline += vp->repeat;
916*b30d1939SAndy Fiddaman 				goto ringbell;
917*b30d1939SAndy Fiddaman 			}
918*b30d1939SAndy Fiddaman 			save_v(vp);
919*b30d1939SAndy Fiddaman 			cur_virt = INVALID;
920*b30d1939SAndy Fiddaman 		newhist:
921*b30d1939SAndy Fiddaman 			if(curhline!=histmax || cur_virt==INVALID)
922*b30d1939SAndy Fiddaman 				hist_copy((char*)virtual, MAXLINE, curhline,-1);
923*b30d1939SAndy Fiddaman 			else
924*b30d1939SAndy Fiddaman 			{
925*b30d1939SAndy Fiddaman 				strcpy((char*)virtual,(char*)vp->u_space);
926*b30d1939SAndy Fiddaman #if SHOPT_MULTIBYTE
927*b30d1939SAndy Fiddaman 				ed_internal((char*)vp->u_space,vp->u_space);
928*b30d1939SAndy Fiddaman #endif /* SHOPT_MULTIBYTE */
929*b30d1939SAndy Fiddaman 			}
930*b30d1939SAndy Fiddaman #if SHOPT_MULTIBYTE
931*b30d1939SAndy Fiddaman 			ed_internal((char*)virtual,virtual);
932*b30d1939SAndy Fiddaman #endif /* SHOPT_MULTIBYTE */
933*b30d1939SAndy Fiddaman 			if((last_virt=genlen(virtual)-1) >= 0  && cur_virt == INVALID)
934*b30d1939SAndy Fiddaman 				cur_virt = 0;
935*b30d1939SAndy Fiddaman #if SHOPT_EDPREDICT
936*b30d1939SAndy Fiddaman 			if(vp->ed->hlist)
937*b30d1939SAndy Fiddaman 			{
938*b30d1939SAndy Fiddaman 				ed_histlist(vp->ed,0);
939*b30d1939SAndy Fiddaman 				if(c=='\n')
940*b30d1939SAndy Fiddaman 					ed_ungetchar(vp->ed,c);
941*b30d1939SAndy Fiddaman 				ed_ungetchar(vp->ed,cntl('L'));
942*b30d1939SAndy Fiddaman 				vp->nonewline = 1;
943*b30d1939SAndy Fiddaman 				cur_virt = 0;
944*b30d1939SAndy Fiddaman 			}
945*b30d1939SAndy Fiddaman #endif /*SHOPT_EDPREDICT */
946*b30d1939SAndy Fiddaman 			break;
947*b30d1939SAndy Fiddaman 
948*b30d1939SAndy Fiddaman 
949*b30d1939SAndy Fiddaman 		case 'u':		/** undo the last thing done **/
950*b30d1939SAndy Fiddaman 			restore_v(vp);
951*b30d1939SAndy Fiddaman 			break;
952*b30d1939SAndy Fiddaman 
953*b30d1939SAndy Fiddaman 		case 'U':		/** Undo everything **/
954*b30d1939SAndy Fiddaman 			save_v(vp);
955*b30d1939SAndy Fiddaman 			if( virtual[0] == '\0' )
956*b30d1939SAndy Fiddaman 				goto ringbell;
957*b30d1939SAndy Fiddaman 			else
958*b30d1939SAndy Fiddaman 			{
959*b30d1939SAndy Fiddaman 				gencpy(virtual, vp->U_space);
960*b30d1939SAndy Fiddaman 				last_virt = genlen(vp->U_space) - 1;
961*b30d1939SAndy Fiddaman 				cur_virt = 0;
962*b30d1939SAndy Fiddaman 			}
963*b30d1939SAndy Fiddaman 			break;
964*b30d1939SAndy Fiddaman 
965*b30d1939SAndy Fiddaman #if KSHELL
966*b30d1939SAndy Fiddaman 		case 'v':
967*b30d1939SAndy Fiddaman 			if(vp->repeat_set==0)
968*b30d1939SAndy Fiddaman 				goto vcommand;
969*b30d1939SAndy Fiddaman #endif /* KSHELL */
970*b30d1939SAndy Fiddaman 			/* FALLTHROUGH */
971*b30d1939SAndy Fiddaman 
972*b30d1939SAndy Fiddaman 		case 'G':		/** goto command repeat **/
973*b30d1939SAndy Fiddaman 			if(vp->repeat_set==0)
974*b30d1939SAndy Fiddaman 				vp->repeat = histmin+1;
975*b30d1939SAndy Fiddaman 			if( vp->repeat <= histmin || vp->repeat > histmax )
976*b30d1939SAndy Fiddaman 			{
977*b30d1939SAndy Fiddaman 				goto ringbell;
978*b30d1939SAndy Fiddaman 			}
979*b30d1939SAndy Fiddaman 			curhline = vp->repeat;
980*b30d1939SAndy Fiddaman 			save_v(vp);
981*b30d1939SAndy Fiddaman 			if(c == 'G')
982*b30d1939SAndy Fiddaman 			{
983*b30d1939SAndy Fiddaman 				cur_virt = INVALID;
984*b30d1939SAndy Fiddaman 				goto newhist;
985*b30d1939SAndy Fiddaman 			}
986*b30d1939SAndy Fiddaman 
987*b30d1939SAndy Fiddaman #if KSHELL
988*b30d1939SAndy Fiddaman 		vcommand:
989*b30d1939SAndy Fiddaman 			if(ed_fulledit(vp->ed)==GOOD)
990*b30d1939SAndy Fiddaman 				return(BIGVI);
991*b30d1939SAndy Fiddaman 			else
992*b30d1939SAndy Fiddaman 				goto ringbell;
993*b30d1939SAndy Fiddaman #endif	/* KSHELL */
994*b30d1939SAndy Fiddaman 
995*b30d1939SAndy Fiddaman 		case '#':	/** insert(delete) # to (no)comment command **/
996*b30d1939SAndy Fiddaman 			if( cur_virt != INVALID )
997*b30d1939SAndy Fiddaman 			{
998*b30d1939SAndy Fiddaman 				register genchar *p = &virtual[last_virt+1];
999*b30d1939SAndy Fiddaman 				*p = 0;
1000*b30d1939SAndy Fiddaman 				/*** see whether first char is comment char ***/
1001*b30d1939SAndy Fiddaman 				c = (virtual[0]=='#');
1002*b30d1939SAndy Fiddaman 				while(p-- >= virtual)
1003*b30d1939SAndy Fiddaman 				{
1004*b30d1939SAndy Fiddaman 					if(*p=='\n' || p<virtual)
1005*b30d1939SAndy Fiddaman 					{
1006*b30d1939SAndy Fiddaman 						if(c) /* delete '#' */
1007*b30d1939SAndy Fiddaman 						{
1008*b30d1939SAndy Fiddaman 							if(p[1]=='#')
1009*b30d1939SAndy Fiddaman 							{
1010*b30d1939SAndy Fiddaman 								last_virt--;
1011*b30d1939SAndy Fiddaman 								gencpy(p+1,p+2);
1012*b30d1939SAndy Fiddaman 							}
1013*b30d1939SAndy Fiddaman 						}
1014*b30d1939SAndy Fiddaman 						else
1015*b30d1939SAndy Fiddaman 						{
1016*b30d1939SAndy Fiddaman 							cur_virt = p-virtual;
1017*b30d1939SAndy Fiddaman 							append(vp,'#', APPEND);
1018*b30d1939SAndy Fiddaman 						}
1019*b30d1939SAndy Fiddaman 					}
1020*b30d1939SAndy Fiddaman 				}
1021*b30d1939SAndy Fiddaman 				if(c)
1022*b30d1939SAndy Fiddaman 				{
1023*b30d1939SAndy Fiddaman 					curhline = histmax;
1024*b30d1939SAndy Fiddaman 					cur_virt = 0;
1025*b30d1939SAndy Fiddaman 					break;
1026*b30d1939SAndy Fiddaman 				}
1027*b30d1939SAndy Fiddaman 				refresh(vp,INPUT);
1028*b30d1939SAndy Fiddaman 			}
1029*b30d1939SAndy Fiddaman 			/* FALLTHROUGH */
1030*b30d1939SAndy Fiddaman 
1031*b30d1939SAndy Fiddaman 		case '\n':		/** send to shell **/
1032*b30d1939SAndy Fiddaman #if SHOPT_EDPREDICT
1033*b30d1939SAndy Fiddaman 			if(!vp->ed->hlist)
1034*b30d1939SAndy Fiddaman 			return(ENTER);
1035*b30d1939SAndy Fiddaman 		case '\t':		/** bring choice to edit **/
1036*b30d1939SAndy Fiddaman 			if(vp->ed->hlist)
1037*b30d1939SAndy Fiddaman 			{
1038*b30d1939SAndy Fiddaman 				if(vp->repeat > vp->ed->nhlist-vp->ed->hoff)
1039*b30d1939SAndy Fiddaman 					goto ringbell;
1040*b30d1939SAndy Fiddaman 				curhline = vp->ed->hlist[vp->repeat+vp->ed->hoff-1]->index;
1041*b30d1939SAndy Fiddaman 				goto newhist;
1042*b30d1939SAndy Fiddaman 			}
1043*b30d1939SAndy Fiddaman 			goto ringbell;
1044*b30d1939SAndy Fiddaman #else
1045*b30d1939SAndy Fiddaman 			return(ENTER);
1046*b30d1939SAndy Fiddaman #endif /* SHOPT_EDPREDICT */
1047*b30d1939SAndy Fiddaman 	        case ESC:
1048*b30d1939SAndy Fiddaman 			/* don't ring bell if next char is '[' */
1049*b30d1939SAndy Fiddaman 			if(!lookahead)
1050*b30d1939SAndy Fiddaman 			{
1051*b30d1939SAndy Fiddaman 				char x;
1052*b30d1939SAndy Fiddaman 				if(sfpkrd(editb.e_fd,&x,1,'\r',400L,-1)>0)
1053*b30d1939SAndy Fiddaman 					ed_ungetchar(vp->ed,x);
1054*b30d1939SAndy Fiddaman 			}
1055*b30d1939SAndy Fiddaman 			if(lookahead)
1056*b30d1939SAndy Fiddaman 			{
1057*b30d1939SAndy Fiddaman 				ed_ungetchar(vp->ed,c=ed_getchar(vp->ed,1));
1058*b30d1939SAndy Fiddaman 				if(c=='[')
1059*b30d1939SAndy Fiddaman 				{
1060*b30d1939SAndy Fiddaman 					vp->repeat = 1;
1061*b30d1939SAndy Fiddaman 					continue;
1062*b30d1939SAndy Fiddaman 				}
1063*b30d1939SAndy Fiddaman 			}
1064*b30d1939SAndy Fiddaman 			/* FALLTHROUGH */
1065*b30d1939SAndy Fiddaman 		default:
1066*b30d1939SAndy Fiddaman 		ringbell:
1067*b30d1939SAndy Fiddaman 			ed_ringbell();
1068*b30d1939SAndy Fiddaman 			vp->repeat = 1;
1069*b30d1939SAndy Fiddaman 			continue;
1070*b30d1939SAndy Fiddaman 		}
1071*b30d1939SAndy Fiddaman 
1072*b30d1939SAndy Fiddaman 		refresh(vp,CONTROL);
1073*b30d1939SAndy Fiddaman 		vp->repeat = 1;
1074*b30d1939SAndy Fiddaman 	}
1075*b30d1939SAndy Fiddaman /* NOTREACHED */
1076*b30d1939SAndy Fiddaman 	return(0);
1077*b30d1939SAndy Fiddaman }
1078*b30d1939SAndy Fiddaman 
1079*b30d1939SAndy Fiddaman /*{	CURSOR( new_current_physical )
1080*b30d1939SAndy Fiddaman  *
1081*b30d1939SAndy Fiddaman  *	This routine will position the virtual cursor at
1082*b30d1939SAndy Fiddaman  * physical column x in the window.
1083*b30d1939SAndy Fiddaman  *
1084*b30d1939SAndy Fiddaman }*/
1085*b30d1939SAndy Fiddaman 
cursor(Vi_t * vp,register int x)1086*b30d1939SAndy Fiddaman static void cursor(Vi_t *vp,register int x)
1087*b30d1939SAndy Fiddaman {
1088*b30d1939SAndy Fiddaman #if SHOPT_MULTIBYTE
1089*b30d1939SAndy Fiddaman 	while(physical[x]==MARKER)
1090*b30d1939SAndy Fiddaman 		x++;
1091*b30d1939SAndy Fiddaman #endif /* SHOPT_MULTIBYTE */
1092*b30d1939SAndy Fiddaman 	cur_phys = ed_setcursor(vp->ed, physical, cur_phys,x,vp->first_wind);
1093*b30d1939SAndy Fiddaman }
1094*b30d1939SAndy Fiddaman 
1095*b30d1939SAndy Fiddaman /*{	DELETE( nchars, mode )
1096*b30d1939SAndy Fiddaman  *
1097*b30d1939SAndy Fiddaman  *	Delete nchars from the virtual space and leave cur_virt positioned
1098*b30d1939SAndy Fiddaman  * at cur_virt-1.
1099*b30d1939SAndy Fiddaman  *
1100*b30d1939SAndy Fiddaman  *	If mode	= 'c', do not save the characters deleted
1101*b30d1939SAndy Fiddaman  *		= 'd', save them in yankbuf and delete.
1102*b30d1939SAndy Fiddaman  *		= 'y', save them in yankbuf but do not delete.
1103*b30d1939SAndy Fiddaman  *
1104*b30d1939SAndy Fiddaman }*/
1105*b30d1939SAndy Fiddaman 
cdelete(Vi_t * vp,register int nchars,int mode)1106*b30d1939SAndy Fiddaman static void cdelete(Vi_t *vp,register int nchars, int mode)
1107*b30d1939SAndy Fiddaman {
1108*b30d1939SAndy Fiddaman 	register int i;
1109*b30d1939SAndy Fiddaman 	register genchar *cp;
1110*b30d1939SAndy Fiddaman 
1111*b30d1939SAndy Fiddaman 	if( cur_virt < first_virt )
1112*b30d1939SAndy Fiddaman 	{
1113*b30d1939SAndy Fiddaman 		ed_ringbell();
1114*b30d1939SAndy Fiddaman 		return;
1115*b30d1939SAndy Fiddaman 	}
1116*b30d1939SAndy Fiddaman 	if( nchars > 0 )
1117*b30d1939SAndy Fiddaman 	{
1118*b30d1939SAndy Fiddaman 		cp = virtual+cur_virt;
1119*b30d1939SAndy Fiddaman 		vp->o_v_char = cp[0];
1120*b30d1939SAndy Fiddaman 		if( (cur_virt-- + nchars) > last_virt )
1121*b30d1939SAndy Fiddaman 		{
1122*b30d1939SAndy Fiddaman 			/*** set nchars to number actually deleted ***/
1123*b30d1939SAndy Fiddaman 			nchars = last_virt - cur_virt;
1124*b30d1939SAndy Fiddaman 		}
1125*b30d1939SAndy Fiddaman 
1126*b30d1939SAndy Fiddaman 		/*** save characters to be deleted ***/
1127*b30d1939SAndy Fiddaman 
1128*b30d1939SAndy Fiddaman 		if( mode != 'c' )
1129*b30d1939SAndy Fiddaman 		{
1130*b30d1939SAndy Fiddaman 			i = cp[nchars];
1131*b30d1939SAndy Fiddaman 			cp[nchars] = 0;
1132*b30d1939SAndy Fiddaman 			gencpy(yankbuf,cp);
1133*b30d1939SAndy Fiddaman 			cp[nchars] = i;
1134*b30d1939SAndy Fiddaman 		}
1135*b30d1939SAndy Fiddaman 
1136*b30d1939SAndy Fiddaman 		/*** now delete these characters ***/
1137*b30d1939SAndy Fiddaman 
1138*b30d1939SAndy Fiddaman 		if( mode != 'y' )
1139*b30d1939SAndy Fiddaman 		{
1140*b30d1939SAndy Fiddaman 			gencpy(cp,cp+nchars);
1141*b30d1939SAndy Fiddaman 			last_virt -= nchars;
1142*b30d1939SAndy Fiddaman 		}
1143*b30d1939SAndy Fiddaman 	}
1144*b30d1939SAndy Fiddaman 	return;
1145*b30d1939SAndy Fiddaman }
1146*b30d1939SAndy Fiddaman 
1147*b30d1939SAndy Fiddaman /*{	DEL_LINE( mode )
1148*b30d1939SAndy Fiddaman  *
1149*b30d1939SAndy Fiddaman  *	This routine will delete the line.
1150*b30d1939SAndy Fiddaman  *	mode = GOOD, do a save_v()
1151*b30d1939SAndy Fiddaman  *
1152*b30d1939SAndy Fiddaman }*/
del_line(register Vi_t * vp,int mode)1153*b30d1939SAndy Fiddaman static void del_line(register Vi_t *vp, int mode)
1154*b30d1939SAndy Fiddaman {
1155*b30d1939SAndy Fiddaman 	if( last_virt == INVALID )
1156*b30d1939SAndy Fiddaman 		return;
1157*b30d1939SAndy Fiddaman 
1158*b30d1939SAndy Fiddaman 	if( mode == GOOD )
1159*b30d1939SAndy Fiddaman 		save_v(vp);
1160*b30d1939SAndy Fiddaman 
1161*b30d1939SAndy Fiddaman 	cur_virt = 0;
1162*b30d1939SAndy Fiddaman 	first_virt = 0;
1163*b30d1939SAndy Fiddaman 	cdelete(vp,last_virt+1, BAD);
1164*b30d1939SAndy Fiddaman 	refresh(vp,CONTROL);
1165*b30d1939SAndy Fiddaman 
1166*b30d1939SAndy Fiddaman 	cur_virt = INVALID;
1167*b30d1939SAndy Fiddaman 	cur_phys = 0;
1168*b30d1939SAndy Fiddaman 	vp->findchar = INVALID;
1169*b30d1939SAndy Fiddaman 	last_phys = INVALID;
1170*b30d1939SAndy Fiddaman 	last_virt = INVALID;
1171*b30d1939SAndy Fiddaman 	vp->last_wind = INVALID;
1172*b30d1939SAndy Fiddaman 	vp->first_wind = 0;
1173*b30d1939SAndy Fiddaman 	vp->o_v_char = '\0';
1174*b30d1939SAndy Fiddaman 	vp->ocur_phys = 0;
1175*b30d1939SAndy Fiddaman 	vp->ocur_virt = MAXCHAR;
1176*b30d1939SAndy Fiddaman 	vp->ofirst_wind = 0;
1177*b30d1939SAndy Fiddaman 	window[0] = '\0';
1178*b30d1939SAndy Fiddaman 	return;
1179*b30d1939SAndy Fiddaman }
1180*b30d1939SAndy Fiddaman 
1181*b30d1939SAndy Fiddaman /*{	DELMOTION( motion, mode )
1182*b30d1939SAndy Fiddaman  *
1183*b30d1939SAndy Fiddaman  *	Delete thru motion.
1184*b30d1939SAndy Fiddaman  *
1185*b30d1939SAndy Fiddaman  *	mode	= 'd', save deleted characters, delete
1186*b30d1939SAndy Fiddaman  *		= 'c', do not save characters, change
1187*b30d1939SAndy Fiddaman  *		= 'y', save characters, yank
1188*b30d1939SAndy Fiddaman  *
1189*b30d1939SAndy Fiddaman  *	Returns 1 if operation successful; else 0.
1190*b30d1939SAndy Fiddaman  *
1191*b30d1939SAndy Fiddaman }*/
1192*b30d1939SAndy Fiddaman 
delmotion(Vi_t * vp,int motion,int mode)1193*b30d1939SAndy Fiddaman static int delmotion(Vi_t *vp,int motion, int mode)
1194*b30d1939SAndy Fiddaman {
1195*b30d1939SAndy Fiddaman 	register int begin, end, delta;
1196*b30d1939SAndy Fiddaman 	/* the following saves a register */
1197*b30d1939SAndy Fiddaman 
1198*b30d1939SAndy Fiddaman 	if( cur_virt == INVALID )
1199*b30d1939SAndy Fiddaman 		return(0);
1200*b30d1939SAndy Fiddaman 	if( mode != 'y' )
1201*b30d1939SAndy Fiddaman 		save_v(vp);
1202*b30d1939SAndy Fiddaman 	begin = cur_virt;
1203*b30d1939SAndy Fiddaman 
1204*b30d1939SAndy Fiddaman 	/*** fake out the motion routines by appending a blank ***/
1205*b30d1939SAndy Fiddaman 
1206*b30d1939SAndy Fiddaman 	virtual[++last_virt] = ' ';
1207*b30d1939SAndy Fiddaman 	end = mvcursor(vp,motion);
1208*b30d1939SAndy Fiddaman 	virtual[last_virt--] = 0;
1209*b30d1939SAndy Fiddaman 	if(!end)
1210*b30d1939SAndy Fiddaman 		return(0);
1211*b30d1939SAndy Fiddaman 
1212*b30d1939SAndy Fiddaman 	end = cur_virt;
1213*b30d1939SAndy Fiddaman 	if( mode=='c' && end>begin && strchr("wW", motion) )
1214*b30d1939SAndy Fiddaman 	{
1215*b30d1939SAndy Fiddaman 		/*** called by change operation, user really expects ***/
1216*b30d1939SAndy Fiddaman 		/* the effect of the eE commands, so back up to end of word */
1217*b30d1939SAndy Fiddaman 		while( end>begin && isblank(end-1) )
1218*b30d1939SAndy Fiddaman 			--end;
1219*b30d1939SAndy Fiddaman 		if( end == begin )
1220*b30d1939SAndy Fiddaman 			++end;
1221*b30d1939SAndy Fiddaman 	}
1222*b30d1939SAndy Fiddaman 
1223*b30d1939SAndy Fiddaman 	delta = end - begin;
1224*b30d1939SAndy Fiddaman 	if( delta >= 0 )
1225*b30d1939SAndy Fiddaman 	{
1226*b30d1939SAndy Fiddaman 		cur_virt = begin;
1227*b30d1939SAndy Fiddaman 		if( strchr("eE;,TtFf%", motion) )
1228*b30d1939SAndy Fiddaman 			++delta;
1229*b30d1939SAndy Fiddaman 	}
1230*b30d1939SAndy Fiddaman 	else
1231*b30d1939SAndy Fiddaman 	{
1232*b30d1939SAndy Fiddaman 		delta = -delta + (motion=='%');
1233*b30d1939SAndy Fiddaman 	}
1234*b30d1939SAndy Fiddaman 
1235*b30d1939SAndy Fiddaman 	cdelete(vp,delta, mode);
1236*b30d1939SAndy Fiddaman 	if( mode == 'y' )
1237*b30d1939SAndy Fiddaman 		cur_virt = begin;
1238*b30d1939SAndy Fiddaman 	return(1);
1239*b30d1939SAndy Fiddaman }
1240*b30d1939SAndy Fiddaman 
1241*b30d1939SAndy Fiddaman 
1242*b30d1939SAndy Fiddaman /*{	ENDWORD( nwords, cmd )
1243*b30d1939SAndy Fiddaman  *
1244*b30d1939SAndy Fiddaman  *	This routine will move cur_virt to the end of the nth word.
1245*b30d1939SAndy Fiddaman  *
1246*b30d1939SAndy Fiddaman }*/
1247*b30d1939SAndy Fiddaman 
endword(Vi_t * vp,int nwords,register int cmd)1248*b30d1939SAndy Fiddaman static void endword(Vi_t *vp, int nwords, register int cmd)
1249*b30d1939SAndy Fiddaman {
1250*b30d1939SAndy Fiddaman 	register int tcur_virt = cur_virt;
1251*b30d1939SAndy Fiddaman 	while( nwords-- )
1252*b30d1939SAndy Fiddaman 	{
1253*b30d1939SAndy Fiddaman 		if( !isblank(tcur_virt) && tcur_virt<=last_virt )
1254*b30d1939SAndy Fiddaman 			++tcur_virt;
1255*b30d1939SAndy Fiddaman 		while( isblank(tcur_virt) && tcur_virt<=last_virt )
1256*b30d1939SAndy Fiddaman 			++tcur_virt;
1257*b30d1939SAndy Fiddaman 		if( cmd == 'E' )
1258*b30d1939SAndy Fiddaman 		{
1259*b30d1939SAndy Fiddaman 			while( !isblank(tcur_virt) && tcur_virt<=last_virt )
1260*b30d1939SAndy Fiddaman 				++tcur_virt;
1261*b30d1939SAndy Fiddaman 		}
1262*b30d1939SAndy Fiddaman 		else
1263*b30d1939SAndy Fiddaman 		{
1264*b30d1939SAndy Fiddaman 			if( isalph(tcur_virt) )
1265*b30d1939SAndy Fiddaman 				while( isalph(tcur_virt) && tcur_virt<=last_virt )
1266*b30d1939SAndy Fiddaman 					++tcur_virt;
1267*b30d1939SAndy Fiddaman 			else
1268*b30d1939SAndy Fiddaman 				while( !isalph(tcur_virt) && !isblank(tcur_virt)
1269*b30d1939SAndy Fiddaman 					&& tcur_virt<=last_virt )
1270*b30d1939SAndy Fiddaman 					++tcur_virt;
1271*b30d1939SAndy Fiddaman 		}
1272*b30d1939SAndy Fiddaman 		if( tcur_virt > first_virt )
1273*b30d1939SAndy Fiddaman 			tcur_virt--;
1274*b30d1939SAndy Fiddaman 	}
1275*b30d1939SAndy Fiddaman 	cur_virt = tcur_virt;
1276*b30d1939SAndy Fiddaman 	return;
1277*b30d1939SAndy Fiddaman }
1278*b30d1939SAndy Fiddaman 
1279*b30d1939SAndy Fiddaman /*{	FORWARD( nwords, cmd )
1280*b30d1939SAndy Fiddaman  *
1281*b30d1939SAndy Fiddaman  *	This routine will move cur_virt forward to the next nth word.
1282*b30d1939SAndy Fiddaman  *
1283*b30d1939SAndy Fiddaman }*/
1284*b30d1939SAndy Fiddaman 
forward(Vi_t * vp,register int nwords,int cmd)1285*b30d1939SAndy Fiddaman static void forward(Vi_t *vp,register int nwords, int cmd)
1286*b30d1939SAndy Fiddaman {
1287*b30d1939SAndy Fiddaman 	register int tcur_virt = cur_virt;
1288*b30d1939SAndy Fiddaman 	while( nwords-- )
1289*b30d1939SAndy Fiddaman 	{
1290*b30d1939SAndy Fiddaman 		if( cmd == 'W' )
1291*b30d1939SAndy Fiddaman 		{
1292*b30d1939SAndy Fiddaman 			while( !isblank(tcur_virt) && tcur_virt < last_virt )
1293*b30d1939SAndy Fiddaman 				++tcur_virt;
1294*b30d1939SAndy Fiddaman 		}
1295*b30d1939SAndy Fiddaman 		else
1296*b30d1939SAndy Fiddaman 		{
1297*b30d1939SAndy Fiddaman 			if( isalph(tcur_virt) )
1298*b30d1939SAndy Fiddaman 			{
1299*b30d1939SAndy Fiddaman 				while( isalph(tcur_virt) && tcur_virt<last_virt )
1300*b30d1939SAndy Fiddaman 					++tcur_virt;
1301*b30d1939SAndy Fiddaman 			}
1302*b30d1939SAndy Fiddaman 			else
1303*b30d1939SAndy Fiddaman 			{
1304*b30d1939SAndy Fiddaman 				while( !isalph(tcur_virt) && !isblank(tcur_virt)
1305*b30d1939SAndy Fiddaman 					&& tcur_virt < last_virt )
1306*b30d1939SAndy Fiddaman 					++tcur_virt;
1307*b30d1939SAndy Fiddaman 			}
1308*b30d1939SAndy Fiddaman 		}
1309*b30d1939SAndy Fiddaman 		while( isblank(tcur_virt) && tcur_virt < last_virt )
1310*b30d1939SAndy Fiddaman 			++tcur_virt;
1311*b30d1939SAndy Fiddaman 	}
1312*b30d1939SAndy Fiddaman 	cur_virt = tcur_virt;
1313*b30d1939SAndy Fiddaman 	return;
1314*b30d1939SAndy Fiddaman }
1315*b30d1939SAndy Fiddaman 
1316*b30d1939SAndy Fiddaman 
1317*b30d1939SAndy Fiddaman 
1318*b30d1939SAndy Fiddaman /*{	GETCOUNT(c)
1319*b30d1939SAndy Fiddaman  *
1320*b30d1939SAndy Fiddaman  *	Set repeat to the user typed number and return the terminating
1321*b30d1939SAndy Fiddaman  * character.
1322*b30d1939SAndy Fiddaman  *
1323*b30d1939SAndy Fiddaman }*/
1324*b30d1939SAndy Fiddaman 
getcount(register Vi_t * vp,register int c)1325*b30d1939SAndy Fiddaman static int getcount(register Vi_t *vp,register int c)
1326*b30d1939SAndy Fiddaman {
1327*b30d1939SAndy Fiddaman 	register int i;
1328*b30d1939SAndy Fiddaman 
1329*b30d1939SAndy Fiddaman 	/*** get any repeat count ***/
1330*b30d1939SAndy Fiddaman 
1331*b30d1939SAndy Fiddaman 	if( c == '0' )
1332*b30d1939SAndy Fiddaman 		return(c);
1333*b30d1939SAndy Fiddaman 
1334*b30d1939SAndy Fiddaman 	vp->repeat_set++;
1335*b30d1939SAndy Fiddaman 	i = 0;
1336*b30d1939SAndy Fiddaman 	while( digit(c) )
1337*b30d1939SAndy Fiddaman 	{
1338*b30d1939SAndy Fiddaman 		i = i*10 + c - '0';
1339*b30d1939SAndy Fiddaman 		c = ed_getchar(vp->ed,-1);
1340*b30d1939SAndy Fiddaman 	}
1341*b30d1939SAndy Fiddaman 
1342*b30d1939SAndy Fiddaman 	if( i > 0 )
1343*b30d1939SAndy Fiddaman 		vp->repeat *= i;
1344*b30d1939SAndy Fiddaman 	return(c);
1345*b30d1939SAndy Fiddaman }
1346*b30d1939SAndy Fiddaman 
1347*b30d1939SAndy Fiddaman 
1348*b30d1939SAndy Fiddaman /*{	GETLINE( mode )
1349*b30d1939SAndy Fiddaman  *
1350*b30d1939SAndy Fiddaman  *	This routine will fetch a line.
1351*b30d1939SAndy Fiddaman  *	mode	= APPEND, allow escape to cntlmode subroutine
1352*b30d1939SAndy Fiddaman  *		  appending characters.
1353*b30d1939SAndy Fiddaman  *		= REPLACE, allow escape to cntlmode subroutine
1354*b30d1939SAndy Fiddaman  *		  replacing characters.
1355*b30d1939SAndy Fiddaman  *		= SEARCH, no escape allowed
1356*b30d1939SAndy Fiddaman  *		= ESC, enter control mode immediately
1357*b30d1939SAndy Fiddaman  *
1358*b30d1939SAndy Fiddaman  *	The cursor will always be positioned after the last
1359*b30d1939SAndy Fiddaman  * char printed.
1360*b30d1939SAndy Fiddaman  *
1361*b30d1939SAndy Fiddaman  *	This routine returns when cr, nl, or (eof in column 0) is
1362*b30d1939SAndy Fiddaman  * received (column 0 is the first char position).
1363*b30d1939SAndy Fiddaman  *
1364*b30d1939SAndy Fiddaman }*/
1365*b30d1939SAndy Fiddaman 
getline(register Vi_t * vp,register int mode)1366*b30d1939SAndy Fiddaman static void getline(register Vi_t* vp,register int mode)
1367*b30d1939SAndy Fiddaman {
1368*b30d1939SAndy Fiddaman 	register int c;
1369*b30d1939SAndy Fiddaman 	register int tmp;
1370*b30d1939SAndy Fiddaman 	int	max_virt=0, last_save=0;
1371*b30d1939SAndy Fiddaman 	genchar saveline[MAXLINE];
1372*b30d1939SAndy Fiddaman 	vp->addnl = 1;
1373*b30d1939SAndy Fiddaman 
1374*b30d1939SAndy Fiddaman 	if( mode == ESC )
1375*b30d1939SAndy Fiddaman 	{
1376*b30d1939SAndy Fiddaman 		/*** go directly to control mode ***/
1377*b30d1939SAndy Fiddaman 		goto escape;
1378*b30d1939SAndy Fiddaman 	}
1379*b30d1939SAndy Fiddaman 
1380*b30d1939SAndy Fiddaman 	for(;;)
1381*b30d1939SAndy Fiddaman 	{
1382*b30d1939SAndy Fiddaman 		if( (c=ed_getchar(vp->ed,mode==SEARCH?1:-2)) == usreof )
1383*b30d1939SAndy Fiddaman 			c = UEOF;
1384*b30d1939SAndy Fiddaman 		else if( c == usrerase )
1385*b30d1939SAndy Fiddaman 			c = UERASE;
1386*b30d1939SAndy Fiddaman 		else if( c == usrkill )
1387*b30d1939SAndy Fiddaman 			c = UKILL;
1388*b30d1939SAndy Fiddaman 		else if( c == editb.e_werase )
1389*b30d1939SAndy Fiddaman 			c = UWERASE;
1390*b30d1939SAndy Fiddaman 		else if( c == usrlnext )
1391*b30d1939SAndy Fiddaman 			c = ULNEXT;
1392*b30d1939SAndy Fiddaman 		else if(mode==SEARCH && c==editb.e_intr)
1393*b30d1939SAndy Fiddaman 			c = UINTR;
1394*b30d1939SAndy Fiddaman 
1395*b30d1939SAndy Fiddaman 		if( c == ULNEXT)
1396*b30d1939SAndy Fiddaman 		{
1397*b30d1939SAndy Fiddaman 			/*** implement ^V to escape next char ***/
1398*b30d1939SAndy Fiddaman 			c = ed_getchar(vp->ed,2);
1399*b30d1939SAndy Fiddaman 			append(vp,c, mode);
1400*b30d1939SAndy Fiddaman 			refresh(vp,INPUT);
1401*b30d1939SAndy Fiddaman 			continue;
1402*b30d1939SAndy Fiddaman 		}
1403*b30d1939SAndy Fiddaman 		if(c!='\t')
1404*b30d1939SAndy Fiddaman 			vp->ed->e_tabcount = 0;
1405*b30d1939SAndy Fiddaman 
1406*b30d1939SAndy Fiddaman 		switch( c )
1407*b30d1939SAndy Fiddaman 		{
1408*b30d1939SAndy Fiddaman 		case ESC:		/** enter control mode **/
1409*b30d1939SAndy Fiddaman 			if(!sh_isoption(SH_VI))
1410*b30d1939SAndy Fiddaman 			{
1411*b30d1939SAndy Fiddaman 				append(vp,c, mode);
1412*b30d1939SAndy Fiddaman 				break;
1413*b30d1939SAndy Fiddaman 			}
1414*b30d1939SAndy Fiddaman 			if( mode == SEARCH )
1415*b30d1939SAndy Fiddaman 			{
1416*b30d1939SAndy Fiddaman 				ed_ringbell();
1417*b30d1939SAndy Fiddaman 				continue;
1418*b30d1939SAndy Fiddaman 			}
1419*b30d1939SAndy Fiddaman 			else
1420*b30d1939SAndy Fiddaman 			{
1421*b30d1939SAndy Fiddaman 	escape:
1422*b30d1939SAndy Fiddaman 				if( mode == REPLACE )
1423*b30d1939SAndy Fiddaman 				{
1424*b30d1939SAndy Fiddaman 					c = max_virt-cur_virt;
1425*b30d1939SAndy Fiddaman 					if(c > 0 && last_save>=cur_virt)
1426*b30d1939SAndy Fiddaman 					{
1427*b30d1939SAndy Fiddaman 						genncpy((&virtual[cur_virt]),&saveline[cur_virt],c);
1428*b30d1939SAndy Fiddaman 						if(last_virt>=last_save)
1429*b30d1939SAndy Fiddaman 							last_virt=last_save-1;
1430*b30d1939SAndy Fiddaman 						refresh(vp,INPUT);
1431*b30d1939SAndy Fiddaman 					}
1432*b30d1939SAndy Fiddaman 					--cur_virt;
1433*b30d1939SAndy Fiddaman 				}
1434*b30d1939SAndy Fiddaman 				tmp = cntlmode(vp);
1435*b30d1939SAndy Fiddaman 				if( tmp == ENTER || tmp == BIGVI )
1436*b30d1939SAndy Fiddaman 				{
1437*b30d1939SAndy Fiddaman #if SHOPT_MULTIBYTE
1438*b30d1939SAndy Fiddaman 					vp->bigvi = (tmp==BIGVI);
1439*b30d1939SAndy Fiddaman #endif /* SHOPT_MULTIBYTE */
1440*b30d1939SAndy Fiddaman 					return;
1441*b30d1939SAndy Fiddaman 				}
1442*b30d1939SAndy Fiddaman 				if( tmp == INSERT )
1443*b30d1939SAndy Fiddaman 				{
1444*b30d1939SAndy Fiddaman 					mode = APPEND;
1445*b30d1939SAndy Fiddaman 					continue;
1446*b30d1939SAndy Fiddaman 				}
1447*b30d1939SAndy Fiddaman 				mode = tmp;
1448*b30d1939SAndy Fiddaman 				if(mode==REPLACE)
1449*b30d1939SAndy Fiddaman 				{
1450*b30d1939SAndy Fiddaman 					c = last_save = last_virt+1;
1451*b30d1939SAndy Fiddaman 					if(c >= MAXLINE)
1452*b30d1939SAndy Fiddaman 						c = MAXLINE-1;
1453*b30d1939SAndy Fiddaman 					genncpy(saveline, virtual, c);
1454*b30d1939SAndy Fiddaman 				}
1455*b30d1939SAndy Fiddaman 			}
1456*b30d1939SAndy Fiddaman 			break;
1457*b30d1939SAndy Fiddaman 
1458*b30d1939SAndy Fiddaman 		case UINTR:
1459*b30d1939SAndy Fiddaman 				first_virt = 0;
1460*b30d1939SAndy Fiddaman 				cdelete(vp,cur_virt+1, BAD);
1461*b30d1939SAndy Fiddaman 				cur_virt = -1;
1462*b30d1939SAndy Fiddaman 				return;
1463*b30d1939SAndy Fiddaman 		case UERASE:		/** user erase char **/
1464*b30d1939SAndy Fiddaman 				/*** treat as backspace ***/
1465*b30d1939SAndy Fiddaman 
1466*b30d1939SAndy Fiddaman 		case '\b':		/** backspace **/
1467*b30d1939SAndy Fiddaman 			if( virtual[cur_virt] == '\\' )
1468*b30d1939SAndy Fiddaman 			{
1469*b30d1939SAndy Fiddaman 				cdelete(vp,1, BAD);
1470*b30d1939SAndy Fiddaman 				append(vp,usrerase, mode);
1471*b30d1939SAndy Fiddaman 			}
1472*b30d1939SAndy Fiddaman 			else
1473*b30d1939SAndy Fiddaman 			{
1474*b30d1939SAndy Fiddaman 				if( mode==SEARCH && cur_virt==0 )
1475*b30d1939SAndy Fiddaman 				{
1476*b30d1939SAndy Fiddaman 					first_virt = 0;
1477*b30d1939SAndy Fiddaman 					cdelete(vp,1, BAD);
1478*b30d1939SAndy Fiddaman 					return;
1479*b30d1939SAndy Fiddaman 				}
1480*b30d1939SAndy Fiddaman 				if(mode==REPLACE || (last_save>0 && last_virt<=last_save))
1481*b30d1939SAndy Fiddaman 				{
1482*b30d1939SAndy Fiddaman 					if(cur_virt<=first_virt)
1483*b30d1939SAndy Fiddaman 						ed_ringbell();
1484*b30d1939SAndy Fiddaman 					else if(mode==REPLACE)
1485*b30d1939SAndy Fiddaman 						--cur_virt;
1486*b30d1939SAndy Fiddaman 					mode = REPLACE;
1487*b30d1939SAndy Fiddaman 					sync_cursor(vp);
1488*b30d1939SAndy Fiddaman 					continue;
1489*b30d1939SAndy Fiddaman 				}
1490*b30d1939SAndy Fiddaman 				else
1491*b30d1939SAndy Fiddaman 					cdelete(vp,1, BAD);
1492*b30d1939SAndy Fiddaman 			}
1493*b30d1939SAndy Fiddaman 			break;
1494*b30d1939SAndy Fiddaman 
1495*b30d1939SAndy Fiddaman 		case UWERASE:		/** delete back word **/
1496*b30d1939SAndy Fiddaman 			if( cur_virt > first_virt &&
1497*b30d1939SAndy Fiddaman 				!isblank(cur_virt) &&
1498*b30d1939SAndy Fiddaman 				!ispunct(virtual[cur_virt]) &&
1499*b30d1939SAndy Fiddaman 				isblank(cur_virt-1) )
1500*b30d1939SAndy Fiddaman 			{
1501*b30d1939SAndy Fiddaman 				cdelete(vp,1, BAD);
1502*b30d1939SAndy Fiddaman 			}
1503*b30d1939SAndy Fiddaman 			else
1504*b30d1939SAndy Fiddaman 			{
1505*b30d1939SAndy Fiddaman 				tmp = cur_virt;
1506*b30d1939SAndy Fiddaman 				backword(vp,1, 'W');
1507*b30d1939SAndy Fiddaman 				cdelete(vp,tmp - cur_virt + 1, BAD);
1508*b30d1939SAndy Fiddaman 			}
1509*b30d1939SAndy Fiddaman 			break;
1510*b30d1939SAndy Fiddaman 
1511*b30d1939SAndy Fiddaman 		case UKILL:		/** user kill line char **/
1512*b30d1939SAndy Fiddaman 			if( virtual[cur_virt] == '\\' )
1513*b30d1939SAndy Fiddaman 			{
1514*b30d1939SAndy Fiddaman 				cdelete(vp,1, BAD);
1515*b30d1939SAndy Fiddaman 				append(vp,usrkill, mode);
1516*b30d1939SAndy Fiddaman 			}
1517*b30d1939SAndy Fiddaman 			else
1518*b30d1939SAndy Fiddaman 			{
1519*b30d1939SAndy Fiddaman 				if( mode == SEARCH )
1520*b30d1939SAndy Fiddaman 				{
1521*b30d1939SAndy Fiddaman 					cur_virt = 1;
1522*b30d1939SAndy Fiddaman 					delmotion(vp, '$', BAD);
1523*b30d1939SAndy Fiddaman 				}
1524*b30d1939SAndy Fiddaman 				else if(first_virt)
1525*b30d1939SAndy Fiddaman 				{
1526*b30d1939SAndy Fiddaman 					tmp = cur_virt;
1527*b30d1939SAndy Fiddaman 					cur_virt = first_virt;
1528*b30d1939SAndy Fiddaman 					cdelete(vp,tmp - cur_virt + 1, BAD);
1529*b30d1939SAndy Fiddaman 				}
1530*b30d1939SAndy Fiddaman 				else
1531*b30d1939SAndy Fiddaman 					del_line(vp,GOOD);
1532*b30d1939SAndy Fiddaman 			}
1533*b30d1939SAndy Fiddaman 			break;
1534*b30d1939SAndy Fiddaman 
1535*b30d1939SAndy Fiddaman 		case UEOF:		/** eof char **/
1536*b30d1939SAndy Fiddaman 			if( cur_virt != INVALID )
1537*b30d1939SAndy Fiddaman 				continue;
1538*b30d1939SAndy Fiddaman 			vp->addnl = 0;
1539*b30d1939SAndy Fiddaman 			/* FALLTHROUGH */
1540*b30d1939SAndy Fiddaman 
1541*b30d1939SAndy Fiddaman 		case '\n':		/** newline or return **/
1542*b30d1939SAndy Fiddaman 			if( mode != SEARCH )
1543*b30d1939SAndy Fiddaman 				save_last(vp);
1544*b30d1939SAndy Fiddaman 			refresh(vp,INPUT);
1545*b30d1939SAndy Fiddaman 			physical[++last_phys] = 0;
1546*b30d1939SAndy Fiddaman 			return;
1547*b30d1939SAndy Fiddaman 
1548*b30d1939SAndy Fiddaman 		case '\t':		/** command completion **/
1549*b30d1939SAndy Fiddaman 			if(mode!=SEARCH && last_virt>=0 && (vp->ed->e_tabcount|| !isblank(cur_virt)) && vp->ed->sh->nextprompt)
1550*b30d1939SAndy Fiddaman 			{
1551*b30d1939SAndy Fiddaman 				if(virtual[cur_virt]=='\\')
1552*b30d1939SAndy Fiddaman 				{
1553*b30d1939SAndy Fiddaman 					virtual[cur_virt] = '\t';
1554*b30d1939SAndy Fiddaman 					break;
1555*b30d1939SAndy Fiddaman 				}
1556*b30d1939SAndy Fiddaman 				if(vp->ed->e_tabcount==0)
1557*b30d1939SAndy Fiddaman 				{
1558*b30d1939SAndy Fiddaman 					ed_ungetchar(vp->ed,'\\');
1559*b30d1939SAndy Fiddaman 					vp->ed->e_tabcount=1;
1560*b30d1939SAndy Fiddaman 					goto escape;
1561*b30d1939SAndy Fiddaman 				}
1562*b30d1939SAndy Fiddaman 				else if(vp->ed->e_tabcount==1)
1563*b30d1939SAndy Fiddaman 				{
1564*b30d1939SAndy Fiddaman 					ed_ungetchar(vp->ed,'=');
1565*b30d1939SAndy Fiddaman 					goto escape;
1566*b30d1939SAndy Fiddaman 				}
1567*b30d1939SAndy Fiddaman 				vp->ed->e_tabcount = 0;
1568*b30d1939SAndy Fiddaman 			}
1569*b30d1939SAndy Fiddaman 			/* FALL THRU*/
1570*b30d1939SAndy Fiddaman 		default:
1571*b30d1939SAndy Fiddaman 			if( mode == REPLACE )
1572*b30d1939SAndy Fiddaman 			{
1573*b30d1939SAndy Fiddaman 				if( cur_virt < last_virt )
1574*b30d1939SAndy Fiddaman 				{
1575*b30d1939SAndy Fiddaman 					replace(vp,c, 1);
1576*b30d1939SAndy Fiddaman 					if(cur_virt>max_virt)
1577*b30d1939SAndy Fiddaman 						max_virt = cur_virt;
1578*b30d1939SAndy Fiddaman 					continue;
1579*b30d1939SAndy Fiddaman 				}
1580*b30d1939SAndy Fiddaman 				cdelete(vp,1, BAD);
1581*b30d1939SAndy Fiddaman 				mode = APPEND;
1582*b30d1939SAndy Fiddaman 				max_virt = last_virt+3;
1583*b30d1939SAndy Fiddaman 			}
1584*b30d1939SAndy Fiddaman 			append(vp,c, mode);
1585*b30d1939SAndy Fiddaman 			break;
1586*b30d1939SAndy Fiddaman 		}
1587*b30d1939SAndy Fiddaman 		refresh(vp,INPUT);
1588*b30d1939SAndy Fiddaman 
1589*b30d1939SAndy Fiddaman 	}
1590*b30d1939SAndy Fiddaman }
1591*b30d1939SAndy Fiddaman 
1592*b30d1939SAndy Fiddaman /*{	MVCURSOR( motion )
1593*b30d1939SAndy Fiddaman  *
1594*b30d1939SAndy Fiddaman  *	This routine will move the virtual cursor according to motion
1595*b30d1939SAndy Fiddaman  * for repeat times.
1596*b30d1939SAndy Fiddaman  *
1597*b30d1939SAndy Fiddaman  * It returns GOOD if successful; else BAD.
1598*b30d1939SAndy Fiddaman  *
1599*b30d1939SAndy Fiddaman }*/
1600*b30d1939SAndy Fiddaman 
mvcursor(register Vi_t * vp,register int motion)1601*b30d1939SAndy Fiddaman static int mvcursor(register Vi_t* vp,register int motion)
1602*b30d1939SAndy Fiddaman {
1603*b30d1939SAndy Fiddaman 	register int count;
1604*b30d1939SAndy Fiddaman 	register int tcur_virt;
1605*b30d1939SAndy Fiddaman 	register int incr = -1;
1606*b30d1939SAndy Fiddaman 	register int bound = 0;
1607*b30d1939SAndy Fiddaman 
1608*b30d1939SAndy Fiddaman 	switch(motion)
1609*b30d1939SAndy Fiddaman 	{
1610*b30d1939SAndy Fiddaman 		/***** Cursor move commands *****/
1611*b30d1939SAndy Fiddaman 
1612*b30d1939SAndy Fiddaman 	case '0':		/** First column **/
1613*b30d1939SAndy Fiddaman 		tcur_virt = 0;
1614*b30d1939SAndy Fiddaman 		break;
1615*b30d1939SAndy Fiddaman 
1616*b30d1939SAndy Fiddaman 	case '^':		/** First nonblank character **/
1617*b30d1939SAndy Fiddaman 		tcur_virt = first_virt;
1618*b30d1939SAndy Fiddaman 		while( isblank(tcur_virt) && tcur_virt < last_virt )
1619*b30d1939SAndy Fiddaman 			++tcur_virt;
1620*b30d1939SAndy Fiddaman 		break;
1621*b30d1939SAndy Fiddaman 
1622*b30d1939SAndy Fiddaman 	case '|':
1623*b30d1939SAndy Fiddaman 		tcur_virt = vp->repeat-1;
1624*b30d1939SAndy Fiddaman 		if(tcur_virt <= last_virt)
1625*b30d1939SAndy Fiddaman 			break;
1626*b30d1939SAndy Fiddaman 		/* fall through */
1627*b30d1939SAndy Fiddaman 
1628*b30d1939SAndy Fiddaman 	case '$':		/** End of line **/
1629*b30d1939SAndy Fiddaman 		tcur_virt = last_virt;
1630*b30d1939SAndy Fiddaman 		break;
1631*b30d1939SAndy Fiddaman 
1632*b30d1939SAndy Fiddaman 	case '[':
1633*b30d1939SAndy Fiddaman 		switch(motion=getcount(vp,ed_getchar(vp->ed,-1)))
1634*b30d1939SAndy Fiddaman 		{
1635*b30d1939SAndy Fiddaman 		    case 'A':
1636*b30d1939SAndy Fiddaman #if SHOPT_EDPREDICT
1637*b30d1939SAndy Fiddaman 			if(!vp->ed->hlist && cur_virt>=0  && cur_virt<(SEARCHSIZE-2) && cur_virt == last_virt)
1638*b30d1939SAndy Fiddaman #else
1639*b30d1939SAndy Fiddaman 			if(cur_virt>=0  && cur_virt<(SEARCHSIZE-2) && cur_virt == last_virt)
1640*b30d1939SAndy Fiddaman #endif /* SHOPT_EDPREDICT */
1641*b30d1939SAndy Fiddaman 			{
1642*b30d1939SAndy Fiddaman 				virtual[last_virt + 1] = '\0';
1643*b30d1939SAndy Fiddaman #if SHOPT_MULTIBYTE
1644*b30d1939SAndy Fiddaman 				ed_external(virtual,lsearch+1);
1645*b30d1939SAndy Fiddaman #else
1646*b30d1939SAndy Fiddaman 				strcpy(lsearch+1,virtual);
1647*b30d1939SAndy Fiddaman #endif /* SHOPT_MULTIBYTE */
1648*b30d1939SAndy Fiddaman 				*lsearch = '^';
1649*b30d1939SAndy Fiddaman 				vp->direction = -2;
1650*b30d1939SAndy Fiddaman 				ed_ungetchar(vp->ed,'n');
1651*b30d1939SAndy Fiddaman 			}
1652*b30d1939SAndy Fiddaman 			else if(cur_virt==0 && vp->direction == -2)
1653*b30d1939SAndy Fiddaman 				ed_ungetchar(vp->ed,'n');
1654*b30d1939SAndy Fiddaman 			else
1655*b30d1939SAndy Fiddaman 				ed_ungetchar(vp->ed,'k');
1656*b30d1939SAndy Fiddaman 			return(1);
1657*b30d1939SAndy Fiddaman 		    case 'B':
1658*b30d1939SAndy Fiddaman 			ed_ungetchar(vp->ed,'j');
1659*b30d1939SAndy Fiddaman 			return(1);
1660*b30d1939SAndy Fiddaman 		    case 'C':
1661*b30d1939SAndy Fiddaman 			motion = last_virt;
1662*b30d1939SAndy Fiddaman 			incr = 1;
1663*b30d1939SAndy Fiddaman 			goto walk;
1664*b30d1939SAndy Fiddaman 		    case 'D':
1665*b30d1939SAndy Fiddaman 			motion = first_virt;
1666*b30d1939SAndy Fiddaman 			goto walk;
1667*b30d1939SAndy Fiddaman 		    case 'H':
1668*b30d1939SAndy Fiddaman 			tcur_virt = 0;
1669*b30d1939SAndy Fiddaman 			break;
1670*b30d1939SAndy Fiddaman 		    case 'Y':
1671*b30d1939SAndy Fiddaman 			tcur_virt = last_virt;
1672*b30d1939SAndy Fiddaman 			break;
1673*b30d1939SAndy Fiddaman 		    default:
1674*b30d1939SAndy Fiddaman 			ed_ungetchar(vp->ed,motion);
1675*b30d1939SAndy Fiddaman 			return(0);
1676*b30d1939SAndy Fiddaman 		}
1677*b30d1939SAndy Fiddaman 		break;
1678*b30d1939SAndy Fiddaman 
1679*b30d1939SAndy Fiddaman 	case 'h':		/** Left one **/
1680*b30d1939SAndy Fiddaman 	case '\b':
1681*b30d1939SAndy Fiddaman 		motion = first_virt;
1682*b30d1939SAndy Fiddaman 		goto walk;
1683*b30d1939SAndy Fiddaman 
1684*b30d1939SAndy Fiddaman 	case ' ':
1685*b30d1939SAndy Fiddaman 	case 'l':		/** Right one **/
1686*b30d1939SAndy Fiddaman 		motion = last_virt;
1687*b30d1939SAndy Fiddaman 		incr = 1;
1688*b30d1939SAndy Fiddaman 	walk:
1689*b30d1939SAndy Fiddaman 		tcur_virt = cur_virt;
1690*b30d1939SAndy Fiddaman 		if( incr*tcur_virt < motion)
1691*b30d1939SAndy Fiddaman 		{
1692*b30d1939SAndy Fiddaman 			tcur_virt += vp->repeat*incr;
1693*b30d1939SAndy Fiddaman 			if( incr*tcur_virt > motion)
1694*b30d1939SAndy Fiddaman 				tcur_virt = motion;
1695*b30d1939SAndy Fiddaman 		}
1696*b30d1939SAndy Fiddaman 		else
1697*b30d1939SAndy Fiddaman 			return(0);
1698*b30d1939SAndy Fiddaman 		break;
1699*b30d1939SAndy Fiddaman 
1700*b30d1939SAndy Fiddaman 	case 'B':
1701*b30d1939SAndy Fiddaman 	case 'b':		/** back word **/
1702*b30d1939SAndy Fiddaman 		tcur_virt = cur_virt;
1703*b30d1939SAndy Fiddaman 		backword(vp,vp->repeat, motion);
1704*b30d1939SAndy Fiddaman 		if( cur_virt == tcur_virt )
1705*b30d1939SAndy Fiddaman 			return(0);
1706*b30d1939SAndy Fiddaman 		return(1);
1707*b30d1939SAndy Fiddaman 
1708*b30d1939SAndy Fiddaman 	case 'E':
1709*b30d1939SAndy Fiddaman 	case 'e':		/** end of word **/
1710*b30d1939SAndy Fiddaman 		tcur_virt = cur_virt;
1711*b30d1939SAndy Fiddaman 		if(tcur_virt >=0)
1712*b30d1939SAndy Fiddaman 			endword(vp, vp->repeat, motion);
1713*b30d1939SAndy Fiddaman 		if( cur_virt == tcur_virt )
1714*b30d1939SAndy Fiddaman 			return(0);
1715*b30d1939SAndy Fiddaman 		return(1);
1716*b30d1939SAndy Fiddaman 
1717*b30d1939SAndy Fiddaman 	case ',':		/** reverse find old char **/
1718*b30d1939SAndy Fiddaman 	case ';':		/** find old char **/
1719*b30d1939SAndy Fiddaman 		switch(vp->last_find)
1720*b30d1939SAndy Fiddaman 		{
1721*b30d1939SAndy Fiddaman 		case 't':
1722*b30d1939SAndy Fiddaman 		case 'f':
1723*b30d1939SAndy Fiddaman 			if(motion==';')
1724*b30d1939SAndy Fiddaman 			{
1725*b30d1939SAndy Fiddaman 				bound = last_virt;
1726*b30d1939SAndy Fiddaman 				incr = 1;
1727*b30d1939SAndy Fiddaman 			}
1728*b30d1939SAndy Fiddaman 			goto find_b;
1729*b30d1939SAndy Fiddaman 
1730*b30d1939SAndy Fiddaman 		case 'T':
1731*b30d1939SAndy Fiddaman 		case 'F':
1732*b30d1939SAndy Fiddaman 			if(motion==',')
1733*b30d1939SAndy Fiddaman 			{
1734*b30d1939SAndy Fiddaman 				bound = last_virt;
1735*b30d1939SAndy Fiddaman 				incr = 1;
1736*b30d1939SAndy Fiddaman 			}
1737*b30d1939SAndy Fiddaman 			goto find_b;
1738*b30d1939SAndy Fiddaman 
1739*b30d1939SAndy Fiddaman 		default:
1740*b30d1939SAndy Fiddaman 			return(0);
1741*b30d1939SAndy Fiddaman 		}
1742*b30d1939SAndy Fiddaman 
1743*b30d1939SAndy Fiddaman 
1744*b30d1939SAndy Fiddaman 	case 't':		/** find up to new char forward **/
1745*b30d1939SAndy Fiddaman 	case 'f':		/** find new char forward **/
1746*b30d1939SAndy Fiddaman 		bound = last_virt;
1747*b30d1939SAndy Fiddaman 		incr = 1;
1748*b30d1939SAndy Fiddaman 		/* FALLTHROUGH */
1749*b30d1939SAndy Fiddaman 
1750*b30d1939SAndy Fiddaman 	case 'T':		/** find up to new char backward **/
1751*b30d1939SAndy Fiddaman 	case 'F':		/** find new char backward **/
1752*b30d1939SAndy Fiddaman 		vp->last_find = motion;
1753*b30d1939SAndy Fiddaman 		if((vp->findchar=getrchar(vp))==ESC)
1754*b30d1939SAndy Fiddaman 			return(1);
1755*b30d1939SAndy Fiddaman find_b:
1756*b30d1939SAndy Fiddaman 		tcur_virt = cur_virt;
1757*b30d1939SAndy Fiddaman 		count = vp->repeat;
1758*b30d1939SAndy Fiddaman 		while( count-- )
1759*b30d1939SAndy Fiddaman 		{
1760*b30d1939SAndy Fiddaman 			while( incr*(tcur_virt+=incr) <= bound
1761*b30d1939SAndy Fiddaman 				&& virtual[tcur_virt] != vp->findchar );
1762*b30d1939SAndy Fiddaman 			if( incr*tcur_virt > bound )
1763*b30d1939SAndy Fiddaman 			{
1764*b30d1939SAndy Fiddaman 				return(0);
1765*b30d1939SAndy Fiddaman 			}
1766*b30d1939SAndy Fiddaman 		}
1767*b30d1939SAndy Fiddaman 		if( fold(vp->last_find) == 'T' )
1768*b30d1939SAndy Fiddaman 			tcur_virt -= incr;
1769*b30d1939SAndy Fiddaman 		break;
1770*b30d1939SAndy Fiddaman 
1771*b30d1939SAndy Fiddaman         case '%':
1772*b30d1939SAndy Fiddaman 	{
1773*b30d1939SAndy Fiddaman 		int nextmotion;
1774*b30d1939SAndy Fiddaman 		int nextc;
1775*b30d1939SAndy Fiddaman 		tcur_virt = cur_virt;
1776*b30d1939SAndy Fiddaman 		while( tcur_virt <= last_virt
1777*b30d1939SAndy Fiddaman 			&& strchr(paren_chars,virtual[tcur_virt])==(char*)0)
1778*b30d1939SAndy Fiddaman 				tcur_virt++;
1779*b30d1939SAndy Fiddaman 		if(tcur_virt > last_virt )
1780*b30d1939SAndy Fiddaman 			return(0);
1781*b30d1939SAndy Fiddaman 		nextc = virtual[tcur_virt];
1782*b30d1939SAndy Fiddaman 		count = strchr(paren_chars,nextc)-paren_chars;
1783*b30d1939SAndy Fiddaman 		if(count < 3)
1784*b30d1939SAndy Fiddaman 		{
1785*b30d1939SAndy Fiddaman 			incr = 1;
1786*b30d1939SAndy Fiddaman 			bound = last_virt;
1787*b30d1939SAndy Fiddaman 			nextmotion = paren_chars[count+3];
1788*b30d1939SAndy Fiddaman 		}
1789*b30d1939SAndy Fiddaman 		else
1790*b30d1939SAndy Fiddaman 			nextmotion = paren_chars[count-3];
1791*b30d1939SAndy Fiddaman 		count = 1;
1792*b30d1939SAndy Fiddaman 		while(count >0 &&  incr*(tcur_virt+=incr) <= bound)
1793*b30d1939SAndy Fiddaman 		{
1794*b30d1939SAndy Fiddaman 		        if(virtual[tcur_virt] == nextmotion)
1795*b30d1939SAndy Fiddaman 		        	count--;
1796*b30d1939SAndy Fiddaman 		        else if(virtual[tcur_virt]==nextc)
1797*b30d1939SAndy Fiddaman 		        	count++;
1798*b30d1939SAndy Fiddaman 		}
1799*b30d1939SAndy Fiddaman 		if(count)
1800*b30d1939SAndy Fiddaman 			return(0);
1801*b30d1939SAndy Fiddaman 		break;
1802*b30d1939SAndy Fiddaman 	}
1803*b30d1939SAndy Fiddaman 
1804*b30d1939SAndy Fiddaman 	case 'W':
1805*b30d1939SAndy Fiddaman 	case 'w':		/** forward word **/
1806*b30d1939SAndy Fiddaman 		tcur_virt = cur_virt;
1807*b30d1939SAndy Fiddaman 		forward(vp,vp->repeat, motion);
1808*b30d1939SAndy Fiddaman 		if( tcur_virt == cur_virt )
1809*b30d1939SAndy Fiddaman 			return(0);
1810*b30d1939SAndy Fiddaman 		return(1);
1811*b30d1939SAndy Fiddaman 
1812*b30d1939SAndy Fiddaman 	default:
1813*b30d1939SAndy Fiddaman 		return(0);
1814*b30d1939SAndy Fiddaman 	}
1815*b30d1939SAndy Fiddaman 	cur_virt = tcur_virt;
1816*b30d1939SAndy Fiddaman 
1817*b30d1939SAndy Fiddaman 	return(1);
1818*b30d1939SAndy Fiddaman }
1819*b30d1939SAndy Fiddaman 
1820*b30d1939SAndy Fiddaman /*
1821*b30d1939SAndy Fiddaman  * print a string
1822*b30d1939SAndy Fiddaman  */
1823*b30d1939SAndy Fiddaman 
pr_string(register Vi_t * vp,register const char * sp)1824*b30d1939SAndy Fiddaman static void pr_string(register Vi_t *vp, register const char *sp)
1825*b30d1939SAndy Fiddaman {
1826*b30d1939SAndy Fiddaman 	/*** copy string sp ***/
1827*b30d1939SAndy Fiddaman 	register char *ptr = editb.e_outptr;
1828*b30d1939SAndy Fiddaman 	while(*sp)
1829*b30d1939SAndy Fiddaman 		*ptr++ = *sp++;
1830*b30d1939SAndy Fiddaman 	editb.e_outptr = ptr;
1831*b30d1939SAndy Fiddaman 	return;
1832*b30d1939SAndy Fiddaman }
1833*b30d1939SAndy Fiddaman 
1834*b30d1939SAndy Fiddaman /*{	PUTSTRING( column, nchars )
1835*b30d1939SAndy Fiddaman  *
1836*b30d1939SAndy Fiddaman  *	Put nchars starting at column of physical into the workspace
1837*b30d1939SAndy Fiddaman  * to be printed.
1838*b30d1939SAndy Fiddaman  *
1839*b30d1939SAndy Fiddaman }*/
1840*b30d1939SAndy Fiddaman 
putstring(register Vi_t * vp,register int col,register int nchars)1841*b30d1939SAndy Fiddaman static void putstring(register Vi_t *vp,register int col, register int nchars)
1842*b30d1939SAndy Fiddaman {
1843*b30d1939SAndy Fiddaman 	while( nchars-- )
1844*b30d1939SAndy Fiddaman 		putchar(physical[col++]);
1845*b30d1939SAndy Fiddaman 	return;
1846*b30d1939SAndy Fiddaman }
1847*b30d1939SAndy Fiddaman 
1848*b30d1939SAndy Fiddaman /*{	REFRESH( mode )
1849*b30d1939SAndy Fiddaman  *
1850*b30d1939SAndy Fiddaman  *	This routine will refresh the crt so the physical image matches
1851*b30d1939SAndy Fiddaman  * the virtual image and display the proper window.
1852*b30d1939SAndy Fiddaman  *
1853*b30d1939SAndy Fiddaman  *	mode	= CONTROL, refresh in control mode, ie. leave cursor
1854*b30d1939SAndy Fiddaman  *			positioned at last char printed.
1855*b30d1939SAndy Fiddaman  *		= INPUT, refresh in input mode; leave cursor positioned
1856*b30d1939SAndy Fiddaman  *			after last char printed.
1857*b30d1939SAndy Fiddaman  *		= TRANSLATE, perform virtual to physical translation
1858*b30d1939SAndy Fiddaman  *			and adjust left margin only.
1859*b30d1939SAndy Fiddaman  *
1860*b30d1939SAndy Fiddaman  *		+-------------------------------+
1861*b30d1939SAndy Fiddaman  *		|   | |    virtual	  | |   |
1862*b30d1939SAndy Fiddaman  *		+-------------------------------+
1863*b30d1939SAndy Fiddaman  *		  cur_virt		last_virt
1864*b30d1939SAndy Fiddaman  *
1865*b30d1939SAndy Fiddaman  *		+-----------------------------------------------+
1866*b30d1939SAndy Fiddaman  *		|	  | |	        physical	 | |    |
1867*b30d1939SAndy Fiddaman  *		+-----------------------------------------------+
1868*b30d1939SAndy Fiddaman  *			cur_phys			last_phys
1869*b30d1939SAndy Fiddaman  *
1870*b30d1939SAndy Fiddaman  *				0			w_size - 1
1871*b30d1939SAndy Fiddaman  *				+-----------------------+
1872*b30d1939SAndy Fiddaman  *				| | |  window		|
1873*b30d1939SAndy Fiddaman  *				+-----------------------+
1874*b30d1939SAndy Fiddaman  *				cur_window = cur_phys - first_wind
1875*b30d1939SAndy Fiddaman }*/
1876*b30d1939SAndy Fiddaman 
refresh(register Vi_t * vp,int mode)1877*b30d1939SAndy Fiddaman static void refresh(register Vi_t* vp, int mode)
1878*b30d1939SAndy Fiddaman {
1879*b30d1939SAndy Fiddaman 	register int p;
1880*b30d1939SAndy Fiddaman 	register int v;
1881*b30d1939SAndy Fiddaman 	register int first_w = vp->first_wind;
1882*b30d1939SAndy Fiddaman 	int p_differ;
1883*b30d1939SAndy Fiddaman 	int new_lw;
1884*b30d1939SAndy Fiddaman 	int ncur_phys;
1885*b30d1939SAndy Fiddaman 	int opflag;			/* search optimize flag */
1886*b30d1939SAndy Fiddaman 
1887*b30d1939SAndy Fiddaman #	define	w	v
1888*b30d1939SAndy Fiddaman 
1889*b30d1939SAndy Fiddaman 	/*** find out if it's necessary to start translating at beginning ***/
1890*b30d1939SAndy Fiddaman 
1891*b30d1939SAndy Fiddaman 	if(lookahead>0)
1892*b30d1939SAndy Fiddaman 	{
1893*b30d1939SAndy Fiddaman 		p = previous[lookahead-1];
1894*b30d1939SAndy Fiddaman 		if(p != ESC && p != '\n' && p != '\r')
1895*b30d1939SAndy Fiddaman 			mode = TRANSLATE;
1896*b30d1939SAndy Fiddaman 	}
1897*b30d1939SAndy Fiddaman 	v = cur_virt;
1898*b30d1939SAndy Fiddaman #if SHOPT_EDPREDICT
1899*b30d1939SAndy Fiddaman 	if(mode==INPUT && v>0 && virtual[0]=='#' && v==last_virt && virtual[v]!='*' && sh_isoption(SH_VI))
1900*b30d1939SAndy Fiddaman 	{
1901*b30d1939SAndy Fiddaman 		int		n;
1902*b30d1939SAndy Fiddaman 		virtual[last_virt+1] = 0;
1903*b30d1939SAndy Fiddaman #   if SHOPT_MULTIBYTE
1904*b30d1939SAndy Fiddaman 		ed_external(virtual,(char*)virtual);
1905*b30d1939SAndy Fiddaman #   endif /* SHOPT_MULTIBYTE */
1906*b30d1939SAndy Fiddaman 		n = ed_histgen(vp->ed,(char*)virtual);
1907*b30d1939SAndy Fiddaman #   if SHOPT_MULTIBYTE
1908*b30d1939SAndy Fiddaman 		ed_internal((char*)virtual,virtual);
1909*b30d1939SAndy Fiddaman #   endif /* SHOPT_MULTIBYTE */
1910*b30d1939SAndy Fiddaman 		if(vp->ed->hlist)
1911*b30d1939SAndy Fiddaman 		{
1912*b30d1939SAndy Fiddaman 			ed_histlist(vp->ed,n);
1913*b30d1939SAndy Fiddaman 			pr_string(vp,Prompt);
1914*b30d1939SAndy Fiddaman 			vp->ocur_virt = INVALID;
1915*b30d1939SAndy Fiddaman 			ed_setcursor(vp->ed,physical,0,cur_phys,0);
1916*b30d1939SAndy Fiddaman 		}
1917*b30d1939SAndy Fiddaman 		else
1918*b30d1939SAndy Fiddaman 			ed_ringbell();
1919*b30d1939SAndy Fiddaman 	}
1920*b30d1939SAndy Fiddaman 	else if(mode==INPUT && v<=1 && vp->ed->hlist)
1921*b30d1939SAndy Fiddaman 		ed_histlist(vp->ed,0);
1922*b30d1939SAndy Fiddaman #endif /* SHOPT_EDPREDICT */
1923*b30d1939SAndy Fiddaman 	if( v<vp->ocur_virt || vp->ocur_virt==INVALID
1924*b30d1939SAndy Fiddaman 		|| ( v==vp->ocur_virt
1925*b30d1939SAndy Fiddaman 			&& (!is_print(virtual[v]) || !is_print(vp->o_v_char))) )
1926*b30d1939SAndy Fiddaman 	{
1927*b30d1939SAndy Fiddaman 		opflag = 0;
1928*b30d1939SAndy Fiddaman 		p = 0;
1929*b30d1939SAndy Fiddaman 		v = 0;
1930*b30d1939SAndy Fiddaman 	}
1931*b30d1939SAndy Fiddaman 	else
1932*b30d1939SAndy Fiddaman 	{
1933*b30d1939SAndy Fiddaman 		opflag = 1;
1934*b30d1939SAndy Fiddaman 		p = vp->ocur_phys;
1935*b30d1939SAndy Fiddaman 		v = vp->ocur_virt;
1936*b30d1939SAndy Fiddaman 		if( !is_print(virtual[v]) )
1937*b30d1939SAndy Fiddaman 		{
1938*b30d1939SAndy Fiddaman 			/*** avoid double ^'s ***/
1939*b30d1939SAndy Fiddaman 			++p;
1940*b30d1939SAndy Fiddaman 			++v;
1941*b30d1939SAndy Fiddaman 		}
1942*b30d1939SAndy Fiddaman 	}
1943*b30d1939SAndy Fiddaman 	virtual[last_virt+1] = 0;
1944*b30d1939SAndy Fiddaman 	ncur_phys = ed_virt_to_phys(vp->ed,virtual,physical,cur_virt,v,p);
1945*b30d1939SAndy Fiddaman 	p = genlen(physical);
1946*b30d1939SAndy Fiddaman 	if( --p < 0 )
1947*b30d1939SAndy Fiddaman 		last_phys = 0;
1948*b30d1939SAndy Fiddaman 	else
1949*b30d1939SAndy Fiddaman 		last_phys = p;
1950*b30d1939SAndy Fiddaman 
1951*b30d1939SAndy Fiddaman 	/*** see if this was a translate only ***/
1952*b30d1939SAndy Fiddaman 
1953*b30d1939SAndy Fiddaman 	if( mode == TRANSLATE )
1954*b30d1939SAndy Fiddaman 		return;
1955*b30d1939SAndy Fiddaman 
1956*b30d1939SAndy Fiddaman 	/*** adjust left margin if necessary ***/
1957*b30d1939SAndy Fiddaman 
1958*b30d1939SAndy Fiddaman 	if( ncur_phys<first_w || ncur_phys>=(first_w + w_size) )
1959*b30d1939SAndy Fiddaman 	{
1960*b30d1939SAndy Fiddaman 		cursor(vp,first_w);
1961*b30d1939SAndy Fiddaman 		first_w = ncur_phys - (w_size>>1);
1962*b30d1939SAndy Fiddaman 		if( first_w < 0 )
1963*b30d1939SAndy Fiddaman 			first_w = 0;
1964*b30d1939SAndy Fiddaman 		vp->first_wind = cur_phys = first_w;
1965*b30d1939SAndy Fiddaman 	}
1966*b30d1939SAndy Fiddaman 
1967*b30d1939SAndy Fiddaman 	/*** attempt to optimize search somewhat to find ***/
1968*b30d1939SAndy Fiddaman 	/*** out where physical and window images differ ***/
1969*b30d1939SAndy Fiddaman 
1970*b30d1939SAndy Fiddaman 	if( first_w==vp->ofirst_wind && ncur_phys>=vp->ocur_phys && opflag==1 )
1971*b30d1939SAndy Fiddaman 	{
1972*b30d1939SAndy Fiddaman 		p = vp->ocur_phys;
1973*b30d1939SAndy Fiddaman 		w = p - first_w;
1974*b30d1939SAndy Fiddaman 	}
1975*b30d1939SAndy Fiddaman 	else
1976*b30d1939SAndy Fiddaman 	{
1977*b30d1939SAndy Fiddaman 		p = first_w;
1978*b30d1939SAndy Fiddaman 		w = 0;
1979*b30d1939SAndy Fiddaman 	}
1980*b30d1939SAndy Fiddaman 
1981*b30d1939SAndy Fiddaman 	for(; (p<=last_phys && w<=vp->last_wind); ++p, ++w)
1982*b30d1939SAndy Fiddaman 	{
1983*b30d1939SAndy Fiddaman 		if( window[w] != physical[p] )
1984*b30d1939SAndy Fiddaman 			break;
1985*b30d1939SAndy Fiddaman 	}
1986*b30d1939SAndy Fiddaman 	p_differ = p;
1987*b30d1939SAndy Fiddaman 
1988*b30d1939SAndy Fiddaman 	if( (p>last_phys || p>=first_w+w_size) && w>vp->last_wind
1989*b30d1939SAndy Fiddaman 		&& cur_virt==vp->ocur_virt )
1990*b30d1939SAndy Fiddaman 	{
1991*b30d1939SAndy Fiddaman 		/*** images are identical ***/
1992*b30d1939SAndy Fiddaman 		return;
1993*b30d1939SAndy Fiddaman 	}
1994*b30d1939SAndy Fiddaman 
1995*b30d1939SAndy Fiddaman 	/*** copy the physical image to the window image ***/
1996*b30d1939SAndy Fiddaman 
1997*b30d1939SAndy Fiddaman 	if( last_virt != INVALID )
1998*b30d1939SAndy Fiddaman 	{
1999*b30d1939SAndy Fiddaman 		while( p <= last_phys && w < w_size )
2000*b30d1939SAndy Fiddaman 			window[w++] = physical[p++];
2001*b30d1939SAndy Fiddaman 	}
2002*b30d1939SAndy Fiddaman 	new_lw = w;
2003*b30d1939SAndy Fiddaman 
2004*b30d1939SAndy Fiddaman 	/*** erase trailing characters if needed ***/
2005*b30d1939SAndy Fiddaman 
2006*b30d1939SAndy Fiddaman 	while( w <= vp->last_wind )
2007*b30d1939SAndy Fiddaman 		window[w++] = ' ';
2008*b30d1939SAndy Fiddaman 	vp->last_wind = --w;
2009*b30d1939SAndy Fiddaman 
2010*b30d1939SAndy Fiddaman 	p = p_differ;
2011*b30d1939SAndy Fiddaman 
2012*b30d1939SAndy Fiddaman 	/*** move cursor to start of difference ***/
2013*b30d1939SAndy Fiddaman 
2014*b30d1939SAndy Fiddaman 	cursor(vp,p);
2015*b30d1939SAndy Fiddaman 
2016*b30d1939SAndy Fiddaman 	/*** and output difference ***/
2017*b30d1939SAndy Fiddaman 
2018*b30d1939SAndy Fiddaman 	w = p - first_w;
2019*b30d1939SAndy Fiddaman 	while( w <= vp->last_wind )
2020*b30d1939SAndy Fiddaman 		putchar(window[w++]);
2021*b30d1939SAndy Fiddaman 
2022*b30d1939SAndy Fiddaman 	cur_phys = w + first_w;
2023*b30d1939SAndy Fiddaman 	vp->last_wind = --new_lw;
2024*b30d1939SAndy Fiddaman 
2025*b30d1939SAndy Fiddaman 	if( last_phys >= w_size )
2026*b30d1939SAndy Fiddaman 	{
2027*b30d1939SAndy Fiddaman 		if( first_w == 0 )
2028*b30d1939SAndy Fiddaman 			vp->long_char = '>';
2029*b30d1939SAndy Fiddaman 		else if( last_phys < (first_w+w_size) )
2030*b30d1939SAndy Fiddaman 			vp->long_char = '<';
2031*b30d1939SAndy Fiddaman 		else
2032*b30d1939SAndy Fiddaman 			vp->long_char = '*';
2033*b30d1939SAndy Fiddaman 	}
2034*b30d1939SAndy Fiddaman 	else
2035*b30d1939SAndy Fiddaman 		vp->long_char = ' ';
2036*b30d1939SAndy Fiddaman 
2037*b30d1939SAndy Fiddaman 	if( vp->long_line != vp->long_char )
2038*b30d1939SAndy Fiddaman 	{
2039*b30d1939SAndy Fiddaman 		/*** indicate lines longer than window ***/
2040*b30d1939SAndy Fiddaman 		while( w++ < w_size )
2041*b30d1939SAndy Fiddaman 		{
2042*b30d1939SAndy Fiddaman 			putchar(' ');
2043*b30d1939SAndy Fiddaman 			++cur_phys;
2044*b30d1939SAndy Fiddaman 		}
2045*b30d1939SAndy Fiddaman 		putchar(vp->long_char);
2046*b30d1939SAndy Fiddaman 		++cur_phys;
2047*b30d1939SAndy Fiddaman 		vp->long_line = vp->long_char;
2048*b30d1939SAndy Fiddaman 	}
2049*b30d1939SAndy Fiddaman 
2050*b30d1939SAndy Fiddaman 	if(vp->ed->e_multiline &&  vp->ofirst_wind==INVALID && !vp->ed->e_nocrnl)
2051*b30d1939SAndy Fiddaman 		ed_setcursor(vp->ed, physical, last_phys+1, last_phys+1, -1);
2052*b30d1939SAndy Fiddaman 	vp->ed->e_nocrnl = 0;
2053*b30d1939SAndy Fiddaman 	vp->ocur_phys = ncur_phys;
2054*b30d1939SAndy Fiddaman 	vp->ocur_virt = cur_virt;
2055*b30d1939SAndy Fiddaman 	vp->ofirst_wind = first_w;
2056*b30d1939SAndy Fiddaman 
2057*b30d1939SAndy Fiddaman 	if( mode==INPUT && cur_virt>INVALID )
2058*b30d1939SAndy Fiddaman 		++ncur_phys;
2059*b30d1939SAndy Fiddaman 
2060*b30d1939SAndy Fiddaman 	cursor(vp,ncur_phys);
2061*b30d1939SAndy Fiddaman 	ed_flush(vp->ed);
2062*b30d1939SAndy Fiddaman 	return;
2063*b30d1939SAndy Fiddaman }
2064*b30d1939SAndy Fiddaman 
2065*b30d1939SAndy Fiddaman /*{	REPLACE( char, increment )
2066*b30d1939SAndy Fiddaman  *
2067*b30d1939SAndy Fiddaman  *	Replace the cur_virt character with char.  This routine attempts
2068*b30d1939SAndy Fiddaman  * to avoid using refresh().
2069*b30d1939SAndy Fiddaman  *
2070*b30d1939SAndy Fiddaman  *	increment	= 1, increment cur_virt after replacement.
2071*b30d1939SAndy Fiddaman  *			= 0, leave cur_virt where it is.
2072*b30d1939SAndy Fiddaman  *
2073*b30d1939SAndy Fiddaman }*/
2074*b30d1939SAndy Fiddaman 
replace(register Vi_t * vp,register int c,register int increment)2075*b30d1939SAndy Fiddaman static void replace(register Vi_t *vp, register int c, register int increment)
2076*b30d1939SAndy Fiddaman {
2077*b30d1939SAndy Fiddaman 	register int cur_window;
2078*b30d1939SAndy Fiddaman 
2079*b30d1939SAndy Fiddaman 	if( cur_virt == INVALID )
2080*b30d1939SAndy Fiddaman 	{
2081*b30d1939SAndy Fiddaman 		/*** can't replace invalid cursor ***/
2082*b30d1939SAndy Fiddaman 		ed_ringbell();
2083*b30d1939SAndy Fiddaman 		return;
2084*b30d1939SAndy Fiddaman 	}
2085*b30d1939SAndy Fiddaman 	cur_window = cur_phys - vp->first_wind;
2086*b30d1939SAndy Fiddaman 	if( vp->ocur_virt == INVALID || !is_print(c)
2087*b30d1939SAndy Fiddaman 		|| !is_print(virtual[cur_virt])
2088*b30d1939SAndy Fiddaman 		|| !is_print(vp->o_v_char)
2089*b30d1939SAndy Fiddaman #if SHOPT_MULTIBYTE
2090*b30d1939SAndy Fiddaman 		|| !iswascii(c) || mbwidth(vp->o_v_char)>1
2091*b30d1939SAndy Fiddaman 		|| !iswascii(virtual[cur_virt])
2092*b30d1939SAndy Fiddaman #endif /* SHOPT_MULTIBYTE */
2093*b30d1939SAndy Fiddaman 		|| (increment && (cur_window==w_size-1)
2094*b30d1939SAndy Fiddaman 			|| !is_print(virtual[cur_virt+1])) )
2095*b30d1939SAndy Fiddaman 	{
2096*b30d1939SAndy Fiddaman 		/*** must use standard refresh routine ***/
2097*b30d1939SAndy Fiddaman 
2098*b30d1939SAndy Fiddaman 		cdelete(vp,1, BAD);
2099*b30d1939SAndy Fiddaman 		append(vp,c, APPEND);
2100*b30d1939SAndy Fiddaman 		if( increment && cur_virt<last_virt )
2101*b30d1939SAndy Fiddaman 			++cur_virt;
2102*b30d1939SAndy Fiddaman 		refresh(vp,CONTROL);
2103*b30d1939SAndy Fiddaman 	}
2104*b30d1939SAndy Fiddaman 	else
2105*b30d1939SAndy Fiddaman 	{
2106*b30d1939SAndy Fiddaman 		virtual[cur_virt] = c;
2107*b30d1939SAndy Fiddaman 		physical[cur_phys] = c;
2108*b30d1939SAndy Fiddaman 		window[cur_window] = c;
2109*b30d1939SAndy Fiddaman 		putchar(c);
2110*b30d1939SAndy Fiddaman 		if(increment)
2111*b30d1939SAndy Fiddaman 		{
2112*b30d1939SAndy Fiddaman 			c = virtual[++cur_virt];
2113*b30d1939SAndy Fiddaman 			++cur_phys;
2114*b30d1939SAndy Fiddaman 		}
2115*b30d1939SAndy Fiddaman 		else
2116*b30d1939SAndy Fiddaman 		{
2117*b30d1939SAndy Fiddaman 			putchar('\b');
2118*b30d1939SAndy Fiddaman 		}
2119*b30d1939SAndy Fiddaman 		vp->o_v_char = c;
2120*b30d1939SAndy Fiddaman 		ed_flush(vp->ed);
2121*b30d1939SAndy Fiddaman 	}
2122*b30d1939SAndy Fiddaman 	return;
2123*b30d1939SAndy Fiddaman }
2124*b30d1939SAndy Fiddaman 
2125*b30d1939SAndy Fiddaman /*{	RESTORE_V()
2126*b30d1939SAndy Fiddaman  *
2127*b30d1939SAndy Fiddaman  *	Restore the contents of virtual space from u_space.
2128*b30d1939SAndy Fiddaman  *
2129*b30d1939SAndy Fiddaman }*/
2130*b30d1939SAndy Fiddaman 
restore_v(register Vi_t * vp)2131*b30d1939SAndy Fiddaman static void restore_v(register Vi_t *vp)
2132*b30d1939SAndy Fiddaman {
2133*b30d1939SAndy Fiddaman 	register int tmpcol;
2134*b30d1939SAndy Fiddaman 	genchar tmpspace[MAXLINE];
2135*b30d1939SAndy Fiddaman 
2136*b30d1939SAndy Fiddaman 	if( vp->u_column == INVALID-1 )
2137*b30d1939SAndy Fiddaman 	{
2138*b30d1939SAndy Fiddaman 		/*** never saved anything ***/
2139*b30d1939SAndy Fiddaman 		ed_ringbell();
2140*b30d1939SAndy Fiddaman 		return;
2141*b30d1939SAndy Fiddaman 	}
2142*b30d1939SAndy Fiddaman 	gencpy(tmpspace, vp->u_space);
2143*b30d1939SAndy Fiddaman 	tmpcol = vp->u_column;
2144*b30d1939SAndy Fiddaman 	save_v(vp);
2145*b30d1939SAndy Fiddaman 	gencpy(virtual, tmpspace);
2146*b30d1939SAndy Fiddaman 	cur_virt = tmpcol;
2147*b30d1939SAndy Fiddaman 	last_virt = genlen(tmpspace) - 1;
2148*b30d1939SAndy Fiddaman 	vp->ocur_virt = MAXCHAR;	/** invalidate refresh optimization **/
2149*b30d1939SAndy Fiddaman 	return;
2150*b30d1939SAndy Fiddaman }
2151*b30d1939SAndy Fiddaman 
2152*b30d1939SAndy Fiddaman /*{	SAVE_LAST()
2153*b30d1939SAndy Fiddaman  *
2154*b30d1939SAndy Fiddaman  *	If the user has typed something, save it in last line.
2155*b30d1939SAndy Fiddaman  *
2156*b30d1939SAndy Fiddaman }*/
2157*b30d1939SAndy Fiddaman 
save_last(register Vi_t * vp)2158*b30d1939SAndy Fiddaman static void save_last(register Vi_t* vp)
2159*b30d1939SAndy Fiddaman {
2160*b30d1939SAndy Fiddaman 	register int i;
2161*b30d1939SAndy Fiddaman 
2162*b30d1939SAndy Fiddaman 	if( (i = cur_virt - first_virt + 1) > 0 )
2163*b30d1939SAndy Fiddaman 	{
2164*b30d1939SAndy Fiddaman 		/*** save last thing user typed ***/
2165*b30d1939SAndy Fiddaman 		if(i >= MAXLINE)
2166*b30d1939SAndy Fiddaman 			i = MAXLINE-1;
2167*b30d1939SAndy Fiddaman 		genncpy(vp->lastline, (&virtual[first_virt]), i);
2168*b30d1939SAndy Fiddaman 		vp->lastline[i] = '\0';
2169*b30d1939SAndy Fiddaman 	}
2170*b30d1939SAndy Fiddaman 	return;
2171*b30d1939SAndy Fiddaman }
2172*b30d1939SAndy Fiddaman 
2173*b30d1939SAndy Fiddaman /*{	SAVE_V()
2174*b30d1939SAndy Fiddaman  *
2175*b30d1939SAndy Fiddaman  *	This routine will save the contents of virtual in u_space.
2176*b30d1939SAndy Fiddaman  *
2177*b30d1939SAndy Fiddaman }*/
2178*b30d1939SAndy Fiddaman 
save_v(register Vi_t * vp)2179*b30d1939SAndy Fiddaman static void save_v(register Vi_t *vp)
2180*b30d1939SAndy Fiddaman {
2181*b30d1939SAndy Fiddaman 	if(!inmacro)
2182*b30d1939SAndy Fiddaman 	{
2183*b30d1939SAndy Fiddaman 		virtual[last_virt + 1] = '\0';
2184*b30d1939SAndy Fiddaman 		gencpy(vp->u_space, virtual);
2185*b30d1939SAndy Fiddaman 		vp->u_column = cur_virt;
2186*b30d1939SAndy Fiddaman 	}
2187*b30d1939SAndy Fiddaman 	return;
2188*b30d1939SAndy Fiddaman }
2189*b30d1939SAndy Fiddaman 
2190*b30d1939SAndy Fiddaman /*{	SEARCH( mode )
2191*b30d1939SAndy Fiddaman  *
2192*b30d1939SAndy Fiddaman  *	Search history file for regular expression.
2193*b30d1939SAndy Fiddaman  *
2194*b30d1939SAndy Fiddaman  *	mode	= '/'	require search string and search new to old
2195*b30d1939SAndy Fiddaman  *	mode	= '?'	require search string and search old to new
2196*b30d1939SAndy Fiddaman  *	mode	= 'N'	repeat last search in reverse direction
2197*b30d1939SAndy Fiddaman  *	mode	= 'n'	repeat last search
2198*b30d1939SAndy Fiddaman  *
2199*b30d1939SAndy Fiddaman }*/
2200*b30d1939SAndy Fiddaman 
2201*b30d1939SAndy Fiddaman /*
2202*b30d1939SAndy Fiddaman  * search for <string> in the current command
2203*b30d1939SAndy Fiddaman  */
curline_search(Vi_t * vp,const char * string)2204*b30d1939SAndy Fiddaman static int curline_search(Vi_t *vp, const char *string)
2205*b30d1939SAndy Fiddaman {
2206*b30d1939SAndy Fiddaman 	register size_t len=strlen(string);
2207*b30d1939SAndy Fiddaman 	register const char *dp,*cp=string, *dpmax;
2208*b30d1939SAndy Fiddaman #if SHOPT_MULTIBYTE
2209*b30d1939SAndy Fiddaman 	ed_external(vp->u_space,(char*)vp->u_space);
2210*b30d1939SAndy Fiddaman #endif /* SHOPT_MULTIBYTE */
2211*b30d1939SAndy Fiddaman 	for(dp=(char*)vp->u_space,dpmax=dp+strlen(dp)-len; dp<=dpmax; dp++)
2212*b30d1939SAndy Fiddaman 	{
2213*b30d1939SAndy Fiddaman 		if(*dp==*cp && memcmp(cp,dp,len)==0)
2214*b30d1939SAndy Fiddaman 			return(dp-(char*)vp->u_space);
2215*b30d1939SAndy Fiddaman 	}
2216*b30d1939SAndy Fiddaman #if SHOPT_MULTIBYTE
2217*b30d1939SAndy Fiddaman 	ed_internal((char*)vp->u_space,vp->u_space);
2218*b30d1939SAndy Fiddaman #endif /* SHOPT_MULTIBYTE */
2219*b30d1939SAndy Fiddaman 	return(-1);
2220*b30d1939SAndy Fiddaman }
2221*b30d1939SAndy Fiddaman 
search(register Vi_t * vp,register int mode)2222*b30d1939SAndy Fiddaman static int search(register Vi_t* vp,register int mode)
2223*b30d1939SAndy Fiddaman {
2224*b30d1939SAndy Fiddaman 	register int new_direction;
2225*b30d1939SAndy Fiddaman 	register int oldcurhline;
2226*b30d1939SAndy Fiddaman 	register int i;
2227*b30d1939SAndy Fiddaman 	Histloc_t  location;
2228*b30d1939SAndy Fiddaman 
2229*b30d1939SAndy Fiddaman 	if( vp->direction == -2 && mode != 'n')
2230*b30d1939SAndy Fiddaman 		vp->direction = -1;
2231*b30d1939SAndy Fiddaman 	if( mode == '/' || mode == '?')
2232*b30d1939SAndy Fiddaman 	{
2233*b30d1939SAndy Fiddaman 		/*** new search expression ***/
2234*b30d1939SAndy Fiddaman 		del_line(vp,BAD);
2235*b30d1939SAndy Fiddaman 		append(vp,mode, APPEND);
2236*b30d1939SAndy Fiddaman 		refresh(vp,INPUT);
2237*b30d1939SAndy Fiddaman 		first_virt = 1;
2238*b30d1939SAndy Fiddaman 		getline(vp,SEARCH);
2239*b30d1939SAndy Fiddaman 		first_virt = 0;
2240*b30d1939SAndy Fiddaman 		virtual[last_virt + 1] = '\0';	/*** make null terminated ***/
2241*b30d1939SAndy Fiddaman 		vp->direction = mode=='/' ? -1 : 1;
2242*b30d1939SAndy Fiddaman 	}
2243*b30d1939SAndy Fiddaman 
2244*b30d1939SAndy Fiddaman 	if( cur_virt == INVALID )
2245*b30d1939SAndy Fiddaman 	{
2246*b30d1939SAndy Fiddaman 		/*** no operation ***/
2247*b30d1939SAndy Fiddaman 		return(ABORT);
2248*b30d1939SAndy Fiddaman 	}
2249*b30d1939SAndy Fiddaman 
2250*b30d1939SAndy Fiddaman 	if( cur_virt==0 ||  fold(mode)=='N' )
2251*b30d1939SAndy Fiddaman 	{
2252*b30d1939SAndy Fiddaman 		/*** user wants repeat of last search ***/
2253*b30d1939SAndy Fiddaman 		del_line(vp,BAD);
2254*b30d1939SAndy Fiddaman 		strcpy( ((char*)virtual)+1, lsearch);
2255*b30d1939SAndy Fiddaman #if SHOPT_MULTIBYTE
2256*b30d1939SAndy Fiddaman 		*((char*)virtual) = '/';
2257*b30d1939SAndy Fiddaman 		ed_internal((char*)virtual,virtual);
2258*b30d1939SAndy Fiddaman #endif /* SHOPT_MULTIBYTE */
2259*b30d1939SAndy Fiddaman 	}
2260*b30d1939SAndy Fiddaman 
2261*b30d1939SAndy Fiddaman 	if( mode == 'N' )
2262*b30d1939SAndy Fiddaman 		new_direction = -vp->direction;
2263*b30d1939SAndy Fiddaman 	else
2264*b30d1939SAndy Fiddaman 		new_direction = vp->direction;
2265*b30d1939SAndy Fiddaman 
2266*b30d1939SAndy Fiddaman 
2267*b30d1939SAndy Fiddaman 	/*** now search ***/
2268*b30d1939SAndy Fiddaman 
2269*b30d1939SAndy Fiddaman 	oldcurhline = curhline;
2270*b30d1939SAndy Fiddaman #if SHOPT_MULTIBYTE
2271*b30d1939SAndy Fiddaman 	ed_external(virtual,(char*)virtual);
2272*b30d1939SAndy Fiddaman #endif /* SHOPT_MULTIBYTE */
2273*b30d1939SAndy Fiddaman 	if(mode=='?' && (i=curline_search(vp,((char*)virtual)+1))>=0)
2274*b30d1939SAndy Fiddaman 	{
2275*b30d1939SAndy Fiddaman 		location.hist_command = curhline;
2276*b30d1939SAndy Fiddaman 		location.hist_char = i;
2277*b30d1939SAndy Fiddaman 	}
2278*b30d1939SAndy Fiddaman 	else
2279*b30d1939SAndy Fiddaman 	{
2280*b30d1939SAndy Fiddaman 		i = INVALID;
2281*b30d1939SAndy Fiddaman 		if( new_direction==1 && curhline >= histmax )
2282*b30d1939SAndy Fiddaman 			curhline = histmin + 1;
2283*b30d1939SAndy Fiddaman 		location = hist_find(shgd->hist_ptr,((char*)virtual)+1, curhline, 1, new_direction);
2284*b30d1939SAndy Fiddaman 	}
2285*b30d1939SAndy Fiddaman 	cur_virt = i;
2286*b30d1939SAndy Fiddaman 	strncpy(lsearch, ((char*)virtual)+1, SEARCHSIZE);
2287*b30d1939SAndy Fiddaman 	lsearch[SEARCHSIZE-1] = 0;
2288*b30d1939SAndy Fiddaman 	if( (curhline=location.hist_command) >=0 )
2289*b30d1939SAndy Fiddaman 	{
2290*b30d1939SAndy Fiddaman 		vp->ocur_virt = INVALID;
2291*b30d1939SAndy Fiddaman 		return(GOOD);
2292*b30d1939SAndy Fiddaman 	}
2293*b30d1939SAndy Fiddaman 
2294*b30d1939SAndy Fiddaman 	/*** could not find matching line ***/
2295*b30d1939SAndy Fiddaman 
2296*b30d1939SAndy Fiddaman 	curhline = oldcurhline;
2297*b30d1939SAndy Fiddaman 	return(BAD);
2298*b30d1939SAndy Fiddaman }
2299*b30d1939SAndy Fiddaman 
2300*b30d1939SAndy Fiddaman /*{	SYNC_CURSOR()
2301*b30d1939SAndy Fiddaman  *
2302*b30d1939SAndy Fiddaman  *	This routine will move the physical cursor to the same
2303*b30d1939SAndy Fiddaman  * column as the virtual cursor.
2304*b30d1939SAndy Fiddaman  *
2305*b30d1939SAndy Fiddaman }*/
2306*b30d1939SAndy Fiddaman 
sync_cursor(register Vi_t * vp)2307*b30d1939SAndy Fiddaman static void sync_cursor(register Vi_t *vp)
2308*b30d1939SAndy Fiddaman {
2309*b30d1939SAndy Fiddaman 	register int p;
2310*b30d1939SAndy Fiddaman 	register int v;
2311*b30d1939SAndy Fiddaman 	register int c;
2312*b30d1939SAndy Fiddaman 	int new_phys;
2313*b30d1939SAndy Fiddaman 
2314*b30d1939SAndy Fiddaman 	if( cur_virt == INVALID )
2315*b30d1939SAndy Fiddaman 		return;
2316*b30d1939SAndy Fiddaman 
2317*b30d1939SAndy Fiddaman 	/*** find physical col that corresponds to virtual col ***/
2318*b30d1939SAndy Fiddaman 
2319*b30d1939SAndy Fiddaman 	new_phys = 0;
2320*b30d1939SAndy Fiddaman 	if(vp->first_wind==vp->ofirst_wind && cur_virt>vp->ocur_virt && vp->ocur_virt!=INVALID)
2321*b30d1939SAndy Fiddaman 	{
2322*b30d1939SAndy Fiddaman 		/*** try to optimize search a little ***/
2323*b30d1939SAndy Fiddaman 		p = vp->ocur_phys + 1;
2324*b30d1939SAndy Fiddaman #if SHOPT_MULTIBYTE
2325*b30d1939SAndy Fiddaman 		while(physical[p]==MARKER)
2326*b30d1939SAndy Fiddaman 			p++;
2327*b30d1939SAndy Fiddaman #endif /* SHOPT_MULTIBYTE */
2328*b30d1939SAndy Fiddaman 		v = vp->ocur_virt + 1;
2329*b30d1939SAndy Fiddaman 	}
2330*b30d1939SAndy Fiddaman 	else
2331*b30d1939SAndy Fiddaman 	{
2332*b30d1939SAndy Fiddaman 		p = 0;
2333*b30d1939SAndy Fiddaman 		v = 0;
2334*b30d1939SAndy Fiddaman 	}
2335*b30d1939SAndy Fiddaman 	for(; v <= last_virt; ++p, ++v)
2336*b30d1939SAndy Fiddaman 	{
2337*b30d1939SAndy Fiddaman #if SHOPT_MULTIBYTE
2338*b30d1939SAndy Fiddaman 		int d;
2339*b30d1939SAndy Fiddaman 		c = virtual[v];
2340*b30d1939SAndy Fiddaman 		if((d = mbwidth(c)) > 1)
2341*b30d1939SAndy Fiddaman 		{
2342*b30d1939SAndy Fiddaman 			if( v != cur_virt )
2343*b30d1939SAndy Fiddaman 				p += (d-1);
2344*b30d1939SAndy Fiddaman 		}
2345*b30d1939SAndy Fiddaman 		else if(!iswprint(c))
2346*b30d1939SAndy Fiddaman #else
2347*b30d1939SAndy Fiddaman 		c = virtual[v];
2348*b30d1939SAndy Fiddaman 		if(!isprint(c))
2349*b30d1939SAndy Fiddaman #endif	/* SHOPT_MULTIBYTE */
2350*b30d1939SAndy Fiddaman 		{
2351*b30d1939SAndy Fiddaman 			if( c == '\t' )
2352*b30d1939SAndy Fiddaman 			{
2353*b30d1939SAndy Fiddaman 				p -= ((p+editb.e_plen)%TABSIZE);
2354*b30d1939SAndy Fiddaman 				p += (TABSIZE-1);
2355*b30d1939SAndy Fiddaman 			}
2356*b30d1939SAndy Fiddaman 			else
2357*b30d1939SAndy Fiddaman 			{
2358*b30d1939SAndy Fiddaman 				++p;
2359*b30d1939SAndy Fiddaman 			}
2360*b30d1939SAndy Fiddaman 		}
2361*b30d1939SAndy Fiddaman 		if( v == cur_virt )
2362*b30d1939SAndy Fiddaman 		{
2363*b30d1939SAndy Fiddaman 			new_phys = p;
2364*b30d1939SAndy Fiddaman 			break;
2365*b30d1939SAndy Fiddaman 		}
2366*b30d1939SAndy Fiddaman 	}
2367*b30d1939SAndy Fiddaman 
2368*b30d1939SAndy Fiddaman 	if( new_phys < vp->first_wind || new_phys >= vp->first_wind + w_size )
2369*b30d1939SAndy Fiddaman 	{
2370*b30d1939SAndy Fiddaman 		/*** asked to move outside of window ***/
2371*b30d1939SAndy Fiddaman 
2372*b30d1939SAndy Fiddaman 		window[0] = '\0';
2373*b30d1939SAndy Fiddaman 		refresh(vp,CONTROL);
2374*b30d1939SAndy Fiddaman 		return;
2375*b30d1939SAndy Fiddaman 	}
2376*b30d1939SAndy Fiddaman 
2377*b30d1939SAndy Fiddaman 	cursor(vp,new_phys);
2378*b30d1939SAndy Fiddaman 	ed_flush(vp->ed);
2379*b30d1939SAndy Fiddaman 	vp->ocur_phys = cur_phys;
2380*b30d1939SAndy Fiddaman 	vp->ocur_virt = cur_virt;
2381*b30d1939SAndy Fiddaman 	vp->o_v_char = virtual[vp->ocur_virt];
2382*b30d1939SAndy Fiddaman 
2383*b30d1939SAndy Fiddaman 	return;
2384*b30d1939SAndy Fiddaman }
2385*b30d1939SAndy Fiddaman 
2386*b30d1939SAndy Fiddaman /*{	TEXTMOD( command, mode )
2387*b30d1939SAndy Fiddaman  *
2388*b30d1939SAndy Fiddaman  *	Modify text operations.
2389*b30d1939SAndy Fiddaman  *
2390*b30d1939SAndy Fiddaman  *	mode != 0, repeat previous operation
2391*b30d1939SAndy Fiddaman  *
2392*b30d1939SAndy Fiddaman }*/
2393*b30d1939SAndy Fiddaman 
textmod(register Vi_t * vp,register int c,int mode)2394*b30d1939SAndy Fiddaman static int textmod(register Vi_t *vp,register int c, int mode)
2395*b30d1939SAndy Fiddaman {
2396*b30d1939SAndy Fiddaman 	register int i;
2397*b30d1939SAndy Fiddaman 	register genchar *p = vp->lastline;
2398*b30d1939SAndy Fiddaman 	register int trepeat = vp->repeat;
2399*b30d1939SAndy Fiddaman 	genchar *savep;
2400*b30d1939SAndy Fiddaman 
2401*b30d1939SAndy Fiddaman 	if(mode && (fold(vp->lastmotion)=='F' || fold(vp->lastmotion)=='T'))
2402*b30d1939SAndy Fiddaman 		vp->lastmotion = ';';
2403*b30d1939SAndy Fiddaman 
2404*b30d1939SAndy Fiddaman 	if( fold(c) == 'P' )
2405*b30d1939SAndy Fiddaman 	{
2406*b30d1939SAndy Fiddaman 		/*** change p from lastline to yankbuf ***/
2407*b30d1939SAndy Fiddaman 		p = yankbuf;
2408*b30d1939SAndy Fiddaman 	}
2409*b30d1939SAndy Fiddaman 
2410*b30d1939SAndy Fiddaman addin:
2411*b30d1939SAndy Fiddaman 	switch( c )
2412*b30d1939SAndy Fiddaman 	{
2413*b30d1939SAndy Fiddaman 			/***** Input commands *****/
2414*b30d1939SAndy Fiddaman 
2415*b30d1939SAndy Fiddaman #if KSHELL
2416*b30d1939SAndy Fiddaman         case '\t':
2417*b30d1939SAndy Fiddaman 		if(vp->ed->e_tabcount!=1)
2418*b30d1939SAndy Fiddaman 			return(BAD);
2419*b30d1939SAndy Fiddaman 		c = '=';
2420*b30d1939SAndy Fiddaman 		/* FALLTHROUGH */
2421*b30d1939SAndy Fiddaman 	case '*':		/** do file name expansion in place **/
2422*b30d1939SAndy Fiddaman 	case '\\':		/** do file name completion in place **/
2423*b30d1939SAndy Fiddaman 		if( cur_virt == INVALID )
2424*b30d1939SAndy Fiddaman 			return(BAD);
2425*b30d1939SAndy Fiddaman 		/* FALLTHROUGH */
2426*b30d1939SAndy Fiddaman 	case '=':		/** list file name expansions **/
2427*b30d1939SAndy Fiddaman 		save_v(vp);
2428*b30d1939SAndy Fiddaman 		i = last_virt;
2429*b30d1939SAndy Fiddaman 		++last_virt;
2430*b30d1939SAndy Fiddaman 		mode = cur_virt-1;
2431*b30d1939SAndy Fiddaman 		virtual[last_virt] = 0;
2432*b30d1939SAndy Fiddaman 		if(ed_expand(vp->ed,(char*)virtual, &cur_virt, &last_virt, c, vp->repeat_set?vp->repeat:-1)<0)
2433*b30d1939SAndy Fiddaman 		{
2434*b30d1939SAndy Fiddaman 			if(vp->ed->e_tabcount)
2435*b30d1939SAndy Fiddaman 			{
2436*b30d1939SAndy Fiddaman 				vp->ed->e_tabcount=2;
2437*b30d1939SAndy Fiddaman 				ed_ungetchar(vp->ed,'\t');
2438*b30d1939SAndy Fiddaman 				--last_virt;
2439*b30d1939SAndy Fiddaman 				return(APPEND);
2440*b30d1939SAndy Fiddaman 			}
2441*b30d1939SAndy Fiddaman 			last_virt = i;
2442*b30d1939SAndy Fiddaman 			ed_ringbell();
2443*b30d1939SAndy Fiddaman 		}
2444*b30d1939SAndy Fiddaman 		else if((c=='=' || (c=='\\'&&virtual[i]=='/')) && !vp->repeat_set)
2445*b30d1939SAndy Fiddaman 		{
2446*b30d1939SAndy Fiddaman 			last_virt = i;
2447*b30d1939SAndy Fiddaman 			vp->nonewline++;
2448*b30d1939SAndy Fiddaman 			ed_ungetchar(vp->ed,cntl('L'));
2449*b30d1939SAndy Fiddaman 			return(GOOD);
2450*b30d1939SAndy Fiddaman 		}
2451*b30d1939SAndy Fiddaman 		else
2452*b30d1939SAndy Fiddaman 		{
2453*b30d1939SAndy Fiddaman 			--cur_virt;
2454*b30d1939SAndy Fiddaman 			--last_virt;
2455*b30d1939SAndy Fiddaman 			vp->ocur_virt = MAXCHAR;
2456*b30d1939SAndy Fiddaman 			if(c=='=' || (mode<cur_virt && (virtual[cur_virt]==' ' || virtual[cur_virt]=='/')))
2457*b30d1939SAndy Fiddaman 				vp->ed->e_tabcount = 0;
2458*b30d1939SAndy Fiddaman 			return(APPEND);
2459*b30d1939SAndy Fiddaman 		}
2460*b30d1939SAndy Fiddaman 		break;
2461*b30d1939SAndy Fiddaman 
2462*b30d1939SAndy Fiddaman 	case '@':		/** macro expansion **/
2463*b30d1939SAndy Fiddaman 		if( mode )
2464*b30d1939SAndy Fiddaman 			c = vp->lastmacro;
2465*b30d1939SAndy Fiddaman 		else
2466*b30d1939SAndy Fiddaman 			if((c=getrchar(vp))==ESC)
2467*b30d1939SAndy Fiddaman 				return(GOOD);
2468*b30d1939SAndy Fiddaman 		if(!inmacro)
2469*b30d1939SAndy Fiddaman 			vp->lastmacro = c;
2470*b30d1939SAndy Fiddaman 		if(ed_macro(vp->ed,c))
2471*b30d1939SAndy Fiddaman 		{
2472*b30d1939SAndy Fiddaman 			save_v(vp);
2473*b30d1939SAndy Fiddaman 			inmacro++;
2474*b30d1939SAndy Fiddaman 			return(GOOD);
2475*b30d1939SAndy Fiddaman 		}
2476*b30d1939SAndy Fiddaman 		ed_ringbell();
2477*b30d1939SAndy Fiddaman 		return(BAD);
2478*b30d1939SAndy Fiddaman 
2479*b30d1939SAndy Fiddaman #endif	/* KSHELL */
2480*b30d1939SAndy Fiddaman 	case '_':		/** append last argument of prev command **/
2481*b30d1939SAndy Fiddaman 		save_v(vp);
2482*b30d1939SAndy Fiddaman 		{
2483*b30d1939SAndy Fiddaman 			genchar tmpbuf[MAXLINE];
2484*b30d1939SAndy Fiddaman 			if(vp->repeat_set==0)
2485*b30d1939SAndy Fiddaman 				vp->repeat = -1;
2486*b30d1939SAndy Fiddaman 			p = (genchar*)hist_word((char*)tmpbuf,MAXLINE,vp->repeat);
2487*b30d1939SAndy Fiddaman 			if(p==0)
2488*b30d1939SAndy Fiddaman 			{
2489*b30d1939SAndy Fiddaman 				ed_ringbell();
2490*b30d1939SAndy Fiddaman 				break;
2491*b30d1939SAndy Fiddaman 			}
2492*b30d1939SAndy Fiddaman #if SHOPT_MULTIBYTE
2493*b30d1939SAndy Fiddaman 			ed_internal((char*)p,tmpbuf);
2494*b30d1939SAndy Fiddaman 			p = tmpbuf;
2495*b30d1939SAndy Fiddaman #endif /* SHOPT_MULTIBYTE */
2496*b30d1939SAndy Fiddaman 			i = ' ';
2497*b30d1939SAndy Fiddaman 			do
2498*b30d1939SAndy Fiddaman 			{
2499*b30d1939SAndy Fiddaman 				append(vp,i,APPEND);
2500*b30d1939SAndy Fiddaman 			}
2501*b30d1939SAndy Fiddaman 			while(i = *p++);
2502*b30d1939SAndy Fiddaman 			return(APPEND);
2503*b30d1939SAndy Fiddaman 		}
2504*b30d1939SAndy Fiddaman 
2505*b30d1939SAndy Fiddaman 	case 'A':		/** append to end of line **/
2506*b30d1939SAndy Fiddaman 		cur_virt = last_virt;
2507*b30d1939SAndy Fiddaman 		sync_cursor(vp);
2508*b30d1939SAndy Fiddaman 		/* FALLTHROUGH */
2509*b30d1939SAndy Fiddaman 
2510*b30d1939SAndy Fiddaman 	case 'a':		/** append **/
2511*b30d1939SAndy Fiddaman 		if( fold(mode) == 'A' )
2512*b30d1939SAndy Fiddaman 		{
2513*b30d1939SAndy Fiddaman 			c = 'p';
2514*b30d1939SAndy Fiddaman 			goto addin;
2515*b30d1939SAndy Fiddaman 		}
2516*b30d1939SAndy Fiddaman 		save_v(vp);
2517*b30d1939SAndy Fiddaman 		if( cur_virt != INVALID )
2518*b30d1939SAndy Fiddaman 		{
2519*b30d1939SAndy Fiddaman 			first_virt = cur_virt + 1;
2520*b30d1939SAndy Fiddaman 			cursor(vp,cur_phys + 1);
2521*b30d1939SAndy Fiddaman 			ed_flush(vp->ed);
2522*b30d1939SAndy Fiddaman 		}
2523*b30d1939SAndy Fiddaman 		return(APPEND);
2524*b30d1939SAndy Fiddaman 
2525*b30d1939SAndy Fiddaman 	case 'I':		/** insert at beginning of line **/
2526*b30d1939SAndy Fiddaman 		cur_virt = first_virt;
2527*b30d1939SAndy Fiddaman 		sync_cursor(vp);
2528*b30d1939SAndy Fiddaman 		/* FALLTHROUGH */
2529*b30d1939SAndy Fiddaman 
2530*b30d1939SAndy Fiddaman 	case 'i':		/** insert **/
2531*b30d1939SAndy Fiddaman 		if( fold(mode) == 'I' )
2532*b30d1939SAndy Fiddaman 		{
2533*b30d1939SAndy Fiddaman 			c = 'P';
2534*b30d1939SAndy Fiddaman 			goto addin;
2535*b30d1939SAndy Fiddaman 		}
2536*b30d1939SAndy Fiddaman 		save_v(vp);
2537*b30d1939SAndy Fiddaman 		if( cur_virt != INVALID )
2538*b30d1939SAndy Fiddaman  		{
2539*b30d1939SAndy Fiddaman  			vp->o_v_char = virtual[cur_virt];
2540*b30d1939SAndy Fiddaman 			first_virt = cur_virt--;
2541*b30d1939SAndy Fiddaman   		}
2542*b30d1939SAndy Fiddaman 		return(INSERT);
2543*b30d1939SAndy Fiddaman 
2544*b30d1939SAndy Fiddaman 	case 'C':		/** change to eol **/
2545*b30d1939SAndy Fiddaman 		c = '$';
2546*b30d1939SAndy Fiddaman 		goto chgeol;
2547*b30d1939SAndy Fiddaman 
2548*b30d1939SAndy Fiddaman 	case 'c':		/** change **/
2549*b30d1939SAndy Fiddaman 		if( mode )
2550*b30d1939SAndy Fiddaman 			c = vp->lastmotion;
2551*b30d1939SAndy Fiddaman 		else
2552*b30d1939SAndy Fiddaman 			c = getcount(vp,ed_getchar(vp->ed,-1));
2553*b30d1939SAndy Fiddaman chgeol:
2554*b30d1939SAndy Fiddaman 		vp->lastmotion = c;
2555*b30d1939SAndy Fiddaman 		if( c == 'c' )
2556*b30d1939SAndy Fiddaman 		{
2557*b30d1939SAndy Fiddaman 			del_line(vp,GOOD);
2558*b30d1939SAndy Fiddaman 			return(APPEND);
2559*b30d1939SAndy Fiddaman 		}
2560*b30d1939SAndy Fiddaman 
2561*b30d1939SAndy Fiddaman 		if(!delmotion(vp, c, 'c'))
2562*b30d1939SAndy Fiddaman 			return(BAD);
2563*b30d1939SAndy Fiddaman 
2564*b30d1939SAndy Fiddaman 		if( mode == 'c' )
2565*b30d1939SAndy Fiddaman 		{
2566*b30d1939SAndy Fiddaman 			c = 'p';
2567*b30d1939SAndy Fiddaman 			trepeat = 1;
2568*b30d1939SAndy Fiddaman 			goto addin;
2569*b30d1939SAndy Fiddaman 		}
2570*b30d1939SAndy Fiddaman 		first_virt = cur_virt + 1;
2571*b30d1939SAndy Fiddaman 		return(APPEND);
2572*b30d1939SAndy Fiddaman 
2573*b30d1939SAndy Fiddaman 	case 'D':		/** delete to eol **/
2574*b30d1939SAndy Fiddaman 		c = '$';
2575*b30d1939SAndy Fiddaman 		goto deleol;
2576*b30d1939SAndy Fiddaman 
2577*b30d1939SAndy Fiddaman 	case 'd':		/** delete **/
2578*b30d1939SAndy Fiddaman 		if( mode )
2579*b30d1939SAndy Fiddaman 			c = vp->lastmotion;
2580*b30d1939SAndy Fiddaman 		else
2581*b30d1939SAndy Fiddaman 			c = getcount(vp,ed_getchar(vp->ed,-1));
2582*b30d1939SAndy Fiddaman deleol:
2583*b30d1939SAndy Fiddaman 		vp->lastmotion = c;
2584*b30d1939SAndy Fiddaman 		if( c == 'd' )
2585*b30d1939SAndy Fiddaman 		{
2586*b30d1939SAndy Fiddaman 			del_line(vp,GOOD);
2587*b30d1939SAndy Fiddaman 			break;
2588*b30d1939SAndy Fiddaman 		}
2589*b30d1939SAndy Fiddaman 		if(!delmotion(vp, c, 'd'))
2590*b30d1939SAndy Fiddaman 			return(BAD);
2591*b30d1939SAndy Fiddaman 		if( cur_virt < last_virt )
2592*b30d1939SAndy Fiddaman 			++cur_virt;
2593*b30d1939SAndy Fiddaman 		break;
2594*b30d1939SAndy Fiddaman 
2595*b30d1939SAndy Fiddaman 	case 'P':
2596*b30d1939SAndy Fiddaman 		if( p[0] == '\0' )
2597*b30d1939SAndy Fiddaman 			return(BAD);
2598*b30d1939SAndy Fiddaman 		if( cur_virt != INVALID )
2599*b30d1939SAndy Fiddaman 		{
2600*b30d1939SAndy Fiddaman 			i = virtual[cur_virt];
2601*b30d1939SAndy Fiddaman 			if(!is_print(i))
2602*b30d1939SAndy Fiddaman 				vp->ocur_virt = INVALID;
2603*b30d1939SAndy Fiddaman 			--cur_virt;
2604*b30d1939SAndy Fiddaman 		}
2605*b30d1939SAndy Fiddaman 		/* FALLTHROUGH */
2606*b30d1939SAndy Fiddaman 
2607*b30d1939SAndy Fiddaman 	case 'p':		/** print **/
2608*b30d1939SAndy Fiddaman 		if( p[0] == '\0' )
2609*b30d1939SAndy Fiddaman 			return(BAD);
2610*b30d1939SAndy Fiddaman 
2611*b30d1939SAndy Fiddaman 		if( mode != 's' && mode != 'c' )
2612*b30d1939SAndy Fiddaman 		{
2613*b30d1939SAndy Fiddaman 			save_v(vp);
2614*b30d1939SAndy Fiddaman 			if( c == 'P' )
2615*b30d1939SAndy Fiddaman 			{
2616*b30d1939SAndy Fiddaman 				/*** fix stored cur_virt ***/
2617*b30d1939SAndy Fiddaman 				++vp->u_column;
2618*b30d1939SAndy Fiddaman 			}
2619*b30d1939SAndy Fiddaman 		}
2620*b30d1939SAndy Fiddaman 		if( mode == 'R' )
2621*b30d1939SAndy Fiddaman 			mode = REPLACE;
2622*b30d1939SAndy Fiddaman 		else
2623*b30d1939SAndy Fiddaman 			mode = APPEND;
2624*b30d1939SAndy Fiddaman 		savep = p;
2625*b30d1939SAndy Fiddaman 		for(i=0; i<trepeat; ++i)
2626*b30d1939SAndy Fiddaman 		{
2627*b30d1939SAndy Fiddaman 			while(c= *p++)
2628*b30d1939SAndy Fiddaman 				append(vp,c,mode);
2629*b30d1939SAndy Fiddaman 			p = savep;
2630*b30d1939SAndy Fiddaman 		}
2631*b30d1939SAndy Fiddaman 		break;
2632*b30d1939SAndy Fiddaman 
2633*b30d1939SAndy Fiddaman 	case 'R':		/* Replace many chars **/
2634*b30d1939SAndy Fiddaman 		if( mode == 'R' )
2635*b30d1939SAndy Fiddaman 		{
2636*b30d1939SAndy Fiddaman 			c = 'P';
2637*b30d1939SAndy Fiddaman 			goto addin;
2638*b30d1939SAndy Fiddaman 		}
2639*b30d1939SAndy Fiddaman 		save_v(vp);
2640*b30d1939SAndy Fiddaman 		if( cur_virt != INVALID )
2641*b30d1939SAndy Fiddaman 			first_virt = cur_virt;
2642*b30d1939SAndy Fiddaman 		return(REPLACE);
2643*b30d1939SAndy Fiddaman 
2644*b30d1939SAndy Fiddaman 	case 'r':		/** replace **/
2645*b30d1939SAndy Fiddaman 		if( mode )
2646*b30d1939SAndy Fiddaman 			c = *p;
2647*b30d1939SAndy Fiddaman 		else
2648*b30d1939SAndy Fiddaman 			if((c=getrchar(vp))==ESC)
2649*b30d1939SAndy Fiddaman 				return(GOOD);
2650*b30d1939SAndy Fiddaman 		*p = c;
2651*b30d1939SAndy Fiddaman 		save_v(vp);
2652*b30d1939SAndy Fiddaman 		while(trepeat--)
2653*b30d1939SAndy Fiddaman 			replace(vp,c, trepeat!=0);
2654*b30d1939SAndy Fiddaman 		return(GOOD);
2655*b30d1939SAndy Fiddaman 
2656*b30d1939SAndy Fiddaman 	case 'S':		/** Substitute line - cc **/
2657*b30d1939SAndy Fiddaman 		c = 'c';
2658*b30d1939SAndy Fiddaman 		goto chgeol;
2659*b30d1939SAndy Fiddaman 
2660*b30d1939SAndy Fiddaman 	case 's':		/** substitute **/
2661*b30d1939SAndy Fiddaman 		save_v(vp);
2662*b30d1939SAndy Fiddaman 		cdelete(vp,vp->repeat, BAD);
2663*b30d1939SAndy Fiddaman 		if( mode )
2664*b30d1939SAndy Fiddaman 		{
2665*b30d1939SAndy Fiddaman 			c = 'p';
2666*b30d1939SAndy Fiddaman 			trepeat = 1;
2667*b30d1939SAndy Fiddaman 			goto addin;
2668*b30d1939SAndy Fiddaman 		}
2669*b30d1939SAndy Fiddaman 		first_virt = cur_virt + 1;
2670*b30d1939SAndy Fiddaman 		return(APPEND);
2671*b30d1939SAndy Fiddaman 
2672*b30d1939SAndy Fiddaman 	case 'Y':		/** Yank to end of line **/
2673*b30d1939SAndy Fiddaman 		c = '$';
2674*b30d1939SAndy Fiddaman 		goto yankeol;
2675*b30d1939SAndy Fiddaman 
2676*b30d1939SAndy Fiddaman 	case 'y':		/** yank thru motion **/
2677*b30d1939SAndy Fiddaman 		if( mode )
2678*b30d1939SAndy Fiddaman 			c = vp->lastmotion;
2679*b30d1939SAndy Fiddaman 		else
2680*b30d1939SAndy Fiddaman 			c = getcount(vp,ed_getchar(vp->ed,-1));
2681*b30d1939SAndy Fiddaman yankeol:
2682*b30d1939SAndy Fiddaman 		vp->lastmotion = c;
2683*b30d1939SAndy Fiddaman 		if( c == 'y' )
2684*b30d1939SAndy Fiddaman 		{
2685*b30d1939SAndy Fiddaman 			gencpy(yankbuf, virtual);
2686*b30d1939SAndy Fiddaman 		}
2687*b30d1939SAndy Fiddaman 		else if(!delmotion(vp, c, 'y'))
2688*b30d1939SAndy Fiddaman 		{
2689*b30d1939SAndy Fiddaman 			return(BAD);
2690*b30d1939SAndy Fiddaman 		}
2691*b30d1939SAndy Fiddaman 		break;
2692*b30d1939SAndy Fiddaman 
2693*b30d1939SAndy Fiddaman 	case 'x':		/** delete repeat chars forward - dl **/
2694*b30d1939SAndy Fiddaman 		c = 'l';
2695*b30d1939SAndy Fiddaman 		goto deleol;
2696*b30d1939SAndy Fiddaman 
2697*b30d1939SAndy Fiddaman 	case 'X':		/** delete repeat chars backward - dh **/
2698*b30d1939SAndy Fiddaman 		c = 'h';
2699*b30d1939SAndy Fiddaman 		goto deleol;
2700*b30d1939SAndy Fiddaman 
2701*b30d1939SAndy Fiddaman 	case '~':		/** invert case and advance **/
2702*b30d1939SAndy Fiddaman 		if( cur_virt != INVALID )
2703*b30d1939SAndy Fiddaman 		{
2704*b30d1939SAndy Fiddaman 			save_v(vp);
2705*b30d1939SAndy Fiddaman 			i = INVALID;
2706*b30d1939SAndy Fiddaman 			while(trepeat-->0 && i!=cur_virt)
2707*b30d1939SAndy Fiddaman 			{
2708*b30d1939SAndy Fiddaman 				i = cur_virt;
2709*b30d1939SAndy Fiddaman 				c = virtual[cur_virt];
2710*b30d1939SAndy Fiddaman #if SHOPT_MULTIBYTE
2711*b30d1939SAndy Fiddaman 				if((c&~STRIP)==0)
2712*b30d1939SAndy Fiddaman #endif /* SHOPT_MULTIBYTE */
2713*b30d1939SAndy Fiddaman 				if( isupper(c) )
2714*b30d1939SAndy Fiddaman 					c = tolower(c);
2715*b30d1939SAndy Fiddaman 				else if( islower(c) )
2716*b30d1939SAndy Fiddaman 					c = toupper(c);
2717*b30d1939SAndy Fiddaman 				replace(vp,c, 1);
2718*b30d1939SAndy Fiddaman 			}
2719*b30d1939SAndy Fiddaman 			return(GOOD);
2720*b30d1939SAndy Fiddaman 		}
2721*b30d1939SAndy Fiddaman 		else
2722*b30d1939SAndy Fiddaman 			return(BAD);
2723*b30d1939SAndy Fiddaman 
2724*b30d1939SAndy Fiddaman 	default:
2725*b30d1939SAndy Fiddaman 		return(BAD);
2726*b30d1939SAndy Fiddaman 	}
2727*b30d1939SAndy Fiddaman 	refresh(vp,CONTROL);
2728*b30d1939SAndy Fiddaman 	return(GOOD);
2729*b30d1939SAndy Fiddaman }
2730*b30d1939SAndy Fiddaman 
2731*b30d1939SAndy Fiddaman 
2732*b30d1939SAndy Fiddaman #if SHOPT_MULTIBYTE
_isalph(register int v)2733*b30d1939SAndy Fiddaman     static int _isalph(register int v)
2734*b30d1939SAndy Fiddaman     {
2735*b30d1939SAndy Fiddaman #ifdef _lib_iswalnum
2736*b30d1939SAndy Fiddaman 	return(iswalnum(v) || v=='_');
2737*b30d1939SAndy Fiddaman #else
2738*b30d1939SAndy Fiddaman 	return((v&~STRIP) || isalnum(v) || v=='_');
2739*b30d1939SAndy Fiddaman #endif
2740*b30d1939SAndy Fiddaman     }
2741*b30d1939SAndy Fiddaman 
2742*b30d1939SAndy Fiddaman 
_isblank(register int v)2743*b30d1939SAndy Fiddaman     static int _isblank(register int v)
2744*b30d1939SAndy Fiddaman     {
2745*b30d1939SAndy Fiddaman 	return((v&~STRIP)==0 && isspace(v));
2746*b30d1939SAndy Fiddaman     }
2747*b30d1939SAndy Fiddaman 
_ismetach(register int v)2748*b30d1939SAndy Fiddaman     static int _ismetach(register int v)
2749*b30d1939SAndy Fiddaman     {
2750*b30d1939SAndy Fiddaman 	return((v&~STRIP)==0 && ismeta(v));
2751*b30d1939SAndy Fiddaman     }
2752*b30d1939SAndy Fiddaman 
2753*b30d1939SAndy Fiddaman #endif	/* SHOPT_MULTIBYTE */
2754*b30d1939SAndy Fiddaman 
2755*b30d1939SAndy Fiddaman /*
2756*b30d1939SAndy Fiddaman  * get a character, after ^V processing
2757*b30d1939SAndy Fiddaman  */
getrchar(register Vi_t * vp)2758*b30d1939SAndy Fiddaman static int getrchar(register Vi_t *vp)
2759*b30d1939SAndy Fiddaman {
2760*b30d1939SAndy Fiddaman 	register int c;
2761*b30d1939SAndy Fiddaman 	if((c=ed_getchar(vp->ed,1))== usrlnext)
2762*b30d1939SAndy Fiddaman 		c = ed_getchar(vp->ed,2);
2763*b30d1939SAndy Fiddaman 	return(c);
2764*b30d1939SAndy Fiddaman }
2765