xref: /csrg-svn/local/toolchest/ksh/sh/edit.c (revision 35136)
1*35136Smarc /* @(#)edit.c	1.1 */
2*35136Smarc 
3*35136Smarc /*
4*35136Smarc  *  edit.c - common routines for vi and emacs one line editors in shell
5*35136Smarc  *
6*35136Smarc  *   David Korn				P.D. Sullivan
7*35136Smarc  *   AT&T Bell Laboratories		AT&T Bell Laboratories
8*35136Smarc  *   Room 5D-112			Room 1E253
9*35136Smarc  *   Murray Hill, N. J. 07974		Columbus, OH 43213
10*35136Smarc  *   Tel. x7975				Tel. x 2655
11*35136Smarc  *
12*35136Smarc  *   Coded April 1983.
13*35136Smarc  */
14*35136Smarc 
15*35136Smarc #include	<errno.h>
16*35136Smarc 
17*35136Smarc #ifdef KSHELL
18*35136Smarc #include	"shtype.h"
19*35136Smarc #include	"flags.h"
20*35136Smarc #include	"defs.h"
21*35136Smarc #include	"io.h"
22*35136Smarc #include	"name.h"
23*35136Smarc #include	"sym.h"
24*35136Smarc #include	"stak.h"
25*35136Smarc #include	"mode.h"
26*35136Smarc #include	"builtins.h"
27*35136Smarc #include	"brkincr.h"
28*35136Smarc 
29*35136Smarc #else
30*35136Smarc #include	<stdio.h>
31*35136Smarc #include	<signal.h>
32*35136Smarc #include	<setjmp.h>
33*35136Smarc #include	<ctype.h>
34*35136Smarc #endif	/* KSHELL */
35*35136Smarc 
36*35136Smarc #include	"history.h"
37*35136Smarc #include	"edit.h"
38*35136Smarc 
39*35136Smarc #define BAD	-1
40*35136Smarc #define GOOD	0
41*35136Smarc #define	TRUE	(-1)
42*35136Smarc #define	FALSE	0
43*35136Smarc #define	SYSERR	-1
44*35136Smarc 
45*35136Smarc #ifdef VENIX
46*35136Smarc #define RT 1
47*35136Smarc #endif	/* VENIX */
48*35136Smarc 
49*35136Smarc void	e_crlf();
50*35136Smarc void	e_flush();
51*35136Smarc int	e_getchar();
52*35136Smarc void	e_putchar();
53*35136Smarc void	e_ringbell();
54*35136Smarc void	e_setup();
55*35136Smarc int	e_virt_to_phys();
56*35136Smarc int	e_window();
57*35136Smarc void	setcooked();
58*35136Smarc void	ungetchar();
59*35136Smarc 
60*35136Smarc #if BSD || RT
61*35136Smarc #include	<sgtty.h>
62*35136Smarc # ifdef BSD_4_2
63*35136Smarc # include	<sys/time.h>
64*35136Smarc # endif /* BSD_4_2 */
65*35136Smarc static struct sgttyb ttyparm;		/* initial tty parameters */
66*35136Smarc static struct sgttyb nttyparm;		/* raw tty parameters */
67*35136Smarc # ifdef BSD
68*35136Smarc extern int tty_speeds[];
69*35136Smarc static int delay;
70*35136Smarc static int l_mask;
71*35136Smarc static struct tchars l_ttychars;
72*35136Smarc static struct ltchars l_chars;
73*35136Smarc static  char  l_changed;	/* set if mode bits changed */
74*35136Smarc #define L_CHARS	4
75*35136Smarc #define T_CHARS	2
76*35136Smarc #define L_MASK	1
77*35136Smarc # endif /* BSD */
78*35136Smarc #else
79*35136Smarc # ifdef XENIX	/* avoid symbol table overflows */
80*35136Smarc # define NCC 8
81*35136Smarc struct termio {
82*35136Smarc 	unsigned short	c_iflag;	/* input modes */
83*35136Smarc 	unsigned short	c_oflag;	/* output modes */
84*35136Smarc 	unsigned short	c_cflag;	/* control modes */
85*35136Smarc 	unsigned short	c_lflag;	/* line discipline modes */
86*35136Smarc 	char		c_line;		/* line discipline */
87*35136Smarc 	unsigned char	c_cc[NCC];	/* control chars */
88*35136Smarc 	char		c_res;		/* padding, AFTER the array */
89*35136Smarc };
90*35136Smarc #define TIOC	('T'<<8)
91*35136Smarc #define	BRKINT	0000002
92*35136Smarc #define	CBAUD	0000017
93*35136Smarc #define	ECHO	0000010
94*35136Smarc #define	ECHOE	0000020
95*35136Smarc #define	ECHOK	0000040
96*35136Smarc #define	ECHONL	0000100
97*35136Smarc #define	ICANON	0000002
98*35136Smarc #define	ICRNL	0000400
99*35136Smarc #define	IGNCR	0000200
100*35136Smarc #define	IGNPAR	0000004
101*35136Smarc #define	INLCR	0000100
102*35136Smarc #define	PARMRK	0000010
103*35136Smarc #define	TCGETA	(TIOC|1)
104*35136Smarc #define	TCSETAW	(TIOC|3)
105*35136Smarc #define	TCXONC	(TIOC|6)
106*35136Smarc #define	VEOF	4
107*35136Smarc #define	VERASE	2
108*35136Smarc #define	VKILL	3
109*35136Smarc #define	VMIN	4
110*35136Smarc #define	VTIME	5
111*35136Smarc #define TM_CECHO	0010
112*35136Smarc # else
113*35136Smarc # include	<termio.h>
114*35136Smarc # endif /* XENIX */
115*35136Smarc 
116*35136Smarc static struct termio ttyparm;		/* initial tty parameters */
117*35136Smarc static struct termio nttyparm;		/* raw tty parameters */
118*35136Smarc #endif	/* RT */
119*35136Smarc 
120*35136Smarc #define lookahead	editb.e_index
121*35136Smarc #define env		editb.e_env
122*35136Smarc #define previous	editb.e_lbuf
123*35136Smarc #define fildes		editb.e_fd
124*35136Smarc 
125*35136Smarc #ifdef KSHELL
126*35136Smarc extern struct Amemory	*alias;
127*35136Smarc extern char		**arg_build();
128*35136Smarc extern void		failed();
129*35136Smarc extern void		fault();
130*35136Smarc extern struct Namnod	*findnod();
131*35136Smarc extern int		f_complete();
132*35136Smarc extern void		gsort();
133*35136Smarc extern char		*movstr();
134*35136Smarc extern void		p_flush();
135*35136Smarc extern void		p_setout();
136*35136Smarc extern char		*simple();
137*35136Smarc extern char		*tilde();
138*35136Smarc extern char		*valup();
139*35136Smarc static char macro[]	= "_?";
140*35136Smarc 
141*35136Smarc #else
142*35136Smarc static char badcooked[]	= "cannot reset tty to cooked mode";
143*35136Smarc struct edit editb;
144*35136Smarc char trapnote;
145*35136Smarc extern char trapnote;
146*35136Smarc extern int errno;
147*35136Smarc #define p_flush()	fflush(stderr)
148*35136Smarc #define p_setout(s)	fflush(stdout)
149*35136Smarc #define error(s)	failed(s,NULL)
150*35136Smarc #define SIGSLOW 1
151*35136Smarc #define output	stderr
152*35136Smarc #endif	/* KSHELL */
153*35136Smarc 
154*35136Smarc extern char *strrchr();
155*35136Smarc extern char *strcpy();
156*35136Smarc 
157*35136Smarc static char bellchr[] = "\7";		/* bell char */
158*35136Smarc 
159*35136Smarc static int control();
160*35136Smarc /*{	SETCOOKED( fd )
161*35136Smarc  *
162*35136Smarc  *	This routine will set the tty in cooked mode.
163*35136Smarc  * It is also called by error.done().
164*35136Smarc  *
165*35136Smarc }*/
166*35136Smarc 
setcooked(fd)167*35136Smarc void setcooked(fd)
168*35136Smarc register int fd;
169*35136Smarc {
170*35136Smarc 	/*** don't do ioctl unless ttyparm has valid data ***/
171*35136Smarc 	/* or in raw mode */
172*35136Smarc 
173*35136Smarc 	if(editb.e_ttyspeed==0 || editb.e_raw==0)
174*35136Smarc 		return;
175*35136Smarc 
176*35136Smarc #ifdef BSD
177*35136Smarc 	if(editb.e_raw==RAWMODE && ioctl(fd, TIOCSETN, &ttyparm) == SYSERR )
178*35136Smarc 	{
179*35136Smarc 		if(errno!=EBADF && errno!=ENOTTY)
180*35136Smarc 			error(badcooked);
181*35136Smarc 		return;
182*35136Smarc 	}
183*35136Smarc 	/* restore flags */
184*35136Smarc 	if(l_changed&L_MASK)
185*35136Smarc 		ioctl(fd,TIOCLSET,&l_mask);
186*35136Smarc 	if(l_changed&T_CHARS)
187*35136Smarc 		/* restore alternate break character */
188*35136Smarc 		ioctl(fd,TIOCSETC,&l_ttychars);
189*35136Smarc 	if(l_changed&L_CHARS)
190*35136Smarc 		/* restore alternate break character */
191*35136Smarc 		ioctl(fd,TIOCSLTC,&l_chars);
192*35136Smarc 	l_changed = 0;
193*35136Smarc #else
194*35136Smarc # ifdef RT
195*35136Smarc 	if (stty(fd,&ttyparm) == SYSERR)
196*35136Smarc # else
197*35136Smarc 	if( editb.e_raw && control(fd, TCSETAW, &ttyparm) == SYSERR )
198*35136Smarc # endif /* RT */
199*35136Smarc 	{
200*35136Smarc 		if(errno!=EBADF && errno!=ENOTTY)
201*35136Smarc 			error(badcooked);
202*35136Smarc 		return;
203*35136Smarc 	}
204*35136Smarc #endif	/* BSD */
205*35136Smarc 	editb.e_raw = 0;
206*35136Smarc 	return;
207*35136Smarc }
208*35136Smarc 
209*35136Smarc /*{	SETRAW( fd )
210*35136Smarc  *
211*35136Smarc  *	This routine will set the tty in raw mode.
212*35136Smarc  *
213*35136Smarc }*/
214*35136Smarc 
setraw(fd)215*35136Smarc setraw(fd)
216*35136Smarc register int fd;
217*35136Smarc {
218*35136Smarc #ifdef BSD
219*35136Smarc 	struct ltchars lchars;
220*35136Smarc #endif	/* BSD */
221*35136Smarc 	if(editb.e_raw==RAWMODE)
222*35136Smarc 		return(GOOD);
223*35136Smarc 	/* characters are echoed on standard error */
224*35136Smarc 	p_setout(stderr);
225*35136Smarc #if BSD || RT
226*35136Smarc # ifdef BSD
227*35136Smarc 	if((ioctl(fd,TIOCGETP,&ttyparm) == SYSERR)
228*35136Smarc # else
229*35136Smarc 	if ((gtty(fd,&ttyparm) == SYSERR)
230*35136Smarc # endif /* BSD */
231*35136Smarc 		|| !(ttyparm.sg_flags & ECHO )
232*35136Smarc 		|| (ttyparm.sg_flags & LCASE ))
233*35136Smarc 	{
234*35136Smarc 		return(BAD);
235*35136Smarc 	}
236*35136Smarc 	nttyparm = ttyparm;
237*35136Smarc 	nttyparm.sg_flags &= ~(ECHO | TBDELAY);
238*35136Smarc # ifdef BSD
239*35136Smarc 	nttyparm.sg_flags |= CBREAK;
240*35136Smarc # else
241*35136Smarc 	nttyparm.sg_flags |= RAW;
242*35136Smarc # endif /* BSD */
243*35136Smarc 	editb.e_erase = ttyparm.sg_erase;
244*35136Smarc 	editb.e_kill = ttyparm.sg_kill;
245*35136Smarc 	editb.e_eof = cntl(D);
246*35136Smarc # ifdef BSD
247*35136Smarc 	if( ioctl(fd, TIOCSETN, &nttyparm) == SYSERR )
248*35136Smarc # else
249*35136Smarc 	if( stty(fd, &nttyparm) == SYSERR )
250*35136Smarc # endif /* BSD */
251*35136Smarc 	{
252*35136Smarc 		return(BAD);
253*35136Smarc 	}
254*35136Smarc 	editb.e_ttyspeed = (ttyparm.sg_ospeed>=B1200?FAST:SLOW);
255*35136Smarc #ifdef BSD
256*35136Smarc 	delay = tty_speeds[ttyparm.sg_ospeed];
257*35136Smarc 	/* try to remove effect of ^V  and ^Y */
258*35136Smarc 	if(ioctl(fd,TIOCGLTC,&l_chars) != SYSERR)
259*35136Smarc 	{
260*35136Smarc 		lchars = l_chars;
261*35136Smarc 		lchars.t_lnextc = -1;
262*35136Smarc 		lchars.t_dsuspc = -1;	/* no delayed stop process signal */
263*35136Smarc 		if(ioctl(fd,TIOCSLTC,&lchars) != SYSERR)
264*35136Smarc 			l_changed |= L_CHARS;
265*35136Smarc 	}
266*35136Smarc #endif	/* BSD */
267*35136Smarc #else
268*35136Smarc 
269*35136Smarc # ifndef RAWONLY
270*35136Smarc 	if(editb.e_raw != ALTMODE)
271*35136Smarc # endif /* RAWONLY */
272*35136Smarc 		if( (ioctl(fd, TCGETA, &ttyparm) == SYSERR)
273*35136Smarc 			|| (!(ttyparm.c_lflag & ECHO )))
274*35136Smarc 		{
275*35136Smarc 			return(BAD);
276*35136Smarc 		}
277*35136Smarc 
278*35136Smarc 	nttyparm = ttyparm;
279*35136Smarc #ifndef u370
280*35136Smarc 	nttyparm.c_iflag &= ~(IGNPAR|PARMRK|INLCR|IGNCR|ICRNL);
281*35136Smarc 	nttyparm.c_iflag |= BRKINT;
282*35136Smarc 	nttyparm.c_lflag &= ~(ICANON|ECHO);
283*35136Smarc #else
284*35136Smarc 	nttyparm.c_iflag &=
285*35136Smarc 			~(IGNBRK|PARMRK|INLCR|IGNCR|ICRNL|INPCK);
286*35136Smarc 	nttyparm.c_iflag |= (BRKINT|IGNPAR);
287*35136Smarc 	nttyparm.c_lflag &= ~(ICANON|ECHO);
288*35136Smarc #endif	/* u370 */
289*35136Smarc 	nttyparm.c_cc[VTIME] = 0;
290*35136Smarc 	nttyparm.c_cc[VMIN] = 1;
291*35136Smarc 	editb.e_eof = ttyparm.c_cc[VEOF];
292*35136Smarc 	editb.e_erase = ttyparm.c_cc[VERASE];
293*35136Smarc 	editb.e_kill = ttyparm.c_cc[VKILL];
294*35136Smarc #ifndef u370
295*35136Smarc 	if( control(fd, TCSETAW, &nttyparm) == SYSERR )
296*35136Smarc #else
297*35136Smarc 	/* delays are too long, don't wait for output to drain */
298*35136Smarc 	if( control(fd, TCSETA, &nttyparm) == SYSERR )
299*35136Smarc #endif	/* u370 */
300*35136Smarc 	{
301*35136Smarc 		return(BAD);
302*35136Smarc 	}
303*35136Smarc 	control(fd,TCXONC,1);
304*35136Smarc 	editb.e_ttyspeed = ttyparm.c_cflag & CBAUD;
305*35136Smarc #endif
306*35136Smarc 	editb.e_raw = RAWMODE;
307*35136Smarc 	return(GOOD);
308*35136Smarc }
309*35136Smarc 
310*35136Smarc #ifndef BSD
311*35136Smarc /*
312*35136Smarc  * give two tries for ioctl
313*35136Smarc  * interrupts are ignored
314*35136Smarc  */
315*35136Smarc 
control(fd,request,arg)316*35136Smarc static int control(fd,request,arg)
317*35136Smarc {
318*35136Smarc 	register int i;
319*35136Smarc 	register int k = 2;
320*35136Smarc 	errno = 0;
321*35136Smarc 	while(k--)
322*35136Smarc 	{
323*35136Smarc 		if((i = ioctl(fd,request,arg)) != SYSERR)
324*35136Smarc 			return(i);
325*35136Smarc 		if(errno == EINTR)
326*35136Smarc 		{
327*35136Smarc 			errno = 0;
328*35136Smarc 			k++;
329*35136Smarc 		}
330*35136Smarc 	}
331*35136Smarc 	return(SYSERR);
332*35136Smarc }
333*35136Smarc #endif	/* BSD */
334*35136Smarc #ifndef RAWONLY
335*35136Smarc 
336*35136Smarc /*	SET_TTY( fd )
337*35136Smarc  *
338*35136Smarc  *	Get tty parameters and make ESC and '\r' wakeup characters.
339*35136Smarc  *
340*35136Smarc  */
341*35136Smarc 
342*35136Smarc #ifdef BSD
setalt(fd)343*35136Smarc setalt(fd)
344*35136Smarc register int fd;
345*35136Smarc {
346*35136Smarc 	int mask;
347*35136Smarc 	struct tchars ttychars;
348*35136Smarc 	if(editb.e_raw==ALTMODE)
349*35136Smarc 		return(GOOD);
350*35136Smarc 	if(editb.e_raw==RAWMODE)
351*35136Smarc 		setcooked(fd);
352*35136Smarc 	l_changed = 0;
353*35136Smarc 	if( editb.e_ttyspeed == 0)
354*35136Smarc 	{
355*35136Smarc 		if((ioctl(fd,TIOCGETP,&ttyparm) != SYSERR))
356*35136Smarc 			editb.e_ttyspeed = (ttyparm.sg_ospeed>=B1200?FAST:SLOW);
357*35136Smarc 	}
358*35136Smarc 	if(ioctl(fd,TIOCGETC,&l_ttychars) == SYSERR)
359*35136Smarc 		return(BAD);
360*35136Smarc 	if(ioctl(fd,TIOCLGET,&l_mask)==SYSERR)
361*35136Smarc 		return(BAD);
362*35136Smarc 	ttychars = l_ttychars;
363*35136Smarc 	mask =  LCRTBS|LCRTERA|LCTLECH|LPENDIN|LCRTKIL;
364*35136Smarc 	if((l_mask|mask) != l_mask)
365*35136Smarc 		l_changed = L_MASK;
366*35136Smarc 	if(ioctl(fd,TIOCLBIS,&mask)==SYSERR)
367*35136Smarc 		return(BAD);
368*35136Smarc 	ttychars.t_brkc = ESC;
369*35136Smarc 	l_changed |= T_CHARS;
370*35136Smarc 	if(ioctl(fd,TIOCSETC,&ttychars) == SYSERR)
371*35136Smarc 		return(BAD);
372*35136Smarc 	editb.e_raw = ALTMODE;
373*35136Smarc 	return(GOOD);
374*35136Smarc }
375*35136Smarc #else
setalt(fd)376*35136Smarc setalt(fd)
377*35136Smarc register int fd;
378*35136Smarc {
379*35136Smarc 	if(editb.e_raw==ALTMODE)
380*35136Smarc 		return(GOOD);
381*35136Smarc 	if(editb.e_raw==RAWMODE)
382*35136Smarc 		setcooked(fd);
383*35136Smarc 	if( (control(fd, TCGETA, &ttyparm) == SYSERR)
384*35136Smarc 		|| (!(ttyparm.c_lflag & ECHO )))
385*35136Smarc 	{
386*35136Smarc 		return(BAD);
387*35136Smarc 	}
388*35136Smarc 	nttyparm = ttyparm;
389*35136Smarc 	nttyparm.c_iflag &= ~(IGNCR|ICRNL);
390*35136Smarc 	nttyparm.c_iflag |= INLCR;
391*35136Smarc 	nttyparm.c_lflag |= (ECHOE|ECHOK);
392*35136Smarc 	nttyparm.c_cc[VEOF] = ESC;	/* make ESC the eof char */
393*35136Smarc 	nttyparm.c_cc[VEOL] = '\r';	/* make CR an eol char */
394*35136Smarc 	editb.e_eof = ttyparm.c_cc[VEOF];
395*35136Smarc 	nttyparm.c_cc[VEOL2] = editb.e_eof;	/* make EOF an eol char */
396*35136Smarc 	editb.e_erase = ttyparm.c_cc[VERASE];
397*35136Smarc 	editb.e_kill = ttyparm.c_cc[VKILL];
398*35136Smarc 	if( control(fd, TCSETAW, &nttyparm) == SYSERR )
399*35136Smarc 	{
400*35136Smarc 		return(BAD);
401*35136Smarc 	}
402*35136Smarc 	editb.e_ttyspeed = ((ttyparm.c_cflag&CBAUD)>=B1200?FAST:SLOW);
403*35136Smarc 	editb.e_raw = ALTMODE;
404*35136Smarc 	return(GOOD);
405*35136Smarc }
406*35136Smarc 
407*35136Smarc #endif	/* BSD */
408*35136Smarc #endif	/* RAWONLY */
409*35136Smarc 
410*35136Smarc /*
411*35136Smarc  *	E_WINDOW()
412*35136Smarc  *
413*35136Smarc  *	return the window size
414*35136Smarc  */
415*35136Smarc 
e_window()416*35136Smarc int e_window()
417*35136Smarc {
418*35136Smarc 	register int n = DFLTWINDOW-1;
419*35136Smarc 	register char *cp = valup(COLUMNS);
420*35136Smarc 	if(cp)
421*35136Smarc 	{
422*35136Smarc 		n = atoi(cp)-1;
423*35136Smarc 		if(n < MINWINDOW)
424*35136Smarc 			n = MINWINDOW;
425*35136Smarc 		if(n > MAXWINDOW)
426*35136Smarc 			n = MAXWINDOW;
427*35136Smarc 	}
428*35136Smarc 	return(n);
429*35136Smarc }
430*35136Smarc 
431*35136Smarc /*	E_FLUSH()
432*35136Smarc  *
433*35136Smarc  *	Flush the output buffer.
434*35136Smarc  *
435*35136Smarc  */
436*35136Smarc 
e_flush()437*35136Smarc void e_flush()
438*35136Smarc {
439*35136Smarc 	register unsigned char *buf = (unsigned char*)output->_base;
440*35136Smarc 	register int n = editb.e_outptr-buf;
441*35136Smarc 	register int fd = fileno(output);
442*35136Smarc 	if(n<=0)
443*35136Smarc 		return;
444*35136Smarc 	write(fd,(char*)buf,n);
445*35136Smarc 	editb.e_outptr = buf;
446*35136Smarc #ifdef BSD
447*35136Smarc # ifdef BSD_4_2
448*35136Smarc 	if(delay && n > delay/100)
449*35136Smarc 	{
450*35136Smarc 		/* delay until output drains */
451*35136Smarc 		struct timeval timeloc;
452*35136Smarc 		n *= 10;
453*35136Smarc 		timeloc.tv_sec = n/delay;
454*35136Smarc 		timeloc.tv_usec = (1000000*(n%delay))/delay;
455*35136Smarc 		select(0,0,0,0,&timeloc);
456*35136Smarc 	}
457*35136Smarc # endif /* BSD_4_2 */
458*35136Smarc #else
459*35136Smarc # ifndef RT
460*35136Smarc 	if(editb.e_raw==RAWMODE && n > 16)
461*35136Smarc 		ioctl(fd, TCSETAW, &nttyparm);
462*35136Smarc # endif /* RT */
463*35136Smarc #endif /* BSD */
464*35136Smarc }
465*35136Smarc 
466*35136Smarc /*
467*35136Smarc  * send the bell character ^G to the terminal
468*35136Smarc  */
469*35136Smarc 
e_ringbell()470*35136Smarc void e_ringbell()
471*35136Smarc {
472*35136Smarc 	write(fileno(output),bellchr,1);
473*35136Smarc }
474*35136Smarc 
475*35136Smarc /*
476*35136Smarc  * send a carriage return line feed to the terminal
477*35136Smarc  */
478*35136Smarc 
e_crlf()479*35136Smarc void e_crlf()
480*35136Smarc {
481*35136Smarc #ifdef u370
482*35136Smarc 	e_putchar('\r');
483*35136Smarc #endif	/* u370 */
484*35136Smarc #ifdef VENIX
485*35136Smarc 	e_putchar('\r');
486*35136Smarc #endif /* VENIX */
487*35136Smarc 	e_putchar('\n');
488*35136Smarc 	e_flush();
489*35136Smarc }
490*35136Smarc 
491*35136Smarc /*	E_SETUP( max_prompt_size )
492*35136Smarc  *
493*35136Smarc  *	This routine sets up the prompt string
494*35136Smarc  */
495*35136Smarc 
e_setup(fd,PRSIZE)496*35136Smarc void	e_setup(fd,PRSIZE)
497*35136Smarc {
498*35136Smarc 	register char *last;
499*35136Smarc 	register char *pp = (char*)(output->_base);
500*35136Smarc 	char *ppmax;
501*35136Smarc 	editb.e_fd = fd;
502*35136Smarc 	if(fc_fix)
503*35136Smarc 	{
504*35136Smarc 		register struct fixcmd *fp = fc_fix;
505*35136Smarc 		editb.e_hismax = fp->fixind;
506*35136Smarc 		editb.e_hloff = fp->fixline;
507*35136Smarc 		editb.e_hismin = fp->fixind-fp->fixmax;
508*35136Smarc 		if(editb.e_hismin<0)
509*35136Smarc 			editb.e_hismin = 0;
510*35136Smarc 	}
511*35136Smarc 	else
512*35136Smarc 	{
513*35136Smarc 		editb.e_hismax = editb.e_hismin = editb.e_hloff = 0;
514*35136Smarc 	}
515*35136Smarc 	editb.e_hline = editb.e_hismax;
516*35136Smarc 	editb.e_wsize = e_window()-2;
517*35136Smarc 	editb.e_outptr = (unsigned char*)pp;
518*35136Smarc 	editb.e_crlf = YES;
519*35136Smarc 	*(output->_ptr) = 0;
520*35136Smarc 	if((last=strrchr(pp,'\n'))==NULL)
521*35136Smarc 	{
522*35136Smarc 		if(*(last=pp)==0)
523*35136Smarc 			editb.e_crlf = NO;
524*35136Smarc 	}
525*35136Smarc 	else
526*35136Smarc 		last++;
527*35136Smarc 	pp = editb.e_prompt;
528*35136Smarc 	ppmax = pp+PRSIZE-1;
529*35136Smarc 	*pp++ = '\r';
530*35136Smarc 	{
531*35136Smarc 		register int c;
532*35136Smarc 		while(c = *last++)
533*35136Smarc 		{
534*35136Smarc 			/* cut out bells */
535*35136Smarc 			if(c!=BELL)
536*35136Smarc 			{
537*35136Smarc 				if(pp < ppmax)
538*35136Smarc 					*pp++ = c;
539*35136Smarc 				if(!isprint(c))
540*35136Smarc 					editb.e_crlf = NO;
541*35136Smarc 			}
542*35136Smarc 		}
543*35136Smarc 	}
544*35136Smarc 	editb.e_plen = pp - editb.e_prompt - 1;
545*35136Smarc 	*pp = 0;
546*35136Smarc #ifdef u370
547*35136Smarc 	if (editb.e_raw == RAWMODE)
548*35136Smarc 		u370fflush(output);
549*35136Smarc 	else
550*35136Smarc #endif	/* u370 */
551*35136Smarc 	p_flush();
552*35136Smarc }
553*35136Smarc 
554*35136Smarc #ifdef u370
555*35136Smarc /* The u370 does not \r before \n in raw mode (known bug).
556*35136Smarc 	  To get around this we will insert a \r before each \n
557*35136Smarc 	  in the output buffer.
558*35136Smarc */
559*35136Smarc 
u370fflush(file)560*35136Smarc u370fflush(file)
561*35136Smarc FILE *file;
562*35136Smarc {
563*35136Smarc 	unsigned char *base,*ptr,buffer[BUFSIZ*2];
564*35136Smarc 	int icnt,ocnt;
565*35136Smarc 	ptr = buffer;
566*35136Smarc 	icnt = file->_ptr - file->_base;
567*35136Smarc 	ocnt = icnt;
568*35136Smarc 	base = file->_base ;
569*35136Smarc 	if (icnt <= 0) return;
570*35136Smarc 	while (base < file->_ptr)
571*35136Smarc 	{
572*35136Smarc 		if (*base == '\n' )
573*35136Smarc 		{
574*35136Smarc 			*ptr++ = '\r';
575*35136Smarc 			ocnt++;
576*35136Smarc 		}
577*35136Smarc 		*ptr++ = *base++;
578*35136Smarc 	}
579*35136Smarc 	base = file->_base;
580*35136Smarc 	ptr = buffer;
581*35136Smarc 	while (ocnt>0)
582*35136Smarc 	{
583*35136Smarc 		for(icnt=0;icnt<BUFSIZ;icnt++)
584*35136Smarc 		{
585*35136Smarc 			*base++ = *ptr++;
586*35136Smarc 			if (--ocnt <= 0) break;
587*35136Smarc 		}
588*35136Smarc 		file->_ptr = base;
589*35136Smarc 		p_flush();
590*35136Smarc 		base = file->_base;
591*35136Smarc 	}
592*35136Smarc }
593*35136Smarc #endif	/* u370 */
594*35136Smarc 
595*35136Smarc #ifdef KSHELL
596*35136Smarc /*
597*35136Smarc  * look for edit macro named _i
598*35136Smarc  * if found, puts the macro definition into lookahead buffer and returns 1
599*35136Smarc  */
600*35136Smarc 
e_macro(i)601*35136Smarc e_macro(i)
602*35136Smarc register int i;
603*35136Smarc {
604*35136Smarc 	register char *out;
605*35136Smarc 	struct Namnod *np;
606*35136Smarc 	genchar buff[LOOKAHEAD+1];
607*35136Smarc 	if(i != '@')
608*35136Smarc 		macro[1] = i;
609*35136Smarc 	if (isalnum(i)&&(np=findnod(macro,alias,0))&&(out=valup(np)))
610*35136Smarc 	{
611*35136Smarc #ifdef MULTIBYTE
612*35136Smarc 		/* copy to buff in internal representation */
613*35136Smarc 		int c = out[LOOKAHEAD];
614*35136Smarc 		out[LOOKAHEAD] = 0;
615*35136Smarc 		i = e_internal(out,buff);
616*35136Smarc 		out[LOOKAHEAD] = c;
617*35136Smarc #else
618*35136Smarc 		strncpy((char*)buff,out,LOOKAHEAD);
619*35136Smarc 		i = strlen((char*)buff);
620*35136Smarc #endif /* MULTIBYTE */
621*35136Smarc 		while(i-- > 0)
622*35136Smarc 			ungetchar(buff[i]);
623*35136Smarc 		return(1);
624*35136Smarc 	}
625*35136Smarc 	return(0);
626*35136Smarc }
627*35136Smarc /*
628*35136Smarc  * file name generation for edit modes
629*35136Smarc  * non-zero exit for error, <0 ring bell
630*35136Smarc  * don't search back past <start> character of the buffer
631*35136Smarc  * mode is '*' for inline expansion, otherwise files are listed in select format
632*35136Smarc  */
633*35136Smarc 
q_expand(outbuff,cur,eol,start,mode)634*35136Smarc q_expand(outbuff,cur,eol,start,mode)
635*35136Smarc char outbuff[];
636*35136Smarc int *cur;
637*35136Smarc int *eol;
638*35136Smarc int start;
639*35136Smarc int mode;
640*35136Smarc {
641*35136Smarc 	STKPTR staksav = stakbot;
642*35136Smarc 	COMPTR  comptr = (COMPTR)getstak(COMTYPE);
643*35136Smarc 	ARGPTR ap = (ARGPTR)locstak();
644*35136Smarc 	register char *out;
645*35136Smarc 	char *outmin = outbuff + start;
646*35136Smarc 	char *begin;
647*35136Smarc 	char *last;
648*35136Smarc 	int rval = 0;
649*35136Smarc 	int strip;
650*35136Smarc 	optflag savflags = flags;
651*35136Smarc #ifdef MULTIBYTE
652*35136Smarc 	{
653*35136Smarc 		register int c = *cur;
654*35136Smarc 		register genchar *cp;
655*35136Smarc 		/* adjust cur */
656*35136Smarc 		cp = (genchar *)outbuff + *cur;
657*35136Smarc 		c = *cp;
658*35136Smarc 		*cp = 0;
659*35136Smarc 		*cur = e_external((genchar*)outbuff,(char*)stakbot);
660*35136Smarc 		*cp = c;
661*35136Smarc 		*eol = e_external((genchar*)outbuff,outbuff);
662*35136Smarc 	}
663*35136Smarc #endif /* MULTIBYTE */
664*35136Smarc 	out = outbuff + *cur;
665*35136Smarc 	comptr->comtyp = COMSCAN;
666*35136Smarc 	comptr->comarg = ap;
667*35136Smarc 	ap->argflag = (A_MAC|A_EXP);
668*35136Smarc 	ap->argnxt = 0;
669*35136Smarc 	{
670*35136Smarc 		register int c;
671*35136Smarc 		register char *ptr = ap->argval;
672*35136Smarc 		int chktilde = 0;
673*35136Smarc 		int flag;
674*35136Smarc 		char *cp;
675*35136Smarc 		if(out>outmin)
676*35136Smarc 		{
677*35136Smarc 			/* go to beginning of word */
678*35136Smarc 			do
679*35136Smarc 			{
680*35136Smarc 				out--;
681*35136Smarc 				c = *(unsigned char*)out;
682*35136Smarc 			}
683*35136Smarc 			while(out>outmin && !isqmeta(c));
684*35136Smarc 			/* copy word into arg */
685*35136Smarc 			if(isqmeta(c))
686*35136Smarc 				out++;
687*35136Smarc 		}
688*35136Smarc 		else
689*35136Smarc 			out = outmin;
690*35136Smarc 		begin = out;
691*35136Smarc 		flag = '*';
692*35136Smarc 		strip = TRUE;
693*35136Smarc 		/* copy word to arg and do ~ expansion */
694*35136Smarc 		do
695*35136Smarc 		{
696*35136Smarc 			c = *(unsigned char*)out++;
697*35136Smarc 			if(isexp(c))
698*35136Smarc 				flag = 0;
699*35136Smarc 			if ((c == '/') && (flag == 0))
700*35136Smarc 				strip = FALSE;
701*35136Smarc 			*ptr++ = c;
702*35136Smarc 			if(chktilde==0 && (c==0 || c == '/'))
703*35136Smarc 			{
704*35136Smarc 				chktilde++;
705*35136Smarc 				if(cp=tilde(begin))
706*35136Smarc 				{
707*35136Smarc 					ptr = movstr(cp,ap->argval);
708*35136Smarc 					*ptr++ = c;
709*35136Smarc 				}
710*35136Smarc 			}
711*35136Smarc 
712*35136Smarc 		} while (c && !isqmeta(c));
713*35136Smarc 
714*35136Smarc 		out--;
715*35136Smarc 		*(ptr-1) = flag;
716*35136Smarc 		endstak(ptr);
717*35136Smarc 		last = ptr-1;
718*35136Smarc 	}
719*35136Smarc 	if(mode!='*')
720*35136Smarc 		on_option(MARKDIR);
721*35136Smarc 	{
722*35136Smarc 		register char **com;
723*35136Smarc 		int	 narg;
724*35136Smarc 		register int size;
725*35136Smarc 		while(1)
726*35136Smarc 		{
727*35136Smarc 			com = arg_build(&narg,comptr);
728*35136Smarc 			/*  match? */
729*35136Smarc 			if (narg > 1 || !eq(ap->argval,*com))
730*35136Smarc 				break;
731*35136Smarc 			if (*last == 0)
732*35136Smarc 				*last = '*';
733*35136Smarc 			else
734*35136Smarc 			{
735*35136Smarc 				rval = -1;
736*35136Smarc 				goto done;
737*35136Smarc 			}
738*35136Smarc 		}
739*35136Smarc 		if(mode!='*')
740*35136Smarc 		{
741*35136Smarc 			if (strip)
742*35136Smarc 			{
743*35136Smarc 				register char **ptrcom;
744*35136Smarc 				for(ptrcom=com;*ptrcom;ptrcom++)
745*35136Smarc 					/* trim directory prefix */
746*35136Smarc 					*ptrcom = simple (*ptrcom);
747*35136Smarc 			}
748*35136Smarc 			p_setout(stderr);
749*35136Smarc 			newline();
750*35136Smarc 			p_list(narg,com);
751*35136Smarc 			p_flush();
752*35136Smarc 			goto done;
753*35136Smarc 		}
754*35136Smarc 		/* see if there is enough room */
755*35136Smarc 		size = *eol - (out-begin);
756*35136Smarc 		size += narg;
757*35136Smarc 		{
758*35136Smarc 			char **savcom = com;
759*35136Smarc 			while (*com)
760*35136Smarc 				size += strlen(*com++);
761*35136Smarc 			com = savcom;
762*35136Smarc 		}
763*35136Smarc 		/* see if room for expansion */
764*35136Smarc 		if(outbuff+size >= &outbuff[MAXLINE])
765*35136Smarc 		{
766*35136Smarc 			com[0] = ap->argval;
767*35136Smarc 			com[1] = NULL;
768*35136Smarc 		}
769*35136Smarc 		/* save remainder of the buffer */
770*35136Smarc 		strcpy(stakbot,out);
771*35136Smarc 		out = begin;
772*35136Smarc 		while (*com)
773*35136Smarc 		{
774*35136Smarc 			out = movstr(*com,out);
775*35136Smarc 			if (*++com)
776*35136Smarc 				*out++  = ' ';
777*35136Smarc 		}
778*35136Smarc 		*cur = (out-outbuff);
779*35136Smarc 		/* restore rest of buffer */
780*35136Smarc 		out = movstr(stakbot,out);
781*35136Smarc 		*eol = (out-outbuff);
782*35136Smarc 	}
783*35136Smarc  done:
784*35136Smarc 	tdystak(staksav);
785*35136Smarc 	flags = savflags;
786*35136Smarc #ifdef MULTIBYTE
787*35136Smarc 	{
788*35136Smarc 		register int c;
789*35136Smarc 		/* first re-adjust cur */
790*35136Smarc 		out = outbuff + *cur;
791*35136Smarc 		c = *out;
792*35136Smarc 		*out = 0;
793*35136Smarc 		*cur = e_internal(outbuff,(genchar*)stakbot);
794*35136Smarc 		*out = c;
795*35136Smarc 		outbuff[*eol+1] = 0;
796*35136Smarc 		*eol = e_internal(outbuff,(genchar*)outbuff);
797*35136Smarc 	}
798*35136Smarc #endif /* MULTIBYTE */
799*35136Smarc 	return(rval);
800*35136Smarc }
801*35136Smarc #endif	/* KSHELL */
802*35136Smarc 
803*35136Smarc 
804*35136Smarc /*
805*35136Smarc  * routine to perform read from terminal for vi and emacs mode
806*35136Smarc  */
807*35136Smarc 
808*35136Smarc 
809*35136Smarc int
e_getchar()810*35136Smarc e_getchar()
811*35136Smarc {
812*35136Smarc 	register int i;
813*35136Smarc 	register int c;
814*35136Smarc 	register int maxtry = 100;
815*35136Smarc 	int nchar;	/* number of characters to read at a time */
816*35136Smarc #ifdef MULTIBYTE
817*35136Smarc 	static int curchar;
818*35136Smarc 	static int cursize;
819*35136Smarc #endif /* MULTIBYTE */
820*35136Smarc 	char readin[LOOKAHEAD] ;
821*35136Smarc 	if (lookahead)
822*35136Smarc 	{
823*35136Smarc 		c = previous[--lookahead];
824*35136Smarc 		/*** map '\r' to '\n' ***/
825*35136Smarc 		if(c == '\r')
826*35136Smarc 			c = '\n';
827*35136Smarc 		return(c);
828*35136Smarc 	}
829*35136Smarc 
830*35136Smarc 	e_flush() ;
831*35136Smarc 	/* you can't chance read ahead at the end of line */
832*35136Smarc 	nchar = (editb.e_cur>=editb.e_eol?1:READAHEAD);
833*35136Smarc 	/* Set 'i' to indicate read failed, in case intr set */
834*35136Smarc retry:
835*35136Smarc 	i = -1;
836*35136Smarc 	errno = 0;
837*35136Smarc 	editb.e_inmacro = 0;
838*35136Smarc 	while((trapnote&SIGSLOW)==0 && maxtry--)
839*35136Smarc 	{
840*35136Smarc 		errno=0;
841*35136Smarc 		if ((i = read(fildes,readin, nchar)) != -1)
842*35136Smarc 			break;
843*35136Smarc 	}
844*35136Smarc #ifdef MULTIBYTE
845*35136Smarc 	lookahead = maxtry = i;
846*35136Smarc 	i = 0;
847*35136Smarc 	while (i < maxtry)
848*35136Smarc 	{
849*35136Smarc 		c = readin[i++] & STRIP;
850*35136Smarc 	next:
851*35136Smarc 		if(cursize-- > 0)
852*35136Smarc 		{
853*35136Smarc 			curchar = (curchar<<7) | (c&~HIGHBIT);
854*35136Smarc 			if(cursize==0)
855*35136Smarc 			{
856*35136Smarc 				c = curchar;
857*35136Smarc 				goto gotit;
858*35136Smarc 			}
859*35136Smarc 			else if(i>=maxtry)
860*35136Smarc 				goto retry;
861*35136Smarc 			continue;
862*35136Smarc 		}
863*35136Smarc 		else if(curchar = echarset(c))
864*35136Smarc 		{
865*35136Smarc 			cursize = in_csize(curchar);
866*35136Smarc 			if(curchar != 1)
867*35136Smarc 				c = 0;
868*35136Smarc 			curchar <<= 7*(ESS_MAXCHAR-cursize);
869*35136Smarc 			if(c)
870*35136Smarc 				goto next;
871*35136Smarc 			else if(i>=maxtry)
872*35136Smarc 				goto retry;
873*35136Smarc 			continue;
874*35136Smarc 		}
875*35136Smarc 	gotit:
876*35136Smarc 		previous[--lookahead] = c;
877*35136Smarc #else
878*35136Smarc 	while (i > 0)
879*35136Smarc 	{
880*35136Smarc 		c = readin[--i] & STRIP;
881*35136Smarc 		previous[lookahead++] = c;
882*35136Smarc #endif /* MULTIBYTE */
883*35136Smarc #ifndef BSD
884*35136Smarc 		if( c == '\0' )
885*35136Smarc 		{
886*35136Smarc 			/*** user break key ***/
887*35136Smarc 			lookahead = 0;
888*35136Smarc # ifdef KSHELL
889*35136Smarc 			fault(SIGINT);
890*35136Smarc 			longjmp(env, UINTR);
891*35136Smarc # endif	/* KSHELL */
892*35136Smarc 		}
893*35136Smarc #endif	/* !BSD */
894*35136Smarc 	}
895*35136Smarc #ifdef MULTIBYTE
896*35136Smarc 	/* shift lookahead buffer if necessary */
897*35136Smarc 	if(lookahead)
898*35136Smarc 	{
899*35136Smarc 		for(i=lookahead;i < maxtry;i++)
900*35136Smarc 			previous[i-lookahead] = previous[i];
901*35136Smarc 	}
902*35136Smarc 	lookahead = maxtry-lookahead;
903*35136Smarc #endif /* MULTIBYTE */
904*35136Smarc 	if (lookahead > 0)
905*35136Smarc 		return(e_getchar(1));
906*35136Smarc 	longjmp(env,(i==0?UEOF:UINTR)); /* What a mess! Give up */
907*35136Smarc 	/* NOTREACHED */
908*35136Smarc }
909*35136Smarc 
910*35136Smarc void ungetchar(c)
911*35136Smarc register int c;
912*35136Smarc {
913*35136Smarc 	if (lookahead < LOOKAHEAD)
914*35136Smarc 		previous[lookahead++] = c;
915*35136Smarc 	return;
916*35136Smarc }
917*35136Smarc 
918*35136Smarc /*
919*35136Smarc  * put a character into the output buffer
920*35136Smarc  */
921*35136Smarc 
922*35136Smarc void	e_putchar(c)
923*35136Smarc register int c;
924*35136Smarc {
925*35136Smarc 	register unsigned char *dp = editb.e_outptr;
926*35136Smarc #ifdef MULTIBYTE
927*35136Smarc 	register int d;
928*35136Smarc 	/* check for place holder */
929*35136Smarc 	if(c == MARKER)
930*35136Smarc 		return;
931*35136Smarc 	if(d = icharset(c))
932*35136Smarc 	{
933*35136Smarc 		if(d == 2)
934*35136Smarc 			*dp++ = ESS2;
935*35136Smarc 		else if(d == 3)
936*35136Smarc 			*dp++ = ESS3;
937*35136Smarc 		d = in_csize(d);
938*35136Smarc 		while(--d>0)
939*35136Smarc 			*dp++ = HIGHBIT|(c>>(7*d));
940*35136Smarc 		c |= HIGHBIT;
941*35136Smarc 	}
942*35136Smarc #endif	/* MULTIBYTE */
943*35136Smarc 	if (c == '_')
944*35136Smarc 	{
945*35136Smarc 		*dp++ = ' ';
946*35136Smarc 		*dp++ = '\b';
947*35136Smarc 	}
948*35136Smarc 	*dp++ = c;
949*35136Smarc 	*dp = '\0';
950*35136Smarc 	if ((dp - (unsigned char*)(output->_base))>=(BUFSIZ-3))
951*35136Smarc 		e_flush();
952*35136Smarc 	else
953*35136Smarc 		editb.e_outptr = dp;
954*35136Smarc }
955*35136Smarc 
956*35136Smarc /*
957*35136Smarc  * copy virtual to physical and return the index for cursor in physical buffer
958*35136Smarc  */
959*35136Smarc e_virt_to_phys(virt,phys,cur,voff,poff)
960*35136Smarc genchar *virt;
961*35136Smarc genchar *phys;
962*35136Smarc int cur;
963*35136Smarc {
964*35136Smarc 	register genchar *sp = virt;
965*35136Smarc 	register genchar *dp = phys;
966*35136Smarc 	register int c;
967*35136Smarc 	genchar *curp = sp + cur;
968*35136Smarc 	genchar *dpmax = phys+MAXLINE;
969*35136Smarc 	int r = 0;
970*35136Smarc #ifdef MULTIBYTE
971*35136Smarc 	int d;
972*35136Smarc #endif /* MULTIBYTE */
973*35136Smarc 	sp += voff;
974*35136Smarc 	dp += poff;
975*35136Smarc 	for(r=poff;c= *sp;sp++)
976*35136Smarc 	{
977*35136Smarc 		if(curp == sp)
978*35136Smarc 			r = dp - phys;
979*35136Smarc #ifdef MULTIBYTE
980*35136Smarc 		d = out_csize(icharset(c));
981*35136Smarc 		if(d>1)
982*35136Smarc 		{
983*35136Smarc 			/* multiple width character put in place holders */
984*35136Smarc 			*dp++ = c;
985*35136Smarc 			while(--d >0)
986*35136Smarc 				*dp++ = MARKER;
987*35136Smarc 			/* in vi mode the cursor is at the last character */
988*35136Smarc 			if(dp>=dpmax)
989*35136Smarc 				break;
990*35136Smarc 			continue;
991*35136Smarc 		}
992*35136Smarc 		else
993*35136Smarc #endif	/* MULTIBYTE */
994*35136Smarc 		if(!isprint(c))
995*35136Smarc 		{
996*35136Smarc 			if(c=='\t')
997*35136Smarc 			{
998*35136Smarc 				c = dp-phys;
999*35136Smarc 				c = ((c+8)&~07) - c;
1000*35136Smarc 				while(--c>0)
1001*35136Smarc 					*dp++ = ' ';
1002*35136Smarc 				c = ' ';
1003*35136Smarc 			}
1004*35136Smarc 			else
1005*35136Smarc 			{
1006*35136Smarc 				*dp++ = '^';
1007*35136Smarc 				c ^= TO_PRINT;
1008*35136Smarc 			}
1009*35136Smarc 			/* in vi mode the cursor is at the last character */
1010*35136Smarc 			if(curp == sp && is_option(EDITVI))
1011*35136Smarc 				r = dp - phys;
1012*35136Smarc 		}
1013*35136Smarc 		*dp++ = c;
1014*35136Smarc 		if(dp>=dpmax)
1015*35136Smarc 			break;
1016*35136Smarc 	}
1017*35136Smarc 	*dp = 0;
1018*35136Smarc 	return(r);
1019*35136Smarc }
1020*35136Smarc 
1021*35136Smarc #ifdef MULTIBYTE
1022*35136Smarc /*
1023*35136Smarc  * convert external representation <src> to an array of genchars <dest>
1024*35136Smarc  * <src> and <dest> can be the same
1025*35136Smarc  * returns number of chars in dest
1026*35136Smarc  */
1027*35136Smarc 
1028*35136Smarc int	e_internal(src,dest)
1029*35136Smarc register unsigned char *src;
1030*35136Smarc genchar *dest;
1031*35136Smarc {
1032*35136Smarc 	register int c;
1033*35136Smarc 	register genchar *dp = dest;
1034*35136Smarc 	register int d;
1035*35136Smarc 	register int size;
1036*35136Smarc 	if((unsigned char*)dest == src)
1037*35136Smarc 	{
1038*35136Smarc 		genchar buffer[MAXLINE];
1039*35136Smarc 		c = e_internal(src,buffer);
1040*35136Smarc 		e_gencpy(dp,buffer);
1041*35136Smarc 		return(c);
1042*35136Smarc 	}
1043*35136Smarc 	while(c = *src++)
1044*35136Smarc 	{
1045*35136Smarc 		if(size = echarset(c))
1046*35136Smarc 		{
1047*35136Smarc 			d = (size==1?c:0);
1048*35136Smarc 			c = size;
1049*35136Smarc 			size = in_csize(c);
1050*35136Smarc 			c <<= 7*(ESS_MAXCHAR-size);
1051*35136Smarc 			if(d)
1052*35136Smarc 			{
1053*35136Smarc 				size--;
1054*35136Smarc 				c = (c<<7) | (d&~HIGHBIT);
1055*35136Smarc 			}
1056*35136Smarc 			while(size-- >0)
1057*35136Smarc 				c = (c<<7) | ((*src++)&~HIGHBIT);
1058*35136Smarc 		}
1059*35136Smarc 		*dp++ = c;
1060*35136Smarc 	}
1061*35136Smarc 	*dp = 0;
1062*35136Smarc 	return(dp-dest);
1063*35136Smarc }
1064*35136Smarc 
1065*35136Smarc /*
1066*35136Smarc  * convert internal representation <src> into character array <dest>.
1067*35136Smarc  * The <src> and <dest> may be the same.
1068*35136Smarc  * returns number of chars in dest.
1069*35136Smarc  */
1070*35136Smarc 
1071*35136Smarc int	e_external(src,dest)
1072*35136Smarc genchar *src;
1073*35136Smarc char *dest;
1074*35136Smarc {
1075*35136Smarc 	register int c;
1076*35136Smarc 	register char *dp = dest;
1077*35136Smarc 	register int d;
1078*35136Smarc 	char *dpmax = dp+sizeof(genchar)*MAXLINE-2;
1079*35136Smarc 	if((char*)src == dp)
1080*35136Smarc 	{
1081*35136Smarc 		char buffer[MAXLINE*sizeof(genchar)];
1082*35136Smarc 		c = e_external(src,buffer);
1083*35136Smarc 		strcpy(dest,buffer);
1084*35136Smarc 		return(c);
1085*35136Smarc 	}
1086*35136Smarc 	while((c = *src++) && dp<dpmax)
1087*35136Smarc 	{
1088*35136Smarc 		if(d = icharset(c))
1089*35136Smarc 		{
1090*35136Smarc 			if(d == 2)
1091*35136Smarc 				*dp++ = ESS2;
1092*35136Smarc 			else if(d == 3)
1093*35136Smarc 				*dp++ = ESS3;
1094*35136Smarc 			d = in_csize(d);
1095*35136Smarc 			while(--d>0)
1096*35136Smarc 				*dp++ = HIGHBIT|(c>>(7*d));
1097*35136Smarc 			c |= HIGHBIT;
1098*35136Smarc 		}
1099*35136Smarc 		*dp++ = c;
1100*35136Smarc 	}
1101*35136Smarc 	*dp = 0;
1102*35136Smarc 	return(dp-dest);
1103*35136Smarc }
1104*35136Smarc 
1105*35136Smarc /*
1106*35136Smarc  * copy <sp> to <dp>
1107*35136Smarc  */
1108*35136Smarc 
1109*35136Smarc int	e_gencpy(dp,sp)
1110*35136Smarc register genchar *dp;
1111*35136Smarc register genchar *sp;
1112*35136Smarc {
1113*35136Smarc 	while(*dp++ = *sp++);
1114*35136Smarc }
1115*35136Smarc 
1116*35136Smarc /*
1117*35136Smarc  * copy at most <n> items from <sp> to <dp>
1118*35136Smarc  */
1119*35136Smarc 
1120*35136Smarc int	e_genncpy(dp,sp, n)
1121*35136Smarc register genchar *dp;
1122*35136Smarc register genchar *sp;
1123*35136Smarc register int n;
1124*35136Smarc {
1125*35136Smarc 	while(n-->0 && (*dp++ = *sp++));
1126*35136Smarc }
1127*35136Smarc 
1128*35136Smarc /*
1129*35136Smarc  * find the string length of <str>
1130*35136Smarc  */
1131*35136Smarc 
1132*35136Smarc int	e_genlen(str)
1133*35136Smarc register genchar *str;
1134*35136Smarc {
1135*35136Smarc 	register genchar *sp = str;
1136*35136Smarc 	while(*sp++);
1137*35136Smarc 	return(sp-str-1);
1138*35136Smarc }
1139*35136Smarc #endif /* MULTIBYTE */
1140