1*35139Smarc /*
2*35139Smarc
3*35139Smarc * Copyright (c) 1984, 1985, 1986 AT&T
4*35139Smarc * All Rights Reserved
5*35139Smarc
6*35139Smarc * THIS IS UNPUBLISHED PROPRIETARY SOURCE
7*35139Smarc * CODE OF AT&T.
8*35139Smarc * The copyright notice above does not
9*35139Smarc * evidence any actual or intended
10*35139Smarc * publication of such source code.
11*35139Smarc
12*35139Smarc */
13*35139Smarc /* @(#)emacs.c 1.1 */
14*35139Smarc /* Adapted for ksh by David Korn */
15*35139Smarc /* EMACS_MODES: c tabstop=4
16*35139Smarc
17*35139Smarc One line screen editor for any program
18*35139Smarc
19*35139Smarc
20*35139Smarc Questions and comments should be
21*35139Smarc directed to
22*35139Smarc
23*35139Smarc Michael T. Veach
24*35139Smarc IX 1C-341 X1614
25*35139Smarc ihuxl!veach
26*35139Smarc
27*35139Smarc */
28*35139Smarc #ifdef DMERT /* 3bcc #undefs RT */
29*35139Smarc #define RT
30*35139Smarc #endif
31*35139Smarc
32*35139Smarc #ifdef KSHELL
33*35139Smarc #include "defs.h"
34*35139Smarc #include "io.h"
35*35139Smarc #include "shtype.h"
36*35139Smarc
37*35139Smarc #else
38*35139Smarc #include <setjmp.h>
39*35139Smarc #include <stdio.h>
40*35139Smarc #include <signal.h>
41*35139Smarc #include <ctype.h>
42*35139Smarc #endif /* KSHELL */
43*35139Smarc
44*35139Smarc #include "history.h"
45*35139Smarc #include "edit.h"
46*35139Smarc
47*35139Smarc #undef blank
48*35139Smarc #undef putchar
49*35139Smarc #define putchar(c) e_putchar(c)
50*35139Smarc #define beep() e_ringbell()
51*35139Smarc
52*35139Smarc
53*35139Smarc #ifdef KSHELL
54*35139Smarc extern void p_flush();
55*35139Smarc extern char *valup();
56*35139Smarc
57*35139Smarc #else
58*35139Smarc static char version[] = "@(#)Editlib version 06/03/86";
59*35139Smarc extern unsigned char *_sobuf;
60*35139Smarc #define p_flush() fflush(stderr)
61*35139Smarc #define output stderr
62*35139Smarc #endif /* KSHELL */
63*35139Smarc
64*35139Smarc #ifdef MULTIBYTE
65*35139Smarc #define gencpy(a,b) e_gencpy(a,b)
66*35139Smarc #define genncpy(a,b,n) e_genncpy(a,b,n)
67*35139Smarc #define genlen(str) e_genlen(str)
68*35139Smarc static int print();
69*35139Smarc static int isword();
70*35139Smarc
71*35139Smarc #else
72*35139Smarc #define gencpy(a,b) strcpy((char*)(a),(char*)(b))
73*35139Smarc #define genncpy(a,b,n) strncpy((char*)(a),(char*)(b),n)
74*35139Smarc #define genlen(str) strlen(str)
75*35139Smarc #define print(c) isprint(c)
76*35139Smarc #define isword(c) isalnum(out[c])
77*35139Smarc #endif /*MULTIBYTE */
78*35139Smarc
79*35139Smarc extern histloc hist_find();
80*35139Smarc extern histloc hist_locate();
81*35139Smarc extern char *hist_word();
82*35139Smarc extern char *itos();
83*35139Smarc extern char *strcpy();
84*35139Smarc extern char *strncpy();
85*35139Smarc extern void e_flush();
86*35139Smarc extern int e_getchar();
87*35139Smarc extern void e_putchar();
88*35139Smarc extern void ungetchar();
89*35139Smarc
90*35139Smarc #define eol editb.e_eol
91*35139Smarc #define cur editb.e_cur
92*35139Smarc #define mark editb.e_fchar
93*35139Smarc #define hline editb.e_hline
94*35139Smarc #define hloff editb.e_hloff
95*35139Smarc #define hismin editb.e_hismin
96*35139Smarc #define usrkill editb.e_kill
97*35139Smarc #define usreof editb.e_eof
98*35139Smarc #define usrerase editb.e_erase
99*35139Smarc #define crallowed editb.e_crlf
100*35139Smarc #define llimit editb.e_llimit
101*35139Smarc #define Prompt editb.e_prompt
102*35139Smarc #define plen editb.e_plen
103*35139Smarc #define kstack editb.e_tmp
104*35139Smarc #define lstring editb.e_search
105*35139Smarc #define lookahead editb.e_index
106*35139Smarc #define env editb.e_env
107*35139Smarc #define raw editb.e_raw
108*35139Smarc #define histlines editb.e_hismax
109*35139Smarc #define w_size editb.e_wsize
110*35139Smarc #define drawbuff editb.e_inbuf
111*35139Smarc #define NO 0
112*35139Smarc #define YES 1
113*35139Smarc #define LBUF 100
114*35139Smarc #define KILLCHAR UKILL
115*35139Smarc #define ERASECHAR UERASE
116*35139Smarc #define EOFCHAR UEOF
117*35139Smarc
118*35139Smarc /**********************
119*35139Smarc A large lookahead helps when the user is inserting
120*35139Smarc characters in the middle of the line.
121*35139Smarc ************************/
122*35139Smarc
123*35139Smarc
124*35139Smarc static genchar *screen; /* pointer to window buffer */
125*35139Smarc static genchar *cursor; /* Cursor in real screen */
126*35139Smarc static enum
127*35139Smarc {
128*35139Smarc CRT=0, /* Crt terminal */
129*35139Smarc PAPER /* Paper terminal */
130*35139Smarc } terminal ;
131*35139Smarc
132*35139Smarc typedef enum
133*35139Smarc {
134*35139Smarc FIRST, /* First time thru for logical line, prompt on screen */
135*35139Smarc REFRESH, /* Redraw entire screen */
136*35139Smarc APPEND, /* Append char before cursor to screen */
137*35139Smarc UPDATE, /* Update the screen as need be */
138*35139Smarc FINAL /* Update screen even if pending look ahead */
139*35139Smarc } DRAWTYPE;
140*35139Smarc
141*35139Smarc static void draw();
142*35139Smarc static int escape();
143*35139Smarc static void putstring();
144*35139Smarc static int search();
145*35139Smarc static void setcursor();
146*35139Smarc
147*35139Smarc static int cr_ok;
148*35139Smarc
hread(fd,buff,scend)149*35139Smarc hread(fd,buff,scend)
150*35139Smarc char *buff;
151*35139Smarc int fd,scend;
152*35139Smarc {
153*35139Smarc register int c;
154*35139Smarc register int i;
155*35139Smarc register genchar *out;
156*35139Smarc register int count;
157*35139Smarc int adjust,oadjust;
158*35139Smarc char backslash;
159*35139Smarc genchar *kptr;
160*35139Smarc static histloc location;
161*35139Smarc static int CntrlO;
162*35139Smarc char prompt[LBUF];
163*35139Smarc genchar stack[MAXLINE];
164*35139Smarc char string[LBUF*CHARSIZE];
165*35139Smarc genchar Screen[MAXWINDOW];
166*35139Smarc Prompt = prompt;
167*35139Smarc kstack = stack;
168*35139Smarc lstring = string;
169*35139Smarc screen = Screen;
170*35139Smarc drawbuff = out = (genchar*)buff;
171*35139Smarc kstack[0] = '\0';
172*35139Smarc if(setraw(fd) < 0)
173*35139Smarc {
174*35139Smarc p_flush();
175*35139Smarc return(read(fd,buff,scend));
176*35139Smarc }
177*35139Smarc raw = 1;
178*35139Smarc /* This mess in case the read system call fails */
179*35139Smarc
180*35139Smarc e_setup(fd,LBUF);
181*35139Smarc if ((i=setjmp(env))!=0)
182*35139Smarc {
183*35139Smarc setcooked(fd);
184*35139Smarc if (i == UEOF)
185*35139Smarc {
186*35139Smarc return(0); /* EOF */
187*35139Smarc }
188*35139Smarc return(-1); /* some other error */
189*35139Smarc }
190*35139Smarc #ifdef MULTIBYTE
191*35139Smarc plen = e_internal(&Prompt[1],out); /* Skip the leading \r */
192*35139Smarc #else
193*35139Smarc gencpy(buff,&Prompt[1]); /* Skip the leading \r */
194*35139Smarc #endif /* MULTIBYTE */
195*35139Smarc scend -= plen;
196*35139Smarc llimit = scend;
197*35139Smarc mark = eol = cur = plen;
198*35139Smarc draw(FIRST);
199*35139Smarc adjust = -1;
200*35139Smarc backslash = 0;
201*35139Smarc if (CntrlO)
202*35139Smarc {
203*35139Smarc location = hist_locate(location.his_command,location.his_line,1);
204*35139Smarc if (location.his_command < histlines)
205*35139Smarc {
206*35139Smarc hline = location.his_command;
207*35139Smarc hloff = location.his_line;
208*35139Smarc hist_copy((char*)kstack,hline,hloff);
209*35139Smarc #ifdef MULTIBYTE
210*35139Smarc e_internal((char*)kstack,kstack);
211*35139Smarc #endif /* MULTIBYTE */
212*35139Smarc ungetchar(cntl(Y));
213*35139Smarc }
214*35139Smarc }
215*35139Smarc CntrlO = 0;
216*35139Smarc while ((c = e_getchar()) != (-1))
217*35139Smarc {
218*35139Smarc if (backslash)
219*35139Smarc {
220*35139Smarc backslash = 0;
221*35139Smarc if (c==usrerase||c==usrkill||(!print(c) &&
222*35139Smarc (c!='\r'&&c!='\n')))
223*35139Smarc {
224*35139Smarc /* accept a backslashed character */
225*35139Smarc cur--;
226*35139Smarc out[cur++] = c;
227*35139Smarc out[eol] = '\0';
228*35139Smarc draw(APPEND);
229*35139Smarc continue;
230*35139Smarc }
231*35139Smarc }
232*35139Smarc if (c == usrkill)
233*35139Smarc {
234*35139Smarc c = KILLCHAR ;
235*35139Smarc }
236*35139Smarc else if (c == usrerase)
237*35139Smarc {
238*35139Smarc c = ERASECHAR ;
239*35139Smarc }
240*35139Smarc else if ((c == usreof)&&(eol == plen))
241*35139Smarc {
242*35139Smarc c = EOFCHAR;
243*35139Smarc }
244*35139Smarc oadjust = count = adjust;
245*35139Smarc if(count<0)
246*35139Smarc count = 1;
247*35139Smarc adjust = -1;
248*35139Smarc i = cur;
249*35139Smarc switch(c)
250*35139Smarc {
251*35139Smarc case cntl(V):
252*35139Smarc {
253*35139Smarc genchar string[100];
254*35139Smarc /* save current line */
255*35139Smarc genncpy(string,out,sizeof(string)/CHARSIZE-1);
256*35139Smarc out[plen] = '\0';
257*35139Smarc cur = plen;
258*35139Smarc #ifdef MULTIBYTE
259*35139Smarc e_internal(&version[4],out+plen);
260*35139Smarc #else
261*35139Smarc gencpy(buff+plen,&version[4]);
262*35139Smarc #endif /* MULTIBYTE */
263*35139Smarc draw(UPDATE);
264*35139Smarc c = e_getchar();
265*35139Smarc ungetchar(c);
266*35139Smarc /* restore line */
267*35139Smarc cur = i;
268*35139Smarc genncpy(out,string,sizeof(string)/CHARSIZE-1);
269*35139Smarc draw(UPDATE);
270*35139Smarc }
271*35139Smarc continue;
272*35139Smarc case '\0':
273*35139Smarc mark = i;
274*35139Smarc continue;
275*35139Smarc case cntl(X):
276*35139Smarc i = e_getchar();
277*35139Smarc if (i != cntl(X))
278*35139Smarc {
279*35139Smarc beep();
280*35139Smarc continue;
281*35139Smarc }
282*35139Smarc if (mark > eol)
283*35139Smarc mark = eol;
284*35139Smarc i = mark;
285*35139Smarc mark = cur;
286*35139Smarc goto update;
287*35139Smarc case EOFCHAR:
288*35139Smarc e_flush();
289*35139Smarc setcooked(fd);
290*35139Smarc return(0);
291*35139Smarc #ifdef u370
292*35139Smarc case cntl(S) :
293*35139Smarc case cntl(Q) :
294*35139Smarc continue;
295*35139Smarc #endif /* u370 */
296*35139Smarc default:
297*35139Smarc i = ++eol;
298*35139Smarc if (i >= (scend)) /* will not fit on line */
299*35139Smarc {
300*35139Smarc eol--;
301*35139Smarc ungetchar(c); /* save character for next line */
302*35139Smarc draw(FINAL);
303*35139Smarc goto process;
304*35139Smarc }
305*35139Smarc for(i=eol;i>=cur;i--)
306*35139Smarc {
307*35139Smarc out[i] = out[i-1];
308*35139Smarc }
309*35139Smarc backslash = (c == '\\');
310*35139Smarc out[cur++] = c;
311*35139Smarc draw(APPEND);
312*35139Smarc continue;
313*35139Smarc case cntl(Y) :
314*35139Smarc {
315*35139Smarc c = genlen(kstack);
316*35139Smarc if ((c + eol) > scend)
317*35139Smarc {
318*35139Smarc beep();
319*35139Smarc continue;
320*35139Smarc }
321*35139Smarc mark = i;
322*35139Smarc for(i=eol;i>=cur;i--)
323*35139Smarc out[c+i] = out[i];
324*35139Smarc kptr=kstack;
325*35139Smarc while (i = *kptr++)
326*35139Smarc out[cur++] = i;
327*35139Smarc draw(UPDATE);
328*35139Smarc eol = genlen(out);
329*35139Smarc continue;
330*35139Smarc }
331*35139Smarc case '\n':
332*35139Smarc case '\r':
333*35139Smarc draw(FINAL);
334*35139Smarc out[eol++] = '\n';
335*35139Smarc out[eol] = '\0';
336*35139Smarc e_crlf();
337*35139Smarc goto process;
338*35139Smarc case ERASECHAR :
339*35139Smarc if (count > (i-plen))
340*35139Smarc count = i-plen;
341*35139Smarc while ((count--)&&(i>plen))
342*35139Smarc {
343*35139Smarc i--;
344*35139Smarc eol--;
345*35139Smarc }
346*35139Smarc genncpy(kstack,out+i,cur-i);
347*35139Smarc kstack[cur-i] = 0;
348*35139Smarc gencpy(out+i,out+cur);
349*35139Smarc mark = i;
350*35139Smarc goto update;
351*35139Smarc case cntl(W) :
352*35139Smarc if (mark > eol )
353*35139Smarc mark = eol;
354*35139Smarc if (mark == i)
355*35139Smarc continue;
356*35139Smarc if (mark > i)
357*35139Smarc {
358*35139Smarc adjust = mark - i;
359*35139Smarc ungetchar(cntl(D));
360*35139Smarc continue;
361*35139Smarc }
362*35139Smarc adjust = i - mark;
363*35139Smarc ungetchar('\b');
364*35139Smarc continue;
365*35139Smarc case cntl(D) :
366*35139Smarc mark = i;
367*35139Smarc kptr = kstack;
368*35139Smarc while ((count--)&&(eol>plen)&&(i<eol))
369*35139Smarc {
370*35139Smarc *kptr++ = out[i];
371*35139Smarc eol--;
372*35139Smarc while(1)
373*35139Smarc {
374*35139Smarc if ((out[i] = out[(i+1)])==0)
375*35139Smarc break;
376*35139Smarc i++;
377*35139Smarc }
378*35139Smarc i = cur;
379*35139Smarc }
380*35139Smarc *kptr = '\0';
381*35139Smarc goto update;
382*35139Smarc case cntl(C) :
383*35139Smarc case cntl(F) :
384*35139Smarc {
385*35139Smarc int cntlC = (c==cntl(C));
386*35139Smarc while (count-- && eol>i)
387*35139Smarc {
388*35139Smarc if (cntlC)
389*35139Smarc {
390*35139Smarc c = out[i];
391*35139Smarc #ifdef MULTIBYTE
392*35139Smarc if((c&~STRIP)==0 && islower(c))
393*35139Smarc #else
394*35139Smarc if(islower(c))
395*35139Smarc #endif /* MULTIBYTE */
396*35139Smarc {
397*35139Smarc c += 'A' - 'a';
398*35139Smarc out[i] = c;
399*35139Smarc }
400*35139Smarc }
401*35139Smarc i++;
402*35139Smarc }
403*35139Smarc goto update;
404*35139Smarc }
405*35139Smarc case cntl(]) :
406*35139Smarc c = e_getchar();
407*35139Smarc if (out[i])
408*35139Smarc i++;
409*35139Smarc while (i < eol)
410*35139Smarc {
411*35139Smarc if (out[i] == c)
412*35139Smarc goto update;
413*35139Smarc i++;
414*35139Smarc }
415*35139Smarc i = plen;
416*35139Smarc while (i < cur)
417*35139Smarc {
418*35139Smarc if (out[i] == c)
419*35139Smarc break;
420*35139Smarc i++;
421*35139Smarc };
422*35139Smarc
423*35139Smarc update:
424*35139Smarc cur = i;
425*35139Smarc draw(UPDATE);
426*35139Smarc continue;
427*35139Smarc
428*35139Smarc case cntl(B) :
429*35139Smarc if (count > (i-plen))
430*35139Smarc count = i - plen;
431*35139Smarc i -= count;
432*35139Smarc goto update;
433*35139Smarc case cntl(T) :
434*35139Smarc if ((is_option(GMACS))||(eol==i))
435*35139Smarc {
436*35139Smarc if (i >= plen + 2)
437*35139Smarc {
438*35139Smarc c = out[i - 1];
439*35139Smarc out[i-1] = out[i-2];
440*35139Smarc out[i-2] = c;
441*35139Smarc }
442*35139Smarc else
443*35139Smarc {
444*35139Smarc beep();
445*35139Smarc continue;
446*35139Smarc }
447*35139Smarc }
448*35139Smarc else
449*35139Smarc {
450*35139Smarc if (eol>(i+1))
451*35139Smarc {
452*35139Smarc c = out[i];
453*35139Smarc out[i] = out[i+1];
454*35139Smarc out[i+1] = c;
455*35139Smarc i++;
456*35139Smarc }
457*35139Smarc else
458*35139Smarc {
459*35139Smarc beep();
460*35139Smarc continue;
461*35139Smarc }
462*35139Smarc }
463*35139Smarc goto update;
464*35139Smarc case cntl(A) :
465*35139Smarc i = plen;
466*35139Smarc goto update;
467*35139Smarc case cntl(E) :
468*35139Smarc i = eol;
469*35139Smarc goto update;
470*35139Smarc case cntl(U) :
471*35139Smarc adjust = 4*count;
472*35139Smarc continue;
473*35139Smarc case KILLCHAR :
474*35139Smarc cur = plen;
475*35139Smarc oadjust = -1;
476*35139Smarc case cntl(K) :
477*35139Smarc if(oadjust >= 0)
478*35139Smarc {
479*35139Smarc mark = plen+count;
480*35139Smarc ungetchar(cntl(W));
481*35139Smarc continue;
482*35139Smarc }
483*35139Smarc i = cur;
484*35139Smarc eol = i;
485*35139Smarc mark = i;
486*35139Smarc gencpy(kstack,&out[i]);
487*35139Smarc out[i] = 0;
488*35139Smarc draw(UPDATE);
489*35139Smarc if (c == KILLCHAR)
490*35139Smarc {
491*35139Smarc if (terminal == PAPER)
492*35139Smarc putstring("\r\n");
493*35139Smarc c = e_getchar();
494*35139Smarc if (c != usrkill)
495*35139Smarc {
496*35139Smarc ungetchar(c);
497*35139Smarc continue;
498*35139Smarc }
499*35139Smarc if (terminal == PAPER)
500*35139Smarc terminal = CRT;
501*35139Smarc else
502*35139Smarc {
503*35139Smarc terminal = PAPER;
504*35139Smarc putstring("\r\n");
505*35139Smarc }
506*35139Smarc }
507*35139Smarc continue;
508*35139Smarc case cntl(L):
509*35139Smarc e_crlf();
510*35139Smarc draw(REFRESH);
511*35139Smarc continue;
512*35139Smarc case cntl([) :
513*35139Smarc adjust = escape(out,oadjust);
514*35139Smarc continue;
515*35139Smarc case cntl(R) :
516*35139Smarc search(out,count);
517*35139Smarc goto drawline;
518*35139Smarc case cntl(P) :
519*35139Smarc location = hist_locate(hline,hloff,-count);
520*35139Smarc hline = location.his_command;
521*35139Smarc if (hline < hismin)
522*35139Smarc {
523*35139Smarc hline = hismin;
524*35139Smarc beep();
525*35139Smarc }
526*35139Smarc goto common;
527*35139Smarc
528*35139Smarc case cntl(O) :
529*35139Smarc location.his_command = hline;
530*35139Smarc location.his_line = hloff;
531*35139Smarc CntrlO = 1;
532*35139Smarc draw(FINAL);
533*35139Smarc out[eol++] = '\n';
534*35139Smarc out[eol] = '\0';
535*35139Smarc e_crlf();
536*35139Smarc goto process;
537*35139Smarc case cntl(N) :
538*35139Smarc location = hist_locate(hline,hloff,count);
539*35139Smarc if (location.his_command > histlines)
540*35139Smarc {
541*35139Smarc beep();
542*35139Smarc continue;
543*35139Smarc }
544*35139Smarc hline = location.his_command;
545*35139Smarc common:
546*35139Smarc hloff = location.his_line;
547*35139Smarc hist_copy(&out[plen],hline,hloff);
548*35139Smarc #ifdef MULTIBYTE
549*35139Smarc e_internal((char*)(&out[plen]),&out[plen]);
550*35139Smarc #endif /* MULTIBYTE */
551*35139Smarc drawline:
552*35139Smarc eol = genlen(out);
553*35139Smarc cur = eol;
554*35139Smarc draw(UPDATE);
555*35139Smarc continue;
556*35139Smarc }
557*35139Smarc
558*35139Smarc }
559*35139Smarc
560*35139Smarc process:
561*35139Smarc
562*35139Smarc if (c == (-1))
563*35139Smarc {
564*35139Smarc lookahead = 0;
565*35139Smarc beep();
566*35139Smarc out[plen] = '\0';
567*35139Smarc }
568*35139Smarc gencpy(out,&out[plen]);
569*35139Smarc #ifdef MULTIBYTE
570*35139Smarc e_external(out,buff);
571*35139Smarc #endif /* MULTIBYTE */
572*35139Smarc #ifdef u370
573*35139Smarc putchar('\0');
574*35139Smarc #endif /* u370 */
575*35139Smarc e_flush();
576*35139Smarc setcooked(fd);
577*35139Smarc i = strlen(buff);
578*35139Smarc if (i)
579*35139Smarc return(i);
580*35139Smarc return(-1);
581*35139Smarc }
582*35139Smarc
583*35139Smarc
584*35139Smarc static void
585*35139Smarc putstring(s)
586*35139Smarc register char *s;
587*35139Smarc {
588*35139Smarc register int c;
589*35139Smarc while (c= *s++)
590*35139Smarc putchar(c);
591*35139Smarc }
592*35139Smarc
593*35139Smarc
594*35139Smarc static int
595*35139Smarc escape(out,count)
596*35139Smarc register genchar *out;
597*35139Smarc {
598*35139Smarc register int i,value;
599*35139Smarc int digit,ch;
600*35139Smarc digit = 0;
601*35139Smarc value = 0;
602*35139Smarc while ((i=e_getchar()),isdigit(i))
603*35139Smarc {
604*35139Smarc value *= 10;
605*35139Smarc value += (i - '0');
606*35139Smarc digit = 1;
607*35139Smarc }
608*35139Smarc if (digit)
609*35139Smarc {
610*35139Smarc ungetchar(i) ;
611*35139Smarc return(value);
612*35139Smarc }
613*35139Smarc value = count;
614*35139Smarc if(value<0)
615*35139Smarc value = 1;
616*35139Smarc switch(ch=i)
617*35139Smarc {
618*35139Smarc case ' ':
619*35139Smarc mark = cur;
620*35139Smarc return(-1);
621*35139Smarc
622*35139Smarc case 'p': /* M-p == ^W^Y (copy stack == kill & yank) */
623*35139Smarc ungetchar(cntl(Y));
624*35139Smarc ungetchar(cntl(W));
625*35139Smarc return(-1);
626*35139Smarc
627*35139Smarc case 'l': /* M-l == lower-case */
628*35139Smarc case 'd':
629*35139Smarc case 'c':
630*35139Smarc case 'f':
631*35139Smarc {
632*35139Smarc i = cur;
633*35139Smarc while(value-- && i<eol)
634*35139Smarc {
635*35139Smarc while (!isword(i))
636*35139Smarc i++;
637*35139Smarc while ((out[i])&&(isword(i)))
638*35139Smarc i++;
639*35139Smarc }
640*35139Smarc if(ch=='l')
641*35139Smarc {
642*35139Smarc value = i-cur;
643*35139Smarc while (value-- > 0)
644*35139Smarc {
645*35139Smarc i = out[cur];
646*35139Smarc #ifdef MULTIBYTE
647*35139Smarc if((i&~STRIP)==0 && isupper(i))
648*35139Smarc #else
649*35139Smarc if(isupper(i))
650*35139Smarc #endif /* MULTIBYTE */
651*35139Smarc {
652*35139Smarc i += 'a' - 'A';
653*35139Smarc out[cur] = i;
654*35139Smarc }
655*35139Smarc cur++;
656*35139Smarc }
657*35139Smarc draw(UPDATE);
658*35139Smarc return(-1);
659*35139Smarc }
660*35139Smarc
661*35139Smarc else if(ch=='f')
662*35139Smarc {
663*35139Smarc cur = i;
664*35139Smarc draw(UPDATE);
665*35139Smarc return(-1);
666*35139Smarc }
667*35139Smarc else if(ch=='c')
668*35139Smarc {
669*35139Smarc ungetchar(cntl(C));
670*35139Smarc return(i-cur);
671*35139Smarc }
672*35139Smarc else
673*35139Smarc {
674*35139Smarc if (i-cur)
675*35139Smarc {
676*35139Smarc ungetchar(cntl(D));
677*35139Smarc return(i-cur);
678*35139Smarc }
679*35139Smarc beep();
680*35139Smarc return(-1);
681*35139Smarc }
682*35139Smarc }
683*35139Smarc
684*35139Smarc
685*35139Smarc case 'b':
686*35139Smarc case DELETE :
687*35139Smarc case '\b':
688*35139Smarc case 'h':
689*35139Smarc {
690*35139Smarc i = cur;
691*35139Smarc while(value-- && i>plen)
692*35139Smarc {
693*35139Smarc i--;
694*35139Smarc while ((i>plen)&&(!isword(i)))
695*35139Smarc i--;
696*35139Smarc while ((i>plen)&&(isword(i-1)))
697*35139Smarc i--;
698*35139Smarc }
699*35139Smarc if(ch=='b')
700*35139Smarc {
701*35139Smarc cur = i;
702*35139Smarc draw(UPDATE);
703*35139Smarc return(-1);
704*35139Smarc }
705*35139Smarc else
706*35139Smarc {
707*35139Smarc ungetchar(ERASECHAR);
708*35139Smarc return(cur-i);
709*35139Smarc }
710*35139Smarc }
711*35139Smarc
712*35139Smarc case '>':
713*35139Smarc ungetchar(cntl(N));
714*35139Smarc return(histlines-(hline+1));
715*35139Smarc
716*35139Smarc case '<':
717*35139Smarc ungetchar(cntl(P));
718*35139Smarc return(hline);
719*35139Smarc
720*35139Smarc
721*35139Smarc #ifdef KSHELL
722*35139Smarc case '_' :
723*35139Smarc case '.' :
724*35139Smarc {
725*35139Smarc genchar name[MAXLINE];
726*35139Smarc char buf[MAXLINE];
727*35139Smarc char *ptr;
728*35139Smarc ptr = hist_word(buf,(count?count:-1));
729*35139Smarc #ifndef KSHELL
730*35139Smarc if(ptr==NULL)
731*35139Smarc {
732*35139Smarc beep();
733*35139Smarc break;
734*35139Smarc }
735*35139Smarc #endif /* KSHELL */
736*35139Smarc if ((eol - cur) >= sizeof(name))
737*35139Smarc {
738*35139Smarc beep();
739*35139Smarc return(-1);
740*35139Smarc }
741*35139Smarc mark = cur;
742*35139Smarc gencpy(name,&out[cur]);
743*35139Smarc while(*ptr)
744*35139Smarc {
745*35139Smarc out[cur++] = *ptr++;
746*35139Smarc eol++;
747*35139Smarc }
748*35139Smarc gencpy(&out[cur],name);
749*35139Smarc draw(UPDATE);
750*35139Smarc return(-1);
751*35139Smarc }
752*35139Smarc
753*35139Smarc /* file name expansion */
754*35139Smarc case cntl([) : /* easier to type */
755*35139Smarc i = '*';
756*35139Smarc case '*':
757*35139Smarc case '=': /* escape = - list all matching file names */
758*35139Smarc mark = cur;
759*35139Smarc if(q_expand(out,&cur,&eol,plen,i) < 0)
760*35139Smarc beep();
761*35139Smarc else if(i=='*')
762*35139Smarc draw(UPDATE);
763*35139Smarc else
764*35139Smarc draw(REFRESH);
765*35139Smarc return(-1);
766*35139Smarc
767*35139Smarc default:
768*35139Smarc /* look for user defined macro definitions */
769*35139Smarc if(e_macro(i))
770*35139Smarc return(-1);
771*35139Smarc #else
772*35139Smarc default:
773*35139Smarc #endif /* KSHELL */
774*35139Smarc ungetchar(i);
775*35139Smarc ungetchar(cntl([));
776*35139Smarc ungetchar('\\');
777*35139Smarc return(-1);
778*35139Smarc }
779*35139Smarc }
780*35139Smarc
781*35139Smarc
782*35139Smarc static int
783*35139Smarc search(out,direction)
784*35139Smarc genchar out[];
785*35139Smarc {
786*35139Smarc static int prevdirection = 1 ;
787*35139Smarc histloc location;
788*35139Smarc register int i,sl;
789*35139Smarc genchar str_buff[100];
790*35139Smarc register genchar *string = drawbuff;
791*35139Smarc /* save current line */
792*35139Smarc char sav_cur = cur;
793*35139Smarc genncpy(str_buff,string,sizeof(str_buff)/CHARSIZE-1);
794*35139Smarc string[plen] = '^';
795*35139Smarc string[plen+1] = 'R';
796*35139Smarc string[plen+2] = '\0';
797*35139Smarc sl = 2+plen;
798*35139Smarc cur = sl;
799*35139Smarc draw(UPDATE);
800*35139Smarc while ((i = e_getchar())&&(i != '\r')&&(i != '\n'))
801*35139Smarc {
802*35139Smarc if (i==usrerase)
803*35139Smarc {
804*35139Smarc if (sl > 2+plen)
805*35139Smarc {
806*35139Smarc string[--sl] = '\0';
807*35139Smarc cur = sl;
808*35139Smarc draw(UPDATE);
809*35139Smarc }
810*35139Smarc else
811*35139Smarc beep();
812*35139Smarc continue;
813*35139Smarc }
814*35139Smarc if (i==usrkill)
815*35139Smarc {
816*35139Smarc beep();
817*35139Smarc goto restore;
818*35139Smarc }
819*35139Smarc if (i == '\\')
820*35139Smarc {
821*35139Smarc string[sl++] = '\\';
822*35139Smarc string[sl] = '\0';
823*35139Smarc cur = sl;
824*35139Smarc draw(APPEND);
825*35139Smarc i = e_getchar();
826*35139Smarc string[--sl] = '\0';
827*35139Smarc }
828*35139Smarc string[sl++] = i;
829*35139Smarc string[sl] = '\0';
830*35139Smarc cur = sl;
831*35139Smarc draw(APPEND);
832*35139Smarc }
833*35139Smarc i = genlen(string);
834*35139Smarc
835*35139Smarc if (direction < 1)
836*35139Smarc {
837*35139Smarc prevdirection = -prevdirection;
838*35139Smarc direction = 1;
839*35139Smarc }
840*35139Smarc else
841*35139Smarc direction = -1;
842*35139Smarc if (i != 2+plen)
843*35139Smarc {
844*35139Smarc gencpy(lstring,&string[2+plen]);
845*35139Smarc #ifdef MULTIBYTE
846*35139Smarc e_external(lstring,(char*)lstring);
847*35139Smarc #endif /* MULTIBYTE */
848*35139Smarc prevdirection = direction;
849*35139Smarc }
850*35139Smarc else
851*35139Smarc direction = prevdirection ;
852*35139Smarc location = hist_find((char*)lstring,hline,1,direction);
853*35139Smarc i = location.his_command;
854*35139Smarc if(i>0)
855*35139Smarc {
856*35139Smarc hline = i;
857*35139Smarc hloff = location.his_line;
858*35139Smarc hist_copy((char*)&out[plen],hline,hloff);
859*35139Smarc #ifdef MULTIBYTE
860*35139Smarc e_internal((char*)&out[plen],&out[plen]);
861*35139Smarc #endif /* MULTIBYTE */
862*35139Smarc return;
863*35139Smarc }
864*35139Smarc if (i < 0)
865*35139Smarc {
866*35139Smarc beep();
867*35139Smarc hloff = (fc_fix?fc_fix->fixline:0);
868*35139Smarc hline = histlines;
869*35139Smarc }
870*35139Smarc restore:
871*35139Smarc genncpy(string,str_buff,sizeof(str_buff)/CHARSIZE-1);
872*35139Smarc cur = sav_cur;
873*35139Smarc return;
874*35139Smarc }
875*35139Smarc
876*35139Smarc
877*35139Smarc /* Adjust screen to agree with inputs: logical line and cursor */
878*35139Smarc /* If 'first' assume screen is blank */
879*35139Smarc
880*35139Smarc static void
881*35139Smarc draw(option)
882*35139Smarc DRAWTYPE option;
883*35139Smarc {
884*35139Smarc #define NORMAL ' '
885*35139Smarc #define LOWER '<'
886*35139Smarc #define BOTH '*'
887*35139Smarc #define UPPER '>'
888*35139Smarc #define UNDEF 0
889*35139Smarc
890*35139Smarc static char overflow; /* Screen overflow flag set */
891*35139Smarc register genchar *sptr; /* Pointer within screen */
892*35139Smarc
893*35139Smarc static int offset; /* Screen offset */
894*35139Smarc static char scvalid; /* Screen is up to date */
895*35139Smarc
896*35139Smarc genchar nscreen[2*MAXLINE]; /* New entire screen */
897*35139Smarc genchar *ncursor; /* New cursor */
898*35139Smarc register genchar *nptr; /* Pointer to New screen */
899*35139Smarc char longline; /* Line overflow */
900*35139Smarc genchar *logcursor;
901*35139Smarc genchar *nscend; /* end of logical screen */
902*35139Smarc register int i;
903*35139Smarc
904*35139Smarc nptr = nscreen;
905*35139Smarc sptr = drawbuff;
906*35139Smarc logcursor = sptr + cur;
907*35139Smarc ncursor = nscreen;
908*35139Smarc longline = NORMAL;
909*35139Smarc
910*35139Smarc if (option == FIRST || option == REFRESH)
911*35139Smarc {
912*35139Smarc overflow = NORMAL;
913*35139Smarc cursor = screen;
914*35139Smarc offset = 0;
915*35139Smarc cr_ok = crallowed;
916*35139Smarc if (option == FIRST)
917*35139Smarc {
918*35139Smarc scvalid = 1;
919*35139Smarc gencpy(cursor,sptr);
920*35139Smarc cursor += plen;
921*35139Smarc return;
922*35139Smarc }
923*35139Smarc *cursor = '\0';
924*35139Smarc }
925*35139Smarc
926*35139Smarc /*********************
927*35139Smarc Do not update screen if pending characters
928*35139Smarc **********************/
929*35139Smarc
930*35139Smarc if ((lookahead)&&(option != FINAL))
931*35139Smarc {
932*35139Smarc
933*35139Smarc scvalid = 0; /* Screen is out of date, APPEND will not work */
934*35139Smarc
935*35139Smarc return;
936*35139Smarc }
937*35139Smarc
938*35139Smarc /***************************************
939*35139Smarc If in append mode, cursor at end of line, screen up to date,
940*35139Smarc the previous character was a 'normal' character,
941*35139Smarc and the window has room for another character.
942*35139Smarc Then output the character and adjust the screen only.
943*35139Smarc *****************************************/
944*35139Smarc
945*35139Smarc
946*35139Smarc i = *(logcursor-1);
947*35139Smarc
948*35139Smarc if ((option == APPEND)&&(scvalid)&&(*logcursor == '\0')&&
949*35139Smarc print(i)&&((cursor-screen)<(w_size-1)))
950*35139Smarc {
951*35139Smarc putchar(i);
952*35139Smarc *cursor++ = i;
953*35139Smarc *cursor = '\0';
954*35139Smarc return;
955*35139Smarc }
956*35139Smarc
957*35139Smarc /* copy the prompt */
958*35139Smarc i = plen;
959*35139Smarc while(--i >=0)
960*35139Smarc nptr[i] = sptr[i];
961*35139Smarc /* now the rest of the line */
962*35139Smarc ncursor = nptr + e_virt_to_phys(sptr,nptr,cur,plen,plen);
963*35139Smarc nptr += genlen(nptr);
964*35139Smarc sptr += genlen(sptr);
965*35139Smarc nscend = nptr - 1;
966*35139Smarc if(sptr == logcursor)
967*35139Smarc ncursor = nptr;
968*35139Smarc
969*35139Smarc /*********************
970*35139Smarc Does ncursor appear on the screen?
971*35139Smarc If not, adjust the screen offset so it does.
972*35139Smarc **********************/
973*35139Smarc
974*35139Smarc i = ncursor - nscreen;
975*35139Smarc
976*35139Smarc if ((i <= offset)||(i >= (offset+w_size)))
977*35139Smarc {
978*35139Smarc offset = i - (w_size>>1);
979*35139Smarc if (offset < plen)
980*35139Smarc {
981*35139Smarc offset = (crallowed == YES) ? 0 : plen;
982*35139Smarc }
983*35139Smarc if ((offset >= plen)&&(cr_ok == NO))
984*35139Smarc {
985*35139Smarc
986*35139Smarc /*********************************
987*35139Smarc Don't really know whats on the screen
988*35139Smarc because of strange characters in the prompt.
989*35139Smarc
990*35139Smarc Mark entire screen as unknow.
991*35139Smarc ***********************************/
992*35139Smarc
993*35139Smarc cursor = screen;
994*35139Smarc *cursor = '\0';
995*35139Smarc putchar('\r');
996*35139Smarc overflow = UNDEF;
997*35139Smarc cr_ok = YES;
998*35139Smarc }
999*35139Smarc }
1000*35139Smarc /*********************
1001*35139Smarc Is the range of screen[0] thru screen[w_size] up-to-date
1002*35139Smarc with nscreen[offset] thru nscreen[offset+w_size] ?
1003*35139Smarc If not, update as need be.
1004*35139Smarc ***********************/
1005*35139Smarc
1006*35139Smarc nptr = &nscreen[offset];
1007*35139Smarc sptr = screen;
1008*35139Smarc
1009*35139Smarc i = w_size;
1010*35139Smarc
1011*35139Smarc while (i-- > 0)
1012*35139Smarc {
1013*35139Smarc
1014*35139Smarc if (*nptr == '\0')
1015*35139Smarc {
1016*35139Smarc *(nptr + 1) = '\0';
1017*35139Smarc *nptr = ' ';
1018*35139Smarc }
1019*35139Smarc if (*sptr == '\0')
1020*35139Smarc {
1021*35139Smarc *(sptr + 1) = '\0';
1022*35139Smarc *sptr = ' ';
1023*35139Smarc }
1024*35139Smarc if (*nptr == *sptr)
1025*35139Smarc {
1026*35139Smarc nptr++;
1027*35139Smarc sptr++;
1028*35139Smarc continue;
1029*35139Smarc }
1030*35139Smarc setcursor(sptr-screen,*nptr);
1031*35139Smarc *sptr++ = *nptr++;
1032*35139Smarc #ifdef MULTIBYTE
1033*35139Smarc while(*nptr==MARKER)
1034*35139Smarc {
1035*35139Smarc *sptr++ = *nptr++;
1036*35139Smarc i--;
1037*35139Smarc cursor++;
1038*35139Smarc }
1039*35139Smarc #endif /* MULTIBYTE */
1040*35139Smarc }
1041*35139Smarc
1042*35139Smarc /******************
1043*35139Smarc
1044*35139Smarc Screen overflow checks
1045*35139Smarc
1046*35139Smarc ********************/
1047*35139Smarc
1048*35139Smarc if (nscend >= &nscreen[offset+w_size])
1049*35139Smarc {
1050*35139Smarc if (offset > plen)
1051*35139Smarc longline = BOTH;
1052*35139Smarc else
1053*35139Smarc longline = UPPER;
1054*35139Smarc }
1055*35139Smarc else
1056*35139Smarc {
1057*35139Smarc if (offset > plen)
1058*35139Smarc longline = LOWER;
1059*35139Smarc }
1060*35139Smarc
1061*35139Smarc /* Update screen overflow indicator if need be */
1062*35139Smarc
1063*35139Smarc if (longline != overflow)
1064*35139Smarc {
1065*35139Smarc setcursor(w_size,longline);
1066*35139Smarc overflow = longline;
1067*35139Smarc }
1068*35139Smarc i = (ncursor-nscreen) - offset;
1069*35139Smarc setcursor(i,0);
1070*35139Smarc scvalid = 1;
1071*35139Smarc return;
1072*35139Smarc }
1073*35139Smarc
1074*35139Smarc /*
1075*35139Smarc * put the cursor to the <new> position within screen buffer
1076*35139Smarc * if <c> is non-zero then output this character
1077*35139Smarc * cursor is set to reflect the change
1078*35139Smarc */
1079*35139Smarc
1080*35139Smarc static void
1081*35139Smarc setcursor(new,c)
1082*35139Smarc register int new,c;
1083*35139Smarc {
1084*35139Smarc register int old = cursor - screen;
1085*35139Smarc if (old > new)
1086*35139Smarc {
1087*35139Smarc if ((cr_ok == NO) || ((new*2)>old))
1088*35139Smarc {
1089*35139Smarc while (old > new)
1090*35139Smarc {
1091*35139Smarc putchar('\b');
1092*35139Smarc old--;
1093*35139Smarc }
1094*35139Smarc goto skip;
1095*35139Smarc }
1096*35139Smarc putchar('\r');
1097*35139Smarc old = 0;
1098*35139Smarc }
1099*35139Smarc while (new > old)
1100*35139Smarc putchar(screen[old++]);
1101*35139Smarc skip:
1102*35139Smarc if(c)
1103*35139Smarc {
1104*35139Smarc putchar(c);
1105*35139Smarc new++;
1106*35139Smarc }
1107*35139Smarc cursor = screen+new;
1108*35139Smarc return;
1109*35139Smarc }
1110*35139Smarc
1111*35139Smarc #ifdef MULTIBYTE
1112*35139Smarc static int print(c)
1113*35139Smarc register int c;
1114*35139Smarc {
1115*35139Smarc return((c&~STRIP)==0 && isprint(c));
1116*35139Smarc }
1117*35139Smarc
1118*35139Smarc static int isword(i)
1119*35139Smarc register int i;
1120*35139Smarc {
1121*35139Smarc register int c = drawbuff[i];
1122*35139Smarc return((c&~STRIP) || isalnum(c));
1123*35139Smarc }
1124*35139Smarc #endif /* MULTIBYTE */
1125