14887Schin /***********************************************************************
24887Schin * *
34887Schin * This software is part of the ast package *
4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1982-2010 AT&T Intellectual Property *
54887Schin * and is licensed under the *
64887Schin * Common Public License, Version 1.0 *
78462SApril.Chin@Sun.COM * by AT&T Intellectual Property *
84887Schin * *
94887Schin * A copy of the License is available at *
104887Schin * http://www.opensource.org/licenses/cpl1.0.txt *
114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
124887Schin * *
134887Schin * Information and Software Systems Research *
144887Schin * AT&T Research *
154887Schin * Florham Park NJ *
164887Schin * *
174887Schin * David Korn <dgk@research.att.com> *
184887Schin * *
194887Schin ***********************************************************************/
204887Schin #pragma prototyped
214887Schin /* Original version by Michael T. Veach
224887Schin * Adapted for ksh by David Korn */
234887Schin /* EMACS_MODES: c tabstop=4
244887Schin
254887Schin One line screen editor for any program
264887Schin
274887Schin */
284887Schin
294887Schin
304887Schin /* The following is provided by:
314887Schin *
324887Schin * Matthijs N. Melchior
334887Schin * AT&T Network Systems International
344887Schin * APT Nederland
354887Schin * HV BZ335 x2962
364887Schin * hvlpb!mmelchio
374887Schin *
384887Schin * These are now on by default
394887Schin *
404887Schin * ESH_NFIRST
414887Schin * - A ^N as first history related command after the prompt will move
424887Schin * to the next command relative to the last known history position.
434887Schin * It will not start at the position where the last command was entered
444887Schin * as is done by the ^P command. Every history related command will
454887Schin * set both the current and last position. Executing a command will
464887Schin * only set the current position.
474887Schin *
484887Schin * ESH_KAPPEND
494887Schin * - Successive kill and delete commands will accumulate their data
504887Schin * in the kill buffer, by appending or prepending as appropriate.
514887Schin * This mode will be reset by any command not adding something to the
524887Schin * kill buffer.
534887Schin *
544887Schin * ESH_BETTER
554887Schin * - Some enhancements:
564887Schin * - argument for a macro is passed to its replacement
574887Schin * - ^X^H command to find out about history position (debugging)
584887Schin * - ^X^D command to show any debugging info
594887Schin *
604887Schin * I do not pretend these for changes are completely independent,
614887Schin * but you can use them to seperate features.
624887Schin */
634887Schin
644887Schin #include <ast.h>
654887Schin #include "FEATURE/cmds"
664887Schin #if KSHELL
674887Schin # include "defs.h"
6810898Sroland.mainz@nrubsig.org #else
6910898Sroland.mainz@nrubsig.org # include <ctype.h>
704887Schin #endif /* KSHELL */
714887Schin #include "io.h"
724887Schin
734887Schin #include "history.h"
744887Schin #include "edit.h"
754887Schin #include "terminal.h"
764887Schin
774887Schin #define ESH_NFIRST
784887Schin #define ESH_KAPPEND
794887Schin #define ESH_BETTER
804887Schin
814887Schin #undef putchar
824887Schin #define putchar(ed,c) ed_putchar(ed,c)
834887Schin #define beep() ed_ringbell()
844887Schin
854887Schin
864887Schin #if SHOPT_MULTIBYTE
874887Schin # define gencpy(a,b) ed_gencpy(a,b)
884887Schin # define genncpy(a,b,n) ed_genncpy(a,b,n)
894887Schin # define genlen(str) ed_genlen(str)
904887Schin static int print(int);
914887Schin static int _isword(int);
924887Schin # define isword(c) _isword(out[c])
934887Schin
944887Schin #else
954887Schin # define gencpy(a,b) strcpy((char*)(a),(char*)(b))
964887Schin # define genncpy(a,b,n) strncpy((char*)(a),(char*)(b),n)
974887Schin # define genlen(str) strlen(str)
984887Schin # define print(c) isprint(c)
994887Schin # define isword(c) (isalnum(out[c]) || (out[c]=='_'))
1004887Schin #endif /*SHOPT_MULTIBYTE */
1014887Schin
1024887Schin typedef struct _emacs_
1034887Schin {
1044887Schin genchar *screen; /* pointer to window buffer */
1054887Schin genchar *cursor; /* Cursor in real screen */
1064887Schin int mark;
1074887Schin int in_mult;
1084887Schin char cr_ok;
1094887Schin char CntrlO;
1104887Schin char overflow; /* Screen overflow flag set */
1114887Schin char scvalid; /* Screen is up to date */
1128462SApril.Chin@Sun.COM char lastdraw; /* last update type */
1134887Schin int offset; /* Screen offset */
1144887Schin enum
1154887Schin {
1164887Schin CRT=0, /* Crt terminal */
1174887Schin PAPER /* Paper terminal */
1184887Schin } terminal;
1194887Schin Histloc_t _location;
1204887Schin int prevdirection;
1214887Schin Edit_t *ed; /* pointer to edit data */
1224887Schin } Emacs_t;
1234887Schin
1244887Schin #define editb (*ep->ed)
1254887Schin #define eol editb.e_eol
1264887Schin #define cur editb.e_cur
1274887Schin #define hline editb.e_hline
1284887Schin #define hloff editb.e_hloff
1294887Schin #define hismin editb.e_hismin
1304887Schin #define usrkill editb.e_kill
1314887Schin #define usrlnext editb.e_lnext
1324887Schin #define usreof editb.e_eof
1334887Schin #define usrerase editb.e_erase
1344887Schin #define crallowed editb.e_crlf
1354887Schin #define Prompt editb.e_prompt
1364887Schin #define plen editb.e_plen
1374887Schin #define kstack editb.e_killbuf
1384887Schin #define lstring editb.e_search
1394887Schin #define lookahead editb.e_lookahead
1404887Schin #define env editb.e_env
1414887Schin #define raw editb.e_raw
1424887Schin #define histlines editb.e_hismax
1434887Schin #define w_size editb.e_wsize
1444887Schin #define drawbuff editb.e_inbuf
1454887Schin #define killing editb.e_mode
1464887Schin #define location ep->_location
1474887Schin
1484887Schin #define LBUF 100
1494887Schin #define KILLCHAR UKILL
1504887Schin #define ERASECHAR UERASE
1514887Schin #define EOFCHAR UEOF
1524887Schin #define LNEXTCHAR ULNEXT
1534887Schin #define DELETE ('a'==97?0177:7)
1544887Schin
1554887Schin /**********************
1564887Schin A large lookahead helps when the user is inserting
1574887Schin characters in the middle of the line.
1584887Schin ************************/
1594887Schin
1604887Schin
1614887Schin typedef enum
1624887Schin {
1634887Schin FIRST, /* First time thru for logical line, prompt on screen */
1644887Schin REFRESH, /* Redraw entire screen */
1654887Schin APPEND, /* Append char before cursor to screen */
1664887Schin UPDATE, /* Update the screen as need be */
1674887Schin FINAL /* Update screen even if pending look ahead */
1684887Schin } Draw_t;
1694887Schin
1704887Schin static void draw(Emacs_t*,Draw_t);
1714887Schin static int escape(Emacs_t*,genchar*, int);
1724887Schin static void putstring(Emacs_t*,char*);
1734887Schin static void search(Emacs_t*,genchar*,int);
1744887Schin static void setcursor(Emacs_t*,int, int);
1754887Schin static void show_info(Emacs_t*,const char*);
1764887Schin static void xcommands(Emacs_t*,int);
1774887Schin
ed_emacsread(void * context,int fd,char * buff,int scend,int reedit)1784887Schin int ed_emacsread(void *context, int fd,char *buff,int scend, int reedit)
1794887Schin {
1804887Schin Edit_t *ed = (Edit_t*)context;
1814887Schin register int c;
1824887Schin register int i;
1834887Schin register genchar *out;
1844887Schin register int count;
1854887Schin register Emacs_t *ep = ed->e_emacs;
1864887Schin int adjust,oadjust;
1874887Schin char backslash;
1884887Schin genchar *kptr;
1894887Schin char prompt[PRSIZE];
1904887Schin genchar Screen[MAXLINE];
1914887Schin if(!ep)
1924887Schin {
1934887Schin ep = ed->e_emacs = newof(0,Emacs_t,1,0);
1944887Schin ep->ed = ed;
1954887Schin ep->prevdirection = 1;
1964887Schin location.hist_command = -5;
1974887Schin }
1984887Schin Prompt = prompt;
1994887Schin ep->screen = Screen;
2008462SApril.Chin@Sun.COM ep->lastdraw = FINAL;
2014887Schin if(tty_raw(ERRIO,0) < 0)
2024887Schin {
2034887Schin return(reedit?reedit:ed_read(context, fd,buff,scend,0));
2044887Schin }
2054887Schin raw = 1;
2064887Schin /* This mess in case the read system call fails */
2074887Schin
2084887Schin ed_setup(ep->ed,fd,reedit);
2094887Schin out = (genchar*)buff;
2104887Schin #if SHOPT_MULTIBYTE
21110898Sroland.mainz@nrubsig.org out = (genchar*)roundof(buff-(char*)0,sizeof(genchar));
21210898Sroland.mainz@nrubsig.org if(reedit)
21310898Sroland.mainz@nrubsig.org ed_internal(buff,out);
2144887Schin #endif /* SHOPT_MULTIBYTE */
2154887Schin if(!kstack)
2164887Schin {
2174887Schin kstack = (genchar*)malloc(CHARSIZE*MAXLINE);
2184887Schin kstack[0] = '\0';
2194887Schin }
2204887Schin drawbuff = out;
2214887Schin #ifdef ESH_NFIRST
2224887Schin if (location.hist_command == -5) /* to be initialized */
2234887Schin {
2244887Schin kstack[0] = '\0'; /* also clear kstack... */
2254887Schin location.hist_command = hline;
2264887Schin location.hist_line = hloff;
2274887Schin }
2284887Schin if (location.hist_command <= hismin) /* don't start below minimum */
2294887Schin {
2304887Schin location.hist_command = hismin + 1;
2314887Schin location.hist_line = 0;
2324887Schin }
2334887Schin ep->in_mult = hloff; /* save pos in last command */
2344887Schin #endif /* ESH_NFIRST */
2354887Schin i = sigsetjmp(env,0);
2364887Schin if (i !=0)
2374887Schin {
2388462SApril.Chin@Sun.COM if(ep->ed->e_multiline)
2398462SApril.Chin@Sun.COM {
2408462SApril.Chin@Sun.COM cur = eol;
2418462SApril.Chin@Sun.COM draw(ep,FINAL);
2428462SApril.Chin@Sun.COM ed_flush(ep->ed);
2438462SApril.Chin@Sun.COM }
2444887Schin tty_cooked(ERRIO);
2454887Schin if (i == UEOF)
2464887Schin {
2474887Schin return(0); /* EOF */
2484887Schin }
2494887Schin return(-1); /* some other error */
2504887Schin }
2514887Schin out[reedit] = 0;
2524887Schin if(scend+plen > (MAXLINE-2))
2534887Schin scend = (MAXLINE-2)-plen;
2544887Schin ep->mark = 0;
2554887Schin cur = eol;
2564887Schin draw(ep,reedit?REFRESH:FIRST);
2574887Schin adjust = -1;
2584887Schin backslash = 0;
2594887Schin if (ep->CntrlO)
2604887Schin {
2614887Schin #ifdef ESH_NFIRST
2624887Schin ed_ungetchar(ep->ed,cntl('N'));
2634887Schin #else
2644887Schin location = hist_locate(sh.hist_ptr,location.hist_command,location.hist_line,1);
2654887Schin if (location.hist_command < histlines)
2664887Schin {
2674887Schin hline = location.hist_command;
2684887Schin hloff = location.hist_line;
2694887Schin hist_copy((char*)kstack,MAXLINE, hline,hloff);
2704887Schin # if SHOPT_MULTIBYTE
2714887Schin ed_internal((char*)kstack,kstack);
2724887Schin # endif /* SHOPT_MULTIBYTE */
2734887Schin ed_ungetchar(ep->ed,cntl('Y'));
2744887Schin }
2754887Schin #endif /* ESH_NFIRST */
2764887Schin }
2774887Schin ep->CntrlO = 0;
2784887Schin while ((c = ed_getchar(ep->ed,0)) != (-1))
2794887Schin {
2804887Schin if (backslash)
2814887Schin {
2824887Schin backslash = 0;
2834887Schin if (c==usrerase||c==usrkill||(!print(c) &&
2844887Schin (c!='\r'&&c!='\n')))
2854887Schin {
2864887Schin /* accept a backslashed character */
2874887Schin cur--;
2884887Schin out[cur++] = c;
2894887Schin out[eol] = '\0';
2904887Schin draw(ep,APPEND);
2914887Schin continue;
2924887Schin }
2934887Schin }
2944887Schin if (c == usrkill)
2954887Schin {
2964887Schin c = KILLCHAR ;
2974887Schin }
2984887Schin else if (c == usrerase)
2994887Schin {
3004887Schin c = ERASECHAR ;
3014887Schin }
3024887Schin else if (c == usrlnext)
3034887Schin {
3044887Schin c = LNEXTCHAR ;
3054887Schin }
3064887Schin else if ((c == usreof)&&(eol == 0))
3074887Schin {
3084887Schin c = EOFCHAR;
3094887Schin }
3104887Schin #ifdef ESH_KAPPEND
3114887Schin if (--killing <= 0) /* reset killing flag */
3124887Schin killing = 0;
3134887Schin #endif
3144887Schin oadjust = count = adjust;
3154887Schin if(count<0)
3164887Schin count = 1;
3174887Schin adjust = -1;
3184887Schin i = cur;
3194887Schin switch(c)
3204887Schin {
3214887Schin case LNEXTCHAR:
3224887Schin c = ed_getchar(ep->ed,2);
3234887Schin goto do_default_processing;
3244887Schin case cntl('V'):
3254887Schin show_info(ep,fmtident(e_version));
3264887Schin continue;
3274887Schin case '\0':
3284887Schin ep->mark = i;
3294887Schin continue;
3304887Schin case cntl('X'):
3314887Schin xcommands(ep,count);
3324887Schin continue;
3334887Schin case EOFCHAR:
3344887Schin ed_flush(ep->ed);
3354887Schin tty_cooked(ERRIO);
3364887Schin return(0);
3374887Schin #ifdef u370
3384887Schin case cntl('S') :
3394887Schin case cntl('Q') :
3404887Schin continue;
3414887Schin #endif /* u370 */
3424887Schin case '\t':
3434887Schin if(cur>0 && ep->ed->sh->nextprompt)
3444887Schin {
3454887Schin if(ep->ed->e_tabcount==0)
3464887Schin {
3474887Schin ep->ed->e_tabcount=1;
3484887Schin ed_ungetchar(ep->ed,ESC);
3494887Schin goto do_escape;
3504887Schin }
3514887Schin else if(ep->ed->e_tabcount==1)
3524887Schin {
3534887Schin ed_ungetchar(ep->ed,'=');
3544887Schin goto do_escape;
3554887Schin }
3564887Schin ep->ed->e_tabcount = 0;
3574887Schin }
3584887Schin do_default_processing:
3594887Schin default:
3604887Schin
3614887Schin if ((eol+1) >= (scend)) /* will not fit on line */
3624887Schin {
3634887Schin ed_ungetchar(ep->ed,c); /* save character for next line */
3644887Schin goto process;
3654887Schin }
3664887Schin for(i= ++eol; i>cur; i--)
3674887Schin out[i] = out[i-1];
3684887Schin backslash = (c == '\\');
3694887Schin out[cur++] = c;
3704887Schin draw(ep,APPEND);
3714887Schin continue;
3724887Schin case cntl('Y') :
3734887Schin {
3744887Schin c = genlen(kstack);
3754887Schin if ((c + eol) > scend)
3764887Schin {
3774887Schin beep();
3784887Schin continue;
3794887Schin }
3804887Schin ep->mark = i;
3814887Schin for(i=eol;i>=cur;i--)
3824887Schin out[c+i] = out[i];
3834887Schin kptr=kstack;
3844887Schin while (i = *kptr++)
3854887Schin out[cur++] = i;
3864887Schin draw(ep,UPDATE);
3874887Schin eol = genlen(out);
3884887Schin continue;
3894887Schin }
3904887Schin case '\n':
3914887Schin case '\r':
3924887Schin c = '\n';
3934887Schin goto process;
3944887Schin
3954887Schin case DELETE: /* delete char 0x7f */
3964887Schin case '\b': /* backspace, ^h */
3974887Schin case ERASECHAR :
3984887Schin if (count > i)
3994887Schin count = i;
4004887Schin #ifdef ESH_KAPPEND
4014887Schin kptr = &kstack[count]; /* move old contents here */
4024887Schin if (killing) /* prepend to killbuf */
4034887Schin {
4044887Schin c = genlen(kstack) + CHARSIZE; /* include '\0' */
4054887Schin while(c--) /* copy stuff */
4064887Schin kptr[c] = kstack[c];
4074887Schin }
4084887Schin else
4094887Schin *kptr = 0; /* this is end of data */
4104887Schin killing = 2; /* we are killing */
4114887Schin i -= count;
4124887Schin eol -= count;
4134887Schin genncpy(kstack,out+i,cur-i);
4144887Schin #else
4154887Schin while ((count--)&&(i>0))
4164887Schin {
4174887Schin i--;
4184887Schin eol--;
4194887Schin }
4204887Schin genncpy(kstack,out+i,cur-i);
4214887Schin kstack[cur-i] = 0;
4224887Schin #endif /* ESH_KAPPEND */
4234887Schin gencpy(out+i,out+cur);
4244887Schin ep->mark = i;
4254887Schin goto update;
4264887Schin case cntl('W') :
4274887Schin #ifdef ESH_KAPPEND
4284887Schin ++killing; /* keep killing flag */
4294887Schin #endif
4304887Schin if (ep->mark > eol )
4314887Schin ep->mark = eol;
4324887Schin if (ep->mark == i)
4334887Schin continue;
4344887Schin if (ep->mark > i)
4354887Schin {
4364887Schin adjust = ep->mark - i;
4374887Schin ed_ungetchar(ep->ed,cntl('D'));
4384887Schin continue;
4394887Schin }
4404887Schin adjust = i - ep->mark;
4414887Schin ed_ungetchar(ep->ed,usrerase);
4424887Schin continue;
4434887Schin case cntl('D') :
4444887Schin ep->mark = i;
4454887Schin #ifdef ESH_KAPPEND
4464887Schin if (killing)
4474887Schin kptr = &kstack[genlen(kstack)]; /* append here */
4484887Schin else
4494887Schin kptr = kstack;
4504887Schin killing = 2; /* we are now killing */
4514887Schin #else
4524887Schin kptr = kstack;
4534887Schin #endif /* ESH_KAPPEND */
4544887Schin while ((count--)&&(eol>0)&&(i<eol))
4554887Schin {
4564887Schin *kptr++ = out[i];
4574887Schin eol--;
4584887Schin while(1)
4594887Schin {
4604887Schin if ((out[i] = out[(i+1)])==0)
4614887Schin break;
4624887Schin i++;
4634887Schin }
4644887Schin i = cur;
4654887Schin }
4664887Schin *kptr = '\0';
4674887Schin goto update;
4684887Schin case cntl('C') :
4694887Schin case cntl('F') :
4704887Schin {
4714887Schin int cntlC = (c==cntl('C'));
4724887Schin while (count-- && eol>i)
4734887Schin {
4744887Schin if (cntlC)
4754887Schin {
4764887Schin c = out[i];
4774887Schin #if SHOPT_MULTIBYTE
4784887Schin if((c&~STRIP)==0 && islower(c))
4794887Schin #else
4804887Schin if(islower(c))
4814887Schin #endif /* SHOPT_MULTIBYTE */
4824887Schin {
4834887Schin c += 'A' - 'a';
4844887Schin out[i] = c;
4854887Schin }
4864887Schin }
4874887Schin i++;
4884887Schin }
4894887Schin goto update;
4904887Schin }
4914887Schin case cntl(']') :
4924887Schin c = ed_getchar(ep->ed,1);
4934887Schin if ((count == 0) || (count > eol))
4944887Schin {
4954887Schin beep();
4964887Schin continue;
4974887Schin }
4984887Schin if (out[i])
4994887Schin i++;
5004887Schin while (i < eol)
5014887Schin {
5024887Schin if (out[i] == c && --count==0)
5034887Schin goto update;
5044887Schin i++;
5054887Schin }
5064887Schin i = 0;
5074887Schin while (i < cur)
5084887Schin {
5094887Schin if (out[i] == c && --count==0)
5104887Schin break;
5114887Schin i++;
5124887Schin };
5134887Schin
5144887Schin update:
5154887Schin cur = i;
5164887Schin draw(ep,UPDATE);
5174887Schin continue;
5184887Schin
5194887Schin case cntl('B') :
5204887Schin if (count > i)
5214887Schin count = i;
5224887Schin i -= count;
5234887Schin goto update;
5244887Schin case cntl('T') :
5254887Schin if ((sh_isoption(SH_EMACS))&& (eol!=i))
5264887Schin i++;
5274887Schin if (i >= 2)
5284887Schin {
5294887Schin c = out[i - 1];
5304887Schin out[i-1] = out[i-2];
5314887Schin out[i-2] = c;
5324887Schin }
5334887Schin else
5344887Schin {
5354887Schin if(sh_isoption(SH_EMACS))
5364887Schin i--;
5374887Schin beep();
5384887Schin continue;
5394887Schin }
5404887Schin goto update;
5414887Schin case cntl('A') :
5424887Schin i = 0;
5434887Schin goto update;
5444887Schin case cntl('E') :
5454887Schin i = eol;
5464887Schin goto update;
5474887Schin case cntl('U') :
5484887Schin adjust = 4*count;
5494887Schin continue;
5504887Schin case KILLCHAR :
5514887Schin cur = 0;
5524887Schin oadjust = -1;
5534887Schin case cntl('K') :
5544887Schin if(oadjust >= 0)
5554887Schin {
5564887Schin #ifdef ESH_KAPPEND
5574887Schin killing = 2; /* set killing signal */
5584887Schin #endif
5594887Schin ep->mark = count;
5604887Schin ed_ungetchar(ep->ed,cntl('W'));
5614887Schin continue;
5624887Schin }
5634887Schin i = cur;
5644887Schin eol = i;
5654887Schin ep->mark = i;
5664887Schin #ifdef ESH_KAPPEND
5674887Schin if (killing) /* append to kill buffer */
5684887Schin gencpy(&kstack[genlen(kstack)], &out[i]);
5694887Schin else
5704887Schin gencpy(kstack,&out[i]);
5714887Schin killing = 2; /* set killing signal */
5724887Schin #else
5734887Schin gencpy(kstack,&out[i]);
5744887Schin #endif /* ESH_KAPPEND */
5754887Schin out[i] = 0;
5764887Schin draw(ep,UPDATE);
5774887Schin if (c == KILLCHAR)
5784887Schin {
5794887Schin if (ep->terminal == PAPER)
5804887Schin {
5814887Schin putchar(ep->ed,'\n');
5824887Schin putstring(ep,Prompt);
5834887Schin }
5844887Schin c = ed_getchar(ep->ed,0);
5854887Schin if (c != usrkill)
5864887Schin {
5874887Schin ed_ungetchar(ep->ed,c);
5884887Schin continue;
5894887Schin }
5904887Schin if (ep->terminal == PAPER)
5914887Schin ep->terminal = CRT;
5924887Schin else
5934887Schin {
5944887Schin ep->terminal = PAPER;
5954887Schin putchar(ep->ed,'\n');
5964887Schin putstring(ep,Prompt);
5974887Schin }
5984887Schin }
5994887Schin continue;
6004887Schin case cntl('L'):
6018462SApril.Chin@Sun.COM if(!ep->ed->e_nocrnl)
6028462SApril.Chin@Sun.COM ed_crlf(ep->ed);
6034887Schin draw(ep,REFRESH);
6048462SApril.Chin@Sun.COM ep->ed->e_nocrnl = 0;
6054887Schin continue;
6064887Schin case cntl('[') :
6074887Schin do_escape:
6084887Schin adjust = escape(ep,out,oadjust);
6094887Schin continue;
6104887Schin case cntl('R') :
6114887Schin search(ep,out,count);
6124887Schin goto drawline;
6134887Schin case cntl('P') :
6144887Schin if (count <= hloff)
6154887Schin hloff -= count;
6164887Schin else
6174887Schin {
6184887Schin hline -= count - hloff;
6194887Schin hloff = 0;
6204887Schin }
6214887Schin #ifdef ESH_NFIRST
6224887Schin if (hline <= hismin)
6234887Schin #else
6244887Schin if (hline < hismin)
6254887Schin #endif /* ESH_NFIRST */
6264887Schin {
6274887Schin hline = hismin+1;
6284887Schin beep();
6294887Schin #ifndef ESH_NFIRST
6304887Schin continue;
6314887Schin #endif
6324887Schin }
6334887Schin goto common;
6344887Schin
6354887Schin case cntl('O') :
6364887Schin location.hist_command = hline;
6374887Schin location.hist_line = hloff;
6384887Schin ep->CntrlO = 1;
6394887Schin c = '\n';
6404887Schin goto process;
6414887Schin case cntl('N') :
6424887Schin #ifdef ESH_NFIRST
6434887Schin hline = location.hist_command; /* start at saved position */
6444887Schin hloff = location.hist_line;
6454887Schin #endif /* ESH_NFIRST */
6464887Schin location = hist_locate(sh.hist_ptr,hline,hloff,count);
6474887Schin if (location.hist_command > histlines)
6484887Schin {
6494887Schin beep();
6504887Schin #ifdef ESH_NFIRST
6514887Schin location.hist_command = histlines;
6524887Schin location.hist_line = ep->in_mult;
6534887Schin #else
6544887Schin continue;
6554887Schin #endif /* ESH_NFIRST */
6564887Schin }
6574887Schin hline = location.hist_command;
6584887Schin hloff = location.hist_line;
6594887Schin common:
6604887Schin #ifdef ESH_NFIRST
6614887Schin location.hist_command = hline; /* save current position */
6624887Schin location.hist_line = hloff;
6634887Schin #endif
6648462SApril.Chin@Sun.COM cur = 0;
6658462SApril.Chin@Sun.COM draw(ep,UPDATE);
6664887Schin hist_copy((char*)out,MAXLINE, hline,hloff);
6674887Schin #if SHOPT_MULTIBYTE
6684887Schin ed_internal((char*)(out),out);
6694887Schin #endif /* SHOPT_MULTIBYTE */
6704887Schin drawline:
6714887Schin eol = genlen(out);
6724887Schin cur = eol;
6734887Schin draw(ep,UPDATE);
6744887Schin continue;
6754887Schin }
6764887Schin
6774887Schin }
6784887Schin
6794887Schin process:
6804887Schin
6814887Schin if (c == (-1))
6824887Schin {
6834887Schin lookahead = 0;
6844887Schin beep();
6854887Schin *out = '\0';
6864887Schin }
6874887Schin draw(ep,FINAL);
6884887Schin tty_cooked(ERRIO);
6894887Schin if(ed->e_nlist)
6904887Schin {
6914887Schin ed->e_nlist = 0;
6924887Schin stakset(ed->e_stkptr,ed->e_stkoff);
6934887Schin }
6944887Schin if(c == '\n')
6954887Schin {
6964887Schin out[eol++] = '\n';
6974887Schin out[eol] = '\0';
6984887Schin ed_crlf(ep->ed);
6994887Schin }
7004887Schin #if SHOPT_MULTIBYTE
7014887Schin ed_external(out,buff);
7024887Schin #endif /* SHOPT_MULTIBYTE */
7034887Schin i = strlen(buff);
7044887Schin if (i)
7054887Schin return(i);
7064887Schin return(-1);
7074887Schin }
7084887Schin
show_info(Emacs_t * ep,const char * str)7094887Schin static void show_info(Emacs_t *ep,const char *str)
7104887Schin {
7114887Schin register genchar *out = drawbuff;
7124887Schin register int c;
7134887Schin genchar string[LBUF];
7144887Schin int sav_cur = cur;
7154887Schin /* save current line */
7164887Schin genncpy(string,out,sizeof(string)/sizeof(*string));
7174887Schin *out = 0;
7184887Schin cur = 0;
7194887Schin #if SHOPT_MULTIBYTE
7204887Schin ed_internal(str,out);
7214887Schin #else
7224887Schin gencpy(out,str);
7234887Schin #endif /* SHOPT_MULTIBYTE */
7244887Schin draw(ep,UPDATE);
7254887Schin c = ed_getchar(ep->ed,0);
7264887Schin if(c!=' ')
7274887Schin ed_ungetchar(ep->ed,c);
7284887Schin /* restore line */
7294887Schin cur = sav_cur;
7304887Schin genncpy(out,string,sizeof(string)/sizeof(*string));
7314887Schin draw(ep,UPDATE);
7324887Schin }
7334887Schin
putstring(Emacs_t * ep,register char * sp)7344887Schin static void putstring(Emacs_t* ep,register char *sp)
7354887Schin {
7364887Schin register int c;
7374887Schin while (c= *sp++)
7384887Schin putchar(ep->ed,c);
7394887Schin }
7404887Schin
7414887Schin
escape(register Emacs_t * ep,register genchar * out,int count)7424887Schin static int escape(register Emacs_t* ep,register genchar *out,int count)
7434887Schin {
7444887Schin register int i,value;
7454887Schin int digit,ch;
7464887Schin digit = 0;
7474887Schin value = 0;
7484887Schin while ((i=ed_getchar(ep->ed,0)),isdigit(i))
7494887Schin {
7504887Schin value *= 10;
7514887Schin value += (i - '0');
7524887Schin digit = 1;
7534887Schin }
7544887Schin if (digit)
7554887Schin {
7564887Schin ed_ungetchar(ep->ed,i) ;
7574887Schin #ifdef ESH_KAPPEND
7584887Schin ++killing; /* don't modify killing signal */
7594887Schin #endif
7604887Schin return(value);
7614887Schin }
7624887Schin value = count;
7634887Schin if(value<0)
7644887Schin value = 1;
7654887Schin switch(ch=i)
7664887Schin {
7674887Schin case cntl('V'):
7684887Schin show_info(ep,fmtident(e_version));
7694887Schin return(-1);
7704887Schin case ' ':
7714887Schin ep->mark = cur;
7724887Schin return(-1);
7734887Schin
7744887Schin #ifdef ESH_KAPPEND
7754887Schin case '+': /* M-+ = append next kill */
7764887Schin killing = 2;
7774887Schin return -1; /* no argument for next command */
7784887Schin #endif
7794887Schin
7804887Schin case 'p': /* M-p == ^W^Y (copy stack == kill & yank) */
7814887Schin ed_ungetchar(ep->ed,cntl('Y'));
7824887Schin ed_ungetchar(ep->ed,cntl('W'));
7834887Schin #ifdef ESH_KAPPEND
7844887Schin killing = 0; /* start fresh */
7854887Schin #endif
7864887Schin return(-1);
7874887Schin
7884887Schin case 'l': /* M-l == lower-case */
7894887Schin case 'd':
7904887Schin case 'c':
7914887Schin case 'f':
7924887Schin {
7934887Schin i = cur;
7944887Schin while(value-- && i<eol)
7954887Schin {
7964887Schin while ((out[i])&&(!isword(i)))
7974887Schin i++;
7984887Schin while ((out[i])&&(isword(i)))
7994887Schin i++;
8004887Schin }
8014887Schin if(ch=='l')
8024887Schin {
8034887Schin value = i-cur;
8044887Schin while (value-- > 0)
8054887Schin {
8064887Schin i = out[cur];
8074887Schin #if SHOPT_MULTIBYTE
8084887Schin if((i&~STRIP)==0 && isupper(i))
8094887Schin #else
8104887Schin if(isupper(i))
8114887Schin #endif /* SHOPT_MULTIBYTE */
8124887Schin {
8134887Schin i += 'a' - 'A';
8144887Schin out[cur] = i;
8154887Schin }
8164887Schin cur++;
8174887Schin }
8184887Schin draw(ep,UPDATE);
8194887Schin return(-1);
8204887Schin }
8214887Schin
8224887Schin else if(ch=='f')
8234887Schin goto update;
8244887Schin else if(ch=='c')
8254887Schin {
8264887Schin ed_ungetchar(ep->ed,cntl('C'));
8274887Schin return(i-cur);
8284887Schin }
8294887Schin else
8304887Schin {
8314887Schin if (i-cur)
8324887Schin {
8334887Schin ed_ungetchar(ep->ed,cntl('D'));
8344887Schin #ifdef ESH_KAPPEND
8354887Schin ++killing; /* keep killing signal */
8364887Schin #endif
8374887Schin return(i-cur);
8384887Schin }
8394887Schin beep();
8404887Schin return(-1);
8414887Schin }
8424887Schin }
8434887Schin
8444887Schin
8454887Schin case 'b':
8464887Schin case DELETE :
8474887Schin case '\b':
8484887Schin case 'h':
8494887Schin {
8504887Schin i = cur;
8514887Schin while(value-- && i>0)
8524887Schin {
8534887Schin i--;
8544887Schin while ((i>0)&&(!isword(i)))
8554887Schin i--;
8564887Schin while ((i>0)&&(isword(i-1)))
8574887Schin i--;
8584887Schin }
8594887Schin if(ch=='b')
8604887Schin goto update;
8614887Schin else
8624887Schin {
8634887Schin ed_ungetchar(ep->ed,usrerase);
8644887Schin #ifdef ESH_KAPPEND
8654887Schin ++killing;
8664887Schin #endif
8674887Schin return(cur-i);
8684887Schin }
8694887Schin }
8704887Schin
8714887Schin case '>':
8724887Schin ed_ungetchar(ep->ed,cntl('N'));
8734887Schin #ifdef ESH_NFIRST
8744887Schin if (ep->in_mult)
8754887Schin {
8764887Schin location.hist_command = histlines;
8774887Schin location.hist_line = ep->in_mult - 1;
8784887Schin }
8794887Schin else
8804887Schin {
8814887Schin location.hist_command = histlines - 1;
8824887Schin location.hist_line = 0;
8834887Schin }
8844887Schin #else
8854887Schin hline = histlines-1;
8864887Schin hloff = 0;
8874887Schin #endif /* ESH_NFIRST */
8884887Schin return(0);
8894887Schin
8904887Schin case '<':
8914887Schin ed_ungetchar(ep->ed,cntl('P'));
8924887Schin hloff = 0;
8934887Schin #ifdef ESH_NFIRST
8944887Schin hline = hismin + 1;
8954887Schin return 0;
8964887Schin #else
8974887Schin return(hline-hismin);
8984887Schin #endif /* ESH_NFIRST */
8994887Schin
9004887Schin
9014887Schin case '#':
9024887Schin ed_ungetchar(ep->ed,'\n');
9034887Schin ed_ungetchar(ep->ed,(out[0]=='#')?cntl('D'):'#');
9044887Schin ed_ungetchar(ep->ed,cntl('A'));
9054887Schin return(-1);
9064887Schin case '_' :
9074887Schin case '.' :
9084887Schin {
9094887Schin genchar name[MAXLINE];
9104887Schin char buf[MAXLINE];
9114887Schin char *ptr;
9124887Schin ptr = hist_word(buf,MAXLINE,(count?count:-1));
9134887Schin if(ptr==0)
9144887Schin {
9154887Schin beep();
9164887Schin break;
9174887Schin }
9184887Schin if ((eol - cur) >= sizeof(name))
9194887Schin {
9204887Schin beep();
9214887Schin return(-1);
9224887Schin }
9234887Schin ep->mark = cur;
9244887Schin gencpy(name,&out[cur]);
9254887Schin while(*ptr)
9264887Schin {
9274887Schin out[cur++] = *ptr++;
9284887Schin eol++;
9294887Schin }
9304887Schin gencpy(&out[cur],name);
9314887Schin draw(ep,UPDATE);
9324887Schin return(-1);
9334887Schin }
9344887Schin #if KSHELL
9354887Schin
9364887Schin /* file name expansion */
9374887Schin case cntl('[') : /* filename completion */
9384887Schin i = '\\';
9394887Schin case '*': /* filename expansion */
9404887Schin case '=': /* escape = - list all matching file names */
9414887Schin ep->mark = cur;
9424887Schin if(ed_expand(ep->ed,(char*)out,&cur,&eol,i,count) < 0)
9434887Schin {
9444887Schin if(ep->ed->e_tabcount==1)
9454887Schin {
9464887Schin ep->ed->e_tabcount=2;
9474887Schin ed_ungetchar(ep->ed,cntl('\t'));
9484887Schin return(-1);
9494887Schin }
9504887Schin beep();
9514887Schin }
9524887Schin else if(i=='=')
9534887Schin {
9544887Schin draw(ep,REFRESH);
9554887Schin if(count>0)
9564887Schin ep->ed->e_tabcount=0;
9574887Schin else
9584887Schin {
9594887Schin i=ed_getchar(ep->ed,0);
9604887Schin ed_ungetchar(ep->ed,i);
9614887Schin if(isdigit(i))
9624887Schin ed_ungetchar(ep->ed,ESC);
9634887Schin }
9644887Schin }
9654887Schin else
9664887Schin {
9674887Schin if(i=='\\' && cur>ep->mark && (out[cur-1]=='/' || out[cur-1]==' '))
9684887Schin ep->ed->e_tabcount=0;
9694887Schin draw(ep,UPDATE);
9704887Schin }
9714887Schin return(-1);
9724887Schin
9734887Schin /* search back for character */
9744887Schin case cntl(']'): /* feature not in book */
9754887Schin {
9764887Schin int c = ed_getchar(ep->ed,1);
9774887Schin if ((value == 0) || (value > eol))
9784887Schin {
9794887Schin beep();
9804887Schin return(-1);
9814887Schin }
9824887Schin i = cur;
9834887Schin if (i > 0)
9844887Schin i--;
9854887Schin while (i >= 0)
9864887Schin {
9874887Schin if (out[i] == c && --value==0)
9884887Schin goto update;
9894887Schin i--;
9904887Schin }
9914887Schin i = eol;
9924887Schin while (i > cur)
9934887Schin {
9944887Schin if (out[i] == c && --value==0)
9954887Schin break;
9964887Schin i--;
9974887Schin };
9984887Schin
9994887Schin }
10004887Schin update:
10014887Schin cur = i;
10024887Schin draw(ep,UPDATE);
10034887Schin return(-1);
10044887Schin
10054887Schin #ifdef _cmd_tput
10064887Schin case cntl('L'): /* clear screen */
10074887Schin sh_trap("tput clear", 0);
10084887Schin draw(ep,REFRESH);
10094887Schin return(-1);
10104887Schin #endif
10114887Schin case '[': /* feature not in book */
10124887Schin switch(i=ed_getchar(ep->ed,1))
10134887Schin {
10144887Schin case 'A':
10158462SApril.Chin@Sun.COM if(cur>0 && eol==cur && (cur<(SEARCHSIZE-2) || ep->prevdirection == -2))
10168462SApril.Chin@Sun.COM {
10178462SApril.Chin@Sun.COM if(ep->lastdraw==APPEND && ep->prevdirection != -2)
10188462SApril.Chin@Sun.COM {
10198462SApril.Chin@Sun.COM out[cur] = 0;
10208462SApril.Chin@Sun.COM gencpy(&((genchar*)lstring)[1],out);
10218462SApril.Chin@Sun.COM #if SHOPT_MULTIBYTE
10228462SApril.Chin@Sun.COM ed_external(&((genchar*)lstring)[1],lstring+1);
10238462SApril.Chin@Sun.COM #endif /* SHOPT_MULTIBYTE */
10248462SApril.Chin@Sun.COM *lstring = '^';
10258462SApril.Chin@Sun.COM ep->prevdirection = -2;
10268462SApril.Chin@Sun.COM }
10278462SApril.Chin@Sun.COM if(*lstring)
10288462SApril.Chin@Sun.COM {
10298462SApril.Chin@Sun.COM ed_ungetchar(ep->ed,'\r');
10308462SApril.Chin@Sun.COM ed_ungetchar(ep->ed,cntl('R'));
10318462SApril.Chin@Sun.COM return(-1);
10328462SApril.Chin@Sun.COM }
10338462SApril.Chin@Sun.COM }
10348462SApril.Chin@Sun.COM *lstring = 0;
10354887Schin ed_ungetchar(ep->ed,cntl('P'));
10364887Schin return(-1);
10374887Schin case 'B':
10384887Schin ed_ungetchar(ep->ed,cntl('N'));
10394887Schin return(-1);
10404887Schin case 'C':
10414887Schin ed_ungetchar(ep->ed,cntl('F'));
10424887Schin return(-1);
10434887Schin case 'D':
10444887Schin ed_ungetchar(ep->ed,cntl('B'));
10454887Schin return(-1);
10464887Schin case 'H':
10474887Schin ed_ungetchar(ep->ed,cntl('A'));
10484887Schin return(-1);
10494887Schin case 'Y':
10504887Schin ed_ungetchar(ep->ed,cntl('E'));
10514887Schin return(-1);
10524887Schin default:
10534887Schin ed_ungetchar(ep->ed,i);
10544887Schin }
10554887Schin i = '_';
10564887Schin
10574887Schin default:
10584887Schin /* look for user defined macro definitions */
10594887Schin if(ed_macro(ep->ed,i))
10604887Schin # ifdef ESH_BETTER
10614887Schin return(count); /* pass argument to macro */
10624887Schin # else
10634887Schin return(-1);
10644887Schin # endif /* ESH_BETTER */
10654887Schin #else
10664887Schin update:
10674887Schin cur = i;
10684887Schin draw(ep,UPDATE);
10694887Schin return(-1);
10704887Schin
10714887Schin default:
10724887Schin #endif /* KSHELL */
10734887Schin beep();
10744887Schin return(-1);
10754887Schin }
107610898Sroland.mainz@nrubsig.org return(-1);
10774887Schin }
10784887Schin
10794887Schin
10804887Schin /*
10814887Schin * This routine process all commands starting with ^X
10824887Schin */
10834887Schin
xcommands(register Emacs_t * ep,int count)10844887Schin static void xcommands(register Emacs_t *ep,int count)
10854887Schin {
10864887Schin register int i = ed_getchar(ep->ed,0);
10874887Schin NOT_USED(count);
10884887Schin switch(i)
10894887Schin {
10904887Schin case cntl('X'): /* exchange dot and mark */
10914887Schin if (ep->mark > eol)
10924887Schin ep->mark = eol;
10934887Schin i = ep->mark;
10944887Schin ep->mark = cur;
10954887Schin cur = i;
10964887Schin draw(ep,UPDATE);
10974887Schin return;
10984887Schin
10994887Schin #if KSHELL
11004887Schin # ifdef ESH_BETTER
11014887Schin case cntl('E'): /* invoke emacs on current command */
11024887Schin if(ed_fulledit(ep->ed)==-1)
11034887Schin beep();
11044887Schin else
11054887Schin {
11064887Schin #if SHOPT_MULTIBYTE
11074887Schin ed_internal((char*)drawbuff,drawbuff);
11084887Schin #endif /* SHOPT_MULTIBYTE */
11094887Schin ed_ungetchar(ep->ed,'\n');
11104887Schin }
11114887Schin return;
11124887Schin
11134887Schin # define itos(i) fmtbase((long)(i),0,0)/* want signed conversion */
11144887Schin
11154887Schin case cntl('H'): /* ^X^H show history info */
11164887Schin {
11174887Schin char hbuf[MAXLINE];
11184887Schin
11194887Schin strcpy(hbuf, "Current command ");
11204887Schin strcat(hbuf, itos(hline));
11214887Schin if (hloff)
11224887Schin {
11234887Schin strcat(hbuf, " (line ");
11244887Schin strcat(hbuf, itos(hloff+1));
11254887Schin strcat(hbuf, ")");
11264887Schin }
11274887Schin if ((hline != location.hist_command) ||
11284887Schin (hloff != location.hist_line))
11294887Schin {
11304887Schin strcat(hbuf, "; Previous command ");
11314887Schin strcat(hbuf, itos(location.hist_command));
11324887Schin if (location.hist_line)
11334887Schin {
11344887Schin strcat(hbuf, " (line ");
11354887Schin strcat(hbuf, itos(location.hist_line+1));
11364887Schin strcat(hbuf, ")");
11374887Schin }
11384887Schin }
11394887Schin show_info(ep,hbuf);
11404887Schin return;
11414887Schin }
11424887Schin # if 0 /* debugging, modify as required */
11434887Schin case cntl('D'): /* ^X^D show debugging info */
11444887Schin {
11454887Schin char debugbuf[MAXLINE];
11464887Schin
11474887Schin strcpy(debugbuf, "count=");
11484887Schin strcat(debugbuf, itos(count));
11494887Schin strcat(debugbuf, " eol=");
11504887Schin strcat(debugbuf, itos(eol));
11514887Schin strcat(debugbuf, " cur=");
11524887Schin strcat(debugbuf, itos(cur));
11534887Schin strcat(debugbuf, " crallowed=");
11544887Schin strcat(debugbuf, itos(crallowed));
11554887Schin strcat(debugbuf, " plen=");
11564887Schin strcat(debugbuf, itos(plen));
11574887Schin strcat(debugbuf, " w_size=");
11584887Schin strcat(debugbuf, itos(w_size));
11594887Schin
11604887Schin show_info(ep,debugbuf);
11614887Schin return;
11624887Schin }
11634887Schin # endif /* debugging code */
11644887Schin # endif /* ESH_BETTER */
11654887Schin #endif /* KSHELL */
11664887Schin
11674887Schin default:
11684887Schin beep();
11694887Schin return;
11704887Schin }
11714887Schin }
11724887Schin
search(Emacs_t * ep,genchar * out,int direction)11734887Schin static void search(Emacs_t* ep,genchar *out,int direction)
11744887Schin {
11754887Schin #ifndef ESH_NFIRST
11764887Schin Histloc_t location;
11774887Schin #endif
11784887Schin register int i,sl;
11794887Schin genchar str_buff[LBUF];
11804887Schin register genchar *string = drawbuff;
11814887Schin /* save current line */
11824887Schin int sav_cur = cur;
11834887Schin genncpy(str_buff,string,sizeof(str_buff)/sizeof(*str_buff));
11844887Schin string[0] = '^';
11854887Schin string[1] = 'R';
11864887Schin string[2] = '\0';
11874887Schin sl = 2;
11884887Schin cur = sl;
11894887Schin draw(ep,UPDATE);
11904887Schin while ((i = ed_getchar(ep->ed,1))&&(i != '\r')&&(i != '\n'))
11914887Schin {
11924887Schin if (i==usrerase || i==DELETE || i=='\b' || i==ERASECHAR)
11934887Schin {
11944887Schin if (sl > 2)
11954887Schin {
11964887Schin string[--sl] = '\0';
11974887Schin cur = sl;
11984887Schin draw(ep,UPDATE);
11994887Schin }
12004887Schin else
12014887Schin beep();
12024887Schin continue;
12034887Schin }
12044887Schin if (i==usrkill)
12054887Schin {
12064887Schin beep();
12074887Schin goto restore;
12084887Schin }
12094887Schin if (i == '\\')
12104887Schin {
12114887Schin string[sl++] = '\\';
12124887Schin string[sl] = '\0';
12134887Schin cur = sl;
12144887Schin draw(ep,APPEND);
12154887Schin i = ed_getchar(ep->ed,1);
12164887Schin string[--sl] = '\0';
12174887Schin }
12184887Schin string[sl++] = i;
12194887Schin string[sl] = '\0';
12204887Schin cur = sl;
12214887Schin draw(ep,APPEND);
12224887Schin }
12234887Schin i = genlen(string);
12244887Schin
12258462SApril.Chin@Sun.COM if(ep->prevdirection == -2 && i!=2 || direction!=1)
12268462SApril.Chin@Sun.COM ep->prevdirection = -1;
12274887Schin if (direction < 1)
12284887Schin {
12294887Schin ep->prevdirection = -ep->prevdirection;
12304887Schin direction = 1;
12314887Schin }
12324887Schin else
12334887Schin direction = -1;
12344887Schin if (i != 2)
12354887Schin {
12364887Schin #if SHOPT_MULTIBYTE
12374887Schin ed_external(string,(char*)string);
12384887Schin #endif /* SHOPT_MULTIBYTE */
12394887Schin strncpy(lstring,((char*)string)+2,SEARCHSIZE);
12404887Schin ep->prevdirection = direction;
12414887Schin }
12424887Schin else
12434887Schin direction = ep->prevdirection ;
12444887Schin location = hist_find(sh.hist_ptr,(char*)lstring,hline,1,direction);
12454887Schin i = location.hist_command;
12464887Schin if(i>0)
12474887Schin {
12484887Schin hline = i;
12494887Schin #ifdef ESH_NFIRST
12504887Schin hloff = location.hist_line = 0; /* display first line of multi line command */
12514887Schin #else
12524887Schin hloff = location.hist_line;
12534887Schin #endif /* ESH_NFIRST */
12544887Schin hist_copy((char*)out,MAXLINE, hline,hloff);
12554887Schin #if SHOPT_MULTIBYTE
12564887Schin ed_internal((char*)out,out);
12574887Schin #endif /* SHOPT_MULTIBYTE */
12584887Schin return;
12594887Schin }
12604887Schin if (i < 0)
12614887Schin {
12624887Schin beep();
12634887Schin #ifdef ESH_NFIRST
12644887Schin location.hist_command = hline;
12654887Schin location.hist_line = hloff;
12664887Schin #else
12674887Schin hloff = 0;
12684887Schin hline = histlines;
12694887Schin #endif /* ESH_NFIRST */
12704887Schin }
12714887Schin restore:
12724887Schin genncpy(string,str_buff,sizeof(str_buff)/sizeof(*str_buff));
12734887Schin cur = sav_cur;
12744887Schin return;
12754887Schin }
12764887Schin
12774887Schin
12784887Schin /* Adjust screen to agree with inputs: logical line and cursor */
12794887Schin /* If 'first' assume screen is blank */
12804887Schin /* Prompt is always kept on the screen */
12814887Schin
draw(register Emacs_t * ep,Draw_t option)12824887Schin static void draw(register Emacs_t *ep,Draw_t option)
12834887Schin {
12844887Schin #define NORMAL ' '
12854887Schin #define LOWER '<'
12864887Schin #define BOTH '*'
12874887Schin #define UPPER '>'
12884887Schin
12894887Schin register genchar *sptr; /* Pointer within screen */
12904887Schin genchar nscreen[2*MAXLINE]; /* New entire screen */
12914887Schin genchar *ncursor; /* New cursor */
12924887Schin register genchar *nptr; /* Pointer to New screen */
12934887Schin char longline; /* Line overflow */
12944887Schin genchar *logcursor;
12954887Schin genchar *nscend; /* end of logical screen */
12964887Schin register int i;
12974887Schin
12984887Schin nptr = nscreen;
12994887Schin sptr = drawbuff;
13004887Schin logcursor = sptr + cur;
13014887Schin longline = NORMAL;
13028462SApril.Chin@Sun.COM ep->lastdraw = option;
13034887Schin
13044887Schin if (option == FIRST || option == REFRESH)
13054887Schin {
13064887Schin ep->overflow = NORMAL;
13074887Schin ep->cursor = ep->screen;
13084887Schin ep->offset = 0;
13094887Schin ep->cr_ok = crallowed;
13104887Schin if (option == FIRST)
13114887Schin {
13124887Schin ep->scvalid = 1;
13134887Schin return;
13144887Schin }
13154887Schin *ep->cursor = '\0';
13164887Schin putstring(ep,Prompt); /* start with prompt */
13174887Schin }
13184887Schin
13194887Schin /*********************
13204887Schin Do not update screen if pending characters
13214887Schin **********************/
13224887Schin
13234887Schin if ((lookahead)&&(option != FINAL))
13244887Schin {
13254887Schin
13264887Schin ep->scvalid = 0; /* Screen is out of date, APPEND will not work */
13274887Schin
13284887Schin return;
13294887Schin }
13304887Schin
13314887Schin /***************************************
13324887Schin If in append mode, cursor at end of line, screen up to date,
13334887Schin the previous character was a 'normal' character,
13344887Schin and the window has room for another character.
13354887Schin Then output the character and adjust the screen only.
13364887Schin *****************************************/
13374887Schin
13384887Schin
13394887Schin i = *(logcursor-1); /* last character inserted */
13404887Schin
13414887Schin if ((option == APPEND)&&(ep->scvalid)&&(*logcursor == '\0')&&
13424887Schin print(i)&&((ep->cursor-ep->screen)<(w_size-1)))
13434887Schin {
13444887Schin putchar(ep->ed,i);
13454887Schin *ep->cursor++ = i;
13464887Schin *ep->cursor = '\0';
13474887Schin return;
13484887Schin }
13494887Schin
13504887Schin /* copy the line */
13514887Schin ncursor = nptr + ed_virt_to_phys(ep->ed,sptr,nptr,cur,0,0);
13524887Schin nptr += genlen(nptr);
13534887Schin sptr += genlen(sptr);
13544887Schin nscend = nptr - 1;
13554887Schin if(sptr == logcursor)
13564887Schin ncursor = nptr;
13574887Schin
13584887Schin /*********************
13594887Schin Does ncursor appear on the screen?
13604887Schin If not, adjust the screen offset so it does.
13614887Schin **********************/
13624887Schin
13634887Schin i = ncursor - nscreen;
13644887Schin
13654887Schin if ((ep->offset && i<=ep->offset)||(i >= (ep->offset+w_size)))
13664887Schin {
13674887Schin /* Center the cursor on the screen */
13684887Schin ep->offset = i - (w_size>>1);
13694887Schin if (--ep->offset < 0)
13704887Schin ep->offset = 0;
13714887Schin }
13724887Schin
13734887Schin /*********************
13744887Schin Is the range of screen[0] thru screen[w_size] up-to-date
13754887Schin with nscreen[offset] thru nscreen[offset+w_size] ?
13764887Schin If not, update as need be.
13774887Schin ***********************/
13784887Schin
13794887Schin nptr = &nscreen[ep->offset];
13804887Schin sptr = ep->screen;
13814887Schin
13824887Schin i = w_size;
13834887Schin
13844887Schin while (i-- > 0)
13854887Schin {
13864887Schin
13874887Schin if (*nptr == '\0')
13884887Schin {
13894887Schin *(nptr + 1) = '\0';
13904887Schin *nptr = ' ';
13914887Schin }
13924887Schin if (*sptr == '\0')
13934887Schin {
13944887Schin *(sptr + 1) = '\0';
13954887Schin *sptr = ' ';
13964887Schin }
13974887Schin if (*nptr == *sptr)
13984887Schin {
13994887Schin nptr++;
14004887Schin sptr++;
14014887Schin continue;
14024887Schin }
14034887Schin setcursor(ep,sptr-ep->screen,*nptr);
14044887Schin *sptr++ = *nptr++;
14054887Schin #if SHOPT_MULTIBYTE
14064887Schin while(*nptr==MARKER)
14074887Schin {
14084887Schin if(*sptr=='\0')
14094887Schin *(sptr + 1) = '\0';
14104887Schin *sptr++ = *nptr++;
14114887Schin i--;
14124887Schin ep->cursor++;
14134887Schin }
14144887Schin #endif /* SHOPT_MULTIBYTE */
14154887Schin }
14168462SApril.Chin@Sun.COM if(ep->ed->e_multiline && option == REFRESH && ep->ed->e_nocrnl==0)
14178462SApril.Chin@Sun.COM ed_setcursor(ep->ed, ep->screen, ep->cursor-ep->screen, ep->ed->e_peol, -1);
14188462SApril.Chin@Sun.COM
14194887Schin
14204887Schin /******************
14214887Schin
14224887Schin Screen overflow checks
14234887Schin
14244887Schin ********************/
14254887Schin
14264887Schin if (nscend >= &nscreen[ep->offset+w_size])
14274887Schin {
14284887Schin if (ep->offset > 0)
14294887Schin longline = BOTH;
14304887Schin else
14314887Schin longline = UPPER;
14324887Schin }
14334887Schin else
14344887Schin {
14354887Schin if (ep->offset > 0)
14364887Schin longline = LOWER;
14374887Schin }
14384887Schin
14394887Schin /* Update screen overflow indicator if need be */
14404887Schin
14414887Schin if (longline != ep->overflow)
14424887Schin {
14434887Schin setcursor(ep,w_size,longline);
14444887Schin ep->overflow = longline;
14454887Schin }
14464887Schin i = (ncursor-nscreen) - ep->offset;
14474887Schin setcursor(ep,i,0);
14484887Schin if(option==FINAL && ep->ed->e_multiline)
14498462SApril.Chin@Sun.COM setcursor(ep,nscend+1-nscreen,0);
14504887Schin ep->scvalid = 1;
14514887Schin return;
14524887Schin }
14534887Schin
14544887Schin /*
14554887Schin * put the cursor to the <newp> position within screen buffer
14564887Schin * if <c> is non-zero then output this character
14574887Schin * cursor is set to reflect the change
14584887Schin */
14594887Schin
setcursor(register Emacs_t * ep,register int newp,int c)14604887Schin static void setcursor(register Emacs_t *ep,register int newp,int c)
14614887Schin {
14624887Schin register int oldp = ep->cursor - ep->screen;
14634887Schin newp = ed_setcursor(ep->ed, ep->screen, oldp, newp, 0);
14644887Schin if(c)
14654887Schin {
14664887Schin putchar(ep->ed,c);
14674887Schin newp++;
14684887Schin }
14694887Schin ep->cursor = ep->screen+newp;
14704887Schin return;
14714887Schin }
14724887Schin
14734887Schin #if SHOPT_MULTIBYTE
print(register int c)14744887Schin static int print(register int c)
14754887Schin {
14764887Schin return((c&~STRIP)==0 && isprint(c));
14774887Schin }
14784887Schin
_isword(register int c)14794887Schin static int _isword(register int c)
14804887Schin {
14814887Schin return((c&~STRIP) || isalnum(c) || c=='_');
14824887Schin }
14834887Schin #endif /* SHOPT_MULTIBYTE */
1484