xref: /titanic_41/usr/src/lib/libshell/common/edit/emacs.c (revision 3e14f97f673e8a630f076077de35afdd43dc1587)
1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4*3e14f97fSRoger A. Faulkner *          Copyright (c) 1982-2010 AT&T Intellectual Property          *
5da2e3ebdSchin *                      and is licensed under the                       *
6da2e3ebdSchin *                  Common Public License, Version 1.0                  *
77c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
8da2e3ebdSchin *                                                                      *
9da2e3ebdSchin *                A copy of the License is available at                 *
10da2e3ebdSchin *            http://www.opensource.org/licenses/cpl1.0.txt             *
11da2e3ebdSchin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12da2e3ebdSchin *                                                                      *
13da2e3ebdSchin *              Information and Software Systems Research               *
14da2e3ebdSchin *                            AT&T Research                             *
15da2e3ebdSchin *                           Florham Park NJ                            *
16da2e3ebdSchin *                                                                      *
17da2e3ebdSchin *                  David Korn <dgk@research.att.com>                   *
18da2e3ebdSchin *                                                                      *
19da2e3ebdSchin ***********************************************************************/
20da2e3ebdSchin #pragma prototyped
21da2e3ebdSchin /* Original version by Michael T. Veach
22da2e3ebdSchin  * Adapted for ksh by David Korn */
23da2e3ebdSchin /* EMACS_MODES: c tabstop=4
24da2e3ebdSchin 
25da2e3ebdSchin One line screen editor for any program
26da2e3ebdSchin 
27da2e3ebdSchin */
28da2e3ebdSchin 
29da2e3ebdSchin 
30da2e3ebdSchin /*	The following is provided by:
31da2e3ebdSchin  *
32da2e3ebdSchin  *			Matthijs N. Melchior
33da2e3ebdSchin  *			AT&T Network Systems International
34da2e3ebdSchin  *			APT Nederland
35da2e3ebdSchin  *			HV BZ335 x2962
36da2e3ebdSchin  *			hvlpb!mmelchio
37da2e3ebdSchin  *
38da2e3ebdSchin  *  These are now on by default
39da2e3ebdSchin  *
40da2e3ebdSchin  *  ESH_NFIRST
41da2e3ebdSchin  *	-  A ^N as first history related command after the prompt will move
42da2e3ebdSchin  *	   to the next command relative to the last known history position.
43da2e3ebdSchin  *	   It will not start at the position where the last command was entered
44da2e3ebdSchin  *	   as is done by the ^P command.  Every history related command will
45da2e3ebdSchin  *	   set both the current and last position.  Executing a command will
46da2e3ebdSchin  *	   only set the current position.
47da2e3ebdSchin  *
48da2e3ebdSchin  *  ESH_KAPPEND
49da2e3ebdSchin  *	-  Successive kill and delete commands will accumulate their data
50da2e3ebdSchin  *	   in the kill buffer, by appending or prepending as appropriate.
51da2e3ebdSchin  *	   This mode will be reset by any command not adding something to the
52da2e3ebdSchin  *	   kill buffer.
53da2e3ebdSchin  *
54da2e3ebdSchin  *  ESH_BETTER
55da2e3ebdSchin  *	-  Some enhancements:
56da2e3ebdSchin  *		- argument for a macro is passed to its replacement
57da2e3ebdSchin  *		- ^X^H command to find out about history position (debugging)
58da2e3ebdSchin  *		- ^X^D command to show any debugging info
59da2e3ebdSchin  *
60da2e3ebdSchin  *  I do not pretend these for changes are completely independent,
61da2e3ebdSchin  *  but you can use them to seperate features.
62da2e3ebdSchin  */
63da2e3ebdSchin 
64da2e3ebdSchin #include	<ast.h>
65da2e3ebdSchin #include	"FEATURE/cmds"
66da2e3ebdSchin #if KSHELL
67da2e3ebdSchin #   include	"defs.h"
6834f9b3eeSRoland Mainz #else
6934f9b3eeSRoland Mainz #   include	<ctype.h>
70da2e3ebdSchin #endif	/* KSHELL */
71da2e3ebdSchin #include	"io.h"
72da2e3ebdSchin 
73da2e3ebdSchin #include	"history.h"
74da2e3ebdSchin #include	"edit.h"
75da2e3ebdSchin #include	"terminal.h"
76da2e3ebdSchin 
77da2e3ebdSchin #define ESH_NFIRST
78da2e3ebdSchin #define ESH_KAPPEND
79da2e3ebdSchin #define ESH_BETTER
80da2e3ebdSchin 
81da2e3ebdSchin #undef putchar
82da2e3ebdSchin #define putchar(ed,c)	ed_putchar(ed,c)
83da2e3ebdSchin #define beep()		ed_ringbell()
84da2e3ebdSchin 
85da2e3ebdSchin 
86da2e3ebdSchin #if SHOPT_MULTIBYTE
87da2e3ebdSchin #   define gencpy(a,b)	ed_gencpy(a,b)
88da2e3ebdSchin #   define genncpy(a,b,n)	ed_genncpy(a,b,n)
89da2e3ebdSchin #   define genlen(str)	ed_genlen(str)
90da2e3ebdSchin     static int	print(int);
91da2e3ebdSchin     static int	_isword(int);
92da2e3ebdSchin #   define  isword(c)	_isword(out[c])
93da2e3ebdSchin 
94da2e3ebdSchin #else
95da2e3ebdSchin #   define gencpy(a,b)	strcpy((char*)(a),(char*)(b))
96da2e3ebdSchin #   define genncpy(a,b,n)	strncpy((char*)(a),(char*)(b),n)
97da2e3ebdSchin #   define genlen(str)	strlen(str)
98da2e3ebdSchin #   define print(c)	isprint(c)
99da2e3ebdSchin #   define isword(c)	(isalnum(out[c]) || (out[c]=='_'))
100da2e3ebdSchin #endif /*SHOPT_MULTIBYTE */
101da2e3ebdSchin 
102da2e3ebdSchin typedef struct _emacs_
103da2e3ebdSchin {
104da2e3ebdSchin 	genchar *screen;	/* pointer to window buffer */
105da2e3ebdSchin 	genchar *cursor;	/* Cursor in real screen */
106da2e3ebdSchin 	int 	mark;
107da2e3ebdSchin 	int 	in_mult;
108da2e3ebdSchin 	char	cr_ok;
109da2e3ebdSchin 	char	CntrlO;
110da2e3ebdSchin 	char	overflow;		/* Screen overflow flag set */
111da2e3ebdSchin 	char	scvalid;		/* Screen is up to date */
1127c2fbfb3SApril Chin 	char	lastdraw;	/* last update type */
113da2e3ebdSchin 	int	offset;		/* Screen offset */
114da2e3ebdSchin 	enum
115da2e3ebdSchin 	{
116da2e3ebdSchin 		CRT=0,	/* Crt terminal */
117da2e3ebdSchin 		PAPER	/* Paper terminal */
118da2e3ebdSchin 	} terminal;
119da2e3ebdSchin 	Histloc_t _location;
120da2e3ebdSchin 	int	prevdirection;
121da2e3ebdSchin 	Edit_t	*ed;	/* pointer to edit data */
122da2e3ebdSchin } Emacs_t;
123da2e3ebdSchin 
124da2e3ebdSchin #define	editb		(*ep->ed)
125da2e3ebdSchin #define eol		editb.e_eol
126da2e3ebdSchin #define cur		editb.e_cur
127da2e3ebdSchin #define hline		editb.e_hline
128da2e3ebdSchin #define hloff		editb.e_hloff
129da2e3ebdSchin #define hismin		editb.e_hismin
130da2e3ebdSchin #define usrkill		editb.e_kill
131da2e3ebdSchin #define usrlnext	editb.e_lnext
132da2e3ebdSchin #define usreof		editb.e_eof
133da2e3ebdSchin #define usrerase	editb.e_erase
134da2e3ebdSchin #define crallowed	editb.e_crlf
135da2e3ebdSchin #define Prompt		editb.e_prompt
136da2e3ebdSchin #define plen		editb.e_plen
137da2e3ebdSchin #define kstack		editb.e_killbuf
138da2e3ebdSchin #define lstring		editb.e_search
139da2e3ebdSchin #define lookahead	editb.e_lookahead
140da2e3ebdSchin #define env		editb.e_env
141da2e3ebdSchin #define raw		editb.e_raw
142da2e3ebdSchin #define histlines	editb.e_hismax
143da2e3ebdSchin #define w_size		editb.e_wsize
144da2e3ebdSchin #define drawbuff	editb.e_inbuf
145da2e3ebdSchin #define killing		editb.e_mode
146da2e3ebdSchin #define location	ep->_location
147da2e3ebdSchin 
148da2e3ebdSchin #define LBUF	100
149da2e3ebdSchin #define KILLCHAR	UKILL
150da2e3ebdSchin #define ERASECHAR	UERASE
151da2e3ebdSchin #define EOFCHAR		UEOF
152da2e3ebdSchin #define LNEXTCHAR		ULNEXT
153da2e3ebdSchin #define DELETE		('a'==97?0177:7)
154da2e3ebdSchin 
155da2e3ebdSchin /**********************
156da2e3ebdSchin A large lookahead helps when the user is inserting
157da2e3ebdSchin characters in the middle of the line.
158da2e3ebdSchin ************************/
159da2e3ebdSchin 
160da2e3ebdSchin 
161da2e3ebdSchin typedef enum
162da2e3ebdSchin {
163da2e3ebdSchin 	FIRST,		/* First time thru for logical line, prompt on screen */
164da2e3ebdSchin 	REFRESH,	/* Redraw entire screen */
165da2e3ebdSchin 	APPEND,		/* Append char before cursor to screen */
166da2e3ebdSchin 	UPDATE,		/* Update the screen as need be */
167da2e3ebdSchin 	FINAL		/* Update screen even if pending look ahead */
168da2e3ebdSchin } Draw_t;
169da2e3ebdSchin 
170da2e3ebdSchin static void draw(Emacs_t*,Draw_t);
171da2e3ebdSchin static int escape(Emacs_t*,genchar*, int);
172da2e3ebdSchin static void putstring(Emacs_t*,char*);
173da2e3ebdSchin static void search(Emacs_t*,genchar*,int);
174da2e3ebdSchin static void setcursor(Emacs_t*,int, int);
175da2e3ebdSchin static void show_info(Emacs_t*,const char*);
176da2e3ebdSchin static void xcommands(Emacs_t*,int);
177da2e3ebdSchin 
ed_emacsread(void * context,int fd,char * buff,int scend,int reedit)178da2e3ebdSchin int ed_emacsread(void *context, int fd,char *buff,int scend, int reedit)
179da2e3ebdSchin {
180da2e3ebdSchin 	Edit_t *ed = (Edit_t*)context;
181da2e3ebdSchin 	register int c;
182da2e3ebdSchin 	register int i;
183da2e3ebdSchin 	register genchar *out;
184da2e3ebdSchin 	register int count;
185da2e3ebdSchin 	register Emacs_t *ep = ed->e_emacs;
186da2e3ebdSchin 	int adjust,oadjust;
187da2e3ebdSchin 	char backslash;
188da2e3ebdSchin 	genchar *kptr;
189da2e3ebdSchin 	char prompt[PRSIZE];
190da2e3ebdSchin 	genchar Screen[MAXLINE];
191da2e3ebdSchin 	if(!ep)
192da2e3ebdSchin 	{
193da2e3ebdSchin 		ep = ed->e_emacs = newof(0,Emacs_t,1,0);
194da2e3ebdSchin 		ep->ed = ed;
195da2e3ebdSchin 		ep->prevdirection =  1;
196da2e3ebdSchin 		location.hist_command =  -5;
197da2e3ebdSchin 	}
198da2e3ebdSchin 	Prompt = prompt;
199da2e3ebdSchin 	ep->screen = Screen;
2007c2fbfb3SApril Chin 	ep->lastdraw = FINAL;
201da2e3ebdSchin 	if(tty_raw(ERRIO,0) < 0)
202da2e3ebdSchin 	{
203da2e3ebdSchin 		 return(reedit?reedit:ed_read(context, fd,buff,scend,0));
204da2e3ebdSchin 	}
205da2e3ebdSchin 	raw = 1;
206da2e3ebdSchin 	/* This mess in case the read system call fails */
207da2e3ebdSchin 
208da2e3ebdSchin 	ed_setup(ep->ed,fd,reedit);
209da2e3ebdSchin 	out = (genchar*)buff;
210da2e3ebdSchin #if SHOPT_MULTIBYTE
21134f9b3eeSRoland Mainz 	out = (genchar*)roundof(buff-(char*)0,sizeof(genchar));
21234f9b3eeSRoland Mainz 	if(reedit)
21334f9b3eeSRoland Mainz 		ed_internal(buff,out);
214da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
215da2e3ebdSchin 	if(!kstack)
216da2e3ebdSchin 	{
217da2e3ebdSchin 		kstack = (genchar*)malloc(CHARSIZE*MAXLINE);
218da2e3ebdSchin 		kstack[0] = '\0';
219da2e3ebdSchin 	}
220da2e3ebdSchin 	drawbuff = out;
221da2e3ebdSchin #ifdef ESH_NFIRST
222da2e3ebdSchin 	if (location.hist_command == -5)		/* to be initialized */
223da2e3ebdSchin 	{
224da2e3ebdSchin 		kstack[0] = '\0';		/* also clear kstack... */
225da2e3ebdSchin 		location.hist_command = hline;
226da2e3ebdSchin 		location.hist_line = hloff;
227da2e3ebdSchin 	}
228da2e3ebdSchin 	if (location.hist_command <= hismin)	/* don't start below minimum */
229da2e3ebdSchin 	{
230da2e3ebdSchin 		location.hist_command = hismin + 1;
231da2e3ebdSchin 		location.hist_line = 0;
232da2e3ebdSchin 	}
233da2e3ebdSchin 	ep->in_mult = hloff;			/* save pos in last command */
234da2e3ebdSchin #endif /* ESH_NFIRST */
235da2e3ebdSchin 	i = sigsetjmp(env,0);
236da2e3ebdSchin 	if (i !=0)
237da2e3ebdSchin 	{
2387c2fbfb3SApril Chin 		if(ep->ed->e_multiline)
2397c2fbfb3SApril Chin 		{
2407c2fbfb3SApril Chin 			cur = eol;
2417c2fbfb3SApril Chin 			draw(ep,FINAL);
2427c2fbfb3SApril Chin 			ed_flush(ep->ed);
2437c2fbfb3SApril Chin 		}
244da2e3ebdSchin 		tty_cooked(ERRIO);
245da2e3ebdSchin 		if (i == UEOF)
246da2e3ebdSchin 		{
247da2e3ebdSchin 			return(0); /* EOF */
248da2e3ebdSchin 		}
249da2e3ebdSchin 		return(-1); /* some other error */
250da2e3ebdSchin 	}
251da2e3ebdSchin 	out[reedit] = 0;
252da2e3ebdSchin 	if(scend+plen > (MAXLINE-2))
253da2e3ebdSchin 		scend = (MAXLINE-2)-plen;
254da2e3ebdSchin 	ep->mark = 0;
255da2e3ebdSchin 	cur = eol;
256da2e3ebdSchin 	draw(ep,reedit?REFRESH:FIRST);
257da2e3ebdSchin 	adjust = -1;
258da2e3ebdSchin 	backslash = 0;
259da2e3ebdSchin 	if (ep->CntrlO)
260da2e3ebdSchin 	{
261da2e3ebdSchin #ifdef ESH_NFIRST
262da2e3ebdSchin 		ed_ungetchar(ep->ed,cntl('N'));
263da2e3ebdSchin #else
264da2e3ebdSchin 		location = hist_locate(sh.hist_ptr,location.hist_command,location.hist_line,1);
265da2e3ebdSchin 		if (location.hist_command < histlines)
266da2e3ebdSchin 		{
267da2e3ebdSchin 			hline = location.hist_command;
268da2e3ebdSchin 			hloff = location.hist_line;
269da2e3ebdSchin 			hist_copy((char*)kstack,MAXLINE, hline,hloff);
270da2e3ebdSchin #   if SHOPT_MULTIBYTE
271da2e3ebdSchin 			ed_internal((char*)kstack,kstack);
272da2e3ebdSchin #   endif /* SHOPT_MULTIBYTE */
273da2e3ebdSchin 			ed_ungetchar(ep->ed,cntl('Y'));
274da2e3ebdSchin 		}
275da2e3ebdSchin #endif /* ESH_NFIRST */
276da2e3ebdSchin 	}
277da2e3ebdSchin 	ep->CntrlO = 0;
278da2e3ebdSchin 	while ((c = ed_getchar(ep->ed,0)) != (-1))
279da2e3ebdSchin 	{
280da2e3ebdSchin 		if (backslash)
281da2e3ebdSchin 		{
282da2e3ebdSchin 			backslash = 0;
283da2e3ebdSchin 			if (c==usrerase||c==usrkill||(!print(c) &&
284da2e3ebdSchin 				(c!='\r'&&c!='\n')))
285da2e3ebdSchin 			{
286da2e3ebdSchin 				/* accept a backslashed character */
287da2e3ebdSchin 				cur--;
288da2e3ebdSchin 				out[cur++] = c;
289da2e3ebdSchin 				out[eol] = '\0';
290da2e3ebdSchin 				draw(ep,APPEND);
291da2e3ebdSchin 				continue;
292da2e3ebdSchin 			}
293da2e3ebdSchin 		}
294da2e3ebdSchin 		if (c == usrkill)
295da2e3ebdSchin 		{
296da2e3ebdSchin 			c = KILLCHAR ;
297da2e3ebdSchin 		}
298da2e3ebdSchin 		else if (c == usrerase)
299da2e3ebdSchin 		{
300da2e3ebdSchin 			c = ERASECHAR ;
301da2e3ebdSchin 		}
302da2e3ebdSchin 		else if (c == usrlnext)
303da2e3ebdSchin 		{
304da2e3ebdSchin 			c = LNEXTCHAR ;
305da2e3ebdSchin 		}
306da2e3ebdSchin 		else if ((c == usreof)&&(eol == 0))
307da2e3ebdSchin 		{
308da2e3ebdSchin 			c = EOFCHAR;
309da2e3ebdSchin 		}
310da2e3ebdSchin #ifdef ESH_KAPPEND
311da2e3ebdSchin 		if (--killing <= 0)	/* reset killing flag */
312da2e3ebdSchin 			killing = 0;
313da2e3ebdSchin #endif
314da2e3ebdSchin 		oadjust = count = adjust;
315da2e3ebdSchin 		if(count<0)
316da2e3ebdSchin 			count = 1;
317da2e3ebdSchin 		adjust = -1;
318da2e3ebdSchin 		i = cur;
319da2e3ebdSchin 		switch(c)
320da2e3ebdSchin 		{
321da2e3ebdSchin 		case LNEXTCHAR:
322da2e3ebdSchin 			c = ed_getchar(ep->ed,2);
323da2e3ebdSchin 			goto do_default_processing;
324da2e3ebdSchin 		case cntl('V'):
325da2e3ebdSchin 			show_info(ep,fmtident(e_version));
326da2e3ebdSchin 			continue;
327da2e3ebdSchin 		case '\0':
328da2e3ebdSchin 			ep->mark = i;
329da2e3ebdSchin 			continue;
330da2e3ebdSchin 		case cntl('X'):
331da2e3ebdSchin 			xcommands(ep,count);
332da2e3ebdSchin 			continue;
333da2e3ebdSchin 		case EOFCHAR:
334da2e3ebdSchin 			ed_flush(ep->ed);
335da2e3ebdSchin 			tty_cooked(ERRIO);
336da2e3ebdSchin 			return(0);
337da2e3ebdSchin #ifdef u370
338da2e3ebdSchin 		case cntl('S') :
339da2e3ebdSchin 		case cntl('Q') :
340da2e3ebdSchin 			continue;
341da2e3ebdSchin #endif	/* u370 */
342da2e3ebdSchin 		case '\t':
343da2e3ebdSchin 			if(cur>0  && ep->ed->sh->nextprompt)
344da2e3ebdSchin 			{
345da2e3ebdSchin 				if(ep->ed->e_tabcount==0)
346da2e3ebdSchin 				{
347da2e3ebdSchin 					ep->ed->e_tabcount=1;
348da2e3ebdSchin 					ed_ungetchar(ep->ed,ESC);
349da2e3ebdSchin 					goto do_escape;
350da2e3ebdSchin 				}
351da2e3ebdSchin 				else if(ep->ed->e_tabcount==1)
352da2e3ebdSchin 				{
353da2e3ebdSchin 					ed_ungetchar(ep->ed,'=');
354da2e3ebdSchin 					goto do_escape;
355da2e3ebdSchin 				}
356da2e3ebdSchin 				ep->ed->e_tabcount = 0;
357da2e3ebdSchin 			}
358da2e3ebdSchin 		do_default_processing:
359da2e3ebdSchin 		default:
360da2e3ebdSchin 
361da2e3ebdSchin 			if ((eol+1) >= (scend)) /*  will not fit on line */
362da2e3ebdSchin 			{
363da2e3ebdSchin 				ed_ungetchar(ep->ed,c); /* save character for next line */
364da2e3ebdSchin 				goto process;
365da2e3ebdSchin 			}
366da2e3ebdSchin 			for(i= ++eol; i>cur; i--)
367da2e3ebdSchin 				out[i] = out[i-1];
368da2e3ebdSchin 			backslash =  (c == '\\');
369da2e3ebdSchin 			out[cur++] = c;
370da2e3ebdSchin 			draw(ep,APPEND);
371da2e3ebdSchin 			continue;
372da2e3ebdSchin 		case cntl('Y') :
373da2e3ebdSchin 			{
374da2e3ebdSchin 				c = genlen(kstack);
375da2e3ebdSchin 				if ((c + eol) > scend)
376da2e3ebdSchin 				{
377da2e3ebdSchin 					beep();
378da2e3ebdSchin 					continue;
379da2e3ebdSchin 				}
380da2e3ebdSchin 				ep->mark = i;
381da2e3ebdSchin 				for(i=eol;i>=cur;i--)
382da2e3ebdSchin 					out[c+i] = out[i];
383da2e3ebdSchin 				kptr=kstack;
384da2e3ebdSchin 				while (i = *kptr++)
385da2e3ebdSchin 					out[cur++] = i;
386da2e3ebdSchin 				draw(ep,UPDATE);
387da2e3ebdSchin 				eol = genlen(out);
388da2e3ebdSchin 				continue;
389da2e3ebdSchin 			}
390da2e3ebdSchin 		case '\n':
391da2e3ebdSchin 		case '\r':
392da2e3ebdSchin 			c = '\n';
393da2e3ebdSchin 			goto process;
394da2e3ebdSchin 
395da2e3ebdSchin 		case DELETE:	/* delete char 0x7f */
396da2e3ebdSchin 		case '\b':	/* backspace, ^h */
397da2e3ebdSchin 		case ERASECHAR :
398da2e3ebdSchin 			if (count > i)
399da2e3ebdSchin 				count = i;
400da2e3ebdSchin #ifdef ESH_KAPPEND
401da2e3ebdSchin 			kptr = &kstack[count];	/* move old contents here */
402da2e3ebdSchin 			if (killing)		/* prepend to killbuf */
403da2e3ebdSchin 			{
404da2e3ebdSchin 				c = genlen(kstack) + CHARSIZE; /* include '\0' */
405da2e3ebdSchin 				while(c--)	/* copy stuff */
406da2e3ebdSchin 					kptr[c] = kstack[c];
407da2e3ebdSchin 			}
408da2e3ebdSchin 			else
409da2e3ebdSchin 				*kptr = 0;	/* this is end of data */
410da2e3ebdSchin 			killing = 2;		/* we are killing */
411da2e3ebdSchin 			i -= count;
412da2e3ebdSchin 			eol -= count;
413da2e3ebdSchin 			genncpy(kstack,out+i,cur-i);
414da2e3ebdSchin #else
415da2e3ebdSchin 			while ((count--)&&(i>0))
416da2e3ebdSchin 			{
417da2e3ebdSchin 				i--;
418da2e3ebdSchin 				eol--;
419da2e3ebdSchin 			}
420da2e3ebdSchin 			genncpy(kstack,out+i,cur-i);
421da2e3ebdSchin 			kstack[cur-i] = 0;
422da2e3ebdSchin #endif /* ESH_KAPPEND */
423da2e3ebdSchin 			gencpy(out+i,out+cur);
424da2e3ebdSchin 			ep->mark = i;
425da2e3ebdSchin 			goto update;
426da2e3ebdSchin 		case cntl('W') :
427da2e3ebdSchin #ifdef ESH_KAPPEND
428da2e3ebdSchin 			++killing;		/* keep killing flag */
429da2e3ebdSchin #endif
430da2e3ebdSchin 			if (ep->mark > eol )
431da2e3ebdSchin 				ep->mark = eol;
432da2e3ebdSchin 			if (ep->mark == i)
433da2e3ebdSchin 				continue;
434da2e3ebdSchin 			if (ep->mark > i)
435da2e3ebdSchin 			{
436da2e3ebdSchin 				adjust = ep->mark - i;
437da2e3ebdSchin 				ed_ungetchar(ep->ed,cntl('D'));
438da2e3ebdSchin 				continue;
439da2e3ebdSchin 			}
440da2e3ebdSchin 			adjust = i - ep->mark;
441da2e3ebdSchin 			ed_ungetchar(ep->ed,usrerase);
442da2e3ebdSchin 			continue;
443da2e3ebdSchin 		case cntl('D') :
444da2e3ebdSchin 			ep->mark = i;
445da2e3ebdSchin #ifdef ESH_KAPPEND
446da2e3ebdSchin 			if (killing)
447da2e3ebdSchin 				kptr = &kstack[genlen(kstack)];	/* append here */
448da2e3ebdSchin 			else
449da2e3ebdSchin 				kptr = kstack;
450da2e3ebdSchin 			killing = 2;			/* we are now killing */
451da2e3ebdSchin #else
452da2e3ebdSchin 			kptr = kstack;
453da2e3ebdSchin #endif /* ESH_KAPPEND */
454da2e3ebdSchin 			while ((count--)&&(eol>0)&&(i<eol))
455da2e3ebdSchin 			{
456da2e3ebdSchin 				*kptr++ = out[i];
457da2e3ebdSchin 				eol--;
458da2e3ebdSchin 				while(1)
459da2e3ebdSchin 				{
460da2e3ebdSchin 					if ((out[i] = out[(i+1)])==0)
461da2e3ebdSchin 						break;
462da2e3ebdSchin 					i++;
463da2e3ebdSchin 				}
464da2e3ebdSchin 				i = cur;
465da2e3ebdSchin 			}
466da2e3ebdSchin 			*kptr = '\0';
467da2e3ebdSchin 			goto update;
468da2e3ebdSchin 		case cntl('C') :
469da2e3ebdSchin 		case cntl('F') :
470da2e3ebdSchin 		{
471da2e3ebdSchin 			int cntlC = (c==cntl('C'));
472da2e3ebdSchin 			while (count-- && eol>i)
473da2e3ebdSchin 			{
474da2e3ebdSchin 				if (cntlC)
475da2e3ebdSchin 				{
476da2e3ebdSchin 					c = out[i];
477da2e3ebdSchin #if SHOPT_MULTIBYTE
478da2e3ebdSchin 					if((c&~STRIP)==0 && islower(c))
479da2e3ebdSchin #else
480da2e3ebdSchin 					if(islower(c))
481da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
482da2e3ebdSchin 					{
483da2e3ebdSchin 						c += 'A' - 'a';
484da2e3ebdSchin 						out[i] = c;
485da2e3ebdSchin 					}
486da2e3ebdSchin 				}
487da2e3ebdSchin 				i++;
488da2e3ebdSchin 			}
489da2e3ebdSchin 			goto update;
490da2e3ebdSchin 		}
491da2e3ebdSchin 		case cntl(']') :
492da2e3ebdSchin 			c = ed_getchar(ep->ed,1);
493da2e3ebdSchin 			if ((count == 0) || (count > eol))
494da2e3ebdSchin                         {
495da2e3ebdSchin                                 beep();
496da2e3ebdSchin                                 continue;
497da2e3ebdSchin                         }
498da2e3ebdSchin 			if (out[i])
499da2e3ebdSchin 				i++;
500da2e3ebdSchin 			while (i < eol)
501da2e3ebdSchin 			{
502da2e3ebdSchin 				if (out[i] == c && --count==0)
503da2e3ebdSchin 					goto update;
504da2e3ebdSchin 				i++;
505da2e3ebdSchin 			}
506da2e3ebdSchin 			i = 0;
507da2e3ebdSchin 			while (i < cur)
508da2e3ebdSchin 			{
509da2e3ebdSchin 				if (out[i] == c && --count==0)
510da2e3ebdSchin 					break;
511da2e3ebdSchin 				i++;
512da2e3ebdSchin 			};
513da2e3ebdSchin 
514da2e3ebdSchin update:
515da2e3ebdSchin 			cur = i;
516da2e3ebdSchin 			draw(ep,UPDATE);
517da2e3ebdSchin 			continue;
518da2e3ebdSchin 
519da2e3ebdSchin 		case cntl('B') :
520da2e3ebdSchin 			if (count > i)
521da2e3ebdSchin 				count = i;
522da2e3ebdSchin 			i -= count;
523da2e3ebdSchin 			goto update;
524da2e3ebdSchin 		case cntl('T') :
525da2e3ebdSchin 			if ((sh_isoption(SH_EMACS))&& (eol!=i))
526da2e3ebdSchin 				i++;
527da2e3ebdSchin 			if (i >= 2)
528da2e3ebdSchin 			{
529da2e3ebdSchin 				c = out[i - 1];
530da2e3ebdSchin 				out[i-1] = out[i-2];
531da2e3ebdSchin 				out[i-2] = c;
532da2e3ebdSchin 			}
533da2e3ebdSchin 			else
534da2e3ebdSchin 			{
535da2e3ebdSchin 				if(sh_isoption(SH_EMACS))
536da2e3ebdSchin 					i--;
537da2e3ebdSchin 				beep();
538da2e3ebdSchin 				continue;
539da2e3ebdSchin 			}
540da2e3ebdSchin 			goto update;
541da2e3ebdSchin 		case cntl('A') :
542da2e3ebdSchin 			i = 0;
543da2e3ebdSchin 			goto update;
544da2e3ebdSchin 		case cntl('E') :
545da2e3ebdSchin 			i = eol;
546da2e3ebdSchin 			goto update;
547da2e3ebdSchin 		case cntl('U') :
548da2e3ebdSchin 			adjust = 4*count;
549da2e3ebdSchin 			continue;
550da2e3ebdSchin 		case KILLCHAR :
551da2e3ebdSchin 			cur = 0;
552da2e3ebdSchin 			oadjust = -1;
553da2e3ebdSchin 		case cntl('K') :
554da2e3ebdSchin 			if(oadjust >= 0)
555da2e3ebdSchin 			{
556da2e3ebdSchin #ifdef ESH_KAPPEND
557da2e3ebdSchin 				killing = 2;		/* set killing signal */
558da2e3ebdSchin #endif
559da2e3ebdSchin 				ep->mark = count;
560da2e3ebdSchin 				ed_ungetchar(ep->ed,cntl('W'));
561da2e3ebdSchin 				continue;
562da2e3ebdSchin 			}
563da2e3ebdSchin 			i = cur;
564da2e3ebdSchin 			eol = i;
565da2e3ebdSchin 			ep->mark = i;
566da2e3ebdSchin #ifdef ESH_KAPPEND
567da2e3ebdSchin 			if (killing)			/* append to kill buffer */
568da2e3ebdSchin 				gencpy(&kstack[genlen(kstack)], &out[i]);
569da2e3ebdSchin 			else
570da2e3ebdSchin 				gencpy(kstack,&out[i]);
571da2e3ebdSchin 			killing = 2;			/* set killing signal */
572da2e3ebdSchin #else
573da2e3ebdSchin 			gencpy(kstack,&out[i]);
574da2e3ebdSchin #endif /* ESH_KAPPEND */
575da2e3ebdSchin 			out[i] = 0;
576da2e3ebdSchin 			draw(ep,UPDATE);
577da2e3ebdSchin 			if (c == KILLCHAR)
578da2e3ebdSchin 			{
579da2e3ebdSchin 				if (ep->terminal == PAPER)
580da2e3ebdSchin 				{
581da2e3ebdSchin 					putchar(ep->ed,'\n');
582da2e3ebdSchin 					putstring(ep,Prompt);
583da2e3ebdSchin 				}
584da2e3ebdSchin 				c = ed_getchar(ep->ed,0);
585da2e3ebdSchin 				if (c != usrkill)
586da2e3ebdSchin 				{
587da2e3ebdSchin 					ed_ungetchar(ep->ed,c);
588da2e3ebdSchin 					continue;
589da2e3ebdSchin 				}
590da2e3ebdSchin 				if (ep->terminal == PAPER)
591da2e3ebdSchin 					ep->terminal = CRT;
592da2e3ebdSchin 				else
593da2e3ebdSchin 				{
594da2e3ebdSchin 					ep->terminal = PAPER;
595da2e3ebdSchin 					putchar(ep->ed,'\n');
596da2e3ebdSchin 					putstring(ep,Prompt);
597da2e3ebdSchin 				}
598da2e3ebdSchin 			}
599da2e3ebdSchin 			continue;
600da2e3ebdSchin 		case cntl('L'):
6017c2fbfb3SApril Chin 			if(!ep->ed->e_nocrnl)
602da2e3ebdSchin 				ed_crlf(ep->ed);
603da2e3ebdSchin 			draw(ep,REFRESH);
6047c2fbfb3SApril Chin 			ep->ed->e_nocrnl = 0;
605da2e3ebdSchin 			continue;
606da2e3ebdSchin 		case cntl('[') :
607da2e3ebdSchin 		do_escape:
608da2e3ebdSchin 			adjust = escape(ep,out,oadjust);
609da2e3ebdSchin 			continue;
610da2e3ebdSchin 		case cntl('R') :
611da2e3ebdSchin 			search(ep,out,count);
612da2e3ebdSchin 			goto drawline;
613da2e3ebdSchin 		case cntl('P') :
614da2e3ebdSchin                         if (count <= hloff)
615da2e3ebdSchin                                 hloff -= count;
616da2e3ebdSchin                         else
617da2e3ebdSchin                         {
618da2e3ebdSchin                                 hline -= count - hloff;
619da2e3ebdSchin                                 hloff = 0;
620da2e3ebdSchin                         }
621da2e3ebdSchin #ifdef ESH_NFIRST
622da2e3ebdSchin 			if (hline <= hismin)
623da2e3ebdSchin #else
624da2e3ebdSchin 			if (hline < hismin)
625da2e3ebdSchin #endif /* ESH_NFIRST */
626da2e3ebdSchin 			{
627da2e3ebdSchin 				hline = hismin+1;
628da2e3ebdSchin 				beep();
629da2e3ebdSchin #ifndef ESH_NFIRST
630da2e3ebdSchin 				continue;
631da2e3ebdSchin #endif
632da2e3ebdSchin 			}
633da2e3ebdSchin 			goto common;
634da2e3ebdSchin 
635da2e3ebdSchin 		case cntl('O') :
636da2e3ebdSchin 			location.hist_command = hline;
637da2e3ebdSchin 			location.hist_line = hloff;
638da2e3ebdSchin 			ep->CntrlO = 1;
639da2e3ebdSchin 			c = '\n';
640da2e3ebdSchin 			goto process;
641da2e3ebdSchin 		case cntl('N') :
642da2e3ebdSchin #ifdef ESH_NFIRST
643da2e3ebdSchin 			hline = location.hist_command;	/* start at saved position */
644da2e3ebdSchin 			hloff = location.hist_line;
645da2e3ebdSchin #endif /* ESH_NFIRST */
646da2e3ebdSchin 			location = hist_locate(sh.hist_ptr,hline,hloff,count);
647da2e3ebdSchin 			if (location.hist_command > histlines)
648da2e3ebdSchin 			{
649da2e3ebdSchin 				beep();
650da2e3ebdSchin #ifdef ESH_NFIRST
651da2e3ebdSchin 				location.hist_command = histlines;
652da2e3ebdSchin 				location.hist_line = ep->in_mult;
653da2e3ebdSchin #else
654da2e3ebdSchin 				continue;
655da2e3ebdSchin #endif /* ESH_NFIRST */
656da2e3ebdSchin 			}
657da2e3ebdSchin 			hline = location.hist_command;
658da2e3ebdSchin 			hloff = location.hist_line;
659da2e3ebdSchin 		common:
660da2e3ebdSchin #ifdef ESH_NFIRST
661da2e3ebdSchin 			location.hist_command = hline;	/* save current position */
662da2e3ebdSchin 			location.hist_line = hloff;
663da2e3ebdSchin #endif
6647c2fbfb3SApril Chin 			cur = 0;
6657c2fbfb3SApril Chin 			draw(ep,UPDATE);
666da2e3ebdSchin 			hist_copy((char*)out,MAXLINE, hline,hloff);
667da2e3ebdSchin #if SHOPT_MULTIBYTE
668da2e3ebdSchin 			ed_internal((char*)(out),out);
669da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
670da2e3ebdSchin 		drawline:
671da2e3ebdSchin 			eol = genlen(out);
672da2e3ebdSchin 			cur = eol;
673da2e3ebdSchin 			draw(ep,UPDATE);
674da2e3ebdSchin 			continue;
675da2e3ebdSchin 		}
676da2e3ebdSchin 
677da2e3ebdSchin 	}
678da2e3ebdSchin 
679da2e3ebdSchin process:
680da2e3ebdSchin 
681da2e3ebdSchin 	if (c == (-1))
682da2e3ebdSchin 	{
683da2e3ebdSchin 		lookahead = 0;
684da2e3ebdSchin 		beep();
685da2e3ebdSchin 		*out = '\0';
686da2e3ebdSchin 	}
687da2e3ebdSchin 	draw(ep,FINAL);
688da2e3ebdSchin 	tty_cooked(ERRIO);
689da2e3ebdSchin 	if(ed->e_nlist)
690da2e3ebdSchin 	{
691da2e3ebdSchin 		ed->e_nlist = 0;
692da2e3ebdSchin 		stakset(ed->e_stkptr,ed->e_stkoff);
693da2e3ebdSchin 	}
694da2e3ebdSchin 	if(c == '\n')
695da2e3ebdSchin 	{
696da2e3ebdSchin 		out[eol++] = '\n';
697da2e3ebdSchin 		out[eol] = '\0';
698da2e3ebdSchin 		ed_crlf(ep->ed);
699da2e3ebdSchin 	}
700da2e3ebdSchin #if SHOPT_MULTIBYTE
701da2e3ebdSchin 	ed_external(out,buff);
702da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
703da2e3ebdSchin 	i = strlen(buff);
704da2e3ebdSchin 	if (i)
705da2e3ebdSchin 		return(i);
706da2e3ebdSchin 	return(-1);
707da2e3ebdSchin }
708da2e3ebdSchin 
show_info(Emacs_t * ep,const char * str)709da2e3ebdSchin static void show_info(Emacs_t *ep,const char *str)
710da2e3ebdSchin {
711da2e3ebdSchin 	register genchar *out = drawbuff;
712da2e3ebdSchin 	register int c;
713da2e3ebdSchin 	genchar string[LBUF];
714da2e3ebdSchin 	int sav_cur = cur;
715da2e3ebdSchin 	/* save current line */
716da2e3ebdSchin 	genncpy(string,out,sizeof(string)/sizeof(*string));
717da2e3ebdSchin 	*out = 0;
718da2e3ebdSchin 	cur = 0;
719da2e3ebdSchin #if SHOPT_MULTIBYTE
720da2e3ebdSchin 	ed_internal(str,out);
721da2e3ebdSchin #else
722da2e3ebdSchin 	gencpy(out,str);
723da2e3ebdSchin #endif	/* SHOPT_MULTIBYTE */
724da2e3ebdSchin 	draw(ep,UPDATE);
725da2e3ebdSchin 	c = ed_getchar(ep->ed,0);
726da2e3ebdSchin 	if(c!=' ')
727da2e3ebdSchin 		ed_ungetchar(ep->ed,c);
728da2e3ebdSchin 	/* restore line */
729da2e3ebdSchin 	cur = sav_cur;
730da2e3ebdSchin 	genncpy(out,string,sizeof(string)/sizeof(*string));
731da2e3ebdSchin 	draw(ep,UPDATE);
732da2e3ebdSchin }
733da2e3ebdSchin 
putstring(Emacs_t * ep,register char * sp)734da2e3ebdSchin static void putstring(Emacs_t* ep,register char *sp)
735da2e3ebdSchin {
736da2e3ebdSchin 	register int c;
737da2e3ebdSchin 	while (c= *sp++)
738da2e3ebdSchin 		 putchar(ep->ed,c);
739da2e3ebdSchin }
740da2e3ebdSchin 
741da2e3ebdSchin 
escape(register Emacs_t * ep,register genchar * out,int count)742da2e3ebdSchin static int escape(register Emacs_t* ep,register genchar *out,int count)
743da2e3ebdSchin {
744da2e3ebdSchin 	register int i,value;
745da2e3ebdSchin 	int digit,ch;
746da2e3ebdSchin 	digit = 0;
747da2e3ebdSchin 	value = 0;
748da2e3ebdSchin 	while ((i=ed_getchar(ep->ed,0)),isdigit(i))
749da2e3ebdSchin 	{
750da2e3ebdSchin 		value *= 10;
751da2e3ebdSchin 		value += (i - '0');
752da2e3ebdSchin 		digit = 1;
753da2e3ebdSchin 	}
754da2e3ebdSchin 	if (digit)
755da2e3ebdSchin 	{
756da2e3ebdSchin 		ed_ungetchar(ep->ed,i) ;
757da2e3ebdSchin #ifdef ESH_KAPPEND
758da2e3ebdSchin 		++killing;		/* don't modify killing signal */
759da2e3ebdSchin #endif
760da2e3ebdSchin 		return(value);
761da2e3ebdSchin 	}
762da2e3ebdSchin 	value = count;
763da2e3ebdSchin 	if(value<0)
764da2e3ebdSchin 		value = 1;
765da2e3ebdSchin 	switch(ch=i)
766da2e3ebdSchin 	{
767da2e3ebdSchin 		case cntl('V'):
768da2e3ebdSchin 			show_info(ep,fmtident(e_version));
769da2e3ebdSchin 			return(-1);
770da2e3ebdSchin 		case ' ':
771da2e3ebdSchin 			ep->mark = cur;
772da2e3ebdSchin 			return(-1);
773da2e3ebdSchin 
774da2e3ebdSchin #ifdef ESH_KAPPEND
775da2e3ebdSchin 		case '+':		/* M-+ = append next kill */
776da2e3ebdSchin 			killing = 2;
777da2e3ebdSchin 			return -1;	/* no argument for next command */
778da2e3ebdSchin #endif
779da2e3ebdSchin 
780da2e3ebdSchin 		case 'p':	/* M-p == ^W^Y (copy stack == kill & yank) */
781da2e3ebdSchin 			ed_ungetchar(ep->ed,cntl('Y'));
782da2e3ebdSchin 			ed_ungetchar(ep->ed,cntl('W'));
783da2e3ebdSchin #ifdef ESH_KAPPEND
784da2e3ebdSchin 			killing = 0;	/* start fresh */
785da2e3ebdSchin #endif
786da2e3ebdSchin 			return(-1);
787da2e3ebdSchin 
788da2e3ebdSchin 		case 'l':	/* M-l == lower-case */
789da2e3ebdSchin 		case 'd':
790da2e3ebdSchin 		case 'c':
791da2e3ebdSchin 		case 'f':
792da2e3ebdSchin 		{
793da2e3ebdSchin 			i = cur;
794da2e3ebdSchin 			while(value-- && i<eol)
795da2e3ebdSchin 			{
796da2e3ebdSchin 				while ((out[i])&&(!isword(i)))
797da2e3ebdSchin 					i++;
798da2e3ebdSchin 				while ((out[i])&&(isword(i)))
799da2e3ebdSchin 					i++;
800da2e3ebdSchin 			}
801da2e3ebdSchin 			if(ch=='l')
802da2e3ebdSchin 			{
803da2e3ebdSchin 				value = i-cur;
804da2e3ebdSchin 				while (value-- > 0)
805da2e3ebdSchin 				{
806da2e3ebdSchin 					i = out[cur];
807da2e3ebdSchin #if SHOPT_MULTIBYTE
808da2e3ebdSchin 					if((i&~STRIP)==0 && isupper(i))
809da2e3ebdSchin #else
810da2e3ebdSchin 					if(isupper(i))
811da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
812da2e3ebdSchin 					{
813da2e3ebdSchin 						i += 'a' - 'A';
814da2e3ebdSchin 						out[cur] = i;
815da2e3ebdSchin 					}
816da2e3ebdSchin 					cur++;
817da2e3ebdSchin 				}
818da2e3ebdSchin 				draw(ep,UPDATE);
819da2e3ebdSchin 				return(-1);
820da2e3ebdSchin 			}
821da2e3ebdSchin 
822da2e3ebdSchin 			else if(ch=='f')
823da2e3ebdSchin 				goto update;
824da2e3ebdSchin 			else if(ch=='c')
825da2e3ebdSchin 			{
826da2e3ebdSchin 				ed_ungetchar(ep->ed,cntl('C'));
827da2e3ebdSchin 				return(i-cur);
828da2e3ebdSchin 			}
829da2e3ebdSchin 			else
830da2e3ebdSchin 			{
831da2e3ebdSchin 				if (i-cur)
832da2e3ebdSchin 				{
833da2e3ebdSchin 					ed_ungetchar(ep->ed,cntl('D'));
834da2e3ebdSchin #ifdef ESH_KAPPEND
835da2e3ebdSchin 					++killing;	/* keep killing signal */
836da2e3ebdSchin #endif
837da2e3ebdSchin 					return(i-cur);
838da2e3ebdSchin 				}
839da2e3ebdSchin 				beep();
840da2e3ebdSchin 				return(-1);
841da2e3ebdSchin 			}
842da2e3ebdSchin 		}
843da2e3ebdSchin 
844da2e3ebdSchin 
845da2e3ebdSchin 		case 'b':
846da2e3ebdSchin 		case DELETE :
847da2e3ebdSchin 		case '\b':
848da2e3ebdSchin 		case 'h':
849da2e3ebdSchin 		{
850da2e3ebdSchin 			i = cur;
851da2e3ebdSchin 			while(value-- && i>0)
852da2e3ebdSchin 			{
853da2e3ebdSchin 				i--;
854da2e3ebdSchin 				while ((i>0)&&(!isword(i)))
855da2e3ebdSchin 					i--;
856da2e3ebdSchin 				while ((i>0)&&(isword(i-1)))
857da2e3ebdSchin 					i--;
858da2e3ebdSchin 			}
859da2e3ebdSchin 			if(ch=='b')
860da2e3ebdSchin 				goto update;
861da2e3ebdSchin 			else
862da2e3ebdSchin 			{
863da2e3ebdSchin 				ed_ungetchar(ep->ed,usrerase);
864da2e3ebdSchin #ifdef ESH_KAPPEND
865da2e3ebdSchin 				++killing;
866da2e3ebdSchin #endif
867da2e3ebdSchin 				return(cur-i);
868da2e3ebdSchin 			}
869da2e3ebdSchin 		}
870da2e3ebdSchin 
871da2e3ebdSchin 		case '>':
872da2e3ebdSchin 			ed_ungetchar(ep->ed,cntl('N'));
873da2e3ebdSchin #ifdef ESH_NFIRST
874da2e3ebdSchin 			if (ep->in_mult)
875da2e3ebdSchin 			{
876da2e3ebdSchin 				location.hist_command = histlines;
877da2e3ebdSchin 				location.hist_line = ep->in_mult - 1;
878da2e3ebdSchin 			}
879da2e3ebdSchin 			else
880da2e3ebdSchin 			{
881da2e3ebdSchin 				location.hist_command = histlines - 1;
882da2e3ebdSchin 				location.hist_line = 0;
883da2e3ebdSchin 			}
884da2e3ebdSchin #else
885da2e3ebdSchin 			hline = histlines-1;
886da2e3ebdSchin 			hloff = 0;
887da2e3ebdSchin #endif /* ESH_NFIRST */
888da2e3ebdSchin 			return(0);
889da2e3ebdSchin 
890da2e3ebdSchin 		case '<':
891da2e3ebdSchin 			ed_ungetchar(ep->ed,cntl('P'));
892da2e3ebdSchin 			hloff = 0;
893da2e3ebdSchin #ifdef ESH_NFIRST
894da2e3ebdSchin 			hline = hismin + 1;
895da2e3ebdSchin 			return 0;
896da2e3ebdSchin #else
897da2e3ebdSchin 			return(hline-hismin);
898da2e3ebdSchin #endif /* ESH_NFIRST */
899da2e3ebdSchin 
900da2e3ebdSchin 
901da2e3ebdSchin 		case '#':
902da2e3ebdSchin 			ed_ungetchar(ep->ed,'\n');
903da2e3ebdSchin 			ed_ungetchar(ep->ed,(out[0]=='#')?cntl('D'):'#');
904da2e3ebdSchin 			ed_ungetchar(ep->ed,cntl('A'));
905da2e3ebdSchin 			return(-1);
906da2e3ebdSchin 		case '_' :
907da2e3ebdSchin 		case '.' :
908da2e3ebdSchin 		{
909da2e3ebdSchin 			genchar name[MAXLINE];
910da2e3ebdSchin 			char buf[MAXLINE];
911da2e3ebdSchin 			char *ptr;
912da2e3ebdSchin 			ptr = hist_word(buf,MAXLINE,(count?count:-1));
913da2e3ebdSchin 			if(ptr==0)
914da2e3ebdSchin 			{
915da2e3ebdSchin 				beep();
916da2e3ebdSchin 				break;
917da2e3ebdSchin 			}
918da2e3ebdSchin 			if ((eol - cur) >= sizeof(name))
919da2e3ebdSchin 			{
920da2e3ebdSchin 				beep();
921da2e3ebdSchin 				return(-1);
922da2e3ebdSchin 			}
923da2e3ebdSchin 			ep->mark = cur;
924da2e3ebdSchin 			gencpy(name,&out[cur]);
925da2e3ebdSchin 			while(*ptr)
926da2e3ebdSchin 			{
927da2e3ebdSchin 				out[cur++] = *ptr++;
928da2e3ebdSchin 				eol++;
929da2e3ebdSchin 			}
930da2e3ebdSchin 			gencpy(&out[cur],name);
931da2e3ebdSchin 			draw(ep,UPDATE);
932da2e3ebdSchin 			return(-1);
933da2e3ebdSchin 		}
934da2e3ebdSchin #if KSHELL
935da2e3ebdSchin 
936da2e3ebdSchin 		/* file name expansion */
937da2e3ebdSchin 		case cntl('[') :	/* filename completion */
938da2e3ebdSchin 			i = '\\';
939da2e3ebdSchin 		case '*':		/* filename expansion */
940da2e3ebdSchin 		case '=':	/* escape = - list all matching file names */
941da2e3ebdSchin 			ep->mark = cur;
942da2e3ebdSchin 			if(ed_expand(ep->ed,(char*)out,&cur,&eol,i,count) < 0)
943da2e3ebdSchin 			{
944da2e3ebdSchin 				if(ep->ed->e_tabcount==1)
945da2e3ebdSchin 				{
946da2e3ebdSchin 					ep->ed->e_tabcount=2;
947da2e3ebdSchin 					ed_ungetchar(ep->ed,cntl('\t'));
948da2e3ebdSchin 					return(-1);
949da2e3ebdSchin 				}
950da2e3ebdSchin 				beep();
951da2e3ebdSchin 			}
952da2e3ebdSchin 			else if(i=='=')
953da2e3ebdSchin 			{
954da2e3ebdSchin 				draw(ep,REFRESH);
955da2e3ebdSchin 				if(count>0)
956da2e3ebdSchin 					ep->ed->e_tabcount=0;
957da2e3ebdSchin 				else
958da2e3ebdSchin 				{
959da2e3ebdSchin 					i=ed_getchar(ep->ed,0);
960da2e3ebdSchin 					ed_ungetchar(ep->ed,i);
961da2e3ebdSchin 					if(isdigit(i))
962da2e3ebdSchin 						ed_ungetchar(ep->ed,ESC);
963da2e3ebdSchin 				}
964da2e3ebdSchin 			}
965da2e3ebdSchin 			else
966da2e3ebdSchin 			{
967da2e3ebdSchin 				if(i=='\\' && cur>ep->mark && (out[cur-1]=='/' || out[cur-1]==' '))
968da2e3ebdSchin 					ep->ed->e_tabcount=0;
969da2e3ebdSchin 				draw(ep,UPDATE);
970da2e3ebdSchin 			}
971da2e3ebdSchin 			return(-1);
972da2e3ebdSchin 
973da2e3ebdSchin 		/* search back for character */
974da2e3ebdSchin 		case cntl(']'):	/* feature not in book */
975da2e3ebdSchin 		{
976da2e3ebdSchin 			int c = ed_getchar(ep->ed,1);
977da2e3ebdSchin 			if ((value == 0) || (value > eol))
978da2e3ebdSchin 			{
979da2e3ebdSchin 				beep();
980da2e3ebdSchin 				return(-1);
981da2e3ebdSchin 			}
982da2e3ebdSchin 			i = cur;
983da2e3ebdSchin 			if (i > 0)
984da2e3ebdSchin 				i--;
985da2e3ebdSchin 			while (i >= 0)
986da2e3ebdSchin 			{
987da2e3ebdSchin 				if (out[i] == c && --value==0)
988da2e3ebdSchin 					goto update;
989da2e3ebdSchin 				i--;
990da2e3ebdSchin 			}
991da2e3ebdSchin 			i = eol;
992da2e3ebdSchin 			while (i > cur)
993da2e3ebdSchin 			{
994da2e3ebdSchin 				if (out[i] == c && --value==0)
995da2e3ebdSchin 					break;
996da2e3ebdSchin 				i--;
997da2e3ebdSchin 			};
998da2e3ebdSchin 
999da2e3ebdSchin 		}
1000da2e3ebdSchin 		update:
1001da2e3ebdSchin 			cur = i;
1002da2e3ebdSchin 			draw(ep,UPDATE);
1003da2e3ebdSchin 			return(-1);
1004da2e3ebdSchin 
1005da2e3ebdSchin #ifdef _cmd_tput
1006da2e3ebdSchin 		case cntl('L'): /* clear screen */
1007da2e3ebdSchin 			sh_trap("tput clear", 0);
1008da2e3ebdSchin 			draw(ep,REFRESH);
1009da2e3ebdSchin 			return(-1);
1010da2e3ebdSchin #endif
1011da2e3ebdSchin 		case '[':	/* feature not in book */
1012da2e3ebdSchin 			switch(i=ed_getchar(ep->ed,1))
1013da2e3ebdSchin 			{
1014da2e3ebdSchin 			    case 'A':
10157c2fbfb3SApril Chin 				if(cur>0 && eol==cur && (cur<(SEARCHSIZE-2) || ep->prevdirection == -2))
10167c2fbfb3SApril Chin 				{
10177c2fbfb3SApril Chin 					if(ep->lastdraw==APPEND && ep->prevdirection != -2)
10187c2fbfb3SApril Chin 					{
10197c2fbfb3SApril Chin 						out[cur] = 0;
10207c2fbfb3SApril Chin 						gencpy(&((genchar*)lstring)[1],out);
10217c2fbfb3SApril Chin #if SHOPT_MULTIBYTE
10227c2fbfb3SApril Chin 						ed_external(&((genchar*)lstring)[1],lstring+1);
10237c2fbfb3SApril Chin #endif /* SHOPT_MULTIBYTE */
10247c2fbfb3SApril Chin 						*lstring = '^';
10257c2fbfb3SApril Chin 						ep->prevdirection = -2;
10267c2fbfb3SApril Chin 					}
10277c2fbfb3SApril Chin 					if(*lstring)
10287c2fbfb3SApril Chin 					{
10297c2fbfb3SApril Chin 						ed_ungetchar(ep->ed,'\r');
10307c2fbfb3SApril Chin 						ed_ungetchar(ep->ed,cntl('R'));
10317c2fbfb3SApril Chin 						return(-1);
10327c2fbfb3SApril Chin 					}
10337c2fbfb3SApril Chin 				}
10347c2fbfb3SApril Chin 				*lstring = 0;
1035da2e3ebdSchin 				ed_ungetchar(ep->ed,cntl('P'));
1036da2e3ebdSchin 				return(-1);
1037da2e3ebdSchin 			    case 'B':
1038da2e3ebdSchin 				ed_ungetchar(ep->ed,cntl('N'));
1039da2e3ebdSchin 				return(-1);
1040da2e3ebdSchin 			    case 'C':
1041da2e3ebdSchin 				ed_ungetchar(ep->ed,cntl('F'));
1042da2e3ebdSchin 				return(-1);
1043da2e3ebdSchin 			    case 'D':
1044da2e3ebdSchin 				ed_ungetchar(ep->ed,cntl('B'));
1045da2e3ebdSchin 				return(-1);
1046da2e3ebdSchin 			    case 'H':
1047da2e3ebdSchin 				ed_ungetchar(ep->ed,cntl('A'));
1048da2e3ebdSchin 				return(-1);
1049da2e3ebdSchin 			    case 'Y':
1050da2e3ebdSchin 				ed_ungetchar(ep->ed,cntl('E'));
1051da2e3ebdSchin 				return(-1);
1052da2e3ebdSchin 			    default:
1053da2e3ebdSchin 				ed_ungetchar(ep->ed,i);
1054da2e3ebdSchin 			}
1055da2e3ebdSchin 			i = '_';
1056da2e3ebdSchin 
1057da2e3ebdSchin 		default:
1058da2e3ebdSchin 			/* look for user defined macro definitions */
1059da2e3ebdSchin 			if(ed_macro(ep->ed,i))
1060da2e3ebdSchin #   ifdef ESH_BETTER
1061da2e3ebdSchin 				return(count);	/* pass argument to macro */
1062da2e3ebdSchin #   else
1063da2e3ebdSchin 				return(-1);
1064da2e3ebdSchin #   endif /* ESH_BETTER */
1065da2e3ebdSchin #else
1066da2e3ebdSchin 		update:
1067da2e3ebdSchin 			cur = i;
1068da2e3ebdSchin 			draw(ep,UPDATE);
1069da2e3ebdSchin 			return(-1);
1070da2e3ebdSchin 
1071da2e3ebdSchin 		default:
1072da2e3ebdSchin #endif	/* KSHELL */
1073da2e3ebdSchin 		beep();
1074da2e3ebdSchin 		return(-1);
1075da2e3ebdSchin 	}
107634f9b3eeSRoland Mainz 	return(-1);
1077da2e3ebdSchin }
1078da2e3ebdSchin 
1079da2e3ebdSchin 
1080da2e3ebdSchin /*
1081da2e3ebdSchin  * This routine process all commands starting with ^X
1082da2e3ebdSchin  */
1083da2e3ebdSchin 
xcommands(register Emacs_t * ep,int count)1084da2e3ebdSchin static void xcommands(register Emacs_t *ep,int count)
1085da2e3ebdSchin {
1086da2e3ebdSchin         register int i = ed_getchar(ep->ed,0);
1087da2e3ebdSchin 	NOT_USED(count);
1088da2e3ebdSchin         switch(i)
1089da2e3ebdSchin         {
1090da2e3ebdSchin                 case cntl('X'):	/* exchange dot and mark */
1091da2e3ebdSchin                         if (ep->mark > eol)
1092da2e3ebdSchin                                 ep->mark = eol;
1093da2e3ebdSchin                         i = ep->mark;
1094da2e3ebdSchin                         ep->mark = cur;
1095da2e3ebdSchin                         cur = i;
1096da2e3ebdSchin                         draw(ep,UPDATE);
1097da2e3ebdSchin                         return;
1098da2e3ebdSchin 
1099da2e3ebdSchin #if KSHELL
1100da2e3ebdSchin #   ifdef ESH_BETTER
1101da2e3ebdSchin                 case cntl('E'):	/* invoke emacs on current command */
1102da2e3ebdSchin 			if(ed_fulledit(ep->ed)==-1)
1103da2e3ebdSchin 				beep();
1104da2e3ebdSchin 			else
1105da2e3ebdSchin 			{
1106da2e3ebdSchin #if SHOPT_MULTIBYTE
1107da2e3ebdSchin 				ed_internal((char*)drawbuff,drawbuff);
1108da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
1109da2e3ebdSchin 				ed_ungetchar(ep->ed,'\n');
1110da2e3ebdSchin 			}
1111da2e3ebdSchin 			return;
1112da2e3ebdSchin 
1113da2e3ebdSchin #	define itos(i)	fmtbase((long)(i),0,0)/* want signed conversion */
1114da2e3ebdSchin 
1115da2e3ebdSchin 		case cntl('H'):		/* ^X^H show history info */
1116da2e3ebdSchin 			{
1117da2e3ebdSchin 				char hbuf[MAXLINE];
1118da2e3ebdSchin 
1119da2e3ebdSchin 				strcpy(hbuf, "Current command ");
1120da2e3ebdSchin 				strcat(hbuf, itos(hline));
1121da2e3ebdSchin 				if (hloff)
1122da2e3ebdSchin 				{
1123da2e3ebdSchin 					strcat(hbuf, " (line ");
1124da2e3ebdSchin 					strcat(hbuf, itos(hloff+1));
1125da2e3ebdSchin 					strcat(hbuf, ")");
1126da2e3ebdSchin 				}
1127da2e3ebdSchin 				if ((hline != location.hist_command) ||
1128da2e3ebdSchin 				    (hloff != location.hist_line))
1129da2e3ebdSchin 				{
1130da2e3ebdSchin 					strcat(hbuf, "; Previous command ");
1131da2e3ebdSchin 					strcat(hbuf, itos(location.hist_command));
1132da2e3ebdSchin 					if (location.hist_line)
1133da2e3ebdSchin 					{
1134da2e3ebdSchin 						strcat(hbuf, " (line ");
1135da2e3ebdSchin 						strcat(hbuf, itos(location.hist_line+1));
1136da2e3ebdSchin 						strcat(hbuf, ")");
1137da2e3ebdSchin 					}
1138da2e3ebdSchin 				}
1139da2e3ebdSchin 				show_info(ep,hbuf);
1140da2e3ebdSchin 				return;
1141da2e3ebdSchin 			}
1142da2e3ebdSchin #	if 0	/* debugging, modify as required */
1143da2e3ebdSchin 		case cntl('D'):		/* ^X^D show debugging info */
1144da2e3ebdSchin 			{
1145da2e3ebdSchin 				char debugbuf[MAXLINE];
1146da2e3ebdSchin 
1147da2e3ebdSchin 				strcpy(debugbuf, "count=");
1148da2e3ebdSchin 				strcat(debugbuf, itos(count));
1149da2e3ebdSchin 				strcat(debugbuf, " eol=");
1150da2e3ebdSchin 				strcat(debugbuf, itos(eol));
1151da2e3ebdSchin 				strcat(debugbuf, " cur=");
1152da2e3ebdSchin 				strcat(debugbuf, itos(cur));
1153da2e3ebdSchin 				strcat(debugbuf, " crallowed=");
1154da2e3ebdSchin 				strcat(debugbuf, itos(crallowed));
1155da2e3ebdSchin 				strcat(debugbuf, " plen=");
1156da2e3ebdSchin 				strcat(debugbuf, itos(plen));
1157da2e3ebdSchin 				strcat(debugbuf, " w_size=");
1158da2e3ebdSchin 				strcat(debugbuf, itos(w_size));
1159da2e3ebdSchin 
1160da2e3ebdSchin 				show_info(ep,debugbuf);
1161da2e3ebdSchin 				return;
1162da2e3ebdSchin 			}
1163da2e3ebdSchin #	endif /* debugging code */
1164da2e3ebdSchin #   endif /* ESH_BETTER */
1165da2e3ebdSchin #endif /* KSHELL */
1166da2e3ebdSchin 
1167da2e3ebdSchin                 default:
1168da2e3ebdSchin                         beep();
1169da2e3ebdSchin                         return;
1170da2e3ebdSchin 	}
1171da2e3ebdSchin }
1172da2e3ebdSchin 
search(Emacs_t * ep,genchar * out,int direction)1173da2e3ebdSchin static void search(Emacs_t* ep,genchar *out,int direction)
1174da2e3ebdSchin {
1175da2e3ebdSchin #ifndef ESH_NFIRST
1176da2e3ebdSchin 	Histloc_t location;
1177da2e3ebdSchin #endif
1178da2e3ebdSchin 	register int i,sl;
1179da2e3ebdSchin 	genchar str_buff[LBUF];
1180da2e3ebdSchin 	register genchar *string = drawbuff;
1181da2e3ebdSchin 	/* save current line */
1182da2e3ebdSchin 	int sav_cur = cur;
1183da2e3ebdSchin 	genncpy(str_buff,string,sizeof(str_buff)/sizeof(*str_buff));
1184da2e3ebdSchin 	string[0] = '^';
1185da2e3ebdSchin 	string[1] = 'R';
1186da2e3ebdSchin 	string[2] = '\0';
1187da2e3ebdSchin 	sl = 2;
1188da2e3ebdSchin 	cur = sl;
1189da2e3ebdSchin 	draw(ep,UPDATE);
1190da2e3ebdSchin 	while ((i = ed_getchar(ep->ed,1))&&(i != '\r')&&(i != '\n'))
1191da2e3ebdSchin 	{
1192da2e3ebdSchin 		if (i==usrerase || i==DELETE || i=='\b' || i==ERASECHAR)
1193da2e3ebdSchin 		{
1194da2e3ebdSchin 			if (sl > 2)
1195da2e3ebdSchin 			{
1196da2e3ebdSchin 				string[--sl] = '\0';
1197da2e3ebdSchin 				cur = sl;
1198da2e3ebdSchin 				draw(ep,UPDATE);
1199da2e3ebdSchin 			}
1200da2e3ebdSchin 			else
1201da2e3ebdSchin 				beep();
1202da2e3ebdSchin 			continue;
1203da2e3ebdSchin 		}
1204da2e3ebdSchin 		if (i==usrkill)
1205da2e3ebdSchin 		{
1206da2e3ebdSchin 			beep();
1207da2e3ebdSchin 			goto restore;
1208da2e3ebdSchin 		}
1209da2e3ebdSchin 		if (i == '\\')
1210da2e3ebdSchin 		{
1211da2e3ebdSchin 			string[sl++] = '\\';
1212da2e3ebdSchin 			string[sl] = '\0';
1213da2e3ebdSchin 			cur = sl;
1214da2e3ebdSchin 			draw(ep,APPEND);
1215da2e3ebdSchin 			i = ed_getchar(ep->ed,1);
1216da2e3ebdSchin 			string[--sl] = '\0';
1217da2e3ebdSchin 		}
1218da2e3ebdSchin 		string[sl++] = i;
1219da2e3ebdSchin 		string[sl] = '\0';
1220da2e3ebdSchin 		cur = sl;
1221da2e3ebdSchin 		draw(ep,APPEND);
1222da2e3ebdSchin 	}
1223da2e3ebdSchin 	i = genlen(string);
1224da2e3ebdSchin 
12257c2fbfb3SApril Chin 	if(ep->prevdirection == -2 && i!=2 || direction!=1)
12267c2fbfb3SApril Chin 		ep->prevdirection = -1;
1227da2e3ebdSchin 	if (direction < 1)
1228da2e3ebdSchin 	{
1229da2e3ebdSchin 		ep->prevdirection = -ep->prevdirection;
1230da2e3ebdSchin 		direction = 1;
1231da2e3ebdSchin 	}
1232da2e3ebdSchin 	else
1233da2e3ebdSchin 		direction = -1;
1234da2e3ebdSchin 	if (i != 2)
1235da2e3ebdSchin 	{
1236da2e3ebdSchin #if SHOPT_MULTIBYTE
1237da2e3ebdSchin 		ed_external(string,(char*)string);
1238da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
1239da2e3ebdSchin 		strncpy(lstring,((char*)string)+2,SEARCHSIZE);
1240da2e3ebdSchin 		ep->prevdirection = direction;
1241da2e3ebdSchin 	}
1242da2e3ebdSchin 	else
1243da2e3ebdSchin 		direction = ep->prevdirection ;
1244da2e3ebdSchin 	location = hist_find(sh.hist_ptr,(char*)lstring,hline,1,direction);
1245da2e3ebdSchin 	i = location.hist_command;
1246da2e3ebdSchin 	if(i>0)
1247da2e3ebdSchin 	{
1248da2e3ebdSchin 		hline = i;
1249da2e3ebdSchin #ifdef ESH_NFIRST
1250da2e3ebdSchin 		hloff = location.hist_line = 0;	/* display first line of multi line command */
1251da2e3ebdSchin #else
1252da2e3ebdSchin 		hloff = location.hist_line;
1253da2e3ebdSchin #endif /* ESH_NFIRST */
1254da2e3ebdSchin 		hist_copy((char*)out,MAXLINE, hline,hloff);
1255da2e3ebdSchin #if SHOPT_MULTIBYTE
1256da2e3ebdSchin 		ed_internal((char*)out,out);
1257da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
1258da2e3ebdSchin 		return;
1259da2e3ebdSchin 	}
1260da2e3ebdSchin 	if (i < 0)
1261da2e3ebdSchin 	{
1262da2e3ebdSchin 		beep();
1263da2e3ebdSchin #ifdef ESH_NFIRST
1264da2e3ebdSchin 		location.hist_command = hline;
1265da2e3ebdSchin 		location.hist_line = hloff;
1266da2e3ebdSchin #else
1267da2e3ebdSchin 		hloff = 0;
1268da2e3ebdSchin 		hline = histlines;
1269da2e3ebdSchin #endif /* ESH_NFIRST */
1270da2e3ebdSchin 	}
1271da2e3ebdSchin restore:
1272da2e3ebdSchin 	genncpy(string,str_buff,sizeof(str_buff)/sizeof(*str_buff));
1273da2e3ebdSchin 	cur = sav_cur;
1274da2e3ebdSchin 	return;
1275da2e3ebdSchin }
1276da2e3ebdSchin 
1277da2e3ebdSchin 
1278da2e3ebdSchin /* Adjust screen to agree with inputs: logical line and cursor */
1279da2e3ebdSchin /* If 'first' assume screen is blank */
1280da2e3ebdSchin /* Prompt is always kept on the screen */
1281da2e3ebdSchin 
draw(register Emacs_t * ep,Draw_t option)1282da2e3ebdSchin static void draw(register Emacs_t *ep,Draw_t option)
1283da2e3ebdSchin {
1284da2e3ebdSchin #define	NORMAL ' '
1285da2e3ebdSchin #define	LOWER  '<'
1286da2e3ebdSchin #define	BOTH   '*'
1287da2e3ebdSchin #define	UPPER  '>'
1288da2e3ebdSchin 
1289da2e3ebdSchin 	register genchar *sptr;		/* Pointer within screen */
1290da2e3ebdSchin 	genchar nscreen[2*MAXLINE];	/* New entire screen */
1291da2e3ebdSchin 	genchar *ncursor;		/* New cursor */
1292da2e3ebdSchin 	register genchar *nptr;		/* Pointer to New screen */
1293da2e3ebdSchin 	char  longline;			/* Line overflow */
1294da2e3ebdSchin 	genchar *logcursor;
1295da2e3ebdSchin 	genchar *nscend;		/* end of logical screen */
1296da2e3ebdSchin 	register int i;
1297da2e3ebdSchin 
1298da2e3ebdSchin 	nptr = nscreen;
1299da2e3ebdSchin 	sptr = drawbuff;
1300da2e3ebdSchin 	logcursor = sptr + cur;
1301da2e3ebdSchin 	longline = NORMAL;
13027c2fbfb3SApril Chin 	ep->lastdraw = option;
1303da2e3ebdSchin 
1304da2e3ebdSchin 	if (option == FIRST || option == REFRESH)
1305da2e3ebdSchin 	{
1306da2e3ebdSchin 		ep->overflow = NORMAL;
1307da2e3ebdSchin 		ep->cursor = ep->screen;
1308da2e3ebdSchin 		ep->offset = 0;
1309da2e3ebdSchin 		ep->cr_ok = crallowed;
1310da2e3ebdSchin 		if (option == FIRST)
1311da2e3ebdSchin 		{
1312da2e3ebdSchin 			ep->scvalid = 1;
1313da2e3ebdSchin 			return;
1314da2e3ebdSchin 		}
1315da2e3ebdSchin 		*ep->cursor = '\0';
1316da2e3ebdSchin 		putstring(ep,Prompt);	/* start with prompt */
1317da2e3ebdSchin 	}
1318da2e3ebdSchin 
1319da2e3ebdSchin 	/*********************
1320da2e3ebdSchin 	 Do not update screen if pending characters
1321da2e3ebdSchin 	**********************/
1322da2e3ebdSchin 
1323da2e3ebdSchin 	if ((lookahead)&&(option != FINAL))
1324da2e3ebdSchin 	{
1325da2e3ebdSchin 
1326da2e3ebdSchin 		ep->scvalid = 0; /* Screen is out of date, APPEND will not work */
1327da2e3ebdSchin 
1328da2e3ebdSchin 		return;
1329da2e3ebdSchin 	}
1330da2e3ebdSchin 
1331da2e3ebdSchin 	/***************************************
1332da2e3ebdSchin 	If in append mode, cursor at end of line, screen up to date,
1333da2e3ebdSchin 	the previous character was a 'normal' character,
1334da2e3ebdSchin 	and the window has room for another character.
1335da2e3ebdSchin 	Then output the character and adjust the screen only.
1336da2e3ebdSchin 	*****************************************/
1337da2e3ebdSchin 
1338da2e3ebdSchin 
1339da2e3ebdSchin 	i = *(logcursor-1);	/* last character inserted */
1340da2e3ebdSchin 
1341da2e3ebdSchin 	if ((option == APPEND)&&(ep->scvalid)&&(*logcursor == '\0')&&
1342da2e3ebdSchin 	    print(i)&&((ep->cursor-ep->screen)<(w_size-1)))
1343da2e3ebdSchin 	{
1344da2e3ebdSchin 		putchar(ep->ed,i);
1345da2e3ebdSchin 		*ep->cursor++ = i;
1346da2e3ebdSchin 		*ep->cursor = '\0';
1347da2e3ebdSchin 		return;
1348da2e3ebdSchin 	}
1349da2e3ebdSchin 
1350da2e3ebdSchin 	/* copy the line */
1351da2e3ebdSchin 	ncursor = nptr + ed_virt_to_phys(ep->ed,sptr,nptr,cur,0,0);
1352da2e3ebdSchin 	nptr += genlen(nptr);
1353da2e3ebdSchin 	sptr += genlen(sptr);
1354da2e3ebdSchin 	nscend = nptr - 1;
1355da2e3ebdSchin 	if(sptr == logcursor)
1356da2e3ebdSchin 		ncursor = nptr;
1357da2e3ebdSchin 
1358da2e3ebdSchin 	/*********************
1359da2e3ebdSchin 	 Does ncursor appear on the screen?
1360da2e3ebdSchin 	 If not, adjust the screen offset so it does.
1361da2e3ebdSchin 	**********************/
1362da2e3ebdSchin 
1363da2e3ebdSchin 	i = ncursor - nscreen;
1364da2e3ebdSchin 
1365da2e3ebdSchin 	if ((ep->offset && i<=ep->offset)||(i >= (ep->offset+w_size)))
1366da2e3ebdSchin 	{
1367da2e3ebdSchin 		/* Center the cursor on the screen */
1368da2e3ebdSchin 		ep->offset = i - (w_size>>1);
1369da2e3ebdSchin 		if (--ep->offset < 0)
1370da2e3ebdSchin 			ep->offset = 0;
1371da2e3ebdSchin 	}
1372da2e3ebdSchin 
1373da2e3ebdSchin 	/*********************
1374da2e3ebdSchin 	 Is the range of screen[0] thru screen[w_size] up-to-date
1375da2e3ebdSchin 	 with nscreen[offset] thru nscreen[offset+w_size] ?
1376da2e3ebdSchin 	 If not, update as need be.
1377da2e3ebdSchin 	***********************/
1378da2e3ebdSchin 
1379da2e3ebdSchin 	nptr = &nscreen[ep->offset];
1380da2e3ebdSchin 	sptr = ep->screen;
1381da2e3ebdSchin 
1382da2e3ebdSchin 	i = w_size;
1383da2e3ebdSchin 
1384da2e3ebdSchin 	while (i-- > 0)
1385da2e3ebdSchin 	{
1386da2e3ebdSchin 
1387da2e3ebdSchin 		if (*nptr == '\0')
1388da2e3ebdSchin 		{
1389da2e3ebdSchin 			*(nptr + 1) = '\0';
1390da2e3ebdSchin 			*nptr = ' ';
1391da2e3ebdSchin 		}
1392da2e3ebdSchin 		if (*sptr == '\0')
1393da2e3ebdSchin 		{
1394da2e3ebdSchin 			*(sptr + 1) = '\0';
1395da2e3ebdSchin 			*sptr = ' ';
1396da2e3ebdSchin 		}
1397da2e3ebdSchin 		if (*nptr == *sptr)
1398da2e3ebdSchin 		{
1399da2e3ebdSchin 			nptr++;
1400da2e3ebdSchin 			sptr++;
1401da2e3ebdSchin 			continue;
1402da2e3ebdSchin 		}
1403da2e3ebdSchin 		setcursor(ep,sptr-ep->screen,*nptr);
1404da2e3ebdSchin 		*sptr++ = *nptr++;
1405da2e3ebdSchin #if SHOPT_MULTIBYTE
1406da2e3ebdSchin 		while(*nptr==MARKER)
1407da2e3ebdSchin 		{
1408da2e3ebdSchin 			if(*sptr=='\0')
1409da2e3ebdSchin 				*(sptr + 1) = '\0';
1410da2e3ebdSchin 			*sptr++ = *nptr++;
1411da2e3ebdSchin 			i--;
1412da2e3ebdSchin 			ep->cursor++;
1413da2e3ebdSchin 		}
1414da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
1415da2e3ebdSchin 	}
14167c2fbfb3SApril Chin 	if(ep->ed->e_multiline && option == REFRESH && ep->ed->e_nocrnl==0)
14177c2fbfb3SApril Chin 		ed_setcursor(ep->ed, ep->screen, ep->cursor-ep->screen, ep->ed->e_peol, -1);
14187c2fbfb3SApril Chin 
1419da2e3ebdSchin 
1420da2e3ebdSchin 	/******************
1421da2e3ebdSchin 
1422da2e3ebdSchin 	Screen overflow checks
1423da2e3ebdSchin 
1424da2e3ebdSchin 	********************/
1425da2e3ebdSchin 
1426da2e3ebdSchin 	if (nscend >= &nscreen[ep->offset+w_size])
1427da2e3ebdSchin 	{
1428da2e3ebdSchin 		if (ep->offset > 0)
1429da2e3ebdSchin 			longline = BOTH;
1430da2e3ebdSchin 		else
1431da2e3ebdSchin 			longline = UPPER;
1432da2e3ebdSchin 	}
1433da2e3ebdSchin 	else
1434da2e3ebdSchin 	{
1435da2e3ebdSchin 		if (ep->offset > 0)
1436da2e3ebdSchin 			longline = LOWER;
1437da2e3ebdSchin 	}
1438da2e3ebdSchin 
1439da2e3ebdSchin 	/* Update screen overflow indicator if need be */
1440da2e3ebdSchin 
1441da2e3ebdSchin 	if (longline != ep->overflow)
1442da2e3ebdSchin 	{
1443da2e3ebdSchin 		setcursor(ep,w_size,longline);
1444da2e3ebdSchin 		ep->overflow = longline;
1445da2e3ebdSchin 	}
1446da2e3ebdSchin 	i = (ncursor-nscreen) - ep->offset;
1447da2e3ebdSchin 	setcursor(ep,i,0);
1448da2e3ebdSchin 	if(option==FINAL && ep->ed->e_multiline)
14497c2fbfb3SApril Chin 		setcursor(ep,nscend+1-nscreen,0);
1450da2e3ebdSchin 	ep->scvalid = 1;
1451da2e3ebdSchin 	return;
1452da2e3ebdSchin }
1453da2e3ebdSchin 
1454da2e3ebdSchin /*
1455da2e3ebdSchin  * put the cursor to the <newp> position within screen buffer
1456da2e3ebdSchin  * if <c> is non-zero then output this character
1457da2e3ebdSchin  * cursor is set to reflect the change
1458da2e3ebdSchin  */
1459da2e3ebdSchin 
setcursor(register Emacs_t * ep,register int newp,int c)1460da2e3ebdSchin static void setcursor(register Emacs_t *ep,register int newp,int c)
1461da2e3ebdSchin {
1462da2e3ebdSchin 	register int oldp = ep->cursor - ep->screen;
1463da2e3ebdSchin 	newp  = ed_setcursor(ep->ed, ep->screen, oldp, newp, 0);
1464da2e3ebdSchin 	if(c)
1465da2e3ebdSchin 	{
1466da2e3ebdSchin 		putchar(ep->ed,c);
1467da2e3ebdSchin 		newp++;
1468da2e3ebdSchin 	}
1469da2e3ebdSchin 	ep->cursor = ep->screen+newp;
1470da2e3ebdSchin 	return;
1471da2e3ebdSchin }
1472da2e3ebdSchin 
1473da2e3ebdSchin #if SHOPT_MULTIBYTE
print(register int c)1474da2e3ebdSchin static int print(register int c)
1475da2e3ebdSchin {
1476da2e3ebdSchin 	return((c&~STRIP)==0 && isprint(c));
1477da2e3ebdSchin }
1478da2e3ebdSchin 
_isword(register int c)1479da2e3ebdSchin static int _isword(register int c)
1480da2e3ebdSchin {
1481da2e3ebdSchin 	return((c&~STRIP) || isalnum(c) || c=='_');
1482da2e3ebdSchin }
1483da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
1484