home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / More Source / C⁄C++ / Xconq 7.0d37 / source / libcurses / curses.c next >
Encoding:
C/C++ Source or Header  |  1995-01-10  |  32.2 KB  |  1,660 lines  |  [TEXT/KAHL]

  1. /*
  2.  *  Module    curses        (Hopefully) machine-independant curses library.
  3.  *  Author    larry gensch, ESQ
  4.  *
  5.  *  Note:   The inspiration for this module was an article by
  6.  *        Allen I. Holub in Dr. Dobbs Journal C Chest column.
  7.  *        Extensive modifications were made by larry gensch
  8.  *        to make the module conform to System V curses.
  9.  *
  10.  *  Copyright (c) 1987, 1988, 1989
  11.  *    by Larry Gensch  /  104 Lowell Road  /  Salem, NH  03079
  12.  *
  13.  *  This code may be included in any work, public or private, with the
  14.  *  exception of creating a commercial curses-compatible subroutine
  15.  *  library.  (In other words, use the code all you want, but please don't
  16.  *  rip off the author by reselling this code as your own).
  17.  *
  18.  *  If you make modifications to this code (specifically, enhancements that
  19.  *  are compatible with System V.x curses), please send them to larry gensch at
  20.  *  the address above to be considered for inclusion in subsequent releases.
  21.  *  Any machine specific implementation modules (similar to v-msdos.c) for
  22.  *  other machines are welcomed.
  23.  */
  24.  
  25. #include "curses.h"
  26. #include <ctype.h>
  27. #include <stdlib.h>
  28.  
  29. /****
  30. * There is no vsscanf function in ANSI standard, so it can't be relied
  31. * on.  Define VSSCANF to the appropriate function name if it is supplied
  32. * with the compiler.  If VSSCANF is not defined, the scanw family of calls
  33. * will not be included in compilation.
  34. ****/
  35.  
  36. #ifdef THINK_C
  37. #    define VSSCANF _vsscanf
  38. #endif
  39.  
  40. #ifdef __WATCOMC__
  41. #    define VSSCANF vsscanf
  42. #endif
  43.  
  44. /*
  45.  * EXPORT is used to show entry points into this module.  Simply grep
  46.  * using the pattern '^EXPORT' to list them out.
  47.  */
  48.  
  49. #ifndef EXPORT
  50. #define EXPORT
  51. #endif
  52.  
  53. /*
  54.  * Exported variables (accessible by user programs):
  55.  */
  56.  
  57. static char prntw_buf[512];
  58.  
  59. EXPORT int    COLS            = 0;
  60. EXPORT int    LINES            = 0;
  61. EXPORT WINDOW*    stdscr;
  62. EXPORT char        *_curses_prntw = prntw_buf;
  63. EXPORT unsigned    _curses_prntw_size    = sizeof(prntw_buf);
  64. EXPORT int        _curses_tab_wid = 8;
  65.  
  66. static bool    Echo    = TRUE;        /* echo()/noecho() state    */
  67. static bool    Cbreak    = FALSE;    /* cbreak()/nocbreak() state    */
  68. static bool    Nl    = TRUE;            /* nl()/nonl() state        */
  69. static bool    Endwin    = TRUE;        /* isendwin() state        */
  70. static bool    Raw    = FALSE;        /* raw()/noraw() state        */
  71. static chtype    Kbbuf[256];        /* Keyboard input buffer    */
  72. static chtype    *Kbptr = Kbbuf;    /* Buffer pointer        */
  73. static int    Kbcount = 0;        /* Nbr characters in buffer    */
  74.  
  75. static chtype ungot_char = -1;    /* Character pushed back by ungetch. */
  76.  
  77. /****
  78. * The following variables are used to communicate between waddch
  79. * and get_input (wgetch) when echo is on:
  80. ****/
  81.  
  82. static int waddch_scroll_cnt;    /* Number of lines window was scrolled up in get_input call. */
  83. static int waddch_end_of_window_flag;    /* Set to TRUE if end of window reached and cannot scroll. */
  84. static int waddch_allow_backspace_up;    /* Set to TRUE to allow backspace character to go up a line. */
  85.  
  86. /*
  87.  * initscr() - initialize the screen and curses internal variables.
  88.  *
  89.  * Returns a pointer to stdscr if successful, otherwise prints a message
  90.  * to stderr and exits.
  91.  */
  92.  
  93. EXPORT WINDOW    *initscr    (void)
  94. {
  95.     if (! Endwin)
  96.         return NULL;
  97.  
  98.     if (! CURS_INIT_FN()) {
  99. #ifdef THINK_C
  100.         maccur_alert_msg("curses: error in terminal initialization.");
  101. #else
  102.         fputs("curses: error in terminal initialization.\n", stderr);
  103. #endif
  104.         exit(1);
  105.     }
  106.  
  107.     if (LINES == 0)
  108.         LINES = 24;
  109.     if (COLS == 0)
  110.         COLS = 80;
  111.  
  112.     stdscr = newwin(0,0,0,0);
  113.     if (stdscr == NULL) {
  114. #ifdef THINK_C
  115.         maccur_alert_msg("curses: cannot allocate stdscr window.");
  116. #else
  117.         fputs("curses: cannot allocate stdscr window.\n", stderr);
  118. #endif
  119.         abort();
  120.     }
  121.  
  122.     Endwin = FALSE;
  123.  
  124.     return stdscr;
  125. }
  126.  
  127. /*
  128.  * endwin() - reset terminal into previous state.  Required before any call to
  129.  * system() or exit().
  130.  */
  131.  
  132. EXPORT int    endwin        (void)
  133. {
  134.     if (stdscr == NULL)
  135.         return ERR;
  136.  
  137.     Endwin = TRUE;
  138.  
  139.     return CURS_END_FN();
  140. }
  141.  
  142. /*
  143.  * isendwin() - determine if endwin() has been called without any subsequent
  144.  * calls to wrefresh().
  145.  */
  146.  
  147. EXPORT bool    isendwin    (void)
  148. {
  149.     return Endwin;
  150. }
  151.  
  152. /* -------------------------------------------- */
  153. /*             Window manipulation              */
  154. /* -------------------------------------------- */
  155.  
  156. /*
  157.  * wrefresh() - Write window to terminal.  Returns ERR if an error occurs.
  158.  */
  159.  
  160. EXPORT int    wrefresh    (WINDOW *win)
  161. {
  162.     if (win != NULL && (win->_flags & _ISPAD) == 0) {
  163.         Endwin = FALSE;
  164.     
  165.         if (win->_flags & (_WINCHANGED | _WINMOVED)) {
  166.             win->_flags &= ~(_WINCHANGED | _WINMOVED);
  167.             return CURS_REFRESH_FN(win, TRUE);
  168.         }
  169.         return OK;
  170.     }
  171.  
  172.     return ERR;
  173. }
  174.  
  175. /*
  176.  * wnoutrefresh() - Update virtual terminal image (physical image updated by
  177.  * doupdate()).
  178.  */
  179.  
  180. EXPORT int    wnoutrefresh    (WINDOW *win)
  181. {
  182.     if (win != NULL && (win->_flags & _ISPAD) == 0) {
  183.         if (win->_flags & (_WINCHANGED | _WINMOVED))
  184.         {
  185.             win->_flags &= ~(_WINCHANGED | _WINMOVED);
  186.             return CURS_REFRESH_FN(win, FALSE);
  187.         }
  188.         return OK;
  189.     }
  190.  
  191.     return ERR;
  192. }
  193.  
  194. /*
  195.  * pad_map: Used by prefresh/pnoutrefresh to determine  what part of
  196.  *            pad to display.  Returns ERR on bad parameters.  Sets _WINMOVED
  197.  *            flag if pad is not mapped to same location as previous call.
  198.  */
  199.  
  200. static int pad_map        (WINDOW *pad, int pminy, int pminx,
  201.                          int sminy, int sminx, int smaxy, int smaxx)
  202. {
  203.     int pmaxx, pmaxy;
  204.  
  205.     pminy = MAX(pminy, 0);
  206.     pminx = MAX(pminx, 0);
  207.     sminy = MAX(sminy, 0);
  208.     sminx = MAX(sminx, 0);
  209.     if (sminx >= smaxx && sminy >= smaxy) return ERR;
  210.  
  211.     pmaxx = pminx + (smaxx - sminx + 1);
  212.     pmaxy = pminy + (smaxy - sminy + 1);
  213.     pmaxx = MIN(pmaxx, pad->_maxx);
  214.     pmaxy = MIN(pmaxy, pad->_maxy);
  215.     
  216.     if (sminy != pad->_begy || sminx != pad->_begx ||
  217.             pminy != pad->_pmap_orgy || pminx != pad->_pmap_orgx ||
  218.             pmaxy != pad->_pmap_maxy || pmaxx != pad->_pmap_maxx)
  219.     {
  220.         pad->_flags |= _WINMOVED;
  221.         pad->_begy = sminy;
  222.         pad->_begx = sminx;
  223.         pad->_pmap_orgy = pminy;
  224.         pad->_pmap_orgx = pminx;
  225.         pad->_pmap_maxy = pmaxy;
  226.         pad->_pmap_maxx = pmaxx;
  227.     }
  228.  
  229.     return OK;
  230. }
  231.  
  232. /*
  233.  * prefresh() - Map and write pad to terminal.  Returns ERR if an error occurs.
  234.  */
  235.  
  236. EXPORT int    prefresh    (WINDOW *pad, int pminy, int pminx,
  237.                          int sminy, int sminx, int smaxy, int smaxx)
  238. {
  239.     if (pad != NULL && (pad->_flags & _ISPAD))
  240.     {
  241.         Endwin = FALSE;
  242.  
  243.         if (pad_map(pad, pminy, pminx, sminy, sminx,
  244.                                     smaxy, smaxx) == ERR)
  245.             return ERR;
  246.  
  247.         if (pad->_flags & (_WINCHANGED | _WINMOVED))
  248.         {
  249.             pad->_flags &= ~(_WINCHANGED | _WINMOVED);
  250.             return CURS_REFRESH_FN(pad, TRUE);
  251.         }
  252.         return OK;
  253.     }
  254.  
  255.     return ERR;
  256. }
  257.  
  258. /*
  259.  * pnoutrefresh() - Update virtual terminal image (physical image updated by
  260.  * doupdate()).
  261.  */
  262.  
  263. EXPORT int    pnoutrefresh    (WINDOW *pad, int pminy, int pminx,
  264.                          int sminy, int sminx, int smaxy, int smaxx)
  265. {
  266.     if (pad != NULL && (pad->_flags & _ISPAD))
  267.     {
  268.         if (pad_map(pad, pminy, pminx, sminy, sminx,
  269.                                     smaxy, smaxx) == ERR)
  270.             return ERR;
  271.  
  272.         if (pad->_flags & (_WINCHANGED | _WINMOVED))
  273.         {
  274.             pad->_flags &= ~(_WINCHANGED | _WINMOVED);
  275.             return CURS_REFRESH_FN(pad, FALSE);
  276.         }
  277.         return OK;
  278.     }
  279.  
  280.     return ERR;
  281. }
  282.  
  283. /*
  284.  * doupdate() - Update the physical terminal image.
  285.  */
  286.  
  287. EXPORT int    doupdate    (void)
  288. {
  289.     Endwin = FALSE;
  290.     return CURS_REFRESH_FN(NULL, TRUE);
  291. }
  292.  
  293. /*
  294.  * window_init() - Initialize window structure.
  295.  */
  296.  
  297. static void window_init    (WINDOW *win, int nlines, int ncols, int beg_y, int beg_x)
  298. {
  299.     win->_cury        = 0;
  300.     win->_curx        = 0;
  301.     win->_maxy        = nlines;
  302.     win->_maxx        = ncols;
  303.        win->_xdim        = ncols;
  304.     win->_begy        = beg_y;
  305.     win->_begx        = beg_x;
  306.     win->_flags        = _WINCHANGED;
  307.     win->_attrs        = 0;
  308.     win->_clear        = FALSE;
  309.     win->_leave        = FALSE;
  310.     win->_scroll    = FALSE;
  311.     win->_use_idl    = FALSE;
  312.     win->_use_keypad    = FALSE;
  313.     win->_use_meta    = FALSE;
  314.     win->_nodelay    = FALSE;
  315.     win->_firstch    = NULL;
  316.     win->_lastch    = NULL;
  317.     win->_notimeout    = FALSE;
  318.     win->_need_idl    = FALSE;
  319.     win->_tmarg        = 0;
  320.     win->_bmarg        = nlines;
  321. }
  322.  
  323. /*
  324.  * newwin() - Create and return a pointer to a new window.
  325.  */
  326.  
  327. EXPORT WINDOW*    newwin        (int nlines, int ncols, int beg_y, int beg_x)
  328. {
  329.     WINDOW    *win;
  330.     chtype    *screen;
  331.     int        i;
  332.  
  333.     if (nlines > LINES || ncols > COLS)
  334.         return NULL;
  335.  
  336.     if (nlines < 1)
  337.         nlines = LINES;
  338.  
  339.     if (ncols < 1)
  340.         ncols = COLS;
  341.  
  342.     if ( (beg_y < 0 || beg_y >= LINES) ||    /* RZ: Was >= on x/y + beg compare to lines/cols */
  343.      (beg_x < 0 || beg_x >= COLS)    ||
  344.          (nlines + beg_y > LINES)    ||
  345.      (ncols + beg_x > COLS) )
  346.         return NULL;
  347.  
  348.     if ((win = calloc(1, sizeof(WINDOW))) == NULL)
  349.         return NULL;
  350.  
  351.     if ((screen = calloc(nlines * ncols, sizeof(chtype))) == NULL) {
  352.         free(win);
  353.         return NULL;
  354.     }
  355.  
  356.     window_init(win, nlines, ncols, beg_y, beg_x);
  357.     win->_y = screen;
  358.  
  359.     for (i = 0; i < nlines * ncols; i++, screen++)
  360.         *screen = ' ';
  361.  
  362.     return win;
  363. }
  364.  
  365. /*
  366.  * subwin() - Create and return a pointer to a new window.
  367.  */
  368.  
  369. EXPORT WINDOW*    subwin        (WINDOW *parnt_win, int nlines, int ncols, int beg_y, int beg_x)
  370. {
  371.     WINDOW *win;
  372.  
  373.     if (parnt_win == NULL)
  374.         return NULL;
  375.  
  376.     if (nlines < 1 || ncols < 1)
  377.         return NULL;
  378.  
  379.     if ( (beg_y < parnt_win->_begy) ||
  380.             (beg_x < parnt_win->_begx) ||
  381.             (nlines + beg_y > parnt_win->_maxy + parnt_win->_begy) ||
  382.             (ncols + beg_x > parnt_win->_maxx + parnt_win->_begx) )
  383.         return NULL;
  384.  
  385.     if ((win = calloc(1, sizeof(WINDOW))) == NULL)
  386.         return NULL;
  387.  
  388.     window_init(win, nlines, ncols, beg_y, beg_x);
  389.     win->_flags |= _SUBWIN;
  390.     win->_y = parnt_win->_y + ((beg_y - parnt_win->_begy) * parnt_win->_xdim +
  391.                                 beg_x - parnt_win->_begx);
  392.     win->_xdim = parnt_win->_maxx;
  393.  
  394.     return win;
  395. }
  396.  
  397. /*
  398.  * newpad() - Create and return a pointer to a new pad.
  399.  */
  400.  
  401. EXPORT WINDOW*    newpad        (int nlines, int ncols)
  402. {
  403.     WINDOW    *pad;
  404.     chtype    *screen;
  405.     int        i;
  406.  
  407.     if ( nlines < 1 || ncols < 1 )
  408.         return NULL;
  409.  
  410.     if ((pad = calloc(1, sizeof(WINDOW))) == NULL)
  411.         return NULL;
  412.  
  413.     if ((screen = calloc(nlines * ncols, sizeof(chtype))) == NULL) {
  414.         free(pad);
  415.         return NULL;
  416.     }
  417.  
  418.     window_init(pad, nlines, ncols, 0, 0);
  419.     pad->_pmap_orgy = 0;
  420.     pad->_pmap_orgx = 0;
  421.     pad->_pmap_maxy = LINES;
  422.     pad->_pmap_maxx = COLS;
  423.     pad->_flags |= _ISPAD;
  424.     pad->_y = screen;
  425.  
  426.     for (i = 0; i < nlines * ncols; i++, screen++)
  427.         *screen = ' ';
  428.  
  429.     return pad;
  430. }
  431.  
  432. /*
  433.  * subpad() - Create and return a pointer to a pad inside another pad.
  434.  */
  435.  
  436. EXPORT WINDOW*    subpad        (WINDOW *parnt_pad, int nlines, int ncols, int beg_y, int beg_x)
  437. {
  438.     WINDOW *pad;
  439.  
  440.     if (parnt_pad == NULL || (parnt_pad->_flags & _ISPAD) == 0)
  441.         return NULL;
  442.  
  443.     if (nlines < 1 || ncols < 1)
  444.         return NULL;
  445.  
  446.     if ( (beg_y < 0) ||
  447.             (beg_x < 0) ||
  448.             (nlines + beg_y > parnt_pad->_maxy) ||
  449.             (ncols + beg_x > parnt_pad->_maxx) )
  450.         return NULL;
  451.  
  452.     if ((pad = calloc(1, sizeof(WINDOW))) == NULL)
  453.         return NULL;
  454.  
  455.     window_init(pad, nlines, ncols, beg_y, beg_x);
  456.     pad->_pmap_orgy = parnt_pad->_pmap_orgy;
  457.     pad->_pmap_orgx = parnt_pad->_pmap_orgx;
  458.     pad->_pmap_maxy = parnt_pad->_pmap_maxy;
  459.     pad->_pmap_maxx = parnt_pad->_pmap_maxx;
  460.     pad->_flags |= (_SUBWIN | _ISPAD);
  461.     pad->_y = parnt_pad->_y + (beg_y * parnt_pad->_xdim + beg_x);
  462.     pad->_xdim = parnt_pad->_maxx;
  463.  
  464.     return pad;
  465. }
  466.  
  467. /*
  468.  * mvwin() - move window so that the upper left corner will be at the specified
  469.  * position.
  470.  */
  471.  
  472. EXPORT int    mvwin        (WINDOW *win, int y, int x)
  473. {
  474.     if (win == NULL || (win->_flags & _ISPAD))
  475.         return ERR;
  476.  
  477.     if ( (x + win->_maxx > COLS)    ||
  478.          (y + win->_maxy > LINES) )    /* RZ -- Check was >=, eliminated OK mappings. */
  479.         return ERR;
  480.  
  481.     win->_begx = x;
  482.     win->_begy = y;
  483.     win->_flags |= _WINMOVED;
  484.  
  485.     return OK;
  486. }
  487.  
  488. /*
  489.  * delwin() - delete the named window, freeing all memory associated with it.
  490.  */
  491.  
  492. EXPORT int    delwin        (WINDOW *win)
  493. {
  494.     if (win == NULL)
  495.         return ERR;
  496.  
  497.     free(win->_y);
  498.     free(win);
  499.  
  500.     return OK;
  501. }
  502.  
  503. /*
  504.  * waddch() - Output the specified character to the specified window.
  505.  *
  506.  * Note:  The "unctrl" routine in the default: case below is
  507.  *      specific to the ASCII character set.
  508.  *
  509.  */
  510.  
  511. EXPORT int    waddch        (WINDOW *win, chtype ch)
  512. {
  513.     int        rval = OK;
  514.     chtype c, attr;
  515.  
  516.     if (win == NULL)
  517.         return ERR;
  518.  
  519.     win->_flags |= _WINCHANGED;
  520.  
  521.     waddch_scroll_cnt = 0;
  522.     waddch_end_of_window_flag = FALSE;
  523.  
  524.     c = (ch & A_CHARTEXT);
  525.     attr = (ch & A_ATTRIBUTES);
  526.     switch (c | (ch & A_ALTCHARSET))
  527.     {
  528.         case '\b':
  529.             if (win->_curx > 0 || (waddch_allow_backspace_up && win->_cury > 0))
  530.             {
  531.                 win->_y[win->_cury*win->_xdim + --win->_curx] = ' ' | win->_attrs;
  532.                 if (win->_curx < 0)
  533.                 {
  534.                     win->_cury--;
  535.                     win->_curx = win->_maxx - 1;
  536.                 }
  537.             }
  538.             else rval = ERR;
  539.     
  540.             break;
  541.  
  542.         case '\t':
  543.             do {
  544.                 waddch(win, ' ' | attr);
  545.             } while (win->_curx % _curses_tab_wid &&
  546.                      win->_curx > 0 && !waddch_end_of_window_flag);    /* Don't let tab spill into new line. */
  547.             break;
  548.     
  549.         case '\r':
  550.             win->_curx = 0;
  551.             break;
  552.     
  553.         default:
  554.             if ( ( (ch & A_ALTCHARSET) == 0) &&
  555.                     iscntrl(c))
  556.             {
  557.                 waddch(win, '^' | attr);
  558.                 ch = ((c == 0x7f) ? '?' : c + 'A' - 1) | attr;
  559.             }
  560.     
  561.             win->_y[win->_cury*win->_xdim+win->_curx] = ch | win->_attrs;
  562.     
  563.             if (++(win->_curx) < win->_maxx)
  564.                 break;
  565.     
  566.             /* fall through to newline */
  567.     
  568.         case '\n':
  569.             if (ch == '\n')
  570.                 wclrtoeol(win);
  571.  
  572.             win->_curx = 0;
  573.             win->_cury++;
  574.  
  575.             if (win->_scroll && win->_cury >= win->_bmarg )
  576.             {
  577.                 if ((rval = scroll(win)) != ERR)
  578.                 {
  579.                     win->_cury = win->_bmarg - 1;
  580.                     waddch_scroll_cnt++;
  581.                 }
  582.             }
  583.     
  584.             break;
  585.     }
  586.  
  587.     if (win->_cury >= win->_maxy)
  588.     {
  589.         win->_cury = win->_maxy - 1;
  590.         win->_curx = win->_maxx - 1;
  591.         waddch_end_of_window_flag = TRUE;
  592.         rval = ERR;
  593.     }
  594.  
  595.     win->_flags |= _WINCHANGED;
  596.     waddch_allow_backspace_up = FALSE;
  597.     return rval;
  598. }
  599.  
  600. /*
  601.  * wechochar() - waddch() followed by refresh()
  602.  */
  603.  
  604. EXPORT int    wechochar    (WINDOW *win, chtype ch)
  605. {
  606.     waddch(win,ch);
  607.     return wrefresh(win);
  608. }
  609.  
  610. /*
  611.  * pechochar() - waddch() followed by prefresh()
  612.  */
  613.  
  614. EXPORT int    pechochar    (WINDOW *pad, chtype ch);
  615.  
  616. EXPORT int    pechochar    (WINDOW *pad, chtype ch)
  617. {
  618.     waddch(pad,ch);
  619.     return prefresh(pad, pad->_pmap_orgy, pad->_pmap_orgx,
  620.                                 pad->_begy, pad->_begx,
  621.                                 pad->_begy + pad->_pmap_maxy - pad->_pmap_orgy - 1,
  622.                                 pad->_begx + pad->_pmap_maxx - pad->_pmap_orgx - 1);
  623. }
  624.  
  625. /*
  626.  * waddstr() - Write the characters in the string to the window.
  627.  */
  628.  
  629. EXPORT int    waddstr        (WINDOW *win, char *str)
  630. {
  631.     int        rval = OK;
  632.  
  633.     while (*str)
  634.         if (waddch(win, (chtype) *(str++)) == ERR)
  635.             rval = ERR;
  636.  
  637.     return rval;
  638. }
  639.  
  640. /*
  641.  * wattroff() - Turn off the specified attributes in the window.
  642.  */
  643.  
  644. EXPORT int    wattroff    (WINDOW *win, chtype attrs)
  645. {
  646.     if (win == NULL)
  647.         return ERR;
  648.  
  649.     win->_attrs &= ~(attrs & A_ATTRIBUTES);
  650.     return OK;
  651. }
  652.  
  653. /*
  654.  * wattron() - Turn on the specified attributes in the window.
  655.  */
  656.  
  657. EXPORT int    wattron        (WINDOW *win, chtype attrs)
  658. {
  659.     if (win == NULL)
  660.         return ERR;
  661.  
  662.     win->_attrs |= (attrs & A_ATTRIBUTES);
  663.     return OK;
  664. }
  665.  
  666. /*
  667.  * wattrset() - Set the specified attributes in the window.
  668.  */
  669.  
  670. EXPORT int    wattrset    (WINDOW *win, chtype attrs)
  671. {
  672.     if (win == NULL)
  673.         return ERR;
  674.  
  675.     win->_attrs = (attrs & A_ATTRIBUTES);
  676.     return OK;
  677. }
  678.  
  679. /*
  680.  * wstandout() - Turn on standout mode.
  681.  */
  682.  
  683. EXPORT int    wstandout    (WINDOW *win)
  684. {
  685.     return wattron(win, A_STANDOUT);
  686. }
  687.  
  688. /*
  689.  * wstandend() - Turn off all attributes.
  690.  */
  691.  
  692. EXPORT int    wstandend    (WINDOW *win)
  693. {
  694.     return wattrset(win, A_NORMAL);
  695. }
  696.  
  697. /*
  698.  * beep() - Sound the audible alarm()
  699.  */
  700.  
  701. EXPORT int    beep        (void)
  702. {
  703.     CURS_BEEP_FN(FALSE);
  704.     return OK;
  705. }
  706.  
  707. /*
  708.  * flash() - Flash the screen (alternately, sound the alarm)
  709.  */
  710.  
  711. EXPORT int    alarm        (void)
  712. {
  713.     CURS_BEEP_FN(TRUE);
  714.     return OK;
  715. }
  716.  
  717. /*
  718.  * box() - Draw a box around the edge of the window.
  719.  */
  720.  
  721. EXPORT int    box        (WINDOW *win, chtype vertch, chtype horch)
  722. {
  723.     chtype    ul, ur, ll, lr;
  724.     int        i;
  725.     int        ox, oy;
  726.     bool    os;
  727.  
  728.     if (win == NULL)
  729.         return ERR;
  730.  
  731.     if (horch == '\b' || vertch == '\b')                /* These could cause infinite loop. */
  732.         return ERR;
  733.  
  734.     if (vertch == 0)
  735.         vertch = ACS_VLINE;
  736.     if (horch == 0)
  737.         horch = ACS_HLINE;
  738.  
  739.     if (vertch == ACS_VLINE && horch == ACS_HLINE) {
  740.         ul = ACS_ULCORNER;
  741.         ur = ACS_URCORNER;
  742.         ll = ACS_LLCORNER;
  743.         lr = ACS_LRCORNER;
  744.     }
  745.     else
  746.         ul = ur = ll = lr = horch;
  747.  
  748.     ox = win->_cury;
  749.     oy = win->_curx;
  750.     os = win->_scroll;
  751.  
  752.     wmove(win, 0, 0);
  753.     waddch(win, ul);
  754.     win->_scroll = FALSE;
  755.  
  756.     for (i = 2; i < win->_maxx; i++)
  757.         waddch(win, horch);
  758.  
  759.     waddch(win, ur);
  760.  
  761.     for (i = 1; i < win->_maxy - 1; i++) {
  762.         wmove(win, i, 0);
  763.         waddch(win, vertch);
  764.         wmove(win, i, win->_maxx-1);
  765.         waddch(win, vertch);
  766.     }
  767.  
  768.     mvwaddch(win, win->_maxy - 1, 0, ll);
  769.  
  770.     for (i = 2; i < win->_maxx; i++)
  771.         waddch(win, horch);
  772.  
  773.     waddch(win, lr);
  774.  
  775.     win->_cury   = ox;
  776.     win->_curx   = oy;
  777.     win->_scroll = os;
  778.     win->_flags |= _WINCHANGED;
  779.  
  780.     return OK;
  781. }
  782.  
  783. /*
  784.  * werase() - Erase a window.
  785.  */
  786.  
  787. EXPORT int    werase        (WINDOW *win)
  788. {
  789.     int        i, i_rw;
  790.     chtype    ch;
  791.     chtype    *screen, *dst_ptr;
  792.  
  793.     if (win == NULL)
  794.         return ERR;
  795.  
  796.     ch = ' ';
  797.     screen = win->_y;
  798.     i = win->_maxx * win->_maxy;
  799.  
  800.     for (i_rw = 0; i_rw < win->_maxy; i_rw++)            /* Have to do row-by-row because of possible subwin/pad. */
  801.     {
  802.         dst_ptr = screen + i_rw * win->_xdim;
  803.         for (i = 0; i < win->_maxx; i++)
  804.             *(dst_ptr + i) = ch;
  805.     }
  806.  
  807.     win->_flags |= _WINCHANGED;
  808.     return OK;
  809. }
  810.  
  811. /*
  812.  * wclear() - Clear the window (functionally identical to erase())
  813.  */
  814.  
  815. EXPORT int    wclear        (WINDOW *win)
  816. {
  817.     return werase(win);
  818. }
  819.  
  820. /*
  821.  * wclrtobot() - Clear from cursor position to the bottom of the window.
  822.  */
  823.  
  824. EXPORT int    wclrtobot    (WINDOW *win)
  825. {
  826.     int        i, i_rw;
  827.     int        max;
  828.     chtype    *dst_ptr;
  829.     chtype    ch;
  830.  
  831.     if (win == NULL)
  832.         return ERR;
  833.  
  834.     win->_flags |= _WINCHANGED;
  835.  
  836.     ch = ' ';
  837.  
  838.     for (i_rw = win->_cury; i_rw < win->_maxy; i_rw++)        /* Have to do row-by-row because of possible subwin/pad. */
  839.     {
  840.         dst_ptr = win->_y + i_rw * win->_xdim;
  841.         for (i = (i_rw == win->_cury ? win->_curx : 0); i < win->_maxx; i++)
  842.             *(dst_ptr + i) = ch;
  843.     }
  844.  
  845.  
  846.     return OK;
  847. }
  848.  
  849. /*
  850.  * wclrtoeol() - Clear from cursor position to end of line in window.
  851.  */
  852.  
  853. EXPORT int    wclrtoeol    (WINDOW *win)
  854. {
  855.     int        i;
  856.     chtype    *screen;
  857.     chtype    ch;
  858.  
  859.     if (win == NULL)
  860.         return ERR;
  861.  
  862.     if (win->_cury >= win->_maxy)
  863.         return ERR;
  864.  
  865.     win->_flags |= _WINCHANGED;
  866.  
  867.     screen = win->_y + (win->_cury * win->_xdim);
  868.     ch = ' ';
  869.  
  870.     for (i = win->_curx; i < win->_maxx; i++)
  871.         *(screen + i) = ch;
  872.  
  873.     return OK;
  874. }
  875.  
  876. /*
  877.  * delch() - Delete character under cursor, moving all characters to end of
  878.  * line in the window to the right one character.
  879.  */
  880.  
  881. void *memmove(void *s1, const void *s2, size_t n);
  882.  
  883. EXPORT int    wdelch        (WINDOW *win)
  884. {
  885.     chtype    *dst_ptr;
  886.     int n;
  887.  
  888.     if (win == NULL)
  889.         return ERR;
  890.  
  891.     win->_flags |= _WINCHANGED;
  892.  
  893.     dst_ptr = win->_y + (win->_cury * win->_xdim + win->_curx);
  894.     n = win->_maxx - win->_curx - 1;
  895.     memmove(dst_ptr, dst_ptr + 1, n * sizeof(chtype));
  896.     *(dst_ptr + n) = ' ' | win->_attrs;
  897.  
  898.     return OK;
  899. }
  900.  
  901. /*
  902.  * wdeleteln() - Delete the line containing the cursor, moving all subsequent
  903.  * lines in the window up one line.
  904.  */
  905.  
  906. void *memcpy(void *s1, const void *s2, size_t n);
  907.  
  908. EXPORT int    wdeleteln    (WINDOW *win)
  909. {
  910.     int        i, i_rw;
  911.     chtype    *dst_ptr;
  912.     chtype    ch;
  913.  
  914.     if (win == NULL)
  915.         return ERR;
  916.  
  917.     win->_flags |= _WINCHANGED;
  918.  
  919.     for (i_rw = win->_cury; i_rw < win->_maxy - 1; i_rw++)
  920.     {
  921.         dst_ptr = win->_y + (i_rw * win->_xdim);
  922.         memcpy(dst_ptr, dst_ptr + win->_xdim, win->_maxx * sizeof(chtype));
  923.     }
  924.  
  925.     dst_ptr = win->_y + ((win->_maxy - 1) * win->_xdim);
  926.     for (i = 0; i < win->_maxx; i++)
  927.         *(dst_ptr + i) = ch;
  928.  
  929.     return OK;
  930. }
  931.  
  932. /*
  933.  * winsch() - Insert a character at the cursor position in the window, moving
  934.  * all subsequent characters (to end of line) to the right one character.
  935.  */
  936.  
  937. EXPORT int    winsch        (WINDOW *win, chtype ch)
  938. {
  939.     chtype    *src_ptr;
  940.  
  941.     if (win == NULL)
  942.         return ERR;
  943.  
  944.     win->_flags |= _WINCHANGED;
  945.  
  946.     src_ptr = win->_y + (win->_cury * win->_xdim + win->_curx);
  947.     memmove(src_ptr + 1, src_ptr, (win->_maxx - win->_curx - 1) * sizeof(chtype));
  948.     *src_ptr = ch | win->_attrs;
  949.  
  950.     return OK;
  951. }
  952.  
  953. /*
  954.  * winsertln() - Insert a blank line above current line. (had a bug)
  955.  */
  956.  
  957. EXPORT int    winsertln    (WINDOW *win)
  958. {
  959.     int        i, i_rw;
  960.     chtype    *dst_ptr;
  961.     chtype    ch;
  962.  
  963.     if (win == NULL)
  964.         return ERR;
  965.  
  966.     win->_flags |= _WINCHANGED;
  967.  
  968.     ch = ' ';
  969.  
  970.     for (i_rw = win->_cury + 1; i_rw < win->_maxy; i_rw++)
  971.     {
  972.         dst_ptr = win->_y + (i_rw * win->_xdim);
  973.         memcpy(dst_ptr, dst_ptr - win->_xdim, win->_maxx * sizeof(chtype));
  974.     }
  975.  
  976.     dst_ptr = win->_y + (win->_cury * win->_xdim);
  977.     for (i = 0; i < win->_maxx; i++)
  978.         *(dst_ptr + i) = ch;
  979.  
  980.     return OK;
  981. }
  982.  
  983. /*
  984.  * printw() - Print a printf()-formatted string onto stdscr.
  985.  */
  986.  
  987. EXPORT int    printw        (char *fmt, ...)
  988. {
  989.     va_list args;
  990.  
  991.     va_start(args, fmt);
  992.     vsprintf(_curses_prntw, fmt, args);
  993.     va_end(args);
  994.  
  995.     return addstr(_curses_prntw);
  996. }
  997.  
  998. /*
  999.  * mvprintw() - Print a printf()-formatted string onto stdscr after positioning.
  1000.  */
  1001.  
  1002. EXPORT int    mvprintw    (int y, int x, char *fmt, ...)
  1003. {
  1004.     va_list args;
  1005.  
  1006.     move(y, x);
  1007.  
  1008.     va_start(args, fmt);
  1009.     vsprintf(_curses_prntw, fmt, args);
  1010.     va_end(args);
  1011.  
  1012.     return addstr(_curses_prntw);
  1013. }
  1014.  
  1015. /*
  1016.  * wprintw() - Print a printf()-formatted string onto a window.
  1017.  */
  1018.  
  1019. EXPORT int    wprintw        (WINDOW *win, char *fmt, ...)
  1020. {
  1021.     va_list args;
  1022.  
  1023.     va_start(args, fmt);
  1024.     vsprintf(_curses_prntw, fmt, args);
  1025.     va_end(args);
  1026.  
  1027.     return waddstr(win, _curses_prntw);
  1028. }
  1029.  
  1030. /*
  1031.  * mvwprintw() - Print a printf()-formatted string onto a window after positioning.
  1032.  */
  1033.  
  1034. EXPORT int    mvwprintw    (WINDOW *win, int y, int x, char *fmt, ...)
  1035. {
  1036.     va_list args;
  1037.  
  1038.     wmove(win, y, x);
  1039.  
  1040.     va_start(args, fmt);
  1041.     vsprintf(_curses_prntw, fmt, args);
  1042.     va_end(args);
  1043.  
  1044.     return waddstr(win, _curses_prntw);
  1045. }
  1046.  
  1047. /*
  1048.  * vwprintw() - Print a printf()-formatted string onto a window using a
  1049.  * variable argument list.
  1050.  */
  1051.  
  1052. EXPORT int    vwprintw    (WINDOW *win, char *fmt, va_list ap)
  1053. {
  1054.     va_list args;
  1055.  
  1056.     vsprintf(_curses_prntw, fmt, ap);
  1057.  
  1058.     return waddstr(win, _curses_prntw);
  1059. }
  1060.  
  1061. /*
  1062.  * scroll() - Scroll a window up one line.
  1063.  *    This is the same as wdeleteln on the top scrolling char.
  1064.  */
  1065.  
  1066. EXPORT int    scroll        (WINDOW *win)
  1067. {
  1068.     int        i, i_rw;
  1069.     chtype    *dst_ptr;
  1070.     chtype    ch;
  1071.  
  1072.     if (win == NULL)
  1073.         return ERR;
  1074.  
  1075.     if (!win->_scroll)
  1076.         return ERR;
  1077.  
  1078.     win->_flags |= _WINCHANGED;
  1079.  
  1080.     ch = ' ' | win->_attrs;
  1081.  
  1082.     for (i_rw = win->_tmarg; i_rw < win->_bmarg - 1; i_rw++)
  1083.     {
  1084.         dst_ptr = win->_y + (i_rw * win->_xdim);
  1085.         memcpy(dst_ptr, dst_ptr + win->_xdim, win->_maxx * sizeof(chtype));
  1086.     }
  1087.  
  1088.     dst_ptr = win->_y + ((win->_bmarg - 1) * win->_xdim);
  1089.     for (i = 0; i < win->_maxx; i++)
  1090.         *(dst_ptr + i) = ch;
  1091.  
  1092.     return OK;
  1093. }
  1094.  
  1095. /*
  1096.  * touchwin() - Pretend that the window has been modified since last refresh().
  1097.  */
  1098.  
  1099. EXPORT int    touchwin    (WINDOW *win)
  1100. {
  1101.     if (win == NULL)
  1102.         return ERR;
  1103.  
  1104.     win->_flags |= _WINCHANGED;
  1105.  
  1106.     return OK;
  1107. }
  1108.  
  1109. /*
  1110.  * touchline() - Functionally identical to touchwin()
  1111.  */
  1112.  
  1113. EXPORT int    touchline    (WINDOW *win, int start, int count)
  1114. {
  1115.     return touchwin(win);
  1116. }
  1117.  
  1118. /*
  1119.  * wmove() - Set the cursor position within a window.
  1120.  */
  1121.  
  1122. EXPORT int    wmove        (WINDOW *win, int ypos, int xpos)
  1123. {
  1124.     if (win == NULL)
  1125.         return ERR;
  1126.  
  1127.     if ( (xpos < 0 || xpos >= win->_maxx) ||
  1128.      (ypos < 0 || ypos >= win->_maxy) )
  1129.         return ERR;
  1130.  
  1131.     win->_curx = xpos;
  1132.     win->_cury = ypos;
  1133.  
  1134.     return OK;
  1135. }
  1136.  
  1137. /*
  1138.  * copywin() - Move text from one window to another.
  1139.  */
  1140.  
  1141. EXPORT int copywin        (WINDOW *src_win, WINDOW *dst_win,
  1142.                          int sminy, int sminx, int dminy, int dminx,
  1143.                          int dmaxy, int dmaxx, bool overlay_flag)
  1144. {
  1145.     int nrows, nchars, i, j;
  1146.     chtype *src_ptr, *dst_ptr;
  1147.  
  1148.     sminy = MAX(sminy, 0);
  1149.     sminx = MAX(sminx, 0);
  1150.     dminy = MAX(dminy, 0);
  1151.     dminx = MAX(dminx, 0);
  1152.  
  1153.     if (sminy >= src_win->_maxy || sminx >= src_win->_maxx ||
  1154.             dminy >= dst_win->_maxy || dminx >= dst_win->_maxx ||
  1155.             dminy >= dmaxy || dminx >= dmaxx)
  1156.         return ERR;
  1157.  
  1158.     dst_win->_flags |= _WINCHANGED;
  1159.  
  1160.     nrows = MIN(dmaxy + 1, dst_win->_maxy) - dminy;
  1161.     nrows = MIN(nrows, src_win->_maxy - sminy);
  1162.     nchars = MIN(dmaxx + 1, dst_win->_maxx) - dminx;
  1163.     nchars = MIN(nchars, src_win->_maxx - sminx);
  1164.     src_ptr = src_win->_y + (sminy * src_win->_xdim) + sminx;
  1165.     dst_ptr = dst_win->_y + (dminy * dst_win->_xdim) + dminx;
  1166.  
  1167.     for (i = 0; i < nrows; i++)
  1168.     {
  1169.         if (overlay_flag)
  1170.         {
  1171.             for (j = 0; j < nchars; j++)
  1172.                 if ((*src_ptr & A_CHARTEXT) != ' ')
  1173.                     *(dst_ptr + j) = *(src_ptr + j);
  1174.         }
  1175.         else
  1176.             memmove(dst_ptr, src_ptr, nchars * sizeof(chtype));
  1177.  
  1178.         src_ptr += src_win->_xdim;
  1179.         dst_ptr += dst_win->_xdim;
  1180.     }
  1181.  
  1182.     return OK;
  1183. }
  1184.  
  1185. /*
  1186.  * overwrite()/overlay() - Copy one window onto another.  If either is
  1187.  *    a pad, the copy is done as if the two windows/pads have the same
  1188.  *    upper left corner.
  1189.  */
  1190.  
  1191. EXPORT int    overwrite    (WINDOW *src_win, WINDOW *dst_win)
  1192. {
  1193.  
  1194.     if ((src_win->_flags & _ISPAD) || (dst_win->_flags & _ISPAD))
  1195.         return copywin(src_win, dst_win, 0, 0, 0, 0,
  1196.                                     dst_win->_maxy - 1,
  1197.                                     dst_win->_maxx - 1,
  1198.                                     FALSE);
  1199.     else
  1200.         return copywin(src_win, dst_win, 0, 0,
  1201.                                     src_win->_begy - dst_win->_begy,
  1202.                                     src_win->_begx - dst_win->_begx,
  1203.                                     src_win->_maxy + src_win->_begy - dst_win->_begy - 1,
  1204.                                     src_win->_maxx + src_win->_begx - dst_win->_begx - 1,
  1205.                                     FALSE);
  1206. }
  1207.  
  1208. EXPORT int    overlay        (WINDOW *src_win, WINDOW *dst_win)
  1209. {
  1210.  
  1211.     if ((src_win->_flags & _ISPAD) || (dst_win->_flags & _ISPAD))
  1212.         return copywin(src_win, dst_win, 0, 0, 0, 0,
  1213.                                     dst_win->_maxy - 1,
  1214.                                     dst_win->_maxx - 1,
  1215.                                     TRUE);
  1216.     else
  1217.         return copywin(src_win, dst_win, 0, 0,
  1218.                                     src_win->_begy - dst_win->_begy,
  1219.                                     src_win->_begx - dst_win->_begx,
  1220.                                     src_win->_maxy + src_win->_begy - dst_win->_begy - 1,
  1221.                                     src_win->_maxx + src_win->_begx - dst_win->_begx - 1,
  1222.                                     TRUE);
  1223. }
  1224.  
  1225. /*
  1226.  * cbreak()/nocbreak() - Put the terminal into cbreak mode (ignored currently)
  1227.  */
  1228.  
  1229. EXPORT int    cbreak        (void)
  1230. {
  1231.     return (Cbreak = TRUE);
  1232. }
  1233.  
  1234. EXPORT int    nocbreak    (void)
  1235. {
  1236.     return (Cbreak = FALSE);
  1237. }
  1238.  
  1239. /*
  1240.  * echo()/noecho() - Echo characters as they are typed
  1241.  */
  1242.  
  1243. EXPORT int    echo        (void)
  1244. {
  1245.     return (Echo = TRUE);
  1246. }
  1247.  
  1248. EXPORT int    noecho        (void)
  1249. {
  1250.     return (Echo = FALSE);
  1251. }
  1252.  
  1253. /*
  1254.  * nl()/nonl() - CR -> NL mapping
  1255.  */
  1256.  
  1257. EXPORT int    nl        (void)
  1258. {
  1259.     return (Nl = TRUE);
  1260. }
  1261.  
  1262. EXPORT int    nonl        (void)
  1263. {
  1264.     return (Nl = FALSE);
  1265. }
  1266.  
  1267. /*
  1268.  * halfdelay() - ignored
  1269.  */
  1270.  
  1271. EXPORT int    halfdelay    (int tenths)
  1272. {
  1273.     return OK;
  1274. }
  1275.  
  1276. /*
  1277.  * intrflush() - Determines whether or not to flush input on interrupt.
  1278.  */
  1279.  
  1280. EXPORT int    intrflush    (WINDOW *win, bool flag)
  1281. {
  1282.     if (win == NULL)
  1283.     return ERR;
  1284.     win->_flags |= _FLUSH;
  1285.     return OK;
  1286. }
  1287.  
  1288. /*
  1289.  * keypad() - Turns on/off special key mapping.
  1290.  */
  1291.  
  1292. EXPORT int    keypad        (WINDOW *win, bool flag)
  1293. {
  1294.     if (win == NULL)
  1295.     return ERR;
  1296.     win->_use_keypad = flag;
  1297.     return OK;
  1298. }
  1299.  
  1300. /*
  1301.  * meta() - Turns on/off meta mapping.
  1302.  */
  1303.  
  1304. EXPORT int    meta        (WINDOW *win, bool flag)
  1305. {
  1306.     if (win == NULL)
  1307.     return ERR;
  1308.     win->_use_meta = flag;
  1309.     return OK;
  1310. }
  1311.  
  1312. /*
  1313.  * nodelay() - Turns wgetch() into a non-blocking call.
  1314.  */
  1315.  
  1316. EXPORT int    nodelay        (WINDOW *win, bool flag)
  1317. {
  1318.     if (win == NULL)
  1319.     return ERR;
  1320.  
  1321.     win->_nodelay = flag;
  1322.     return OK;
  1323. }
  1324.  
  1325. /*
  1326.  * notimeout() - Turn on/off escape sequence timing.
  1327.  */
  1328.  
  1329. EXPORT int    notimeout    (WINDOW *win, bool flag)
  1330. {
  1331.     if (win == NULL)
  1332.     return ERR;
  1333.     win->_notimeout = flag;
  1334.     return OK;
  1335. }
  1336.  
  1337. /*
  1338.  * raw()/noraw() - Return characters as they are received.
  1339.  */
  1340.  
  1341. EXPORT int    raw        (void)
  1342. {
  1343.     return (Raw = TRUE);
  1344. }
  1345.  
  1346. EXPORT int    noraw        (void)
  1347. {
  1348.     return (Raw = FALSE);
  1349. }
  1350.  
  1351. /*
  1352.  * get_input() - Get input from keyboard.  Does an implicit refresh of screen.
  1353.  */
  1354.  
  1355. static int    get_input        (WINDOW *win, chtype *chrs, int chrs_max,
  1356.                              bool cbrk_flag, bool raw_flag)
  1357. {
  1358.     chtype    c, save_attr;
  1359.     int c_pos, start_col, start_row, i;
  1360.  
  1361.     c_pos = 0;
  1362.     start_col = win->_curx;
  1363.     start_row = win->_cury;
  1364.  
  1365.     wrefresh(win);
  1366.  
  1367.     for (;;)
  1368.     {
  1369.         c = CURS_KBINP_FN(win, raw_flag, cbrk_flag);
  1370.     
  1371.         if (c == ERR)
  1372.             return ERR;
  1373.     
  1374.         if (Nl && c == '\r')
  1375.             c = '\n';
  1376.  
  1377.         if (cbrk_flag)
  1378.         {
  1379.             *(chrs + c_pos++) = c;
  1380.             if (Echo)
  1381.                 waddch(win, c);
  1382.         }
  1383.         else
  1384.         {
  1385.             switch (c)
  1386.             {
  1387.                 case '\b':                /* Backspace (delete previous character) key. */
  1388.                     if (!raw_flag)        /* Raw mode will fall through to default case. */
  1389.                     {
  1390.                         if (c_pos <= 0) {
  1391.                             beep();
  1392.                             break;
  1393.                         }
  1394.         
  1395.                         if (Echo)
  1396.                         {
  1397.                             waddch_allow_backspace_up = TRUE;
  1398.                             waddch(win, c);
  1399.                             if (iscntrl( (*(chrs + (c_pos - 1))) & A_CHARTEXT ))
  1400.                                {
  1401.                                 waddch_allow_backspace_up = TRUE;
  1402.                                 waddch(win, c);
  1403.                             }
  1404.                         }
  1405.                         c_pos--;
  1406.                         break;
  1407.                     }
  1408.  
  1409.                 case '\025':            /* ctrl-U => Clear input. */
  1410.                     if (!raw_flag)        /* Raw mode will fall through to default case. */
  1411.                     {
  1412.                         if (Echo)
  1413.                         {
  1414.                             win->_curx = start_col;
  1415.                             win->_cury = start_row;
  1416.                             save_attr = win->_attrs;
  1417.                             win->_attrs = 0;
  1418.                             for (i = 0; i < c_pos; i++)
  1419.                             {
  1420.                                 if ( ((*(chrs + i)) & A_CHARTEXT) == '\t')
  1421.                                     waddch(win, '\t');
  1422.                                 else
  1423.                                 {
  1424.                                     waddch(win, ' ');
  1425.                                     if (iscntrl((*(chrs + i)) & A_CHARTEXT))
  1426.                                         waddch(win, ' ');
  1427.                                 }
  1428.                                 if (waddch_end_of_window_flag) break;
  1429.                             }
  1430.                             win->_curx = start_col;
  1431.                             win->_cury = start_row;
  1432.                             win->_attrs = save_attr;
  1433.                         }
  1434.                         c_pos = 0;
  1435.                         break;
  1436.                     }
  1437.  
  1438.                 default:
  1439.                     if (chrs_max != -1 && c_pos >= chrs_max)
  1440.                     {
  1441.                         beep();
  1442.                         break;
  1443.                     }
  1444.                     *(chrs + c_pos++) = c;
  1445.                     if (Echo)
  1446.                     {
  1447.                         waddch(win, c);
  1448.                         start_row -= waddch_scroll_cnt;
  1449.                     }
  1450.                     break;
  1451.             }
  1452.         }
  1453.         if (Echo)
  1454.             wrefresh(win);
  1455.         if (cbrk_flag || c == '\n' || c == '\r')
  1456.             return c_pos;
  1457.     }
  1458. }
  1459.  
  1460. /*
  1461.  * ungetch() - Push back a character to be returned by next
  1462.  *    call to wgetch or wgetstr.
  1463.  */
  1464.  
  1465. EXPORT int ungetch        (chtype ch)
  1466. {
  1467.     ungot_char = ch;
  1468.  
  1469.     return ch;
  1470. }
  1471.  
  1472. /*
  1473.  * wgetch() - Get character from keyboard.
  1474.  */
  1475.  
  1476. EXPORT int    wgetch        (WINDOW *win)
  1477. {
  1478.     int cnt;
  1479.  
  1480.     if (ungot_char != -1)
  1481.     {
  1482.         chtype ch = ungot_char;
  1483.         ungot_char = -1;
  1484.         return ch;
  1485.     }
  1486.  
  1487.     if (Kbcount <= 0)
  1488.     {
  1489.         Kbptr = Kbbuf;
  1490.  
  1491.         if ((cnt = get_input(win, Kbbuf, sizeof(Kbbuf),
  1492.                              Cbreak, Raw)) == ERR || cnt == 0)
  1493.             return ERR;
  1494.  
  1495.         Kbcount = cnt;
  1496.     }
  1497.  
  1498.     Kbcount--;
  1499.     return *(Kbptr++);
  1500. }
  1501.  
  1502. /*
  1503.  * wgetstr() - Get a string from keyboard.  Input is terminated by return
  1504.  *    or newline (which is stripped from string and replaced with null termination).
  1505.  */
  1506.  
  1507. EXPORT int wgetstr        (WINDOW *win, char *str)
  1508. {
  1509.     int i, ungot_off, cnt, c;
  1510.  
  1511.     if (ungot_char != -1)
  1512.     {
  1513.         if ((*(str) = (ungot_char & A_CHARTEXT)) == '\n' || *str == '\r')
  1514.         {
  1515.             ungot_char = -1;
  1516.             *str = '\0';
  1517.             return OK;
  1518.         }
  1519.         ungot_off = 1;
  1520.         ungot_char = -1;
  1521.     }
  1522.     else ungot_off = 0;
  1523.  
  1524.     if (Kbcount <= 0)
  1525.     {
  1526.         Kbptr = Kbbuf;
  1527.  
  1528.         if ((cnt = get_input(win, Kbbuf, sizeof(Kbbuf),
  1529.                              FALSE, FALSE)) == ERR || cnt == 0)
  1530.             return ERR;
  1531.  
  1532.         Kbcount = cnt;
  1533.     }
  1534.  
  1535.     for (i = 0; i < Kbcount - 1; i++)
  1536.         *(str + ungot_off + i) = Kbbuf[i] & A_CHARTEXT;
  1537.  
  1538.     if ((c = (Kbbuf[i] & A_CHARTEXT)) != '\n' && c != '\r')
  1539.         *(str + ungot_off + i++) = c;
  1540.  
  1541.     Kbcount = 0;
  1542.     *(str + ungot_off + i) = '\0';
  1543.     return OK;
  1544. }
  1545.  
  1546. #ifdef VSSCANF
  1547.  
  1548. /*
  1549.  * scanw() - Read a scanf()-formatted string from stdscr.
  1550.  */
  1551.  
  1552. EXPORT int    scanw        (char *fmt, ...)
  1553. {
  1554.     va_list args;
  1555.     int rtn;
  1556.  
  1557.     if (wgetstr(stdscr, _curses_prntw) == ERR)
  1558.         return ERR;
  1559.  
  1560.     va_start(args, fmt);
  1561.     rtn = VSSCANF(_curses_prntw, fmt, args);
  1562.     va_end(args);
  1563.  
  1564.     return rtn;
  1565. }
  1566.  
  1567. /*
  1568.  * mvscanw() - Read a scanf()-formatted string from stdscr after positioning.
  1569.  */
  1570.  
  1571. EXPORT int    mvscanw    (int y, int x, char *fmt, ...)
  1572. {
  1573.     va_list args;
  1574.     int rtn;
  1575.  
  1576.     move(y, x);
  1577.  
  1578.     if (wgetstr(stdscr, _curses_prntw) == ERR)
  1579.         return ERR;
  1580.  
  1581.     va_start(args, fmt);
  1582.     rtn = VSSCANF(_curses_prntw, fmt, args);
  1583.     va_end(args);
  1584.  
  1585.     return rtn;
  1586. }
  1587.  
  1588. /*
  1589.  * wscanw() - Read a scanf()-formatted string from a window.
  1590.  */
  1591.  
  1592. EXPORT int    wscanw        (WINDOW *win, char *fmt, ...)
  1593. {
  1594.     va_list args;
  1595.     int rtn;
  1596.  
  1597.     if (wgetstr(win, _curses_prntw) == ERR)
  1598.         return ERR;
  1599.  
  1600.     va_start(args, fmt);
  1601.     rtn = VSSCANF(_curses_prntw, fmt, args);
  1602.     va_end(args);
  1603.  
  1604.     return rtn;
  1605. }
  1606.  
  1607. /*
  1608.  * mvwscanw() - Read a scanf()-formatted string from a window after positioning.
  1609.  */
  1610.  
  1611. EXPORT int    mvwscanw    (WINDOW *win, int y, int x, char *fmt, ...)
  1612. {
  1613.     va_list args;
  1614.     int rtn;
  1615.  
  1616.     wmove(win, y, x);;
  1617.  
  1618.     if (wgetstr(win, _curses_prntw) == ERR)
  1619.         return ERR;
  1620.  
  1621.     va_start(args, fmt);
  1622.     rtn = VSSCANF(_curses_prntw, fmt, args);
  1623.     va_end(args);
  1624.  
  1625.     return rtn;
  1626. }
  1627.  
  1628. /*
  1629.  * vwscanw() - Read a scanf()-formatted string from a window using a
  1630.  * variable argument list.
  1631.  */
  1632.  
  1633. EXPORT int    vwscanw    (WINDOW *win, char *fmt, va_list ap)
  1634. {
  1635.     va_list args;
  1636.  
  1637.     if (wgetstr(win, _curses_prntw) == ERR)
  1638.         return ERR;
  1639.  
  1640.     return VSSCANF(_curses_prntw, fmt, ap);
  1641. }
  1642.  
  1643. #endif /* VSSCANF */
  1644.  
  1645. /*
  1646.  * flushinp() - Flush input queue
  1647.  */
  1648.  
  1649. EXPORT int    flushinp    (void)
  1650. {
  1651.     Kbcount = 0;
  1652.     Kbptr = Kbbuf;
  1653.  
  1654.  #ifdef CURS_FLUSHINP_FN
  1655.      CURS_FLUSHINP_FN();
  1656.  #endif
  1657.  
  1658.     return OK;
  1659. }
  1660.