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