1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1982-2012 AT&T Intellectual Property          *
5da2e3ebdSchin *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
77c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
8da2e3ebdSchin *                                                                      *
9da2e3ebdSchin *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
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])
93*b30d1939SAndy Fiddaman #   define digit(c)	((c&~STRIP)==0 && isdigit(c))
94da2e3ebdSchin 
95da2e3ebdSchin #else
96da2e3ebdSchin #   define gencpy(a,b)	strcpy((char*)(a),(char*)(b))
97da2e3ebdSchin #   define genncpy(a,b,n)	strncpy((char*)(a),(char*)(b),n)
98da2e3ebdSchin #   define genlen(str)	strlen(str)
99da2e3ebdSchin #   define print(c)	isprint(c)
100da2e3ebdSchin #   define isword(c)	(isalnum(out[c]) || (out[c]=='_'))
101*b30d1939SAndy Fiddaman #   define digit(c)	isdigit(c)
102da2e3ebdSchin #endif /*SHOPT_MULTIBYTE */
103da2e3ebdSchin 
104da2e3ebdSchin typedef struct _emacs_
105da2e3ebdSchin {
106da2e3ebdSchin 	genchar *screen;	/* pointer to window buffer */
107da2e3ebdSchin 	genchar *cursor;	/* Cursor in real screen */
108da2e3ebdSchin 	int 	mark;
109da2e3ebdSchin 	int 	in_mult;
110da2e3ebdSchin 	char	cr_ok;
111da2e3ebdSchin 	char	CntrlO;
112da2e3ebdSchin 	char	overflow;		/* Screen overflow flag set */
113da2e3ebdSchin 	char	scvalid;		/* Screen is up to date */
1147c2fbfb3SApril Chin 	char	lastdraw;	/* last update type */
115da2e3ebdSchin 	int	offset;		/* Screen offset */
116da2e3ebdSchin 	enum
117da2e3ebdSchin 	{
118da2e3ebdSchin 		CRT=0,	/* Crt terminal */
119da2e3ebdSchin 		PAPER	/* Paper terminal */
120da2e3ebdSchin 	} terminal;
121da2e3ebdSchin 	Histloc_t _location;
122da2e3ebdSchin 	int	prevdirection;
123da2e3ebdSchin 	Edit_t	*ed;	/* pointer to edit data */
124da2e3ebdSchin } Emacs_t;
125da2e3ebdSchin 
126da2e3ebdSchin #define	editb		(*ep->ed)
127da2e3ebdSchin #define eol		editb.e_eol
128da2e3ebdSchin #define cur		editb.e_cur
129da2e3ebdSchin #define hline		editb.e_hline
130da2e3ebdSchin #define hloff		editb.e_hloff
131da2e3ebdSchin #define hismin		editb.e_hismin
132da2e3ebdSchin #define usrkill		editb.e_kill
133da2e3ebdSchin #define usrlnext	editb.e_lnext
134da2e3ebdSchin #define usreof		editb.e_eof
135da2e3ebdSchin #define usrerase	editb.e_erase
136da2e3ebdSchin #define crallowed	editb.e_crlf
137da2e3ebdSchin #define Prompt		editb.e_prompt
138da2e3ebdSchin #define plen		editb.e_plen
139da2e3ebdSchin #define kstack		editb.e_killbuf
140da2e3ebdSchin #define lstring		editb.e_search
141da2e3ebdSchin #define lookahead	editb.e_lookahead
142da2e3ebdSchin #define env		editb.e_env
143da2e3ebdSchin #define raw		editb.e_raw
144da2e3ebdSchin #define histlines	editb.e_hismax
145da2e3ebdSchin #define w_size		editb.e_wsize
146da2e3ebdSchin #define drawbuff	editb.e_inbuf
147da2e3ebdSchin #define killing		editb.e_mode
148da2e3ebdSchin #define location	ep->_location
149da2e3ebdSchin 
150da2e3ebdSchin #define LBUF	100
151da2e3ebdSchin #define KILLCHAR	UKILL
152da2e3ebdSchin #define ERASECHAR	UERASE
153da2e3ebdSchin #define EOFCHAR		UEOF
154da2e3ebdSchin #define LNEXTCHAR		ULNEXT
155da2e3ebdSchin #define DELETE		('a'==97?0177:7)
156da2e3ebdSchin 
157da2e3ebdSchin /**********************
158da2e3ebdSchin A large lookahead helps when the user is inserting
159da2e3ebdSchin characters in the middle of the line.
160da2e3ebdSchin ************************/
161da2e3ebdSchin 
162da2e3ebdSchin 
163da2e3ebdSchin typedef enum
164da2e3ebdSchin {
165da2e3ebdSchin 	FIRST,		/* First time thru for logical line, prompt on screen */
166da2e3ebdSchin 	REFRESH,	/* Redraw entire screen */
167da2e3ebdSchin 	APPEND,		/* Append char before cursor to screen */
168da2e3ebdSchin 	UPDATE,		/* Update the screen as need be */
169da2e3ebdSchin 	FINAL		/* Update screen even if pending look ahead */
170da2e3ebdSchin } Draw_t;
171da2e3ebdSchin 
172da2e3ebdSchin static void draw(Emacs_t*,Draw_t);
173da2e3ebdSchin static int escape(Emacs_t*,genchar*, int);
174da2e3ebdSchin static void putstring(Emacs_t*,char*);
175da2e3ebdSchin static void search(Emacs_t*,genchar*,int);
176da2e3ebdSchin static void setcursor(Emacs_t*,int, int);
177da2e3ebdSchin static void show_info(Emacs_t*,const char*);
178da2e3ebdSchin static void xcommands(Emacs_t*,int);
179da2e3ebdSchin 
ed_emacsread(void * context,int fd,char * buff,int scend,int reedit)180da2e3ebdSchin int ed_emacsread(void *context, int fd,char *buff,int scend, int reedit)
181da2e3ebdSchin {
182da2e3ebdSchin 	Edit_t *ed = (Edit_t*)context;
183da2e3ebdSchin 	register int c;
184da2e3ebdSchin 	register int i;
185da2e3ebdSchin 	register genchar *out;
186da2e3ebdSchin 	register int count;
187da2e3ebdSchin 	register Emacs_t *ep = ed->e_emacs;
188da2e3ebdSchin 	int adjust,oadjust;
189da2e3ebdSchin 	char backslash;
190da2e3ebdSchin 	genchar *kptr;
191da2e3ebdSchin 	char prompt[PRSIZE];
192da2e3ebdSchin 	genchar Screen[MAXLINE];
193*b30d1939SAndy Fiddaman 	memset(Screen,0,sizeof(Screen));
194da2e3ebdSchin 	if(!ep)
195da2e3ebdSchin 	{
196da2e3ebdSchin 		ep = ed->e_emacs = newof(0,Emacs_t,1,0);
197da2e3ebdSchin 		ep->ed = ed;
198da2e3ebdSchin 		ep->prevdirection =  1;
199da2e3ebdSchin 		location.hist_command =  -5;
200da2e3ebdSchin 	}
201da2e3ebdSchin 	Prompt = prompt;
202da2e3ebdSchin 	ep->screen = Screen;
2037c2fbfb3SApril Chin 	ep->lastdraw = FINAL;
204da2e3ebdSchin 	if(tty_raw(ERRIO,0) < 0)
205da2e3ebdSchin 	{
206da2e3ebdSchin 		 return(reedit?reedit:ed_read(context, fd,buff,scend,0));
207da2e3ebdSchin 	}
208da2e3ebdSchin 	raw = 1;
209da2e3ebdSchin 	/* This mess in case the read system call fails */
210da2e3ebdSchin 
211da2e3ebdSchin 	ed_setup(ep->ed,fd,reedit);
212da2e3ebdSchin 	out = (genchar*)buff;
213da2e3ebdSchin #if SHOPT_MULTIBYTE
21434f9b3eeSRoland Mainz 	out = (genchar*)roundof(buff-(char*)0,sizeof(genchar));
21534f9b3eeSRoland Mainz 	if(reedit)
21634f9b3eeSRoland Mainz 		ed_internal(buff,out);
217da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
218da2e3ebdSchin 	if(!kstack)
219da2e3ebdSchin 	{
220da2e3ebdSchin 		kstack = (genchar*)malloc(CHARSIZE*MAXLINE);
221da2e3ebdSchin 		kstack[0] = '\0';
222da2e3ebdSchin 	}
223da2e3ebdSchin 	drawbuff = out;
224da2e3ebdSchin #ifdef ESH_NFIRST
225da2e3ebdSchin 	if (location.hist_command == -5)		/* to be initialized */
226da2e3ebdSchin 	{
227da2e3ebdSchin 		kstack[0] = '\0';		/* also clear kstack... */
228da2e3ebdSchin 		location.hist_command = hline;
229da2e3ebdSchin 		location.hist_line = hloff;
230da2e3ebdSchin 	}
231da2e3ebdSchin 	if (location.hist_command <= hismin)	/* don't start below minimum */
232da2e3ebdSchin 	{
233da2e3ebdSchin 		location.hist_command = hismin + 1;
234da2e3ebdSchin 		location.hist_line = 0;
235da2e3ebdSchin 	}
236da2e3ebdSchin 	ep->in_mult = hloff;			/* save pos in last command */
237da2e3ebdSchin #endif /* ESH_NFIRST */
238da2e3ebdSchin 	i = sigsetjmp(env,0);
239da2e3ebdSchin 	if (i !=0)
240da2e3ebdSchin 	{
2417c2fbfb3SApril Chin 		if(ep->ed->e_multiline)
2427c2fbfb3SApril Chin 		{
2437c2fbfb3SApril Chin 			cur = eol;
2447c2fbfb3SApril Chin 			draw(ep,FINAL);
2457c2fbfb3SApril Chin 			ed_flush(ep->ed);
2467c2fbfb3SApril Chin 		}
247da2e3ebdSchin 		tty_cooked(ERRIO);
248da2e3ebdSchin 		if (i == UEOF)
249da2e3ebdSchin 		{
250da2e3ebdSchin 			return(0); /* EOF */
251da2e3ebdSchin 		}
252da2e3ebdSchin 		return(-1); /* some other error */
253da2e3ebdSchin 	}
254da2e3ebdSchin 	out[reedit] = 0;
255da2e3ebdSchin 	if(scend+plen > (MAXLINE-2))
256da2e3ebdSchin 		scend = (MAXLINE-2)-plen;
257da2e3ebdSchin 	ep->mark = 0;
258da2e3ebdSchin 	cur = eol;
259da2e3ebdSchin 	draw(ep,reedit?REFRESH:FIRST);
260da2e3ebdSchin 	adjust = -1;
261da2e3ebdSchin 	backslash = 0;
262da2e3ebdSchin 	if (ep->CntrlO)
263da2e3ebdSchin 	{
264da2e3ebdSchin #ifdef ESH_NFIRST
265da2e3ebdSchin 		ed_ungetchar(ep->ed,cntl('N'));
266da2e3ebdSchin #else
267*b30d1939SAndy Fiddaman 		location = hist_locate(shgd->hist_ptr,location.hist_command,location.hist_line,1);
268da2e3ebdSchin 		if (location.hist_command < histlines)
269da2e3ebdSchin 		{
270da2e3ebdSchin 			hline = location.hist_command;
271da2e3ebdSchin 			hloff = location.hist_line;
272da2e3ebdSchin 			hist_copy((char*)kstack,MAXLINE, hline,hloff);
273da2e3ebdSchin #   if SHOPT_MULTIBYTE
274da2e3ebdSchin 			ed_internal((char*)kstack,kstack);
275da2e3ebdSchin #   endif /* SHOPT_MULTIBYTE */
276da2e3ebdSchin 			ed_ungetchar(ep->ed,cntl('Y'));
277da2e3ebdSchin 		}
278da2e3ebdSchin #endif /* ESH_NFIRST */
279da2e3ebdSchin 	}
280da2e3ebdSchin 	ep->CntrlO = 0;
281da2e3ebdSchin 	while ((c = ed_getchar(ep->ed,0)) != (-1))
282da2e3ebdSchin 	{
283da2e3ebdSchin 		if (backslash)
284da2e3ebdSchin 		{
285da2e3ebdSchin 			backslash = 0;
286da2e3ebdSchin 			if (c==usrerase||c==usrkill||(!print(c) &&
287da2e3ebdSchin 				(c!='\r'&&c!='\n')))
288da2e3ebdSchin 			{
289da2e3ebdSchin 				/* accept a backslashed character */
290da2e3ebdSchin 				cur--;
291da2e3ebdSchin 				out[cur++] = c;
292da2e3ebdSchin 				out[eol] = '\0';
293da2e3ebdSchin 				draw(ep,APPEND);
294da2e3ebdSchin 				continue;
295da2e3ebdSchin 			}
296da2e3ebdSchin 		}
297da2e3ebdSchin 		if (c == usrkill)
298da2e3ebdSchin 		{
299da2e3ebdSchin 			c = KILLCHAR ;
300da2e3ebdSchin 		}
301da2e3ebdSchin 		else if (c == usrerase)
302da2e3ebdSchin 		{
303da2e3ebdSchin 			c = ERASECHAR ;
304da2e3ebdSchin 		}
305da2e3ebdSchin 		else if (c == usrlnext)
306da2e3ebdSchin 		{
307da2e3ebdSchin 			c = LNEXTCHAR ;
308da2e3ebdSchin 		}
309da2e3ebdSchin 		else if ((c == usreof)&&(eol == 0))
310da2e3ebdSchin 		{
311da2e3ebdSchin 			c = EOFCHAR;
312da2e3ebdSchin 		}
313da2e3ebdSchin #ifdef ESH_KAPPEND
314da2e3ebdSchin 		if (--killing <= 0)	/* reset killing flag */
315da2e3ebdSchin 			killing = 0;
316da2e3ebdSchin #endif
317da2e3ebdSchin 		oadjust = count = adjust;
318da2e3ebdSchin 		if(count<0)
319da2e3ebdSchin 			count = 1;
320da2e3ebdSchin 		adjust = -1;
321da2e3ebdSchin 		i = cur;
322*b30d1939SAndy Fiddaman 		if(c!='\t' && c!=ESC && !digit(c))
323*b30d1939SAndy Fiddaman 			ep->ed->e_tabcount = 0;
324da2e3ebdSchin 		switch(c)
325da2e3ebdSchin 		{
326da2e3ebdSchin 		case LNEXTCHAR:
327da2e3ebdSchin 			c = ed_getchar(ep->ed,2);
328da2e3ebdSchin 			goto do_default_processing;
329da2e3ebdSchin 		case cntl('V'):
330da2e3ebdSchin 			show_info(ep,fmtident(e_version));
331da2e3ebdSchin 			continue;
332da2e3ebdSchin 		case '\0':
333da2e3ebdSchin 			ep->mark = i;
334da2e3ebdSchin 			continue;
335da2e3ebdSchin 		case cntl('X'):
336da2e3ebdSchin 			xcommands(ep,count);
337da2e3ebdSchin 			continue;
338da2e3ebdSchin 		case EOFCHAR:
339da2e3ebdSchin 			ed_flush(ep->ed);
340da2e3ebdSchin 			tty_cooked(ERRIO);
341da2e3ebdSchin 			return(0);
342da2e3ebdSchin #ifdef u370
343da2e3ebdSchin 		case cntl('S') :
344da2e3ebdSchin 		case cntl('Q') :
345da2e3ebdSchin 			continue;
346da2e3ebdSchin #endif	/* u370 */
347da2e3ebdSchin 		case '\t':
348da2e3ebdSchin 			if(cur>0  && ep->ed->sh->nextprompt)
349da2e3ebdSchin 			{
350da2e3ebdSchin 				if(ep->ed->e_tabcount==0)
351da2e3ebdSchin 				{
352da2e3ebdSchin 					ep->ed->e_tabcount=1;
353da2e3ebdSchin 					ed_ungetchar(ep->ed,ESC);
354da2e3ebdSchin 					goto do_escape;
355da2e3ebdSchin 				}
356da2e3ebdSchin 				else if(ep->ed->e_tabcount==1)
357da2e3ebdSchin 				{
358da2e3ebdSchin 					ed_ungetchar(ep->ed,'=');
359da2e3ebdSchin 					goto do_escape;
360da2e3ebdSchin 				}
361da2e3ebdSchin 				ep->ed->e_tabcount = 0;
362da2e3ebdSchin 			}
3635ae8bd53SToomas Soome 			/* FALLTHROUGH */
364da2e3ebdSchin 		do_default_processing:
365da2e3ebdSchin 		default:
366da2e3ebdSchin 
367da2e3ebdSchin 			if ((eol+1) >= (scend)) /*  will not fit on line */
368da2e3ebdSchin 			{
369da2e3ebdSchin 				ed_ungetchar(ep->ed,c); /* save character for next line */
370da2e3ebdSchin 				goto process;
371da2e3ebdSchin 			}
372da2e3ebdSchin 			for(i= ++eol; i>cur; i--)
373da2e3ebdSchin 				out[i] = out[i-1];
374da2e3ebdSchin 			backslash =  (c == '\\');
375da2e3ebdSchin 			out[cur++] = c;
376da2e3ebdSchin 			draw(ep,APPEND);
377da2e3ebdSchin 			continue;
378da2e3ebdSchin 		case cntl('Y') :
379da2e3ebdSchin 			{
380da2e3ebdSchin 				c = genlen(kstack);
381da2e3ebdSchin 				if ((c + eol) > scend)
382da2e3ebdSchin 				{
383da2e3ebdSchin 					beep();
384da2e3ebdSchin 					continue;
385da2e3ebdSchin 				}
386da2e3ebdSchin 				ep->mark = i;
387da2e3ebdSchin 				for(i=eol;i>=cur;i--)
388da2e3ebdSchin 					out[c+i] = out[i];
389da2e3ebdSchin 				kptr=kstack;
390da2e3ebdSchin 				while (i = *kptr++)
391da2e3ebdSchin 					out[cur++] = i;
392da2e3ebdSchin 				draw(ep,UPDATE);
393da2e3ebdSchin 				eol = genlen(out);
394da2e3ebdSchin 				continue;
395da2e3ebdSchin 			}
396da2e3ebdSchin 		case '\n':
397da2e3ebdSchin 		case '\r':
398da2e3ebdSchin 			c = '\n';
399da2e3ebdSchin 			goto process;
400da2e3ebdSchin 
401da2e3ebdSchin 		case DELETE:	/* delete char 0x7f */
402da2e3ebdSchin 		case '\b':	/* backspace, ^h */
403da2e3ebdSchin 		case ERASECHAR :
404da2e3ebdSchin 			if (count > i)
405da2e3ebdSchin 				count = i;
406da2e3ebdSchin #ifdef ESH_KAPPEND
407da2e3ebdSchin 			kptr = &kstack[count];	/* move old contents here */
408da2e3ebdSchin 			if (killing)		/* prepend to killbuf */
409da2e3ebdSchin 			{
410da2e3ebdSchin 				c = genlen(kstack) + CHARSIZE; /* include '\0' */
411da2e3ebdSchin 				while(c--)	/* copy stuff */
412da2e3ebdSchin 					kptr[c] = kstack[c];
413da2e3ebdSchin 			}
414da2e3ebdSchin 			else
415da2e3ebdSchin 				*kptr = 0;	/* this is end of data */
416da2e3ebdSchin 			killing = 2;		/* we are killing */
417da2e3ebdSchin 			i -= count;
418da2e3ebdSchin 			eol -= count;
419da2e3ebdSchin 			genncpy(kstack,out+i,cur-i);
420da2e3ebdSchin #else
421da2e3ebdSchin 			while ((count--)&&(i>0))
422da2e3ebdSchin 			{
423da2e3ebdSchin 				i--;
424da2e3ebdSchin 				eol--;
425da2e3ebdSchin 			}
426da2e3ebdSchin 			genncpy(kstack,out+i,cur-i);
427da2e3ebdSchin 			kstack[cur-i] = 0;
428da2e3ebdSchin #endif /* ESH_KAPPEND */
429da2e3ebdSchin 			gencpy(out+i,out+cur);
430da2e3ebdSchin 			ep->mark = i;
431da2e3ebdSchin 			goto update;
432da2e3ebdSchin 		case cntl('W') :
433da2e3ebdSchin #ifdef ESH_KAPPEND
434da2e3ebdSchin 			++killing;		/* keep killing flag */
435da2e3ebdSchin #endif
436da2e3ebdSchin 			if (ep->mark > eol )
437da2e3ebdSchin 				ep->mark = eol;
438da2e3ebdSchin 			if (ep->mark == i)
439da2e3ebdSchin 				continue;
440da2e3ebdSchin 			if (ep->mark > i)
441da2e3ebdSchin 			{
442da2e3ebdSchin 				adjust = ep->mark - i;
443da2e3ebdSchin 				ed_ungetchar(ep->ed,cntl('D'));
444da2e3ebdSchin 				continue;
445da2e3ebdSchin 			}
446da2e3ebdSchin 			adjust = i - ep->mark;
447da2e3ebdSchin 			ed_ungetchar(ep->ed,usrerase);
448da2e3ebdSchin 			continue;
449da2e3ebdSchin 		case cntl('D') :
450da2e3ebdSchin 			ep->mark = i;
451da2e3ebdSchin #ifdef ESH_KAPPEND
452da2e3ebdSchin 			if (killing)
453da2e3ebdSchin 				kptr = &kstack[genlen(kstack)];	/* append here */
454da2e3ebdSchin 			else
455da2e3ebdSchin 				kptr = kstack;
456da2e3ebdSchin 			killing = 2;			/* we are now killing */
457da2e3ebdSchin #else
458da2e3ebdSchin 			kptr = kstack;
459da2e3ebdSchin #endif /* ESH_KAPPEND */
460da2e3ebdSchin 			while ((count--)&&(eol>0)&&(i<eol))
461da2e3ebdSchin 			{
462da2e3ebdSchin 				*kptr++ = out[i];
463da2e3ebdSchin 				eol--;
464da2e3ebdSchin 				while(1)
465da2e3ebdSchin 				{
466da2e3ebdSchin 					if ((out[i] = out[(i+1)])==0)
467da2e3ebdSchin 						break;
468da2e3ebdSchin 					i++;
469da2e3ebdSchin 				}
470da2e3ebdSchin 				i = cur;
471da2e3ebdSchin 			}
472da2e3ebdSchin 			*kptr = '\0';
473da2e3ebdSchin 			goto update;
474da2e3ebdSchin 		case cntl('C') :
475da2e3ebdSchin 		case cntl('F') :
476da2e3ebdSchin 		{
477da2e3ebdSchin 			int cntlC = (c==cntl('C'));
478da2e3ebdSchin 			while (count-- && eol>i)
479da2e3ebdSchin 			{
480da2e3ebdSchin 				if (cntlC)
481da2e3ebdSchin 				{
482da2e3ebdSchin 					c = out[i];
483da2e3ebdSchin #if SHOPT_MULTIBYTE
484da2e3ebdSchin 					if((c&~STRIP)==0 && islower(c))
485da2e3ebdSchin #else
486da2e3ebdSchin 					if(islower(c))
487da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
488da2e3ebdSchin 					{
489da2e3ebdSchin 						c += 'A' - 'a';
490da2e3ebdSchin 						out[i] = c;
491da2e3ebdSchin 					}
492da2e3ebdSchin 				}
493da2e3ebdSchin 				i++;
494da2e3ebdSchin 			}
495da2e3ebdSchin 			goto update;
496da2e3ebdSchin 		}
497da2e3ebdSchin 		case cntl(']') :
498da2e3ebdSchin 			c = ed_getchar(ep->ed,1);
499da2e3ebdSchin 			if ((count == 0) || (count > eol))
500da2e3ebdSchin                         {
501da2e3ebdSchin                                 beep();
502da2e3ebdSchin                                 continue;
503da2e3ebdSchin                         }
504da2e3ebdSchin 			if (out[i])
505da2e3ebdSchin 				i++;
506da2e3ebdSchin 			while (i < eol)
507da2e3ebdSchin 			{
508da2e3ebdSchin 				if (out[i] == c && --count==0)
509da2e3ebdSchin 					goto update;
510da2e3ebdSchin 				i++;
511da2e3ebdSchin 			}
512da2e3ebdSchin 			i = 0;
513da2e3ebdSchin 			while (i < cur)
514da2e3ebdSchin 			{
515da2e3ebdSchin 				if (out[i] == c && --count==0)
516da2e3ebdSchin 					break;
517da2e3ebdSchin 				i++;
518da2e3ebdSchin 			};
519da2e3ebdSchin 
520da2e3ebdSchin update:
521da2e3ebdSchin 			cur = i;
522da2e3ebdSchin 			draw(ep,UPDATE);
523da2e3ebdSchin 			continue;
524da2e3ebdSchin 
525da2e3ebdSchin 		case cntl('B') :
526da2e3ebdSchin 			if (count > i)
527da2e3ebdSchin 				count = i;
528da2e3ebdSchin 			i -= count;
529da2e3ebdSchin 			goto update;
530da2e3ebdSchin 		case cntl('T') :
531da2e3ebdSchin 			if ((sh_isoption(SH_EMACS))&& (eol!=i))
532da2e3ebdSchin 				i++;
533da2e3ebdSchin 			if (i >= 2)
534da2e3ebdSchin 			{
535da2e3ebdSchin 				c = out[i - 1];
536da2e3ebdSchin 				out[i-1] = out[i-2];
537da2e3ebdSchin 				out[i-2] = c;
538da2e3ebdSchin 			}
539da2e3ebdSchin 			else
540da2e3ebdSchin 			{
541da2e3ebdSchin 				if(sh_isoption(SH_EMACS))
542da2e3ebdSchin 					i--;
543da2e3ebdSchin 				beep();
544da2e3ebdSchin 				continue;
545da2e3ebdSchin 			}
546da2e3ebdSchin 			goto update;
547da2e3ebdSchin 		case cntl('A') :
548da2e3ebdSchin 			i = 0;
549da2e3ebdSchin 			goto update;
550da2e3ebdSchin 		case cntl('E') :
551da2e3ebdSchin 			i = eol;
552da2e3ebdSchin 			goto update;
553da2e3ebdSchin 		case cntl('U') :
554da2e3ebdSchin 			adjust = 4*count;
555da2e3ebdSchin 			continue;
556da2e3ebdSchin 		case KILLCHAR :
557da2e3ebdSchin 			cur = 0;
558da2e3ebdSchin 			oadjust = -1;
5595ae8bd53SToomas Soome 			/* FALLTHROUGH */
560da2e3ebdSchin 		case cntl('K') :
561da2e3ebdSchin 			if(oadjust >= 0)
562da2e3ebdSchin 			{
563da2e3ebdSchin #ifdef ESH_KAPPEND
564da2e3ebdSchin 				killing = 2;		/* set killing signal */
565da2e3ebdSchin #endif
566da2e3ebdSchin 				ep->mark = count;
567da2e3ebdSchin 				ed_ungetchar(ep->ed,cntl('W'));
568da2e3ebdSchin 				continue;
569da2e3ebdSchin 			}
570da2e3ebdSchin 			i = cur;
571da2e3ebdSchin 			eol = i;
572da2e3ebdSchin 			ep->mark = i;
573da2e3ebdSchin #ifdef ESH_KAPPEND
574da2e3ebdSchin 			if (killing)			/* append to kill buffer */
575da2e3ebdSchin 				gencpy(&kstack[genlen(kstack)], &out[i]);
576da2e3ebdSchin 			else
577da2e3ebdSchin 				gencpy(kstack,&out[i]);
578da2e3ebdSchin 			killing = 2;			/* set killing signal */
579da2e3ebdSchin #else
580da2e3ebdSchin 			gencpy(kstack,&out[i]);
581da2e3ebdSchin #endif /* ESH_KAPPEND */
582da2e3ebdSchin 			out[i] = 0;
583da2e3ebdSchin 			draw(ep,UPDATE);
584da2e3ebdSchin 			if (c == KILLCHAR)
585da2e3ebdSchin 			{
586da2e3ebdSchin 				if (ep->terminal == PAPER)
587da2e3ebdSchin 				{
588da2e3ebdSchin 					putchar(ep->ed,'\n');
589da2e3ebdSchin 					putstring(ep,Prompt);
590da2e3ebdSchin 				}
591da2e3ebdSchin 				c = ed_getchar(ep->ed,0);
592da2e3ebdSchin 				if (c != usrkill)
593da2e3ebdSchin 				{
594da2e3ebdSchin 					ed_ungetchar(ep->ed,c);
595da2e3ebdSchin 					continue;
596da2e3ebdSchin 				}
597da2e3ebdSchin 				if (ep->terminal == PAPER)
598da2e3ebdSchin 					ep->terminal = CRT;
599da2e3ebdSchin 				else
600da2e3ebdSchin 				{
601da2e3ebdSchin 					ep->terminal = PAPER;
602da2e3ebdSchin 					putchar(ep->ed,'\n');
603da2e3ebdSchin 					putstring(ep,Prompt);
604da2e3ebdSchin 				}
605da2e3ebdSchin 			}
606da2e3ebdSchin 			continue;
607da2e3ebdSchin 		case cntl('L'):
6087c2fbfb3SApril Chin 			if(!ep->ed->e_nocrnl)
6097c2fbfb3SApril Chin 				ed_crlf(ep->ed);
610da2e3ebdSchin 			draw(ep,REFRESH);
6117c2fbfb3SApril Chin 			ep->ed->e_nocrnl = 0;
612da2e3ebdSchin 			continue;
613da2e3ebdSchin 		case cntl('[') :
614da2e3ebdSchin 		do_escape:
615da2e3ebdSchin 			adjust = escape(ep,out,oadjust);
616da2e3ebdSchin 			continue;
617da2e3ebdSchin 		case cntl('R') :
618da2e3ebdSchin 			search(ep,out,count);
619da2e3ebdSchin 			goto drawline;
620da2e3ebdSchin 		case cntl('P') :
621*b30d1939SAndy Fiddaman #if SHOPT_EDPREDICT
622*b30d1939SAndy Fiddaman 			if(ep->ed->hlist)
623*b30d1939SAndy Fiddaman 			{
624*b30d1939SAndy Fiddaman 				if(ep->ed->hoff == 0)
625*b30d1939SAndy Fiddaman 				{
626*b30d1939SAndy Fiddaman 					beep();
627*b30d1939SAndy Fiddaman 					continue;
628*b30d1939SAndy Fiddaman 				}
629*b30d1939SAndy Fiddaman 				ep->ed->hoff--;
630*b30d1939SAndy Fiddaman 				goto hupdate;
631*b30d1939SAndy Fiddaman 			}
632*b30d1939SAndy Fiddaman #endif /* SHOPT_EDPREDICT */
633da2e3ebdSchin                         if (count <= hloff)
634da2e3ebdSchin                                 hloff -= count;
635da2e3ebdSchin                         else
636da2e3ebdSchin                         {
637da2e3ebdSchin                                 hline -= count - hloff;
638da2e3ebdSchin                                 hloff = 0;
639da2e3ebdSchin                         }
640da2e3ebdSchin #ifdef ESH_NFIRST
641da2e3ebdSchin 			if (hline <= hismin)
642da2e3ebdSchin #else
643da2e3ebdSchin 			if (hline < hismin)
644da2e3ebdSchin #endif /* ESH_NFIRST */
645da2e3ebdSchin 			{
646da2e3ebdSchin 				hline = hismin+1;
647da2e3ebdSchin 				beep();
648da2e3ebdSchin #ifndef ESH_NFIRST
649da2e3ebdSchin 				continue;
650da2e3ebdSchin #endif
651da2e3ebdSchin 			}
652da2e3ebdSchin 			goto common;
653da2e3ebdSchin 
654da2e3ebdSchin 		case cntl('O') :
655da2e3ebdSchin 			location.hist_command = hline;
656da2e3ebdSchin 			location.hist_line = hloff;
657da2e3ebdSchin 			ep->CntrlO = 1;
658da2e3ebdSchin 			c = '\n';
659da2e3ebdSchin 			goto process;
660da2e3ebdSchin 		case cntl('N') :
661*b30d1939SAndy Fiddaman #if SHOPT_EDPREDICT
662*b30d1939SAndy Fiddaman 			if(ep->ed->hlist)
663*b30d1939SAndy Fiddaman 			{
664*b30d1939SAndy Fiddaman 				if(ep->ed->hoff >= ep->ed->hmax)
665*b30d1939SAndy Fiddaman 				{
666*b30d1939SAndy Fiddaman 					beep();
667*b30d1939SAndy Fiddaman 					continue;
668*b30d1939SAndy Fiddaman 				}
669*b30d1939SAndy Fiddaman 				ep->ed->hoff++;
670*b30d1939SAndy Fiddaman 			 hupdate:
671*b30d1939SAndy Fiddaman 				ed_histlist(ep->ed,*ep->ed->hlist!=0);
672*b30d1939SAndy Fiddaman 				draw(ep,REFRESH);
673*b30d1939SAndy Fiddaman 				continue;
674*b30d1939SAndy Fiddaman 			}
675*b30d1939SAndy Fiddaman #endif /* SHOPT_EDPREDICT */
676da2e3ebdSchin #ifdef ESH_NFIRST
677da2e3ebdSchin 			hline = location.hist_command;	/* start at saved position */
678da2e3ebdSchin 			hloff = location.hist_line;
679da2e3ebdSchin #endif /* ESH_NFIRST */
680*b30d1939SAndy Fiddaman 			location = hist_locate(shgd->hist_ptr,hline,hloff,count);
681da2e3ebdSchin 			if (location.hist_command > histlines)
682da2e3ebdSchin 			{
683da2e3ebdSchin 				beep();
684da2e3ebdSchin #ifdef ESH_NFIRST
685da2e3ebdSchin 				location.hist_command = histlines;
686da2e3ebdSchin 				location.hist_line = ep->in_mult;
687da2e3ebdSchin #else
688da2e3ebdSchin 				continue;
689da2e3ebdSchin #endif /* ESH_NFIRST */
690da2e3ebdSchin 			}
691da2e3ebdSchin 			hline = location.hist_command;
692da2e3ebdSchin 			hloff = location.hist_line;
693da2e3ebdSchin 		common:
694da2e3ebdSchin #ifdef ESH_NFIRST
695da2e3ebdSchin 			location.hist_command = hline;	/* save current position */
696da2e3ebdSchin 			location.hist_line = hloff;
697da2e3ebdSchin #endif
6987c2fbfb3SApril Chin 			cur = 0;
6997c2fbfb3SApril Chin 			draw(ep,UPDATE);
700da2e3ebdSchin 			hist_copy((char*)out,MAXLINE, hline,hloff);
701da2e3ebdSchin #if SHOPT_MULTIBYTE
702da2e3ebdSchin 			ed_internal((char*)(out),out);
703da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
704da2e3ebdSchin 		drawline:
705da2e3ebdSchin 			eol = genlen(out);
706da2e3ebdSchin 			cur = eol;
707da2e3ebdSchin 			draw(ep,UPDATE);
708da2e3ebdSchin 			continue;
709da2e3ebdSchin 		}
710da2e3ebdSchin 
711da2e3ebdSchin 	}
712da2e3ebdSchin 
713da2e3ebdSchin process:
714da2e3ebdSchin 
715da2e3ebdSchin 	if (c == (-1))
716da2e3ebdSchin 	{
717da2e3ebdSchin 		lookahead = 0;
718da2e3ebdSchin 		beep();
719da2e3ebdSchin 		*out = '\0';
720da2e3ebdSchin 	}
721da2e3ebdSchin 	draw(ep,FINAL);
722da2e3ebdSchin 	tty_cooked(ERRIO);
723da2e3ebdSchin 	if(ed->e_nlist)
724da2e3ebdSchin 	{
725da2e3ebdSchin 		ed->e_nlist = 0;
726da2e3ebdSchin 		stakset(ed->e_stkptr,ed->e_stkoff);
727da2e3ebdSchin 	}
728da2e3ebdSchin 	if(c == '\n')
729da2e3ebdSchin 	{
730da2e3ebdSchin 		out[eol++] = '\n';
731da2e3ebdSchin 		out[eol] = '\0';
732da2e3ebdSchin 		ed_crlf(ep->ed);
733da2e3ebdSchin 	}
734da2e3ebdSchin #if SHOPT_MULTIBYTE
735da2e3ebdSchin 	ed_external(out,buff);
736da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
737*b30d1939SAndy Fiddaman 	i = (int)strlen(buff);
738da2e3ebdSchin 	if (i)
739da2e3ebdSchin 		return(i);
740da2e3ebdSchin 	return(-1);
741da2e3ebdSchin }
742da2e3ebdSchin 
show_info(Emacs_t * ep,const char * str)743da2e3ebdSchin static void show_info(Emacs_t *ep,const char *str)
744da2e3ebdSchin {
745da2e3ebdSchin 	register genchar *out = drawbuff;
746da2e3ebdSchin 	register int c;
747da2e3ebdSchin 	genchar string[LBUF];
748da2e3ebdSchin 	int sav_cur = cur;
749da2e3ebdSchin 	/* save current line */
750da2e3ebdSchin 	genncpy(string,out,sizeof(string)/sizeof(*string));
751da2e3ebdSchin 	*out = 0;
752da2e3ebdSchin 	cur = 0;
753da2e3ebdSchin #if SHOPT_MULTIBYTE
754da2e3ebdSchin 	ed_internal(str,out);
755da2e3ebdSchin #else
756da2e3ebdSchin 	gencpy(out,str);
757da2e3ebdSchin #endif	/* SHOPT_MULTIBYTE */
758da2e3ebdSchin 	draw(ep,UPDATE);
759da2e3ebdSchin 	c = ed_getchar(ep->ed,0);
760da2e3ebdSchin 	if(c!=' ')
761da2e3ebdSchin 		ed_ungetchar(ep->ed,c);
762da2e3ebdSchin 	/* restore line */
763da2e3ebdSchin 	cur = sav_cur;
764da2e3ebdSchin 	genncpy(out,string,sizeof(string)/sizeof(*string));
765da2e3ebdSchin 	draw(ep,UPDATE);
766da2e3ebdSchin }
767da2e3ebdSchin 
putstring(Emacs_t * ep,register char * sp)768da2e3ebdSchin static void putstring(Emacs_t* ep,register char *sp)
769da2e3ebdSchin {
770da2e3ebdSchin 	register int c;
771da2e3ebdSchin 	while (c= *sp++)
772da2e3ebdSchin 		 putchar(ep->ed,c);
773da2e3ebdSchin }
774da2e3ebdSchin 
775da2e3ebdSchin 
escape(register Emacs_t * ep,register genchar * out,int count)776da2e3ebdSchin static int escape(register Emacs_t* ep,register genchar *out,int count)
777da2e3ebdSchin {
778da2e3ebdSchin 	register int i,value;
779da2e3ebdSchin 	int digit,ch;
780da2e3ebdSchin 	digit = 0;
781da2e3ebdSchin 	value = 0;
782*b30d1939SAndy Fiddaman 	while ((i=ed_getchar(ep->ed,0)),digit(i))
783da2e3ebdSchin 	{
784da2e3ebdSchin 		value *= 10;
785da2e3ebdSchin 		value += (i - '0');
786da2e3ebdSchin 		digit = 1;
787da2e3ebdSchin 	}
788da2e3ebdSchin 	if (digit)
789da2e3ebdSchin 	{
790da2e3ebdSchin 		ed_ungetchar(ep->ed,i) ;
791da2e3ebdSchin #ifdef ESH_KAPPEND
792da2e3ebdSchin 		++killing;		/* don't modify killing signal */
793da2e3ebdSchin #endif
794da2e3ebdSchin 		return(value);
795da2e3ebdSchin 	}
796da2e3ebdSchin 	value = count;
797da2e3ebdSchin 	if(value<0)
798da2e3ebdSchin 		value = 1;
799da2e3ebdSchin 	switch(ch=i)
800da2e3ebdSchin 	{
801da2e3ebdSchin 		case cntl('V'):
802da2e3ebdSchin 			show_info(ep,fmtident(e_version));
803da2e3ebdSchin 			return(-1);
804da2e3ebdSchin 		case ' ':
805da2e3ebdSchin 			ep->mark = cur;
806da2e3ebdSchin 			return(-1);
807da2e3ebdSchin 
808da2e3ebdSchin #ifdef ESH_KAPPEND
809da2e3ebdSchin 		case '+':		/* M-+ = append next kill */
810da2e3ebdSchin 			killing = 2;
811da2e3ebdSchin 			return -1;	/* no argument for next command */
812da2e3ebdSchin #endif
813da2e3ebdSchin 
814da2e3ebdSchin 		case 'p':	/* M-p == ^W^Y (copy stack == kill & yank) */
815da2e3ebdSchin 			ed_ungetchar(ep->ed,cntl('Y'));
816da2e3ebdSchin 			ed_ungetchar(ep->ed,cntl('W'));
817da2e3ebdSchin #ifdef ESH_KAPPEND
818da2e3ebdSchin 			killing = 0;	/* start fresh */
819da2e3ebdSchin #endif
820da2e3ebdSchin 			return(-1);
821da2e3ebdSchin 
822da2e3ebdSchin 		case 'l':	/* M-l == lower-case */
823da2e3ebdSchin 		case 'd':
824da2e3ebdSchin 		case 'c':
825da2e3ebdSchin 		case 'f':
826da2e3ebdSchin 		{
827da2e3ebdSchin 			i = cur;
828da2e3ebdSchin 			while(value-- && i<eol)
829da2e3ebdSchin 			{
830da2e3ebdSchin 				while ((out[i])&&(!isword(i)))
831da2e3ebdSchin 					i++;
832da2e3ebdSchin 				while ((out[i])&&(isword(i)))
833da2e3ebdSchin 					i++;
834da2e3ebdSchin 			}
835da2e3ebdSchin 			if(ch=='l')
836da2e3ebdSchin 			{
837da2e3ebdSchin 				value = i-cur;
838da2e3ebdSchin 				while (value-- > 0)
839da2e3ebdSchin 				{
840da2e3ebdSchin 					i = out[cur];
841da2e3ebdSchin #if SHOPT_MULTIBYTE
842da2e3ebdSchin 					if((i&~STRIP)==0 && isupper(i))
843da2e3ebdSchin #else
844da2e3ebdSchin 					if(isupper(i))
845da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
846da2e3ebdSchin 					{
847da2e3ebdSchin 						i += 'a' - 'A';
848da2e3ebdSchin 						out[cur] = i;
849da2e3ebdSchin 					}
850da2e3ebdSchin 					cur++;
851da2e3ebdSchin 				}
852da2e3ebdSchin 				draw(ep,UPDATE);
853da2e3ebdSchin 				return(-1);
854da2e3ebdSchin 			}
855da2e3ebdSchin 
856da2e3ebdSchin 			else if(ch=='f')
857da2e3ebdSchin 				goto update;
858da2e3ebdSchin 			else if(ch=='c')
859da2e3ebdSchin 			{
860da2e3ebdSchin 				ed_ungetchar(ep->ed,cntl('C'));
861da2e3ebdSchin 				return(i-cur);
862da2e3ebdSchin 			}
863da2e3ebdSchin 			else
864da2e3ebdSchin 			{
865da2e3ebdSchin 				if (i-cur)
866da2e3ebdSchin 				{
867da2e3ebdSchin 					ed_ungetchar(ep->ed,cntl('D'));
868da2e3ebdSchin #ifdef ESH_KAPPEND
869da2e3ebdSchin 					++killing;	/* keep killing signal */
870da2e3ebdSchin #endif
871da2e3ebdSchin 					return(i-cur);
872da2e3ebdSchin 				}
873da2e3ebdSchin 				beep();
874da2e3ebdSchin 				return(-1);
875da2e3ebdSchin 			}
876da2e3ebdSchin 		}
877da2e3ebdSchin 
878da2e3ebdSchin 
879da2e3ebdSchin 		case 'b':
880da2e3ebdSchin 		case DELETE :
881da2e3ebdSchin 		case '\b':
882da2e3ebdSchin 		case 'h':
883da2e3ebdSchin 		{
884da2e3ebdSchin 			i = cur;
885da2e3ebdSchin 			while(value-- && i>0)
886da2e3ebdSchin 			{
887da2e3ebdSchin 				i--;
888da2e3ebdSchin 				while ((i>0)&&(!isword(i)))
889da2e3ebdSchin 					i--;
890da2e3ebdSchin 				while ((i>0)&&(isword(i-1)))
891da2e3ebdSchin 					i--;
892da2e3ebdSchin 			}
893da2e3ebdSchin 			if(ch=='b')
894da2e3ebdSchin 				goto update;
895da2e3ebdSchin 			else
896da2e3ebdSchin 			{
897da2e3ebdSchin 				ed_ungetchar(ep->ed,usrerase);
898da2e3ebdSchin #ifdef ESH_KAPPEND
899da2e3ebdSchin 				++killing;
900da2e3ebdSchin #endif
901da2e3ebdSchin 				return(cur-i);
902da2e3ebdSchin 			}
903da2e3ebdSchin 		}
904da2e3ebdSchin 
905da2e3ebdSchin 		case '>':
906da2e3ebdSchin 			ed_ungetchar(ep->ed,cntl('N'));
907da2e3ebdSchin #ifdef ESH_NFIRST
908da2e3ebdSchin 			if (ep->in_mult)
909da2e3ebdSchin 			{
910da2e3ebdSchin 				location.hist_command = histlines;
911da2e3ebdSchin 				location.hist_line = ep->in_mult - 1;
912da2e3ebdSchin 			}
913da2e3ebdSchin 			else
914da2e3ebdSchin 			{
915da2e3ebdSchin 				location.hist_command = histlines - 1;
916da2e3ebdSchin 				location.hist_line = 0;
917da2e3ebdSchin 			}
918da2e3ebdSchin #else
919da2e3ebdSchin 			hline = histlines-1;
920da2e3ebdSchin 			hloff = 0;
921da2e3ebdSchin #endif /* ESH_NFIRST */
922da2e3ebdSchin 			return(0);
923da2e3ebdSchin 
924da2e3ebdSchin 		case '<':
925da2e3ebdSchin 			ed_ungetchar(ep->ed,cntl('P'));
926da2e3ebdSchin 			hloff = 0;
927da2e3ebdSchin #ifdef ESH_NFIRST
928da2e3ebdSchin 			hline = hismin + 1;
929da2e3ebdSchin 			return 0;
930da2e3ebdSchin #else
931da2e3ebdSchin 			return(hline-hismin);
932da2e3ebdSchin #endif /* ESH_NFIRST */
933da2e3ebdSchin 
934da2e3ebdSchin 
935da2e3ebdSchin 		case '#':
936da2e3ebdSchin 			ed_ungetchar(ep->ed,'\n');
937da2e3ebdSchin 			ed_ungetchar(ep->ed,(out[0]=='#')?cntl('D'):'#');
938da2e3ebdSchin 			ed_ungetchar(ep->ed,cntl('A'));
939da2e3ebdSchin 			return(-1);
940da2e3ebdSchin 		case '_' :
941da2e3ebdSchin 		case '.' :
942da2e3ebdSchin 		{
943da2e3ebdSchin 			genchar name[MAXLINE];
944da2e3ebdSchin 			char buf[MAXLINE];
945da2e3ebdSchin 			char *ptr;
946da2e3ebdSchin 			ptr = hist_word(buf,MAXLINE,(count?count:-1));
947da2e3ebdSchin 			if(ptr==0)
948da2e3ebdSchin 			{
949da2e3ebdSchin 				beep();
950da2e3ebdSchin 				break;
951da2e3ebdSchin 			}
952da2e3ebdSchin 			if ((eol - cur) >= sizeof(name))
953da2e3ebdSchin 			{
954da2e3ebdSchin 				beep();
955da2e3ebdSchin 				return(-1);
956da2e3ebdSchin 			}
957da2e3ebdSchin 			ep->mark = cur;
958da2e3ebdSchin 			gencpy(name,&out[cur]);
959da2e3ebdSchin 			while(*ptr)
960da2e3ebdSchin 			{
961da2e3ebdSchin 				out[cur++] = *ptr++;
962da2e3ebdSchin 				eol++;
963da2e3ebdSchin 			}
964da2e3ebdSchin 			gencpy(&out[cur],name);
965da2e3ebdSchin 			draw(ep,UPDATE);
966da2e3ebdSchin 			return(-1);
967da2e3ebdSchin 		}
968da2e3ebdSchin #if KSHELL
969da2e3ebdSchin 
970*b30d1939SAndy Fiddaman #if SHOPT_EDPREDICT
971*b30d1939SAndy Fiddaman 		case '\n':  case '\t':
972*b30d1939SAndy Fiddaman 			if(!ep->ed->hlist)
973*b30d1939SAndy Fiddaman 			{
974*b30d1939SAndy Fiddaman 				beep();
975*b30d1939SAndy Fiddaman 				break;
976*b30d1939SAndy Fiddaman 			}
977*b30d1939SAndy Fiddaman 			if(ch=='\n')
978*b30d1939SAndy Fiddaman 				ed_ungetchar(ep->ed,'\n');
979*b30d1939SAndy Fiddaman #endif /* SHOPT_EDPREDICT */
980da2e3ebdSchin 		/* file name expansion */
981da2e3ebdSchin 		case cntl('[') :	/* filename completion */
982*b30d1939SAndy Fiddaman #if SHOPT_EDPREDICT
983*b30d1939SAndy Fiddaman 			if(ep->ed->hlist)
984*b30d1939SAndy Fiddaman 			{
985*b30d1939SAndy Fiddaman 				value += ep->ed->hoff;
986*b30d1939SAndy Fiddaman 				if(value > ep->ed->nhlist)
987*b30d1939SAndy Fiddaman 					beep();
988*b30d1939SAndy Fiddaman 				else
989*b30d1939SAndy Fiddaman 				{
990*b30d1939SAndy Fiddaman 					value = histlines - ep->ed->hlist[value-1]->index;
991*b30d1939SAndy Fiddaman 					ed_histlist(ep->ed,0);
992*b30d1939SAndy Fiddaman 					ed_ungetchar(ep->ed,cntl('P'));
993*b30d1939SAndy Fiddaman 					return(value);
994*b30d1939SAndy Fiddaman 				}
995*b30d1939SAndy Fiddaman 			}
996*b30d1939SAndy Fiddaman #endif /* SHOPT_EDPREDICT */
997da2e3ebdSchin 			i = '\\';
9985ae8bd53SToomas Soome 			/* FALLTHROUGH */
999da2e3ebdSchin 		case '*':		/* filename expansion */
1000da2e3ebdSchin 		case '=':	/* escape = - list all matching file names */
1001da2e3ebdSchin 			ep->mark = cur;
1002da2e3ebdSchin 			if(ed_expand(ep->ed,(char*)out,&cur,&eol,i,count) < 0)
1003da2e3ebdSchin 			{
1004da2e3ebdSchin 				if(ep->ed->e_tabcount==1)
1005da2e3ebdSchin 				{
1006da2e3ebdSchin 					ep->ed->e_tabcount=2;
1007da2e3ebdSchin 					ed_ungetchar(ep->ed,cntl('\t'));
1008da2e3ebdSchin 					return(-1);
1009da2e3ebdSchin 				}
1010da2e3ebdSchin 				beep();
1011da2e3ebdSchin 			}
1012*b30d1939SAndy Fiddaman 			else if(i=='=' || (i=='\\' && out[cur-1]=='/'))
1013da2e3ebdSchin 			{
1014da2e3ebdSchin 				draw(ep,REFRESH);
1015da2e3ebdSchin 				if(count>0)
1016da2e3ebdSchin 					ep->ed->e_tabcount=0;
1017da2e3ebdSchin 				else
1018da2e3ebdSchin 				{
1019da2e3ebdSchin 					i=ed_getchar(ep->ed,0);
1020da2e3ebdSchin 					ed_ungetchar(ep->ed,i);
1021*b30d1939SAndy Fiddaman 					if(digit(i))
1022da2e3ebdSchin 						ed_ungetchar(ep->ed,ESC);
1023da2e3ebdSchin 				}
1024da2e3ebdSchin 			}
1025da2e3ebdSchin 			else
1026da2e3ebdSchin 			{
1027da2e3ebdSchin 				if(i=='\\' && cur>ep->mark && (out[cur-1]=='/' || out[cur-1]==' '))
1028da2e3ebdSchin 					ep->ed->e_tabcount=0;
1029da2e3ebdSchin 				draw(ep,UPDATE);
1030da2e3ebdSchin 			}
1031da2e3ebdSchin 			return(-1);
1032da2e3ebdSchin 
1033da2e3ebdSchin 		/* search back for character */
1034da2e3ebdSchin 		case cntl(']'):	/* feature not in book */
1035da2e3ebdSchin 		{
1036da2e3ebdSchin 			int c = ed_getchar(ep->ed,1);
1037da2e3ebdSchin 			if ((value == 0) || (value > eol))
1038da2e3ebdSchin 			{
1039da2e3ebdSchin 				beep();
1040da2e3ebdSchin 				return(-1);
1041da2e3ebdSchin 			}
1042da2e3ebdSchin 			i = cur;
1043da2e3ebdSchin 			if (i > 0)
1044da2e3ebdSchin 				i--;
1045da2e3ebdSchin 			while (i >= 0)
1046da2e3ebdSchin 			{
1047da2e3ebdSchin 				if (out[i] == c && --value==0)
1048da2e3ebdSchin 					goto update;
1049da2e3ebdSchin 				i--;
1050da2e3ebdSchin 			}
1051da2e3ebdSchin 			i = eol;
1052da2e3ebdSchin 			while (i > cur)
1053da2e3ebdSchin 			{
1054da2e3ebdSchin 				if (out[i] == c && --value==0)
1055da2e3ebdSchin 					break;
1056da2e3ebdSchin 				i--;
1057da2e3ebdSchin 			};
1058da2e3ebdSchin 
1059da2e3ebdSchin 		}
1060da2e3ebdSchin 		update:
1061da2e3ebdSchin 			cur = i;
1062da2e3ebdSchin 			draw(ep,UPDATE);
1063da2e3ebdSchin 			return(-1);
1064da2e3ebdSchin 
1065da2e3ebdSchin #ifdef _cmd_tput
1066da2e3ebdSchin 		case cntl('L'): /* clear screen */
1067da2e3ebdSchin 			sh_trap("tput clear", 0);
1068da2e3ebdSchin 			draw(ep,REFRESH);
1069da2e3ebdSchin 			return(-1);
1070da2e3ebdSchin #endif
1071da2e3ebdSchin 		case '[':	/* feature not in book */
1072da2e3ebdSchin 			switch(i=ed_getchar(ep->ed,1))
1073da2e3ebdSchin 			{
1074da2e3ebdSchin 			    case 'A':
1075*b30d1939SAndy Fiddaman #if SHOPT_EDPREDICT
1076*b30d1939SAndy Fiddaman 				if(!ep->ed->hlist && cur>0 && eol==cur && (cur<(SEARCHSIZE-2) || ep->prevdirection == -2))
1077*b30d1939SAndy Fiddaman #else
10787c2fbfb3SApril Chin 				if(cur>0 && eol==cur && (cur<(SEARCHSIZE-2) || ep->prevdirection == -2))
1079*b30d1939SAndy Fiddaman #endif /* SHOPT_EDPREDICT */
10807c2fbfb3SApril Chin 				{
10817c2fbfb3SApril Chin 					if(ep->lastdraw==APPEND && ep->prevdirection != -2)
10827c2fbfb3SApril Chin 					{
10837c2fbfb3SApril Chin 						out[cur] = 0;
1084*b30d1939SAndy Fiddaman 						gencpy((genchar*)lstring+1,out);
10857c2fbfb3SApril Chin #if SHOPT_MULTIBYTE
1086*b30d1939SAndy Fiddaman 						ed_external((genchar*)lstring+1,lstring+1);
10877c2fbfb3SApril Chin #endif /* SHOPT_MULTIBYTE */
10887c2fbfb3SApril Chin 						*lstring = '^';
10897c2fbfb3SApril Chin 						ep->prevdirection = -2;
10907c2fbfb3SApril Chin 					}
10917c2fbfb3SApril Chin 					if(*lstring)
10927c2fbfb3SApril Chin 					{
10937c2fbfb3SApril Chin 						ed_ungetchar(ep->ed,'\r');
10947c2fbfb3SApril Chin 						ed_ungetchar(ep->ed,cntl('R'));
10957c2fbfb3SApril Chin 						return(-1);
10967c2fbfb3SApril Chin 					}
10977c2fbfb3SApril Chin 				}
10987c2fbfb3SApril Chin 				*lstring = 0;
1099da2e3ebdSchin 				ed_ungetchar(ep->ed,cntl('P'));
1100da2e3ebdSchin 				return(-1);
1101da2e3ebdSchin 			    case 'B':
1102da2e3ebdSchin 				ed_ungetchar(ep->ed,cntl('N'));
1103da2e3ebdSchin 				return(-1);
1104da2e3ebdSchin 			    case 'C':
1105da2e3ebdSchin 				ed_ungetchar(ep->ed,cntl('F'));
1106da2e3ebdSchin 				return(-1);
1107da2e3ebdSchin 			    case 'D':
1108da2e3ebdSchin 				ed_ungetchar(ep->ed,cntl('B'));
1109da2e3ebdSchin 				return(-1);
1110da2e3ebdSchin 			    case 'H':
1111da2e3ebdSchin 				ed_ungetchar(ep->ed,cntl('A'));
1112da2e3ebdSchin 				return(-1);
1113da2e3ebdSchin 			    case 'Y':
1114da2e3ebdSchin 				ed_ungetchar(ep->ed,cntl('E'));
1115da2e3ebdSchin 				return(-1);
1116da2e3ebdSchin 			    default:
1117da2e3ebdSchin 				ed_ungetchar(ep->ed,i);
1118da2e3ebdSchin 			}
1119da2e3ebdSchin 			i = '_';
11205ae8bd53SToomas Soome 			/* FALLTHROUGH */
1121da2e3ebdSchin 
1122da2e3ebdSchin 		default:
1123da2e3ebdSchin 			/* look for user defined macro definitions */
1124da2e3ebdSchin 			if(ed_macro(ep->ed,i))
1125da2e3ebdSchin #   ifdef ESH_BETTER
1126da2e3ebdSchin 				return(count);	/* pass argument to macro */
1127da2e3ebdSchin #   else
1128da2e3ebdSchin 				return(-1);
1129da2e3ebdSchin #   endif /* ESH_BETTER */
1130da2e3ebdSchin #else
1131da2e3ebdSchin 		update:
1132da2e3ebdSchin 			cur = i;
1133da2e3ebdSchin 			draw(ep,UPDATE);
1134da2e3ebdSchin 			return(-1);
1135da2e3ebdSchin 
1136da2e3ebdSchin 		default:
1137da2e3ebdSchin #endif	/* KSHELL */
1138da2e3ebdSchin 		beep();
1139da2e3ebdSchin 		return(-1);
1140da2e3ebdSchin 	}
114134f9b3eeSRoland Mainz 	return(-1);
1142da2e3ebdSchin }
1143da2e3ebdSchin 
1144da2e3ebdSchin 
1145da2e3ebdSchin /*
1146da2e3ebdSchin  * This routine process all commands starting with ^X
1147da2e3ebdSchin  */
1148da2e3ebdSchin 
xcommands(register Emacs_t * ep,int count)1149da2e3ebdSchin static void xcommands(register Emacs_t *ep,int count)
1150da2e3ebdSchin {
1151da2e3ebdSchin         register int i = ed_getchar(ep->ed,0);
1152da2e3ebdSchin 	NOT_USED(count);
1153da2e3ebdSchin         switch(i)
1154da2e3ebdSchin         {
1155da2e3ebdSchin                 case cntl('X'):	/* exchange dot and mark */
1156da2e3ebdSchin                         if (ep->mark > eol)
1157da2e3ebdSchin                                 ep->mark = eol;
1158da2e3ebdSchin                         i = ep->mark;
1159da2e3ebdSchin                         ep->mark = cur;
1160da2e3ebdSchin                         cur = i;
1161da2e3ebdSchin                         draw(ep,UPDATE);
1162da2e3ebdSchin                         return;
1163da2e3ebdSchin 
1164da2e3ebdSchin #if KSHELL
1165da2e3ebdSchin #   ifdef ESH_BETTER
1166da2e3ebdSchin                 case cntl('E'):	/* invoke emacs on current command */
1167da2e3ebdSchin 			if(ed_fulledit(ep->ed)==-1)
1168da2e3ebdSchin 				beep();
1169da2e3ebdSchin 			else
1170da2e3ebdSchin 			{
1171da2e3ebdSchin #if SHOPT_MULTIBYTE
1172da2e3ebdSchin 				ed_internal((char*)drawbuff,drawbuff);
1173da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
1174da2e3ebdSchin 				ed_ungetchar(ep->ed,'\n');
1175da2e3ebdSchin 			}
1176da2e3ebdSchin 			return;
1177da2e3ebdSchin 
1178da2e3ebdSchin #	define itos(i)	fmtbase((long)(i),0,0)/* want signed conversion */
1179da2e3ebdSchin 
1180da2e3ebdSchin 		case cntl('H'):		/* ^X^H show history info */
1181da2e3ebdSchin 			{
1182da2e3ebdSchin 				char hbuf[MAXLINE];
1183da2e3ebdSchin 
1184da2e3ebdSchin 				strcpy(hbuf, "Current command ");
1185da2e3ebdSchin 				strcat(hbuf, itos(hline));
1186da2e3ebdSchin 				if (hloff)
1187da2e3ebdSchin 				{
1188da2e3ebdSchin 					strcat(hbuf, " (line ");
1189da2e3ebdSchin 					strcat(hbuf, itos(hloff+1));
1190da2e3ebdSchin 					strcat(hbuf, ")");
1191da2e3ebdSchin 				}
1192da2e3ebdSchin 				if ((hline != location.hist_command) ||
1193da2e3ebdSchin 				    (hloff != location.hist_line))
1194da2e3ebdSchin 				{
1195da2e3ebdSchin 					strcat(hbuf, "; Previous command ");
1196da2e3ebdSchin 					strcat(hbuf, itos(location.hist_command));
1197da2e3ebdSchin 					if (location.hist_line)
1198da2e3ebdSchin 					{
1199da2e3ebdSchin 						strcat(hbuf, " (line ");
1200da2e3ebdSchin 						strcat(hbuf, itos(location.hist_line+1));
1201da2e3ebdSchin 						strcat(hbuf, ")");
1202da2e3ebdSchin 					}
1203da2e3ebdSchin 				}
1204da2e3ebdSchin 				show_info(ep,hbuf);
1205da2e3ebdSchin 				return;
1206da2e3ebdSchin 			}
1207da2e3ebdSchin #	if 0	/* debugging, modify as required */
1208da2e3ebdSchin 		case cntl('D'):		/* ^X^D show debugging info */
1209da2e3ebdSchin 			{
1210da2e3ebdSchin 				char debugbuf[MAXLINE];
1211da2e3ebdSchin 
1212da2e3ebdSchin 				strcpy(debugbuf, "count=");
1213da2e3ebdSchin 				strcat(debugbuf, itos(count));
1214da2e3ebdSchin 				strcat(debugbuf, " eol=");
1215da2e3ebdSchin 				strcat(debugbuf, itos(eol));
1216da2e3ebdSchin 				strcat(debugbuf, " cur=");
1217da2e3ebdSchin 				strcat(debugbuf, itos(cur));
1218da2e3ebdSchin 				strcat(debugbuf, " crallowed=");
1219da2e3ebdSchin 				strcat(debugbuf, itos(crallowed));
1220da2e3ebdSchin 				strcat(debugbuf, " plen=");
1221da2e3ebdSchin 				strcat(debugbuf, itos(plen));
1222da2e3ebdSchin 				strcat(debugbuf, " w_size=");
1223da2e3ebdSchin 				strcat(debugbuf, itos(w_size));
1224da2e3ebdSchin 
1225da2e3ebdSchin 				show_info(ep,debugbuf);
1226da2e3ebdSchin 				return;
1227da2e3ebdSchin 			}
1228da2e3ebdSchin #	endif /* debugging code */
1229da2e3ebdSchin #   endif /* ESH_BETTER */
1230da2e3ebdSchin #endif /* KSHELL */
1231da2e3ebdSchin 
1232da2e3ebdSchin                 default:
1233da2e3ebdSchin                         beep();
1234da2e3ebdSchin                         return;
1235da2e3ebdSchin 	}
1236da2e3ebdSchin }
1237da2e3ebdSchin 
search(Emacs_t * ep,genchar * out,int direction)1238da2e3ebdSchin static void search(Emacs_t* ep,genchar *out,int direction)
1239da2e3ebdSchin {
1240da2e3ebdSchin #ifndef ESH_NFIRST
1241da2e3ebdSchin 	Histloc_t location;
1242da2e3ebdSchin #endif
1243da2e3ebdSchin 	register int i,sl;
1244da2e3ebdSchin 	genchar str_buff[LBUF];
1245da2e3ebdSchin 	register genchar *string = drawbuff;
1246da2e3ebdSchin 	/* save current line */
1247da2e3ebdSchin 	int sav_cur = cur;
1248da2e3ebdSchin 	genncpy(str_buff,string,sizeof(str_buff)/sizeof(*str_buff));
1249da2e3ebdSchin 	string[0] = '^';
1250da2e3ebdSchin 	string[1] = 'R';
1251da2e3ebdSchin 	string[2] = '\0';
1252da2e3ebdSchin 	sl = 2;
1253da2e3ebdSchin 	cur = sl;
1254da2e3ebdSchin 	draw(ep,UPDATE);
1255da2e3ebdSchin 	while ((i = ed_getchar(ep->ed,1))&&(i != '\r')&&(i != '\n'))
1256da2e3ebdSchin 	{
1257da2e3ebdSchin 		if (i==usrerase || i==DELETE || i=='\b' || i==ERASECHAR)
1258da2e3ebdSchin 		{
1259da2e3ebdSchin 			if (sl > 2)
1260da2e3ebdSchin 			{
1261da2e3ebdSchin 				string[--sl] = '\0';
1262da2e3ebdSchin 				cur = sl;
1263da2e3ebdSchin 				draw(ep,UPDATE);
1264da2e3ebdSchin 			}
1265da2e3ebdSchin 			else
1266*b30d1939SAndy Fiddaman 				goto restore;
1267da2e3ebdSchin 			continue;
1268da2e3ebdSchin 		}
1269*b30d1939SAndy Fiddaman 		if(i == ep->ed->e_intr)
1270*b30d1939SAndy Fiddaman 			goto restore;
1271da2e3ebdSchin 		if (i==usrkill)
1272da2e3ebdSchin 		{
1273da2e3ebdSchin 			beep();
1274da2e3ebdSchin 			goto restore;
1275da2e3ebdSchin 		}
1276da2e3ebdSchin 		if (i == '\\')
1277da2e3ebdSchin 		{
1278da2e3ebdSchin 			string[sl++] = '\\';
1279da2e3ebdSchin 			string[sl] = '\0';
1280da2e3ebdSchin 			cur = sl;
1281da2e3ebdSchin 			draw(ep,APPEND);
1282da2e3ebdSchin 			i = ed_getchar(ep->ed,1);
1283da2e3ebdSchin 			string[--sl] = '\0';
1284da2e3ebdSchin 		}
1285da2e3ebdSchin 		string[sl++] = i;
1286da2e3ebdSchin 		string[sl] = '\0';
1287da2e3ebdSchin 		cur = sl;
1288da2e3ebdSchin 		draw(ep,APPEND);
1289da2e3ebdSchin 	}
1290da2e3ebdSchin 	i = genlen(string);
1291da2e3ebdSchin 
12927c2fbfb3SApril Chin 	if(ep->prevdirection == -2 && i!=2 || direction!=1)
12937c2fbfb3SApril Chin 		ep->prevdirection = -1;
1294da2e3ebdSchin 	if (direction < 1)
1295da2e3ebdSchin 	{
1296da2e3ebdSchin 		ep->prevdirection = -ep->prevdirection;
1297da2e3ebdSchin 		direction = 1;
1298da2e3ebdSchin 	}
1299da2e3ebdSchin 	else
1300da2e3ebdSchin 		direction = -1;
1301da2e3ebdSchin 	if (i != 2)
1302da2e3ebdSchin 	{
1303da2e3ebdSchin #if SHOPT_MULTIBYTE
1304da2e3ebdSchin 		ed_external(string,(char*)string);
1305da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
1306da2e3ebdSchin 		strncpy(lstring,((char*)string)+2,SEARCHSIZE);
1307*b30d1939SAndy Fiddaman 		lstring[SEARCHSIZE-1] = 0;
1308da2e3ebdSchin 		ep->prevdirection = direction;
1309da2e3ebdSchin 	}
1310da2e3ebdSchin 	else
1311da2e3ebdSchin 		direction = ep->prevdirection ;
1312*b30d1939SAndy Fiddaman 	location = hist_find(shgd->hist_ptr,(char*)lstring,hline,1,direction);
1313da2e3ebdSchin 	i = location.hist_command;
1314da2e3ebdSchin 	if(i>0)
1315da2e3ebdSchin 	{
1316da2e3ebdSchin 		hline = i;
1317da2e3ebdSchin #ifdef ESH_NFIRST
1318da2e3ebdSchin 		hloff = location.hist_line = 0;	/* display first line of multi line command */
1319da2e3ebdSchin #else
1320da2e3ebdSchin 		hloff = location.hist_line;
1321da2e3ebdSchin #endif /* ESH_NFIRST */
1322da2e3ebdSchin 		hist_copy((char*)out,MAXLINE, hline,hloff);
1323da2e3ebdSchin #if SHOPT_MULTIBYTE
1324da2e3ebdSchin 		ed_internal((char*)out,out);
1325da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
1326da2e3ebdSchin 		return;
1327da2e3ebdSchin 	}
1328da2e3ebdSchin 	if (i < 0)
1329da2e3ebdSchin 	{
1330da2e3ebdSchin 		beep();
1331da2e3ebdSchin #ifdef ESH_NFIRST
1332da2e3ebdSchin 		location.hist_command = hline;
1333da2e3ebdSchin 		location.hist_line = hloff;
1334da2e3ebdSchin #else
1335da2e3ebdSchin 		hloff = 0;
1336da2e3ebdSchin 		hline = histlines;
1337da2e3ebdSchin #endif /* ESH_NFIRST */
1338da2e3ebdSchin 	}
1339da2e3ebdSchin restore:
1340da2e3ebdSchin 	genncpy(string,str_buff,sizeof(str_buff)/sizeof(*str_buff));
1341da2e3ebdSchin 	cur = sav_cur;
1342da2e3ebdSchin 	return;
1343da2e3ebdSchin }
1344da2e3ebdSchin 
1345da2e3ebdSchin 
1346da2e3ebdSchin /* Adjust screen to agree with inputs: logical line and cursor */
1347da2e3ebdSchin /* If 'first' assume screen is blank */
1348da2e3ebdSchin /* Prompt is always kept on the screen */
1349da2e3ebdSchin 
draw(register Emacs_t * ep,Draw_t option)1350da2e3ebdSchin static void draw(register Emacs_t *ep,Draw_t option)
1351da2e3ebdSchin {
1352da2e3ebdSchin #define	NORMAL ' '
1353da2e3ebdSchin #define	LOWER  '<'
1354da2e3ebdSchin #define	BOTH   '*'
1355da2e3ebdSchin #define	UPPER  '>'
1356da2e3ebdSchin 
1357da2e3ebdSchin 	register genchar *sptr;		/* Pointer within screen */
1358da2e3ebdSchin 	genchar nscreen[2*MAXLINE];	/* New entire screen */
1359da2e3ebdSchin 	genchar *ncursor;		/* New cursor */
1360da2e3ebdSchin 	register genchar *nptr;		/* Pointer to New screen */
1361da2e3ebdSchin 	char  longline;			/* Line overflow */
1362da2e3ebdSchin 	genchar *logcursor;
1363da2e3ebdSchin 	genchar *nscend;		/* end of logical screen */
1364da2e3ebdSchin 	register int i;
1365da2e3ebdSchin 
1366da2e3ebdSchin 	nptr = nscreen;
1367da2e3ebdSchin 	sptr = drawbuff;
1368da2e3ebdSchin 	logcursor = sptr + cur;
1369da2e3ebdSchin 	longline = NORMAL;
13707c2fbfb3SApril Chin 	ep->lastdraw = option;
1371da2e3ebdSchin 
1372da2e3ebdSchin 	if (option == FIRST || option == REFRESH)
1373da2e3ebdSchin 	{
1374da2e3ebdSchin 		ep->overflow = NORMAL;
1375da2e3ebdSchin 		ep->cursor = ep->screen;
1376da2e3ebdSchin 		ep->offset = 0;
1377da2e3ebdSchin 		ep->cr_ok = crallowed;
1378da2e3ebdSchin 		if (option == FIRST)
1379da2e3ebdSchin 		{
1380da2e3ebdSchin 			ep->scvalid = 1;
1381da2e3ebdSchin 			return;
1382da2e3ebdSchin 		}
1383da2e3ebdSchin 		*ep->cursor = '\0';
1384da2e3ebdSchin 		putstring(ep,Prompt);	/* start with prompt */
1385da2e3ebdSchin 	}
1386da2e3ebdSchin 
1387da2e3ebdSchin 	/*********************
1388da2e3ebdSchin 	 Do not update screen if pending characters
1389da2e3ebdSchin 	**********************/
1390da2e3ebdSchin 
1391da2e3ebdSchin 	if ((lookahead)&&(option != FINAL))
1392da2e3ebdSchin 	{
1393da2e3ebdSchin 
1394da2e3ebdSchin 		ep->scvalid = 0; /* Screen is out of date, APPEND will not work */
1395da2e3ebdSchin 
1396da2e3ebdSchin 		return;
1397da2e3ebdSchin 	}
1398da2e3ebdSchin 
1399da2e3ebdSchin 	/***************************************
1400da2e3ebdSchin 	If in append mode, cursor at end of line, screen up to date,
1401da2e3ebdSchin 	the previous character was a 'normal' character,
1402da2e3ebdSchin 	and the window has room for another character.
1403da2e3ebdSchin 	Then output the character and adjust the screen only.
1404da2e3ebdSchin 	*****************************************/
1405da2e3ebdSchin 
1406da2e3ebdSchin