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 /*
22da2e3ebdSchin * edit.c - common routines for vi and emacs one line editors in shell
23da2e3ebdSchin *
24da2e3ebdSchin * David Korn P.D. Sullivan
25da2e3ebdSchin * AT&T Labs
26da2e3ebdSchin *
27da2e3ebdSchin * Coded April 1983.
28da2e3ebdSchin */
29da2e3ebdSchin
30da2e3ebdSchin #include <ast.h>
31da2e3ebdSchin #include <errno.h>
32da2e3ebdSchin #include <ccode.h>
33da2e3ebdSchin #include "FEATURE/options"
34da2e3ebdSchin #include "FEATURE/time"
35da2e3ebdSchin #include "FEATURE/cmds"
36da2e3ebdSchin #ifdef _hdr_utime
37da2e3ebdSchin # include <utime.h>
38da2e3ebdSchin # include <ls.h>
39da2e3ebdSchin #endif
40da2e3ebdSchin
41da2e3ebdSchin #if KSHELL
42da2e3ebdSchin # include "defs.h"
43da2e3ebdSchin # include "variables.h"
44da2e3ebdSchin #else
4534f9b3eeSRoland Mainz # include <ctype.h>
46da2e3ebdSchin extern char ed_errbuf[];
47da2e3ebdSchin char e_version[] = "\n@(#)$Id: Editlib version 1993-12-28 r $\0\n";
48da2e3ebdSchin #endif /* KSHELL */
49da2e3ebdSchin #include "io.h"
50da2e3ebdSchin #include "terminal.h"
51da2e3ebdSchin #include "history.h"
52da2e3ebdSchin #include "edit.h"
53da2e3ebdSchin
54da2e3ebdSchin static char CURSOR_UP[20] = { ESC, '[', 'A', 0 };
55*b30d1939SAndy Fiddaman static char KILL_LINE[20] = { ESC, '[', 'J', 0 };
56da2e3ebdSchin
577c2fbfb3SApril Chin
587c2fbfb3SApril Chin
59da2e3ebdSchin #if SHOPT_MULTIBYTE
60da2e3ebdSchin # define is_cntrl(c) ((c<=STRIP) && iscntrl(c))
61da2e3ebdSchin # define is_print(c) ((c&~STRIP) || isprint(c))
62da2e3ebdSchin #else
63da2e3ebdSchin # define is_cntrl(c) iscntrl(c)
64da2e3ebdSchin # define is_print(c) isprint(c)
65da2e3ebdSchin #endif
66da2e3ebdSchin
67da2e3ebdSchin #if (CC_NATIVE == CC_ASCII)
68da2e3ebdSchin # define printchar(c) ((c) ^ ('A'-cntl('A')))
69da2e3ebdSchin #else
printchar(int c)70da2e3ebdSchin static int printchar(int c)
71da2e3ebdSchin {
72da2e3ebdSchin switch(c)
73da2e3ebdSchin {
74da2e3ebdSchin
75da2e3ebdSchin case cntl('A'): return('A');
76da2e3ebdSchin case cntl('B'): return('B');
77da2e3ebdSchin case cntl('C'): return('C');
78da2e3ebdSchin case cntl('D'): return('D');
79da2e3ebdSchin case cntl('E'): return('E');
80da2e3ebdSchin case cntl('F'): return('F');
81da2e3ebdSchin case cntl('G'): return('G');
82da2e3ebdSchin case cntl('H'): return('H');
83da2e3ebdSchin case cntl('I'): return('I');
84da2e3ebdSchin case cntl('J'): return('J');
85da2e3ebdSchin case cntl('K'): return('K');
86da2e3ebdSchin case cntl('L'): return('L');
87da2e3ebdSchin case cntl('M'): return('M');
88da2e3ebdSchin case cntl('N'): return('N');
89da2e3ebdSchin case cntl('O'): return('O');
90da2e3ebdSchin case cntl('P'): return('P');
91da2e3ebdSchin case cntl('Q'): return('Q');
92da2e3ebdSchin case cntl('R'): return('R');
93da2e3ebdSchin case cntl('S'): return('S');
94da2e3ebdSchin case cntl('T'): return('T');
95da2e3ebdSchin case cntl('U'): return('U');
96da2e3ebdSchin case cntl('V'): return('V');
97da2e3ebdSchin case cntl('W'): return('W');
98da2e3ebdSchin case cntl('X'): return('X');
99da2e3ebdSchin case cntl('Y'): return('Y');
100da2e3ebdSchin case cntl('Z'): return('Z');
101da2e3ebdSchin case cntl(']'): return(']');
102da2e3ebdSchin case cntl('['): return('[');
103da2e3ebdSchin }
104da2e3ebdSchin return('?');
105da2e3ebdSchin }
106da2e3ebdSchin #endif
107da2e3ebdSchin #define MINWINDOW 15 /* minimum width window */
108da2e3ebdSchin #define DFLTWINDOW 80 /* default window width */
109da2e3ebdSchin #define RAWMODE 1
110da2e3ebdSchin #define ALTMODE 2
111da2e3ebdSchin #define ECHOMODE 3
112da2e3ebdSchin #define SYSERR -1
113da2e3ebdSchin
114da2e3ebdSchin #if SHOPT_OLDTERMIO
115da2e3ebdSchin # undef tcgetattr
116da2e3ebdSchin # undef tcsetattr
117da2e3ebdSchin #endif /* SHOPT_OLDTERMIO */
118da2e3ebdSchin
119da2e3ebdSchin #ifdef RT
120da2e3ebdSchin # define VENIX 1
121da2e3ebdSchin #endif /* RT */
122da2e3ebdSchin
123da2e3ebdSchin
124da2e3ebdSchin #ifdef _hdr_sgtty
125da2e3ebdSchin # ifdef TIOCGETP
126da2e3ebdSchin static int l_mask;
127da2e3ebdSchin static struct tchars l_ttychars;
128da2e3ebdSchin static struct ltchars l_chars;
129da2e3ebdSchin static char l_changed; /* set if mode bits changed */
130da2e3ebdSchin # define L_CHARS 4
131da2e3ebdSchin # define T_CHARS 2
132da2e3ebdSchin # define L_MASK 1
133da2e3ebdSchin # endif /* TIOCGETP */
134da2e3ebdSchin #endif /* _hdr_sgtty */
135da2e3ebdSchin
136da2e3ebdSchin #if KSHELL
137da2e3ebdSchin static int keytrap(Edit_t *,char*, int, int, int);
138da2e3ebdSchin #else
139da2e3ebdSchin Edit_t editb;
140da2e3ebdSchin #endif /* KSHELL */
141da2e3ebdSchin
142da2e3ebdSchin
143da2e3ebdSchin #ifndef _POSIX_DISABLE
144da2e3ebdSchin # define _POSIX_DISABLE 0
145da2e3ebdSchin #endif
146da2e3ebdSchin
147da2e3ebdSchin #ifdef future
148da2e3ebdSchin static int compare(const char*, const char*, int);
149da2e3ebdSchin #endif /* future */
150da2e3ebdSchin #if SHOPT_VSH || SHOPT_ESH
151da2e3ebdSchin # define ttyparm (ep->e_ttyparm)
152da2e3ebdSchin # define nttyparm (ep->e_nttyparm)
153da2e3ebdSchin static const char bellchr[] = "\a"; /* bell char */
154da2e3ebdSchin #endif /* SHOPT_VSH || SHOPT_ESH */
155da2e3ebdSchin
156da2e3ebdSchin
157da2e3ebdSchin /*
158da2e3ebdSchin * This routine returns true if fd refers to a terminal
159da2e3ebdSchin * This should be equivalent to isatty
160da2e3ebdSchin */
tty_check(int fd)161da2e3ebdSchin int tty_check(int fd)
162da2e3ebdSchin {
163*b30d1939SAndy Fiddaman register Edit_t *ep = (Edit_t*)(shgd->ed_context);
164da2e3ebdSchin struct termios tty;
165da2e3ebdSchin ep->e_savefd = -1;
166da2e3ebdSchin return(tty_get(fd,&tty)==0);
167da2e3ebdSchin }
168da2e3ebdSchin
169da2e3ebdSchin /*
170da2e3ebdSchin * Get the current terminal attributes
171da2e3ebdSchin * This routine remembers the attributes and just returns them if it
172da2e3ebdSchin * is called again without an intervening tty_set()
173da2e3ebdSchin */
174da2e3ebdSchin
tty_get(register int fd,register struct termios * tty)175da2e3ebdSchin int tty_get(register int fd, register struct termios *tty)
176da2e3ebdSchin {
177*b30d1939SAndy Fiddaman register Edit_t *ep = (Edit_t*)(shgd->ed_context);
178da2e3ebdSchin if(fd == ep->e_savefd)
179da2e3ebdSchin *tty = ep->e_savetty;
180da2e3ebdSchin else
181da2e3ebdSchin {
182da2e3ebdSchin while(tcgetattr(fd,tty) == SYSERR)
183da2e3ebdSchin {
184da2e3ebdSchin if(errno !=EINTR)
185da2e3ebdSchin return(SYSERR);
186da2e3ebdSchin errno = 0;
187da2e3ebdSchin }
188da2e3ebdSchin /* save terminal settings if in cannonical state */
189da2e3ebdSchin if(ep->e_raw==0)
190da2e3ebdSchin {
191da2e3ebdSchin ep->e_savetty = *tty;
192da2e3ebdSchin ep->e_savefd = fd;
193da2e3ebdSchin }
194da2e3ebdSchin }
195da2e3ebdSchin return(0);
196da2e3ebdSchin }
197da2e3ebdSchin
198da2e3ebdSchin /*
199da2e3ebdSchin * Set the terminal attributes
200da2e3ebdSchin * If fd<0, then current attributes are invalidated
201da2e3ebdSchin */
202da2e3ebdSchin
tty_set(int fd,int action,struct termios * tty)203da2e3ebdSchin int tty_set(int fd, int action, struct termios *tty)
204da2e3ebdSchin {
205*b30d1939SAndy Fiddaman register Edit_t *ep = (Edit_t*)(shgd->ed_context);
206da2e3ebdSchin if(fd >=0)
207da2e3ebdSchin {
208da2e3ebdSchin #ifdef future
209da2e3ebdSchin if(ep->e_savefd>=0 && compare(&ep->e_savetty,tty,sizeof(struct termios)))
210da2e3ebdSchin return(0);
211da2e3ebdSchin #endif
212da2e3ebdSchin while(tcsetattr(fd, action, tty) == SYSERR)
213da2e3ebdSchin {
214da2e3ebdSchin if(errno !=EINTR)
215da2e3ebdSchin return(SYSERR);
216da2e3ebdSchin errno = 0;
217da2e3ebdSchin }
218da2e3ebdSchin ep->e_savetty = *tty;
219da2e3ebdSchin }
220da2e3ebdSchin ep->e_savefd = fd;
221da2e3ebdSchin return(0);
222da2e3ebdSchin }
223da2e3ebdSchin
224da2e3ebdSchin #if SHOPT_ESH || SHOPT_VSH
225da2e3ebdSchin /*{ TTY_COOKED( fd )
226da2e3ebdSchin *
227da2e3ebdSchin * This routine will set the tty in cooked mode.
228da2e3ebdSchin * It is also called by error.done().
229da2e3ebdSchin *
230da2e3ebdSchin }*/
231da2e3ebdSchin
tty_cooked(register int fd)232da2e3ebdSchin void tty_cooked(register int fd)
233da2e3ebdSchin {
234*b30d1939SAndy Fiddaman register Edit_t *ep = (Edit_t*)(shgd->ed_context);
235*b30d1939SAndy Fiddaman ep->e_keytrap = 0;
236da2e3ebdSchin if(ep->e_raw==0)
237da2e3ebdSchin return;
238da2e3ebdSchin if(fd < 0)
239da2e3ebdSchin fd = ep->e_savefd;
240da2e3ebdSchin #ifdef L_MASK
241da2e3ebdSchin /* restore flags */
242da2e3ebdSchin if(l_changed&L_MASK)
243da2e3ebdSchin ioctl(fd,TIOCLSET,&l_mask);
244da2e3ebdSchin if(l_changed&T_CHARS)
245da2e3ebdSchin /* restore alternate break character */
246da2e3ebdSchin ioctl(fd,TIOCSETC,&l_ttychars);
247da2e3ebdSchin if(l_changed&L_CHARS)
248da2e3ebdSchin /* restore alternate break character */
249da2e3ebdSchin ioctl(fd,TIOCSLTC,&l_chars);
250da2e3ebdSchin l_changed = 0;
251da2e3ebdSchin #endif /* L_MASK */
252da2e3ebdSchin /*** don't do tty_set unless ttyparm has valid data ***/
253da2e3ebdSchin if(tty_set(fd, TCSANOW, &ttyparm) == SYSERR)
254da2e3ebdSchin return;
255da2e3ebdSchin ep->e_raw = 0;
256da2e3ebdSchin return;
257da2e3ebdSchin }
258da2e3ebdSchin
259da2e3ebdSchin /*{ TTY_RAW( fd )
260da2e3ebdSchin *
261da2e3ebdSchin * This routine will set the tty in raw mode.
262da2e3ebdSchin *
263da2e3ebdSchin }*/
264da2e3ebdSchin
tty_raw(register int fd,int echomode)265da2e3ebdSchin int tty_raw(register int fd, int echomode)
266da2e3ebdSchin {
267da2e3ebdSchin int echo = echomode;
268da2e3ebdSchin #ifdef L_MASK
269da2e3ebdSchin struct ltchars lchars;
270da2e3ebdSchin #endif /* L_MASK */
271*b30d1939SAndy Fiddaman register Edit_t *ep = (Edit_t*)(shgd->ed_context);
272da2e3ebdSchin if(ep->e_raw==RAWMODE)
273da2e3ebdSchin return(echo?-1:0);
274da2e3ebdSchin else if(ep->e_raw==ECHOMODE)
275da2e3ebdSchin return(echo?0:-1);
276da2e3ebdSchin #if !SHOPT_RAWONLY
277da2e3ebdSchin if(ep->e_raw != ALTMODE)
278da2e3ebdSchin #endif /* SHOPT_RAWONLY */
279da2e3ebdSchin {
280da2e3ebdSchin if(tty_get(fd,&ttyparm) == SYSERR)
281da2e3ebdSchin return(-1);
282da2e3ebdSchin }
283da2e3ebdSchin #if L_MASK || VENIX
284da2e3ebdSchin if(ttyparm.sg_flags&LCASE)
285da2e3ebdSchin return(-1);
286da2e3ebdSchin if(!(ttyparm.sg_flags&ECHO))
287da2e3ebdSchin {
288da2e3ebdSchin if(!echomode)
289da2e3ebdSchin return(-1);
290da2e3ebdSchin echo = 0;
291da2e3ebdSchin }
292da2e3ebdSchin nttyparm = ttyparm;
293da2e3ebdSchin if(!echo)
294da2e3ebdSchin nttyparm.sg_flags &= ~(ECHO | TBDELAY);
295da2e3ebdSchin # ifdef CBREAK
296da2e3ebdSchin nttyparm.sg_flags |= CBREAK;
297da2e3ebdSchin # else
298da2e3ebdSchin nttyparm.sg_flags |= RAW;
299da2e3ebdSchin # endif /* CBREAK */
300da2e3ebdSchin ep->e_erase = ttyparm.sg_erase;
301da2e3ebdSchin ep->e_kill = ttyparm.sg_kill;
302da2e3ebdSchin ep->e_eof = cntl('D');
303da2e3ebdSchin ep->e_werase = cntl('W');
304da2e3ebdSchin ep->e_lnext = cntl('V');
305da2e3ebdSchin if( tty_set(fd, TCSADRAIN, &nttyparm) == SYSERR )
306da2e3ebdSchin return(-1);
307da2e3ebdSchin ep->e_ttyspeed = (ttyparm.sg_ospeed>=B1200?FAST:SLOW);
308da2e3ebdSchin # ifdef TIOCGLTC
309da2e3ebdSchin /* try to remove effect of ^V and ^Y and ^O */
310da2e3ebdSchin if(ioctl(fd,TIOCGLTC,&l_chars) != SYSERR)
311da2e3ebdSchin {
312da2e3ebdSchin lchars = l_chars;
313da2e3ebdSchin lchars.t_lnextc = -1;
314da2e3ebdSchin lchars.t_flushc = -1;
315da2e3ebdSchin lchars.t_dsuspc = -1; /* no delayed stop process signal */
316da2e3ebdSchin if(ioctl(fd,TIOCSLTC,&lchars) != SYSERR)
317da2e3ebdSchin l_changed |= L_CHARS;
318da2e3ebdSchin }
319da2e3ebdSchin # endif /* TIOCGLTC */
320da2e3ebdSchin #else
321da2e3ebdSchin if (!(ttyparm.c_lflag & ECHO ))
322da2e3ebdSchin {
323da2e3ebdSchin if(!echomode)
324da2e3ebdSchin return(-1);
325da2e3ebdSchin echo = 0;
326da2e3ebdSchin }
327da2e3ebdSchin # ifdef FLUSHO
328da2e3ebdSchin ttyparm.c_lflag &= ~FLUSHO;
329da2e3ebdSchin # endif /* FLUSHO */
330da2e3ebdSchin nttyparm = ttyparm;
331da2e3ebdSchin # ifndef u370
332da2e3ebdSchin nttyparm.c_iflag &= ~(IGNPAR|PARMRK|INLCR|IGNCR|ICRNL);
333da2e3ebdSchin nttyparm.c_iflag |= BRKINT;
334da2e3ebdSchin # else
335da2e3ebdSchin nttyparm.c_iflag &=
336da2e3ebdSchin ~(IGNBRK|PARMRK|INLCR|IGNCR|ICRNL|INPCK);
337da2e3ebdSchin nttyparm.c_iflag |= (BRKINT|IGNPAR);
338da2e3ebdSchin # endif /* u370 */
339da2e3ebdSchin if(echo)
340*b30d1939SAndy Fiddaman nttyparm.c_lflag &= ~(ICANON);
341da2e3ebdSchin else
342*b30d1939SAndy Fiddaman nttyparm.c_lflag &= ~(ICANON|ISIG|ECHO|ECHOK);
343da2e3ebdSchin nttyparm.c_cc[VTIME] = 0;
344da2e3ebdSchin nttyparm.c_cc[VMIN] = 1;
345da2e3ebdSchin # ifdef VREPRINT
346da2e3ebdSchin nttyparm.c_cc[VREPRINT] = _POSIX_DISABLE;
347da2e3ebdSchin # endif /* VREPRINT */
348da2e3ebdSchin # ifdef VDISCARD
349da2e3ebdSchin nttyparm.c_cc[VDISCARD] = _POSIX_DISABLE;
350da2e3ebdSchin # endif /* VDISCARD */
351da2e3ebdSchin # ifdef VDSUSP
352da2e3ebdSchin nttyparm.c_cc[VDSUSP] = _POSIX_DISABLE;
353da2e3ebdSchin # endif /* VDSUSP */
354da2e3ebdSchin # ifdef VWERASE
355da2e3ebdSchin if(ttyparm.c_cc[VWERASE] == _POSIX_DISABLE)
356da2e3ebdSchin ep->e_werase = cntl('W');
357da2e3ebdSchin else
358da2e3ebdSchin ep->e_werase = nttyparm.c_cc[VWERASE];
359da2e3ebdSchin nttyparm.c_cc[VWERASE] = _POSIX_DISABLE;
360da2e3ebdSchin # else
361da2e3ebdSchin ep->e_werase = cntl('W');
362da2e3ebdSchin # endif /* VWERASE */
363da2e3ebdSchin # ifdef VLNEXT
364da2e3ebdSchin if(ttyparm.c_cc[VLNEXT] == _POSIX_DISABLE )
365da2e3ebdSchin ep->e_lnext = cntl('V');
366da2e3ebdSchin else
367da2e3ebdSchin ep->e_lnext = nttyparm.c_cc[VLNEXT];
368da2e3ebdSchin nttyparm.c_cc[VLNEXT] = _POSIX_DISABLE;
369da2e3ebdSchin # else
370da2e3ebdSchin ep->e_lnext = cntl('V');
371da2e3ebdSchin # endif /* VLNEXT */
372*b30d1939SAndy Fiddaman ep->e_intr = ttyparm.c_cc[VINTR];
373da2e3ebdSchin ep->e_eof = ttyparm.c_cc[VEOF];
374da2e3ebdSchin ep->e_erase = ttyparm.c_cc[VERASE];
375da2e3ebdSchin ep->e_kill = ttyparm.c_cc[VKILL];
376da2e3ebdSchin if( tty_set(fd, TCSADRAIN, &nttyparm) == SYSERR )
377da2e3ebdSchin return(-1);
378da2e3ebdSchin ep->e_ttyspeed = (cfgetospeed(&ttyparm)>=B1200?FAST:SLOW);
379da2e3ebdSchin #endif
380da2e3ebdSchin ep->e_raw = (echomode?ECHOMODE:RAWMODE);
381da2e3ebdSchin return(0);
382da2e3ebdSchin }
383da2e3ebdSchin
384da2e3ebdSchin #if !SHOPT_RAWONLY
385da2e3ebdSchin
386da2e3ebdSchin /*
387da2e3ebdSchin *
388da2e3ebdSchin * Get tty parameters and make ESC and '\r' wakeup characters.
389da2e3ebdSchin *
390da2e3ebdSchin */
391da2e3ebdSchin
392da2e3ebdSchin # ifdef TIOCGETC
tty_alt(register int fd)393da2e3ebdSchin int tty_alt(register int fd)
394da2e3ebdSchin {
395*b30d1939SAndy Fiddaman register Edit_t *ep = (Edit_t*)(shgd->ed_context);
396da2e3ebdSchin int mask;
397da2e3ebdSchin struct tchars ttychars;
398da2e3ebdSchin switch(ep->e_raw)
399da2e3ebdSchin {
400da2e3ebdSchin case ECHOMODE:
401da2e3ebdSchin return(-1);
402da2e3ebdSchin case ALTMODE:
403da2e3ebdSchin return(0);
404da2e3ebdSchin case RAWMODE:
405da2e3ebdSchin tty_cooked(fd);
406da2e3ebdSchin }
407da2e3ebdSchin l_changed = 0;
408da2e3ebdSchin if( ep->e_ttyspeed == 0)
409da2e3ebdSchin {
410da2e3ebdSchin if((tty_get(fd,&ttyparm) != SYSERR))
411da2e3ebdSchin ep->e_ttyspeed = (ttyparm.sg_ospeed>=B1200?FAST:SLOW);
412da2e3ebdSchin ep->e_raw = ALTMODE;
413da2e3ebdSchin }
414da2e3ebdSchin if(ioctl(fd,TIOCGETC,&l_ttychars) == SYSERR)
415da2e3ebdSchin return(-1);
416da2e3ebdSchin if(ioctl(fd,TIOCLGET,&l_mask)==SYSERR)
417da2e3ebdSchin return(-1);
418da2e3ebdSchin ttychars = l_ttychars;
419da2e3ebdSchin mask = LCRTBS|LCRTERA|LCTLECH|LPENDIN|LCRTKIL;
420da2e3ebdSchin if((l_mask|mask) != l_mask)
421da2e3ebdSchin l_changed = L_MASK;
422da2e3ebdSchin if(ioctl(fd,TIOCLBIS,&mask)==SYSERR)
423da2e3ebdSchin return(-1);
424da2e3ebdSchin if(ttychars.t_brkc!=ESC)
425da2e3ebdSchin {
426da2e3ebdSchin ttychars.t_brkc = ESC;
427da2e3ebdSchin l_changed |= T_CHARS;
428da2e3ebdSchin if(ioctl(fd,TIOCSETC,&ttychars) == SYSERR)
429da2e3ebdSchin return(-1);
430da2e3ebdSchin }
431da2e3ebdSchin return(0);
432da2e3ebdSchin }
433da2e3ebdSchin # else
434da2e3ebdSchin # ifndef PENDIN
435da2e3ebdSchin # define PENDIN 0
436da2e3ebdSchin # endif /* PENDIN */
437da2e3ebdSchin # ifndef IEXTEN
438da2e3ebdSchin # define IEXTEN 0
439da2e3ebdSchin # endif /* IEXTEN */
440da2e3ebdSchin
tty_alt(register int fd)441da2e3ebdSchin int tty_alt(register int fd)
442da2e3ebdSchin {
443*b30d1939SAndy Fiddaman register Edit_t *ep = (Edit_t*)(shgd->ed_context);
444da2e3ebdSchin switch(ep->e_raw)
445da2e3ebdSchin {
446da2e3ebdSchin case ECHOMODE:
447da2e3ebdSchin return(-1);
448da2e3ebdSchin case ALTMODE:
449da2e3ebdSchin return(0);
450da2e3ebdSchin case RAWMODE:
451da2e3ebdSchin tty_cooked(fd);
452da2e3ebdSchin }
453da2e3ebdSchin if((tty_get(fd, &ttyparm)==SYSERR) || (!(ttyparm.c_lflag&ECHO)))
454da2e3ebdSchin return(-1);
455da2e3ebdSchin # ifdef FLUSHO
456da2e3ebdSchin ttyparm.c_lflag &= ~FLUSHO;
457da2e3ebdSchin # endif /* FLUSHO */
458da2e3ebdSchin nttyparm = ttyparm;
459da2e3ebdSchin ep->e_eof = ttyparm.c_cc[VEOF];
460da2e3ebdSchin # ifdef ECHOCTL
461da2e3ebdSchin /* escape character echos as ^[ */
462da2e3ebdSchin nttyparm.c_lflag |= (ECHOE|ECHOK|ECHOCTL|PENDIN|IEXTEN);
463da2e3ebdSchin nttyparm.c_cc[VEOL] = ESC;
464da2e3ebdSchin # else
465da2e3ebdSchin /* switch VEOL2 and EOF, since EOF isn't echo'd by driver */
466da2e3ebdSchin nttyparm.c_lflag |= (ECHOE|ECHOK);
467da2e3ebdSchin nttyparm.c_cc[VEOF] = ESC; /* make ESC the eof char */
468da2e3ebdSchin # ifdef VEOL2
469da2e3ebdSchin nttyparm.c_iflag &= ~(IGNCR|ICRNL);
470da2e3ebdSchin nttyparm.c_iflag |= INLCR;
471da2e3ebdSchin nttyparm.c_cc[VEOL] = '\r'; /* make CR an eol char */
472da2e3ebdSchin nttyparm.c_cc[VEOL2] = ep->e_eof; /* make EOF an eol char */
473da2e3ebdSchin # else
474da2e3ebdSchin nttyparm.c_cc[VEOL] = ep->e_eof; /* make EOF an eol char */
475da2e3ebdSchin # endif /* VEOL2 */
476da2e3ebdSchin # endif /* ECHOCTL */
477da2e3ebdSchin # ifdef VREPRINT
478da2e3ebdSchin nttyparm.c_cc[VREPRINT] = _POSIX_DISABLE;
479da2e3ebdSchin # endif /* VREPRINT */
480da2e3ebdSchin # ifdef VDISCARD
481da2e3ebdSchin nttyparm.c_cc[VDISCARD] = _POSIX_DISABLE;
482da2e3ebdSchin # endif /* VDISCARD */
483da2e3ebdSchin # ifdef VWERASE
484da2e3ebdSchin if(ttyparm.c_cc[VWERASE] == _POSIX_DISABLE)
485da2e3ebdSchin nttyparm.c_cc[VWERASE] = cntl('W');
486da2e3ebdSchin ep->e_werase = nttyparm.c_cc[VWERASE];
487da2e3ebdSchin # else
488da2e3ebdSchin ep->e_werase = cntl('W');
489da2e3ebdSchin # endif /* VWERASE */
490da2e3ebdSchin # ifdef VLNEXT
491da2e3ebdSchin if(ttyparm.c_cc[VLNEXT] == _POSIX_DISABLE )
492da2e3ebdSchin nttyparm.c_cc[VLNEXT] = cntl('V');
493da2e3ebdSchin ep->e_lnext = nttyparm.c_cc[VLNEXT];
494da2e3ebdSchin # else
495da2e3ebdSchin ep->e_lnext = cntl('V');
496da2e3ebdSchin # endif /* VLNEXT */
497da2e3ebdSchin ep->e_erase = ttyparm.c_cc[VERASE];
498da2e3ebdSchin ep->e_kill = ttyparm.c_cc[VKILL];
499da2e3ebdSchin if( tty_set(fd, TCSADRAIN, &nttyparm) == SYSERR )
500da2e3ebdSchin return(-1);
501da2e3ebdSchin ep->e_ttyspeed = (cfgetospeed(&ttyparm)>=B1200?FAST:SLOW);
502da2e3ebdSchin ep->e_raw = ALTMODE;
503da2e3ebdSchin return(0);
504da2e3ebdSchin }
505da2e3ebdSchin
506da2e3ebdSchin # endif /* TIOCGETC */
507da2e3ebdSchin #endif /* SHOPT_RAWONLY */
508da2e3ebdSchin
509da2e3ebdSchin /*
510da2e3ebdSchin * ED_WINDOW()
511da2e3ebdSchin *
512da2e3ebdSchin * return the window size
513da2e3ebdSchin */
ed_window(void)514da2e3ebdSchin int ed_window(void)
515da2e3ebdSchin {
516da2e3ebdSchin int rows,cols;
517da2e3ebdSchin register char *cp = nv_getval(COLUMNS);
518da2e3ebdSchin if(cp)
519da2e3ebdSchin cols = (int)strtol(cp, (char**)0, 10)-1;
520da2e3ebdSchin else
521da2e3ebdSchin {
522da2e3ebdSchin astwinsize(2,&rows,&cols);
523da2e3ebdSchin if(--cols <0)
524da2e3ebdSchin cols = DFLTWINDOW-1;
525da2e3ebdSchin }
526da2e3ebdSchin if(cols < MINWINDOW)
527da2e3ebdSchin cols = MINWINDOW;
528da2e3ebdSchin else if(cols > MAXWINDOW)
529da2e3ebdSchin cols = MAXWINDOW;
530da2e3ebdSchin return(cols);
531da2e3ebdSchin }
532da2e3ebdSchin
533da2e3ebdSchin /* E_FLUSH()
534da2e3ebdSchin *
535da2e3ebdSchin * Flush the output buffer.
536da2e3ebdSchin *
537da2e3ebdSchin */
538da2e3ebdSchin
ed_flush(Edit_t * ep)539da2e3ebdSchin void ed_flush(Edit_t *ep)
540da2e3ebdSchin {
541da2e3ebdSchin register int n = ep->e_outptr-ep->e_outbase;
542da2e3ebdSchin register int fd = ERRIO;
543da2e3ebdSchin if(n<=0)
544da2e3ebdSchin return;
545da2e3ebdSchin write(fd,ep->e_outbase,(unsigned)n);
546da2e3ebdSchin ep->e_outptr = ep->e_outbase;
547da2e3ebdSchin }
548da2e3ebdSchin
549da2e3ebdSchin /*
550da2e3ebdSchin * send the bell character ^G to the terminal
551da2e3ebdSchin */
552da2e3ebdSchin
ed_ringbell(void)553da2e3ebdSchin void ed_ringbell(void)
554da2e3ebdSchin {
555da2e3ebdSchin write(ERRIO,bellchr,1);
556da2e3ebdSchin }
557da2e3ebdSchin
558da2e3ebdSchin /*
559da2e3ebdSchin * send a carriage return line feed to the terminal
560da2e3ebdSchin */
561da2e3ebdSchin
ed_crlf(register Edit_t * ep)562da2e3ebdSchin void ed_crlf(register Edit_t *ep)
563da2e3ebdSchin {
564da2e3ebdSchin #ifdef cray
565da2e3ebdSchin ed_putchar(ep,'\r');
566da2e3ebdSchin #endif /* cray */
567da2e3ebdSchin #ifdef u370
568da2e3ebdSchin ed_putchar(ep,'\r');
569da2e3ebdSchin #endif /* u370 */
570da2e3ebdSchin #ifdef VENIX
571da2e3ebdSchin ed_putchar(ep,'\r');
572da2e3ebdSchin #endif /* VENIX */
573da2e3ebdSchin ed_putchar(ep,'\n');
574da2e3ebdSchin ed_flush(ep);
575da2e3ebdSchin }
576da2e3ebdSchin
577da2e3ebdSchin /* ED_SETUP( max_prompt_size )
578da2e3ebdSchin *
579da2e3ebdSchin * This routine sets up the prompt string
580da2e3ebdSchin * The following is an unadvertised feature.
581da2e3ebdSchin * Escape sequences in the prompt can be excluded from the calculated
582da2e3ebdSchin * prompt length. This is accomplished as follows:
583da2e3ebdSchin * - if the prompt string starts with "%\r, or contains \r%\r", where %
584da2e3ebdSchin * represents any char, then % is taken to be the quote character.
585da2e3ebdSchin * - strings enclosed by this quote character, and the quote character,
586da2e3ebdSchin * are not counted as part of the prompt length.
587da2e3ebdSchin */
588da2e3ebdSchin
ed_setup(register Edit_t * ep,int fd,int reedit)589da2e3ebdSchin void ed_setup(register Edit_t *ep, int fd, int reedit)
590da2e3ebdSchin {
5917c2fbfb3SApril Chin Shell_t *shp = ep->sh;
592da2e3ebdSchin register char *pp;
5937c2fbfb3SApril Chin register char *last, *prev;
594da2e3ebdSchin char *ppmax;
595da2e3ebdSchin int myquote = 0, n;
5967c2fbfb3SApril Chin register int qlen = 1, qwid;
597da2e3ebdSchin char inquote = 0;
598da2e3ebdSchin ep->e_fd = fd;
599da2e3ebdSchin ep->e_multiline = sh_isoption(SH_MULTILINE)!=0;
600da2e3ebdSchin #ifdef SIGWINCH
6017c2fbfb3SApril Chin if(!(shp->sigflag[SIGWINCH]&SH_SIGFAULT))
602da2e3ebdSchin {
603da2e3ebdSchin signal(SIGWINCH,sh_fault);
6047c2fbfb3SApril Chin shp->sigflag[SIGWINCH] |= SH_SIGFAULT;
605da2e3ebdSchin }
6067c2fbfb3SApril Chin pp = shp->st.trapcom[SIGWINCH];
6077c2fbfb3SApril Chin shp->st.trapcom[SIGWINCH] = 0;
608da2e3ebdSchin sh_fault(SIGWINCH);
6097c2fbfb3SApril Chin shp->st.trapcom[SIGWINCH] = pp;
6107c2fbfb3SApril Chin ep->sh->winch = 0;
611da2e3ebdSchin #endif
612*b30d1939SAndy Fiddaman #if SHOPT_EDPREDICT
613*b30d1939SAndy Fiddaman ep->hlist = 0;
614*b30d1939SAndy Fiddaman ep->nhlist = 0;
615*b30d1939SAndy Fiddaman ep->hoff = 0;
616*b30d1939SAndy Fiddaman #endif /* SHOPT_EDPREDICT */
617da2e3ebdSchin #if KSHELL
618da2e3ebdSchin ep->e_stkptr = stakptr(0);
619da2e3ebdSchin ep->e_stkoff = staktell();
6207c2fbfb3SApril Chin if(!(last = shp->prompt))
621da2e3ebdSchin last = "";
6227c2fbfb3SApril Chin shp->prompt = 0;
623da2e3ebdSchin #else
624da2e3ebdSchin last = ep->e_prbuff;
625da2e3ebdSchin #endif /* KSHELL */
626*b30d1939SAndy Fiddaman if(shp->gd->hist_ptr)
627da2e3ebdSchin {
628*b30d1939SAndy Fiddaman register History_t *hp = shp->gd->hist_ptr;
629da2e3ebdSchin ep->e_hismax = hist_max(hp);
630da2e3ebdSchin ep->e_hismin = hist_min(hp);
631da2e3ebdSchin }
632da2e3ebdSchin else
633da2e3ebdSchin {
634da2e3ebdSchin ep->e_hismax = ep->e_hismin = ep->e_hloff = 0;
635da2e3ebdSchin }
636da2e3ebdSchin ep->e_hline = ep->e_hismax;
637da2e3ebdSchin if(!sh_isoption(SH_VI) && !sh_isoption(SH_EMACS) && !sh_isoption(SH_GMACS))
638da2e3ebdSchin ep->e_wsize = MAXLINE;
639da2e3ebdSchin else
640da2e3ebdSchin ep->e_wsize = ed_window()-2;
641da2e3ebdSchin ep->e_winsz = ep->e_wsize+2;
642da2e3ebdSchin ep->e_crlf = 1;
643da2e3ebdSchin ep->e_plen = 0;
644da2e3ebdSchin pp = ep->e_prompt;
645da2e3ebdSchin ppmax = pp+PRSIZE-1;
646da2e3ebdSchin *pp++ = '\r';
647da2e3ebdSchin {
648da2e3ebdSchin register int c;
6497c2fbfb3SApril Chin while(prev = last, c = mbchar(last)) switch(c)
650da2e3ebdSchin {
651da2e3ebdSchin case ESC:
652da2e3ebdSchin {
653da2e3ebdSchin int skip=0;
654da2e3ebdSchin ep->e_crlf = 0;
655*b30d1939SAndy Fiddaman if (pp < ppmax)
656*b30d1939SAndy Fiddaman *pp++ = c;
657da2e3ebdSchin for(n=1; c = *last++; n++)
658da2e3ebdSchin {
659da2e3ebdSchin if(pp < ppmax)
660da2e3ebdSchin *pp++ = c;
6617c2fbfb3SApril Chin if(c=='\a' || c==ESC || c=='\r')
662da2e3ebdSchin break;
663da2e3ebdSchin if(skip || (c>='0' && c<='9'))
664*b30d1939SAndy Fiddaman {
665*b30d1939SAndy Fiddaman skip = 0;
666da2e3ebdSchin continue;
667*b30d1939SAndy Fiddaman }
668da2e3ebdSchin if(n>1 && c==';')
669da2e3ebdSchin skip = 1;
670da2e3ebdSchin else if(n>2 || (c!= '[' && c!= ']'))
671da2e3ebdSchin break;
672da2e3ebdSchin }
6737c2fbfb3SApril Chin if(c==0 || c==ESC || c=='\r')
6747c2fbfb3SApril Chin last--;
675da2e3ebdSchin qlen += (n+1);
676da2e3ebdSchin break;
677da2e3ebdSchin }
678da2e3ebdSchin case '\b':
679da2e3ebdSchin if(pp>ep->e_prompt+1)
680da2e3ebdSchin pp--;
681da2e3ebdSchin break;
682da2e3ebdSchin case '\r':
683da2e3ebdSchin if(pp == (ep->e_prompt+2)) /* quote char */
684da2e3ebdSchin myquote = *(pp-1);
685da2e3ebdSchin /*FALLTHROUGH*/
686da2e3ebdSchin
687da2e3ebdSchin case '\n':
688da2e3ebdSchin /* start again */
689da2e3ebdSchin ep->e_crlf = 1;
690da2e3ebdSchin qlen = 1;
691da2e3ebdSchin inquote = 0;
692da2e3ebdSchin pp = ep->e_prompt+1;
693da2e3ebdSchin break;
694da2e3ebdSchin
695da2e3ebdSchin case '\t':
696da2e3ebdSchin /* expand tabs */
697da2e3ebdSchin while((pp-ep->e_prompt)%TABSIZE)
698da2e3ebdSchin {
699da2e3ebdSchin if(pp >= ppmax)
700da2e3ebdSchin break;
701da2e3ebdSchin *pp++ = ' ';
702da2e3ebdSchin }
703da2e3ebdSchin break;
704da2e3ebdSchin
705da2e3ebdSchin case '\a':
706da2e3ebdSchin /* cut out bells */
707da2e3ebdSchin break;
708da2e3ebdSchin
709da2e3ebdSchin default:
710da2e3ebdSchin if(c==myquote)
711da2e3ebdSchin {
712da2e3ebdSchin qlen += inquote;
713da2e3ebdSchin inquote ^= 1;
714da2e3ebdSchin }
715da2e3ebdSchin if(pp < ppmax)
716da2e3ebdSchin {
7177c2fbfb3SApril Chin if(inquote)
7187c2fbfb3SApril Chin qlen++;
7197c2fbfb3SApril Chin else if(!is_print(c))
720da2e3ebdSchin ep->e_crlf = 0;
7217c2fbfb3SApril Chin if((qwid = last - prev) > 1)
7227c2fbfb3SApril Chin qlen += qwid - mbwidth(c);
7237c2fbfb3SApril Chin while(prev < last && pp < ppmax)
7247c2fbfb3SApril Chin *pp++ = *prev++;
725da2e3ebdSchin }
7267c2fbfb3SApril Chin break;
727da2e3ebdSchin }
728da2e3ebdSchin }
729da2e3ebdSchin if(pp-ep->e_prompt > qlen)
730da2e3ebdSchin ep->e_plen = pp - ep->e_prompt - qlen;
731da2e3ebdSchin *pp = 0;
7327c2fbfb3SApril Chin if(!ep->e_multiline && (ep->e_wsize -= ep->e_plen) < 7)
733da2e3ebdSchin {
734da2e3ebdSchin register int shift = 7-ep->e_wsize;
735da2e3ebdSchin ep->e_wsize = 7;
736da2e3ebdSchin pp = ep->e_prompt+1;
737da2e3ebdSchin strcpy(pp,pp+shift);
738da2e3ebdSchin ep->e_plen -= shift;
739da2e3ebdSchin last[-ep->e_plen-2] = '\r';
740da2e3ebdSchin }
741da2e3ebdSchin sfsync(sfstderr);
742da2e3ebdSchin if(fd == sffileno(sfstderr))
743da2e3ebdSchin {
744da2e3ebdSchin /* can't use output buffer when reading from stderr */
745da2e3ebdSchin static char *buff;
746da2e3ebdSchin if(!buff)
747da2e3ebdSchin buff = (char*)malloc(MAXLINE);
748da2e3ebdSchin ep->e_outbase = ep->e_outptr = buff;
749da2e3ebdSchin ep->e_outlast = ep->e_outptr + MAXLINE;
750da2e3ebdSchin return;
751da2e3ebdSchin }
752da2e3ebdSchin qlen = sfset(sfstderr,SF_READ,0);
753da2e3ebdSchin /* make sure SF_READ not on */
754da2e3ebdSchin ep->e_outbase = ep->e_outptr = (char*)sfreserve(sfstderr,SF_UNBOUND,SF_LOCKR);
755da2e3ebdSchin ep->e_outlast = ep->e_outptr + sfvalue(sfstderr);
756da2e3ebdSchin if(qlen)
757da2e3ebdSchin sfset(sfstderr,SF_READ,1);
758da2e3ebdSchin sfwrite(sfstderr,ep->e_outptr,0);
759da2e3ebdSchin ep->e_eol = reedit;
760da2e3ebdSchin if(ep->e_multiline)
761da2e3ebdSchin {
762da2e3ebdSchin #ifdef _cmd_tput
763da2e3ebdSchin char *term;
764da2e3ebdSchin if(!ep->e_term)
7657c2fbfb3SApril Chin ep->e_term = nv_search("TERM",shp->var_tree,0);
766da2e3ebdSchin if(ep->e_term && (term=nv_getval(ep->e_term)) && strlen(term)<sizeof(ep->e_termname) && strcmp(term,ep->e_termname))
767da2e3ebdSchin {
768da2e3ebdSchin sh_trap(".sh.subscript=$(tput cuu1 2>/dev/null)",0);
769da2e3ebdSchin if(pp=nv_getval(SH_SUBSCRNOD))
770da2e3ebdSchin strncpy(CURSOR_UP,pp,sizeof(CURSOR_UP)-1);
771da2e3ebdSchin nv_unset(SH_SUBSCRNOD);
772da2e3ebdSchin strcpy(ep->e_termname,term);
773da2e3ebdSchin }
774da2e3ebdSchin #endif
7757c2fbfb3SApril Chin ep->e_wsize = MAXLINE - (ep->e_plen+1);
776da2e3ebdSchin }
777da2e3ebdSchin if(ep->e_default && (pp = nv_getval(ep->e_default)))
778da2e3ebdSchin {
779da2e3ebdSchin n = strlen(pp);
780da2e3ebdSchin if(n > LOOKAHEAD)
781da2e3ebdSchin n = LOOKAHEAD;
782da2e3ebdSchin ep->e_lookahead = n;
783da2e3ebdSchin while(n-- > 0)
784da2e3ebdSchin ep->e_lbuf[n] = *pp++;
785da2e3ebdSchin ep->e_default = 0;
786da2e3ebdSchin }
787da2e3ebdSchin }
788da2e3ebdSchin
ed_putstring(register Edit_t * ep,const char * str)7897c2fbfb3SApril Chin static void ed_putstring(register Edit_t *ep, const char *str)
7907c2fbfb3SApril Chin {
7917c2fbfb3SApril Chin register int c;
7927c2fbfb3SApril Chin while(c = *str++)
7937c2fbfb3SApril Chin ed_putchar(ep,c);
7947c2fbfb3SApril Chin }
7957c2fbfb3SApril Chin
ed_nputchar(register Edit_t * ep,int n,int c)7967c2fbfb3SApril Chin static void ed_nputchar(register Edit_t *ep, int n, int c)
7977c2fbfb3SApril Chin {
7987c2fbfb3SApril Chin while(n-->0)
7997c2fbfb3SApril Chin ed_putchar(ep,c);
8007c2fbfb3SApril Chin }
8017c2fbfb3SApril Chin
802da2e3ebdSchin /*
803da2e3ebdSchin * Do read, restart on interrupt unless SH_SIGSET or SH_SIGTRAP is set
804da2e3ebdSchin * Use sfpkrd() to poll() or select() to wait for input if possible
805da2e3ebdSchin * Unfortunately, systems that get interrupted from slow reads update
806da2e3ebdSchin * this access time for for the terminal (in violation of POSIX).
807da2e3ebdSchin * The fixtime() macro, resets the time to the time at entry in
808da2e3ebdSchin * this case. This is not necessary for systems that can handle
809da2e3ebdSchin * sfpkrd() correctly (i,e., those that support poll() or select()
810da2e3ebdSchin */
ed_read(void * context,int fd,char * buff,int size,int reedit)811da2e3ebdSchin int ed_read(void *context, int fd, char *buff, int size, int reedit)
812da2e3ebdSchin {
813da2e3ebdSchin register Edit_t *ep = (Edit_t*)context;
814da2e3ebdSchin register int rv= -1;
815*b30d1939SAndy Fiddaman register int delim = ((ep->e_raw&RAWMODE)?nttyparm.c_cc[VEOL]:'\n');
8167c2fbfb3SApril Chin Shell_t *shp = ep->sh;
817da2e3ebdSchin int mode = -1;
818*b30d1939SAndy Fiddaman int (*waitevent)(int,long,int) = shp->gd->waitevent;
819da2e3ebdSchin if(ep->e_raw==ALTMODE)
820da2e3ebdSchin mode = 1;
821da2e3ebdSchin if(size < 0)
822da2e3ebdSchin {
823da2e3ebdSchin mode = 1;
824da2e3ebdSchin size = -size;
825da2e3ebdSchin }
826da2e3ebdSchin sh_onstate(SH_TTYWAIT);
827da2e3ebdSchin errno = EINTR;
828*b30d1939SAndy Fiddaman shp->gd->waitevent = 0;
829da2e3ebdSchin while(rv<0 && errno==EINTR)
830da2e3ebdSchin {
8317c2fbfb3SApril Chin if(shp->trapnote&(SH_SIGSET|SH_SIGTRAP))
832da2e3ebdSchin goto done;
83334f9b3eeSRoland Mainz if(ep->sh->winch && sh_isstate(SH_INTERACTIVE) && (sh_isoption(SH_VI) || sh_isoption(SH_EMACS)))
8347c2fbfb3SApril Chin {
8357c2fbfb3SApril Chin Edpos_t lastpos;
8367c2fbfb3SApril Chin int n, rows, newsize;
8377c2fbfb3SApril Chin /* move cursor to start of first line */
8387c2fbfb3SApril Chin ed_putchar(ep,'\r');
8397c2fbfb3SApril Chin ed_flush(ep);
8407c2fbfb3SApril Chin astwinsize(2,&rows,&newsize);
8417c2fbfb3SApril Chin n = (ep->e_plen+ep->e_cur)/++ep->e_winsz;
8427c2fbfb3SApril Chin while(n--)
8437c2fbfb3SApril Chin ed_putstring(ep,CURSOR_UP);
8447c2fbfb3SApril Chin if(ep->e_multiline && newsize>ep->e_winsz && (lastpos.line=(ep->e_plen+ep->e_peol)/ep->e_winsz))
8457c2fbfb3SApril Chin {
8467c2fbfb3SApril Chin /* clear the current command line */
8477c2fbfb3SApril Chin n = lastpos.line;
8487c2fbfb3SApril Chin while(lastpos.line--)
8497c2fbfb3SApril Chin {
8507c2fbfb3SApril Chin ed_nputchar(ep,ep->e_winsz,' ');
8517c2fbfb3SApril Chin ed_putchar(ep,'\n');
8527c2fbfb3SApril Chin }
8537c2fbfb3SApril Chin ed_nputchar(ep,ep->e_winsz,' ');
8547c2fbfb3SApril Chin while(n--)
8557c2fbfb3SApril Chin ed_putstring(ep,CURSOR_UP);
8567c2fbfb3SApril Chin }
8577c2fbfb3SApril Chin ep->sh->winch = 0;
8587c2fbfb3SApril Chin ed_flush(ep);
8597c2fbfb3SApril Chin sh_delay(.05);
8607c2fbfb3SApril Chin astwinsize(2,&rows,&newsize);
8617c2fbfb3SApril Chin ep->e_winsz = newsize-1;
862*b30d1939SAndy Fiddaman if(ep->e_winsz < MINWINDOW)
863*b30d1939SAndy Fiddaman ep->e_winsz = MINWINDOW;
8647c2fbfb3SApril Chin if(!ep->e_multiline && ep->e_wsize < MAXLINE)
8657c2fbfb3SApril Chin ep->e_wsize = ep->e_winsz-2;
8667c2fbfb3SApril Chin ep->e_nocrnl=1;
8677c2fbfb3SApril Chin if(*ep->e_vi_insert)
8687c2fbfb3SApril Chin {
8697c2fbfb3SApril Chin buff[0] = ESC;
8707c2fbfb3SApril Chin buff[1] = cntl('L');
8717c2fbfb3SApril Chin buff[2] = 'a';
8727c2fbfb3SApril Chin return(3);
8737c2fbfb3SApril Chin }
87434f9b3eeSRoland Mainz if(sh_isoption(SH_EMACS) || sh_isoption(SH_VI))
87534f9b3eeSRoland Mainz buff[0] = cntl('L');
8767c2fbfb3SApril Chin return(1);
8777c2fbfb3SApril Chin }
87834f9b3eeSRoland Mainz else
87934f9b3eeSRoland Mainz ep->sh->winch = 0;
880da2e3ebdSchin /* an interrupt that should be ignored */
881da2e3ebdSchin errno = 0;
882da2e3ebdSchin if(!waitevent || (rv=(*waitevent)(fd,-1L,0))>=0)
883da2e3ebdSchin rv = sfpkrd(fd,buff,size,delim,-1L,mode);
884da2e3ebdSchin }
885da2e3ebdSchin if(rv < 0)
886da2e3ebdSchin {
887da2e3ebdSchin #ifdef _hdr_utime
888da2e3ebdSchin # define fixtime() if(isdevtty)utime(ep->e_tty,&utimes)
889da2e3ebdSchin int isdevtty=0;
890da2e3ebdSchin struct stat statb;
891da2e3ebdSchin struct utimbuf utimes;
892da2e3ebdSchin if(errno==0 && !ep->e_tty)
893da2e3ebdSchin {
894da2e3ebdSchin if((ep->e_tty=ttyname(fd)) && stat(ep->e_tty,&statb)>=0)
895da2e3ebdSchin {
896da2e3ebdSchin ep->e_tty_ino = statb.st_ino;
897da2e3ebdSchin ep->e_tty_dev = statb.st_dev;
898da2e3ebdSchin }
899da2e3ebdSchin }
900da2e3ebdSchin if(ep->e_tty_ino && fstat(fd,&statb)>=0 && statb.st_ino==ep->e_tty_ino && statb.st_dev==ep->e_tty_dev)
901da2e3ebdSchin {
902da2e3ebdSchin utimes.actime = statb.st_atime;
903da2e3ebdSchin utimes.modtime = statb.st_mtime;
904da2e3ebdSchin isdevtty=1;
905da2e3ebdSchin }
906da2e3ebdSchin #else
907da2e3ebdSchin # define fixtime()
908da2e3ebdSchin #endif /* _hdr_utime */
909da2e3ebdSchin while(1)
910da2e3ebdSchin {
911da2e3ebdSchin rv = read(fd,buff,size);
912da2e3ebdSchin if(rv>=0 || errno!=EINTR)
913da2e3ebdSchin break;
9147c2fbfb3SApril Chin if(shp->trapnote&(SH_SIGSET|SH_SIGTRAP))
915da2e3ebdSchin goto done;
916da2e3ebdSchin /* an interrupt that should be ignored */
917da2e3ebdSchin fixtime();
918da2e3ebdSchin }
919da2e3ebdSchin }
920da2e3ebdSchin else if(rv>=0 && mode>0)
921da2e3ebdSchin rv = read(fd,buff,rv>0?rv:1);
922da2e3ebdSchin done:
923*b30d1939SAndy Fiddaman shp->gd->waitevent = waitevent;
924da2e3ebdSchin sh_offstate(SH_TTYWAIT);
925da2e3ebdSchin return(rv);
926da2e3ebdSchin }
927da2e3ebdSchin
928da2e3ebdSchin
929da2e3ebdSchin /*
930da2e3ebdSchin * put <string> of length <nbyte> onto lookahead stack
931da2e3ebdSchin * if <type> is non-zero, the negation of the character is put
932da2e3ebdSchin * onto the stack so that it can be checked for KEYTRAP
933da2e3ebdSchin * putstack() returns 1 except when in the middle of a multi-byte char
934da2e3ebdSchin */
935da2e3ebdSchin static int putstack(Edit_t *ep,char string[], register int nbyte, int type)
936da2e3ebdSchin {
937da2e3ebdSchin register int c;
938da2e3ebdSchin #if SHOPT_MULTIBYTE
939da2e3ebdSchin char *endp, *p=string;
940da2e3ebdSchin int size, offset = ep->e_lookahead + nbyte;
941da2e3ebdSchin *(endp = &p[nbyte]) = 0;
942da2e3ebdSchin endp = &p[nbyte];
943da2e3ebdSchin do
944da2e3ebdSchin {
945da2e3ebdSchin c = (int)((*p) & STRIP);
946da2e3ebdSchin if(c< 0x80 && c!='<')
947da2e3ebdSchin {
948da2e3ebdSchin if (type)
949da2e3ebdSchin c = -c;
950da2e3ebdSchin # ifndef CBREAK
951da2e3ebdSchin if(c == '\0')
952da2e3ebdSchin {
953da2e3ebdSchin /*** user break key ***/
954da2e3ebdSchin ep->e_lookahead = 0;
955da2e3ebdSchin # if KSHELL
956da2e3ebdSchin sh_fault(SIGINT);
957da2e3ebdSchin siglongjmp(ep->e_env, UINTR);
958da2e3ebdSchin # endif /* KSHELL */
959da2e3ebdSchin }
960da2e3ebdSchin # endif /* CBREAK */
961da2e3ebdSchin
962da2e3ebdSchin }
963da2e3ebdSchin else
964da2e3ebdSchin {
965da2e3ebdSchin again:
966da2e3ebdSchin if((c=mbchar(p)) >=0)
967da2e3ebdSchin {
968da2e3ebdSchin p--; /* incremented below */
969da2e3ebdSchin if(type)
970da2e3ebdSchin c = -c;
971da2e3ebdSchin }
972da2e3ebdSchin #ifdef EILSEQ
973da2e3ebdSchin else if(errno == EILSEQ)
974da2e3ebdSchin errno = 0;
975da2e3ebdSchin #endif
976da2e3ebdSchin else if((endp-p) < mbmax())
977da2e3ebdSchin {
978da2e3ebdSchin if ((c=ed_read(ep,ep->e_fd,endp, 1,0)) == 1)
979da2e3ebdSchin {
980da2e3ebdSchin *++endp = 0;
981da2e3ebdSchin goto again;
982da2e3ebdSchin }
983da2e3ebdSchin return(c);
984da2e3ebdSchin }
985da2e3ebdSchin else
986da2e3ebdSchin {
987da2e3ebdSchin ed_ringbell();
988da2e3ebdSchin c = -(int)((*p) & STRIP);
989da2e3ebdSchin offset += mbmax()-1;
990da2e3ebdSchin }
991da2e3ebdSchin }
992da2e3ebdSchin ep->e_lbuf[--offset] = c;
993da2e3ebdSchin p++;
994da2e3ebdSchin }
995da2e3ebdSchin while (p < endp);
996da2e3ebdSchin /* shift lookahead buffer if necessary */
997da2e3ebdSchin if(offset -= ep->e_lookahead)
998da2e3ebdSchin {
999da2e3ebdSchin for(size=offset;size < nbyte;size++)
1000da2e3ebdSchin ep->e_lbuf[ep->e_lookahead+size-offset] = ep->e_lbuf[ep->e_lookahead+size];
1001da2e3ebdSchin }
1002da2e3ebdSchin ep->e_lookahead += nbyte-offset;
1003da2e3ebdSchin #else
1004da2e3ebdSchin while (nbyte > 0)
1005da2e3ebdSchin {
1006da2e3ebdSchin c = string[--nbyte] & STRIP;
1007da2e3ebdSchin ep->e_lbuf[ep->e_lookahead++] = (type?-c:c);
1008da2e3ebdSchin # ifndef CBREAK
1009da2e3ebdSchin if( c == '\0' )
1010da2e3ebdSchin {
1011da2e3ebdSchin /*** user break key ***/
1012da2e3ebdSchin ep->e_lookahead = 0;
1013da2e3ebdSchin # if KSHELL
1014da2e3ebdSchin sh_fault(SIGINT);
1015da2e3ebdSchin siglongjmp(ep->e_env, UINTR);
1016da2e3ebdSchin # endif /* KSHELL */
1017da2e3ebdSchin }
1018da2e3ebdSchin # endif /* CBREAK */
1019da2e3ebdSchin }
1020da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
1021da2e3ebdSchin return(1);
1022da2e3ebdSchin }
1023da2e3ebdSchin
1024da2e3ebdSchin /*
1025da2e3ebdSchin * routine to perform read from terminal for vi and emacs mode
1026da2e3ebdSchin * <mode> can be one of the following:
1027da2e3ebdSchin * -2 vi insert mode - key binding is in effect
1028da2e3ebdSchin * -1 vi control mode - key binding is in effect
1029da2e3ebdSchin * 0 normal command mode - key binding is in effect
1030da2e3ebdSchin * 1 edit keys not mapped
1031da2e3ebdSchin * 2 Next key is literal
1032da2e3ebdSchin */
1033da2e3ebdSchin int ed_getchar(register Edit_t *ep,int mode)
1034da2e3ebdSchin {
1035da2e3ebdSchin register int n, c;
1036da2e3ebdSchin char readin[LOOKAHEAD+1];
1037da2e3ebdSchin if(!ep->e_lookahead)
1038da2e3ebdSchin {
1039da2e3ebdSchin ed_flush(ep);
1040da2e3ebdSchin ep->e_inmacro = 0;
1041da2e3ebdSchin /* The while is necessary for reads of partial multbyte chars */
10427c2fbfb3SApril Chin *ep->e_vi_insert = (mode==-2);
1043da2e3ebdSchin if((n=ed_read(ep,ep->e_fd,readin,-LOOKAHEAD,0)) > 0)
1044da2e3ebdSchin n = putstack(ep,readin,n,1);
10457c2fbfb3SApril Chin *ep->e_vi_insert = 0;
1046da2e3ebdSchin }
1047da2e3ebdSchin if(ep->e_lookahead)
1048da2e3ebdSchin {
1049da2e3ebdSchin /* check for possible key mapping */
1050da2e3ebdSchin if((c = ep->e_lbuf[--ep->e_lookahead]) < 0)
1051da2e3ebdSchin {
1052*b30d1939SAndy Fiddaman if(mode<=0 && -c == ep->e_intr)
1053*b30d1939SAndy Fiddaman {
1054*b30d1939SAndy Fiddaman sh_fault(SIGINT);
1055*b30d1939SAndy Fiddaman siglongjmp(ep->e_env, UINTR);
1056*b30d1939SAndy Fiddaman }
10577c2fbfb3SApril Chin if(mode<=0 && ep->sh->st.trap[SH_KEYTRAP])
1058da2e3ebdSchin {
1059*b30d1939SAndy Fiddaman ep->e_keytrap = 1;
1060da2e3ebdSchin n=1;
1061da2e3ebdSchin if((readin[0]= -c) == ESC)
1062da2e3ebdSchin {
1063da2e3ebdSchin while(1)
1064da2e3ebdSchin {
1065da2e3ebdSchin if(!ep->e_lookahead)
1066da2e3ebdSchin {
1067da2e3ebdSchin if((c=sfpkrd(ep->e_fd,readin+n,1,'\r',(mode?400L:-1L),0))>0)
1068da2e3ebdSchin putstack(ep,readin+n,c,1);
1069da2e3ebdSchin }
1070da2e3ebdSchin if(!ep->e_lookahead)
1071da2e3ebdSchin break;
1072da2e3ebdSchin if((c=ep->e_lbuf[--ep->e_lookahead])>=0)
1073da2e3ebdSchin {
1074da2e3ebdSchin ep->e_lookahead++;
1075da2e3ebdSchin break;
1076da2e3ebdSchin }
1077da2e3ebdSchin c = -c;
1078da2e3ebdSchin readin[n++] = c;
1079da2e3ebdSchin if(c>='0' && c<='9' && n>2)
1080da2e3ebdSchin continue;
1081da2e3ebdSchin if(n>2 || (c!= '[' && c!= 'O'))
1082da2e3ebdSchin break;
1083da2e3ebdSchin }
1084da2e3ebdSchin }
1085da2e3ebdSchin if(n=keytrap(ep,readin,n,LOOKAHEAD-n,mode))
1086da2e3ebdSchin {
1087da2e3ebdSchin putstack(ep,readin,n,0);
1088da2e3ebdSchin c = ep->e_lbuf[--ep->e_lookahead];
1089da2e3ebdSchin }
1090da2e3ebdSchin else
1091da2e3ebdSchin c = ed_getchar(ep,mode);
1092*b30d1939SAndy Fiddaman ep->e_keytrap = 0;
1093da2e3ebdSchin }
1094da2e3ebdSchin else
1095da2e3ebdSchin c = -c;
1096da2e3ebdSchin }
1097da2e3ebdSchin /*** map '\r' to '\n' ***/
1098da2e3ebdSchin if(c == '\r' && mode!=2)
1099da2e3ebdSchin c = '\n';
1100da2e3ebdSchin if(ep->e_tabcount && !(c=='\t'||c==ESC || c=='\\' || c=='=' || c==cntl('L') || isdigit(c)))
1101da2e3ebdSchin ep->e_tabcount = 0;
1102da2e3ebdSchin }
1103da2e3ebdSchin else
1104da2e3ebdSchin siglongjmp(ep->e_env,(n==0?UEOF:UINTR));
1105da2e3ebdSchin return(c);
1106da2e3ebdSchin }
1107da2e3ebdSchin
1108da2e3ebdSchin void ed_ungetchar(Edit_t *ep,register int c)
1109da2e3ebdSchin {
1110da2e3ebdSchin if (ep->e_lookahead < LOOKAHEAD)
1111da2e3ebdSchin ep->e_lbuf[ep->e_lookahead++] = c;
1112da2e3ebdSchin return;
1113da2e3ebdSchin }
1114da2e3ebdSchin
1115da2e3ebdSchin /*
1116da2e3ebdSchin * put a character into the output buffer
1117da2e3ebdSchin */
1118da2e3ebdSchin
1119da2e3ebdSchin void ed_putchar(register Edit_t *ep,register int c)
1120da2e3ebdSchin {
1121da2e3ebdSchin char buf[8];
1122da2e3ebdSchin register char *dp = ep->e_outptr;
1123da2e3ebdSchin register int i,size=1;
11247c2fbfb3SApril Chin if(!dp)
11257c2fbfb3SApril Chin return;
1126da2e3ebdSchin buf[0] = c;
1127da2e3ebdSchin #if SHOPT_MULTIBYTE
1128da2e3ebdSchin /* check for place holder */
1129da2e3ebdSchin if(c == MARKER)
1130da2e3ebdSchin return;
1131da2e3ebdSchin if((size = mbconv(buf, (wchar_t)c)) > 1)
1132da2e3ebdSchin {
1133da2e3ebdSchin for (i = 0; i < (size-1); i++)
1134da2e3ebdSchin *dp++ = buf[i];
1135da2e3ebdSchin c = buf[i];
1136da2e3ebdSchin }
1137da2e3ebdSchin else
1138da2e3ebdSchin {
1139da2e3ebdSchin buf[0] = c;
1140da2e3ebdSchin size = 1;
1141da2e3ebdSchin }
1142da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
1143da2e3ebdSchin if (buf[0] == '_' && size==1)
1144da2e3ebdSchin {
1145da2e3ebdSchin *dp++ = ' ';
1146da2e3ebdSchin *dp++ = '\b';
1147da2e3ebdSchin }
1148da2e3ebdSchin *dp++ = c;
1149da2e3ebdSchin *dp = '\0';
1150da2e3ebdSchin if(dp >= ep->e_outlast)
1151da2e3ebdSchin ed_flush(ep);
1152da2e3ebdSchin else
1153da2e3ebdSchin ep->e_outptr = dp;
1154da2e3ebdSchin }
1155da2e3ebdSchin
1156da2e3ebdSchin /*
1157da2e3ebdSchin * returns the line and column corresponding to offset <off> in the physical buffer
1158da2e3ebdSchin * if <cur> is non-zero and <= <off>, then correspodning <curpos> will start the search
1159da2e3ebdSchin */
1160da2e3ebdSchin Edpos_t ed_curpos(Edit_t *ep,genchar *phys, int off, int cur, Edpos_t curpos)
1161da2e3ebdSchin {
1162da2e3ebdSchin register genchar *sp=phys;
1163da2e3ebdSchin register int c=1, col=ep->e_plen;
1164da2e3ebdSchin Edpos_t pos;
1165da2e3ebdSchin #if SHOPT_MULTIBYTE
1166da2e3ebdSchin char p[16];
1167da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
1168da2e3ebdSchin if(cur && off>=cur)
1169da2e3ebdSchin {
1170da2e3ebdSchin sp += cur;
1171da2e3ebdSchin off -= cur;
1172da2e3ebdSchin pos = curpos;
1173da2e3ebdSchin col = pos.col;
1174da2e3ebdSchin }
1175da2e3ebdSchin else
11767c2fbfb3SApril Chin {
1177da2e3ebdSchin pos.line = 0;
11787c2fbfb3SApril Chin while(col > ep->e_winsz)
11797c2fbfb3SApril Chin {
11807c2fbfb3SApril Chin pos.line++;
11817c2fbfb3SApril Chin col -= (ep->e_winsz+1);
11827c2fbfb3SApril Chin }
11837c2fbfb3SApril Chin }
1184da2e3ebdSchin while(off-->0)
1185da2e3ebdSchin {
1186da2e3ebdSchin if(c)
1187da2e3ebdSchin c = *sp++;
1188da2e3ebdSchin #if SHOPT_MULTIBYTE
1189da2e3ebdSchin if(c && (mbconv(p, (wchar_t)c))==1 && p[0]=='\n')
1190da2e3ebdSchin #else
1191da2e3ebdSchin if(c=='\n')
1192da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
1193da2e3ebdSchin col = 0;
1194da2e3ebdSchin else
1195da2e3ebdSchin col++;
1196da2e3ebdSchin if(col > ep->e_winsz)
1197da2e3ebdSchin col = 0;
1198da2e3ebdSchin if(col==0)
1199da2e3ebdSchin pos.line++;
1200da2e3ebdSchin }
1201da2e3ebdSchin pos.col = col;
1202da2e3ebdSchin return(pos);
1203da2e3ebdSchin }
1204da2e3ebdSchin
1205da2e3ebdSchin int ed_setcursor(register Edit_t *ep,genchar *physical,register int old,register int new,int first)
1206da2e3ebdSchin {
1207da2e3ebdSchin static int oldline;
1208da2e3ebdSchin register int delta;
12097c2fbfb3SApril Chin int clear = 0;
1210da2e3ebdSchin Edpos_t newpos;
1211da2e3ebdSchin
1212da2e3ebdSchin delta = new - old;
12137c2fbfb3SApril Chin if(first < 0)
12147c2fbfb3SApril Chin {
12157c2fbfb3SApril Chin first = 0;
12167c2fbfb3SApril Chin clear = 1;
12177c2fbfb3SApril Chin }
12187c2fbfb3SApril Chin if( delta == 0 && !clear)
1219da2e3ebdSchin return(new);
1220da2e3ebdSchin if(ep->e_multiline)
1221da2e3ebdSchin {
1222da2e3ebdSchin ep->e_curpos = ed_curpos(ep, physical, old,0,ep->e_curpos);
12237c2fbfb3SApril Chin if(clear && old>=ep->e_peol && (clear=ep->e_winsz-ep->e_curpos.col)>0)
12247c2fbfb3SApril Chin {
12257c2fbfb3SApril Chin ed_nputchar(ep,clear,' ');
12267c2fbfb3SApril Chin ed_nputchar(ep,clear,'\b');
12277c2fbfb3SApril Chin return(new);
12287c2fbfb3SApril Chin }
1229da2e3ebdSchin newpos = ed_curpos(ep, physical, new,old,ep->e_curpos);
1230da2e3ebdSchin if(ep->e_curpos.col==0 && ep->e_curpos.line>0 && oldline<ep->e_curpos.line && delta<0)
1231da2e3ebdSchin ed_putstring(ep,"\r\n");
1232da2e3ebdSchin oldline = newpos.line;
1233da2e3ebdSchin if(ep->e_curpos.line > newpos.line)
1234da2e3ebdSchin {
12357c2fbfb3SApril Chin int n,pline,plen=ep->e_plen;
1236da2e3ebdSchin for(;ep->e_curpos.line > newpos.line; ep->e_curpos.line--)
1237da2e3ebdSchin ed_putstring(ep,CURSOR_UP);
12387c2fbfb3SApril Chin pline = plen/(ep->e_winsz+1);
12397c2fbfb3SApril Chin if(newpos.line <= pline)
12407c2fbfb3SApril Chin plen -= pline*(ep->e_winsz+1);
12417c2fbfb3SApril Chin else
12427c2fbfb3SApril Chin plen = 0;
12437c2fbfb3SApril Chin if((n=plen- ep->e_curpos.col)>0)
1244da2e3ebdSchin {
1245da2e3ebdSchin ep->e_curpos.col += n;
1246da2e3ebdSchin ed_putchar(ep,'\r');
12477c2fbfb3SApril Chin if(!ep->e_crlf && pline==0)
1248da2e3ebdSchin ed_putstring(ep,ep->e_prompt);
1249da2e3ebdSchin else
1250da2e3ebdSchin {
12517c2fbfb3SApril Chin int m = ep->e_winsz+1-plen;
1252da2e3ebdSchin ed_putchar(ep,'\n');
12537c2fbfb3SApril Chin n = plen;
1254da2e3ebdSchin if(m < ed_genlen(physical))
1255da2e3ebdSchin {
1256da2e3ebdSchin while(physical[m] && n-->0)
1257da2e3ebdSchin ed_putchar(ep,physical[m++]);
1258da2e3ebdSchin }
12597c2fbfb3SApril Chin ed_nputchar(ep,n,' ');
1260da2e3ebdSchin ed_putstring(ep,CURSOR_UP);
1261da2e3ebdSchin }
1262da2e3ebdSchin }
1263da2e3ebdSchin }
1264da2e3ebdSchin else if(ep->e_curpos.line < newpos.line)
1265da2e3ebdSchin {
12667c2fbfb3SApril Chin ed_nputchar(ep, newpos.line-ep->e_curpos.line,'\n');
12677c2fbfb3SApril Chin ep->e_curpos.line = newpos.line;
1268da2e3ebdSchin ed_putchar(ep,'\r');
1269da2e3ebdSchin ep->e_curpos.col = 0;
1270da2e3ebdSchin }
1271da2e3ebdSchin delta = newpos.col - ep->e_curpos.col;
1272da2e3ebdSchin old = new - delta;
1273da2e3ebdSchin }
1274da2e3ebdSchin else
1275da2e3ebdSchin newpos.line=0;
1276da2e3ebdSchin if(delta<0)
1277da2e3ebdSchin {
12787c2fbfb3SApril Chin int bs= newpos.line && ep->e_plen>ep->e_winsz;
1279da2e3ebdSchin /*** move to left ***/
1280da2e3ebdSchin delta = -delta;
1281da2e3ebdSchin /*** attempt to optimize cursor movement ***/
12827c2fbfb3SApril Chin if(!ep->e_crlf || bs || (2*delta <= ((old-first)+(newpos.line?0:ep->e_plen))) )
1283da2e3ebdSchin {
12847c2fbfb3SApril Chin ed_nputchar(ep,delta,'\b');
12857c2fbfb3SApril Chin delta = 0;
1286da2e3ebdSchin }
1287da2e3ebdSchin else
1288da2e3ebdSchin {
1289da2e3ebdSchin if(newpos.line==0)
1290da2e3ebdSchin ed_putstring(ep,ep->e_prompt);
12917c2fbfb3SApril Chin else
12927c2fbfb3SApril Chin {
12937c2fbfb3SApril Chin first = 1+(newpos.line*ep->e_winsz - ep->e_plen);
12947c2fbfb3SApril Chin ed_putchar(ep,'\r');
12957c2fbfb3SApril Chin }
1296da2e3ebdSchin old = first;
1297da2e3ebdSchin delta = new-first;
1298da2e3ebdSchin }
1299da2e3ebdSchin }
1300da2e3ebdSchin while(delta-->0)
1301da2e3ebdSchin ed_putchar(ep,physical[old++]);
1302da2e3ebdSchin return(new);
1303da2e3ebdSchin }
1304da2e3ebdSchin
1305da2e3ebdSchin /*
1306da2e3ebdSchin * copy virtual to physical and return the index for cursor in physical buffer
1307da2e3ebdSchin */
1308da2e3ebdSchin int ed_virt_to_phys(Edit_t *ep,genchar *virt,genchar *phys,int cur,int voff,int poff)
1309da2e3ebdSchin {
1310da2e3ebdSchin register genchar *sp = virt;
1311da2e3ebdSchin register genchar *dp = phys;
1312da2e3ebdSchin register int c;
1313da2e3ebdSchin genchar *curp = sp + cur;
1314da2e3ebdSchin genchar *dpmax = phys+MAXLINE;
1315da2e3ebdSchin int d, r;
1316da2e3ebdSchin sp += voff;
1317da2e3ebdSchin dp += poff;
1318da2e3ebdSchin for(r=poff;c= *sp;sp++)
1319da2e3ebdSchin {
1320da2e3ebdSchin if(curp == sp)
1321da2e3ebdSchin r = dp - phys;
1322da2e3ebdSchin #if SHOPT_MULTIBYTE
1323da2e3ebdSchin d = mbwidth((wchar_t)c);
1324da2e3ebdSchin if(d==1 && is_cntrl(c))
1325da2e3ebdSchin d = -1;
1326da2e3ebdSchin if(d>1)
1327da2e3ebdSchin {
1328da2e3ebdSchin /* multiple width character put in place holders */
1329da2e3ebdSchin *dp++ = c;
1330da2e3ebdSchin while(--d >0)
1331da2e3ebdSchin *dp++ = MARKER;
1332da2e3ebdSchin /* in vi mode the cursor is at the last character */
1333da2e3ebdSchin if(dp>=dpmax)
1334da2e3ebdSchin break;
1335da2e3ebdSchin continue;
1336da2e3ebdSchin }
1337da2e3ebdSchin else
1338da2e3ebdSchin #else
1339da2e3ebdSchin d = (is_cntrl(c)?-1:1);
1340da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
1341da2e3ebdSchin if(d<0)
1342da2e3ebdSchin {
1343da2e3ebdSchin if(c=='\t')
1344da2e3ebdSchin {
1345da2e3ebdSchin c = dp-phys;
1346da2e3ebdSchin if(sh_isoption(SH_VI))
1347da2e3ebdSchin c += ep->e_plen;
1348da2e3ebdSchin c = TABSIZE - c%TABSIZE;
1349da2e3ebdSchin while(--c>0)
1350da2e3ebdSchin *dp++ = ' ';
1351da2e3ebdSchin c = ' ';
1352da2e3ebdSchin }
1353da2e3ebdSchin else
1354da2e3ebdSchin {
1355da2e3ebdSchin *dp++ = '^';
1356da2e3ebdSchin c = printchar(c);
1357da2e3ebdSchin }
1358da2e3ebdSchin /* in vi mode the cursor is at the last character */
1359da2e3ebdSchin if(curp == sp && sh_isoption(SH_VI))
1360da2e3ebdSchin r = dp - phys;
1361da2e3ebdSchin }
1362da2e3ebdSchin *dp++ = c;
1363da2e3ebdSchin if(dp>=dpmax)
1364da2e3ebdSchin break;
1365da2e3ebdSchin }
1366da2e3ebdSchin *dp = 0;
13677c2fbfb3SApril Chin ep->e_peol = dp-phys;
1368da2e3ebdSchin return(r);
1369da2e3ebdSchin }
1370da2e3ebdSchin
1371da2e3ebdSchin #if SHOPT_MULTIBYTE
1372da2e3ebdSchin /*
1373da2e3ebdSchin * convert external representation <src> to an array of genchars <dest>
1374da2e3ebdSchin * <src> and <dest> can be the same
1375da2e3ebdSchin * returns number of chars in dest
1376da2e3ebdSchin */
1377da2e3ebdSchin
1378da2e3ebdSchin int ed_internal(const char *src, genchar *dest)
1379da2e3ebdSchin {
1380da2e3ebdSchin register const unsigned char *cp = (unsigned char *)src;
1381da2e3ebdSchin register int c;
1382da2e3ebdSchin register wchar_t *dp = (wchar_t*)dest;
1383da2e3ebdSchin if(dest == (genchar*)roundof(cp-(unsigned char*)0,sizeof(genchar)))
1384da2e3ebdSchin {
1385da2e3ebdSchin genchar buffer[MAXLINE];
1386da2e3ebdSchin c = ed_internal(src,buffer);
1387da2e3ebdSchin ed_gencpy((genchar*)dp,buffer);
1388da2e3ebdSchin return(c);
1389da2e3ebdSchin }
1390da2e3ebdSchin while(*cp)
1391da2e3ebdSchin *dp++ = mbchar(cp);
1392da2e3ebdSchin *dp = 0;
1393da2e3ebdSchin return(dp-(wchar_t*)dest);
1394da2e3ebdSchin }
1395da2e3ebdSchin
1396da2e3ebdSchin /*
1397da2e3ebdSchin * convert internal representation <src> into character array <dest>.
1398da2e3ebdSchin * The <src> and <dest> may be the same.
1399da2e3ebdSchin * returns number of chars in dest.
1400da2e3ebdSchin */
1401da2e3ebdSchin
1402da2e3ebdSchin int ed_external(const genchar *src, char *dest)
1403da2e3ebdSchin {
1404da2e3ebdSchin register genchar wc;
1405da2e3ebdSchin register int c,size;
1406da2e3ebdSchin register char *dp = dest;
1407da2e3ebdSchin char *dpmax = dp+sizeof(genchar)*MAXLINE-2;
1408da2e3ebdSchin if((char*)src == dp)
1409da2e3ebdSchin {
1410da2e3ebdSchin char buffer[MAXLINE*sizeof(genchar)];
1411da2e3ebdSchin c = ed_external(src,buffer);
1412da2e3ebdSchin
1413da2e3ebdSchin #ifdef _lib_wcscpy
1414da2e3ebdSchin wcscpy((wchar_t *)dest,(const wchar_t *)buffer);
1415da2e3ebdSchin #else
1416da2e3ebdSchin strcpy(dest,buffer);
1417da2e3ebdSchin #endif
1418da2e3ebdSchin return(c);
1419da2e3ebdSchin }
1420da2e3ebdSchin while((wc = *src++) && dp<dpmax)
1421da2e3ebdSchin {
1422da2e3ebdSchin if((size = mbconv(dp, wc)) < 0)
1423da2e3ebdSchin {
1424da2e3ebdSchin /* copy the character as is */
1425da2e3ebdSchin size = 1;
1426da2e3ebdSchin *dp = wc;
1427da2e3ebdSchin }
1428da2e3ebdSchin dp += size;
1429da2e3ebdSchin }
1430da2e3ebdSchin *dp = 0;
1431da2e3ebdSchin return(dp-dest);
1432da2e3ebdSchin }
1433da2e3ebdSchin
1434da2e3ebdSchin /*
1435da2e3ebdSchin * copy <sp> to <dp>
1436da2e3ebdSchin */
1437da2e3ebdSchin
1438da2e3ebdSchin void ed_gencpy(genchar *dp,const genchar *sp)
1439da2e3ebdSchin {
1440da2e3ebdSchin dp = (genchar*)roundof((char*)dp-(char*)0,sizeof(genchar));
1441da2e3ebdSchin sp = (const genchar*)roundof((char*)sp-(char*)0,sizeof(genchar));
1442da2e3ebdSchin while(*dp++ = *sp++);
1443da2e3ebdSchin }
1444da2e3ebdSchin
1445da2e3ebdSchin /*
1446da2e3ebdSchin * copy at most <n> items from <sp> to <dp>
1447da2e3ebdSchin */
1448da2e3ebdSchin
1449da2e3ebdSchin void ed_genncpy(register genchar *dp,register const genchar *sp, int n)
1450da2e3ebdSchin {
1451da2e3ebdSchin dp = (genchar*)roundof((char*)dp-(char*)0,sizeof(genchar));
1452da2e3ebdSchin sp = (const genchar*)roundof((char*)sp-(char*)0,sizeof(genchar));
1453da2e3ebdSchin while(n-->0 && (*dp++ = *sp++));
1454da2e3ebdSchin }
1455da2e3ebdSchin
1456*b30d1939SAndy Fiddaman #endif /* SHOPT_MULTIBYTE */
1457da2e3ebdSchin /*
1458da2e3ebdSchin * find the string length of <str>
1459da2e3ebdSchin */
1460da2e3ebdSchin
1461da2e3ebdSchin int ed_genlen(register const genchar *str)
1462da2e3ebdSchin {
1463da2e3ebdSchin register const genchar *sp = str;
1464da2e3ebdSchin sp = (const genchar*)roundof((char*)sp-(char*)0,sizeof(genchar));
1465da2e3ebdSchin while(*sp++);
1466da2e3ebdSchin return(sp-str-1);
1467da2e3ebdSchin }
1468da2e3ebdSchin #endif /* SHOPT_ESH || SHOPT_VSH */
1469da2e3ebdSchin
1470da2e3ebdSchin #ifdef future
1471da2e3ebdSchin /*
1472da2e3ebdSchin * returns 1 when <n> bytes starting at <a> and <b> are equal
1473da2e3ebdSchin */
1474da2e3ebdSchin static int compare(register const char *a,register const char *b,register int n)
1475da2e3ebdSchin {
1476da2e3ebdSchin while(n-->0)
1477da2e3ebdSchin {
1478da2e3ebdSchin if(*a++ != *b++)
1479da2e3ebdSchin return(0);
1480da2e3ebdSchin }
1481da2e3ebdSchin return(1);
1482da2e3ebdSchin }
1483da2e3ebdSchin #endif
1484da2e3ebdSchin
1485da2e3ebdSchin #if SHOPT_OLDTERMIO
1486da2e3ebdSchin
1487da2e3ebdSchin # include <sys/termio.h>
1488da2e3ebdSchin
1489da2e3ebdSchin #ifndef ECHOCTL
1490da2e3ebdSchin # define ECHOCTL 0
1491da2e3ebdSchin #endif /* !ECHOCTL */
1492da2e3ebdSchin #define ott ep->e_ott
1493da2e3ebdSchin
1494da2e3ebdSchin /*
1495da2e3ebdSchin * For backward compatibility only
1496da2e3ebdSchin * This version will use termios when possible, otherwise termio
1497da2e3ebdSchin */
1498da2e3ebdSchin
14997c2fbfb3SApril Chin int tcgetattr(int fd, struct termios *tt)
1500da2e3ebdSchin {
1501*b30d1939SAndy Fiddaman register Edit_t *ep = (Edit_t*)(shgd->ed_context);
1502da2e3ebdSchin register int r,i;
1503da2e3ebdSchin ep->e_tcgeta = 0;
1504da2e3ebdSchin ep->e_echoctl = (ECHOCTL!=0);
1505da2e3ebdSchin if((r=ioctl(fd,TCGETS,tt))>=0 || errno!=EINVAL)
1506da2e3ebdSchin return(r);
1507da2e3ebdSchin if((r=ioctl(fd,TCGETA,&ott)) >= 0)
1508da2e3ebdSchin {
1509da2e3ebdSchin tt->c_lflag = ott.c_lflag;
1510da2e3ebdSchin tt->c_oflag = ott.c_oflag;
1511da2e3ebdSchin tt->c_iflag = ott.c_iflag;
1512da2e3ebdSchin tt->c_cflag = ott.c_cflag;
1513da2e3ebdSchin for(i=0; i<NCC; i++)
1514da2e3ebdSchin tt->c_cc[i] = ott.c_cc[i];
1515da2e3ebdSchin ep->e_tcgeta++;
1516da2e3ebdSchin ep->e_echoctl = 0;
1517da2e3ebdSchin }
1518da2e3ebdSchin return(r);
1519da2e3ebdSchin }
1520da2e3ebdSchin
15217c2fbfb3SApril Chin int tcsetattr(int fd,int mode,struct termios *tt)
1522da2e3ebdSchin {
1523*b30d1939SAndy Fiddaman register Edit_t *ep = (Edit_t*)(shgd->ed_context);
1524da2e3ebdSchin register int r;
1525da2e3ebdSchin if(ep->e_tcgeta)
1526da2e3ebdSchin {
1527da2e3ebdSchin register int i;
1528da2e3ebdSchin ott.c_lflag = tt->c_lflag;
1529da2e3ebdSchin ott.c_oflag = tt->c_oflag;
1530da2e3ebdSchin ott.c_iflag = tt->c_iflag;
1531da2e3ebdSchin ott.c_cflag = tt->c_cflag;
1532da2e3ebdSchin for(i=0; i<NCC; i++)
1533da2e3ebdSchin ott.c_cc[i] = tt->c_cc[i];
1534da2e3ebdSchin if(tt->c_lflag&ECHOCTL)
1535da2e3ebdSchin {
1536da2e3ebdSchin ott.c_lflag &= ~(ECHOCTL|IEXTEN);
1537da2e3ebdSchin ott.c_iflag &= ~(IGNCR|ICRNL);
1538da2e3ebdSchin ott.c_iflag |= INLCR;
1539da2e3ebdSchin ott.c_cc[VEOF]= ESC; /* ESC -> eof char */
1540da2e3ebdSchin ott.c_cc[VEOL] = '\r'; /* CR -> eol char */
1541da2e3ebdSchin ott.c_cc[VEOL2] = tt->c_cc[VEOF]; /* EOF -> eol char */
1542da2e3ebdSchin }
1543da2e3ebdSchin switch(mode)
1544da2e3ebdSchin {
1545da2e3ebdSchin case TCSANOW:
1546da2e3ebdSchin mode = TCSETA;
1547da2e3ebdSchin break;
1548da2e3ebdSchin case TCSADRAIN:
1549da2e3ebdSchin mode = TCSETAW;
1550da2e3ebdSchin break;
1551da2e3ebdSchin case TCSAFLUSH:
1552da2e3ebdSchin mode = TCSETAF;
1553da2e3ebdSchin }
1554da2e3ebdSchin return(ioctl(fd,mode,&ott));
1555da2e3ebdSchin }
1556da2e3ebdSchin return(ioctl(fd,mode,tt));
1557da2e3ebdSchin }
1558da2e3ebdSchin #endif /* SHOPT_OLDTERMIO */
1559da2e3ebdSchin
1560da2e3ebdSchin #if KSHELL
1561da2e3ebdSchin /*
1562da2e3ebdSchin * Execute keyboard trap on given buffer <inbuff> of given size <isize>
1563da2e3ebdSchin * <mode> < 0 for vi insert mode
1564da2e3ebdSchin */
1565da2e3ebdSchin static int keytrap(Edit_t *ep,char *inbuff,register int insize, int bufsize, int mode)
1566da2e3ebdSchin {
1567da2e3ebdSchin register char *cp;
1568da2e3ebdSchin int savexit;
15697c2fbfb3SApril Chin Shell_t *shp = ep->sh;
1570da2e3ebdSchin #if SHOPT_MULTIBYTE
1571da2e3ebdSchin char buff[MAXLINE];
1572da2e3ebdSchin ed_external(ep->e_inbuf,cp=buff);
1573da2e3ebdSchin #else
1574da2e3ebdSchin cp = ep->e_inbuf;
1575da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
1576da2e3ebdSchin inbuff[insize] = 0;
1577da2e3ebdSchin ep->e_col = ep->e_cur;
1578da2e3ebdSchin if(mode== -2)
1579da2e3ebdSchin {
1580da2e3ebdSchin ep->e_col++;
1581da2e3ebdSchin *ep->e_vi_insert = ESC;
1582da2e3ebdSchin }
1583da2e3ebdSchin else
1584da2e3ebdSchin *ep->e_vi_insert = 0;
1585da2e3ebdSchin nv_putval(ED_CHRNOD,inbuff,NV_NOFREE);
1586da2e3ebdSchin nv_putval(ED_COLNOD,(char*)&ep->e_col,NV_NOFREE|NV_INTEGER);
1587da2e3ebdSchin nv_putval(ED_TXTNOD,(char*)cp,NV_NOFREE);
1588da2e3ebdSchin nv_putval(ED_MODENOD,ep->e_vi_insert,NV_NOFREE);
15897c2fbfb3SApril Chin savexit = shp->savexit;
15907c2fbfb3SApril Chin sh_trap(shp->st.trap[SH_KEYTRAP],0);
15917c2fbfb3SApril Chin shp->savexit = savexit;
1592da2e3ebdSchin if((cp = nv_getval(ED_CHRNOD)) == inbuff)
1593da2e3ebdSchin nv_unset(ED_CHRNOD);
15947c2fbfb3SApril Chin else if(bufsize>0)
1595da2e3ebdSchin {
1596da2e3ebdSchin strncpy(inbuff,cp,bufsize);
15977c2fbfb3SApril Chin inbuff[bufsize-1]='\0';
1598da2e3ebdSchin insize = strlen(inbuff);
1599da2e3ebdSchin }
16007c2fbfb3SApril Chin else
16017c2fbfb3SApril Chin insize = 0;
1602da2e3ebdSchin nv_unset(ED_TXTNOD);
1603da2e3ebdSchin return(insize);
1604da2e3ebdSchin }
1605da2e3ebdSchin #endif /* KSHELL */
1606da2e3ebdSchin
1607*b30d1939SAndy Fiddaman #if SHOPT_EDPREDICT
1608*b30d1939SAndy Fiddaman static int ed_sortdata(const char *s1, const char *s2)
1609*b30d1939SAndy Fiddaman {
1610*b30d1939SAndy Fiddaman Histmatch_t *m1 = (Histmatch_t*)s1;
1611*b30d1939SAndy Fiddaman Histmatch_t *m2 = (Histmatch_t*)s2;
1612*b30d1939SAndy Fiddaman return(strcmp(m1->data,m2->data));
1613*b30d1939SAndy Fiddaman }
1614*b30d1939SAndy Fiddaman
1615*b30d1939SAndy Fiddaman static int ed_sortindex(const char *s1, const char *s2)
1616*b30d1939SAndy Fiddaman {
1617*b30d1939SAndy Fiddaman Histmatch_t *m1 = (Histmatch_t*)s1;
1618*b30d1939SAndy Fiddaman Histmatch_t *m2 = (Histmatch_t*)s2;
1619*b30d1939SAndy Fiddaman return(m2->index-m1->index);
1620*b30d1939SAndy Fiddaman }
1621*b30d1939SAndy Fiddaman
1622*b30d1939SAndy Fiddaman static int ed_histlencopy(const char *cp, char *dp)
1623*b30d1939SAndy Fiddaman {
1624*b30d1939SAndy Fiddaman int c,n=1,col=1;
1625*b30d1939SAndy Fiddaman const char *oldcp=cp;
1626*b30d1939SAndy Fiddaman for(n=0;c = mbchar(cp);oldcp=cp,col++)
1627*b30d1939SAndy Fiddaman {
1628*b30d1939SAndy Fiddaman if(c=='\n' && *cp)
1629*b30d1939SAndy Fiddaman {
1630*b30d1939SAndy Fiddaman n += 2;
1631*b30d1939SAndy Fiddaman if(dp)
1632*b30d1939SAndy Fiddaman {
1633*b30d1939SAndy Fiddaman *dp++ = '^';
1634*b30d1939SAndy Fiddaman *dp++ = 'J';
1635*b30d1939SAndy Fiddaman col +=2;
1636*b30d1939SAndy Fiddaman }
1637*b30d1939SAndy Fiddaman }
1638*b30d1939SAndy Fiddaman else if(c=='\t')
1639*b30d1939SAndy Fiddaman {
1640*b30d1939SAndy Fiddaman n++;
1641*b30d1939SAndy Fiddaman if(dp)
1642*b30d1939SAndy Fiddaman *dp++ = ' ';
1643*b30d1939SAndy Fiddaman }
1644*b30d1939SAndy Fiddaman else
1645*b30d1939SAndy Fiddaman {
1646*b30d1939SAndy Fiddaman n += cp-oldcp;
1647*b30d1939SAndy Fiddaman if(dp)
1648*b30d1939SAndy Fiddaman {
1649*b30d1939SAndy Fiddaman while(oldcp < cp)
1650*b30d1939SAndy Fiddaman *dp++ = *oldcp++;
1651*b30d1939SAndy Fiddaman }
1652*b30d1939SAndy Fiddaman }
1653*b30d1939SAndy Fiddaman
1654*b30d1939SAndy Fiddaman }
1655*b30d1939SAndy Fiddaman return(n);
1656*b30d1939SAndy Fiddaman }
1657*b30d1939SAndy Fiddaman
1658*b30d1939SAndy Fiddaman int ed_histgen(Edit_t *ep,const char *pattern)
1659*b30d1939SAndy Fiddaman {
1660*b30d1939SAndy Fiddaman Histmatch_t *mp,*mplast=0;
1661*b30d1939SAndy Fiddaman History_t *hp;
1662*b30d1939SAndy Fiddaman off_t offset;
1663*b30d1939SAndy Fiddaman int ac=0,l,n,index1,index2;
1664*b30d1939SAndy Fiddaman size_t m;
1665*b30d1939SAndy Fiddaman char *cp, **argv=0, **av, **ar;
1666*b30d1939SAndy Fiddaman static int maxmatch;
1667*b30d1939SAndy Fiddaman if(!(hp=ep->sh->gd->hist_ptr) && (!nv_getval(HISTFILE) || !sh_histinit(ep->sh)))
1668*b30d1939SAndy Fiddaman return(0);
1669*b30d1939SAndy Fiddaman if(ep->e_cur <=2)
1670*b30d1939SAndy Fiddaman maxmatch = 0;
1671*b30d1939SAndy Fiddaman else if(maxmatch && ep->e_cur > maxmatch)
1672*b30d1939SAndy Fiddaman {
1673*b30d1939SAndy Fiddaman ep->hlist = 0;
1674*b30d1939SAndy Fiddaman ep->hfirst = 0;
1675*b30d1939SAndy Fiddaman return(0);
1676*b30d1939SAndy Fiddaman }
1677*b30d1939SAndy Fiddaman hp = ep->sh->gd->hist_ptr;
1678*b30d1939SAndy Fiddaman if(*pattern=='#' && *++pattern=='#')
1679*b30d1939SAndy Fiddaman return(0);
1680*b30d1939SAndy Fiddaman cp = stakalloc(m=strlen(pattern)+6);
1681*b30d1939SAndy Fiddaman sfsprintf(cp,m,"@(%s)*%c",pattern,0);
1682*b30d1939SAndy Fiddaman if(ep->hlist)
1683*b30d1939SAndy Fiddaman {
1684*b30d1939SAndy Fiddaman m = strlen(ep->hpat)-4;
1685*b30d1939SAndy Fiddaman if(memcmp(pattern,ep->hpat+2,m)==0)
1686*b30d1939SAndy Fiddaman {
1687*b30d1939SAndy Fiddaman n = strcmp(cp,ep->hpat)==0;
1688*b30d1939SAndy Fiddaman for(argv=av=(char**)ep->hlist,mp=ep->hfirst; mp;mp= mp->next)
1689*b30d1939SAndy Fiddaman {
1690*b30d1939SAndy Fiddaman if(n || strmatch(mp->data,cp))
1691*b30d1939SAndy Fiddaman *av++ = (char*)mp;
1692*b30d1939SAndy Fiddaman }
1693*b30d1939SAndy Fiddaman *av = 0;
1694*b30d1939SAndy Fiddaman ep->hmax = av-argv;
1695*b30d1939SAndy Fiddaman if(ep->hmax==0)
1696*b30d1939SAndy Fiddaman maxmatch = ep->e_cur;
1697*b30d1939SAndy Fiddaman return(ep->hmax=av-argv);
1698*b30d1939SAndy Fiddaman }
1699*b30d1939SAndy Fiddaman stakset(ep->e_stkptr,ep->e_stkoff);
1700*b30d1939SAndy Fiddaman }
1701*b30d1939SAndy Fiddaman if((m=strlen(cp)) >= sizeof(ep->hpat))
1702*b30d1939SAndy Fiddaman m = sizeof(ep->hpat)-1;
1703*b30d1939SAndy Fiddaman memcpy(ep->hpat,cp,m);
1704*b30d1939SAndy Fiddaman ep->hpat[m] = 0;
1705*b30d1939SAndy Fiddaman pattern = cp;
1706*b30d1939SAndy Fiddaman index1 = (int)hp->histind;
1707*b30d1939SAndy Fiddaman for(index2=index1-hp->histsize; index1>index2; index1--)
1708*b30d1939SAndy Fiddaman {
1709*b30d1939SAndy Fiddaman offset = hist_tell(hp,index1);
1710*b30d1939SAndy Fiddaman sfseek(hp->histfp,offset,SEEK_SET);
1711*b30d1939SAndy Fiddaman if(!(cp = sfgetr(hp->histfp,0,0)))
1712*b30d1939SAndy Fiddaman continue;
1713*b30d1939SAndy Fiddaman if(*cp=='#')
1714*b30d1939SAndy Fiddaman continue;
1715*b30d1939SAndy Fiddaman if(strmatch(cp,pattern))
1716*b30d1939SAndy Fiddaman {
1717*b30d1939SAndy Fiddaman l = ed_histlencopy(cp,(char*)0);
1718*b30d1939SAndy Fiddaman mp = (Histmatch_t*)stakalloc(sizeof(Histmatch_t)+l);
1719*b30d1939SAndy Fiddaman mp->next = mplast;
1720*b30d1939SAndy Fiddaman mplast = mp;
1721*b30d1939SAndy Fiddaman mp->len = l;
1722*b30d1939SAndy Fiddaman ed_histlencopy(cp,mp->data);
1723*b30d1939SAndy Fiddaman mp->count = 1;
1724*b30d1939SAndy Fiddaman mp->data[l] = 0;
1725*b30d1939SAndy Fiddaman mp->index = index1;
1726*b30d1939SAndy Fiddaman ac++;
1727*b30d1939SAndy Fiddaman }
1728*b30d1939SAndy Fiddaman }
1729*b30d1939SAndy Fiddaman if(ac>0)
1730*b30d1939SAndy Fiddaman {
1731*b30d1939SAndy Fiddaman l = ac;
1732*b30d1939SAndy Fiddaman argv = av = (char**)stakalloc((ac+1)*sizeof(char*));
1733*b30d1939SAndy Fiddaman for(mplast=0; l>=0 && (*av= (char*)mp); mplast=mp,mp=mp->next,av++)
1734*b30d1939SAndy Fiddaman {
1735*b30d1939SAndy Fiddaman l--;
1736*b30d1939SAndy Fiddaman }
1737*b30d1939SAndy Fiddaman *av = 0;
1738*b30d1939SAndy Fiddaman strsort(argv,ac,ed_sortdata);
1739*b30d1939SAndy Fiddaman mplast = (Histmatch_t*)argv[0];
1740*b30d1939SAndy Fiddaman for(ar= av= &argv[1]; mp=(Histmatch_t*)*av; av++)
1741*b30d1939SAndy Fiddaman {
1742*b30d1939SAndy Fiddaman if(strcmp(mp->data,mplast->data)==0)
1743*b30d1939SAndy Fiddaman {
1744*b30d1939SAndy Fiddaman mplast->count++;
1745*b30d1939SAndy Fiddaman if(mp->index> mplast->index)
1746*b30d1939SAndy Fiddaman mplast->index = mp->index;
1747*b30d1939SAndy Fiddaman continue;
1748*b30d1939SAndy Fiddaman }
1749*b30d1939SAndy Fiddaman *ar++ = (char*)(mplast=mp);
1750*b30d1939SAndy Fiddaman }
1751*b30d1939SAndy Fiddaman *ar = 0;
1752*b30d1939SAndy Fiddaman mplast->next = 0;
1753*b30d1939SAndy Fiddaman ac = ar-argv;
1754*b30d1939SAndy Fiddaman strsort(argv,ac,ed_sortindex);
1755*b30d1939SAndy Fiddaman mplast = (Histmatch_t*)argv[0];
1756*b30d1939SAndy Fiddaman for(av= &argv[1]; mp=(Histmatch_t*)*av; av++, mplast=mp)
1757*b30d1939SAndy Fiddaman mplast->next = mp;
1758*b30d1939SAndy Fiddaman mplast->next = 0;
1759*b30d1939SAndy Fiddaman }
1760*b30d1939SAndy Fiddaman ep->hlist = (Histmatch_t**)argv;
1761*b30d1939SAndy Fiddaman ep->hfirst = ep->hlist?ep->hlist[0]:0;
1762*b30d1939SAndy Fiddaman return(ep->hmax=ac);
1763*b30d1939SAndy Fiddaman }
1764*b30d1939SAndy Fiddaman
1765*b30d1939SAndy Fiddaman void ed_histlist(Edit_t *ep,int n)
1766*b30d1939SAndy Fiddaman {
1767*b30d1939SAndy Fiddaman Histmatch_t *mp,**mpp = ep->hlist+ep->hoff;
1768*b30d1939SAndy Fiddaman int i,last=0,save[2];
1769*b30d1939SAndy Fiddaman if(n)
1770*b30d1939SAndy Fiddaman {
1771*b30d1939SAndy Fiddaman /* don't bother updating the screen if there is typeahead */
1772*b30d1939SAndy Fiddaman if(!ep->e_lookahead && sfpkrd(ep->e_fd,save,1,'\r',200L,-1)>0)
1773*b30d1939SAndy Fiddaman ed_ungetchar(ep,save[0]);
1774*b30d1939SAndy Fiddaman if(ep->e_lookahead)
1775*b30d1939SAndy Fiddaman return;
1776*b30d1939SAndy Fiddaman ed_putchar(ep,'\n');
1777*b30d1939SAndy Fiddaman ed_putchar(ep,'\r');
1778*b30d1939SAndy Fiddaman }
1779*b30d1939SAndy Fiddaman else
1780*b30d1939SAndy Fiddaman {
1781*b30d1939SAndy Fiddaman stakset(ep->e_stkptr,ep->e_stkoff);
1782*b30d1939SAndy Fiddaman ep->hlist = 0;
1783*b30d1939SAndy Fiddaman ep->nhlist = 0;
1784*b30d1939SAndy Fiddaman }
1785*b30d1939SAndy Fiddaman ed_putstring(ep,KILL_LINE);
1786*b30d1939SAndy Fiddaman if(n)
1787*b30d1939SAndy Fiddaman {
1788*b30d1939SAndy Fiddaman for(i=1; (mp= *mpp) && i <= 16 ; i++,mpp++)
1789*b30d1939SAndy Fiddaman {
1790*b30d1939SAndy Fiddaman last = 0;
1791*b30d1939SAndy Fiddaman if(mp->len >= ep->e_winsz-4)
1792*b30d1939SAndy Fiddaman {
1793*b30d1939SAndy Fiddaman last = ep->e_winsz-4;
1794*b30d1939SAndy Fiddaman save[0] = mp->data[last-1];
1795*b30d1939SAndy Fiddaman save[1] = mp->data[last];
1796*b30d1939SAndy Fiddaman mp->data[last-1] = '\n';
1797*b30d1939SAndy Fiddaman mp->data[last] = 0;
1798*b30d1939SAndy Fiddaman }
1799*b30d1939SAndy Fiddaman ed_putchar(ep,i<10?' ':'1');
1800*b30d1939SAndy Fiddaman ed_putchar(ep,i<10?'0'+i:'0'+i-10);
1801*b30d1939SAndy Fiddaman ed_putchar(ep,')');
1802*b30d1939SAndy Fiddaman ed_putchar(ep,' ');
1803*b30d1939SAndy Fiddaman ed_putstring(ep,mp->data);
1804*b30d1939SAndy Fiddaman if(last)
1805*b30d1939SAndy Fiddaman {
1806*b30d1939SAndy Fiddaman mp->data[last-1] = save[0];
1807*b30d1939SAndy Fiddaman mp->data[last] = save[1];
1808*b30d1939SAndy Fiddaman }
1809*b30d1939SAndy Fiddaman ep->nhlist = i;
1810*b30d1939SAndy Fiddaman }
1811*b30d1939SAndy Fiddaman last = i-1;
1812*b30d1939SAndy Fiddaman while(i-->0)
1813*b30d1939SAndy Fiddaman ed_putstring(ep,CURSOR_UP);
1814*b30d1939SAndy Fiddaman }
1815*b30d1939SAndy Fiddaman ed_flush(ep);
1816*b30d1939SAndy Fiddaman }
1817*b30d1939SAndy Fiddaman #endif /* SHOPT_EDPREDICT */
1818*b30d1939SAndy Fiddaman
1819da2e3ebdSchin void *ed_open(Shell_t *shp)
1820da2e3ebdSchin {
1821da2e3ebdSchin Edit_t *ed = newof(0,Edit_t,1,0);
1822da2e3ebdSchin ed->sh = shp;
1823da2e3ebdSchin strcpy(ed->e_macro,"_??");
1824da2e3ebdSchin return((void*)ed);
1825da2e3ebdSchin }
1826*b30d1939SAndy Fiddaman
1827*b30d1939SAndy Fiddaman #undef ioctl
1828*b30d1939SAndy Fiddaman int sh_ioctl(int fd, int cmd, void* val, int sz)
1829*b30d1939SAndy Fiddaman {
1830*b30d1939SAndy Fiddaman int r,err=errno;
1831*b30d1939SAndy Fiddaman if(sz == sizeof(void*))
1832*b30d1939SAndy Fiddaman {
1833*b30d1939SAndy Fiddaman while((r=ioctl(fd,cmd,val)) < 0 && errno==EINTR)
1834*b30d1939SAndy Fiddaman errno = err;
1835*b30d1939SAndy Fiddaman }
1836*b30d1939SAndy Fiddaman else
1837*b30d1939SAndy Fiddaman {
1838*b30d1939SAndy Fiddaman Sflong_t l = (Sflong_t)(uintptr_t)val;
1839*b30d1939SAndy Fiddaman if(sizeof(val)==sizeof(long))
1840*b30d1939SAndy Fiddaman {
1841*b30d1939SAndy Fiddaman while((r=ioctl(fd,cmd,(unsigned long)l)) < 0 && errno==EINTR)
1842*b30d1939SAndy Fiddaman errno = err;
1843*b30d1939SAndy Fiddaman }
1844*b30d1939SAndy Fiddaman else if(sizeof(int)!=sizeof(long))
1845*b30d1939SAndy Fiddaman {
1846*b30d1939SAndy Fiddaman while((r=ioctl(fd,cmd,(unsigned int)l)) < 0 && errno==EINTR)
1847*b30d1939SAndy Fiddaman errno = err;
1848*b30d1939SAndy Fiddaman }
1849*b30d1939SAndy Fiddaman }
1850*b30d1939SAndy Fiddaman return(r);
1851*b30d1939SAndy Fiddaman }
1852*b30d1939SAndy Fiddaman
1853*b30d1939SAndy Fiddaman #ifdef _lib_tcgetattr
1854*b30d1939SAndy Fiddaman # undef tcgetattr
1855*b30d1939SAndy Fiddaman int
1856*b30d1939SAndy Fiddaman sh_tcgetattr(int fd, struct termios *tty)
1857*b30d1939SAndy Fiddaman {
1858*b30d1939SAndy Fiddaman int r,err = errno;
1859*b30d1939SAndy Fiddaman while((r=tcgetattr(fd,tty)) < 0 && errno==EINTR)
1860*b30d1939SAndy Fiddaman errno = err;
1861*b30d1939SAndy Fiddaman return(r);
1862*b30d1939SAndy Fiddaman }
1863*b30d1939SAndy Fiddaman
1864*b30d1939SAndy Fiddaman # undef tcsetattr
1865*b30d1939SAndy Fiddaman int
1866*b30d1939SAndy Fiddaman sh_tcsetattr(int fd, int cmd, struct termios *tty)
1867*b30d1939SAndy Fiddaman {
1868*b30d1939SAndy Fiddaman int r,err = errno;
1869*b30d1939SAndy Fiddaman while((r=tcsetattr(fd,cmd,tty)) < 0 && errno==EINTR)
1870*b30d1939SAndy Fiddaman errno = err;
1871*b30d1939SAndy Fiddaman return(r);
1872*b30d1939SAndy Fiddaman }
1873*b30d1939SAndy Fiddaman #endif
1874