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