1*4887Schin /*********************************************************************** 2*4887Schin * * 3*4887Schin * This software is part of the ast package * 4*4887Schin * Copyright (c) 1982-2007 AT&T Knowledge Ventures * 5*4887Schin * and is licensed under the * 6*4887Schin * Common Public License, Version 1.0 * 7*4887Schin * by AT&T Knowledge Ventures * 8*4887Schin * * 9*4887Schin * A copy of the License is available at * 10*4887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 11*4887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12*4887Schin * * 13*4887Schin * Information and Software Systems Research * 14*4887Schin * AT&T Research * 15*4887Schin * Florham Park NJ * 16*4887Schin * * 17*4887Schin * David Korn <dgk@research.att.com> * 18*4887Schin * * 19*4887Schin ***********************************************************************/ 20*4887Schin #pragma prototyped 21*4887Schin /* Original version by Michael T. Veach 22*4887Schin * Adapted for ksh by David Korn */ 23*4887Schin /* EMACS_MODES: c tabstop=4 24*4887Schin 25*4887Schin One line screen editor for any program 26*4887Schin 27*4887Schin */ 28*4887Schin 29*4887Schin 30*4887Schin /* The following is provided by: 31*4887Schin * 32*4887Schin * Matthijs N. Melchior 33*4887Schin * AT&T Network Systems International 34*4887Schin * APT Nederland 35*4887Schin * HV BZ335 x2962 36*4887Schin * hvlpb!mmelchio 37*4887Schin * 38*4887Schin * These are now on by default 39*4887Schin * 40*4887Schin * ESH_NFIRST 41*4887Schin * - A ^N as first history related command after the prompt will move 42*4887Schin * to the next command relative to the last known history position. 43*4887Schin * It will not start at the position where the last command was entered 44*4887Schin * as is done by the ^P command. Every history related command will 45*4887Schin * set both the current and last position. Executing a command will 46*4887Schin * only set the current position. 47*4887Schin * 48*4887Schin * ESH_KAPPEND 49*4887Schin * - Successive kill and delete commands will accumulate their data 50*4887Schin * in the kill buffer, by appending or prepending as appropriate. 51*4887Schin * This mode will be reset by any command not adding something to the 52*4887Schin * kill buffer. 53*4887Schin * 54*4887Schin * ESH_BETTER 55*4887Schin * - Some enhancements: 56*4887Schin * - argument for a macro is passed to its replacement 57*4887Schin * - ^X^H command to find out about history position (debugging) 58*4887Schin * - ^X^D command to show any debugging info 59*4887Schin * 60*4887Schin * I do not pretend these for changes are completely independent, 61*4887Schin * but you can use them to seperate features. 62*4887Schin */ 63*4887Schin 64*4887Schin #include <ast.h> 65*4887Schin #include <ctype.h> 66*4887Schin #include "FEATURE/cmds" 67*4887Schin #if KSHELL 68*4887Schin # include "defs.h" 69*4887Schin #endif /* KSHELL */ 70*4887Schin #include "io.h" 71*4887Schin 72*4887Schin #include "history.h" 73*4887Schin #include "edit.h" 74*4887Schin #include "terminal.h" 75*4887Schin 76*4887Schin #define ESH_NFIRST 77*4887Schin #define ESH_KAPPEND 78*4887Schin #define ESH_BETTER 79*4887Schin 80*4887Schin #undef putchar 81*4887Schin #define putchar(ed,c) ed_putchar(ed,c) 82*4887Schin #define beep() ed_ringbell() 83*4887Schin 84*4887Schin 85*4887Schin #if SHOPT_MULTIBYTE 86*4887Schin # define gencpy(a,b) ed_gencpy(a,b) 87*4887Schin # define genncpy(a,b,n) ed_genncpy(a,b,n) 88*4887Schin # define genlen(str) ed_genlen(str) 89*4887Schin static int print(int); 90*4887Schin static int _isword(int); 91*4887Schin # define isword(c) _isword(out[c]) 92*4887Schin 93*4887Schin #else 94*4887Schin # define gencpy(a,b) strcpy((char*)(a),(char*)(b)) 95*4887Schin # define genncpy(a,b,n) strncpy((char*)(a),(char*)(b),n) 96*4887Schin # define genlen(str) strlen(str) 97*4887Schin # define print(c) isprint(c) 98*4887Schin # define isword(c) (isalnum(out[c]) || (out[c]=='_')) 99*4887Schin #endif /*SHOPT_MULTIBYTE */ 100*4887Schin 101*4887Schin typedef struct _emacs_ 102*4887Schin { 103*4887Schin genchar *screen; /* pointer to window buffer */ 104*4887Schin genchar *cursor; /* Cursor in real screen */ 105*4887Schin int mark; 106*4887Schin int in_mult; 107*4887Schin char cr_ok; 108*4887Schin char CntrlO; 109*4887Schin char overflow; /* Screen overflow flag set */ 110*4887Schin char scvalid; /* Screen is up to date */ 111*4887Schin int offset; /* Screen offset */ 112*4887Schin enum 113*4887Schin { 114*4887Schin CRT=0, /* Crt terminal */ 115*4887Schin PAPER /* Paper terminal */ 116*4887Schin } terminal; 117*4887Schin Histloc_t _location; 118*4887Schin int prevdirection; 119*4887Schin Edit_t *ed; /* pointer to edit data */ 120*4887Schin } Emacs_t; 121*4887Schin 122*4887Schin #define editb (*ep->ed) 123*4887Schin #define eol editb.e_eol 124*4887Schin #define cur editb.e_cur 125*4887Schin #define hline editb.e_hline 126*4887Schin #define hloff editb.e_hloff 127*4887Schin #define hismin editb.e_hismin 128*4887Schin #define usrkill editb.e_kill 129*4887Schin #define usrlnext editb.e_lnext 130*4887Schin #define usreof editb.e_eof 131*4887Schin #define usrerase editb.e_erase 132*4887Schin #define crallowed editb.e_crlf 133*4887Schin #define Prompt editb.e_prompt 134*4887Schin #define plen editb.e_plen 135*4887Schin #define kstack editb.e_killbuf 136*4887Schin #define lstring editb.e_search 137*4887Schin #define lookahead editb.e_lookahead 138*4887Schin #define env editb.e_env 139*4887Schin #define raw editb.e_raw 140*4887Schin #define histlines editb.e_hismax 141*4887Schin #define w_size editb.e_wsize 142*4887Schin #define drawbuff editb.e_inbuf 143*4887Schin #define killing editb.e_mode 144*4887Schin #define location ep->_location 145*4887Schin 146*4887Schin #define LBUF 100 147*4887Schin #define KILLCHAR UKILL 148*4887Schin #define ERASECHAR UERASE 149*4887Schin #define EOFCHAR UEOF 150*4887Schin #define LNEXTCHAR ULNEXT 151*4887Schin #define DELETE ('a'==97?0177:7) 152*4887Schin 153*4887Schin /********************** 154*4887Schin A large lookahead helps when the user is inserting 155*4887Schin characters in the middle of the line. 156*4887Schin ************************/ 157*4887Schin 158*4887Schin 159*4887Schin typedef enum 160*4887Schin { 161*4887Schin FIRST, /* First time thru for logical line, prompt on screen */ 162*4887Schin REFRESH, /* Redraw entire screen */ 163*4887Schin APPEND, /* Append char before cursor to screen */ 164*4887Schin UPDATE, /* Update the screen as need be */ 165*4887Schin FINAL /* Update screen even if pending look ahead */ 166*4887Schin } Draw_t; 167*4887Schin 168*4887Schin static void draw(Emacs_t*,Draw_t); 169*4887Schin static int escape(Emacs_t*,genchar*, int); 170*4887Schin static void putstring(Emacs_t*,char*); 171*4887Schin static void search(Emacs_t*,genchar*,int); 172*4887Schin static void setcursor(Emacs_t*,int, int); 173*4887Schin static void show_info(Emacs_t*,const char*); 174*4887Schin static void xcommands(Emacs_t*,int); 175*4887Schin 176*4887Schin int ed_emacsread(void *context, int fd,char *buff,int scend, int reedit) 177*4887Schin { 178*4887Schin Edit_t *ed = (Edit_t*)context; 179*4887Schin register int c; 180*4887Schin register int i; 181*4887Schin register genchar *out; 182*4887Schin register int count; 183*4887Schin register Emacs_t *ep = ed->e_emacs; 184*4887Schin int adjust,oadjust; 185*4887Schin char backslash; 186*4887Schin genchar *kptr; 187*4887Schin char prompt[PRSIZE]; 188*4887Schin genchar Screen[MAXLINE]; 189*4887Schin if(!ep) 190*4887Schin { 191*4887Schin ep = ed->e_emacs = newof(0,Emacs_t,1,0); 192*4887Schin ep->ed = ed; 193*4887Schin ep->prevdirection = 1; 194*4887Schin location.hist_command = -5; 195*4887Schin } 196*4887Schin Prompt = prompt; 197*4887Schin ep->screen = Screen; 198*4887Schin if(tty_raw(ERRIO,0) < 0) 199*4887Schin { 200*4887Schin return(reedit?reedit:ed_read(context, fd,buff,scend,0)); 201*4887Schin } 202*4887Schin raw = 1; 203*4887Schin /* This mess in case the read system call fails */ 204*4887Schin 205*4887Schin ed_setup(ep->ed,fd,reedit); 206*4887Schin out = (genchar*)buff; 207*4887Schin #if SHOPT_MULTIBYTE 208*4887Schin out = (genchar*)roundof((char*)out-(char*)0,sizeof(genchar)); 209*4887Schin ed_internal(buff,out); 210*4887Schin #endif /* SHOPT_MULTIBYTE */ 211*4887Schin if(!kstack) 212*4887Schin { 213*4887Schin kstack = (genchar*)malloc(CHARSIZE*MAXLINE); 214*4887Schin kstack[0] = '\0'; 215*4887Schin } 216*4887Schin drawbuff = out; 217*4887Schin #ifdef ESH_NFIRST 218*4887Schin if (location.hist_command == -5) /* to be initialized */ 219*4887Schin { 220*4887Schin kstack[0] = '\0'; /* also clear kstack... */ 221*4887Schin location.hist_command = hline; 222*4887Schin location.hist_line = hloff; 223*4887Schin } 224*4887Schin if (location.hist_command <= hismin) /* don't start below minimum */ 225*4887Schin { 226*4887Schin location.hist_command = hismin + 1; 227*4887Schin location.hist_line = 0; 228*4887Schin } 229*4887Schin ep->in_mult = hloff; /* save pos in last command */ 230*4887Schin #endif /* ESH_NFIRST */ 231*4887Schin i = sigsetjmp(env,0); 232*4887Schin if (i !=0) 233*4887Schin { 234*4887Schin tty_cooked(ERRIO); 235*4887Schin if (i == UEOF) 236*4887Schin { 237*4887Schin return(0); /* EOF */ 238*4887Schin } 239*4887Schin return(-1); /* some other error */ 240*4887Schin } 241*4887Schin out[reedit] = 0; 242*4887Schin if(scend+plen > (MAXLINE-2)) 243*4887Schin scend = (MAXLINE-2)-plen; 244*4887Schin ep->mark = 0; 245*4887Schin cur = eol; 246*4887Schin draw(ep,reedit?REFRESH:FIRST); 247*4887Schin adjust = -1; 248*4887Schin backslash = 0; 249*4887Schin if (ep->CntrlO) 250*4887Schin { 251*4887Schin #ifdef ESH_NFIRST 252*4887Schin ed_ungetchar(ep->ed,cntl('N')); 253*4887Schin #else 254*4887Schin location = hist_locate(sh.hist_ptr,location.hist_command,location.hist_line,1); 255*4887Schin if (location.hist_command < histlines) 256*4887Schin { 257*4887Schin hline = location.hist_command; 258*4887Schin hloff = location.hist_line; 259*4887Schin hist_copy((char*)kstack,MAXLINE, hline,hloff); 260*4887Schin # if SHOPT_MULTIBYTE 261*4887Schin ed_internal((char*)kstack,kstack); 262*4887Schin # endif /* SHOPT_MULTIBYTE */ 263*4887Schin ed_ungetchar(ep->ed,cntl('Y')); 264*4887Schin } 265*4887Schin #endif /* ESH_NFIRST */ 266*4887Schin } 267*4887Schin ep->CntrlO = 0; 268*4887Schin while ((c = ed_getchar(ep->ed,0)) != (-1)) 269*4887Schin { 270*4887Schin if (backslash) 271*4887Schin { 272*4887Schin backslash = 0; 273*4887Schin if (c==usrerase||c==usrkill||(!print(c) && 274*4887Schin (c!='\r'&&c!='\n'))) 275*4887Schin { 276*4887Schin /* accept a backslashed character */ 277*4887Schin cur--; 278*4887Schin out[cur++] = c; 279*4887Schin out[eol] = '\0'; 280*4887Schin draw(ep,APPEND); 281*4887Schin continue; 282*4887Schin } 283*4887Schin } 284*4887Schin if (c == usrkill) 285*4887Schin { 286*4887Schin c = KILLCHAR ; 287*4887Schin } 288*4887Schin else if (c == usrerase) 289*4887Schin { 290*4887Schin c = ERASECHAR ; 291*4887Schin } 292*4887Schin else if (c == usrlnext) 293*4887Schin { 294*4887Schin c = LNEXTCHAR ; 295*4887Schin } 296*4887Schin else if ((c == usreof)&&(eol == 0)) 297*4887Schin { 298*4887Schin c = EOFCHAR; 299*4887Schin } 300*4887Schin #ifdef ESH_KAPPEND 301*4887Schin if (--killing <= 0) /* reset killing flag */ 302*4887Schin killing = 0; 303*4887Schin #endif 304*4887Schin oadjust = count = adjust; 305*4887Schin if(count<0) 306*4887Schin count = 1; 307*4887Schin adjust = -1; 308*4887Schin i = cur; 309*4887Schin switch(c) 310*4887Schin { 311*4887Schin case LNEXTCHAR: 312*4887Schin c = ed_getchar(ep->ed,2); 313*4887Schin goto do_default_processing; 314*4887Schin case cntl('V'): 315*4887Schin show_info(ep,fmtident(e_version)); 316*4887Schin continue; 317*4887Schin case '\0': 318*4887Schin ep->mark = i; 319*4887Schin continue; 320*4887Schin case cntl('X'): 321*4887Schin xcommands(ep,count); 322*4887Schin continue; 323*4887Schin case EOFCHAR: 324*4887Schin ed_flush(ep->ed); 325*4887Schin tty_cooked(ERRIO); 326*4887Schin return(0); 327*4887Schin #ifdef u370 328*4887Schin case cntl('S') : 329*4887Schin case cntl('Q') : 330*4887Schin continue; 331*4887Schin #endif /* u370 */ 332*4887Schin case '\t': 333*4887Schin if(cur>0 && ep->ed->sh->nextprompt) 334*4887Schin { 335*4887Schin if(ep->ed->e_tabcount==0) 336*4887Schin { 337*4887Schin ep->ed->e_tabcount=1; 338*4887Schin ed_ungetchar(ep->ed,ESC); 339*4887Schin goto do_escape; 340*4887Schin } 341*4887Schin else if(ep->ed->e_tabcount==1) 342*4887Schin { 343*4887Schin ed_ungetchar(ep->ed,'='); 344*4887Schin goto do_escape; 345*4887Schin } 346*4887Schin ep->ed->e_tabcount = 0; 347*4887Schin } 348*4887Schin do_default_processing: 349*4887Schin default: 350*4887Schin 351*4887Schin if ((eol+1) >= (scend)) /* will not fit on line */ 352*4887Schin { 353*4887Schin ed_ungetchar(ep->ed,c); /* save character for next line */ 354*4887Schin goto process; 355*4887Schin } 356*4887Schin for(i= ++eol; i>cur; i--) 357*4887Schin out[i] = out[i-1]; 358*4887Schin backslash = (c == '\\'); 359*4887Schin out[cur++] = c; 360*4887Schin draw(ep,APPEND); 361*4887Schin continue; 362*4887Schin case cntl('Y') : 363*4887Schin { 364*4887Schin c = genlen(kstack); 365*4887Schin if ((c + eol) > scend) 366*4887Schin { 367*4887Schin beep(); 368*4887Schin continue; 369*4887Schin } 370*4887Schin ep->mark = i; 371*4887Schin for(i=eol;i>=cur;i--) 372*4887Schin out[c+i] = out[i]; 373*4887Schin kptr=kstack; 374*4887Schin while (i = *kptr++) 375*4887Schin out[cur++] = i; 376*4887Schin draw(ep,UPDATE); 377*4887Schin eol = genlen(out); 378*4887Schin continue; 379*4887Schin } 380*4887Schin case '\n': 381*4887Schin case '\r': 382*4887Schin c = '\n'; 383*4887Schin goto process; 384*4887Schin 385*4887Schin case DELETE: /* delete char 0x7f */ 386*4887Schin case '\b': /* backspace, ^h */ 387*4887Schin case ERASECHAR : 388*4887Schin if (count > i) 389*4887Schin count = i; 390*4887Schin #ifdef ESH_KAPPEND 391*4887Schin kptr = &kstack[count]; /* move old contents here */ 392*4887Schin if (killing) /* prepend to killbuf */ 393*4887Schin { 394*4887Schin c = genlen(kstack) + CHARSIZE; /* include '\0' */ 395*4887Schin while(c--) /* copy stuff */ 396*4887Schin kptr[c] = kstack[c]; 397*4887Schin } 398*4887Schin else 399*4887Schin *kptr = 0; /* this is end of data */ 400*4887Schin killing = 2; /* we are killing */ 401*4887Schin i -= count; 402*4887Schin eol -= count; 403*4887Schin genncpy(kstack,out+i,cur-i); 404*4887Schin #else 405*4887Schin while ((count--)&&(i>0)) 406*4887Schin { 407*4887Schin i--; 408*4887Schin eol--; 409*4887Schin } 410*4887Schin genncpy(kstack,out+i,cur-i); 411*4887Schin kstack[cur-i] = 0; 412*4887Schin #endif /* ESH_KAPPEND */ 413*4887Schin gencpy(out+i,out+cur); 414*4887Schin ep->mark = i; 415*4887Schin goto update; 416*4887Schin case cntl('W') : 417*4887Schin #ifdef ESH_KAPPEND 418*4887Schin ++killing; /* keep killing flag */ 419*4887Schin #endif 420*4887Schin if (ep->mark > eol ) 421*4887Schin ep->mark = eol; 422*4887Schin if (ep->mark == i) 423*4887Schin continue; 424*4887Schin if (ep->mark > i) 425*4887Schin { 426*4887Schin adjust = ep->mark - i; 427*4887Schin ed_ungetchar(ep->ed,cntl('D')); 428*4887Schin continue; 429*4887Schin } 430*4887Schin adjust = i - ep->mark; 431*4887Schin ed_ungetchar(ep->ed,usrerase); 432*4887Schin continue; 433*4887Schin case cntl('D') : 434*4887Schin ep->mark = i; 435*4887Schin #ifdef ESH_KAPPEND 436*4887Schin if (killing) 437*4887Schin kptr = &kstack[genlen(kstack)]; /* append here */ 438*4887Schin else 439*4887Schin kptr = kstack; 440*4887Schin killing = 2; /* we are now killing */ 441*4887Schin #else 442*4887Schin kptr = kstack; 443*4887Schin #endif /* ESH_KAPPEND */ 444*4887Schin while ((count--)&&(eol>0)&&(i<eol)) 445*4887Schin { 446*4887Schin *kptr++ = out[i]; 447*4887Schin eol--; 448*4887Schin while(1) 449*4887Schin { 450*4887Schin if ((out[i] = out[(i+1)])==0) 451*4887Schin break; 452*4887Schin i++; 453*4887Schin } 454*4887Schin i = cur; 455*4887Schin } 456*4887Schin *kptr = '\0'; 457*4887Schin goto update; 458*4887Schin case cntl('C') : 459*4887Schin case cntl('F') : 460*4887Schin { 461*4887Schin int cntlC = (c==cntl('C')); 462*4887Schin while (count-- && eol>i) 463*4887Schin { 464*4887Schin if (cntlC) 465*4887Schin { 466*4887Schin c = out[i]; 467*4887Schin #if SHOPT_MULTIBYTE 468*4887Schin if((c&~STRIP)==0 && islower(c)) 469*4887Schin #else 470*4887Schin if(islower(c)) 471*4887Schin #endif /* SHOPT_MULTIBYTE */ 472*4887Schin { 473*4887Schin c += 'A' - 'a'; 474*4887Schin out[i] = c; 475*4887Schin } 476*4887Schin } 477*4887Schin i++; 478*4887Schin } 479*4887Schin goto update; 480*4887Schin } 481*4887Schin case cntl(']') : 482*4887Schin c = ed_getchar(ep->ed,1); 483*4887Schin if ((count == 0) || (count > eol)) 484*4887Schin { 485*4887Schin beep(); 486*4887Schin continue; 487*4887Schin } 488*4887Schin if (out[i]) 489*4887Schin i++; 490*4887Schin while (i < eol) 491*4887Schin { 492*4887Schin if (out[i] == c && --count==0) 493*4887Schin goto update; 494*4887Schin i++; 495*4887Schin } 496*4887Schin i = 0; 497*4887Schin while (i < cur) 498*4887Schin { 499*4887Schin if (out[i] == c && --count==0) 500*4887Schin break; 501*4887Schin i++; 502*4887Schin }; 503*4887Schin 504*4887Schin update: 505*4887Schin cur = i; 506*4887Schin draw(ep,UPDATE); 507*4887Schin continue; 508*4887Schin 509*4887Schin case cntl('B') : 510*4887Schin if (count > i) 511*4887Schin count = i; 512*4887Schin i -= count; 513*4887Schin goto update; 514*4887Schin case cntl('T') : 515*4887Schin if ((sh_isoption(SH_EMACS))&& (eol!=i)) 516*4887Schin i++; 517*4887Schin if (i >= 2) 518*4887Schin { 519*4887Schin c = out[i - 1]; 520*4887Schin out[i-1] = out[i-2]; 521*4887Schin out[i-2] = c; 522*4887Schin } 523*4887Schin else 524*4887Schin { 525*4887Schin if(sh_isoption(SH_EMACS)) 526*4887Schin i--; 527*4887Schin beep(); 528*4887Schin continue; 529*4887Schin } 530*4887Schin goto update; 531*4887Schin case cntl('A') : 532*4887Schin i = 0; 533*4887Schin goto update; 534*4887Schin case cntl('E') : 535*4887Schin i = eol; 536*4887Schin goto update; 537*4887Schin case cntl('U') : 538*4887Schin adjust = 4*count; 539*4887Schin continue; 540*4887Schin case KILLCHAR : 541*4887Schin cur = 0; 542*4887Schin oadjust = -1; 543*4887Schin case cntl('K') : 544*4887Schin if(oadjust >= 0) 545*4887Schin { 546*4887Schin #ifdef ESH_KAPPEND 547*4887Schin killing = 2; /* set killing signal */ 548*4887Schin #endif 549*4887Schin ep->mark = count; 550*4887Schin ed_ungetchar(ep->ed,cntl('W')); 551*4887Schin continue; 552*4887Schin } 553*4887Schin i = cur; 554*4887Schin eol = i; 555*4887Schin ep->mark = i; 556*4887Schin #ifdef ESH_KAPPEND 557*4887Schin if (killing) /* append to kill buffer */ 558*4887Schin gencpy(&kstack[genlen(kstack)], &out[i]); 559*4887Schin else 560*4887Schin gencpy(kstack,&out[i]); 561*4887Schin killing = 2; /* set killing signal */ 562*4887Schin #else 563*4887Schin gencpy(kstack,&out[i]); 564*4887Schin #endif /* ESH_KAPPEND */ 565*4887Schin out[i] = 0; 566*4887Schin draw(ep,UPDATE); 567*4887Schin if (c == KILLCHAR) 568*4887Schin { 569*4887Schin if (ep->terminal == PAPER) 570*4887Schin { 571*4887Schin putchar(ep->ed,'\n'); 572*4887Schin putstring(ep,Prompt); 573*4887Schin } 574*4887Schin c = ed_getchar(ep->ed,0); 575*4887Schin if (c != usrkill) 576*4887Schin { 577*4887Schin ed_ungetchar(ep->ed,c); 578*4887Schin continue; 579*4887Schin } 580*4887Schin if (ep->terminal == PAPER) 581*4887Schin ep->terminal = CRT; 582*4887Schin else 583*4887Schin { 584*4887Schin ep->terminal = PAPER; 585*4887Schin putchar(ep->ed,'\n'); 586*4887Schin putstring(ep,Prompt); 587*4887Schin } 588*4887Schin } 589*4887Schin continue; 590*4887Schin case cntl('L'): 591*4887Schin ed_crlf(ep->ed); 592*4887Schin draw(ep,REFRESH); 593*4887Schin continue; 594*4887Schin case cntl('[') : 595*4887Schin do_escape: 596*4887Schin adjust = escape(ep,out,oadjust); 597*4887Schin continue; 598*4887Schin case cntl('R') : 599*4887Schin search(ep,out,count); 600*4887Schin goto drawline; 601*4887Schin case cntl('P') : 602*4887Schin if (count <= hloff) 603*4887Schin hloff -= count; 604*4887Schin else 605*4887Schin { 606*4887Schin hline -= count - hloff; 607*4887Schin hloff = 0; 608*4887Schin } 609*4887Schin #ifdef ESH_NFIRST 610*4887Schin if (hline <= hismin) 611*4887Schin #else 612*4887Schin if (hline < hismin) 613*4887Schin #endif /* ESH_NFIRST */ 614*4887Schin { 615*4887Schin hline = hismin+1; 616*4887Schin beep(); 617*4887Schin #ifndef ESH_NFIRST 618*4887Schin continue; 619*4887Schin #endif 620*4887Schin } 621*4887Schin goto common; 622*4887Schin 623*4887Schin case cntl('O') : 624*4887Schin location.hist_command = hline; 625*4887Schin location.hist_line = hloff; 626*4887Schin ep->CntrlO = 1; 627*4887Schin c = '\n'; 628*4887Schin goto process; 629*4887Schin case cntl('N') : 630*4887Schin #ifdef ESH_NFIRST 631*4887Schin hline = location.hist_command; /* start at saved position */ 632*4887Schin hloff = location.hist_line; 633*4887Schin #endif /* ESH_NFIRST */ 634*4887Schin location = hist_locate(sh.hist_ptr,hline,hloff,count); 635*4887Schin if (location.hist_command > histlines) 636*4887Schin { 637*4887Schin beep(); 638*4887Schin #ifdef ESH_NFIRST 639*4887Schin location.hist_command = histlines; 640*4887Schin location.hist_line = ep->in_mult; 641*4887Schin #else 642*4887Schin continue; 643*4887Schin #endif /* ESH_NFIRST */ 644*4887Schin } 645*4887Schin hline = location.hist_command; 646*4887Schin hloff = location.hist_line; 647*4887Schin common: 648*4887Schin #ifdef ESH_NFIRST 649*4887Schin location.hist_command = hline; /* save current position */ 650*4887Schin location.hist_line = hloff; 651*4887Schin #endif 652*4887Schin hist_copy((char*)out,MAXLINE, hline,hloff); 653*4887Schin #if SHOPT_MULTIBYTE 654*4887Schin ed_internal((char*)(out),out); 655*4887Schin #endif /* SHOPT_MULTIBYTE */ 656*4887Schin drawline: 657*4887Schin eol = genlen(out); 658*4887Schin cur = eol; 659*4887Schin draw(ep,UPDATE); 660*4887Schin continue; 661*4887Schin } 662*4887Schin 663*4887Schin } 664*4887Schin 665*4887Schin process: 666*4887Schin 667*4887Schin if (c == (-1)) 668*4887Schin { 669*4887Schin lookahead = 0; 670*4887Schin beep(); 671*4887Schin *out = '\0'; 672*4887Schin } 673*4887Schin draw(ep,FINAL); 674*4887Schin tty_cooked(ERRIO); 675*4887Schin if(ed->e_nlist) 676*4887Schin { 677*4887Schin ed->e_nlist = 0; 678*4887Schin stakset(ed->e_stkptr,ed->e_stkoff); 679*4887Schin } 680*4887Schin if(c == '\n') 681*4887Schin { 682*4887Schin out[eol++] = '\n'; 683*4887Schin out[eol] = '\0'; 684*4887Schin ed_crlf(ep->ed); 685*4887Schin } 686*4887Schin #if SHOPT_MULTIBYTE 687*4887Schin ed_external(out,buff); 688*4887Schin #endif /* SHOPT_MULTIBYTE */ 689*4887Schin i = strlen(buff); 690*4887Schin if (i) 691*4887Schin return(i); 692*4887Schin return(-1); 693*4887Schin } 694*4887Schin 695*4887Schin static void show_info(Emacs_t *ep,const char *str) 696*4887Schin { 697*4887Schin register genchar *out = drawbuff; 698*4887Schin register int c; 699*4887Schin genchar string[LBUF]; 700*4887Schin int sav_cur = cur; 701*4887Schin /* save current line */ 702*4887Schin genncpy(string,out,sizeof(string)/sizeof(*string)); 703*4887Schin *out = 0; 704*4887Schin cur = 0; 705*4887Schin #if SHOPT_MULTIBYTE 706*4887Schin ed_internal(str,out); 707*4887Schin #else 708*4887Schin gencpy(out,str); 709*4887Schin #endif /* SHOPT_MULTIBYTE */ 710*4887Schin draw(ep,UPDATE); 711*4887Schin c = ed_getchar(ep->ed,0); 712*4887Schin if(c!=' ') 713*4887Schin ed_ungetchar(ep->ed,c); 714*4887Schin /* restore line */ 715*4887Schin cur = sav_cur; 716*4887Schin genncpy(out,string,sizeof(string)/sizeof(*string)); 717*4887Schin draw(ep,UPDATE); 718*4887Schin } 719*4887Schin 720*4887Schin static void putstring(Emacs_t* ep,register char *sp) 721*4887Schin { 722*4887Schin register int c; 723*4887Schin while (c= *sp++) 724*4887Schin putchar(ep->ed,c); 725*4887Schin } 726*4887Schin 727*4887Schin 728*4887Schin static int escape(register Emacs_t* ep,register genchar *out,int count) 729*4887Schin { 730*4887Schin register int i,value; 731*4887Schin int digit,ch; 732*4887Schin digit = 0; 733*4887Schin value = 0; 734*4887Schin while ((i=ed_getchar(ep->ed,0)),isdigit(i)) 735*4887Schin { 736*4887Schin value *= 10; 737*4887Schin value += (i - '0'); 738*4887Schin digit = 1; 739*4887Schin } 740*4887Schin if (digit) 741*4887Schin { 742*4887Schin ed_ungetchar(ep->ed,i) ; 743*4887Schin #ifdef ESH_KAPPEND 744*4887Schin ++killing; /* don't modify killing signal */ 745*4887Schin #endif 746*4887Schin return(value); 747*4887Schin } 748*4887Schin value = count; 749*4887Schin if(value<0) 750*4887Schin value = 1; 751*4887Schin switch(ch=i) 752*4887Schin { 753*4887Schin case cntl('V'): 754*4887Schin show_info(ep,fmtident(e_version)); 755*4887Schin return(-1); 756*4887Schin case ' ': 757*4887Schin ep->mark = cur; 758*4887Schin return(-1); 759*4887Schin 760*4887Schin #ifdef ESH_KAPPEND 761*4887Schin case '+': /* M-+ = append next kill */ 762*4887Schin killing = 2; 763*4887Schin return -1; /* no argument for next command */ 764*4887Schin #endif 765*4887Schin 766*4887Schin case 'p': /* M-p == ^W^Y (copy stack == kill & yank) */ 767*4887Schin ed_ungetchar(ep->ed,cntl('Y')); 768*4887Schin ed_ungetchar(ep->ed,cntl('W')); 769*4887Schin #ifdef ESH_KAPPEND 770*4887Schin killing = 0; /* start fresh */ 771*4887Schin #endif 772*4887Schin return(-1); 773*4887Schin 774*4887Schin case 'l': /* M-l == lower-case */ 775*4887Schin case 'd': 776*4887Schin case 'c': 777*4887Schin case 'f': 778*4887Schin { 779*4887Schin i = cur; 780*4887Schin while(value-- && i<eol) 781*4887Schin { 782*4887Schin while ((out[i])&&(!isword(i))) 783*4887Schin i++; 784*4887Schin while ((out[i])&&(isword(i))) 785*4887Schin i++; 786*4887Schin } 787*4887Schin if(ch=='l') 788*4887Schin { 789*4887Schin value = i-cur; 790*4887Schin while (value-- > 0) 791*4887Schin { 792*4887Schin i = out[cur]; 793*4887Schin #if SHOPT_MULTIBYTE 794*4887Schin if((i&~STRIP)==0 && isupper(i)) 795*4887Schin #else 796*4887Schin if(isupper(i)) 797*4887Schin #endif /* SHOPT_MULTIBYTE */ 798*4887Schin { 799*4887Schin i += 'a' - 'A'; 800*4887Schin out[cur] = i; 801*4887Schin } 802*4887Schin cur++; 803*4887Schin } 804*4887Schin draw(ep,UPDATE); 805*4887Schin return(-1); 806*4887Schin } 807*4887Schin 808*4887Schin else if(ch=='f') 809*4887Schin goto update; 810*4887Schin else if(ch=='c') 811*4887Schin { 812*4887Schin ed_ungetchar(ep->ed,cntl('C')); 813*4887Schin return(i-cur); 814*4887Schin } 815*4887Schin else 816*4887Schin { 817*4887Schin if (i-cur) 818*4887Schin { 819*4887Schin ed_ungetchar(ep->ed,cntl('D')); 820*4887Schin #ifdef ESH_KAPPEND 821*4887Schin ++killing; /* keep killing signal */ 822*4887Schin #endif 823*4887Schin return(i-cur); 824*4887Schin } 825*4887Schin beep(); 826*4887Schin return(-1); 827*4887Schin } 828*4887Schin } 829*4887Schin 830*4887Schin 831*4887Schin case 'b': 832*4887Schin case DELETE : 833*4887Schin case '\b': 834*4887Schin case 'h': 835*4887Schin { 836*4887Schin i = cur; 837*4887Schin while(value-- && i>0) 838*4887Schin { 839*4887Schin i--; 840*4887Schin while ((i>0)&&(!isword(i))) 841*4887Schin i--; 842*4887Schin while ((i>0)&&(isword(i-1))) 843*4887Schin i--; 844*4887Schin } 845*4887Schin if(ch=='b') 846*4887Schin goto update; 847*4887Schin else 848*4887Schin { 849*4887Schin ed_ungetchar(ep->ed,usrerase); 850*4887Schin #ifdef ESH_KAPPEND 851*4887Schin ++killing; 852*4887Schin #endif 853*4887Schin return(cur-i); 854*4887Schin } 855*4887Schin } 856*4887Schin 857*4887Schin case '>': 858*4887Schin ed_ungetchar(ep->ed,cntl('N')); 859*4887Schin #ifdef ESH_NFIRST 860*4887Schin if (ep->in_mult) 861*4887Schin { 862*4887Schin location.hist_command = histlines; 863*4887Schin location.hist_line = ep->in_mult - 1; 864*4887Schin } 865*4887Schin else 866*4887Schin { 867*4887Schin location.hist_command = histlines - 1; 868*4887Schin location.hist_line = 0; 869*4887Schin } 870*4887Schin #else 871*4887Schin hline = histlines-1; 872*4887Schin hloff = 0; 873*4887Schin #endif /* ESH_NFIRST */ 874*4887Schin return(0); 875*4887Schin 876*4887Schin case '<': 877*4887Schin ed_ungetchar(ep->ed,cntl('P')); 878*4887Schin hloff = 0; 879*4887Schin #ifdef ESH_NFIRST 880*4887Schin hline = hismin + 1; 881*4887Schin return 0; 882*4887Schin #else 883*4887Schin return(hline-hismin); 884*4887Schin #endif /* ESH_NFIRST */ 885*4887Schin 886*4887Schin 887*4887Schin case '#': 888*4887Schin ed_ungetchar(ep->ed,'\n'); 889*4887Schin ed_ungetchar(ep->ed,(out[0]=='#')?cntl('D'):'#'); 890*4887Schin ed_ungetchar(ep->ed,cntl('A')); 891*4887Schin return(-1); 892*4887Schin case '_' : 893*4887Schin case '.' : 894*4887Schin { 895*4887Schin genchar name[MAXLINE]; 896*4887Schin char buf[MAXLINE]; 897*4887Schin char *ptr; 898*4887Schin ptr = hist_word(buf,MAXLINE,(count?count:-1)); 899*4887Schin #if !KSHELL 900*4887Schin if(ptr==0) 901*4887Schin { 902*4887Schin beep(); 903*4887Schin break; 904*4887Schin } 905*4887Schin #endif /* KSHELL */ 906*4887Schin if ((eol - cur) >= sizeof(name)) 907*4887Schin { 908*4887Schin beep(); 909*4887Schin return(-1); 910*4887Schin } 911*4887Schin ep->mark = cur; 912*4887Schin gencpy(name,&out[cur]); 913*4887Schin while(*ptr) 914*4887Schin { 915*4887Schin out[cur++] = *ptr++; 916*4887Schin eol++; 917*4887Schin } 918*4887Schin gencpy(&out[cur],name); 919*4887Schin draw(ep,UPDATE); 920*4887Schin return(-1); 921*4887Schin } 922*4887Schin #if KSHELL 923*4887Schin 924*4887Schin /* file name expansion */ 925*4887Schin case cntl('[') : /* filename completion */ 926*4887Schin i = '\\'; 927*4887Schin case '*': /* filename expansion */ 928*4887Schin case '=': /* escape = - list all matching file names */ 929*4887Schin ep->mark = cur; 930*4887Schin if(ed_expand(ep->ed,(char*)out,&cur,&eol,i,count) < 0) 931*4887Schin { 932*4887Schin if(ep->ed->e_tabcount==1) 933*4887Schin { 934*4887Schin ep->ed->e_tabcount=2; 935*4887Schin ed_ungetchar(ep->ed,cntl('\t')); 936*4887Schin return(-1); 937*4887Schin } 938*4887Schin beep(); 939*4887Schin } 940*4887Schin else if(i=='=') 941*4887Schin { 942*4887Schin draw(ep,REFRESH); 943*4887Schin if(count>0) 944*4887Schin ep->ed->e_tabcount=0; 945*4887Schin else 946*4887Schin { 947*4887Schin i=ed_getchar(ep->ed,0); 948*4887Schin ed_ungetchar(ep->ed,i); 949*4887Schin if(isdigit(i)) 950*4887Schin ed_ungetchar(ep->ed,ESC); 951*4887Schin } 952*4887Schin } 953*4887Schin else 954*4887Schin { 955*4887Schin if(i=='\\' && cur>ep->mark && (out[cur-1]=='/' || out[cur-1]==' ')) 956*4887Schin ep->ed->e_tabcount=0; 957*4887Schin draw(ep,UPDATE); 958*4887Schin } 959*4887Schin return(-1); 960*4887Schin 961*4887Schin /* search back for character */ 962*4887Schin case cntl(']'): /* feature not in book */ 963*4887Schin { 964*4887Schin int c = ed_getchar(ep->ed,1); 965*4887Schin if ((value == 0) || (value > eol)) 966*4887Schin { 967*4887Schin beep(); 968*4887Schin return(-1); 969*4887Schin } 970*4887Schin i = cur; 971*4887Schin if (i > 0) 972*4887Schin i--; 973*4887Schin while (i >= 0) 974*4887Schin { 975*4887Schin if (out[i] == c && --value==0) 976*4887Schin goto update; 977*4887Schin i--; 978*4887Schin } 979*4887Schin i = eol; 980*4887Schin while (i > cur) 981*4887Schin { 982*4887Schin if (out[i] == c && --value==0) 983*4887Schin break; 984*4887Schin i--; 985*4887Schin }; 986*4887Schin 987*4887Schin } 988*4887Schin update: 989*4887Schin cur = i; 990*4887Schin draw(ep,UPDATE); 991*4887Schin return(-1); 992*4887Schin 993*4887Schin #ifdef _cmd_tput 994*4887Schin case cntl('L'): /* clear screen */ 995*4887Schin sh_trap("tput clear", 0); 996*4887Schin draw(ep,REFRESH); 997*4887Schin return(-1); 998*4887Schin #endif 999*4887Schin case '[': /* feature not in book */ 1000*4887Schin switch(i=ed_getchar(ep->ed,1)) 1001*4887Schin { 1002*4887Schin case 'A': 1003*4887Schin ed_ungetchar(ep->ed,cntl('P')); 1004*4887Schin return(-1); 1005*4887Schin case 'B': 1006*4887Schin ed_ungetchar(ep->ed,cntl('N')); 1007*4887Schin return(-1); 1008*4887Schin case 'C': 1009*4887Schin ed_ungetchar(ep->ed,cntl('F')); 1010*4887Schin return(-1); 1011*4887Schin case 'D': 1012*4887Schin ed_ungetchar(ep->ed,cntl('B')); 1013*4887Schin return(-1); 1014*4887Schin case 'H': 1015*4887Schin ed_ungetchar(ep->ed,cntl('A')); 1016*4887Schin return(-1); 1017*4887Schin case 'Y': 1018*4887Schin ed_ungetchar(ep->ed,cntl('E')); 1019*4887Schin return(-1); 1020*4887Schin default: 1021*4887Schin ed_ungetchar(ep->ed,i); 1022*4887Schin } 1023*4887Schin i = '_'; 1024*4887Schin 1025*4887Schin default: 1026*4887Schin /* look for user defined macro definitions */ 1027*4887Schin if(ed_macro(ep->ed,i)) 1028*4887Schin # ifdef ESH_BETTER 1029*4887Schin return(count); /* pass argument to macro */ 1030*4887Schin # else 1031*4887Schin return(-1); 1032*4887Schin # endif /* ESH_BETTER */ 1033*4887Schin #else 1034*4887Schin update: 1035*4887Schin cur = i; 1036*4887Schin draw(ep,UPDATE); 1037*4887Schin return(-1); 1038*4887Schin 1039*4887Schin default: 1040*4887Schin #endif /* KSHELL */ 1041*4887Schin beep(); 1042*4887Schin return(-1); 1043*4887Schin } 1044*4887Schin } 1045*4887Schin 1046*4887Schin 1047*4887Schin /* 1048*4887Schin * This routine process all commands starting with ^X 1049*4887Schin */ 1050*4887Schin 1051*4887Schin static void xcommands(register Emacs_t *ep,int count) 1052*4887Schin { 1053*4887Schin register int i = ed_getchar(ep->ed,0); 1054*4887Schin NOT_USED(count); 1055*4887Schin switch(i) 1056*4887Schin { 1057*4887Schin case cntl('X'): /* exchange dot and mark */ 1058*4887Schin if (ep->mark > eol) 1059*4887Schin ep->mark = eol; 1060*4887Schin i = ep->mark; 1061*4887Schin ep->mark = cur; 1062*4887Schin cur = i; 1063*4887Schin draw(ep,UPDATE); 1064*4887Schin return; 1065*4887Schin 1066*4887Schin #if KSHELL 1067*4887Schin # ifdef ESH_BETTER 1068*4887Schin case cntl('E'): /* invoke emacs on current command */ 1069*4887Schin if(ed_fulledit(ep->ed)==-1) 1070*4887Schin beep(); 1071*4887Schin else 1072*4887Schin { 1073*4887Schin #if SHOPT_MULTIBYTE 1074*4887Schin ed_internal((char*)drawbuff,drawbuff); 1075*4887Schin #endif /* SHOPT_MULTIBYTE */ 1076*4887Schin ed_ungetchar(ep->ed,'\n'); 1077*4887Schin } 1078*4887Schin return; 1079*4887Schin 1080*4887Schin # define itos(i) fmtbase((long)(i),0,0)/* want signed conversion */ 1081*4887Schin 1082*4887Schin case cntl('H'): /* ^X^H show history info */ 1083*4887Schin { 1084*4887Schin char hbuf[MAXLINE]; 1085*4887Schin 1086*4887Schin strcpy(hbuf, "Current command "); 1087*4887Schin strcat(hbuf, itos(hline)); 1088*4887Schin if (hloff) 1089*4887Schin { 1090*4887Schin strcat(hbuf, " (line "); 1091*4887Schin strcat(hbuf, itos(hloff+1)); 1092*4887Schin strcat(hbuf, ")"); 1093*4887Schin } 1094*4887Schin if ((hline != location.hist_command) || 1095*4887Schin (hloff != location.hist_line)) 1096*4887Schin { 1097*4887Schin strcat(hbuf, "; Previous command "); 1098*4887Schin strcat(hbuf, itos(location.hist_command)); 1099*4887Schin if (location.hist_line) 1100*4887Schin { 1101*4887Schin strcat(hbuf, " (line "); 1102*4887Schin strcat(hbuf, itos(location.hist_line+1)); 1103*4887Schin strcat(hbuf, ")"); 1104*4887Schin } 1105*4887Schin } 1106*4887Schin show_info(ep,hbuf); 1107*4887Schin return; 1108*4887Schin } 1109*4887Schin # if 0 /* debugging, modify as required */ 1110*4887Schin case cntl('D'): /* ^X^D show debugging info */ 1111*4887Schin { 1112*4887Schin char debugbuf[MAXLINE]; 1113*4887Schin 1114*4887Schin strcpy(debugbuf, "count="); 1115*4887Schin strcat(debugbuf, itos(count)); 1116*4887Schin strcat(debugbuf, " eol="); 1117*4887Schin strcat(debugbuf, itos(eol)); 1118*4887Schin strcat(debugbuf, " cur="); 1119*4887Schin strcat(debugbuf, itos(cur)); 1120*4887Schin strcat(debugbuf, " crallowed="); 1121*4887Schin strcat(debugbuf, itos(crallowed)); 1122*4887Schin strcat(debugbuf, " plen="); 1123*4887Schin strcat(debugbuf, itos(plen)); 1124*4887Schin strcat(debugbuf, " w_size="); 1125*4887Schin strcat(debugbuf, itos(w_size)); 1126*4887Schin 1127*4887Schin show_info(ep,debugbuf); 1128*4887Schin return; 1129*4887Schin } 1130*4887Schin # endif /* debugging code */ 1131*4887Schin # endif /* ESH_BETTER */ 1132*4887Schin #endif /* KSHELL */ 1133*4887Schin 1134*4887Schin default: 1135*4887Schin beep(); 1136*4887Schin return; 1137*4887Schin } 1138*4887Schin } 1139*4887Schin 1140*4887Schin static void search(Emacs_t* ep,genchar *out,int direction) 1141*4887Schin { 1142*4887Schin #ifndef ESH_NFIRST 1143*4887Schin Histloc_t location; 1144*4887Schin #endif 1145*4887Schin register int i,sl; 1146*4887Schin genchar str_buff[LBUF]; 1147*4887Schin register genchar *string = drawbuff; 1148*4887Schin /* save current line */ 1149*4887Schin int sav_cur = cur; 1150*4887Schin genncpy(str_buff,string,sizeof(str_buff)/sizeof(*str_buff)); 1151*4887Schin string[0] = '^'; 1152*4887Schin string[1] = 'R'; 1153*4887Schin string[2] = '\0'; 1154*4887Schin sl = 2; 1155*4887Schin cur = sl; 1156*4887Schin draw(ep,UPDATE); 1157*4887Schin while ((i = ed_getchar(ep->ed,1))&&(i != '\r')&&(i != '\n')) 1158*4887Schin { 1159*4887Schin if (i==usrerase || i==DELETE || i=='\b' || i==ERASECHAR) 1160*4887Schin { 1161*4887Schin if (sl > 2) 1162*4887Schin { 1163*4887Schin string[--sl] = '\0'; 1164*4887Schin cur = sl; 1165*4887Schin draw(ep,UPDATE); 1166*4887Schin } 1167*4887Schin else 1168*4887Schin beep(); 1169*4887Schin continue; 1170*4887Schin } 1171*4887Schin if (i==usrkill) 1172*4887Schin { 1173*4887Schin beep(); 1174*4887Schin goto restore; 1175*4887Schin } 1176*4887Schin if (i == '\\') 1177*4887Schin { 1178*4887Schin string[sl++] = '\\'; 1179*4887Schin string[sl] = '\0'; 1180*4887Schin cur = sl; 1181*4887Schin draw(ep,APPEND); 1182*4887Schin i = ed_getchar(ep->ed,1); 1183*4887Schin string[--sl] = '\0'; 1184*4887Schin } 1185*4887Schin string[sl++] = i; 1186*4887Schin string[sl] = '\0'; 1187*4887Schin cur = sl; 1188*4887Schin draw(ep,APPEND); 1189*4887Schin } 1190*4887Schin i = genlen(string); 1191*4887Schin 1192*4887Schin if (direction < 1) 1193*4887Schin { 1194*4887Schin ep->prevdirection = -ep->prevdirection; 1195*4887Schin direction = 1; 1196*4887Schin } 1197*4887Schin else 1198*4887Schin direction = -1; 1199*4887Schin if (i != 2) 1200*4887Schin { 1201*4887Schin #if SHOPT_MULTIBYTE 1202*4887Schin ed_external(string,(char*)string); 1203*4887Schin #endif /* SHOPT_MULTIBYTE */ 1204*4887Schin strncpy(lstring,((char*)string)+2,SEARCHSIZE); 1205*4887Schin ep->prevdirection = direction; 1206*4887Schin } 1207*4887Schin else 1208*4887Schin direction = ep->prevdirection ; 1209*4887Schin location = hist_find(sh.hist_ptr,(char*)lstring,hline,1,direction); 1210*4887Schin i = location.hist_command; 1211*4887Schin if(i>0) 1212*4887Schin { 1213*4887Schin hline = i; 1214*4887Schin #ifdef ESH_NFIRST 1215*4887Schin hloff = location.hist_line = 0; /* display first line of multi line command */ 1216*4887Schin #else 1217*4887Schin hloff = location.hist_line; 1218*4887Schin #endif /* ESH_NFIRST */ 1219*4887Schin hist_copy((char*)out,MAXLINE, hline,hloff); 1220*4887Schin #if SHOPT_MULTIBYTE 1221*4887Schin ed_internal((char*)out,out); 1222*4887Schin #endif /* SHOPT_MULTIBYTE */ 1223*4887Schin return; 1224*4887Schin } 1225*4887Schin if (i < 0) 1226*4887Schin { 1227*4887Schin beep(); 1228*4887Schin #ifdef ESH_NFIRST 1229*4887Schin location.hist_command = hline; 1230*4887Schin location.hist_line = hloff; 1231*4887Schin #else 1232*4887Schin hloff = 0; 1233*4887Schin hline = histlines; 1234*4887Schin #endif /* ESH_NFIRST */ 1235*4887Schin } 1236*4887Schin restore: 1237*4887Schin genncpy(string,str_buff,sizeof(str_buff)/sizeof(*str_buff)); 1238*4887Schin cur = sav_cur; 1239*4887Schin return; 1240*4887Schin } 1241*4887Schin 1242*4887Schin 1243*4887Schin /* Adjust screen to agree with inputs: logical line and cursor */ 1244*4887Schin /* If 'first' assume screen is blank */ 1245*4887Schin /* Prompt is always kept on the screen */ 1246*4887Schin 1247*4887Schin static void draw(register Emacs_t *ep,Draw_t option) 1248*4887Schin { 1249*4887Schin #define NORMAL ' ' 1250*4887Schin #define LOWER '<' 1251*4887Schin #define BOTH '*' 1252*4887Schin #define UPPER '>' 1253*4887Schin 1254*4887Schin register genchar *sptr; /* Pointer within screen */ 1255*4887Schin genchar nscreen[2*MAXLINE]; /* New entire screen */ 1256*4887Schin genchar *ncursor; /* New cursor */ 1257*4887Schin register genchar *nptr; /* Pointer to New screen */ 1258*4887Schin char longline; /* Line overflow */ 1259*4887Schin genchar *logcursor; 1260*4887Schin genchar *nscend; /* end of logical screen */ 1261*4887Schin register int i; 1262*4887Schin 1263*4887Schin nptr = nscreen; 1264*4887Schin sptr = drawbuff; 1265*4887Schin logcursor = sptr + cur; 1266*4887Schin longline = NORMAL; 1267*4887Schin 1268*4887Schin if (option == FIRST || option == REFRESH) 1269*4887Schin { 1270*4887Schin ep->overflow = NORMAL; 1271*4887Schin ep->cursor = ep->screen; 1272*4887Schin ep->offset = 0; 1273*4887Schin ep->cr_ok = crallowed; 1274*4887Schin if (option == FIRST) 1275*4887Schin { 1276*4887Schin ep->scvalid = 1; 1277*4887Schin return; 1278*4887Schin } 1279*4887Schin *ep->cursor = '\0'; 1280*4887Schin putstring(ep,Prompt); /* start with prompt */ 1281*4887Schin } 1282*4887Schin 1283*4887Schin /********************* 1284*4887Schin Do not update screen if pending characters 1285*4887Schin **********************/ 1286*4887Schin 1287*4887Schin if ((lookahead)&&(option != FINAL)) 1288*4887Schin { 1289*4887Schin 1290*4887Schin ep->scvalid = 0; /* Screen is out of date, APPEND will not work */ 1291*4887Schin 1292*4887Schin return; 1293*4887Schin } 1294*4887Schin 1295*4887Schin /*************************************** 1296*4887Schin If in append mode, cursor at end of line, screen up to date, 1297*4887Schin the previous character was a 'normal' character, 1298*4887Schin and the window has room for another character. 1299*4887Schin Then output the character and adjust the screen only. 1300*4887Schin *****************************************/ 1301*4887Schin 1302*4887Schin 1303*4887Schin i = *(logcursor-1); /* last character inserted */ 1304*4887Schin 1305*4887Schin if ((option == APPEND)&&(ep->scvalid)&&(*logcursor == '\0')&& 1306*4887Schin print(i)&&((ep->cursor-ep->screen)<(w_size-1))) 1307*4887Schin { 1308*4887Schin putchar(ep->ed,i); 1309*4887Schin *ep->cursor++ = i; 1310*4887Schin *ep->cursor = '\0'; 1311*4887Schin return; 1312*4887Schin } 1313*4887Schin 1314*4887Schin /* copy the line */ 1315*4887Schin ncursor = nptr + ed_virt_to_phys(ep->ed,sptr,nptr,cur,0,0); 1316*4887Schin nptr += genlen(nptr); 1317*4887Schin sptr += genlen(sptr); 1318*4887Schin nscend = nptr - 1; 1319*4887Schin if(sptr == logcursor) 1320*4887Schin ncursor = nptr; 1321*4887Schin 1322*4887Schin /********************* 1323*4887Schin Does ncursor appear on the screen? 1324*4887Schin If not, adjust the screen offset so it does. 1325*4887Schin **********************/ 1326*4887Schin 1327*4887Schin i = ncursor - nscreen; 1328*4887Schin 1329*4887Schin if ((ep->offset && i<=ep->offset)||(i >= (ep->offset+w_size))) 1330*4887Schin { 1331*4887Schin /* Center the cursor on the screen */ 1332*4887Schin ep->offset = i - (w_size>>1); 1333*4887Schin if (--ep->offset < 0) 1334*4887Schin ep->offset = 0; 1335*4887Schin } 1336*4887Schin 1337*4887Schin /********************* 1338*4887Schin Is the range of screen[0] thru screen[w_size] up-to-date 1339*4887Schin with nscreen[offset] thru nscreen[offset+w_size] ? 1340*4887Schin If not, update as need be. 1341*4887Schin ***********************/ 1342*4887Schin 1343*4887Schin nptr = &nscreen[ep->offset]; 1344*4887Schin sptr = ep->screen; 1345*4887Schin 1346*4887Schin i = w_size; 1347*4887Schin 1348*4887Schin while (i-- > 0) 1349*4887Schin { 1350*4887Schin 1351*4887Schin if (*nptr == '\0') 1352*4887Schin { 1353*4887Schin *(nptr + 1) = '\0'; 1354*4887Schin *nptr = ' '; 1355*4887Schin } 1356*4887Schin if (*sptr == '\0') 1357*4887Schin { 1358*4887Schin *(sptr + 1) = '\0'; 1359*4887Schin *sptr = ' '; 1360*4887Schin } 1361*4887Schin if (*nptr == *sptr) 1362*4887Schin { 1363*4887Schin nptr++; 1364*4887Schin sptr++; 1365*4887Schin continue; 1366*4887Schin } 1367*4887Schin setcursor(ep,sptr-ep->screen,*nptr); 1368*4887Schin *sptr++ = *nptr++; 1369*4887Schin #if SHOPT_MULTIBYTE 1370*4887Schin while(*nptr==MARKER) 1371*4887Schin { 1372*4887Schin if(*sptr=='\0') 1373*4887Schin *(sptr + 1) = '\0'; 1374*4887Schin *sptr++ = *nptr++; 1375*4887Schin i--; 1376*4887Schin ep->cursor++; 1377*4887Schin } 1378*4887Schin #endif /* SHOPT_MULTIBYTE */ 1379*4887Schin } 1380*4887Schin 1381*4887Schin /****************** 1382*4887Schin 1383*4887Schin Screen overflow checks 1384*4887Schin 1385*4887Schin ********************/ 1386*4887Schin 1387*4887Schin if (nscend >= &nscreen[ep->offset+w_size]) 1388*4887Schin { 1389*4887Schin if (ep->offset > 0) 1390*4887Schin longline = BOTH; 1391*4887Schin else 1392*4887Schin longline = UPPER; 1393*4887Schin } 1394*4887Schin else 1395*4887Schin { 1396*4887Schin if (ep->offset > 0) 1397*4887Schin longline = LOWER; 1398*4887Schin } 1399*4887Schin 1400*4887Schin /* Update screen overflow indicator if need be */ 1401*4887Schin 1402*4887Schin if (longline != ep->overflow) 1403*4887Schin { 1404*4887Schin setcursor(ep,w_size,longline); 1405*4887Schin ep->overflow = longline; 1406*4887Schin } 1407*4887Schin i = (ncursor-nscreen) - ep->offset; 1408*4887Schin setcursor(ep,i,0); 1409*4887Schin if(option==FINAL && ep->ed->e_multiline) 1410*4887Schin setcursor(ep,nscend-nscreen,0); 1411*4887Schin ep->scvalid = 1; 1412*4887Schin return; 1413*4887Schin } 1414*4887Schin 1415*4887Schin /* 1416*4887Schin * put the cursor to the <newp> position within screen buffer 1417*4887Schin * if <c> is non-zero then output this character 1418*4887Schin * cursor is set to reflect the change 1419*4887Schin */ 1420*4887Schin 1421*4887Schin static void setcursor(register Emacs_t *ep,register int newp,int c) 1422*4887Schin { 1423*4887Schin register int oldp = ep->cursor - ep->screen; 1424*4887Schin newp = ed_setcursor(ep->ed, ep->screen, oldp, newp, 0); 1425*4887Schin if(c) 1426*4887Schin { 1427*4887Schin putchar(ep->ed,c); 1428*4887Schin newp++; 1429*4887Schin } 1430*4887Schin ep->cursor = ep->screen+newp; 1431*4887Schin return; 1432*4887Schin } 1433*4887Schin 1434*4887Schin #if SHOPT_MULTIBYTE 1435*4887Schin static int print(register int c) 1436*4887Schin { 1437*4887Schin return((c&~STRIP)==0 && isprint(c)); 1438*4887Schin } 1439*4887Schin 1440*4887Schin static int _isword(register int c) 1441*4887Schin { 1442*4887Schin return((c&~STRIP) || isalnum(c) || c=='_'); 1443*4887Schin } 1444*4887Schin #endif /* SHOPT_MULTIBYTE */ 1445