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