home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Spezial / SPEZIAL2_97.zip / SPEZIAL2_97.iso / ANWEND / EDITOR / NVI179B / NVI179B.ZIP / cl / cl_funcs.c < prev    next >
C/C++ Source or Header  |  1997-07-29  |  20KB  |  856 lines

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