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 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 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 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 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 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 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 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 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 14744887Schin static int print(register int c) 14754887Schin { 14764887Schin return((c&~STRIP)==0 && isprint(c)); 14774887Schin } 14784887Schin 14794887Schin static int _isword(register int c) 14804887Schin { 14814887Schin return((c&~STRIP) || isalnum(c) || c=='_'); 14824887Schin } 14834887Schin #endif /* SHOPT_MULTIBYTE */ 1484