1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 27 /* All Rights Reserved */ 28 29 30 /* Copyright (c) 1981 Regents of the University of California */ 31 32 #include <sys/stropts.h> 33 #include <sys/eucioctl.h> 34 #ifndef PRESUNEUC 35 #include <locale.h> 36 /* Undef putchar/getchar if they're defined. */ 37 #ifdef putchar 38 # undef putchar 39 #endif 40 #ifdef getchar 41 # undef getchar 42 #endif 43 #endif /* PRESUNEUC */ 44 45 #include "ex.h" 46 #include "ex_re.h" 47 #include "ex_tty.h" 48 #include "ex_vis.h" 49 50 /* 51 * Random routines, in alphabetical order. 52 */ 53 54 int 55 any(int c, unsigned char *s) 56 { 57 int x; 58 59 while (x = *s++) 60 if (x == c) 61 return (1); 62 return (0); 63 } 64 65 int 66 backtab(int i) 67 { 68 int j; 69 70 j = i % value(vi_SHIFTWIDTH); 71 if (j == 0) 72 j = value(vi_SHIFTWIDTH); 73 i -= j; 74 if (i < 0) 75 i = 0; 76 return (i); 77 } 78 79 void 80 change(void) 81 { 82 83 tchng++; 84 chng = tchng; 85 } 86 87 /* 88 * Column returns the number of 89 * columns occupied by printing the 90 * characters through position cp of the 91 * current line. 92 */ 93 int 94 column(unsigned char *cp) 95 { 96 97 if (cp == 0) 98 cp = &linebuf[LBSIZE - 2]; 99 return (qcolumn(cp, (unsigned char *)0)); 100 } 101 102 /* lcolumn is same as column except it returns number of columns 103 * occupied by characters before position 104 * cp of the current line 105 */ 106 int 107 lcolumn(unsigned char *cp) 108 { 109 110 if (cp == 0) 111 cp = &linebuf[LBSIZE - 2]; 112 return (nqcolumn(lastchr(linebuf, cp), (unsigned char *)0)); 113 } 114 115 /* 116 * Ignore a comment to the end of the line. 117 * This routine eats the trailing newline so don't call donewline(). 118 */ 119 void 120 comment(void) 121 { 122 int c; 123 124 do { 125 c = getchar(); 126 } while (c != '\n' && c != EOF); 127 if (c == EOF) 128 ungetchar(c); 129 } 130 131 void 132 Copy(unsigned char *to, unsigned char *from, int size) 133 { 134 135 if (size > 0) 136 do 137 *to++ = *from++; 138 while (--size > 0); 139 } 140 141 void 142 copyw(line *to, line *from, int size) 143 { 144 145 if (size > 0) 146 do 147 *to++ = *from++; 148 while (--size > 0); 149 } 150 151 void 152 copywR(line *to, line *from, int size) 153 { 154 155 while (--size >= 0) 156 to[size] = from[size]; 157 } 158 159 int 160 ctlof(int c) 161 { 162 163 return (c == DELETE ? '?' : c | ('A' - 1)); 164 } 165 166 void 167 dingdong(void) 168 { 169 170 if (flash_screen && value(vi_FLASH)) 171 putpad((unsigned char *)flash_screen); 172 else if (value(vi_ERRORBELLS)) 173 putpad((unsigned char *)bell); 174 } 175 176 int 177 fixindent(int indent) 178 { 179 int i; 180 unsigned char *cp; 181 182 i = whitecnt(genbuf); 183 cp = vpastwh(genbuf); 184 if (*cp == 0 && i == indent && linebuf[0] == 0) { 185 genbuf[0] = 0; 186 return (i); 187 } 188 CP(genindent(i), cp); 189 return (i); 190 } 191 192 void 193 filioerr(unsigned char *cp) 194 { 195 int oerrno = errno; 196 197 lprintf("\"%s\"", cp); 198 errno = oerrno; 199 syserror(1); 200 } 201 202 unsigned char * 203 genindent(indent) 204 int indent; 205 { 206 unsigned char *cp; 207 208 for (cp = genbuf; indent >= value(vi_TABSTOP); indent -= value(vi_TABSTOP)) 209 *cp++ = '\t'; 210 for (; indent > 0; indent--) 211 *cp++ = ' '; 212 return (cp); 213 } 214 215 void 216 getDOT(void) 217 { 218 219 getaline(*dot); 220 } 221 222 line * 223 getmark(c) 224 int c; 225 { 226 line *addr; 227 228 for (addr = one; addr <= dol; addr++) 229 if (names[c - 'a'] == (*addr &~ 01)) { 230 return (addr); 231 } 232 return (0); 233 } 234 235 void 236 ignnEOF(void) 237 { 238 int c = getchar(); 239 240 if (c == EOF) 241 ungetchar(c); 242 else if (c=='"') 243 comment(); 244 } 245 246 int 247 iswhite(int c) 248 { 249 250 return (c == ' ' || c == '\t'); 251 } 252 253 int 254 junk(wchar_t c) 255 { 256 257 if (c && !value(vi_BEAUTIFY)) 258 return (0); 259 if (c >= ' ' && c != DELETE) 260 return (0); 261 switch (c) { 262 263 case '\t': 264 case '\n': 265 case '\f': 266 return (0); 267 268 default: 269 return (1); 270 } 271 } 272 273 void 274 killed(void) 275 { 276 277 killcnt(addr2 - addr1 + 1); 278 } 279 280 void 281 killcnt(int cnt) 282 { 283 extern char *verbalize(); 284 285 if (inopen) { 286 notecnt = cnt; 287 notenam = notesgn = (unsigned char *)""; 288 return; 289 } 290 if (!notable(cnt)) 291 return; 292 if (value(vi_TERSE) == 0) { 293 verbalize(cnt, Command, ""); 294 } else { 295 if (cnt == 1) { 296 viprintf(gettext("1 line"), cnt); 297 } else { 298 viprintf(gettext("%d lines"), cnt); 299 } 300 } 301 putNFL(); 302 } 303 304 int 305 lineno(line *a) 306 { 307 308 return (a - zero); 309 } 310 311 int 312 lineDOL(void) 313 { 314 315 return (lineno(dol)); 316 } 317 318 int 319 lineDOT(void) 320 { 321 322 return (lineno(dot)); 323 } 324 325 void 326 markDOT(void) 327 { 328 329 markpr(dot); 330 } 331 332 void 333 markpr(line *which) 334 { 335 336 if ((inglobal == 0 || inopen) && which <= endcore) { 337 names['z'-'a'+1] = *which & ~01; 338 if (inopen) 339 ncols['z'-'a'+1] = cursor; 340 } 341 } 342 343 int 344 markreg(int c) 345 { 346 347 if (c == '\'' || c == '`') 348 return ('z' + 1); 349 if (c >= 'a' && c <= 'z') 350 return (c); 351 return (0); 352 } 353 354 /* 355 * Mesg decodes the terse/verbose strings. Thus 356 * 'xxx@yyy' -> 'xxx' if terse, else 'xxx yyy' 357 * 'xxx|yyy' -> 'xxx' if terse, else 'yyy' 358 * All others map to themselves. 359 */ 360 /* 361 * The feature described above was disabled for localizable messaging. 362 */ 363 unsigned char * 364 mesg(str) 365 unsigned char *str; 366 { 367 unsigned char *cp; 368 369 str = (unsigned char *)strcpy(genbuf, str); 370 /* commented out for localizable messaging */ 371 /* for (cp = str; *cp; cp++) 372 switch (*cp) { 373 374 case '@': 375 if (value(vi_TERSE)) 376 *cp = 0; 377 else 378 *cp = ' '; 379 break; 380 381 case '|': 382 if (value(vi_TERSE) == 0) 383 return (cp + 1); 384 *cp = 0; 385 break; 386 } */ 387 return (str); 388 } 389 390 /*VARARGS2*/ 391 void 392 merror(unsigned char *seekpt, int i) 393 { 394 unsigned char *cp = linebuf; 395 396 if (seekpt == 0) 397 return; 398 merror1(seekpt); 399 if (*cp == '\n') 400 putnl(), cp++; 401 if (inopen > 0 && clr_eol) 402 vclreol(); 403 if (enter_standout_mode && exit_bold) 404 putpad((unsigned char *)enter_standout_mode); 405 #ifdef PRESUNEUC 406 viprintf(mesg(cp), i); 407 #else 408 viprintf((char *)mesg(cp), i); 409 #endif /* PRESUNEUC */ 410 if (enter_standout_mode && exit_bold) 411 putpad((unsigned char *)exit_bold); 412 } 413 414 void 415 merror1(unsigned char *seekpt) 416 { 417 418 strcpy(linebuf, seekpt); 419 } 420 421 #define MAXDATA (56*1024) 422 int 423 morelines(void) 424 { 425 unsigned char *end; 426 427 if ((int) sbrk(1024 * sizeof (line)) == -1) { 428 if (endcore >= (line *) MAXDATA) 429 return -1; 430 end = (unsigned char *) MAXDATA; 431 /* 432 * Ask for end+2 sice we want end to be the last used location. 433 */ 434 while (brk(end+2) == -1) 435 end -= 64; 436 if (end <= (unsigned char *) endcore) 437 return -1; 438 endcore = (line *) end; 439 } else { 440 endcore += 1024; 441 } 442 return (0); 443 } 444 445 void 446 nonzero(void) 447 { 448 449 if (addr1 == zero) { 450 notempty(); 451 error(value(vi_TERSE) ? gettext("Nonzero address required") : 452 gettext("Nonzero address required on this command")); 453 } 454 } 455 456 int 457 notable(int i) 458 { 459 460 return (hush == 0 && !inglobal && i > value(vi_REPORT)); 461 } 462 463 464 void 465 notempty(void) 466 { 467 468 if (dol == zero) 469 error(value(vi_TERSE) ? gettext("No lines") : 470 gettext("No lines in the buffer")); 471 } 472 473 474 void 475 netchHAD(int cnt) 476 { 477 478 netchange(lineDOL() - cnt); 479 } 480 481 void 482 netchange(int i) 483 { 484 unsigned char *cp; 485 486 if (i > 0) 487 notesgn = cp = (unsigned char *)"more "; 488 else 489 notesgn = cp = (unsigned char *)"fewer ", i = -i; 490 if (inopen) { 491 notecnt = i; 492 notenam = (unsigned char *)""; 493 return; 494 } 495 if (!notable(i)) 496 return; 497 if (*cp == 'm') /* for ease of messge localization */ 498 #ifdef PRESUNEUC 499 viprintf(mesg(value(vi_TERSE) ? 500 #else 501 viprintf((char *)mesg(value(vi_TERSE) ? 502 #endif /* PRESUNEUC */ 503 gettext("%d more lines") : 504 /* 505 * TRANSLATION_NOTE 506 * Reference order of arguments must not 507 * be changed using '%digit$', since vi's 508 * viprintf() does not support it. 509 */ 510 gettext("%d more lines in file after %s")), i, Command); 511 else 512 #ifdef PRESUNEUC 513 viprintf(mesg(value(vi_TERSE) ? 514 #else 515 viprintf((char *)mesg(value(vi_TERSE) ? 516 #endif /* PRESUNEUC */ 517 gettext("%d fewer lines") : 518 /* 519 * TRANSLATION_NOTE 520 * Reference order of arguments must not 521 * be changed using '%digit$', since vi's 522 * viprintf() does not support it. 523 */ 524 gettext("%d fewer lines in file after %s")), i, Command); 525 putNFL(); 526 } 527 528 void 529 putmark(line *addr) 530 { 531 532 putmk1(addr, putline()); 533 } 534 535 void 536 putmk1(line *addr, int n) 537 { 538 line *markp; 539 int oldglobmk; 540 541 oldglobmk = *addr & 1; 542 *addr &= ~1; 543 for (markp = (anymarks ? names : &names['z'-'a'+1]); 544 markp <= &names['z'-'a'+1]; markp++) 545 if (*markp == *addr) 546 *markp = n; 547 *addr = n | oldglobmk; 548 } 549 550 unsigned char * 551 plural(i) 552 long i; 553 { 554 555 return (i == 1 ? (unsigned char *)"" : (unsigned char *)"s"); 556 } 557 558 int qcount(); 559 short vcntcol; 560 561 int 562 qcolumn(unsigned char *lim, unsigned char *gp) 563 { 564 int x, length; 565 int col; 566 wchar_t wchar; 567 int (*OO)(); 568 569 OO = Outchar; 570 Outchar = qcount; 571 vcntcol = 0; 572 if (lim != NULL) { 573 if(lim == linebuf - 1 || lim == &linebuf[LBSIZE-2]) 574 length = 1; 575 else 576 length = mbtowc(&wchar, (char *)lim, MULTI_BYTE_MAX); 577 if(length < 0) 578 length = 1; 579 x = lim[length]; 580 lim[length] = 0; 581 } 582 pline(0); 583 if (lim != NULL) 584 lim[length] = x; 585 if(length > 1 && !gp) { 586 /* put cursor at beginning of multibyte character */ 587 if ((col = wcwidth(wchar)) < 0) 588 col = 0; 589 vcntcol = vcntcol - col + 1; 590 } 591 if (gp) 592 while (*gp) { 593 length = mbtowc(&wchar, (char *)gp, MULTI_BYTE_MAX); 594 if(length < 0) { 595 putoctal = 1; 596 putchar(*gp++); 597 putoctal = 0; 598 } else { 599 putchar(wchar); 600 gp += length; 601 } 602 } 603 Outchar = OO; 604 return (vcntcol); 605 } 606 607 /* This routine puts cursor after multibyte character */ 608 int 609 nqcolumn(unsigned char *lim, unsigned char *gp) 610 { 611 int x, length; 612 wchar_t wchar; 613 int (*OO)(); 614 615 OO = Outchar; 616 Outchar = qcount; 617 vcntcol = 0; 618 if (lim != NULL) { 619 if(lim == linebuf - 1 || lim == &linebuf[LBSIZE-2]) 620 length = 1; 621 else 622 length = mbtowc(&wchar, (char *)lim, MULTI_BYTE_MAX); 623 if(length < 0) 624 length = 1; 625 x = lim[length]; 626 lim[length] = 0; 627 } 628 pline(0); 629 if (lim != NULL) 630 lim[length] = x; 631 if (gp) 632 while (*gp) { 633 length = mbtowc(&wchar, (char *)gp, MULTI_BYTE_MAX); 634 if(length < 0) { 635 putoctal = 1; 636 putchar(*gp++); 637 putoctal = 0; 638 } else { 639 putchar(wchar); 640 gp += length; 641 } 642 } 643 Outchar = OO; 644 return (vcntcol); 645 } 646 647 int 648 qcount(c) 649 wchar_t c; 650 { 651 int cols; 652 #ifndef PRESUNEUC 653 int remcols; 654 short OWCOLS; 655 #endif /* PRESUNEUC */ 656 657 if (c == '\t') { 658 vcntcol += value(vi_TABSTOP) - vcntcol % value(vi_TABSTOP); 659 return (0); 660 } 661 #ifdef PRESUNEUC 662 if ((cols = wcwidth(c)) > 0) 663 vcntcol += cols; 664 #else 665 if ((cols = wcwidth(c)) < 0) 666 cols = 0; 667 OWCOLS = WCOLS; 668 if (WCOLS == 0) 669 WCOLS = columns; 670 if ((mc_wrap) == 1 && (remcols = (WCOLS - (vcntcol % WCOLS))) < cols) 671 vcntcol += remcols; 672 WCOLS = OWCOLS; 673 vcntcol += cols; 674 #endif /* PRESUNEUC */ 675 return (0); 676 } 677 678 void 679 reverse(line *a1, line *a2) 680 { 681 line t; 682 683 for (;;) { 684 t = *--a2; 685 if (a2 <= a1) 686 return; 687 *a2 = *a1; 688 *a1++ = t; 689 } 690 } 691 692 void 693 save(line *a1, line *a2) 694 { 695 int more; 696 697 if (!FIXUNDO) 698 return; 699 #ifdef UNDOTRACE 700 if (trace) 701 vudump("before save"); 702 #endif 703 undkind = UNDNONE; 704 undadot = dot; 705 more = (a2 - a1 + 1) - (unddol - dol); 706 while (more > (endcore - truedol)) 707 if (morelines() < 0) 708 error(value(vi_TERSE) ? gettext("Out of memory") : 709 gettext("Out of memory saving lines for undo - try using ed")); 710 if (more) 711 (*(more > 0 ? copywR : copyw))(unddol + more + 1, unddol + 1, 712 (truedol - unddol)); 713 unddol += more; 714 truedol += more; 715 copyw(dol + 1, a1, a2 - a1 + 1); 716 undkind = UNDALL; 717 unddel = a1 - 1; 718 undap1 = a1; 719 undap2 = a2 + 1; 720 #ifdef UNDOTRACE 721 if (trace) 722 vudump("after save"); 723 #endif 724 } 725 726 void 727 save12(void) 728 { 729 730 save(addr1, addr2); 731 } 732 733 void 734 saveall(void) 735 { 736 737 save(one, dol); 738 } 739 740 int 741 span(void) 742 { 743 744 return (addr2 - addr1 + 1); 745 } 746 747 void 748 sync(void) 749 { 750 751 chng = 0; 752 tchng = 0; 753 xchng = 0; 754 } 755 756 757 int 758 skipwh(void) 759 { 760 int wh; 761 762 wh = 0; 763 while (iswhite(peekchar())) { 764 wh++; 765 ignchar(); 766 } 767 return (wh); 768 } 769 770 /*VARARGS2*/ 771 void 772 smerror(unsigned char *seekpt, unsigned char *cp) 773 { 774 775 errcnt++; 776 merror1(seekpt); 777 if (inopen && clr_eol) 778 vclreol(); 779 if (enter_standout_mode && exit_bold) 780 putpad((unsigned char *)enter_standout_mode); 781 lprintf(mesg(linebuf), cp); 782 if (enter_standout_mode && exit_bold) 783 putpad((unsigned char *)exit_bold); 784 } 785 786 unsigned char * 787 strend(cp) 788 unsigned char *cp; 789 { 790 791 while (*cp) 792 cp++; 793 return (cp); 794 } 795 796 void 797 strcLIN(unsigned char *dp) 798 { 799 800 CP(linebuf, dp); 801 } 802 803 /* 804 * A system error has occurred that we need to perror. 805 * danger is true if we are unsure of the contents of 806 * the file or our buffer, e.g. a write error in the 807 * middle of a write operation, or a temp file error. 808 */ 809 void 810 syserror(int danger) 811 { 812 int e = errno; 813 char *errstr; 814 extern char *strerror(); 815 816 dirtcnt = 0; 817 putchar(' '); 818 if (danger) 819 edited = 0; /* for temp file errors, for example */ 820 if ((errstr = strerror(e)) != NULL) 821 error(errstr); 822 else 823 error(gettext("System error %d"), e); 824 } 825 826 /* 827 * Return the column number that results from being in column col and 828 * hitting a tab, where tabs are set every ts columns. Work right for 829 * the case where col > columns, even if ts does not divide columns. 830 */ 831 int 832 tabcol(int col, int ts) 833 { 834 int offset, result; 835 836 if (col >= columns) { 837 offset = columns * (col/columns); 838 col -= offset; 839 } else 840 offset = 0; 841 result = col + ts - (col % ts) + offset; 842 return (result); 843 } 844 845 unsigned char * 846 vfindcol(i) 847 int i; 848 { 849 unsigned char *cp, *oldcp; 850 int (*OO)() = Outchar; 851 int length; 852 unsigned char x; 853 wchar_t wchar; 854 855 Outchar = qcount; 856 (void) qcolumn(linebuf - 1, (unsigned char *)NOSTR); 857 for (cp = linebuf; *cp && vcntcol < i; ) { 858 oldcp = cp; 859 length = mbtowc(&wchar, (char *)cp, MULTI_BYTE_MAX); 860 if(length < 0) { 861 putoctal = 1; 862 putchar(*cp++); 863 putoctal = 0; 864 } else { 865 putchar(wchar); 866 cp += length; 867 } 868 } 869 if (cp != linebuf) 870 cp = oldcp; 871 Outchar = OO; 872 return (cp); 873 } 874 875 unsigned char * 876 vskipwh(cp) 877 unsigned char *cp; 878 { 879 880 while (iswhite(*cp) && cp[1]) 881 cp++; 882 return (cp); 883 } 884 885 886 unsigned char * 887 vpastwh(cp) 888 unsigned char *cp; 889 { 890 891 while (iswhite(*cp)) 892 cp++; 893 return (cp); 894 } 895 896 int 897 whitecnt(unsigned char *cp) 898 { 899 int i; 900 901 i = 0; 902 for (;;) 903 switch (*cp++) { 904 905 case '\t': 906 i += value(vi_TABSTOP) - i % value(vi_TABSTOP); 907 break; 908 909 case ' ': 910 i++; 911 break; 912 913 default: 914 return (i); 915 } 916 } 917 918 void 919 markit(line *addr) 920 { 921 922 if (addr != dot && addr >= one && addr <= dol) 923 markDOT(); 924 } 925 926 /* 927 * When a hangup occurs our actions are similar to a preserve 928 * command. If the buffer has not been [Modified], then we do 929 * nothing but remove the temporary files and exit. 930 * Otherwise, we sync the temp file and then attempt a preserve. 931 * If the preserve succeeds, we unlink our temp files. 932 * If the preserve fails, we leave the temp files as they are 933 * as they are a backup even without preservation if they 934 * are not removed. 935 */ 936 937 /*ARGSUSED*/ 938 void 939 onhup(sig) 940 int sig; 941 { 942 943 /* 944 * USG tty driver can send multiple HUP's!! 945 */ 946 signal(SIGINT, SIG_IGN); 947 signal(SIGHUP, SIG_IGN); 948 if (chng == 0) { 949 cleanup(1); 950 exit(++errcnt); 951 } 952 if (setexit() == 0) { 953 if (preserve()) { 954 cleanup(1); 955 exit(++errcnt); 956 } 957 } 958 if (kflag) 959 crypt_close(perm); 960 if (xtflag) 961 crypt_close(tperm); 962 exit(++errcnt); 963 } 964 965 /* 966 * Similar to onhup. This happens when any random core dump occurs, 967 * e.g. a bug in vi. We preserve the file and then generate a core. 968 */ 969 void oncore(sig) 970 int sig; 971 { 972 static int timescalled = 0; 973 char *messagep; /* for message localization */ 974 975 /* 976 * USG tty driver can send multiple HUP's!! 977 */ 978 signal(SIGINT, SIG_IGN); 979 signal(SIGHUP, SIG_IGN); 980 signal(sig, SIG_DFL); /* Insure that we don't catch it again */ 981 messagep = (char *)gettext("\r\nYour file has been preserved\r\n"); 982 if (timescalled++ == 0 && chng && setexit() == 0) { 983 if (inopen) 984 vsave(); 985 (void) preserve(); 986 write(1, messagep, strlen(messagep)); 987 } 988 if (timescalled < 2) { 989 normal(normf); 990 cleanup(2); 991 kill(getpid(), sig); /* Resend ourselves the same signal */ 992 /* We won't get past here */ 993 } 994 if (kflag) 995 crypt_close(perm); 996 if (xtflag) 997 crypt_close(tperm); 998 exit(++errcnt); 999 } 1000 1001 /* 1002 * An interrupt occurred. Drain any output which 1003 * is still in the output buffering pipeline. 1004 * Catch interrupts again. Unless we are in visual 1005 * reset the output state (out of -nl mode, e.g). 1006 * Then like a normal error (with the \n before Interrupt 1007 * suppressed in visual mode). 1008 */ 1009 1010 /*ARGSUSED*/ 1011 void 1012 onintr(sig) 1013 int sig; 1014 { 1015 #ifndef CBREAK 1016 signal(SIGINT, onintr); 1017 #else 1018 signal(SIGINT, inopen ? vintr : onintr); 1019 #endif 1020 cancelalarm(); 1021 draino(); 1022 if (!inopen) { 1023 pstop(); 1024 setlastchar('\n'); 1025 #ifdef CBREAK 1026 } 1027 #else 1028 } else 1029 vraw(); 1030 #endif 1031 error(gettext("\nInterrupt") + (inopen!=0)); 1032 } 1033 1034 /* 1035 * If we are interruptible, enable interrupts again. 1036 * In some critical sections we turn interrupts off, 1037 * but not very often. 1038 */ 1039 void 1040 setrupt(void) 1041 { 1042 1043 if (ruptible) { 1044 #ifndef CBREAK 1045 signal(SIGINT, onintr); 1046 #else 1047 signal(SIGINT, inopen ? vintr : onintr); 1048 #endif 1049 #ifdef SIGTSTP 1050 if (dosusp) 1051 signal(SIGTSTP, onsusp); 1052 #endif 1053 } 1054 } 1055 1056 int 1057 preserve(void) 1058 { 1059 1060 #ifdef VMUNIX 1061 tflush(); 1062 #endif 1063 synctmp(); 1064 pid = fork(); 1065 if (pid < 0) 1066 return (0); 1067 if (pid == 0) { 1068 close(0); 1069 dup(tfile); 1070 execlp(EXPRESERVE, "expreserve", (char *) 0); 1071 exit(++errcnt); 1072 } 1073 waitfor(); 1074 if (rpid == pid && status == 0) 1075 return (1); 1076 return (0); 1077 } 1078 1079 #ifndef V6 1080 void exit(i) 1081 int i; 1082 { 1083 1084 extern void _exit(int) __NORETURN; 1085 #ifdef TRACE 1086 if (trace) 1087 fclose(trace); 1088 #endif 1089 _exit(i); 1090 } 1091 #endif 1092 1093 #ifdef SIGTSTP 1094 /* 1095 * We have just gotten a susp. Suspend and prepare to resume. 1096 */ 1097 extern void redraw(); 1098 1099 /*ARGSUSED*/ 1100 void 1101 onsusp(sig) 1102 int sig; 1103 { 1104 ttymode f; 1105 int savenormtty; 1106 1107 f = setty(normf); 1108 vnfl(); 1109 putpad((unsigned char *)exit_ca_mode); 1110 flush(); 1111 resetterm(); 1112 savenormtty = normtty; 1113 normtty = 0; 1114 1115 signal(SIGTSTP, SIG_DFL); 1116 kill(0, SIGTSTP); 1117 1118 /* the pc stops here */ 1119 1120 signal(SIGTSTP, onsusp); 1121 normtty = savenormtty; 1122 vcontin(0); 1123 flush(); 1124 setty(f); 1125 if (!inopen) 1126 syserror(0); 1127 else { 1128 if(vcnt < 0) { 1129 vcnt = -vcnt; 1130 if(state == VISUAL) 1131 vclear(); 1132 else if(state == CRTOPEN) 1133 vcnt = 0; 1134 } 1135 vdirty(0, lines); 1136 if (sig) 1137 vrepaint(cursor); 1138 } 1139 } 1140 #endif 1141 1142 unsigned char *nextchr(cursor) 1143 unsigned char *cursor; 1144 { 1145 1146 wchar_t wchar; 1147 int length; 1148 length = mbtowc(&wchar, (char *)cursor, MULTI_BYTE_MAX); 1149 if(length <= 0) 1150 return(++cursor); 1151 return(cursor + length); 1152 } 1153 1154 unsigned char *lastchr(linebuf, cursor) 1155 unsigned char *linebuf, *cursor; 1156 { 1157 wchar_t wchar; 1158 int length; 1159 unsigned char *ccursor, *ocursor; 1160 if(cursor == linebuf) 1161 return(linebuf - 1); 1162 ccursor = ocursor = linebuf; 1163 while(ccursor < cursor) { 1164 length = mbtowc(&wchar, (char *)ccursor, MULTI_BYTE_MAX); 1165 ocursor = ccursor; 1166 if(length <= 0) 1167 ccursor++; 1168 else 1169 ccursor += length; 1170 } 1171 return(ocursor); 1172 } 1173 1174 int 1175 ixlatctl(int flag) 1176 { 1177 static struct strioctl sb = {0, 0, 0, 0}; 1178 1179 if (!(MULTI_BYTE_MAX > 1)) 1180 return (0); 1181 1182 switch (flag) { 1183 case 0: 1184 sb.ic_cmd = EUC_MSAVE; 1185 sb.ic_len = 0; 1186 sb.ic_dp = 0; 1187 if (ioctl(0, I_STR, &sb) < 0) 1188 return (-1); 1189 return (0); 1190 case 1: 1191 sb.ic_cmd = EUC_MREST; 1192 sb.ic_len = 0; 1193 sb.ic_dp = 0; 1194 if (ioctl(0, I_STR, &sb) < 0) 1195 return (-1); 1196 return (0); 1197 case 11: 1198 return (0); 1199 default: 1200 return (-1); 1201 } 1202 } 1203 #ifndef PRESUNEUC 1204 1205 /* locale specific initialization */ 1206 void 1207 localize(void) 1208 { 1209 wchar_t fillerchar; 1210 extern int wdchkind(); 1211 extern int wdbindf(); 1212 extern wchar_t *wddelim(); 1213 extern wchar_t mcfiller(); 1214 1215 wdwc = wdchkind; 1216 wdbdg = wdbindf; 1217 wddlm = wddelim; 1218 mcfllr = mcfiller; 1219 mc_wrap = 1; 1220 fillerchar = mcfiller(); 1221 mc_filler = isascii(fillerchar) ? (fillerchar & 0x7f) : '~'; 1222 } 1223 #endif /* PRESUNEUC */ 1224