home *** CD-ROM | disk | FTP | other *** search
/ Freelog 22 / freelog 22.iso / Prog / Djgpp / GPC2952B.ZIP / lib / gcc-lib / djgpp / 2.952 / units / crtc.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-02-08  |  79.6 KB  |  2,834 lines

  1. /*
  2. Support routines for the CRT unit
  3.  
  4. Copyright (C) 1998-2001 Free Software Foundation, Inc.
  5.  
  6. Author: Frank Heckenbach <frank@pascal.gnu.de>
  7.  
  8. This file is part of GNU Pascal.
  9.  
  10. GNU Pascal is free software; you can redistribute it and/or modify
  11. it under the terms of the GNU General Public License as published by
  12. the Free Software Foundation; either version 2, or (at your option)
  13. any later version.
  14.  
  15. GNU Pascal is distributed in the hope that it will be useful,
  16. but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. GNU General Public License for more details.
  19.  
  20. You should have received a copy of the GNU General Public License
  21. along with GNU Pascal; see the file COPYING. If not, write to the
  22. Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
  23. 02111-1307, USA.
  24.  
  25. As a special exception, if you link this file with files compiled
  26. with a GNU compiler to produce an executable, this does not cause
  27. the resulting executable to be covered by the GNU General Public
  28. License. This exception does not however invalidate any other
  29. reasons why the executable file might be covered by the GNU General
  30. Public License.
  31. */
  32.  
  33. /* Prevent stdlib.h from declaring a beep() function which would
  34.    conflict with PDCurses' one */
  35. #ifdef __MINGW32__
  36. #undef _NO_OLDNAMES
  37. #define _NO_OLDNAMES 1
  38. #endif
  39.  
  40. /* @@ Request old behaviour of signal handlers, in particular
  41.    non-restarting system calls */
  42. #ifdef linux
  43. #undef _XOPEN_SOURCE
  44. #define _XOPEN_SOURCE 1
  45. #endif
  46.  
  47. #include <stdlib.h>
  48. #include <stdio.h>
  49. #include <unistd.h>
  50. #include <string.h>
  51. #include <ctype.h>
  52. #include <errno.h>
  53. #include <signal.h>
  54. #include "crtc.h"
  55.  
  56. int crt_get_input_fd (void);
  57. int crt_get_output_fd (void);
  58.  
  59. extern int crt_input_fd, crt_output_fd;
  60.  
  61. #ifdef USE_PDCURSES
  62.  
  63. #ifdef XCURSES
  64.  
  65. #include <xcurses.h>
  66. #include <xpanel.h>
  67. char *XCursesProgramName;
  68.  
  69. /* Try to shut down cleanly when X11 is shut down */
  70. #include <setjmp.h>
  71. static jmp_buf crt_ShutDownJump;
  72. static int crt_ShutDownJumpActive = FALSE;
  73.  
  74. #else
  75.  
  76. #include <curses.h>
  77. #include <panel.h>
  78.  
  79. #endif
  80.  
  81. #define REVERSE_WORKS FALSE
  82. #define INVIS_WORKS TRUE
  83. #define HAVE_RAW_OUTPUT
  84.  
  85. /* This is undocumented, but there doesn't seem to be another way! */
  86. #define SETCURSOR(x,y) wmove (curscr, y, x)
  87.  
  88. int crt_get_input_fd ()
  89. {
  90.   return PDC_get_input_fd ();
  91. }
  92.  
  93. #ifdef XCURSES
  94.  
  95. int crt_get_output_fd ()
  96. {
  97.   return - 1;
  98. }
  99.  
  100. /* We don't have to clear the terminal since XCurses programs run in
  101.    their own windows, anyway. */
  102. static void crt_clear_terminal ()
  103. {
  104. }
  105.  
  106. #else
  107.  
  108. int crt_get_output_fd ()
  109. {
  110.   return crt_output_fd >= 0 ? crt_output_fd : fileno (stdout);
  111. }
  112.  
  113. extern int PDC_clr_scrn (WINDOW *win);
  114.  
  115. static void crt_clear_terminal ()
  116. {
  117.   PDC_clr_scrn (stdscr);
  118. }
  119. #endif
  120. #endif
  121.  
  122. #ifdef USE_NCURSES
  123. #include <ncurses.h>
  124. #if NCURSES_VERSION_MAJOR < 5
  125. #warning The CRT unit needs ncurses version 5.0 or newer because older
  126. #warning versions contain a bug that severely affects CRT programs.
  127. #endif
  128. #include <panel.h>
  129. #include <term.h>
  130. #define REVERSE_WORKS TRUE
  131. #define INVIS_WORKS FALSE
  132. #undef  HAVE_RAW_OUTPUT
  133.  
  134. /* From dialog-0.9 */
  135. #define isprivate(s) ((s) != 0 && strstr (s, "\033[?") != 0)
  136.  
  137. static char *crt_save_enter_ca_mode = NULL, *crt_save_exit_ca_mode = NULL;
  138.  
  139. /* This is undocumented, but there doesn't seem to be another way! */
  140. #define SETCURSOR(x,y) wmove (newscr, y, x)
  141.  
  142. int crt_get_input_fd ()
  143. {
  144.   return crt_input_fd >= 0 ? crt_input_fd : fileno (stdin);
  145. }
  146.  
  147. int crt_get_output_fd ()
  148. {
  149.   return crt_output_fd >= 0 ? crt_output_fd : fileno (stdout);
  150. }
  151.  
  152. static int putch (int c)
  153. {
  154.   char ch = c;
  155.   return write (crt_get_output_fd (), &ch, sizeof (ch)) >= 0 ? c : EOF;
  156. }
  157.  
  158. static void crt_clear_terminal ()
  159. {
  160.   tputs (clear_screen, lines > 0 ? lines : 1, putch);
  161.   fflush (stdout);
  162. }
  163.  
  164. static WINDOW *resize_window (WINDOW *w, int new_lines, int new_columns)
  165. {
  166.   wresize (w, new_lines, new_columns);
  167.   return w;
  168. }
  169. #endif
  170.  
  171. #ifndef A_ALTCHARSET
  172. #define A_ALTCHARSET 0
  173. #endif
  174.  
  175. typedef unsigned char Boolean;
  176. typedef unsigned int  TKey;
  177. typedef unsigned char Char;
  178. typedef unsigned char TTextAttr;
  179. typedef enum { CursorIgnored, CursorHidden, CursorNormal, CursorFat, CursorBlock } TCursorShape;
  180. typedef enum { UpdateNever, UpdateWaitInput, UpdateInput, UpdateRegularly, UpdateAlways } TCRTUpdate;
  181. typedef struct { int x, y; } TPoint;
  182.  
  183. typedef struct
  184. {
  185.   Char Ch;
  186.   TTextAttr Attr;
  187.   Boolean PCCharSet;
  188. } TCharAttr;
  189.  
  190. typedef struct
  191. {
  192.   int curses_key;
  193.   Char crt_key;
  194. } TKeyTable;
  195.  
  196. typedef struct TPanelData
  197. {
  198.   struct TPanelData *Next;
  199.   WINDOW      *w;
  200.   PANEL       *panel;
  201.   Boolean      BoundToBackground, Hidden, ScrollState, PCCharSet, UseControlChars;
  202.   TCursorShape CursorShape;
  203.   int          WindXMin, WindXMax, WindYMin, WindYMax;
  204.   unsigned int LastWindMin, LastWindMax;
  205.   TTextAttr    TextAttr;
  206. } TPanelData;
  207. typedef TPanelData *TPanel;
  208.  
  209. extern int crt_VirtualShiftState;
  210. extern char *crt_term;
  211. extern unsigned int crt_LastMode, crt_WindMin, crt_WindMax;
  212. extern Boolean crt_CheckBreak, crt_CheckEOF, crt_VisualBell, crt_IsMonochrome, crt_terminal_no_crt, crt_clearflag;
  213. extern TTextAttr crt_TextAttr, crt_NormAttr;
  214. extern void (*crt_auto_init_proc) (void);
  215. extern TPoint crt_ScreenSize, crt_cursor_pos;
  216.  
  217. /* modified by signal handlers */
  218. extern volatile Boolean crt_Signaled;
  219. static volatile Boolean crt_screen_size_changed = FALSE, crt_ShutDown = FALSE;
  220. static volatile TKey crt_unget_key_buf = 0;
  221.  
  222. extern char  *crt_get_program_name (void);
  223. extern char **crt_get_c_environment (void);
  224. extern void   crt_dotextmodecommand (int, int);
  225. extern void   crt_registerrestoreterminal (void);
  226. extern void   crt_signal_handler (TKey sig);
  227. extern void   crt_fatal (int) __attribute__((noreturn));
  228. extern void   _p_SetReturnAddress (void *);
  229. extern void   _p_RestoreReturnAddress (void);
  230.  
  231. #define SAVE_RETURN_ADDRESS _p_SetReturnAddress (__builtin_return_address (0))
  232. #define RESTORE_RETURN_ADDRESS _p_RestoreReturnAddress ()
  233. #define DO_RETURN_ADDRESS(stmt) \
  234. do \
  235.   { \
  236.     SAVE_RETURN_ADDRESS; \
  237.     stmt; \
  238.     RESTORE_RETURN_ADDRESS; \
  239.   } \
  240. while (0)
  241.  
  242. static void crt_refresh (void);
  243. void crt_check_winchanged (void);
  244. int crt_default_save_restore_screen (Boolean Restore);
  245.  
  246. #define DO_CRT_CHECK_WINCHANGED DO_RETURN_ADDRESS (crt_check_winchanged ())
  247.  
  248. /*
  249. There are a few features that cannot be implemented in a portable
  250. way, but rather for different systems individually. There are
  251. defaults for systems where they are not specially supported, see the
  252. comment in crt.pas. The following table lists these items, how to
  253. check them in CRTDemo, and how to implement them on a new system.
  254. Implementations for new systems should go into separate files,
  255. included with appropriate ifdefs below this comment. Prototypes of
  256. the functions to be implemented can be found there.
  257.  
  258. - Playing sounds with Sound and NoSound. In CRTDemo, this can be
  259.   checked with the `Sound check' in the `Various checks' window.
  260.  
  261.   To support them on a system, define HAVE_CRT_SOUND and implement
  262.   the functions crt_sound() (start playing a sound of the given
  263.   frequency, until the next crt_sound() or crt_nosound() call), and
  264.   crt_nosound() (stop playing any sound).
  265.  
  266. - Getting the keyboard shift state. In CRTDemo, this can be checked
  267.   in the `Modifier Keys' window.
  268.  
  269.   By default, this is supported on PDCurses platforms. To support
  270.   this on another system (or to override the PDCurses version),
  271.   define HAVE_CRT_GETSHIFTSTATE and implement the function
  272.   crt_getshiftstate() (return the keyboard shift state as a
  273.   combination of the shFoo constants, ORed with the value of the
  274.   variable crt_VirtualShiftState).
  275.  
  276. - Changing the screen size with TextMode. In CRTDemo, this can be
  277.   checked by changing `Screen columns' and/or `Screen lines' in the
  278.   `Status' window.
  279.  
  280.   By default, this is supported on PDCurses platforms except X11
  281.   (and changing the number of columns doesn't work everywhere). For
  282.   ncurses platforms, the code tries to change the size via an
  283.   external executable. To support this on another system (or to
  284.   override the PDCurses version), define HAVE_CRT_GETSHIFTSTATE and
  285.   implement the function crt_change_screen_size() (change the screen
  286.   size to the given size).
  287.  
  288. - Saving and restoring the original screen contents (e.g., after and
  289.   before starting a child program.
  290.  
  291.   By default, this is supported if the terminal supports it via
  292.   smcup/rmcup (as, e.g., xterms do), and it's not necessary on
  293.   XCurses where the program runs in its own window, anyway. To
  294.   support this on another system, define
  295.   HAVE_CRT_SAVE_RESTORE_SCREEN and implement the function
  296.   crt_save_restore_screen() (save or restore the screen contents).
  297.  
  298. - Catching INT (Ctrl-C) and/or TERM, HUP and under XCurses also PIPE
  299.   signals to let them be treated by CRT, dependent on CheckBreak. In
  300.   CRTDemo, this can be checked by verifying that the program reacts
  301.   to interrupt (Ctrl-C) keys (and if applicable, suspend (Ctrl-Z)
  302.   keys as well as to being killed with INT, TERM, HUP signals, or
  303.   for XCurses, shutting down X11) appropriately, depending on the
  304.   setting of `Break checking' in the `Status' window. Also, catching
  305.   WINCH signals. In CRTDemo, this can by checked by resizing the
  306.   terminal or window by external means and verifying that the
  307.   `Status' window recognizes the new screen size.
  308.  
  309.   By default, handlers are implemented for any of these signals
  310.   which are actually defined on the system. These handlers have been
  311.   found working on all systems tested so far, so usually you won't
  312.   have to worry about them. If you want to implement different
  313.   handlers, define HAVE_CRT_SIGNAL_HANDLERS, and implement the
  314.   function crt_init_signals() (install the signal handlers at the
  315.   start of the program). The signal handlers, in turn, should call
  316.   crt_signal_handler() whenever an INT, TERM, HUP or similar signal
  317.   or SIGPIPE under XCurses is received, giving it as an argument a
  318.   pseudo key code for the signal, and make sure that the program is
  319.   not aborted by the signal. Reading a character from the curses
  320.   window should be interrupted by the signal (which ought to happen
  321.   by default), in order for the program to receive the pseudo key
  322.   immediately. The signal handler for WINCH should set
  323.   crt_screen_size_changed and crt_Signaled, and call any previously
  324.   installed signal handler (e.g. ncurses' one).
  325. */
  326. void crt_sound (unsigned Hz);
  327. void crt_nosound (void);
  328. int crt_getshiftstate (void);
  329. static void crt_change_screen_size (int Columns, int Lines);
  330. static int crt_save_restore_screen (Boolean Restore);
  331. static void crt_init_signals (void);
  332.  
  333. #if defined (__linux__) && defined (__i386__) && !defined (XCURSES)
  334. #include "crtlinux386.h"
  335. #elif defined (DJGPP)
  336. #include "crtdjgpp.h"
  337. #endif
  338.  
  339. #define MAXLENGTH 4096
  340.  
  341. static TCRTUpdate   crt_update_level = UpdateWaitInput;
  342. static TCursorShape crt_last_shape = - 1;
  343. static Char     crt_fkey_buf = 0, crt_line_buf [MAXLENGTH], *crt_line_buf_pos = crt_line_buf;
  344. static size_t   crt_line_buf_count = 0;
  345. static TPanel   crt_ActivePanel = NULL, crt_PanelList = NULL;
  346. static PANEL   *crt_SimulateBlockCursorPanel = NULL;
  347. static WINDOW  *crt_dummy_pad = NULL;
  348. static int      crt_inited = 0, crt_key_buf = 0,
  349.                 crt_refresh_inhibit = 0, crt_refresh_flag = 0,
  350.                 crt_save_previous_screen_flag = - 2,
  351.                 crt_colors [8] = { COLOR_BLACK, COLOR_BLUE,    COLOR_GREEN,  COLOR_CYAN,
  352.                                    COLOR_RED,   COLOR_MAGENTA, COLOR_YELLOW, COLOR_WHITE };
  353. static chtype   crt_attrs [8] [8], crt_monoattrs [8] [8];
  354. static Boolean  crt_ColorFlag = FALSE,
  355.                 crt_HasColors = FALSE,
  356.                 crt_screen_restored = FALSE,
  357.                 crt_linux_console = FALSE,
  358.                 crt_LastCheckBreak = - 1,
  359.                 crt_pending_refresh = FALSE,
  360.                 crt_PCCharSet = FALSE,
  361.                 crt_UpdateLevelChanged = FALSE,
  362.                 crt_SimulateBlockCursorActive = FALSE;
  363.  
  364. #define KEY_HUP    (KEY_MAX + 1)
  365. #ifndef KEY_RESIZE
  366. #define KEY_RESIZE (KEY_MAX + 2)
  367. #endif
  368.  
  369. #define FKEY1     KEY_F (1)
  370. #define FKEYSH1   KEY_F (13)
  371. #define FKEYCTRL1 KEY_F (25)
  372. #define FKEYALT1  KEY_F (37)
  373.  
  374. static TKeyTable KeyTable [] =
  375. {
  376.   { KEY_BACKSPACE, chBkSp },
  377.   { '\b',          chBkSp },
  378.   { 127,           chBkSp },
  379.   { KEY_SUSPEND,   26     },
  380.   { '\n',          chCR   },
  381.   #ifdef USE_PDCURSES
  382.   { '\r',          chCR   },
  383.   { PADSTAR,       '*'    },
  384.   { PADMINUS,      '-'    },
  385.   { PADPLUS,       '+'    },
  386.   { CTL_ENTER,     chLF   },
  387.   { CTL_PADENTER,  chLF   },
  388.   { CTL_PADSTAR,   chLF   },
  389.   { CTL_PADMINUS,  chCR   },
  390.   { CTL_PADPLUS,   11     },
  391.   #else
  392.   { '\r',          chLF   },
  393.   #endif
  394.   { 0,             0      }
  395. };
  396.  
  397. static TKeyTable FKeyTable [] =
  398. {
  399.   { KEY_RESIZE,     ksScreenSizeChanged },
  400.   { KEY_BTAB,       ksShTab     },
  401.   { KEY_LEFT,       ksLeft      },
  402.   { KEY_RIGHT,      ksRight     },
  403.   { KEY_UP,         ksUp        },
  404.   { KEY_DOWN,       ksDown      },
  405.   { KEY_A3,         ksPgUp      },
  406.   { KEY_PPAGE,      ksPgUp      },
  407.   { KEY_C3,         ksPgDn      },
  408.   { KEY_NPAGE,      ksPgDn      },
  409.   { KEY_A1,         ksHome      },
  410.   { KEY_HOME,       ksHome      },
  411.   { KEY_C1,         ksEnd       },
  412.   { KEY_END,        ksEnd       },
  413.   { KEY_IC,         ksIns       },
  414.   { KEY_DC,         ksDel       },
  415.   { KEY_B2,         ksCenter    },
  416.   { KEY_CANCEL,     ksCancel    },
  417.   { KEY_COPY,       ksCopy      },
  418.   { KEY_UNDO,       ksUndo      },
  419.   { KEY_REDO,       ksRedo      },
  420.   { KEY_OPEN,       ksOpen      },
  421.   { KEY_CLOSE,      ksClose     },
  422.   { KEY_COMMAND,    ksCommand   },
  423.   { KEY_CREATE,     ksCreate    },
  424.   { KEY_EXIT,       ksExit      },
  425.   { KEY_FIND,       ksFind      },
  426.   { KEY_HELP,       ksHelp      },
  427.   { KEY_MARK,       ksMark      },
  428.   { KEY_MESSAGE,    ksMessage   },
  429.   { KEY_MOVE,       ksMove      },
  430.   { KEY_NEXT,       ksNext      },
  431.   { KEY_PREVIOUS,   ksPrevious  },
  432.   { KEY_OPTIONS,    ksOptions   },
  433.   { KEY_REFERENCE,  ksReference },
  434.   { KEY_REFRESH,    ksRefresh   },
  435.   { KEY_REPLACE,    ksReplace   },
  436.   { KEY_RESTART,    ksRestart   },
  437.   { KEY_SUSPEND,    ksSuspend   },
  438.   { KEY_RESUME,     ksResume    },
  439.   { KEY_SAVE,       ksSave      },
  440.   #ifdef XCURSES
  441.   /* XCurses returns these for *shifted* keys (which is not wrong :-).
  442.      However, we don't have key codes for shifted keys, but we can get
  443.      the shift state via crt_getshiftstate(). Control-key combinations
  444.      are obtained using crt_getshiftstate(). */
  445.   { KEY_SLEFT,      ksLeft      },
  446.   { KEY_SRIGHT,     ksRight     },
  447.   { KEY_SHOME,      ksHome      },
  448.   { KEY_SEND,       ksEnd       },
  449.   { KEY_SDC,        ksDel       },
  450.   { KEY_SIC,        ksIns       },
  451.   #else
  452.   { KEY_SLEFT,      ksCtrlLeft  },
  453.   { KEY_SRIGHT,     ksCtrlRight },
  454.   { KEY_SHOME,      ksCtrlHome  },
  455.   { KEY_SEND,       ksCtrlEnd   },
  456.   { KEY_SDC,        ksCtrlDel   },
  457.   { KEY_SIC,        ksCtrlIns   },
  458.   #endif
  459.   #ifdef USE_PDCURSES
  460.   { CTL_TAB,        ksCtrlTab   },
  461.   { ALT_TAB,        ksAltTab    },
  462.   { KEY_A2,         ksUp        },
  463.   { KEY_B1,         ksLeft      },
  464.   { KEY_B3,         ksRight     },
  465.   { KEY_C2,         ksDown      },
  466.   { CTL_LEFT,       ksCtrlLeft  },
  467.   { CTL_RIGHT,      ksCtrlRight },
  468.   { CTL_UP,         ksCtrlUp    },
  469.   { CTL_DOWN,       ksCtrlDown  },
  470.   { CTL_PGUP,       ksCtrlPgUp  },
  471.   { CTL_PGDN,       ksCtrlPgDn  },
  472.   { CTL_HOME,       ksCtrlHome  },
  473.   { CTL_END,        ksCtrlEnd   },
  474.   { CTL_INS,        ksCtrlIns   },
  475.   { CTL_DEL,        ksCtrlDel   },
  476.   { CTL_PADSTOP,    ksCtrlDel   },
  477.   { CTL_PADCENTER,  ksCtrlCentr },
  478.   { ALT_LEFT,       ksAltLeft   },
  479.   { ALT_RIGHT,      ksAltRight  },
  480.   { ALT_UP,         ksAltUp     },
  481.   { ALT_DOWN,       ksAltDown   },
  482.   { ALT_PGUP,       ksAltPgUp   },
  483.   { ALT_PGDN,       ksAltPgDn   },
  484.   { ALT_HOME,       ksAltHome   },
  485.   { ALT_END,        ksAltEnd    },
  486.   { ALT_INS,        ksAltIns    },
  487.   { ALT_DEL,        ksAltDel    },
  488.   { ALT_ENTER,      ksAltEnter  },
  489.   { ALT_PADENTER,   ksAltEnter  },
  490.   { ALT_PADSTAR,    ksAltPStar  },
  491.   { ALT_PADMINUS,   ksAltPMinus },
  492.   { ALT_PADPLUS,    ksAltPPlus  },
  493.   { ALT_ESC,        ksAltEsc    },
  494.   { ALT_BKSP,       ksAltBkSp   },
  495.   { ALT_MINUS,      ksAltMinus  },
  496.   { ALT_EQUAL,      ksAltEqual  },
  497.   { ALT_LBRACKET,   ksAltLBrack },
  498.   { ALT_RBRACKET,   ksAltRBrack },
  499.   { ALT_SEMICOLON,  ksAltSemic  },
  500.   { ALT_FQUOTE,     ksAltFQuote },
  501.   { ALT_BQUOTE,     ksAltBQuote },
  502.   { ALT_COMMA,      ksAltComma  },
  503.   { ALT_STOP,       ksAltStop   },
  504.   { ALT_FSLASH,     ksAltFSlash },
  505.   { ALT_BSLASH,     ksAltBSlash },
  506.   { ALT_0,          ksAlt0      },
  507.   { ALT_1,          ksAlt1      },
  508.   { ALT_2,          ksAlt2      },
  509.   { ALT_3,          ksAlt3      },
  510.   { ALT_4,          ksAlt4      },
  511.   { ALT_5,          ksAlt5      },
  512.   { ALT_6,          ksAlt6      },
  513.   { ALT_7,          ksAlt7      },
  514.   { ALT_8,          ksAlt8      },
  515.   { ALT_9,          ksAlt9      },
  516.   { ALT_A,          ksAltA      },
  517.   { ALT_B,          ksAltB      },
  518.   { ALT_C,          ksAltC      },
  519.   { ALT_D,          ksAltD      },
  520.   { ALT_E,          ksAltE      },
  521.   { ALT_F,          ksAltF      },
  522.   { ALT_G,          ksAltG      },
  523.   { ALT_H,          ksAltH      },
  524.   { ALT_I,          ksAltI      },
  525.   { ALT_J,          ksAltJ      },
  526.   { ALT_K,          ksAltK      },
  527.   { ALT_L,          ksAltL      },
  528.   { ALT_M,          ksAltM      },
  529.   { ALT_N,          ksAltN      },
  530.   { ALT_O,          ksAltO      },
  531.   { ALT_P,          ksAltP      },
  532.   { ALT_Q,          ksAltQ      },
  533.   { ALT_R,          ksAltR      },
  534.   { ALT_S,          ksAltS      },
  535.   { ALT_T,          ksAltT      },
  536.   { ALT_U,          ksAltU      },
  537.   { ALT_V,          ksAltV      },
  538.   { ALT_W,          ksAltW      },
  539.   { ALT_X,          ksAltX      },
  540.   { ALT_Y,          ksAltY      },
  541.   { ALT_Z,          ksAltZ      },
  542.   #endif
  543.   { FKEYSH1 + 10,   ksShF11     },
  544.   { FKEYSH1 + 11,   ksShF12     },
  545.   { FKEYCTRL1 + 10, ksCtrlF11   },
  546.   { FKEYCTRL1 + 11, ksCtrlF12   },
  547.   { FKEYALT1 + 10,  ksAltF11    },
  548.   { FKEYALT1 + 11,  ksAltF12    },
  549.   { 0,              ksUnknown   }
  550. };
  551.  
  552. static TKeyTable ShiftKeyTable [] =
  553. {
  554.   { chTab, ksShTab },
  555.   { 0,     0       }
  556. };
  557.  
  558. static TKeyTable ShiftFKeyTable [] =
  559. {
  560.   { ksIns, ksShIns },
  561.   { ksDel, ksShDel },
  562.   { 0,     0       }
  563. };
  564.  
  565. static TKeyTable CtrlFKeyTable [] =
  566. {
  567.   { ksLeft,   ksCtrlLeft  },
  568.   { ksRight,  ksCtrlRight },
  569.   { ksUp,     ksCtrlUp    },
  570.   { ksDown,   ksCtrlDown  },
  571.   { ksPgUp,   ksCtrlPgUp  },
  572.   { ksPgDn,   ksCtrlPgDn  },
  573.   { ksHome,   ksCtrlHome  },
  574.   { ksEnd,    ksCtrlEnd   },
  575.   { ksIns,    ksCtrlIns   },
  576.   { ksDel,    ksCtrlDel   },
  577.   { ksCenter, ksCtrlCentr },
  578.   { ksF1,     ksCtrlF1    },
  579.   { ksF2,     ksCtrlF2    },
  580.   { ksF3,     ksCtrlF3    },
  581.   { ksF4,     ksCtrlF4    },
  582.   { ksF5,     ksCtrlF5    },
  583.   { ksF6,     ksCtrlF6    },
  584.   { ksF7,     ksCtrlF7    },
  585.   { ksF8,     ksCtrlF8    },
  586.   { ksF9,     ksCtrlF9    },
  587.   { ksF10,    ksCtrlF10   },
  588.   { ksF11,    ksCtrlF11   },
  589.   { ksF12,    ksCtrlF12   },
  590.   { 0,        0           }
  591. };
  592.  
  593. static TKeyTable AltFKeyTable [] =
  594. {
  595.   { ksLeft,   ksAltLeft  },
  596.   { ksRight,  ksAltRight },
  597.   { ksUp,     ksAltUp    },
  598.   { ksDown,   ksAltDown  },
  599.   { ksPgUp,   ksAltPgUp  },
  600.   { ksPgDn,   ksAltPgDn  },
  601.   { ksHome,   ksAltHome  },
  602.   { ksEnd,    ksAltEnd   },
  603.   { ksIns,    ksAltIns   },
  604.   { ksDel,    ksAltDel   },
  605.   { 0,        0          }
  606. };
  607.  
  608. static TKeyTable AltKeyTable [] =
  609. {
  610.   { ' ',  ksAltSpace },
  611.   { chLF, ksAltEnter },
  612.   { chCR, ksAltEnter },
  613.   { 0,    0          }
  614. };
  615.  
  616. static TKeyTable AltGrKeyTable [] =
  617. {
  618.   { '0',   ksAltGr0 },
  619.   { '1',   ksAltGr1 },
  620.   { '2',   ksAltGr2 },
  621.   { '3',   ksAltGr3 },
  622.   { '4',   ksAltGr4 },
  623.   { '5',   ksAltGr5 },
  624.   { '6',   ksAltGr6 },
  625.   { '7',   ksAltGr7 },
  626.   { '8',   ksAltGr8 },
  627.   { '9',   ksAltGr9 },
  628.   { 'A',   ksAltGrA },
  629.   { 'B',   ksAltGrB },
  630.   { 'C',   ksAltGrC },
  631.   { 'D',   ksAltGrD },
  632.   { 'E',   ksAltGrE },
  633.   { 'F',   ksAltGrF },
  634.   { 'G',   ksAltGrG },
  635.   { 'H',   ksAltGrH },
  636.   { 'I',   ksAltGrI },
  637.   { 'J',   ksAltGrJ },
  638.   { 'K',   ksAltGrK },
  639.   { 'L',   ksAltGrL },
  640.   { 'M',   ksAltGrM },
  641.   { 'N',   ksAltGrN },
  642.   { 'O',   ksAltGrO },
  643.   { 'P',   ksAltGrP },
  644.   { 'Q',   ksAltGrQ },
  645.   { 'R',   ksAltGrR },
  646.   { 'S',   ksAltGrS },
  647.   { 'T',   ksAltGrT },
  648.   { 'U',   ksAltGrU },
  649.   { 'V',   ksAltGrV },
  650.   { 'W',   ksAltGrW },
  651.   { 'X',   ksAltGrX },
  652.   { 'Y',   ksAltGrY },
  653.   { 'Z',   ksAltGrZ },
  654.   #ifdef USE_PDCURSES
  655.   { ALT_0, ksAltGr0 },
  656.   { ALT_1, ksAltGr1 },
  657.   { ALT_2, ksAltGr2 },
  658.   { ALT_3, ksAltGr3 },
  659.   { ALT_4, ksAltGr4 },
  660.   { ALT_5, ksAltGr5 },
  661.   { ALT_6, ksAltGr6 },
  662.   { ALT_7, ksAltGr7 },
  663.   { ALT_8, ksAltGr8 },
  664.   { ALT_9, ksAltGr9 },
  665.   { ALT_A, ksAltGrA },
  666.   { ALT_B, ksAltGrB },
  667.   { ALT_C, ksAltGrC },
  668.   { ALT_D, ksAltGrD },
  669.   { ALT_E, ksAltGrE },
  670.   { ALT_F, ksAltGrF },
  671.   { ALT_G, ksAltGrG },
  672.   { ALT_H, ksAltGrH },
  673.   { ALT_I, ksAltGrI },
  674.   { ALT_J, ksAltGrJ },
  675.   { ALT_K, ksAltGrK },
  676.   { ALT_L, ksAltGrL },
  677.   { ALT_M, ksAltGrM },
  678.   { ALT_N, ksAltGrN },
  679.   { ALT_O, ksAltGrO },
  680.   { ALT_P, ksAltGrP },
  681.   { ALT_Q, ksAltGrQ },
  682.   { ALT_R, ksAltGrR },
  683.   { ALT_S, ksAltGrS },
  684.   { ALT_T, ksAltGrT },
  685.   { ALT_U, ksAltGrU },
  686.   { ALT_V, ksAltGrV },
  687.   { ALT_W, ksAltGrW },
  688.   { ALT_X, ksAltGrX },
  689.   { ALT_Y, ksAltGrY },
  690.   { ALT_Z, ksAltGrZ },
  691.   #endif
  692.   { 0,     0        }
  693. };
  694.  
  695. static TKeyTable ExtraKeyTable [] =
  696. {
  697.   { '0', ksExtra0 },
  698.   { '1', ksExtra1 },
  699.   { '2', ksExtra2 },
  700.   { '3', ksExtra3 },
  701.   { '4', ksExtra4 },
  702.   { '5', ksExtra5 },
  703.   { '6', ksExtra6 },
  704.   { '7', ksExtra7 },
  705.   { '8', ksExtra8 },
  706.   { '9', ksExtra9 },
  707.   { 'A', ksExtraA },
  708.   { 'B', ksExtraB },
  709.   { 'C', ksExtraC },
  710.   { 'D', ksExtraD },
  711.   { 'E', ksExtraE },
  712.   { 'F', ksExtraF },
  713.   { 'G', ksExtraG },
  714.   { 'H', ksExtraH },
  715.   { 'I', ksExtraI },
  716.   { 'J', ksExtraJ },
  717.   { 'K', ksExtraK },
  718.   { 'L', ksExtraL },
  719.   { 'M', ksExtraM },
  720.   { 'N', ksExtraN },
  721.   { 'O', ksExtraO },
  722.   { 'P', ksExtraP },
  723.   { 'Q', ksExtraQ },
  724.   { 'R', ksExtraR },
  725.   { 'S', ksExtraS },
  726.   { 'T', ksExtraT },
  727.   { 'U', ksExtraU },
  728.   { 'V', ksExtraV },
  729.   { 'W', ksExtraW },
  730.   { 'X', ksExtraX },
  731.   { 'Y', ksExtraY },
  732.   { 'Z', ksExtraZ },
  733.   { 0,   0       }
  734. };
  735.  
  736. static TKeyTable EscKeyTable [] =
  737. {
  738.   { KEY_BACKSPACE, ksAltBkSp   },
  739.   { chBkSp,        ksAltBkSp   },
  740.   { chTab,         ksAltTab    },
  741.   { chLF,          ksAltEnter  },
  742.   { chCR,          ksAltEnter  },
  743.   { chEsc,         ksAltEsc    },
  744.   { ' ',           ksAltSpace  },
  745.   { '-',           ksAltMinus  },
  746.   { '=',           ksAltEqual  },
  747.   { '[',           ksAltLBrack },
  748.   { ']',           ksAltRBrack },
  749.   { ';',           ksAltSemic  },
  750.   { '\'',          ksAltFQuote },
  751.   { '`',           ksAltBQuote },
  752.   { ',',           ksAltComma  },
  753.   { '.',           ksAltStop   },
  754.   { '/',           ksAltFSlash },
  755.   { '\\',          ksAltBSlash },
  756.   { 'A',           ksAltA      },
  757.   { 'B',           ksAltB      },
  758.   { 'C',           ksAltC      },
  759.   { 'D',           ksAltD      },
  760.   { 'E',           ksAltE      },
  761.   { 'F',           ksAltF      },
  762.   { 'G',           ksAltG      },
  763.   { 'H',           ksAltH      },
  764.   { 'I',           ksAltI      },
  765.   { 'J',           ksAltJ      },
  766.   { 'K',           ksAltK      },
  767.   { 'L',           ksAltL      },
  768.   { 'M',           ksAltM      },
  769.   { 'N',           ksAltN      },
  770.   { 'O',           ksAltO      },
  771.   { 'P',           ksAltP      },
  772.   { 'Q',           ksAltQ      },
  773.   { 'R',           ksAltR      },
  774.   { 'S',           ksAltS      },
  775.   { 'T',           ksAltT      },
  776.   { 'U',           ksAltU      },
  777.   { 'V',           ksAltV      },
  778.   { 'W',           ksAltW      },
  779.   { 'X',           ksAltX      },
  780.   { 'Y',           ksAltY      },
  781.   { 'Z',           ksAltZ      },
  782.   { '0',           ksAlt0      },
  783.   { '1',           ksAlt1      },
  784.   { '2',           ksAlt2      },
  785.   { '3',           ksAlt3      },
  786.   { '4',           ksAlt4      },
  787.   { '5',           ksAlt5      },
  788.   { '6',           ksAlt6      },
  789.   { '7',           ksAlt7      },
  790.   { '8',           ksAlt8      },
  791.   { '9',           ksAlt9      },
  792.   { 0,             0           }
  793. };
  794.  
  795. #if !defined (USE_PDCURSES) || defined (XCURSES)
  796. static chtype chars_0_31 [32] =
  797. {
  798.   ' ', 'O', 'O', '%',   0, '#', '*', 'o', 'o', 'o', 'o', '/', '+', 'd', 'A', '*',
  799.     0,   0,   0, '!', '#', '$',   0,   0,   0,   0,   0,   0,   0,   0,   0,   0
  800. };
  801.  
  802. static chtype chars_128_255 [128] =
  803. {
  804.   'C', 'u', 'e', 'a', 'a', 'a', 'a', 'c', 'e', 'e', 'e', 'i', 'i', 'i', 'A', 'A',
  805.   'E', 'a', 'A', 'o', 'o', 'o', 'u', 'u', 'y', 'O', 'U', 'C',   0, 'Y', 'P', 'f',
  806.   'a', 'i', 'o', 'u', 'n', 'N',   0,   0, '?',   0,   0, '/', '/', '!',   0,   0,
  807.     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
  808.     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
  809.     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
  810.   'a', 'B', 'T',   0, 'E', 'o', 'u', 't', 'O', 'O', 'O', 'O', 'o', 'o', 'E', 'A',
  811.   '=',   0,   0,   0, '/', '/', '%', '=',   0, '.', '.', 'V', 'n', '2',   0, ' '
  812. };
  813. #endif
  814.  
  815. #ifndef HAVE_CRT_SETTEXTMODE
  816. static void crt_change_screen_size (int Columns, int Lines)
  817. {
  818.   (void) Columns;
  819.   (void) Lines;
  820.   #ifdef USE_PDCURSES
  821.   #ifdef XCURSES
  822.   /* Don't call resize_term() here -- leads to segfaults (PDCurses 2.4beta.22-May-99) */
  823.   #else
  824.   resize_term (Lines, Columns);
  825.   resize_term (Lines, Columns); /* @@ does not always work the first time -- DJGPP bug? */
  826.   crt_screen_size_changed = TRUE;
  827.   #endif
  828.   #endif
  829.   #ifdef USE_NCURSES
  830.   crt_dotextmodecommand (Columns, Lines);
  831.   if (!crt_Signaled)
  832.     napms (1000); /* give the kernel some time to change the size of
  833.                      all consoles -- a SIGWINCH will interrupt this */
  834.   #endif
  835. }
  836. #endif
  837.  
  838. /* Return value:
  839.     1 : available
  840.     0 : not available
  841.    -1 : unknown until ncurses is initialized
  842.    Values of crt_save_previous_screen_flag are the same plus:
  843.    -2 : not requested */
  844. int crt_default_save_restore_screen (Boolean Restore)
  845. {
  846.   (void) Restore;
  847.   /* The smcup/rmcup support is implicit in ncurses. */
  848.   #ifdef USE_NCURSES
  849.   /* Before ncurses is initialized, exit_ca_mode may be undefined
  850.      (not NULL, but a macro dereferencing NULL) */
  851.   if (!crt_inited)
  852.     return -1;
  853.   return isprivate (Restore ? exit_ca_mode : enter_ca_mode);
  854.   #elif defined (XCURSES)
  855.   return 1;
  856.   #else
  857.   return 0;
  858.   #endif
  859. }
  860.  
  861. #ifndef HAVE_CRT_SAVE_RESTORE_SCREEN
  862. static int crt_save_restore_screen (Boolean Restore)
  863. {
  864.   return crt_default_save_restore_screen (Restore);
  865. }
  866. #endif
  867.  
  868. #ifndef HAVE_CRT_GETSHIFTSTATE
  869. int crt_getshiftstate ()
  870. {
  871.   int state = crt_VirtualShiftState;
  872.   #ifdef USE_PDCURSES
  873.   unsigned long modifiers;
  874.   DO_CRT_CHECK_WINCHANGED;
  875.   modifiers = PDC_get_key_modifiers ();
  876.   if (modifiers & PDC_KEY_MODIFIER_SHIFT  ) state |= shShift;
  877.   if (modifiers & PDC_KEY_MODIFIER_CONTROL) state |= shCtrl;
  878.   if (modifiers & PDC_KEY_MODIFIER_ALT    ) state |= shAlt;
  879.   #ifdef XCURSES
  880.   if (modifiers & PDC_KEY_MODIFIER_MOD4   ) state |= shExtra;
  881.   if (modifiers & PDC_KEY_MODIFIER_MOD3   ) state = shAltGr;
  882.   #else
  883.   if (modifiers & PDC_KEY_MODIFIER_NUMLOCK) state |= shExtra;
  884.   #endif
  885.   #endif
  886.   return state;
  887. }
  888. #endif
  889.  
  890. #ifndef HAVE_CRT_SIGNAL_HANDLERS
  891. #ifdef SIGINT
  892. static void int_handler (int sig)
  893. {
  894.   (void) sig;
  895.   if (crt_CheckBreak) /* PDCurses under DJGPP gets a SIGINT for Ctrl-C even in raw mode */
  896.     crt_signal_handler (0x100 * ksInt);
  897.   signal (SIGINT, &int_handler);
  898. }
  899. #endif
  900.  
  901. #ifdef SIGTERM
  902. static void term_handler (int sig)
  903. {
  904.   (void) sig;
  905.   #ifdef XCURSES
  906.   crt_ShutDown = TRUE;
  907.   #endif
  908.   crt_signal_handler (0x100 * ksTerm);
  909.   signal (SIGTERM, &term_handler);
  910. }
  911. #endif
  912.  
  913. #ifdef SIGHUP
  914. static void hup_handler (int sig)
  915. {
  916.   (void) sig;
  917.   #ifdef XCURSES
  918.   crt_ShutDown = TRUE;
  919.   #endif
  920.   crt_signal_handler (0x100 * ksHUp);
  921.   signal (SIGHUP, &hup_handler);
  922. }
  923. #endif
  924.  
  925. #if defined (SIGPIPE) && defined (XCURSES)
  926. static void pipe_handler (int sig)
  927. {
  928.   (void) sig;
  929.   crt_ShutDown = TRUE;
  930.   crt_signal_handler (0x100 * ksHUp);
  931.   signal (SIGPIPE, SIG_IGN);
  932.   if (crt_ShutDownJumpActive)
  933.     longjmp (crt_ShutDownJump, 1);
  934. }
  935. #endif
  936.  
  937. #if defined (SIGTSTP) && !defined (XCURSES)
  938. static void (*crt_old_tstp_handler) (int);
  939.  
  940. static void tstp_handler (int sig)
  941. {
  942.   (void) sig;
  943.   signal (SIGTSTP, crt_old_tstp_handler);
  944.   kill (getpid (), SIGTSTP);
  945.   signal (SIGTSTP, &tstp_handler);
  946.   crt_screen_size_changed = TRUE; /* might have changed while we were stopped */
  947. }
  948. #endif
  949.  
  950. #ifdef SIGWINCH
  951. static void (*crt_old_winch_handler) (int);
  952.  
  953. static void winch_handler (int sig)
  954. {
  955.   crt_screen_size_changed = TRUE;
  956.   crt_Signaled = TRUE;
  957.   if (crt_old_winch_handler != SIG_ERR && crt_old_winch_handler != SIG_IGN && crt_old_winch_handler != SIG_DFL)
  958.     (*crt_old_winch_handler) (sig);
  959.   signal (SIGWINCH, &winch_handler);
  960. }
  961. #endif
  962.  
  963. static void crt_init_signals ()
  964. {
  965. #ifdef SIGINT
  966.   signal (SIGINT, &int_handler);
  967. #endif
  968. #ifdef SIGTERM
  969.   signal (SIGTERM, &term_handler);
  970. #endif
  971. #ifdef SIGHUP
  972.   signal (SIGHUP, &hup_handler);
  973. #endif
  974. #if defined (SIGPIPE) && defined (XCURSES)
  975.   signal (SIGPIPE, &pipe_handler);
  976. #endif
  977. #if defined (SIGTSTP) && !defined (XCURSES)
  978.   crt_old_tstp_handler = signal (SIGTSTP, &tstp_handler);
  979. #endif
  980. #ifdef SIGWINCH
  981.   crt_old_winch_handler = signal (SIGWINCH, &winch_handler);
  982. #endif
  983. }
  984. #endif
  985.  
  986. #if !defined (HAVE_CRT_SOUND) && !defined (NO_CRT_DUMMY_SOUND)
  987. void crt_sound (unsigned Hz)
  988. {
  989. }
  990.  
  991. void crt_nosound ()
  992. {
  993. }
  994. #endif
  995.  
  996. #if defined (USE_NCURSES) || defined (XCURSES)
  997.  
  998. #include <sys/time.h>
  999.  
  1000. /* Time for delayed refreshes */
  1001. #define REFRESH_SECONDS 0
  1002. #define REFRESH_MICROSECONDS 100000
  1003.  
  1004. static void alarm_handler (int sig)
  1005. {
  1006.   (void) sig;
  1007.   crt_refresh ();
  1008. }
  1009.  
  1010. static void no_alarm_handler (int sig)
  1011. {
  1012.   (void) sig;
  1013. }
  1014.  
  1015. /*
  1016.    This function must call crt_refresh(), either immediately, or
  1017.    delayed (e.g. using a timer signal).
  1018.    - Calling crt_refresh() immediately is useful if curses'
  1019.      wrefresh() does not take a long time, like PDCurses under DJGPP
  1020.      which uses direct hardware access. The CRT window will then
  1021.      always be up to date. However, if wrefresh() takes a long time,
  1022.      this will slow down the program substantially.
  1023.    - Calling crt_refresh() delayed (e.g. Unix with ncurses): By
  1024.      using a timer, the number of calls to wrefresh() can be reduced
  1025.      so the program will not be slowed down too much. On the other
  1026.      hand, the timer guarantees that the window will not lag behind
  1027.      more than a specified amount of time. crt_refresh() is
  1028.      re-entrant, so the timer signal handler can call it without
  1029.      worries. Also, crt_schedule_refresh() will not be called when
  1030.      there is a pending refresh (i.e. crt_schedule_refresh() was
  1031.      called, but crt_refresh() was not called since then), so it can
  1032.      set the timer without worrying about disturbing a previously
  1033.      scheduled refresh.
  1034. */
  1035. static void crt_schedule_refresh ()
  1036. {
  1037.   static struct itimerval timerval = { { 0, 0 }, { REFRESH_SECONDS, REFRESH_MICROSECONDS } };
  1038.   signal (SIGALRM, &alarm_handler);
  1039.   setitimer (ITIMER_REAL, &timerval, 0);
  1040. }
  1041.  
  1042. /* Called before a Delay is started, a (blocking) read is done, a
  1043.    child process is executed, or the update level is changed, i.e.
  1044.    when a scheduled refresh should not be done any more because it
  1045.    or its timer event might disturb another operation. If
  1046.    crt_schedule_refresh() has set a timer, this function must clear
  1047.    it, otherwise it might interfere with the Delay or the read, so
  1048.    e.g. Delay might get too short or the read will not read in all
  1049.    characters. crt_refresh() will be called after this function, so
  1050.    the timer can safely be cleared without losing the refresh. */
  1051. static void crt_stop_refresh ()
  1052. {
  1053.   static struct itimerval no_timerval = { { 0, 0 }, { 0, 0 } };
  1054.   signal (SIGALRM, &no_alarm_handler);
  1055.   setitimer (ITIMER_REAL, &no_timerval, 0);
  1056. }
  1057.  
  1058. #else
  1059.  
  1060. static inline void crt_schedule_refresh ()
  1061. {
  1062.   crt_refresh ();
  1063. }
  1064.  
  1065. static void crt_stop_refresh ()
  1066. {
  1067. }
  1068. #endif
  1069.  
  1070. static void crt_setcbreak ()
  1071. {
  1072.   if (crt_CheckBreak)
  1073.     {
  1074.       noraw ();
  1075.       cbreak ();
  1076.     }
  1077.   else
  1078.     raw ();
  1079. }
  1080.  
  1081. static void crt_nodelay (bool bf)
  1082. {
  1083.   crt_setcbreak ();
  1084.   nodelay (crt_ActivePanel -> w, bf);
  1085.   nodelay (stdscr, bf);
  1086. }
  1087.  
  1088. static void crt_checkcheckbreak ()
  1089. {
  1090.   if (crt_CheckBreak != crt_LastCheckBreak)
  1091.     {
  1092.       crt_LastCheckBreak = crt_CheckBreak;
  1093.       crt_setcbreak ();
  1094.     }
  1095. }
  1096.  
  1097. static TPanel CheckPanel (TPanel Panel)
  1098. {
  1099.   TPanel PList = crt_PanelList;
  1100.   while (PList && PList != Panel) PList = PList -> Next;
  1101.   return PList;
  1102. }
  1103.  
  1104. TPanel crt_PanelAbove (TPanel Panel);
  1105. TPanel crt_PanelAbove (TPanel Panel)
  1106. {
  1107.   PANEL *p;
  1108.   if (Panel && !CheckPanel (Panel)) return NULL;
  1109.   p = Panel ? Panel -> panel : NULL;
  1110.   do
  1111.     p = panel_above (p);
  1112.   while (p && !panel_userptr (p));
  1113.   return p ? (TPanel) panel_userptr (p) : NULL;
  1114. }
  1115.  
  1116. TPanel crt_PanelBelow (TPanel Panel);
  1117. TPanel crt_PanelBelow (TPanel Panel)
  1118. {
  1119.   PANEL *p;
  1120.   if (Panel && !CheckPanel (Panel)) return NULL;
  1121.   p = Panel ? Panel -> panel : NULL;
  1122.   do
  1123.     p = panel_below (p);
  1124.   while (p && !panel_userptr (p));
  1125.   return p ? (TPanel) panel_userptr (p) : NULL;
  1126. }
  1127.  
  1128. static TCursorShape GetAbsCursorPos (int *PosX, int *PosY, chtype *CharUnderCursor)
  1129. {
  1130.   int covered, x = 1, y = 1;
  1131.   TCursorShape shape;
  1132.   TPanel Panel, Panel2;
  1133.   for (Panel = crt_PanelBelow (NULL), shape = CursorIgnored;
  1134.        Panel && (shape = Panel -> CursorShape) == CursorIgnored;
  1135.        Panel = crt_PanelBelow (Panel));
  1136.   if (Panel)
  1137.     {
  1138.       getyx (Panel -> w, y, x);
  1139.       x += Panel -> WindXMin;
  1140.       y += Panel -> WindYMin;
  1141.       for (covered = 0, Panel2 = crt_PanelAbove (Panel); !covered && Panel2; Panel2 = crt_PanelAbove (Panel2))
  1142.         if (x >= Panel2 -> WindXMin && x <= Panel2 -> WindXMax &&
  1143.             y >= Panel2 -> WindYMin && y <= Panel2 -> WindYMax) covered = 1;
  1144.       if (covered) shape = CursorHidden;
  1145.       if (CharUnderCursor) *CharUnderCursor = winch (Panel -> w);
  1146.     }
  1147.   if (shape == CursorIgnored) shape = CursorHidden;
  1148.   *PosX = x - 1;
  1149.   *PosY = y - 1;
  1150.   return shape;
  1151. }
  1152.  
  1153. static void crt_update ()
  1154. {
  1155.   int x, y;
  1156.   TCursorShape shape;
  1157.   if (crt_screen_size_changed || crt_ShutDown) return;
  1158.   #ifdef XCURSES
  1159.   crt_ShutDownJumpActive = TRUE;
  1160.   if (setjmp (crt_ShutDownJump))
  1161.     return;
  1162.   #endif
  1163.   shape = GetAbsCursorPos (&x, &y, NULL);
  1164.   update_panels ();
  1165.   if (shape != crt_last_shape)
  1166.     {
  1167.       crt_last_shape = shape;
  1168.       curs_set ((shape == CursorHidden) ? 0 :
  1169.                 (shape == CursorNormal) ? 1 : 2);
  1170.     }
  1171.   if (shape == CursorHidden)
  1172.     {
  1173.       SETCURSOR (0, 0);
  1174.       wmove (stdscr, 0, 0);
  1175.     }
  1176.   else
  1177.     {
  1178.       SETCURSOR (x, y);
  1179.       wmove (stdscr, y, x);
  1180.     }
  1181.   doupdate ();
  1182.   #ifdef XCURSES
  1183.   crt_ShutDownJumpActive = FALSE;
  1184.   #endif
  1185. }
  1186.  
  1187. /* Must be re-entrant! */
  1188. static void crt_refresh ()
  1189. {
  1190.   if (crt_refresh_inhibit == 0)
  1191.     {
  1192.       crt_refresh_inhibit++;
  1193.       crt_pending_refresh = FALSE;
  1194.       crt_update ();
  1195.       (void) idlok (crt_ActivePanel -> w, FALSE);
  1196.       crt_refresh_inhibit--;
  1197.     }
  1198.   else
  1199.     crt_refresh_flag++;
  1200. }
  1201.  
  1202. static void crt_need_refresh ()
  1203. {
  1204.   crt_checkcheckbreak ();
  1205.   if (crt_update_level >= UpdateAlways || crt_refresh_flag)
  1206.     {
  1207.       crt_refresh_flag = 0;
  1208.       crt_refresh ();
  1209.     }
  1210.   else if (crt_update_level >= UpdateRegularly && !crt_pending_refresh)
  1211.     {
  1212.       crt_pending_refresh = TRUE;
  1213.       crt_schedule_refresh ();
  1214.     }
  1215. }
  1216.  
  1217. void crt_SimulateBlockCursor (void);
  1218. void crt_SimulateBlockCursor ()
  1219. {
  1220.   if (!crt_SimulateBlockCursorActive)
  1221.     {
  1222.       int x, y;
  1223.       chtype CharUnderCursor;
  1224.       if (GetAbsCursorPos (&x, &y, &CharUnderCursor) >= CursorFat)
  1225.         {
  1226.           crt_SimulateBlockCursorActive = TRUE;
  1227.           if (!crt_SimulateBlockCursorPanel)
  1228.             {
  1229.               WINDOW *w = newwin (1, 1, y, x);
  1230.               if (!w) DO_RETURN_ADDRESS (crt_fatal (6));
  1231.               keypad (w, TRUE);
  1232.               leaveok (w, FALSE);
  1233.               crt_SimulateBlockCursorPanel = new_panel (w);
  1234.               set_panel_userptr (crt_SimulateBlockCursorPanel, NULL);
  1235.             }
  1236.           else
  1237.             move_panel (crt_SimulateBlockCursorPanel, y, x);
  1238.           mvwaddch (panel_window (crt_SimulateBlockCursorPanel), 0, 0,
  1239.             (crt_linux_console ? (chBlock | A_ALTCHARSET) : ACS_BLOCK)
  1240.             | (CharUnderCursor & A_ATTRIBUTES & ~A_ALTCHARSET));
  1241.           show_panel (crt_SimulateBlockCursorPanel);
  1242.           top_panel (crt_SimulateBlockCursorPanel);
  1243.         }
  1244.     }
  1245.   else
  1246.     {
  1247.       crt_SimulateBlockCursorActive = FALSE;
  1248.       if (crt_SimulateBlockCursorPanel) hide_panel (crt_SimulateBlockCursorPanel);
  1249.     }
  1250.   crt_need_refresh ();
  1251. }
  1252.  
  1253. void crt_SimulateBlockCursorOff (void);
  1254. void crt_SimulateBlockCursorOff ()
  1255. {
  1256.   if (crt_SimulateBlockCursorActive) crt_SimulateBlockCursor ();
  1257. }
  1258.  
  1259. void crt_PanelHide (TPanel Panel);
  1260. void crt_PanelHide (TPanel Panel)
  1261. {
  1262.   if (CheckPanel (Panel) && !Panel -> Hidden)
  1263.     {
  1264.       crt_refresh_inhibit++;
  1265.       hide_panel (Panel -> panel);
  1266.       Panel -> Hidden = TRUE;
  1267.       crt_refresh_inhibit--;
  1268.       crt_need_refresh ();
  1269.     }
  1270. }
  1271.  
  1272. void crt_PanelShow (TPanel Panel);
  1273. void crt_PanelShow (TPanel Panel)
  1274. {
  1275.   if (CheckPanel (Panel) && Panel -> Hidden)
  1276.     {
  1277.       crt_refresh_inhibit++;
  1278.       show_panel (Panel -> panel);
  1279.       Panel -> Hidden = FALSE;
  1280.       crt_refresh_inhibit--;
  1281.       crt_need_refresh ();
  1282.     }
  1283. }
  1284.  
  1285. Boolean crt_PanelHidden (TPanel Panel);
  1286. Boolean crt_PanelHidden (TPanel Panel)
  1287. {
  1288.   return CheckPanel (Panel) && Panel -> Hidden;
  1289. }
  1290.  
  1291. void crt_PanelTop (TPanel Panel);
  1292. void crt_PanelTop (TPanel Panel)
  1293. {
  1294.   if (!CheckPanel (Panel)) return;
  1295.   if (Panel -> Hidden) crt_PanelShow (Panel);
  1296.   crt_refresh_inhibit++;
  1297.   top_panel (Panel -> panel);
  1298.   crt_refresh_inhibit--;
  1299.   crt_need_refresh ();
  1300. }
  1301.  
  1302. void crt_PanelBottom (TPanel Panel);
  1303. void crt_PanelBottom (TPanel Panel)
  1304. {
  1305.   if (!CheckPanel (Panel)) return;
  1306.   if (Panel -> Hidden) crt_PanelShow (Panel);
  1307.   crt_refresh_inhibit++;
  1308.   bottom_panel (Panel -> panel);
  1309.   crt_refresh_inhibit--;
  1310.   crt_need_refresh ();
  1311. }
  1312.  
  1313. void crt_PanelMoveAbove (TPanel Panel, TPanel Above);
  1314. void crt_PanelMoveAbove (TPanel Panel, TPanel Above)
  1315. {
  1316.   if (!CheckPanel (Panel)) return;
  1317.   if (!CheckPanel (Above))
  1318.     crt_PanelBottom (Panel);
  1319.   else if (Above -> Hidden)
  1320.     crt_PanelHide (Panel);
  1321.   else if (Above != Panel)
  1322.     {
  1323.       PANEL *p, *p2;
  1324.       if (Panel -> Hidden) crt_PanelShow (Panel);
  1325.       crt_refresh_inhibit++;
  1326.       top_panel (Panel -> panel);
  1327.       p = panel_above (Above -> panel);
  1328.       while (p && p != Panel -> panel)
  1329.         {
  1330.           p2 = panel_above (p);
  1331.           top_panel (p);
  1332.           p = p2;
  1333.         }
  1334.       crt_refresh_inhibit--;
  1335.       crt_need_refresh ();
  1336.     }
  1337. }
  1338.  
  1339. void crt_PanelMoveBelow (TPanel Panel, TPanel Below);
  1340. void crt_PanelMoveBelow (TPanel Panel, TPanel Below)
  1341. {
  1342.   if (!CheckPanel (Panel)) return;
  1343.   if (!CheckPanel (Below))
  1344.     crt_PanelTop (Panel);
  1345.   else if (Below -> Hidden)
  1346.     crt_PanelHide (Panel);
  1347.   else if (Below != Panel)
  1348.     {
  1349.       PANEL *p, *p2;
  1350.       if (Panel -> Hidden) crt_PanelShow (Panel);
  1351.       crt_refresh_inhibit++;
  1352.       bottom_panel (Panel -> panel);
  1353.       p = panel_below (Below -> panel);
  1354.       while (p && p != Panel -> panel)
  1355.         {
  1356.           p2 = panel_below (p);
  1357.           bottom_panel (p);
  1358.           p = p2;
  1359.         }
  1360.       crt_refresh_inhibit--;
  1361.       crt_need_refresh ();
  1362.     }
  1363. }
  1364.  
  1365. void crt_PanelBindToBackground (TPanel Panel, Boolean Bind);
  1366. void crt_PanelBindToBackground (TPanel Panel, Boolean Bind)
  1367. {
  1368.   if (CheckPanel (Panel)) Panel -> BoundToBackground = Bind;
  1369. }
  1370.  
  1371. Boolean crt_PanelIsBoundToBackground (TPanel Panel);
  1372. Boolean crt_PanelIsBoundToBackground (TPanel Panel)
  1373. {
  1374.   return CheckPanel (Panel) && Panel -> BoundToBackground;
  1375. }
  1376.  
  1377. static WINDOW *crt_newwin (int x1, int y1, int x2, int y2, Boolean BoundToBackground)
  1378. {
  1379.   int xsize = x2 - x1 + 1, ysize = y2 - y1 + 1;
  1380.   WINDOW *w = newwin (ysize, xsize, y1 - 1, x1 - 1);
  1381.   if (!w) DO_RETURN_ADDRESS (crt_fatal (6));
  1382.   if (BoundToBackground)
  1383.     {
  1384.       chtype Buffer [xsize + 1];
  1385.       int yc;
  1386.       for (yc = 0; yc < ysize; yc++)
  1387.         {
  1388.           mvwinchnstr (stdscr, yc + y1 - 1, x1 - 1, Buffer, xsize);
  1389.           mvwaddchnstr (w, yc, 0, Buffer, xsize);
  1390.         }
  1391.     }
  1392.   keypad (w, TRUE);
  1393.   leaveok (w, FALSE);
  1394.   crt_last_shape = - 1;
  1395.   return w;
  1396. }
  1397.  
  1398. /* Save contents of the panel to stdscr to imitate BP behaviour */
  1399. static void savetostdscr (TPanel Panel)
  1400. {
  1401.   if (Panel -> BoundToBackground)
  1402.     {
  1403.       PANEL *panel;
  1404.       int yc,
  1405.           XMin  = Panel -> WindXMin - 1,
  1406.           YMin  = Panel -> WindYMin - 1,
  1407.           XSize = Panel -> WindXMax - XMin,
  1408.           YSize = Panel -> WindYMax - YMin;
  1409.       chtype Buffer [XSize + 1];
  1410.       for (yc = 0; yc < YSize; yc++)
  1411.         {
  1412.           mvwinchnstr (Panel -> w, yc, 0, Buffer, XSize);
  1413.           mvwaddchnstr (stdscr, yc + YMin, XMin, Buffer, XSize);
  1414.         }
  1415.       wnoutrefresh (stdscr);
  1416.       for (panel = panel_above (NULL); panel; panel = panel_above (panel))
  1417.         touchwin (panel_window (panel));
  1418.     }
  1419. }
  1420.  
  1421. static void crt_dosetscroll ()
  1422. {
  1423.   scrollok (crt_ActivePanel -> w, crt_ActivePanel -> ScrollState);
  1424. }
  1425.  
  1426. static void update_crt_cursor_pos ()
  1427. {
  1428.   getyx (crt_ActivePanel -> w, crt_cursor_pos.y, crt_cursor_pos.x);
  1429. }
  1430.  
  1431. static inline int combine_bytes (int lo, int hi)
  1432. {
  1433.   return  ((lo > 254) ? 254 : lo) +
  1434.          (((hi > 254) ? 254 : hi) << 8);
  1435. }
  1436.  
  1437. static void SetWindow (TPanel p, int x1, int y1, int x2, int y2)
  1438. {
  1439.   p -> WindXMin = x1;
  1440.   p -> WindYMin = y1;
  1441.   p -> WindXMax = x2;
  1442.   p -> WindYMax = y2;
  1443.   p -> LastWindMin = combine_bytes (x1 - 1, y1 - 1);
  1444.   p -> LastWindMax = combine_bytes (x2 - 1, y2 - 1);
  1445. }
  1446.  
  1447. static void crt_UpdateDataToActivePanel ()
  1448. {
  1449.   if (crt_ActivePanel)
  1450.     crt_ActivePanel -> TextAttr = crt_TextAttr;
  1451. }
  1452.  
  1453. static void crt_UpdateDataFromActivePanel ()
  1454. {
  1455.   if (crt_ActivePanel)
  1456.     {
  1457.       crt_TextAttr = crt_ActivePanel -> TextAttr;
  1458.       crt_WindMin = combine_bytes (crt_ActivePanel -> WindXMin - 1, crt_ActivePanel -> WindYMin - 1);
  1459.       crt_WindMax = combine_bytes (crt_ActivePanel -> WindXMax - 1, crt_ActivePanel -> WindYMax - 1);
  1460.       update_crt_cursor_pos ();
  1461.     }
  1462. }
  1463.  
  1464. static void change_win (int x1, int y1, int x2, int y2)
  1465. {
  1466.   int x, y;
  1467.   WINDOW *oldwin = crt_ActivePanel -> w;
  1468.   crt_refresh_inhibit++;
  1469.   if (x2 < 1) x2 = 1; if (x2 > crt_ScreenSize.x) x2 = crt_ScreenSize.x;
  1470.   if (y2 < 1) y2 = 1; if (y2 > crt_ScreenSize.y) y2 = crt_ScreenSize.y;
  1471.   if (x1 < 1) x1 = 1; if (x1 > x2) x1 = x2;
  1472.   if (y1 < 1) y1 = 1; if (y1 > y2) y1 = y2;
  1473.   getyx (crt_ActivePanel -> w, y, x);
  1474.   x += crt_ActivePanel -> WindXMin;
  1475.   y += crt_ActivePanel -> WindYMin;
  1476.   savetostdscr (crt_ActivePanel);
  1477.   crt_ActivePanel -> w = crt_newwin (x1, y1, x2, y2, crt_ActivePanel -> BoundToBackground);
  1478.   replace_panel (crt_ActivePanel -> panel, crt_ActivePanel -> w);
  1479.   delwin (oldwin);
  1480.   crt_last_shape = - 1;
  1481.   crt_dosetscroll ();
  1482.   if (x < x1) x = x1;
  1483.   if (x > x2) x = x2;
  1484.   if (y < y1) y = y1;
  1485.   if (y > y2) y = y2;
  1486.   wmove (crt_ActivePanel -> w, y - y1, x - x1);
  1487.   SetWindow (crt_ActivePanel, x1, y1, x2, y2);
  1488.   crt_WindMin = crt_ActivePanel -> LastWindMin;
  1489.   crt_WindMax = crt_ActivePanel -> LastWindMax;
  1490.   crt_refresh_inhibit--;
  1491.   update_crt_cursor_pos ();
  1492.   crt_need_refresh ();
  1493. }
  1494.  
  1495. static void crt_PanelActivate_Internal (TPanel Panel)
  1496. {
  1497.   if (!CheckPanel (Panel)) DO_RETURN_ADDRESS (crt_fatal (5));
  1498.   if (Panel == crt_ActivePanel) return;
  1499.   crt_UpdateDataToActivePanel ();
  1500.   crt_ActivePanel = Panel;
  1501.   crt_UpdateDataFromActivePanel ();
  1502. }
  1503.  
  1504. static void crt_PanelNew_Internal (int x1, int y1, int x2, int y2, Boolean BindToBackground)
  1505. {
  1506.   TPanel NewPanel = malloc (sizeof (TPanelData));
  1507.   crt_refresh_inhibit++;
  1508.   NewPanel -> Next = crt_PanelList;
  1509.   crt_PanelList = NewPanel;
  1510.   if (x2 < 1) x2 = 1; if (x2 > crt_ScreenSize.x) x2 = crt_ScreenSize.x;
  1511.   if (y2 < 1) y2 = 1; if (y2 > crt_ScreenSize.y) y2 = crt_ScreenSize.y;
  1512.   if (x1 < 1) x1 = 1; if (x1 > x2) x1 = x2;
  1513.   if (y1 < 1) y1 = 1; if (y1 > y2) y1 = y2;
  1514.   NewPanel -> BoundToBackground = BindToBackground;
  1515.   NewPanel -> Hidden = FALSE;
  1516.   NewPanel -> ScrollState     = crt_ActivePanel ? crt_ActivePanel -> ScrollState     : TRUE;
  1517.   NewPanel -> PCCharSet       = crt_ActivePanel ? crt_ActivePanel -> PCCharSet       : crt_PCCharSet;
  1518.   NewPanel -> UseControlChars = crt_ActivePanel ? crt_ActivePanel -> UseControlChars : TRUE;
  1519.   NewPanel -> CursorShape     = crt_ActivePanel ? crt_ActivePanel -> CursorShape     : CursorNormal;
  1520.   NewPanel -> TextAttr        = crt_TextAttr;
  1521.   NewPanel -> w = crt_newwin (x1, y1, x2, y2, NewPanel -> BoundToBackground);
  1522.   NewPanel -> panel = new_panel (NewPanel -> w);
  1523.   set_panel_userptr (NewPanel -> panel, (void *) NewPanel);
  1524.   SetWindow (NewPanel, x1, y1, x2, y2);
  1525.   crt_PanelActivate_Internal (NewPanel);
  1526.   wmove (NewPanel -> w, 0, 0);
  1527.   update_crt_cursor_pos ();
  1528.   crt_dosetscroll ();
  1529.   crt_refresh_inhibit--;
  1530. }
  1531.  
  1532. static void crt_GetLastMode ()
  1533. {
  1534.   if (crt_HasColors)
  1535.     {
  1536.       crt_LastMode = 0;
  1537.       if (crt_ColorFlag)          crt_LastMode += 1;
  1538.       if (crt_ScreenSize.x >= 80) crt_LastMode += 2;
  1539.     }
  1540.   else
  1541.     crt_LastMode = 7;
  1542.   if (crt_ScreenSize.y >= 43) crt_LastMode += 0x100;
  1543.   crt_IsMonochrome = !crt_HasColors || !crt_ColorFlag;
  1544. }
  1545.  
  1546. static int crt_attr2cursattr (TTextAttr attr)
  1547. {
  1548.   #ifdef XCURSES
  1549.   /* PDCurses under X has serious problems writing black on black. :-(
  1550.      So we write some other color on black and output spaces (see chtransform()) */
  1551.   if ((attr & ~0x88) == 0) attr = 7;
  1552.   #endif
  1553.   return (crt_ColorFlag ? crt_attrs : crt_monoattrs) [attr & 7] [(attr >> 4) & 7] |
  1554.          (((attr & 8) && (crt_ColorFlag || (attr & 0x77))) ? A_BOLD : 0) |
  1555.          ((attr & 0x80) ? A_BLINK : 0);
  1556. }
  1557.  
  1558. static void crt_rawout (Boolean flag)
  1559. {
  1560.   #ifdef HAVE_RAW_OUTPUT
  1561.   raw_output (flag);
  1562.   #else
  1563.   (void) flag;
  1564.   #endif
  1565. }
  1566.  
  1567. static void crt_set_typeahead ()
  1568. {
  1569.   typeahead ((crt_update_level == UpdateWaitInput) ? crt_get_input_fd () : - 1);
  1570. }
  1571.  
  1572. void crt_save_previous_screen (void);
  1573. void crt_save_previous_screen ()
  1574. {
  1575.   if (crt_save_previous_screen_flag < 0)
  1576.     crt_save_previous_screen_flag = crt_save_restore_screen (FALSE);
  1577. }
  1578.  
  1579. Boolean crt_save_previous_screen_works (void);
  1580. Boolean crt_save_previous_screen_works ()
  1581. {
  1582.   if (crt_save_previous_screen_flag == - 1)
  1583.     crt_save_previous_screen_flag = crt_save_restore_screen (FALSE);
  1584.   return crt_save_previous_screen_flag > 0;
  1585. }
  1586.  
  1587. void crt_init (void);
  1588. void crt_init ()
  1589. {
  1590.   int fg, bg, c, cursattr;
  1591.   #ifdef USE_NCURSES
  1592.   FILE *crt_file_out = NULL, *crt_file_in = NULL;
  1593.   #endif
  1594.   if (crt_inited) return;
  1595.   SAVE_RETURN_ADDRESS;
  1596.   #ifdef XCURSES
  1597.   XCursesProgramName = crt_get_program_name ();
  1598.   #endif
  1599.   crt_screen_size_changed = FALSE;
  1600.   #ifndef USE_NCURSES
  1601.   crt_output_fd = fileno (stdout);
  1602.   crt_input_fd = fileno (stdin);
  1603.   #else
  1604.   if (crt_output_fd < 0)
  1605.     crt_output_fd = fileno (stdout);
  1606.   else if (!(crt_file_out = fdopen (crt_output_fd, "w")))
  1607.     crt_fatal (1);
  1608.   if (crt_input_fd < 0)
  1609.     crt_input_fd = fileno (stdin);
  1610.   else if (!(crt_file_in = fdopen (crt_input_fd, "r")))
  1611.     {
  1612.       if (crt_file_out) fclose (crt_file_out);
  1613.       crt_fatal (1);
  1614.     }
  1615.   if (crt_term || crt_file_in || crt_file_out)
  1616.     {
  1617.       char *value_str, *value_end;
  1618.       int value;
  1619.       if (!newterm (crt_term, crt_file_out ? crt_file_out : stdout, crt_file_in ? crt_file_in : stdin))
  1620.         crt_fatal (2);
  1621.       if ((value_str = getenv ("ESCDELAY")) &&
  1622.           (value = strtol (value_str, &value_end, 10)) >= 0 && (!value_end || !*value_end))
  1623.         ESCDELAY = value;
  1624.       def_prog_mode ();
  1625.     }
  1626.   else
  1627.   #endif
  1628.     if (!initscr ()) crt_fatal (1);
  1629.   crt_dummy_pad = newpad (1, 1);
  1630.   crt_inited = 1;
  1631.   #ifdef XCURSES
  1632.   sleep (1); /* @@There is a problem with XCurses not always starting up
  1633.                 correctly (race condition?). Until it is solved, this
  1634.                 sleep() is an ugly and unreliable way to avoid it
  1635.                 sometimes...  */
  1636.   #endif
  1637.   #ifdef USE_PDCURSES
  1638.   PDC_save_key_modifiers (TRUE);
  1639.   #else
  1640.   crt_linux_console = strncmp (termname (), "linux", 5) == 0;
  1641.   /* Work-around for the problem that ncurses ignores the A_BOLD attribute
  1642.      when clearing which may cause a wrong cursor color. */
  1643.   if (crt_linux_console)
  1644.     back_color_erase = 0;
  1645.   #endif
  1646.   #if !defined (USE_PDCURSES) || defined (XCURSES)
  1647.   chars_0_31 [ 4] = ACS_DIAMOND;
  1648.   chars_0_31 [16] = ACS_RARROW;
  1649.   chars_0_31 [17] = ACS_LARROW;
  1650.   chars_0_31 [18] = ACS_VLINE;
  1651.   chars_0_31 [22] = ACS_S9;
  1652.   chars_0_31 [23] = ACS_DARROW;
  1653.   chars_0_31 [24] = ACS_UARROW;
  1654.   chars_0_31 [25] = ACS_DARROW;
  1655.   chars_0_31 [26] = ACS_RARROW;
  1656.   chars_0_31 [27] = ACS_LARROW;
  1657.   chars_0_31 [28] = ACS_LLCORNER;
  1658.   chars_0_31 [29] = ACS_HLINE;
  1659.   chars_0_31 [30] = ACS_UARROW;
  1660.   chars_0_31 [31] = ACS_DARROW;
  1661.   chars_128_255 [ 28] = ACS_STERLING;
  1662.   chars_128_255 [ 38] = ACS_DEGREE;
  1663.   chars_128_255 [ 39] = ACS_DEGREE;
  1664.   chars_128_255 [ 41] = ACS_ULCORNER;
  1665.   chars_128_255 [ 42] = ACS_URCORNER;
  1666.   chars_128_255 [ 46] = ACS_LARROW;
  1667.   chars_128_255 [ 47] = ACS_RARROW;
  1668.   chars_128_255 [ 48] = ACS_CKBOARD;
  1669.   chars_128_255 [ 49] = ACS_CKBOARD;
  1670.   chars_128_255 [ 50] = ACS_CKBOARD;
  1671.   chars_128_255 [ 51] = ACS_VLINE;
  1672.   chars_128_255 [ 52] = ACS_RTEE;
  1673.   chars_128_255 [ 53] = ACS_RTEE;
  1674.   chars_128_255 [ 54] = ACS_RTEE;
  1675.   chars_128_255 [ 55] = ACS_URCORNER;
  1676.   chars_128_255 [ 56] = ACS_URCORNER;
  1677.   chars_128_255 [ 57] = ACS_RTEE;
  1678.   chars_128_255 [ 58] = ACS_VLINE;
  1679.   chars_128_255 [ 59] = ACS_URCORNER;
  1680.   chars_128_255 [ 60] = ACS_LRCORNER;
  1681.   chars_128_255 [ 61] = ACS_LRCORNER;
  1682.   chars_128_255 [ 62] = ACS_LRCORNER;
  1683.   chars_128_255 [ 63] = ACS_URCORNER;
  1684.   chars_128_255 [ 64] = ACS_LLCORNER;
  1685.   chars_128_255 [ 65] = ACS_BTEE;
  1686.   chars_128_255 [ 66] = ACS_TTEE;
  1687.   chars_128_255 [ 67] = ACS_LTEE;
  1688.   chars_128_255 [ 68] = ACS_HLINE;
  1689.   chars_128_255 [ 69] = ACS_PLUS;
  1690.   chars_128_255 [ 70] = ACS_LTEE;
  1691.   chars_128_255 [ 71] = ACS_LTEE;
  1692.   chars_128_255 [ 72] = ACS_LLCORNER;
  1693.   chars_128_255 [ 73] = ACS_ULCORNER;
  1694.   chars_128_255 [ 74] = ACS_BTEE;
  1695.   chars_128_255 [ 75] = ACS_TTEE;
  1696.   chars_128_255 [ 76] = ACS_LTEE;
  1697.   chars_128_255 [ 77] = ACS_HLINE;
  1698.   chars_128_255 [ 78] = ACS_PLUS;
  1699.   chars_128_255 [ 79] = ACS_BTEE;
  1700.   chars_128_255 [ 80] = ACS_BTEE;
  1701.   chars_128_255 [ 81] = ACS_TTEE;
  1702.   chars_128_255 [ 82] = ACS_TTEE;
  1703.   chars_128_255 [ 83] = ACS_LLCORNER;
  1704.   chars_128_255 [ 84] = ACS_LLCORNER;
  1705.   chars_128_255 [ 85] = ACS_ULCORNER;
  1706.   chars_128_255 [ 86] = ACS_ULCORNER;
  1707.   chars_128_255 [ 87] = ACS_PLUS;
  1708.   chars_128_255 [ 88] = ACS_PLUS;
  1709.   chars_128_255 [ 89] = ACS_LRCORNER;
  1710.   chars_128_255 [ 90] = ACS_ULCORNER;
  1711.   chars_128_255 [ 91] = ACS_BLOCK;
  1712.   chars_128_255 [ 92] = ACS_BLOCK;
  1713.   chars_128_255 [ 93] = ACS_BLOCK;
  1714.   chars_128_255 [ 94] = ACS_BLOCK;
  1715.   chars_128_255 [ 95] = ACS_BLOCK;
  1716.   chars_128_255 [ 99] = ACS_PI;
  1717.   chars_128_255 [113] = ACS_PLMINUS;
  1718.   chars_128_255 [114] = ACS_GEQUAL;
  1719.   chars_128_255 [115] = ACS_LEQUAL;
  1720.   chars_128_255 [120] = ACS_DEGREE;
  1721.   chars_128_255 [126] = ACS_BULLET;
  1722.   #endif
  1723.   cbreak ();
  1724.   noecho ();
  1725.   scrollok (stdscr, TRUE);
  1726.   crt_rawout (TRUE);
  1727.   crt_ColorFlag = crt_HasColors = has_colors ();
  1728.   if (crt_HasColors)
  1729.     {
  1730.       start_color ();
  1731.       c = 0;
  1732.       for (bg = 0; bg < 8; bg++)
  1733.         for (fg = 0; fg < 8; fg++)
  1734.           if (INVIS_WORKS && bg == fg && bg > 0)
  1735.             crt_attrs [fg] [bg] = crt_attrs [0] [bg] | A_INVIS;
  1736.           else if (REVERSE_WORKS && fg < bg)
  1737.             crt_attrs [fg] [bg] = crt_attrs [bg] [fg] | A_REVERSE;
  1738.           else
  1739.             {
  1740.               if (init_pair (++c, crt_colors [fg], crt_colors [bg]) == ERR)
  1741.                 {
  1742.                   fprintf (stderr, "could not create color pair (%i,%i)", fg, bg);
  1743.                   crt_inited = 0;
  1744.                   #ifdef XCURSES
  1745.                   XCursesExit ();
  1746.                   #endif
  1747.                   exit (1);
  1748.                 }
  1749.               crt_attrs [fg] [bg] = COLOR_PAIR (c);
  1750.             }
  1751.       for (bg = 0; bg < 8; bg++)
  1752.         for (fg = 0; fg < 8; fg++)
  1753.           crt_monoattrs [fg] [bg] = crt_attrs [7] [0];
  1754.       crt_monoattrs [0] [0] = crt_attrs [0] [0];
  1755.       crt_monoattrs [1] [0] = crt_attrs [1] [0];
  1756.       crt_monoattrs [0] [7] = crt_attrs [0] [7];
  1757.     }
  1758.   else
  1759.     {
  1760.       for (bg = 0; bg < 8; bg++)
  1761.         for (fg = 0; fg < 8; fg++)
  1762.           crt_monoattrs [fg] [bg] = A_NORMAL;
  1763.       crt_monoattrs [0] [0] = A_INVIS;
  1764.       crt_monoattrs [1] [0] = A_UNDERLINE;
  1765.       crt_monoattrs [0] [7] = A_REVERSE;
  1766.     }
  1767.   cursattr = crt_attr2cursattr (crt_NormAttr);
  1768.   attrset (cursattr);
  1769.   bkgdset (cursattr);
  1770.   erase ();
  1771.   crt_init_signals ();
  1772.   keypad (stdscr, TRUE);
  1773.   getmaxyx (stdscr, crt_ScreenSize.y, crt_ScreenSize.x);
  1774.   wrefresh (stdscr); /* prevents flickering at the beginning of XCurses programs */
  1775.   crt_GetLastMode ();
  1776.   crt_PanelNew_Internal (1, 1, crt_ScreenSize.x, crt_ScreenSize.y, TRUE);
  1777.   typeahead (- 1);
  1778.   crt_set_typeahead ();
  1779.   crt_registerrestoreterminal ();
  1780.   RESTORE_RETURN_ADDRESS;
  1781. }
  1782.  
  1783. static void crt_bp_autoinit ()
  1784. {
  1785.   static Boolean initializing = FALSE;
  1786.   if (initializing) /* in case crt_auto_init_proc causes CRT to auto init again... */
  1787.     initializing = FALSE;
  1788.   else
  1789.     {
  1790.       initializing = TRUE;
  1791.       if (crt_auto_init_proc) (*crt_auto_init_proc) ();
  1792.       if (!initializing) return;
  1793.       initializing = FALSE;
  1794.     }
  1795.   crt_PCCharSet = TRUE;
  1796.   if (!crt_UpdateLevelChanged) crt_update_level = UpdateRegularly;
  1797.   crt_init ();
  1798. }
  1799.  
  1800. static void adjust_size (int *x1, int *y1, int *x2, int *y2, TPoint LastScreenSize)
  1801. {
  1802.   if (*x2 > crt_ScreenSize.x)
  1803.     {
  1804.       *x1 -= *x2 - crt_ScreenSize.x;
  1805.       if (*x1 < 1) *x1 = 1;
  1806.       *x2 = crt_ScreenSize.x;
  1807.     }
  1808.   else if (*x1 == 1 && *x2 == LastScreenSize.x)
  1809.     *x2 = crt_ScreenSize.x;
  1810.   if (*y2 > crt_ScreenSize.y)
  1811.     {
  1812.       *y1 -= *y2 - crt_ScreenSize.y;
  1813.       if (*y1 < 1) *y1 = 1;
  1814.       *y2 = crt_ScreenSize.y;
  1815.     }
  1816.   else if (*y1 == 1 && *y2 == LastScreenSize.y)
  1817.     *y2 = crt_ScreenSize.y;
  1818. }
  1819.  
  1820. static void adjust_panel (PANEL *panel, WINDOW **w, int x1, int y1, int x2, int y2)
  1821. {
  1822.   int x, y, xsize = x2 - x1 + 1, ysize = y2 - y1 + 1;
  1823.   WINDOW *new;
  1824.   /* It's not very clear what has to be updated in the windows and
  1825.      panels, and in which order (in the different curses libraries).
  1826.      So, we rather do too much than too little. First resize, then
  1827.      move, otherwise the move could fail, because the window might
  1828.      not fit on the screen. */
  1829.   getyx ((*w), y, x);
  1830.   new = resize_window ((*w), ysize, xsize);
  1831.   if (new) *w = new;
  1832.   panel->win = *w;
  1833.   replace_panel (panel, (*w));
  1834.   move_panel (panel, y1 - 1, x1 - 1);
  1835.   if (x >= xsize) x = xsize - 1;
  1836.   if (y >= ysize) y = ysize - 1;
  1837.   wmove ((*w), y, x);
  1838.   keypad ((*w), TRUE);
  1839.   leaveok ((*w), FALSE);
  1840. }
  1841.  
  1842. void crt_check_winchanged ()
  1843. {
  1844.   SAVE_RETURN_ADDRESS;
  1845.   if (!crt_inited) crt_bp_autoinit ();
  1846.   #ifdef USE_PDCURSES
  1847.   /* In XCurses, this wouldn't be necessary (but doesn't hurt)
  1848.      because the program will get a SIGWINCH, but e.g. under mingw,
  1849.      it doesn't get a SIGWINCH, so we need this additional check. */
  1850.   if (is_termresized ()) crt_screen_size_changed = TRUE;
  1851.   #endif
  1852.   if (crt_screen_size_changed)
  1853.     {
  1854.       PANEL *panel;
  1855.       TPanel p;
  1856.       TPoint LastScreenSize;
  1857.       crt_refresh_inhibit++;
  1858.       #ifdef USE_PDCURSES
  1859.       /* XCurses: resize the terminal after the user resized the window */
  1860.       if (is_termresized ()) resize_term (0, 0);
  1861.       /* work around a bug in the PDCurses panel library */
  1862.       {
  1863.         extern PANEL __stdscr_pseudo_panel;
  1864.         __stdscr_pseudo_panel.win = stdscr;
  1865.         __stdscr_pseudo_panel.wendy = LINES;
  1866.         __stdscr_pseudo_panel.wendx = COLS;
  1867.       }
  1868.       #endif
  1869.       napms (100); /* wait for a new unimap to be loaded if necessary */
  1870.       /* The following code is a bit tricky...
  1871.          doupdate() will update the screen size in ncurses, but the
  1872.          size or position of any window may have become invalid, so
  1873.          they must not be updated now! */
  1874.       untouchwin (stdscr);
  1875.       for (panel = panel_above (NULL); panel; panel = panel_above (panel))
  1876.         untouchwin (panel_window (panel));
  1877.       if (!crt_ShutDown)
  1878.         doupdate ();
  1879.       LastScreenSize = crt_ScreenSize;
  1880.       getmaxyx (stdscr, crt_ScreenSize.y, crt_ScreenSize.x);
  1881.       /* Resize all CRT panels */
  1882.       for (p = crt_PanelList; p; p = p -> Next)
  1883.         {
  1884.           Boolean SetWinMinMax = p == crt_ActivePanel
  1885.                                  && crt_WindMin == p -> LastWindMin
  1886.                                  && crt_WindMax == p -> LastWindMax;
  1887.           int x1, y1, x2, y2;
  1888.           x1 = p -> WindXMin;
  1889.           y1 = p -> WindYMin;
  1890.           x2 = p -> WindXMax;
  1891.           y2 = p -> WindYMax;
  1892.           adjust_size (&x1, &y1, &x2, &y2, LastScreenSize);
  1893.           if (x1 != p -> WindXMin || y1 != p -> WindYMin ||
  1894.               x2 != p -> WindXMax || y2 != p -> WindYMax)
  1895.             {
  1896.               p -> WindXMin = x1;
  1897.               p -> WindYMin = y1;
  1898.               p -> WindXMax = x2;
  1899.               p -> WindYMax = y2;
  1900.               SetWindow (p, x1, y1, x2, y2);
  1901.               if (SetWinMinMax)
  1902.                 {
  1903.                   crt_WindMin = p -> LastWindMin;
  1904.                   crt_WindMax = p -> LastWindMax;
  1905.                 }
  1906.               adjust_panel (p -> panel, &p -> w, x1, y1, x2, y2);
  1907.               if (p -> Hidden) hide_panel (p -> panel);
  1908.             }
  1909.         }
  1910.       /* Handle panels that don't belong to CRT windows (e.g., the one
  1911.          for the simulated block cursor) */
  1912.       for (panel = panel_above (NULL); panel; panel = panel_above (panel))
  1913.         if (!panel_userptr (panel))
  1914.           {
  1915.             WINDOW *w = panel_window (panel);
  1916.             int x1, y1, x2, y2, xsize, ysize, oldx1, oldy1, oldx2, oldy2;
  1917.             getbegyx (w, y1, x1);
  1918.             x1++;
  1919.             y1++;
  1920.             getmaxyx (w, ysize, xsize);
  1921.             oldx1 = x1;
  1922.             oldy1 = y1;
  1923.             oldx2 = x2 = x1 + xsize - 1;
  1924.             oldy2 = y2 = y1 + ysize - 1;
  1925.             adjust_size (&x1, &y1, &x2, &y2, LastScreenSize);
  1926.             if (x1 != oldx1 || y1 != oldy1 || x2 != oldx2 || y2 != oldy2)
  1927.               adjust_panel (panel, &w, x1, y1, x2, y2);
  1928.           }
  1929.       update_crt_cursor_pos ();
  1930.       /* Now we can refresh everything */
  1931.       touchwin (stdscr);
  1932.       for (panel = panel_above (NULL); panel; panel = panel_above (panel))
  1933.         touchwin (panel_window (panel));
  1934.       /* Overcome ncurses' buffering of the cursor shape, because sometimes
  1935.          when the screen size is changed (e.g. by SVGATextMode), also the
  1936.          cursor shape is reset. */
  1937.       curs_set (1);
  1938.       curs_set (0);
  1939.       crt_last_shape = CursorHidden;
  1940.       crt_dosetscroll ();
  1941.       crt_update ();
  1942.       crt_screen_size_changed = FALSE;
  1943.       crt_GetLastMode ();
  1944.       crt_refresh_inhibit--;
  1945.       if (crt_key_buf == 0) crt_key_buf = KEY_RESIZE;
  1946.     }
  1947.   if (crt_WindMin != crt_ActivePanel -> LastWindMin || crt_WindMax != crt_ActivePanel -> LastWindMax)
  1948.     change_win ((crt_WindMin & 0xff) + 1, (crt_WindMin >> 8) + 1,
  1949.                 (crt_WindMax & 0xff) + 1, (crt_WindMax >> 8) + 1);
  1950.   RESTORE_RETURN_ADDRESS;
  1951. }
  1952.  
  1953. void crt_gotoxy (int x, int y);
  1954. void crt_gotoxy (int x, int y)
  1955. {
  1956.   DO_CRT_CHECK_WINCHANGED;
  1957.   wmove (crt_ActivePanel -> w, y - 1, x - 1);
  1958.   crt_cursor_pos.x = x - 1;
  1959.   crt_cursor_pos.y = y - 1;
  1960.   crt_need_refresh ();
  1961. }
  1962.  
  1963. int crt_wherex (void);
  1964. int crt_wherex ()
  1965. {
  1966.   int x, y;
  1967.   DO_CRT_CHECK_WINCHANGED;
  1968.   getyx (crt_ActivePanel -> w, y, x);
  1969.   return x + 1;
  1970. }
  1971.  
  1972. int crt_wherey (void);
  1973. int crt_wherey ()
  1974. {
  1975.   int x, y;
  1976.   DO_CRT_CHECK_WINCHANGED;
  1977.   getyx (crt_ActivePanel -> w, y, x);
  1978.   return y + 1;
  1979. }
  1980.  
  1981. void crt_window (int x1, int y1, int x2, int y2);
  1982. void crt_window (int x1, int y1, int x2, int y2)
  1983. {
  1984.   DO_CRT_CHECK_WINCHANGED;
  1985.   if (x1 >= 1 && x1 <= x2 && x2 <= crt_ScreenSize.x &&
  1986.       y1 >= 1 && y1 <= y2 && y2 <= crt_ScreenSize.y)
  1987.     {
  1988.       change_win (x1, y1, x2, y2);
  1989.       crt_gotoxy (1, 1);
  1990.     }
  1991. }
  1992.  
  1993. void crt_getwindow (int *x1, int *y1, int *x2, int *y2);
  1994. void crt_getwindow (int *x1, int *y1, int *x2, int *y2)
  1995. {
  1996.   DO_CRT_CHECK_WINCHANGED;
  1997.   if (x1) *x1 = crt_ActivePanel -> WindXMin;
  1998.   if (y1) *y1 = crt_ActivePanel -> WindYMin;
  1999.   if (x2) *x2 = crt_ActivePanel -> WindXMax;
  2000.   if (y2) *y2 = crt_ActivePanel -> WindYMax;
  2001. }
  2002.  
  2003. void crt_setscroll (Boolean state);
  2004. void crt_setscroll (Boolean state)
  2005. {
  2006.   DO_CRT_CHECK_WINCHANGED;
  2007.   crt_ActivePanel -> ScrollState = state;
  2008.   crt_dosetscroll ();
  2009. }
  2010.  
  2011. Boolean crt_getscroll (void);
  2012. Boolean crt_getscroll ()
  2013. {
  2014.   DO_CRT_CHECK_WINCHANGED;
  2015.   return crt_ActivePanel -> ScrollState;
  2016. }
  2017.  
  2018. void crt_setcursorshape (TCursorShape shape);
  2019. void crt_setcursorshape (TCursorShape shape)
  2020. {
  2021.   DO_CRT_CHECK_WINCHANGED;
  2022.   crt_ActivePanel -> CursorShape = shape;
  2023.   crt_need_refresh ();
  2024. }
  2025.  
  2026. TCursorShape crt_getcursorshape (void);
  2027. TCursorShape crt_getcursorshape ()
  2028. {
  2029.   DO_CRT_CHECK_WINCHANGED;
  2030.   return crt_ActivePanel -> CursorShape;
  2031. }
  2032.  
  2033. TPanel crt_GetActivePanel (void);
  2034. TPanel crt_GetActivePanel ()
  2035. {
  2036.   DO_CRT_CHECK_WINCHANGED;
  2037.   return crt_ActivePanel;
  2038. }
  2039.  
  2040. void crt_PanelActivate (TPanel Panel);
  2041. void crt_PanelActivate (TPanel Panel)
  2042. {
  2043.   if (Panel == crt_ActivePanel) return;
  2044.   DO_CRT_CHECK_WINCHANGED;
  2045.   DO_RETURN_ADDRESS (crt_PanelActivate_Internal (Panel));
  2046. }
  2047.  
  2048. void crt_PanelNew (int x1, int y1, int x2, int y2, Boolean BindToBackground);
  2049. void crt_PanelNew (int x1, int y1, int x2, int y2, Boolean BindToBackground)
  2050. {
  2051.   DO_CRT_CHECK_WINCHANGED;
  2052.   DO_RETURN_ADDRESS (crt_PanelNew_Internal (x1, y1, x2, y2, BindToBackground));
  2053.   crt_need_refresh ();
  2054. }
  2055.  
  2056. void crt_PanelDelete (TPanel Panel);
  2057. void crt_PanelDelete (TPanel Panel)
  2058. {
  2059.   TPanel *PList = &crt_PanelList;
  2060.   while (*PList && *PList != Panel) PList = &((*PList) -> Next);
  2061.   if (!*PList) DO_RETURN_ADDRESS (crt_fatal (3));
  2062.   DO_CRT_CHECK_WINCHANGED;
  2063.   crt_refresh_inhibit++;
  2064.   *PList = Panel -> Next;
  2065.   if (!crt_PanelList) DO_RETURN_ADDRESS (crt_fatal (4));
  2066.   savetostdscr (Panel);
  2067.   del_panel (Panel -> panel);
  2068.   delwin (Panel -> w);
  2069.   free (Panel);
  2070.   if (Panel == crt_ActivePanel)
  2071.     {
  2072.       crt_ActivePanel = NULL;
  2073.       crt_PanelActivate_Internal (crt_PanelList);
  2074.     }
  2075.   crt_last_shape = - 1;
  2076.   crt_refresh_inhibit--;
  2077.   crt_need_refresh ();
  2078. }
  2079.  
  2080. static TTextAttr cursattr2attr (int cursattr)
  2081. {
  2082.   int attr = 0;
  2083.   cursattr &= (A_ATTRIBUTES & ~A_ALTCHARSET);
  2084.   if (crt_attr2cursattr (crt_NormAttr) == cursattr) return crt_NormAttr;
  2085.   while (attr < 0x100 && crt_attr2cursattr (attr) != cursattr) attr++;
  2086.   return (attr == 0x100) ? crt_NormAttr : attr;
  2087. }
  2088.  
  2089. static void crt_setattr ()
  2090. {
  2091.   int cursattr;
  2092.   DO_CRT_CHECK_WINCHANGED;
  2093.   cursattr = crt_attr2cursattr (crt_TextAttr);
  2094.   wattrset (crt_ActivePanel -> w, cursattr);
  2095.   wbkgdset (crt_ActivePanel -> w, cursattr | ' ');
  2096. }
  2097.  
  2098. void crt_update_immediately (void);
  2099. void crt_update_immediately ()
  2100. {
  2101.   DO_CRT_CHECK_WINCHANGED;
  2102.   if (crt_update_level == UpdateRegularly) crt_stop_refresh ();
  2103.   typeahead (- 1);
  2104.   crt_refresh ();
  2105.   crt_set_typeahead ();
  2106. }
  2107.  
  2108. void crt_redraw (void);
  2109. void crt_redraw ()
  2110. {
  2111.   PANEL *panel;
  2112.   DO_CRT_CHECK_WINCHANGED;
  2113.   touchwin (stdscr);
  2114.   for (panel = panel_above (NULL); panel; panel = panel_above (panel))
  2115.     touchwin (panel_window (panel));
  2116.   clearok (curscr, TRUE);
  2117.   crt_last_shape = - 1;
  2118.   crt_update ();
  2119. }
  2120.  
  2121. void crt_setupdatelevel (TCRTUpdate level);
  2122. void crt_setupdatelevel (TCRTUpdate level)
  2123. {
  2124.   if (crt_inited)
  2125.     {
  2126.       DO_CRT_CHECK_WINCHANGED;
  2127.       if (crt_update_level == UpdateRegularly) crt_update_immediately ();
  2128.     }
  2129.   crt_update_level = level;
  2130.   crt_UpdateLevelChanged = TRUE;
  2131.   if (crt_inited) crt_set_typeahead ();
  2132. }
  2133.  
  2134. void crt_restore_terminal_no_crt (void);
  2135. void crt_restore_terminal_no_crt ()
  2136. {
  2137.   if (!crt_inited || crt_terminal_no_crt || crt_ShutDown) return;
  2138.   DO_CRT_CHECK_WINCHANGED; /* We DO need this here, otherwise the tputs in
  2139.                               crt_clear_terminal() can cause a segfault. */
  2140.   if (crt_ActivePanel) DO_RETURN_ADDRESS (crt_update_immediately ());
  2141.   crt_terminal_no_crt = TRUE;
  2142.   #ifdef USE_PDCURSES
  2143.   savetty ();
  2144.   #endif
  2145.   if (crt_clearflag)
  2146.     {
  2147.       #ifdef USE_NCURSES
  2148.       if (isprivate (enter_ca_mode))
  2149.         {
  2150.           crt_save_enter_ca_mode = enter_ca_mode;
  2151.           enter_ca_mode = NULL;
  2152.         }
  2153.       if (isprivate (exit_ca_mode))
  2154.         {
  2155.           crt_save_exit_ca_mode = exit_ca_mode;
  2156.           exit_ca_mode = NULL;
  2157.         }
  2158.       #endif
  2159.     }
  2160.   endwin ();
  2161.   #if defined (SIGTSTP) && !defined (XCURSES)
  2162.   signal (SIGTSTP, SIG_DFL);
  2163.   #endif
  2164.   if (crt_clearflag
  2165.       || (crt_save_previous_screen_flag > 0 && !(crt_screen_restored = crt_save_restore_screen (TRUE) > 0))
  2166.       || crt_save_previous_screen_flag == 0)
  2167.     crt_clear_terminal ();
  2168. }
  2169.  
  2170. void crt_restore_terminal_crt (void);
  2171. void crt_restore_terminal_crt ()
  2172. {
  2173.   if (crt_ShutDown) return;
  2174.   if (!crt_inited || !crt_terminal_no_crt) return;
  2175.   DO_CRT_CHECK_WINCHANGED;
  2176.   if (crt_screen_restored)
  2177.     {
  2178.       crt_screen_restored = FALSE;
  2179.       crt_save_restore_screen (FALSE);
  2180.     }
  2181.   #ifdef USE_PDCURSES
  2182.   resetty ();
  2183.   SETCURSOR (0, 0); doupdate (); /* @@ resetty() seems to get the cursor position wrong */
  2184.   #endif
  2185.   #if defined (SIGTSTP) && !defined (XCURSES)
  2186.   signal (SIGTSTP, &tstp_handler);
  2187.   #endif
  2188.   crt_rawout (TRUE);
  2189.   clearok (curscr, TRUE);
  2190.   crt_last_shape = - 1;
  2191.   crt_update ();
  2192.   #ifdef USE_NCURSES
  2193.   if (crt_save_enter_ca_mode) enter_ca_mode = crt_save_enter_ca_mode;
  2194.   if (crt_save_exit_ca_mode) exit_ca_mode = crt_save_exit_ca_mode;
  2195.   crt_save_enter_ca_mode = crt_save_exit_ca_mode = NULL;
  2196.   #endif
  2197.   #ifdef USE_PDCURSES
  2198.   PDC_save_key_modifiers (TRUE);
  2199.   #endif
  2200.   crt_terminal_no_crt = FALSE;
  2201. }
  2202.  
  2203. void crt_done (void);
  2204. void crt_done ()
  2205. {
  2206.   if (!crt_inited || crt_ShutDown) return;
  2207.   if (crt_ActivePanel && !crt_terminal_no_crt)
  2208.     {
  2209.       DO_RETURN_ADDRESS (crt_update_immediately ());
  2210.       endwin ();
  2211.     }
  2212.   #ifdef USE_NCURSES
  2213.   if (crt_save_exit_ca_mode) tputs (crt_save_exit_ca_mode, 1, putch);
  2214.   crt_save_enter_ca_mode = crt_save_exit_ca_mode = NULL;
  2215.   #endif
  2216.   if (crt_save_previous_screen_flag > 0 && !crt_terminal_no_crt)
  2217.     crt_save_restore_screen (TRUE);
  2218.   crt_inited = 0;
  2219.   #ifdef XCURSES
  2220.   XCursesExit ();
  2221.   #endif
  2222. }
  2223.  
  2224. void crt_set_curses_mode (Boolean on);
  2225. void crt_set_curses_mode (Boolean on)
  2226. {
  2227.   if (!crt_inited || crt_ShutDown) return;
  2228.   if (on)
  2229.     {
  2230.       reset_prog_mode ();
  2231.       crt_rawout (TRUE);
  2232.     }
  2233.   else
  2234.     {
  2235.       crt_rawout (FALSE);
  2236.       reset_shell_mode ();
  2237.     }
  2238. }
  2239.  
  2240. void crt_delay (unsigned ms);
  2241. void crt_delay (unsigned ms)
  2242. {
  2243.   DO_CRT_CHECK_WINCHANGED;
  2244.   crt_update_immediately ();
  2245.   napms (ms);
  2246. }
  2247.  
  2248. static int get_ch (void)
  2249. {
  2250.   int i;
  2251.   if (crt_ShutDown)
  2252.     return KEY_HUP;
  2253.   #ifdef XCURSES
  2254.   crt_ShutDownJumpActive = TRUE;
  2255.   if (setjmp (crt_ShutDownJump))
  2256.     i = KEY_HUP;
  2257.   else
  2258.   #endif
  2259.     /* Use stdscr rather than crt_ActivePanel -> w, so a non-top
  2260.        panel will not be redrawn. If the terminal is in non-CRT
  2261.        mode, use a dummy pad because a pad does *not* cause wgetch()
  2262.        to refresh(). Using the dummy pad in CRT mode does not work
  2263.        well for some reason (@@). */
  2264.     i = wgetch (crt_terminal_no_crt ? crt_dummy_pad : stdscr);
  2265.   #ifdef XCURSES
  2266.   crt_ShutDownJumpActive = FALSE;
  2267.   #endif
  2268.   return i;
  2269. }
  2270.  
  2271. static int wgetk ()
  2272. {
  2273.   int i = get_ch ();
  2274.   if (i == KEY_RESIZE) crt_screen_size_changed = TRUE;
  2275.   if (crt_screen_size_changed)
  2276.     {
  2277.       DO_CRT_CHECK_WINCHANGED;
  2278.       if (i != KEY_RESIZE && i != ERR) crt_key_buf = i;
  2279.       if (crt_key_buf == KEY_RESIZE) crt_key_buf = 0;
  2280.       i = KEY_RESIZE;
  2281.     }
  2282.   return i;
  2283. }
  2284.  
  2285. void crt_select (void *PrivateData, Boolean *ReadSelect, Boolean *WriteSelect, Boolean *ExceptSelect);
  2286. void crt_select (void *PrivateData, Boolean *ReadSelect, Boolean *WriteSelect, Boolean *ExceptSelect)
  2287. {
  2288.   (void) PrivateData;
  2289.   DO_CRT_CHECK_WINCHANGED;
  2290.   if (*ReadSelect)
  2291.     {
  2292.       if (crt_update_level == UpdateRegularly)
  2293.         {
  2294.           crt_stop_refresh ();
  2295.           crt_refresh ();
  2296.         }
  2297.       (*ReadSelect) = !!(crt_unget_key_buf || crt_key_buf || crt_fkey_buf || crt_screen_size_changed);
  2298.     }
  2299.   if (crt_get_output_fd () >= 0) (*WriteSelect) = FALSE;
  2300.   (*ExceptSelect) = FALSE;
  2301. }
  2302.  
  2303. static Boolean crt_keypressed_internal ()
  2304. {
  2305.   int ch;
  2306.   crt_nodelay (TRUE);
  2307.   ch = wgetk ();
  2308.   if (ch == ERR) return 0;
  2309.   crt_key_buf = ch;
  2310.   return 1;
  2311. }
  2312.  
  2313. Boolean crt_keypressed (void);
  2314. Boolean crt_keypressed ()
  2315. {
  2316.   DO_CRT_CHECK_WINCHANGED;
  2317.   if (crt_update_level >= UpdateInput) crt_update_immediately ();
  2318.   if (crt_unget_key_buf || crt_key_buf || crt_fkey_buf) return 1;
  2319.   return crt_keypressed_internal ();
  2320. }
  2321.  
  2322. void crt_SetScreenSize (int x, int y);
  2323. void crt_SetScreenSize (int x, int y)
  2324. {
  2325.   DO_CRT_CHECK_WINCHANGED;
  2326.   crt_update_immediately ();
  2327.   crt_change_screen_size (x, y);
  2328.   crt_screen_size_changed = TRUE;
  2329.   crt_setattr ();
  2330.   crt_redraw ();
  2331.   crt_GetLastMode ();
  2332.   crt_keypressed_internal ();
  2333.   if (crt_key_buf == KEY_RESIZE) crt_key_buf = 0;
  2334. }
  2335.  
  2336. void crt_SetMonochrome (Boolean Monochrome);
  2337. void crt_SetMonochrome (Boolean Monochrome)
  2338. {
  2339.   DO_CRT_CHECK_WINCHANGED;
  2340.   crt_ColorFlag = crt_HasColors && !Monochrome;
  2341.   crt_setattr ();
  2342.   crt_redraw ();
  2343.   crt_GetLastMode ();
  2344. }
  2345.  
  2346. void crt_ungetch (TKey ch);
  2347. void crt_ungetch (TKey ch)
  2348. {
  2349.   crt_unget_key_buf = ch;
  2350. }
  2351.  
  2352. static Char find_key (TKeyTable *table, int ch)
  2353. {
  2354.   while (table -> curses_key != 0 && table -> curses_key != ch) table++;
  2355.   return table -> crt_key;
  2356. }
  2357.  
  2358. /* Don't use toupper() since it messes up the function key codes */
  2359. static int upcase (int ch)
  2360. {
  2361.   if (ch >= 'a' && ch <= 'z')
  2362.     return ch - 'a' + 'A';
  2363.   else
  2364.     return ch;
  2365. }
  2366.  
  2367. TKey crt_altkey (Char ch);
  2368. TKey crt_altkey (Char ch)
  2369. {
  2370.   return 0x100 * find_key (EscKeyTable, upcase (ch));
  2371. }
  2372.  
  2373. TKey crt_altgrkey (Char ch);
  2374. TKey crt_altgrkey (Char ch)
  2375. {
  2376.   return 0x100 * find_key (AltGrKeyTable, upcase (ch));
  2377. }
  2378.  
  2379. TKey crt_extrakey (Char ch);
  2380. TKey crt_extrakey (Char ch)
  2381. {
  2382.   return 0x100 * find_key (ExtraKeyTable, upcase (ch));
  2383. }
  2384.  
  2385. TKey crt_readkeyword (void);
  2386. TKey crt_readkeyword ()
  2387. {
  2388.   int ch, chu, shiftstate;
  2389.   Char c, cs;
  2390.   (void) &ch; /* don't put it into a register because of longjmp() */
  2391.   DO_CRT_CHECK_WINCHANGED;
  2392.   if (crt_update_level > UpdateWaitInput ||
  2393.       ((crt_update_level == UpdateWaitInput) &&
  2394.        !(crt_unget_key_buf || crt_key_buf || crt_keypressed_internal ())))
  2395.     crt_update_immediately ();
  2396.   if (crt_unget_key_buf)
  2397.     {
  2398.       TKey k = crt_unget_key_buf;
  2399.       crt_unget_key_buf = 0;
  2400.       return k;
  2401.     }
  2402.   else if (crt_key_buf)
  2403.     {
  2404.       ch = crt_key_buf;
  2405.       crt_key_buf = 0;
  2406.       if (ch == KEY_RESIZE)
  2407.         {
  2408.           int i;
  2409.           crt_nodelay (TRUE);
  2410.           i = get_ch ();
  2411.           if (i != KEY_RESIZE && i == ERR) crt_key_buf = i;
  2412.         }
  2413.     }
  2414.   else
  2415.     {
  2416.       crt_nodelay (FALSE);
  2417.       do
  2418.         {
  2419.           ch = wgetk ();
  2420.           if (crt_unget_key_buf) /* may have been set via crt_ungetch() by a handler for SIGINT etc. */
  2421.             {
  2422.               TKey k = crt_unget_key_buf;
  2423.               crt_unget_key_buf = 0;
  2424.               if (ch != ERR) crt_key_buf = ch;
  2425.               return k;
  2426.             }
  2427.         }
  2428.       while (ch == ERR);
  2429.     }
  2430.   if (ch == KEY_HUP)
  2431.     return 0x100 * ksHUp;
  2432.   #ifndef USE_PDCURSES
  2433.   if (ch == chEsc)
  2434.     {
  2435.       crt_nodelay (TRUE);
  2436.       ch = wgetk ();
  2437.       if (ch == ERR) return chEsc;
  2438.       c = find_key (EscKeyTable, upcase (ch));
  2439.       if (c != 0)
  2440.         return 0x100 * c;
  2441.       if (ch >= FKEY1 && ch <= FKEY1 + 9)
  2442.         return 0x100 * (ksAltF1 + ch - FKEY1);
  2443.       if (ch >= FKEY1 + 10 && ch <= FKEY1 + 11)
  2444.         return 0x100 * (ksAltF11 + ch - (FKEY1 + 10));
  2445.       crt_key_buf = ch;
  2446.       return chEsc;
  2447.     }
  2448.   #endif
  2449.   shiftstate = crt_getshiftstate ();
  2450.   if ((c = find_key (KeyTable, ch))) ch = c;
  2451.   chu = upcase (ch);
  2452.   if ((shiftstate & shShift) && (cs = find_key (ShiftKeyTable, chu))) return 0x100 * cs;
  2453.   if ((shiftstate & shAlt  ) && (cs = find_key (AltKeyTable  , chu))) return 0x100 * cs;
  2454.   if ((shiftstate & shAltGr) && (cs = find_key (AltGrKeyTable, chu))) return 0x100 * cs;
  2455.   if ((shiftstate & shExtra) && (cs = find_key (ExtraKeyTable, chu))) return 0x100 * cs;
  2456.   if (1 <= ch && ch <= 0xff) return ch;
  2457.   if (ch >= FKEY1 && ch <= FKEY1 + 9)
  2458.     {
  2459.       if (shiftstate & shAnyAlt)
  2460.         c = ksAltF1 + ch - FKEY1;
  2461.       else if (shiftstate & shCtrl)
  2462.         c = ksCtrlF1 + ch - FKEY1;
  2463.       else if (shiftstate & shShift)
  2464.         c = ksShF1 + ch - FKEY1;
  2465.       else
  2466.         c = ksF1 + ch - FKEY1;
  2467.     }
  2468.   else if (ch >= FKEY1 + 10 && ch <= FKEY1 + 11)
  2469.     {
  2470.       if (shiftstate & shAnyAlt)
  2471.         c = ksAltF11 + ch - (FKEY1 + 10);
  2472.       else if (shiftstate & shCtrl)
  2473.         c = ksCtrlF11 + ch - (FKEY1 + 10);
  2474.       else if (shiftstate & shShift)
  2475.         c = ksShF11 + ch - (FKEY1 + 10);
  2476.       else
  2477.         c = ksF11 + ch - (FKEY1 + 10);
  2478.     }
  2479.   else if (ch >= FKEYSH1 && ch <= FKEYSH1 + 9)
  2480.     c = ksShF1 + ch - FKEYSH1;
  2481.   else if (ch >= FKEYCTRL1 && ch <= FKEYCTRL1 + 9)
  2482.     c = ksCtrlF1 + ch - FKEYCTRL1;
  2483.   else if (ch >= FKEYALT1 && ch <= FKEYALT1 + 9)
  2484.     c = ksAltF1 + ch - FKEYALT1;
  2485.   else
  2486.     c = find_key (FKeyTable, ch);
  2487.   if ((shiftstate & shShift) && (cs = find_key (ShiftFKeyTable, c)))
  2488.     c = cs;
  2489.   else if ((shiftstate & shCtrl) && (cs = find_key (CtrlFKeyTable, c)))
  2490.     c = cs;
  2491.   else if ((shiftstate & shAlt) && (cs = find_key (AltFKeyTable, c)))
  2492.     c = cs;
  2493.   return 0x100 * c;
  2494. }
  2495.  
  2496. Char crt_readkey (void);
  2497. Char crt_readkey ()
  2498. {
  2499.   Char tmp;
  2500.   int ch;
  2501.   if (crt_fkey_buf)
  2502.     {
  2503.       tmp = crt_fkey_buf;
  2504.       crt_fkey_buf = 0;
  2505.       return tmp;
  2506.     }
  2507.   DO_RETURN_ADDRESS (ch = crt_readkeyword ());
  2508.   if (ch & 0xff) return ch;
  2509.   crt_fkey_buf= ch / 0x100;
  2510.   return 0;
  2511. }
  2512.  
  2513. size_t crt_winsize (void);
  2514. size_t crt_winsize ()
  2515. {
  2516.   DO_CRT_CHECK_WINCHANGED;
  2517.   return   (crt_ActivePanel -> WindXMax - crt_ActivePanel -> WindXMin + 1)
  2518.          * (crt_ActivePanel -> WindYMax - crt_ActivePanel -> WindYMin + 1)
  2519.          * sizeof (chtype);
  2520. }
  2521.  
  2522. void crt_readwin (chtype *buf);
  2523. void crt_readwin (chtype *buf)
  2524. {
  2525.   DO_CRT_CHECK_WINCHANGED;
  2526.   {
  2527.     int xsize = crt_ActivePanel -> WindXMax - crt_ActivePanel -> WindXMin + 1,
  2528.         ysize = crt_ActivePanel -> WindYMax - crt_ActivePanel -> WindYMin + 1,
  2529.         yc, sx, sy;
  2530.     chtype temp [xsize + 1];
  2531.     getyx (crt_ActivePanel -> w, sy, sx);
  2532.     for (yc = 0; yc < ysize; yc++)
  2533.       {
  2534.         mvwinchnstr (crt_ActivePanel -> w, yc, 0, temp, xsize);
  2535.         memcpy (buf + xsize * yc, temp, xsize * sizeof (chtype)); /* don't copy the 0 terminator! */
  2536.       }
  2537.     wmove (crt_ActivePanel -> w, sy, sx);
  2538.   }
  2539. }
  2540.  
  2541. void crt_writewin (chtype *buf);
  2542. void crt_writewin (chtype *buf)
  2543. {
  2544.   DO_CRT_CHECK_WINCHANGED;
  2545.   {
  2546.     int xsize = crt_ActivePanel -> WindXMax - crt_ActivePanel -> WindXMin + 1,
  2547.         ysize = crt_ActivePanel -> WindYMax - crt_ActivePanel -> WindYMin + 1,
  2548.         yc, sx, sy;
  2549.     getyx (crt_ActivePanel -> w, sy, sx);
  2550.     for (yc = 0; yc < ysize; yc++)
  2551.       mvwaddchnstr (crt_ActivePanel -> w, yc, 0, buf + xsize * yc, xsize);
  2552.     wmove (crt_ActivePanel -> w, sy, sx);
  2553.     crt_need_refresh ();
  2554.   }
  2555. }
  2556.  
  2557. void crt_clrscr (void);
  2558. void crt_clrscr ()
  2559. {
  2560.   crt_setattr ();
  2561.   werase (crt_ActivePanel -> w);
  2562.   wmove (crt_ActivePanel -> w, 0, 0);
  2563.   crt_cursor_pos.x = crt_cursor_pos.y = 0;
  2564.   crt_need_refresh ();
  2565. }
  2566.  
  2567. void crt_clreol (void);
  2568. void crt_clreol ()
  2569. {
  2570.   crt_setattr ();
  2571.   wclrtoeol (crt_ActivePanel -> w);
  2572.   crt_need_refresh ();
  2573. }
  2574.  
  2575. void crt_insline (void);
  2576. void crt_insline ()
  2577. {
  2578.   crt_setattr ();
  2579.   winsertln (crt_ActivePanel -> w);
  2580.   (void) idlok (crt_ActivePanel -> w, TRUE);
  2581.   crt_need_refresh ();
  2582. }
  2583.  
  2584. void crt_delline (void);
  2585. void crt_delline ()
  2586. {
  2587.   crt_setattr ();
  2588.   wdeleteln (crt_ActivePanel -> w);
  2589.   (void) idlok (crt_ActivePanel -> w, TRUE);
  2590.   crt_need_refresh ();
  2591. }
  2592.  
  2593. void crt_setpccharset (Boolean PCCharSet);
  2594. void crt_setpccharset (Boolean PCCharSet)
  2595. {
  2596.   DO_CRT_CHECK_WINCHANGED;
  2597.   crt_ActivePanel -> PCCharSet = PCCharSet;
  2598. }
  2599.  
  2600. Boolean crt_getpccharset (void);
  2601. Boolean crt_getpccharset ()
  2602. {
  2603.   DO_CRT_CHECK_WINCHANGED;
  2604.   return crt_ActivePanel -> PCCharSet;
  2605. }
  2606.  
  2607. void crt_setcontrolchars (Boolean UseControlChars);
  2608. void crt_setcontrolchars (Boolean UseControlChars)
  2609. {
  2610.   DO_CRT_CHECK_WINCHANGED;
  2611.   crt_ActivePanel -> UseControlChars = UseControlChars;
  2612. }
  2613.  
  2614. Boolean crt_getcontrolchars (void);
  2615. Boolean crt_getcontrolchars ()
  2616. {
  2617.   DO_CRT_CHECK_WINCHANGED;
  2618.   return crt_ActivePanel -> UseControlChars;
  2619. }
  2620.  
  2621. size_t crt_read (void *PrivateData, Char *buffer, size_t size);
  2622. size_t crt_read (void *PrivateData, Char *buffer, size_t size)
  2623. {
  2624.   int res;
  2625.   size_t n;
  2626.   Char *p;
  2627.   (void) PrivateData;
  2628.   crt_setattr ();
  2629.   if (!crt_line_buf_count)
  2630.     {
  2631.       crt_nodelay (FALSE);
  2632.       crt_rawout (FALSE);
  2633.       echo ();
  2634.       if (crt_update_level >= UpdateWaitInput) crt_update_immediately ();
  2635.       do
  2636.         {
  2637.           errno = 0;
  2638.           res = wgetnstr (crt_ActivePanel -> w, crt_line_buf, MAXLENGTH - 1);
  2639.         }
  2640.       while
  2641.         #ifdef EINTR
  2642.         (res == ERR && errno == EINTR);
  2643.         #else
  2644.         (0);
  2645.         #endif
  2646.       if (res == ERR)
  2647.         crt_line_buf_count = 0;
  2648.       else
  2649.         {
  2650.           if (crt_CheckEOF)
  2651.             {
  2652.               do
  2653.                 {
  2654.                   p = strchr (crt_line_buf, 26);
  2655.                   if (p) *p = 0;
  2656.                 }
  2657.               while (p);
  2658.             }
  2659.           crt_line_buf_count = strlen (crt_line_buf);
  2660.           crt_line_buf [crt_line_buf_count++] = '\n';
  2661.         }
  2662.       crt_line_buf_pos = crt_line_buf;
  2663.       noecho ();
  2664.       crt_rawout (TRUE);
  2665.     }
  2666.   n = (crt_line_buf_count < size) ? crt_line_buf_count : size;
  2667.   memcpy (buffer, crt_line_buf_pos, n);
  2668.   crt_line_buf_pos += n;
  2669.   crt_line_buf_count -= n;
  2670.   return n;
  2671. }
  2672.  
  2673. void crt_flash (void);
  2674. void crt_flash ()
  2675. {
  2676.   DO_CRT_CHECK_WINCHANGED;
  2677.   flash ();
  2678. }
  2679.  
  2680. void crt_beep (void);
  2681. void crt_beep ()
  2682. {
  2683.   DO_CRT_CHECK_WINCHANGED;
  2684.   if (crt_VisualBell)
  2685.     crt_flash ();
  2686.   else
  2687.     {
  2688.       beep ();
  2689.       crt_delay (100);
  2690.     }
  2691. }
  2692.  
  2693. static chtype chtransform (Char ch, TTextAttr attr, Boolean PCCharSet)
  2694. {
  2695.   Boolean pccs = PCCharSet || (ch < ' ');
  2696.   if (ch == 0
  2697.   #ifdef XCURSES
  2698.     || (crt_ColorFlag && (attr & 7) == ((attr >> 4) & 7))
  2699.   #endif
  2700.     || (attr & ~(crt_ColorFlag ? 0x80 : 0x88)) == 0)
  2701.     return ' ';
  2702.   #if !defined (USE_PDCURSES) || defined (XCURSES)
  2703.   if ((!crt_linux_console && pccs)
  2704.       || ch == chBell || ch == chBkSp || ch == chTab || ch == chLF || ch == chFF
  2705.       || ch == chCR || ch == chEsc || ch == 14 || ch == 15 || ch == 155)
  2706.     {
  2707.       if (ch < 32) return chars_0_31 [ch];
  2708.       if (ch >= 128)
  2709.         {
  2710.           chtype c = chars_128_255 [ch - 128];
  2711.           #ifdef XCURSES
  2712.           /* ACS_BLOCK is not supported in all charsets, but we can emulate it */
  2713.           if (c == ACS_BLOCK)
  2714.             c = ' ' | crt_attr2cursattr ((attr >> 4) | ((attr & 15) << 4));
  2715.           #endif
  2716.           return c;
  2717.         }
  2718.     }
  2719.   #endif
  2720.   if (!pccs && iscntrl (ch)) return ' ';
  2721.   return (crt_linux_console && pccs) ? ch | A_ALTCHARSET : ch;
  2722. }
  2723.  
  2724. void crt_readchar (int x, int y, Char *ch, TTextAttr *attr);
  2725. void crt_readchar (int x, int y, Char *ch, TTextAttr *attr)
  2726. {
  2727.   int sx, sy, cc;
  2728.   chtype c;
  2729.   crt_setattr ();
  2730.   getyx (crt_ActivePanel -> w, sy, sx);
  2731.   c = mvwinch (crt_ActivePanel -> w, y - 1, x - 1);
  2732.   *attr = cursattr2attr (c);
  2733.   c &= A_CHARTEXT;
  2734.   for (cc = 0x20; cc < 0x120 && (chtransform (cc % 0x100, 7, crt_ActivePanel -> PCCharSet) & A_CHARTEXT) != c; cc++);
  2735.   *ch = cc % 0x100;
  2736.   wmove (crt_ActivePanel -> w, sy, sx);
  2737. }
  2738.  
  2739. void crt_fillwin (Char ch, TTextAttr attr);
  2740. void crt_fillwin (Char ch, TTextAttr attr)
  2741. {
  2742.   DO_CRT_CHECK_WINCHANGED;
  2743.   wbkgdset (crt_ActivePanel -> w, crt_attr2cursattr (attr) | chtransform (ch, attr, crt_ActivePanel -> PCCharSet));
  2744.   werase (crt_ActivePanel -> w);
  2745.   crt_setattr ();
  2746.   crt_need_refresh ();
  2747. }
  2748.  
  2749. size_t crt_write (void *PrivateData, const Char *buffer, size_t size);
  2750. size_t crt_write (void *PrivateData, const Char *buffer, size_t size)
  2751. {
  2752.   size_t i;
  2753.   Char ch;
  2754.   (void) PrivateData;
  2755.   crt_setattr ();
  2756.   for (i = 0; i < size; i++)
  2757.     {
  2758.       ch = buffer [i];
  2759.       if (crt_ActivePanel -> UseControlChars)
  2760.         {
  2761.           if (ch == chBell)
  2762.             {
  2763.               crt_beep ();
  2764.               continue;
  2765.             }
  2766.           else if (ch == chBkSp)
  2767.             {
  2768.               int x, y;
  2769.               getyx (crt_ActivePanel -> w, y, x);
  2770.               if (x > 0)
  2771.                 wmove (crt_ActivePanel -> w, y, x - 1);
  2772.               continue;
  2773.             }
  2774.           else if (ch == chLF)
  2775.             {
  2776.               int x, y;
  2777.               getyx (crt_ActivePanel -> w, y, x);
  2778.               if (y + crt_ActivePanel -> WindYMin >= crt_ActivePanel -> WindYMax)
  2779.                 {
  2780.                   if (crt_ActivePanel -> ScrollState) wscrl (crt_ActivePanel -> w, 1);
  2781.                   wmove (crt_ActivePanel -> w, y, 0);
  2782.                 }
  2783.               else
  2784.                 wmove (crt_ActivePanel -> w, y + 1, 0);
  2785.               continue;
  2786.             }
  2787.           else if (ch == chCR)
  2788.             {
  2789.               int x, y;
  2790.               getyx (crt_ActivePanel -> w, y, x);
  2791.               wmove (crt_ActivePanel -> w, y, 0);
  2792.               continue;
  2793.             }
  2794.         }
  2795.       waddch (crt_ActivePanel -> w, chtransform (ch, crt_TextAttr, crt_ActivePanel -> PCCharSet));
  2796.     }
  2797.   update_crt_cursor_pos ();
  2798.   crt_need_refresh ();
  2799.   return size;
  2800. }
  2801.  
  2802. void crt_writecharattrat (int x, int y, int Count, TCharAttr *CharAttr);
  2803. void crt_writecharattrat (int x, int y, int Count, TCharAttr *CharAttr)
  2804. {
  2805.   crt_setattr ();
  2806.   {
  2807.     int m = crt_ActivePanel -> WindXMax - crt_ActivePanel -> WindXMin + 1 - x + 1;
  2808.     if (Count > m) Count = m;
  2809.     if (Count > 0)
  2810.       {
  2811.         chtype buf [Count];
  2812.         int cattr = 0, LastAttr = - 1, sx, sy, i;
  2813.         TTextAttr Attr;
  2814.         for (i = 0; i < Count; i++)
  2815.           {
  2816.             Attr = CharAttr [i].Attr;
  2817.             if (Attr != LastAttr)
  2818.               {
  2819.                 cattr = crt_attr2cursattr (Attr);
  2820.                 LastAttr = Attr;
  2821.               }
  2822.             buf [i] = chtransform (CharAttr [i].Ch, Attr, CharAttr [i].PCCharSet) | cattr;
  2823.           }
  2824.         getyx (crt_ActivePanel -> w, sy, sx);
  2825.         wmove (crt_ActivePanel -> w, y - 1, x - 1);
  2826.         crt_setscroll (FALSE);
  2827.         waddchnstr (crt_ActivePanel -> w, buf, Count);
  2828.         crt_setscroll (crt_ActivePanel -> ScrollState);
  2829.         wmove (crt_ActivePanel -> w, sy, sx);
  2830.         crt_need_refresh ();
  2831.       }
  2832.   }
  2833. }
  2834.