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