1 /*- 2 * Copyright (c) 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * Copyright (c) 1993, 1994, 1995, 1996 5 * Keith Bostic. All rights reserved. 6 * 7 * See the LICENSE file for redistribution information. 8 */ 9 10 #include "config.h" 11 12 #include <sys/types.h> 13 #include <sys/queue.h> 14 #include <sys/time.h> 15 16 #include <bitstring.h> 17 #include <ctype.h> 18 #include <signal.h> 19 #include <stdio.h> 20 #include <stdlib.h> 21 #include <string.h> 22 #ifdef HAVE_TERM_H 23 #include <term.h> 24 #endif 25 #include <termios.h> 26 #include <unistd.h> 27 28 #include "../common/common.h" 29 #include "../vi/vi.h" 30 #include "cl.h" 31 32 static void cl_rdiv(SCR *); 33 34 static int 35 addstr4(SCR *sp, void *str, size_t len, int wide) 36 { 37 CL_PRIVATE *clp; 38 WINDOW *win; 39 size_t y, x; 40 int iv; 41 42 clp = CLP(sp); 43 win = CLSP(sp) ? CLSP(sp) : stdscr; 44 45 /* 46 * If ex isn't in control, it's the last line of the screen and 47 * it's a split screen, use inverse video. 48 */ 49 iv = 0; 50 getyx(win, y, x); 51 if (!F_ISSET(sp, SC_SCR_EXWROTE) && 52 y == RLNO(sp, LASTLINE(sp)) && IS_SPLIT(sp)) { 53 iv = 1; 54 (void)wstandout(win); 55 } 56 57 #ifdef USE_WIDECHAR 58 if (wide) { 59 if (waddnwstr(win, str, len) == ERR) 60 return (1); 61 } else 62 #endif 63 if (waddnstr(win, str, len) == ERR) 64 return (1); 65 66 if (iv) 67 (void)wstandend(win); 68 return (0); 69 } 70 71 /* 72 * cl_waddstr -- 73 * Add len bytes from the string at the cursor, advancing the cursor. 74 * 75 * PUBLIC: int cl_waddstr(SCR *, const CHAR_T *, size_t); 76 */ 77 int 78 cl_waddstr(SCR *sp, const CHAR_T *str, size_t len) 79 { 80 return addstr4(sp, (void *)str, len, 1); 81 } 82 83 /* 84 * cl_addstr -- 85 * Add len bytes from the string at the cursor, advancing the cursor. 86 * 87 * PUBLIC: int cl_addstr(SCR *, const char *, size_t); 88 */ 89 int 90 cl_addstr(SCR *sp, const char *str, size_t len) 91 { 92 return addstr4(sp, (void *)str, len, 0); 93 } 94 95 /* 96 * cl_attr -- 97 * Toggle a screen attribute on/off. 98 * 99 * PUBLIC: int cl_attr(SCR *, scr_attr_t, int); 100 */ 101 int 102 cl_attr(SCR *sp, scr_attr_t attribute, int on) 103 { 104 CL_PRIVATE *clp; 105 WINDOW *win; 106 107 clp = CLP(sp); 108 win = CLSP(sp) ? CLSP(sp) : stdscr; 109 110 switch (attribute) { 111 case SA_ALTERNATE: 112 /* 113 * !!! 114 * There's a major layering violation here. The problem is that the 115 * X11 xterm screen has what's known as an "alternate" screen. Some 116 * xterm termcap/terminfo entries include sequences to switch to/from 117 * that alternate screen as part of the ti/te (smcup/rmcup) strings. 118 * Vi runs in the alternate screen, so that you are returned to the 119 * same screen contents on exit from vi that you had when you entered 120 * vi. Further, when you run :shell, or :!date or similar ex commands, 121 * you also see the original screen contents. This wasn't deliberate 122 * on vi's part, it's just that it historically sent terminal init/end 123 * sequences at those times, and the addition of the alternate screen 124 * sequences to the strings changed the behavior of vi. The problem 125 * caused by this is that we don't want to switch back to the alternate 126 * screen while getting a new command from the user, when the user is 127 * continuing to enter ex commands, e.g.: 128 * 129 * :!date <<< switch to original screen 130 * [Hit return to continue] <<< prompt user to continue 131 * :command <<< get command from user 132 * 133 * Note that the :command input is a true vi input mode, e.g., input 134 * maps and abbreviations are being done. So, we need to be able to 135 * switch back into the vi screen mode, without flashing the screen. 136 * 137 * To make matters worse, the curses initscr() and endwin() calls will 138 * do this automatically -- so, this attribute isn't as controlled by 139 * the higher level screen as closely as one might like. 140 */ 141 if (on) { 142 if (clp->ti_te != TI_SENT) { 143 clp->ti_te = TI_SENT; 144 if (clp->smcup == NULL) 145 (void)cl_getcap(sp, "smcup", &clp->smcup); 146 if (clp->smcup != NULL) 147 (void)tputs(clp->smcup, 1, cl_putchar); 148 } 149 } else 150 if (clp->ti_te != TE_SENT) { 151 clp->ti_te = TE_SENT; 152 if (clp->rmcup == NULL) 153 (void)cl_getcap(sp, "rmcup", &clp->rmcup); 154 if (clp->rmcup != NULL) 155 (void)tputs(clp->rmcup, 1, cl_putchar); 156 (void)fflush(stdout); 157 } 158 (void)fflush(stdout); 159 break; 160 case SA_INVERSE: 161 if (F_ISSET(sp, SC_EX | SC_SCR_EXWROTE)) { 162 if (clp->smso == NULL) 163 return (1); 164 if (on) 165 (void)tputs(clp->smso, 1, cl_putchar); 166 else 167 (void)tputs(clp->rmso, 1, cl_putchar); 168 (void)fflush(stdout); 169 } else { 170 if (on) 171 (void)wstandout(win); 172 else 173 (void)wstandend(win); 174 } 175 break; 176 default: 177 abort(); 178 } 179 return (0); 180 } 181 182 /* 183 * cl_baud -- 184 * Return the baud rate. 185 * 186 * PUBLIC: int cl_baud(SCR *, u_long *); 187 */ 188 int 189 cl_baud(SCR *sp, u_long *ratep) 190 { 191 CL_PRIVATE *clp; 192 193 /* 194 * XXX 195 * There's no portable way to get a "baud rate" -- cfgetospeed(3) 196 * returns the value associated with some #define, which we may 197 * never have heard of, or which may be a purely local speed. Vi 198 * only cares if it's SLOW (w300), slow (w1200) or fast (w9600). 199 * Try and detect the slow ones, and default to fast. 200 */ 201 clp = CLP(sp); 202 switch (cfgetospeed(&clp->orig)) { 203 case B50: 204 case B75: 205 case B110: 206 case B134: 207 case B150: 208 case B200: 209 case B300: 210 case B600: 211 *ratep = 600; 212 break; 213 case B1200: 214 *ratep = 1200; 215 break; 216 default: 217 *ratep = 9600; 218 break; 219 } 220 return (0); 221 } 222 223 /* 224 * cl_bell -- 225 * Ring the bell/flash the screen. 226 * 227 * PUBLIC: int cl_bell(SCR *); 228 */ 229 int 230 cl_bell(SCR *sp) 231 { 232 if (F_ISSET(sp, SC_EX | SC_SCR_EXWROTE | SC_SCR_EX)) 233 (void)write(STDOUT_FILENO, "\07", 1); /* \a */ 234 else { 235 /* 236 * Vi has an edit option which determines if the terminal 237 * should be beeped or the screen flashed. 238 */ 239 if (O_ISSET(sp, O_FLASH)) 240 (void)flash(); 241 else 242 (void)beep(); 243 } 244 return (0); 245 } 246 247 /* 248 * cl_clrtoeol -- 249 * Clear from the current cursor to the end of the line. 250 * 251 * PUBLIC: int cl_clrtoeol(SCR *); 252 */ 253 int 254 cl_clrtoeol(SCR *sp) 255 { 256 WINDOW *win; 257 #if 0 258 size_t spcnt, y, x; 259 #endif 260 261 win = CLSP(sp) ? CLSP(sp) : stdscr; 262 263 #if 0 264 if (IS_VSPLIT(sp)) { 265 /* The cursor must be returned to its original position. */ 266 getyx(win, y, x); 267 for (spcnt = (sp->coff + sp->cols) - x; spcnt > 0; --spcnt) 268 (void)waddch(win, ' '); 269 (void)wmove(win, y, x); 270 return (0); 271 } else 272 #endif 273 return (wclrtoeol(win) == ERR); 274 } 275 276 /* 277 * cl_cursor -- 278 * Return the current cursor position. 279 * 280 * PUBLIC: int cl_cursor(SCR *, size_t *, size_t *); 281 */ 282 int 283 cl_cursor(SCR *sp, size_t *yp, size_t *xp) 284 { 285 WINDOW *win; 286 win = CLSP(sp) ? CLSP(sp) : stdscr; 287 /* 288 * The curses screen support splits a single underlying curses screen 289 * into multiple screens to support split screen semantics. For this 290 * reason the returned value must be adjusted to be relative to the 291 * current screen, and not absolute. Screens that implement the split 292 * using physically distinct screens won't need this hack. 293 */ 294 getyx(win, *yp, *xp); 295 /* 296 *yp -= sp->roff; 297 *xp -= sp->coff; 298 */ 299 return (0); 300 } 301 302 /* 303 * cl_deleteln -- 304 * Delete the current line, scrolling all lines below it. 305 * 306 * PUBLIC: int cl_deleteln(SCR *); 307 */ 308 int 309 cl_deleteln(SCR *sp) 310 { 311 CL_PRIVATE *clp; 312 WINDOW *win; 313 size_t y, x; 314 315 clp = CLP(sp); 316 win = CLSP(sp) ? CLSP(sp) : stdscr; 317 318 /* 319 * This clause is required because the curses screen uses reverse 320 * video to delimit split screens. If the screen does not do this, 321 * this code won't be necessary. 322 * 323 * If the bottom line was in reverse video, rewrite it in normal 324 * video before it's scrolled. 325 */ 326 if (!F_ISSET(sp, SC_SCR_EXWROTE) && IS_SPLIT(sp)) { 327 getyx(win, y, x); 328 mvwchgat(win, RLNO(sp, LASTLINE(sp)), 0, -1, A_NORMAL, 0, NULL); 329 (void)wmove(win, y, x); 330 } 331 332 /* 333 * The bottom line is expected to be blank after this operation, 334 * and other screens must support that semantic. 335 */ 336 return (wdeleteln(win) == ERR); 337 } 338 339 /* 340 * cl_discard -- 341 * Discard a screen. 342 * 343 * PUBLIC: int cl_discard(SCR *, SCR **); 344 */ 345 int 346 cl_discard(SCR *discardp, SCR **acquirep) 347 { 348 CL_PRIVATE *clp; 349 SCR* tsp; 350 351 if (discardp) { 352 clp = CLP(discardp); 353 F_SET(clp, CL_LAYOUT); 354 355 if (CLSP(discardp)) { 356 delwin(CLSP(discardp)); 357 discardp->cl_private = NULL; 358 } 359 } 360 361 /* no screens got a piece; we're done */ 362 if (!acquirep) 363 return 0; 364 365 for (; (tsp = *acquirep) != NULL; ++acquirep) { 366 clp = CLP(tsp); 367 F_SET(clp, CL_LAYOUT); 368 369 if (CLSP(tsp)) 370 delwin(CLSP(tsp)); 371 tsp->cl_private = subwin(stdscr, tsp->rows, tsp->cols, 372 tsp->roff, tsp->coff); 373 } 374 375 /* discardp is going away, acquirep is taking up its space. */ 376 return (0); 377 } 378 379 /* 380 * cl_ex_adjust -- 381 * Adjust the screen for ex. This routine is purely for standalone 382 * ex programs. All special purpose, all special case. 383 * 384 * PUBLIC: int cl_ex_adjust(SCR *, exadj_t); 385 */ 386 int 387 cl_ex_adjust(SCR *sp, exadj_t action) 388 { 389 CL_PRIVATE *clp; 390 int cnt; 391 392 clp = CLP(sp); 393 switch (action) { 394 case EX_TERM_SCROLL: 395 /* Move the cursor up one line if that's possible. */ 396 if (clp->cuu1 != NULL) 397 (void)tputs(clp->cuu1, 1, cl_putchar); 398 else if (clp->cup != NULL) 399 (void)tputs(tgoto(clp->cup, 400 0, LINES - 2), 1, cl_putchar); 401 else 402 return (0); 403 /* FALLTHROUGH */ 404 case EX_TERM_CE: 405 /* Clear the line. */ 406 if (clp->el != NULL) { 407 (void)putchar('\r'); 408 (void)tputs(clp->el, 1, cl_putchar); 409 } else { 410 /* 411 * Historically, ex didn't erase the line, so, if the 412 * displayed line was only a single glyph, and <eof> 413 * was more than one glyph, the output would not fully 414 * overwrite the user's input. To fix this, output 415 * the maxiumum character number of spaces. Note, 416 * this won't help if the user entered extra prompt 417 * or <blank> characters before the command character. 418 * We'd have to do a lot of work to make that work, and 419 * it's almost certainly not worth the effort. 420 */ 421 for (cnt = 0; cnt < MAX_CHARACTER_COLUMNS; ++cnt) 422 (void)putchar('\b'); 423 for (cnt = 0; cnt < MAX_CHARACTER_COLUMNS; ++cnt) 424 (void)putchar(' '); 425 (void)putchar('\r'); 426 (void)fflush(stdout); 427 } 428 break; 429 default: 430 abort(); 431 } 432 return (0); 433 } 434 435 /* 436 * cl_insertln -- 437 * Push down the current line, discarding the bottom line. 438 * 439 * PUBLIC: int cl_insertln(SCR *); 440 */ 441 int 442 cl_insertln(SCR *sp) 443 { 444 WINDOW *win; 445 win = CLSP(sp) ? CLSP(sp) : stdscr; 446 /* 447 * The current line is expected to be blank after this operation, 448 * and the screen must support that semantic. 449 */ 450 return (winsertln(win) == ERR); 451 } 452 453 /* 454 * cl_keyval -- 455 * Return the value for a special key. 456 * 457 * PUBLIC: int cl_keyval(SCR *, scr_keyval_t, CHAR_T *, int *); 458 */ 459 int 460 cl_keyval(SCR *sp, scr_keyval_t val, CHAR_T *chp, int *dnep) 461 { 462 CL_PRIVATE *clp; 463 464 /* 465 * VEOF, VERASE and VKILL are required by POSIX 1003.1-1990, 466 * VWERASE is a 4BSD extension. 467 */ 468 clp = CLP(sp); 469 switch (val) { 470 case KEY_VEOF: 471 *dnep = (*chp = clp->orig.c_cc[VEOF]) == _POSIX_VDISABLE; 472 break; 473 case KEY_VERASE: 474 *dnep = (*chp = clp->orig.c_cc[VERASE]) == _POSIX_VDISABLE; 475 break; 476 case KEY_VKILL: 477 *dnep = (*chp = clp->orig.c_cc[VKILL]) == _POSIX_VDISABLE; 478 break; 479 #ifdef VWERASE 480 case KEY_VWERASE: 481 *dnep = (*chp = clp->orig.c_cc[VWERASE]) == _POSIX_VDISABLE; 482 break; 483 #endif 484 default: 485 *dnep = 1; 486 break; 487 } 488 return (0); 489 } 490 491 /* 492 * cl_move -- 493 * Move the cursor. 494 * 495 * PUBLIC: int cl_move(SCR *, size_t, size_t); 496 */ 497 int 498 cl_move(SCR *sp, size_t lno, size_t cno) 499 { 500 WINDOW *win; 501 win = CLSP(sp) ? CLSP(sp) : stdscr; 502 /* See the comment in cl_cursor. */ 503 if (wmove(win, RLNO(sp, lno), RCNO(sp, cno)) == ERR) { 504 msgq(sp, M_ERR, "Error: move: l(%zu + %zu) c(%zu + %zu)", 505 lno, sp->roff, cno, sp->coff); 506 return (1); 507 } 508 return (0); 509 } 510 511 /* 512 * cl_refresh -- 513 * Refresh the screen. 514 * 515 * PUBLIC: int cl_refresh(SCR *, int); 516 */ 517 int 518 cl_refresh(SCR *sp, int repaint) 519 { 520 GS *gp; 521 CL_PRIVATE *clp; 522 WINDOW *win; 523 SCR *psp, *tsp; 524 size_t y, x; 525 526 gp = sp->gp; 527 clp = CLP(sp); 528 win = CLSP(sp) ? CLSP(sp) : stdscr; 529 530 /* 531 * If we received a killer signal, we're done, there's no point 532 * in refreshing the screen. 533 */ 534 if (clp->killersig) 535 return (0); 536 537 /* 538 * If repaint is set, the editor is telling us that we don't know 539 * what's on the screen, so we have to repaint from scratch. 540 * 541 * If repaint set or the screen layout changed, we need to redraw 542 * any lines separating vertically split screens. If the horizontal 543 * offsets are the same, then the split was vertical, and need to 544 * draw a dividing line. 545 */ 546 if (repaint || F_ISSET(clp, CL_LAYOUT)) { 547 getyx(stdscr, y, x); 548 for (psp = sp; psp != NULL; psp = TAILQ_NEXT(psp, q)) 549 for (tsp = TAILQ_NEXT(psp, q); tsp != NULL; 550 tsp = TAILQ_NEXT(tsp, q)) 551 if (psp->roff == tsp->roff) { 552 if (psp->coff + psp->cols + 1 == tsp->coff) 553 cl_rdiv(psp); 554 else 555 if (tsp->coff + tsp->cols + 1 == psp->coff) 556 cl_rdiv(tsp); 557 } 558 (void)wmove(stdscr, y, x); 559 F_CLR(clp, CL_LAYOUT); 560 } 561 562 /* 563 * In the curses library, doing wrefresh(curscr) is okay, but the 564 * screen flashes when we then apply the refresh() to bring it up 565 * to date. So, use clearok(). 566 */ 567 if (repaint) 568 clearok(curscr, 1); 569 /* 570 * Only do an actual refresh, when this is the focus window, 571 * i.e. the one holding the cursor. This assumes that refresh 572 * is called for that window after refreshing the others. 573 * This prevents the cursor being drawn in the other windows. 574 */ 575 return (wnoutrefresh(stdscr) == ERR || 576 wnoutrefresh(win) == ERR || 577 (sp == clp->focus && doupdate() == ERR)); 578 } 579 580 /* 581 * cl_rdiv -- 582 * Draw a dividing line between two vertically split screens. 583 */ 584 static void 585 cl_rdiv(SCR *sp) 586 { 587 #ifdef __NetBSD__ 588 mvvline(sp->roff, sp->cols + sp->coff, '|', sp->rows); 589 #else 590 mvvline(sp->roff, sp->cols + sp->coff, ACS_VLINE, sp->rows); 591 #endif 592 } 593 594 /* 595 * cl_rename -- 596 * Rename the file. 597 * 598 * PUBLIC: int cl_rename(SCR *, char *, int); 599 */ 600 int 601 cl_rename(SCR *sp, char *name, int on) 602 { 603 GS *gp; 604 CL_PRIVATE *clp; 605 FILE *pfp; 606 char buf[256], *s, *e; 607 char * wid; 608 char cmd[64]; 609 610 gp = sp->gp; 611 clp = CLP(sp); 612 613 /* 614 * XXX 615 * We can only rename windows for xterm. 616 */ 617 if (on) { 618 clp->focus = sp; 619 if (!F_ISSET(clp, CL_RENAME_OK) || 620 strncmp(OG_STR(gp, GO_TERM), "xterm", 5)) 621 return (0); 622 623 if (clp->oname == NULL && (wid = getenv("WINDOWID"))) { 624 snprintf(cmd, sizeof(cmd), "xprop -id %s WM_NAME", wid); 625 if ((pfp = popen(cmd, "r")) == NULL) 626 goto rename; 627 if (fgets(buf, sizeof(buf), pfp) == NULL) { 628 pclose(pfp); 629 goto rename; 630 } 631 pclose(pfp); 632 if ((s = strchr(buf, '"')) != NULL && 633 (e = strrchr(buf, '"')) != NULL) 634 clp->oname = strndup(s + 1, e - s - 1); 635 } 636 637 rename: cl_setname(gp, name); 638 639 F_SET(clp, CL_RENAME); 640 } else 641 if (F_ISSET(clp, CL_RENAME)) { 642 cl_setname(gp, clp->oname); 643 644 F_CLR(clp, CL_RENAME); 645 } 646 return (0); 647 } 648 649 /* 650 * cl_setname -- 651 * Set a X11 icon/window name. 652 * 653 * PUBLIC: void cl_setname(GS *, char *); 654 */ 655 void 656 cl_setname(GS *gp, char *name) 657 { 658 /* X11 xterm escape sequence to rename the icon/window. */ 659 #define XTERM_RENAME "\033]0;%s\007" 660 661 (void)printf(XTERM_RENAME, name == NULL ? OG_STR(gp, GO_TERM) : name); 662 (void)fflush(stdout); 663 #undef XTERM_RENAME 664 } 665 666 /* 667 * cl_split -- 668 * Split a screen. 669 * 670 * PUBLIC: int cl_split(SCR *, SCR *); 671 */ 672 int 673 cl_split(SCR *origp, SCR *newp) 674 { 675 CL_PRIVATE *clp; 676 677 clp = CLP(origp); 678 F_SET(clp, CL_LAYOUT); 679 680 if (CLSP(origp)) 681 delwin(CLSP(origp)); 682 683 origp->cl_private = subwin(stdscr, origp->rows, origp->cols, 684 origp->roff, origp->coff); 685 newp->cl_private = subwin(stdscr, newp->rows, newp->cols, 686 newp->roff, newp->coff); 687 688 /* origp is the original screen, giving up space to newp. */ 689 return (0); 690 } 691 692 /* 693 * cl_suspend -- 694 * Suspend a screen. 695 * 696 * PUBLIC: int cl_suspend(SCR *, int *); 697 */ 698 int 699 cl_suspend(SCR *sp, int *allowedp) 700 { 701 struct termios t; 702 CL_PRIVATE *clp; 703 WINDOW *win; 704 GS *gp; 705 size_t y, x; 706 int changed; 707 708 gp = sp->gp; 709 clp = CLP(sp); 710 win = CLSP(sp) ? CLSP(sp) : stdscr; 711 *allowedp = 1; 712 713 /* 714 * The ex implementation of this function isn't needed by screens not 715 * supporting ex commands that require full terminal canonical mode 716 * (e.g. :suspend). 717 * 718 * The vi implementation of this function isn't needed by screens not 719 * supporting vi process suspension, i.e. any screen that isn't backed 720 * by a UNIX shell. 721 * 722 * Setting allowedp to 0 will cause the editor to reject the command. 723 */ 724 if (F_ISSET(sp, SC_EX)) { 725 /* Save the terminal settings, and restore the original ones. */ 726 if (F_ISSET(clp, CL_STDIN_TTY)) { 727 (void)tcgetattr(STDIN_FILENO, &t); 728 (void)tcsetattr(STDIN_FILENO, 729 TCSASOFT | TCSADRAIN, &clp->orig); 730 } 731 732 /* Stop the process group. */ 733 (void)kill(0, SIGTSTP); 734 735 /* Time passes ... */ 736 737 /* Restore terminal settings. */ 738 if (F_ISSET(clp, CL_STDIN_TTY)) 739 (void)tcsetattr(STDIN_FILENO, TCSASOFT | TCSADRAIN, &t); 740 return (0); 741 } 742 743 /* 744 * Move to the lower left-hand corner of the screen. 745 * 746 * XXX 747 * Not sure this is necessary in System V implementations, but it 748 * shouldn't hurt. 749 */ 750 getyx(win, y, x); 751 (void)wmove(win, LINES - 1, 0); 752 (void)wrefresh(win); 753 754 /* 755 * Temporarily end the screen. System V introduced a semantic where 756 * endwin() could be restarted. We use it because restarting curses 757 * from scratch often fails in System V. 4BSD curses didn't support 758 * restarting after endwin(), so we have to do what clean up we can 759 * without calling it. 760 */ 761 /* Save the terminal settings. */ 762 (void)tcgetattr(STDIN_FILENO, &t); 763 764 /* Restore the cursor keys to normal mode. */ 765 (void)keypad(stdscr, FALSE); 766 767 /* Restore the window name. */ 768 (void)cl_rename(sp, NULL, 0); 769 770 (void)endwin(); 771 772 /* 773 * XXX 774 * Restore the original terminal settings. This is bad -- the 775 * reset can cause character loss from the tty queue. However, 776 * we can't call endwin() in BSD curses implementations, and too 777 * many System V curses implementations don't get it right. 778 */ 779 (void)tcsetattr(STDIN_FILENO, TCSADRAIN | TCSASOFT, &clp->orig); 780 781 /* Stop the process group. */ 782 (void)kill(0, SIGTSTP); 783 784 /* Time passes ... */ 785 786 /* 787 * If we received a killer signal, we're done. Leave everything 788 * unchanged. In addition, the terminal has already been reset 789 * correctly, so leave it alone. 790 */ 791 if (clp->killersig) { 792 F_CLR(clp, CL_SCR_EX_INIT | CL_SCR_VI_INIT); 793 return (0); 794 } 795 796 /* Restore terminal settings. */ 797 wrefresh(win); /* Needed on SunOs/Solaris ? */ 798 if (F_ISSET(clp, CL_STDIN_TTY)) 799 (void)tcsetattr(STDIN_FILENO, TCSASOFT | TCSADRAIN, &t); 800 801 /* Set the window name. */ 802 (void)cl_rename(sp, sp->frp->name, 1); 803 804 /* Put the cursor keys into application mode. */ 805 (void)keypad(stdscr, TRUE); 806 807 /* Refresh and repaint the screen. */ 808 (void)wmove(win, y, x); 809 (void)cl_refresh(sp, 1); 810 811 /* If the screen changed size, set the SIGWINCH bit. */ 812 if (cl_ssize(sp, 1, NULL, NULL, &changed)) 813 return (1); 814 if (changed) 815 F_SET(CLP(sp), CL_SIGWINCH); 816 817 return (0); 818 } 819 820 /* 821 * cl_usage -- 822 * Print out the curses usage messages. 823 * 824 * PUBLIC: void cl_usage(void); 825 */ 826 void 827 cl_usage(void) 828 { 829 #define USAGE "\ 830 usage: ex [-eFRrSsv] [-c command] [-t tag] [-w size] [file ...]\n\ 831 usage: vi [-eFlRrSv] [-c command] [-t tag] [-w size] [file ...]\n" 832 (void)fprintf(stderr, "%s", USAGE); 833 #undef USAGE 834 } 835 836 #ifdef DEBUG 837 /* 838 * gdbrefresh -- 839 * Stub routine so can flush out curses screen changes using gdb. 840 */ 841 static int 842 __attribute__((unused)) 843 gdbrefresh(void) 844 { 845 refresh(); 846 return (0); /* XXX Convince gdb to run it. */ 847 } 848 #endif 849