119304Speter/*- 219304Speter * Copyright (c) 1993, 1994 319304Speter * The Regents of the University of California. All rights reserved. 419304Speter * Copyright (c) 1993, 1994, 1995, 1996 519304Speter * Keith Bostic. All rights reserved. 619304Speter * 719304Speter * See the LICENSE file for redistribution information. 819304Speter */ 919304Speter 1019304Speter#include "config.h" 1119304Speter 1219304Speter#ifndef lint 1319304Speterstatic const char sccsid[] = "@(#)cl_funcs.c 10.50 (Berkeley) 9/24/96"; 1419304Speter#endif /* not lint */ 1519304Speter 1619304Speter#include <sys/types.h> 1719304Speter#include <sys/queue.h> 1819304Speter#include <sys/time.h> 1919304Speter 2019304Speter#include <bitstring.h> 2119304Speter#include <ctype.h> 2219304Speter#include <curses.h> 2319304Speter#include <signal.h> 2419304Speter#include <stdio.h> 2519304Speter#include <stdlib.h> 2619304Speter#include <string.h> 2719304Speter#include <termios.h> 2819304Speter#include <unistd.h> 2919304Speter 3019304Speter#include "../common/common.h" 3119304Speter#include "../vi/vi.h" 3219304Speter#include "cl.h" 3319304Speter 3419304Speter/* 3519304Speter * cl_addstr -- 3619304Speter * Add len bytes from the string at the cursor, advancing the cursor. 3719304Speter * 3819304Speter * PUBLIC: int cl_addstr __P((SCR *, const char *, size_t)); 3919304Speter */ 4019304Speterint 4119304Spetercl_addstr(sp, str, len) 4219304Speter SCR *sp; 4319304Speter const char *str; 4419304Speter size_t len; 4519304Speter{ 4619304Speter CL_PRIVATE *clp; 4719304Speter size_t oldy, oldx; 4819304Speter int iv; 4919304Speter 5019304Speter clp = CLP(sp); 5119304Speter 5219304Speter /* 5319304Speter * If ex isn't in control, it's the last line of the screen and 5419304Speter * it's a split screen, use inverse video. 5519304Speter */ 5619304Speter iv = 0; 5719304Speter getyx(stdscr, oldy, oldx); 5819304Speter if (!F_ISSET(sp, SC_SCR_EXWROTE) && 5919304Speter oldy == RLNO(sp, LASTLINE(sp)) && IS_SPLIT(sp)) { 6019304Speter iv = 1; 6119304Speter (void)standout(); 6219304Speter } 6319304Speter 6419304Speter if (addnstr(str, len) == ERR) 6519304Speter return (1); 6619304Speter 6719304Speter if (iv) 6819304Speter (void)standend(); 6919304Speter return (0); 7019304Speter} 7119304Speter 7219304Speter/* 7319304Speter * cl_attr -- 7419304Speter * Toggle a screen attribute on/off. 7519304Speter * 7619304Speter * PUBLIC: int cl_attr __P((SCR *, scr_attr_t, int)); 7719304Speter */ 7819304Speterint 7919304Spetercl_attr(sp, attribute, on) 8019304Speter SCR *sp; 8119304Speter scr_attr_t attribute; 8219304Speter int on; 8319304Speter{ 8419304Speter CL_PRIVATE *clp; 8519304Speter 8619304Speter clp = CLP(sp); 8719304Speter 8819304Speter switch (attribute) { 8919304Speter case SA_ALTERNATE: 9019304Speter /* 9119304Speter * !!! 9219304Speter * There's a major layering violation here. The problem is that the 9319304Speter * X11 xterm screen has what's known as an "alternate" screen. Some 9419304Speter * xterm termcap/terminfo entries include sequences to switch to/from 9519304Speter * that alternate screen as part of the ti/te (smcup/rmcup) strings. 9619304Speter * Vi runs in the alternate screen, so that you are returned to the 9719304Speter * same screen contents on exit from vi that you had when you entered 9819304Speter * vi. Further, when you run :shell, or :!date or similar ex commands, 9919304Speter * you also see the original screen contents. This wasn't deliberate 10019304Speter * on vi's part, it's just that it historically sent terminal init/end 10119304Speter * sequences at those times, and the addition of the alternate screen 10219304Speter * sequences to the strings changed the behavior of vi. The problem 10319304Speter * caused by this is that we don't want to switch back to the alternate 10419304Speter * screen while getting a new command from the user, when the user is 10519304Speter * continuing to enter ex commands, e.g.: 10619304Speter * 10719304Speter * :!date <<< switch to original screen 10819304Speter * [Hit return to continue] <<< prompt user to continue 10919304Speter * :command <<< get command from user 11019304Speter * 11119304Speter * Note that the :command input is a true vi input mode, e.g., input 11219304Speter * maps and abbreviations are being done. So, we need to be able to 11319304Speter * switch back into the vi screen mode, without flashing the screen. 11419304Speter * 11519304Speter * To make matters worse, the curses initscr() and endwin() calls will 11619304Speter * do this automatically -- so, this attribute isn't as controlled by 11719304Speter * the higher level screen as closely as one might like. 11819304Speter */ 11919304Speter if (on) { 12019304Speter if (clp->ti_te != TI_SENT) { 12119304Speter clp->ti_te = TI_SENT; 12219304Speter if (clp->smcup == NULL) 12319304Speter (void)cl_getcap(sp, "smcup", &clp->smcup); 12419304Speter if (clp->smcup != NULL) 12519304Speter (void)tputs(clp->smcup, 1, cl_putchar); 12619304Speter } 12719304Speter } else 12819304Speter if (clp->ti_te != TE_SENT) { 12919304Speter clp->ti_te = TE_SENT; 13019304Speter if (clp->rmcup == NULL) 13119304Speter (void)cl_getcap(sp, "rmcup", &clp->rmcup); 13219304Speter if (clp->rmcup != NULL) 13319304Speter (void)tputs(clp->rmcup, 1, cl_putchar); 13419304Speter (void)fflush(stdout); 13519304Speter } 13619304Speter (void)fflush(stdout); 13719304Speter break; 13819304Speter case SA_INVERSE: 13919304Speter if (F_ISSET(sp, SC_EX | SC_SCR_EXWROTE)) { 14019304Speter if (clp->smso == NULL) 14119304Speter return (1); 14219304Speter if (on) 14319304Speter (void)tputs(clp->smso, 1, cl_putchar); 14419304Speter else 14519304Speter (void)tputs(clp->rmso, 1, cl_putchar); 14619304Speter (void)fflush(stdout); 14719304Speter } else { 14819304Speter if (on) 14919304Speter (void)standout(); 15019304Speter else 15119304Speter (void)standend(); 15219304Speter } 15319304Speter break; 15419304Speter default: 15519304Speter abort(); 15619304Speter } 15719304Speter return (0); 15819304Speter} 15919304Speter 16019304Speter/* 16119304Speter * cl_baud -- 16219304Speter * Return the baud rate. 16319304Speter * 16419304Speter * PUBLIC: int cl_baud __P((SCR *, u_long *)); 16519304Speter */ 16619304Speterint 16719304Spetercl_baud(sp, ratep) 16819304Speter SCR *sp; 16919304Speter u_long *ratep; 17019304Speter{ 17119304Speter CL_PRIVATE *clp; 17219304Speter 17319304Speter /* 17419304Speter * XXX 17519304Speter * There's no portable way to get a "baud rate" -- cfgetospeed(3) 17619304Speter * returns the value associated with some #define, which we may 17719304Speter * never have heard of, or which may be a purely local speed. Vi 17819304Speter * only cares if it's SLOW (w300), slow (w1200) or fast (w9600). 17919304Speter * Try and detect the slow ones, and default to fast. 18019304Speter */ 18119304Speter clp = CLP(sp); 18219304Speter switch (cfgetospeed(&clp->orig)) { 18319304Speter case B50: 18419304Speter case B75: 18519304Speter case B110: 18619304Speter case B134: 18719304Speter case B150: 18819304Speter case B200: 18919304Speter case B300: 19019304Speter case B600: 19119304Speter *ratep = 600; 19219304Speter break; 19319304Speter case B1200: 19419304Speter *ratep = 1200; 19519304Speter break; 19619304Speter default: 19719304Speter *ratep = 9600; 19819304Speter break; 19919304Speter } 20019304Speter return (0); 20119304Speter} 20219304Speter 20319304Speter/* 20419304Speter * cl_bell -- 20519304Speter * Ring the bell/flash the screen. 20619304Speter * 20719304Speter * PUBLIC: int cl_bell __P((SCR *)); 20819304Speter */ 20919304Speterint 21019304Spetercl_bell(sp) 21119304Speter SCR *sp; 21219304Speter{ 21319304Speter if (F_ISSET(sp, SC_EX | SC_SCR_EXWROTE)) 21419304Speter (void)write(STDOUT_FILENO, "\07", 1); /* \a */ 21519304Speter else { 21619304Speter /* 21719304Speter * Vi has an edit option which determines if the terminal 21819304Speter * should be beeped or the screen flashed. 21919304Speter */ 22019304Speter if (O_ISSET(sp, O_FLASH)) 22119304Speter (void)flash(); 22219304Speter else 22319304Speter (void)beep(); 22419304Speter } 22519304Speter return (0); 22619304Speter} 22719304Speter 22819304Speter/* 22919304Speter * cl_clrtoeol -- 23019304Speter * Clear from the current cursor to the end of the line. 23119304Speter * 23219304Speter * PUBLIC: int cl_clrtoeol __P((SCR *)); 23319304Speter */ 23419304Speterint 23519304Spetercl_clrtoeol(sp) 23619304Speter SCR *sp; 23719304Speter{ 23819304Speter return (clrtoeol() == ERR); 23919304Speter} 24019304Speter 24119304Speter/* 24219304Speter * cl_cursor -- 24319304Speter * Return the current cursor position. 24419304Speter * 24519304Speter * PUBLIC: int cl_cursor __P((SCR *, size_t *, size_t *)); 24619304Speter */ 24719304Speterint 24819304Spetercl_cursor(sp, yp, xp) 24919304Speter SCR *sp; 25019304Speter size_t *yp, *xp; 25119304Speter{ 25219304Speter /* 25319304Speter * The curses screen support splits a single underlying curses screen 25419304Speter * into multiple screens to support split screen semantics. For this 25519304Speter * reason the returned value must be adjusted to be relative to the 25619304Speter * current screen, and not absolute. Screens that implement the split 25719304Speter * using physically distinct screens won't need this hack. 25819304Speter */ 25919304Speter getyx(stdscr, *yp, *xp); 26019304Speter *yp -= sp->woff; 26119304Speter return (0); 26219304Speter} 26319304Speter 26419304Speter/* 26519304Speter * cl_deleteln -- 26619304Speter * Delete the current line, scrolling all lines below it. 26719304Speter * 26819304Speter * PUBLIC: int cl_deleteln __P((SCR *)); 26919304Speter */ 27019304Speterint 27119304Spetercl_deleteln(sp) 27219304Speter SCR *sp; 27319304Speter{ 27419304Speter CHAR_T ch; 27519304Speter CL_PRIVATE *clp; 27619304Speter size_t col, lno, spcnt, oldy, oldx; 27719304Speter 27819304Speter clp = CLP(sp); 27919304Speter 28019304Speter /* 28119304Speter * This clause is required because the curses screen uses reverse 28219304Speter * video to delimit split screens. If the screen does not do this, 28319304Speter * this code won't be necessary. 28419304Speter * 28519304Speter * If the bottom line was in reverse video, rewrite it in normal 28619304Speter * video before it's scrolled. 28719304Speter * 28819304Speter * Check for the existence of a chgat function; XSI requires it, but 28919304Speter * historic implementations of System V curses don't. If it's not 29019304Speter * a #define, we'll fall back to doing it by hand, which is slow but 29119304Speter * acceptable. 29219304Speter * 29319304Speter * By hand means walking through the line, retrieving and rewriting 29419304Speter * each character. Curses has no EOL marker, so track strings of 29519304Speter * spaces, and copy the trailing spaces only if there's a non-space 29619304Speter * character following. 29719304Speter */ 29819304Speter if (!F_ISSET(sp, SC_SCR_EXWROTE) && IS_SPLIT(sp)) { 29919304Speter getyx(stdscr, oldy, oldx); 30019304Speter#ifdef mvchgat 30119304Speter mvchgat(RLNO(sp, LASTLINE(sp)), 0, -1, A_NORMAL, 0, NULL); 30219304Speter#else 30319304Speter for (lno = RLNO(sp, LASTLINE(sp)), col = spcnt = 0;;) { 30419304Speter (void)move(lno, col); 30519304Speter ch = winch(stdscr); 30619304Speter if (isblank(ch)) 30719304Speter ++spcnt; 30819304Speter else { 30919304Speter (void)move(lno, col - spcnt); 31019304Speter for (; spcnt > 0; --spcnt) 31119304Speter (void)addch(' '); 31219304Speter (void)addch(ch); 31319304Speter } 31419304Speter if (++col >= sp->cols) 31519304Speter break; 31619304Speter } 31719304Speter#endif 31819304Speter (void)move(oldy, oldx); 31919304Speter } 32019304Speter 32119304Speter /* 32219304Speter * The bottom line is expected to be blank after this operation, 32319304Speter * and other screens must support that semantic. 32419304Speter */ 32519304Speter return (deleteln() == ERR); 32619304Speter} 32719304Speter 32819304Speter/* 32919304Speter * cl_ex_adjust -- 33019304Speter * Adjust the screen for ex. This routine is purely for standalone 33119304Speter * ex programs. All special purpose, all special case. 33219304Speter * 33319304Speter * PUBLIC: int cl_ex_adjust __P((SCR *, exadj_t)); 33419304Speter */ 33519304Speterint 33619304Spetercl_ex_adjust(sp, action) 33719304Speter SCR *sp; 33819304Speter exadj_t action; 33919304Speter{ 34019304Speter CL_PRIVATE *clp; 34119304Speter int cnt; 34219304Speter 34319304Speter clp = CLP(sp); 34419304Speter switch (action) { 34519304Speter case EX_TERM_SCROLL: 34619304Speter /* Move the cursor up one line if that's possible. */ 34719304Speter if (clp->cuu1 != NULL) 34819304Speter (void)tputs(clp->cuu1, 1, cl_putchar); 34919304Speter else if (clp->cup != NULL) 35019304Speter (void)tputs(tgoto(clp->cup, 35119304Speter 0, LINES - 2), 1, cl_putchar); 35219304Speter else 35319304Speter return (0); 35419304Speter /* FALLTHROUGH */ 35519304Speter case EX_TERM_CE: 35619304Speter /* Clear the line. */ 35719304Speter if (clp->el != NULL) { 35819304Speter (void)putchar('\r'); 35919304Speter (void)tputs(clp->el, 1, cl_putchar); 36019304Speter } else { 36119304Speter /* 36219304Speter * Historically, ex didn't erase the line, so, if the 36319304Speter * displayed line was only a single glyph, and <eof> 36419304Speter * was more than one glyph, the output would not fully 36519304Speter * overwrite the user's input. To fix this, output 36619304Speter * the maxiumum character number of spaces. Note, 36719304Speter * this won't help if the user entered extra prompt 36819304Speter * or <blank> characters before the command character. 36919304Speter * We'd have to do a lot of work to make that work, and 37019304Speter * it's almost certainly not worth the effort. 37119304Speter */ 37219304Speter for (cnt = 0; cnt < MAX_CHARACTER_COLUMNS; ++cnt) 37319304Speter (void)putchar('\b'); 37419304Speter for (cnt = 0; cnt < MAX_CHARACTER_COLUMNS; ++cnt) 37519304Speter (void)putchar(' '); 37619304Speter (void)putchar('\r'); 37719304Speter (void)fflush(stdout); 37819304Speter } 37919304Speter break; 38019304Speter default: 38119304Speter abort(); 38219304Speter } 38319304Speter return (0); 38419304Speter} 38519304Speter 38619304Speter/* 38719304Speter * cl_insertln -- 38819304Speter * Push down the current line, discarding the bottom line. 38919304Speter * 39019304Speter * PUBLIC: int cl_insertln __P((SCR *)); 39119304Speter */ 39219304Speterint 39319304Spetercl_insertln(sp) 39419304Speter SCR *sp; 39519304Speter{ 39619304Speter /* 39719304Speter * The current line is expected to be blank after this operation, 39819304Speter * and the screen must support that semantic. 39919304Speter */ 40019304Speter return (insertln() == ERR); 40119304Speter} 40219304Speter 40319304Speter/* 40419304Speter * cl_keyval -- 40519304Speter * Return the value for a special key. 40619304Speter * 40719304Speter * PUBLIC: int cl_keyval __P((SCR *, scr_keyval_t, CHAR_T *, int *)); 40819304Speter */ 40919304Speterint 41019304Spetercl_keyval(sp, val, chp, dnep) 41119304Speter SCR *sp; 41219304Speter scr_keyval_t val; 41319304Speter CHAR_T *chp; 41419304Speter int *dnep; 41519304Speter{ 41619304Speter CL_PRIVATE *clp; 41719304Speter 41819304Speter /* 41919304Speter * VEOF, VERASE and VKILL are required by POSIX 1003.1-1990, 42019304Speter * VWERASE is a 4BSD extension. 42119304Speter */ 42219304Speter clp = CLP(sp); 42319304Speter switch (val) { 42419304Speter case KEY_VEOF: 42519304Speter *dnep = (*chp = clp->orig.c_cc[VEOF]) == _POSIX_VDISABLE; 42619304Speter break; 42719304Speter case KEY_VERASE: 42819304Speter *dnep = (*chp = clp->orig.c_cc[VERASE]) == _POSIX_VDISABLE; 42919304Speter break; 43019304Speter case KEY_VKILL: 43119304Speter *dnep = (*chp = clp->orig.c_cc[VKILL]) == _POSIX_VDISABLE; 43219304Speter break; 43319304Speter#ifdef VWERASE 43419304Speter case KEY_VWERASE: 43519304Speter *dnep = (*chp = clp->orig.c_cc[VWERASE]) == _POSIX_VDISABLE; 43619304Speter break; 43719304Speter#endif 43819304Speter default: 43919304Speter *dnep = 1; 44019304Speter break; 44119304Speter } 44219304Speter return (0); 44319304Speter} 44419304Speter 44519304Speter/* 44619304Speter * cl_move -- 44719304Speter * Move the cursor. 44819304Speter * 44919304Speter * PUBLIC: int cl_move __P((SCR *, size_t, size_t)); 45019304Speter */ 45119304Speterint 45219304Spetercl_move(sp, lno, cno) 45319304Speter SCR *sp; 45419304Speter size_t lno, cno; 45519304Speter{ 45619304Speter /* See the comment in cl_cursor. */ 45719304Speter if (move(RLNO(sp, lno), cno) == ERR) { 45819304Speter msgq(sp, M_ERR, 45919304Speter "Error: move: l(%u) c(%u) o(%u)", lno, cno, sp->woff); 46019304Speter return (1); 46119304Speter } 46219304Speter return (0); 46319304Speter} 46419304Speter 46519304Speter/* 46619304Speter * cl_refresh -- 46719304Speter * Refresh the screen. 46819304Speter * 46919304Speter * PUBLIC: int cl_refresh __P((SCR *, int)); 47019304Speter */ 47119304Speterint 47219304Spetercl_refresh(sp, repaint) 47319304Speter SCR *sp; 47419304Speter int repaint; 47519304Speter{ 47619304Speter CL_PRIVATE *clp; 47719304Speter 47819304Speter clp = CLP(sp); 47919304Speter 48019304Speter /* 48119304Speter * If we received a killer signal, we're done, there's no point 48219304Speter * in refreshing the screen. 48319304Speter */ 48419304Speter if (clp->killersig) 48519304Speter return (0); 48619304Speter 48719304Speter /* 48819304Speter * If repaint is set, the editor is telling us that we don't know 48919304Speter * what's on the screen, so we have to repaint from scratch. 49019304Speter * 49119304Speter * In the curses library, doing wrefresh(curscr) is okay, but the 49219304Speter * screen flashes when we then apply the refresh() to bring it up 49319304Speter * to date. So, use clearok(). 49419304Speter */ 49519304Speter if (repaint) 49619304Speter clearok(curscr, 1); 49719304Speter return (refresh() == ERR); 49819304Speter} 49919304Speter 50019304Speter/* 50119304Speter * cl_rename -- 50219304Speter * Rename the file. 50319304Speter * 50419304Speter * PUBLIC: int cl_rename __P((SCR *, char *, int)); 50519304Speter */ 50619304Speterint 50719304Spetercl_rename(sp, name, on) 50819304Speter SCR *sp; 50919304Speter char *name; 51019304Speter int on; 51119304Speter{ 51219304Speter GS *gp; 51319304Speter CL_PRIVATE *clp; 51419304Speter char *ttype; 51519304Speter 51619304Speter gp = sp->gp; 51719304Speter clp = CLP(sp); 51819304Speter 51919304Speter ttype = OG_STR(gp, GO_TERM); 52019304Speter 52119304Speter /* 52219304Speter * XXX 52319304Speter * We can only rename windows for xterm. 52419304Speter */ 52519304Speter if (on) { 52619304Speter if (F_ISSET(clp, CL_RENAME_OK) && 52719304Speter !strncmp(ttype, "xterm", sizeof("xterm") - 1)) { 52819304Speter F_SET(clp, CL_RENAME); 52919304Speter (void)printf(XTERM_RENAME, name); 53019304Speter (void)fflush(stdout); 53119304Speter } 53219304Speter } else 53319304Speter if (F_ISSET(clp, CL_RENAME)) { 53419304Speter F_CLR(clp, CL_RENAME); 53519304Speter (void)printf(XTERM_RENAME, ttype); 53619304Speter (void)fflush(stdout); 53719304Speter } 53819304Speter return (0); 53919304Speter} 54019304Speter 54119304Speter/* 54219304Speter * cl_suspend -- 54319304Speter * Suspend a screen. 54419304Speter * 54519304Speter * PUBLIC: int cl_suspend __P((SCR *, int *)); 54619304Speter */ 54719304Speterint 54819304Spetercl_suspend(sp, allowedp) 54919304Speter SCR *sp; 55019304Speter int *allowedp; 55119304Speter{ 55219304Speter struct termios t; 55319304Speter CL_PRIVATE *clp; 55419304Speter GS *gp; 55519304Speter size_t oldy, oldx; 55619304Speter int changed; 55719304Speter 55819304Speter gp = sp->gp; 55919304Speter clp = CLP(sp); 56019304Speter *allowedp = 1; 56119304Speter 56219304Speter /* 56319304Speter * The ex implementation of this function isn't needed by screens not 56419304Speter * supporting ex commands that require full terminal canonical mode 56519304Speter * (e.g. :suspend). 56619304Speter * 56719304Speter * The vi implementation of this function isn't needed by screens not 56819304Speter * supporting vi process suspension, i.e. any screen that isn't backed 56919304Speter * by a UNIX shell. 57019304Speter * 57119304Speter * Setting allowedp to 0 will cause the editor to reject the command. 57219304Speter */ 57319304Speter if (F_ISSET(sp, SC_EX)) { 57419304Speter /* Save the terminal settings, and restore the original ones. */ 57519304Speter if (F_ISSET(clp, CL_STDIN_TTY)) { 57619304Speter (void)tcgetattr(STDIN_FILENO, &t); 57719304Speter (void)tcsetattr(STDIN_FILENO, 57819304Speter TCSASOFT | TCSADRAIN, &clp->orig); 57919304Speter } 58019304Speter 58119304Speter /* Stop the process group. */ 58219304Speter (void)kill(0, SIGTSTP); 58319304Speter 58419304Speter /* Time passes ... */ 58519304Speter 58619304Speter /* Restore terminal settings. */ 58719304Speter if (F_ISSET(clp, CL_STDIN_TTY)) 58819304Speter (void)tcsetattr(STDIN_FILENO, TCSASOFT | TCSADRAIN, &t); 58919304Speter return (0); 59019304Speter } 59119304Speter 59219304Speter /* 59319304Speter * Move to the lower left-hand corner of the screen. 59419304Speter * 59519304Speter * XXX 59619304Speter * Not sure this is necessary in System V implementations, but it 59719304Speter * shouldn't hurt. 59819304Speter */ 59919304Speter getyx(stdscr, oldy, oldx); 60019304Speter (void)move(LINES - 1, 0); 60119304Speter (void)refresh(); 60219304Speter 60319304Speter /* 60419304Speter * Temporarily end the screen. System V introduced a semantic where 60519304Speter * endwin() could be restarted. We use it because restarting curses 60619304Speter * from scratch often fails in System V. 4BSD curses didn't support 60719304Speter * restarting after endwin(), so we have to do what clean up we can 60819304Speter * without calling it. 60919304Speter */ 61019304Speter#ifdef HAVE_BSD_CURSES 61119304Speter /* Save the terminal settings. */ 61219304Speter (void)tcgetattr(STDIN_FILENO, &t); 61319304Speter#endif 61419304Speter 61519304Speter /* Restore the cursor keys to normal mode. */ 61619304Speter (void)keypad(stdscr, FALSE); 61719304Speter 61819304Speter /* Restore the window name. */ 61919304Speter (void)cl_rename(sp, NULL, 0); 62019304Speter 62119304Speter#ifdef HAVE_BSD_CURSES 62219304Speter (void)cl_attr(sp, SA_ALTERNATE, 0); 62319304Speter#else 62419304Speter (void)endwin(); 62519304Speter#endif 62619304Speter /* 62719304Speter * XXX 62819304Speter * Restore the original terminal settings. This is bad -- the 62919304Speter * reset can cause character loss from the tty queue. However, 63019304Speter * we can't call endwin() in BSD curses implementations, and too 63119304Speter * many System V curses implementations don't get it right. 63219304Speter */ 63319304Speter (void)tcsetattr(STDIN_FILENO, TCSADRAIN | TCSASOFT, &clp->orig); 63419304Speter 63519304Speter /* Stop the process group. */ 63619304Speter (void)kill(0, SIGTSTP); 63719304Speter 63819304Speter /* Time passes ... */ 63919304Speter 64019304Speter /* 64119304Speter * If we received a killer signal, we're done. Leave everything 64219304Speter * unchanged. In addition, the terminal has already been reset 64319304Speter * correctly, so leave it alone. 64419304Speter */ 64519304Speter if (clp->killersig) { 64619304Speter F_CLR(clp, CL_SCR_EX_INIT | CL_SCR_VI_INIT); 64719304Speter return (0); 64819304Speter } 64919304Speter 65019304Speter#ifdef HAVE_BSD_CURSES 65119304Speter /* Restore terminal settings. */ 65219304Speter if (F_ISSET(clp, CL_STDIN_TTY)) 65319304Speter (void)tcsetattr(STDIN_FILENO, TCSASOFT | TCSADRAIN, &t); 65419304Speter 65519304Speter (void)cl_attr(sp, SA_ALTERNATE, 1); 65619304Speter#endif 65719304Speter 65819304Speter /* Set the window name. */ 65919304Speter (void)cl_rename(sp, sp->frp->name, 1); 66019304Speter 66119304Speter /* Put the cursor keys into application mode. */ 66219304Speter (void)keypad(stdscr, TRUE); 66319304Speter 66419304Speter /* Refresh and repaint the screen. */ 66519304Speter (void)move(oldy, oldx); 66619304Speter (void)cl_refresh(sp, 1); 66719304Speter 66819304Speter /* If the screen changed size, set the SIGWINCH bit. */ 66919304Speter if (cl_ssize(sp, 1, NULL, NULL, &changed)) 67019304Speter return (1); 67119304Speter if (changed) 67219304Speter F_SET(CLP(sp), CL_SIGWINCH); 67319304Speter 67419304Speter return (0); 67519304Speter} 67619304Speter 67719304Speter/* 67819304Speter * cl_usage -- 67919304Speter * Print out the curses usage messages. 68019304Speter * 68119304Speter * PUBLIC: void cl_usage __P((void)); 68219304Speter */ 68319304Spetervoid 68419304Spetercl_usage() 68519304Speter{ 68619304Speter#define USAGE "\ 68719304Speterusage: ex [-eFRrSsv] [-c command] [-t tag] [-w size] [file ...]\n\ 68819304Speterusage: vi [-eFlRrSv] [-c command] [-t tag] [-w size] [file ...]\n" 68919304Speter (void)fprintf(stderr, "%s", USAGE); 69019304Speter#undef USAGE 69119304Speter} 69219304Speter 69319304Speter#ifdef DEBUG 69419304Speter/* 69519304Speter * gdbrefresh -- 69619304Speter * Stub routine so can flush out curses screen changes using gdb. 69719304Speter */ 69819304Speterint 69919304Spetergdbrefresh() 70019304Speter{ 70119304Speter refresh(); 70219304Speter return (0); /* XXX Convince gdb to run it. */ 70319304Speter} 70419304Speter#endif 705