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