* harbour/include/hbgtinfo.ch
* harbour/contrib/libct/ctwin.c
* harbour/source/rtl/gtalleg/gtalleg.c
* harbour/source/rtl/gtcrs/gtcrs.c
* harbour/source/rtl/gtdos/gtdos.c
* harbour/source/rtl/gtos2/gtos2.c
* harbour/source/rtl/gtpca/gtpca.c
* harbour/source/rtl/gtsln/gtsln.c
* harbour/source/rtl/gtstd/gtstd.c
* harbour/source/rtl/gtwin/gtwin.c
* harbour/source/rtl/gtwvt/gtwvt.c
* harbour/source/rtl/gtxwc/gtxwc.c
+ added support for GTI_FULLSCREEN, GTI_KBDSUPPORT, GTI_ISCTWIN
* harbour/source/rtl/hbgtcore.c
! fixed line and box drawing when the coordinates are out of screen size
* harbour/include/hbapi.h
* harbour/include/hbcomp.h
* harbour/include/hbpcode.h
* harbour/include/hbstack.h
* harbour/include/hbvm.h
* harbour/include/hbxvm.h
* harbour/source/compiler/complex.c
* harbour/source/compiler/genc.c
* harbour/source/compiler/gencc.c
* harbour/source/compiler/harbour.c
* harbour/source/compiler/harbour.y
* harbour/source/compiler/harbour.yyc
* harbour/source/compiler/harbour.yyh
* harbour/source/compiler/hbdead.c
* harbour/source/compiler/hbfix.c
* harbour/source/compiler/hblbl.c
* harbour/source/compiler/hbpcode.c
* harbour/source/compiler/hbstripl.c
* harbour/source/vm/classes.c
* harbour/source/vm/estack.c
* harbour/source/vm/hvm.c
* harbour/source/vm/itemapi.c
! added protection against cyclic references in arrays
* eliminated action parameter from hb_vmRequestReenter() /
hb_vmRequestRestore()
* moved s_lRecoverBase and s_uiActionRequest to HB_STACK structure
for future MT HVM version
+ added internal item structure hb_struRecover - it's not real item
but this structure is used to keep information about BEGIN SEQUENCE
data - it reduce HB_STACK usage
+ added support for ALWAYS clause in BEGIN SEQUENCE
The syntax is:
BEGIN SEQUENCE
<code>
[ RECOVER [ USING oErr ] ]
<recoverCode>
[ ALWAYS ]
<alwaysCode>
END [ SEQUENCE ]
It's guaranteed that <alwaysCode> is _ALWAYS_ executed even if
inside <code> or <recoverCode> some new exceptions like RETURN,
BREAK or QUIT will appear.
Please note that when the following code is executed:
BEGIN SEQUENCE
<code>
ALWAYS
<alwaysCode>
END
(without RECOVER clause) then BREAK exception inside <code> is not
recovered, <alwaysCode> is executed and then BREAK exception is
passed to outer BEGIN SEQUENCE. This is the same semantic as
used in TRY / [ CATCH ] / FINALLY / END
Those of you who prefer to use TRY / CATCH / FINALLY / END instead
of BEGIN SEQUENCE / RECOVER / ALWAYS / END can simply add to your
source code:
#command TRY => BEGIN SEQUENCE
#command CATCH [ oErr ] => RECOVER [ USING <oErr> ]
and:
errorBlock( {|oErr| break( oErr ) } )
Though instead of 'break( oErr )' I suggest to use some small function
which will support some basic recovery/substitute operations like in
default errorsys() and LockErrHandler() to not break existing code
which may depends on the default behavior.
If you want I can add direct support for TRY / CATCH / FINALLY / END
but I'm not sure it's really necessary.
Please note also that in Harbour ALWAYS code is execute even for QUIT
excpetion.
When <alwaysCode> is executed current exception is stored and restored
when is finished. If new exception appears inside <alwaysCode> then
restored exception depends on the priority in the following order:
QUIT // highest priority
BREAK
RETURN
If both exceptions have the same priority and contain additional value
(error object in BREAK or return value in RETURN) then the recently set
one is restored. It's similar behavior to destructor code.
* harbour/source/common/hbstr.c
* moved one character length string table (hb_szAscii) from hvm.c
to use it also in compiler and preprocessor
* harbour/source/compiler/ppcomp.c
* harbour/source/pp/ppcore.c
* harbour/source/pp/pplib.c
* tuned error messages to be more Clipper compatible
% use static strings from hb_szAscii
* harbour/source/rtl/alert.prg
* use hb_gtInfo( GTI_FULLSCREEN ) to detect type of GT driver
! some minor fixes
TOFIX: we have to also use GTI_ISCTWIN or add window allocation
to standard GT drivers to be Clipper compatible when CTWIN
is used - In Clipper Tools ALERT() works in differ way then
the standard one. It creates separate window box to display
data, supports SETKEY(), etc. I'll think about adding some
extended support for ALERT() and similar operations (f.e.
separate debugger windows) to GT API so it will be also
possible to overload standard alert() command by GUI message
box in GTGUI and similar GT drivers.
* harbour/source/rtl/binnumx.c
! fixed U2BIN() - wrong casting
3009 lines
89 KiB
C
3009 lines
89 KiB
C
/*
|
|
* $Id$
|
|
*/
|
|
|
|
/*
|
|
* Harbour Project source code:
|
|
* Video subsystem based on ncurses screen library.
|
|
*
|
|
* Copyright 2005 Przemyslaw Czerpak < druzus /at/ priv.onet.pl >
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2, or (at your option)
|
|
* any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this software; see the file COPYING. If not, write to
|
|
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
|
* Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/).
|
|
*
|
|
* As a special exception, the Harbour Project gives permission for
|
|
* additional uses of the text contained in its release of Harbour.
|
|
*
|
|
* The exception is that, if you link the Harbour libraries with other
|
|
* files to produce an executable, this does not by itself cause the
|
|
* resulting executable to be covered by the GNU General Public License.
|
|
* Your use of that executable is in no way restricted on account of
|
|
* linking the Harbour library code into it.
|
|
*
|
|
* This exception does not however invalidate any other reasons why
|
|
* the executable file might be covered by the GNU General Public License.
|
|
*
|
|
* This exception applies only to the code released by the Harbour
|
|
* Project under the name Harbour. If you copy code from other
|
|
* Harbour Project or Free Software Foundation releases into a copy of
|
|
* Harbour, as the General Public License permits, the exception does
|
|
* not apply to the code that you add in this way. To avoid misleading
|
|
* anyone as to the status of such modified files, you must delete
|
|
* this exception notice from them.
|
|
*
|
|
* If you write modifications of your own for Harbour, it is your choice
|
|
* whether to permit this exception to apply to your modifications.
|
|
* If you do not wish that, delete this exception notice.
|
|
*
|
|
*/
|
|
|
|
/* NOTE: User programs should never call this layer directly! */
|
|
|
|
/* *********************************************************************** */
|
|
|
|
#include "gtcrs.h"
|
|
|
|
static HB_GT_FUNCS SuperTable;
|
|
#define HB_GTSUPER (&SuperTable)
|
|
|
|
/* this variable should be global and checked in main VM loop */
|
|
static volatile BOOL s_BreakFlag = FALSE;
|
|
static volatile BOOL s_InetrruptFlag = FALSE;
|
|
static volatile BOOL s_WinSizeChangeFlag = FALSE;
|
|
|
|
static volatile BOOL s_SignalFlag = FALSE;
|
|
static volatile BOOL s_SignalTable[MAX_SIGNO];
|
|
|
|
static int s_iStdIn, s_iStdOut, s_iStdErr;
|
|
|
|
typedef struct evtFD {
|
|
int fd;
|
|
int mode;
|
|
int status;
|
|
void *data;
|
|
int (*eventFunc) (int, int, void*);
|
|
} evtFD;
|
|
|
|
typedef struct mouseEvent {
|
|
int row, col;
|
|
int buttonstate;
|
|
int lbuttons;
|
|
int lbup_row, lbup_col;
|
|
int lbdn_row, lbdn_col;
|
|
int rbup_row, rbup_col;
|
|
int rbdn_row, rbdn_col;
|
|
int mbup_row, mbup_col;
|
|
int mbdn_row, mbdn_col;
|
|
/* to analize DBLCLK on xterm */
|
|
int click_delay;
|
|
struct timeval BL_time;
|
|
struct timeval BR_time;
|
|
struct timeval BM_time;
|
|
} mouseEvent;
|
|
|
|
typedef struct keyTab {
|
|
int ch;
|
|
int key;
|
|
struct keyTab *nextCh;
|
|
struct keyTab *otherCh;
|
|
} keyTab;
|
|
|
|
typedef struct InOutBase {
|
|
int terminal_type;
|
|
|
|
struct keyTab *pKeyTab;
|
|
int key_flag;
|
|
int esc_delay;
|
|
int key_counter;
|
|
int nation_mode;
|
|
unsigned char *in_transtbl;
|
|
unsigned char *out_transtbl;
|
|
unsigned char *nation_transtbl;
|
|
int *charmap;
|
|
|
|
int cursor, lcursor;
|
|
int row, col;
|
|
int maxrow, maxcol;
|
|
int is_color;
|
|
unsigned int disp_count;
|
|
|
|
char *acsc, *beep, *flash, *civis, *cnorm, *cvvis;
|
|
|
|
int mouse_type;
|
|
int mButtons;
|
|
int nTermMouseChars;
|
|
unsigned char cTermMouseBuf[3];
|
|
mouseEvent mLastEvt;
|
|
#ifdef HAVE_GPM_H
|
|
Gpm_Connect Conn;
|
|
#endif
|
|
|
|
int base_infd;
|
|
int base_outfd;
|
|
int stdoutfd;
|
|
int stderrfd;
|
|
pid_t termpid;
|
|
int lTIOsaved;
|
|
struct termios saved_TIO, curr_TIO;
|
|
|
|
unsigned char stdin_buf[STDIN_BUFLEN];
|
|
int stdin_ptr_l;
|
|
int stdin_ptr_r;
|
|
int stdin_inbuf;
|
|
|
|
evtFD **event_fds;
|
|
int efds_size;
|
|
int efds_no;
|
|
|
|
/* curses data */
|
|
SCREEN *basescr;
|
|
WINDOW *stdscr;
|
|
FILE *basein;
|
|
FILE *baseout;
|
|
chtype std_chmap[256];
|
|
chtype box_chmap[256];
|
|
chtype attr_map[256];
|
|
chtype attr_mask;
|
|
} InOutBase;
|
|
|
|
static InOutBase *s_ioBase = NULL;
|
|
|
|
static InOutBase **s_ioBaseTab = NULL;
|
|
static int s_iSize_ioBaseTab = 0;
|
|
static int s_iActive_ioBase = -1;
|
|
|
|
static void set_tmevt(unsigned char *cMBuf, mouseEvent *);
|
|
static int getMouseKey(mouseEvent *);
|
|
static void destroy_ioBase(InOutBase *ioBase);
|
|
static void sig_handler(int signo);
|
|
|
|
static void curs_wrkaround( void );
|
|
|
|
typedef struct ClipKeyCode {
|
|
int key;
|
|
int alt_key;
|
|
int ctrl_key;
|
|
int shift_key;
|
|
} ClipKeyCode;
|
|
|
|
/* The tables below are indexed by internal key value,
|
|
* It cause that we don't have to make any linear scans
|
|
* to access information proper ClipKeyCode entry
|
|
*/
|
|
static const ClipKeyCode stdKeyTab[NO_STDKEYS] = {
|
|
{K_SPACE, 0, 0, 0}, /* 32 */
|
|
{'!', 0, 0, 0}, /* 33 */
|
|
{'"', 0, 0, 0}, /* 34 */
|
|
{'#', 0, 0, 0}, /* 35 */
|
|
{'$', 0, 0, 0}, /* 36 */
|
|
{'%', 0, 0, 0}, /* 37 */
|
|
{'&', 0, 0, 0}, /* 38 */
|
|
{'\'', 296, 7, 0}, /* 39 */
|
|
{'(', 0, 0, 0}, /* 40 */
|
|
{')', 0, 0, 0}, /* 41 */
|
|
{'*', 0, 0, 0}, /* 42 */
|
|
{'+', 0, 0, 0}, /* 43 */
|
|
{',', 307, 0, 0}, /* 44 */
|
|
{'-', 386, 31, 0}, /* 45 */
|
|
{'.', 308, 0, 0}, /* 46 */
|
|
{'/', 309, 127, 0}, /* 47 */
|
|
{'0', K_ALT_0, 0, 0}, /* 48 */
|
|
{'1', K_ALT_1, 0, 0}, /* 49 */
|
|
{'2', K_ALT_2, 259, 0}, /* 50 */
|
|
{'3', K_ALT_3, 27, 0}, /* 51 */
|
|
{'4', K_ALT_4, 28, 0}, /* 52 */
|
|
{'5', K_ALT_5, 29, 0}, /* 53 */
|
|
{'6', K_ALT_6, 30, 0}, /* 54 */
|
|
{'7', K_ALT_7, 31, 0}, /* 55 */
|
|
{'8', K_ALT_8, 127, 0}, /* 56 */
|
|
{'9', K_ALT_9, 0, 0}, /* 57 */
|
|
{':', 0, 0, 0}, /* 58 */
|
|
{';', 295, 0, 0}, /* 59 */
|
|
{'<', 0, 0, 0}, /* 60 */
|
|
{'=', K_ALT_EQUALS, 0, 0}, /* 61 */
|
|
{'>', 0, 0, 0}, /* 62 */
|
|
{'?', 0, 0, 0}, /* 63 */
|
|
{'@', 0, 0, 0}, /* 64 */
|
|
{'A', K_ALT_A, K_CTRL_A, 0}, /* 65 */
|
|
{'B', K_ALT_B, K_CTRL_B, 0}, /* 66 */
|
|
{'C', K_ALT_C, K_CTRL_C, 0}, /* 67 */
|
|
{'D', K_ALT_D, K_CTRL_D, 0}, /* 68 */
|
|
{'E', K_ALT_E, K_CTRL_E, 0}, /* 69 */
|
|
{'F', K_ALT_F, K_CTRL_F, 0}, /* 70 */
|
|
{'G', K_ALT_G, K_CTRL_G, 0}, /* 71 */
|
|
{'H', K_ALT_H, K_CTRL_H, 0}, /* 72 */
|
|
{'I', K_ALT_I, K_CTRL_I, 0}, /* 73 */
|
|
{'J', K_ALT_J, K_CTRL_J, 0}, /* 74 */
|
|
{'K', K_ALT_K, K_CTRL_K, 0}, /* 75 */
|
|
{'L', K_ALT_L, K_CTRL_L, 0}, /* 76 */
|
|
{'M', K_ALT_M, K_CTRL_M, 0}, /* 77 */
|
|
{'N', K_ALT_N, K_CTRL_N, 0}, /* 78 */
|
|
{'O', K_ALT_O, K_CTRL_O, 0}, /* 79 */
|
|
{'P', K_ALT_P, K_CTRL_P, 0}, /* 80 */
|
|
{'Q', K_ALT_Q, K_CTRL_Q, 0}, /* 81 */
|
|
{'R', K_ALT_R, K_CTRL_R, 0}, /* 82 */
|
|
{'S', K_ALT_S, K_CTRL_S, 0}, /* 83 */
|
|
{'T', K_ALT_T, K_CTRL_T, 0}, /* 84 */
|
|
{'U', K_ALT_U, K_CTRL_U, 0}, /* 85 */
|
|
{'V', K_ALT_V, K_CTRL_V, 0}, /* 86 */
|
|
{'W', K_ALT_W, K_CTRL_W, 0}, /* 87 */
|
|
{'X', K_ALT_X, K_CTRL_X, 0}, /* 88 */
|
|
{'Y', K_ALT_Y, K_CTRL_Y, 0}, /* 89 */
|
|
{'Z', K_ALT_Z, K_CTRL_Z, 0}, /* 90 */
|
|
{'[', 282, 27, 0}, /* 91 */
|
|
{'\\', 299, 28, 0}, /* 92 */
|
|
{']', 283, 29, 0}, /* 93 */
|
|
{'^', K_ALT_6, 30, 0}, /* 94 */
|
|
{'_', 386, 31, 0}, /* 95 */
|
|
{'`', 297, 297, 0}, /* 96 */
|
|
{'a', K_ALT_A, K_CTRL_A, 0}, /* 97 */
|
|
{'b', K_ALT_B, K_CTRL_B, 0}, /* 98 */
|
|
{'c', K_ALT_C, K_CTRL_C, 0}, /* 99 */
|
|
{'d', K_ALT_D, K_CTRL_D, 0}, /* 100 */
|
|
{'e', K_ALT_E, K_CTRL_E, 0}, /* 101 */
|
|
{'f', K_ALT_F, K_CTRL_F, 0}, /* 102 */
|
|
{'g', K_ALT_G, K_CTRL_G, 0}, /* 103 */
|
|
{'h', K_ALT_H, K_CTRL_H, 0}, /* 104 */
|
|
{'i', K_ALT_I, K_CTRL_I, 0}, /* 105 */
|
|
{'j', K_ALT_J, K_CTRL_J, 0}, /* 106 */
|
|
{'k', K_ALT_K, K_CTRL_K, 0}, /* 107 */
|
|
{'l', K_ALT_L, K_CTRL_L, 0}, /* 108 */
|
|
{'m', K_ALT_M, K_CTRL_M, 0}, /* 109 */
|
|
{'n', K_ALT_N, K_CTRL_N, 0}, /* 110 */
|
|
{'o', K_ALT_O, K_CTRL_O, 0}, /* 111 */
|
|
{'p', K_ALT_P, K_CTRL_P, 0}, /* 112 */
|
|
{'q', K_ALT_Q, K_CTRL_Q, 0}, /* 113 */
|
|
{'r', K_ALT_R, K_CTRL_R, 0}, /* 114 */
|
|
{'s', K_ALT_S, K_CTRL_S, 0}, /* 115 */
|
|
{'t', K_ALT_T, K_CTRL_T, 0}, /* 116 */
|
|
{'u', K_ALT_U, K_CTRL_U, 0}, /* 117 */
|
|
{'v', K_ALT_V, K_CTRL_V, 0}, /* 118 */
|
|
{'w', K_ALT_W, K_CTRL_W, 0}, /* 119 */
|
|
{'x', K_ALT_X, K_CTRL_X, 0}, /* 120 */
|
|
{'y', K_ALT_Y, K_CTRL_Y, 0}, /* 121 */
|
|
{'z', K_ALT_Z, K_CTRL_Z, 0}, /* 122 */
|
|
{'{', 282, 27, 0}, /* 123 */
|
|
{'|', 299, 28, 0}, /* 124 */
|
|
{'}', 283, 29, 0}, /* 125 */
|
|
{'~', 297, 297, 0}, /* 126 */
|
|
{K_CTRL_BS, K_ALT_BS, 127, 0} /* 127 */
|
|
};
|
|
|
|
static const ClipKeyCode extdKeyTab[NO_EXTDKEYS] = {
|
|
{K_F1, K_ALT_F1, K_CTRL_F1, K_SH_F1}, /* 00 */
|
|
{K_F2, K_ALT_F2, K_CTRL_F2, K_SH_F2}, /* 01 */
|
|
{K_F3, K_ALT_F3, K_CTRL_F3, K_SH_F3}, /* 02 */
|
|
{K_F4, K_ALT_F4, K_CTRL_F4, K_SH_F4}, /* 03 */
|
|
{K_F5, K_ALT_F5, K_CTRL_F5, K_SH_F5}, /* 04 */
|
|
{K_F6, K_ALT_F6, K_CTRL_F6, K_SH_F6}, /* 05 */
|
|
{K_F7, K_ALT_F7, K_CTRL_F7, K_SH_F7}, /* 06 */
|
|
{K_F8, K_ALT_F8, K_CTRL_F8, K_SH_F8}, /* 07 */
|
|
{K_F9, K_ALT_F9, K_CTRL_F9, K_SH_F9}, /* 08 */
|
|
{K_F10, K_ALT_F10, K_CTRL_F10, K_SH_F10}, /* 09 */
|
|
{K_F11, K_ALT_F11, K_CTRL_F11, K_SH_F11}, /* 10 */
|
|
{K_F12, K_ALT_F12, K_CTRL_F12, K_SH_F12}, /* 11 */
|
|
|
|
{K_UP, K_ALT_UP, K_CTRL_UP, K_SH_UP}, /* 12 */
|
|
{K_DOWN, K_ALT_DOWN, K_CTRL_DOWN, K_SH_DOWN}, /* 13 */
|
|
{K_LEFT, K_ALT_LEFT, K_CTRL_LEFT, K_SH_LEFT}, /* 14 */
|
|
{K_RIGHT, K_ALT_RIGHT, K_CTRL_RIGHT,K_SH_RIGHT}, /* 15 */
|
|
{K_INS, K_ALT_INS, K_CTRL_INS, K_SH_INS}, /* 16 */
|
|
{K_DEL, K_ALT_DEL, K_CTRL_DEL, K_SH_DEL}, /* 17 */
|
|
{K_HOME, K_ALT_HOME, K_CTRL_HOME, K_SH_HOME}, /* 18 */
|
|
{K_END, K_ALT_END, K_CTRL_END, K_SH_END}, /* 19 */
|
|
{K_PGUP, K_ALT_PGUP, K_CTRL_PGUP, K_SH_PGUP}, /* 20 */
|
|
{K_PGDN, K_ALT_PGDN, K_CTRL_PGDN, K_SH_PGDN}, /* 21 */
|
|
|
|
{K_BS, K_ALT_BS, 127, K_SH_BS}, /* 22 */
|
|
{K_TAB, K_ALT_TAB, K_CTRL_TAB, K_SH_TAB}, /* 23 */
|
|
{K_ESC, K_ALT_ESC, K_ESC, 0}, /* 24 */
|
|
|
|
{K_ENTER, K_ALT_ENTER, K_CTRL_ENTER,K_SH_ENTER}, /* 25 */
|
|
|
|
{K_ENTER, KP_ALT_ENTER, K_CTRL_ENTER, 0}, /* 26 */
|
|
{KP_CENTER, 0, KP_CTRL_5, 0}, /* 27 */
|
|
{K_PRTSCR, 0, K_CTRL_PRTSCR, 0}, /* 28 */
|
|
{K_PAUSE, 0, 0, 0} /* 29 */
|
|
};
|
|
|
|
|
|
static int getClipKey( int nKey )
|
|
{
|
|
int nRet = 0, nFlag = 0, n;
|
|
|
|
if ( IS_CLIPKEY( nKey ) )
|
|
nRet = GET_CLIPKEY( nKey );
|
|
else
|
|
{
|
|
nFlag = GET_KEYMASK( nKey );
|
|
nKey = CLR_KEYMASK( nKey );
|
|
if ( nFlag & KEY_EXTDMASK )
|
|
{
|
|
if ( nKey >= 0 && nKey < NO_EXTDKEYS )
|
|
{
|
|
if ( ( nFlag & KEY_ALTMASK ) && ( nFlag & KEY_CTRLMASK ) &&
|
|
extdKeyTab[nKey].shift_key != 0 )
|
|
nRet = extdKeyTab[nKey].shift_key;
|
|
else if ( ( nFlag & KEY_ALTMASK ) && extdKeyTab[nKey].alt_key != 0 )
|
|
nRet = extdKeyTab[nKey].alt_key;
|
|
else if ( ( nFlag & KEY_CTRLMASK )
|
|
&& extdKeyTab[nKey].ctrl_key != 0 )
|
|
nRet = extdKeyTab[nKey].ctrl_key;
|
|
else
|
|
nRet = extdKeyTab[nKey].key;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( nKey > 0 && nKey < 32 )
|
|
{
|
|
nFlag |= KEY_CTRLMASK;
|
|
nKey += ( 'A' - 1 );
|
|
}
|
|
n = nKey - 32;
|
|
if ( n >= 0 && n < NO_STDKEYS )
|
|
{
|
|
if ( ( nFlag & KEY_ALTMASK ) && ( nFlag & KEY_CTRLMASK ) &&
|
|
stdKeyTab[n].shift_key != 0 )
|
|
nRet = stdKeyTab[n].shift_key;
|
|
else if ( ( nFlag & KEY_ALTMASK ) && stdKeyTab[n].alt_key != 0 )
|
|
nRet = stdKeyTab[n].alt_key;
|
|
else if ( ( nFlag & KEY_CTRLMASK ) && stdKeyTab[n].ctrl_key != 0 )
|
|
nRet = stdKeyTab[n].ctrl_key;
|
|
else
|
|
nRet = stdKeyTab[n].key;
|
|
}
|
|
else
|
|
nRet = nKey;
|
|
|
|
}
|
|
}
|
|
|
|
return nRet;
|
|
}
|
|
|
|
static void set_sig_handler( int iSig )
|
|
{
|
|
struct sigaction act;
|
|
|
|
sigaction( iSig, 0, &act );
|
|
act.sa_handler = sig_handler;
|
|
act.sa_flags = SA_RESTART | ( iSig == SIGCHLD ? SA_NOCLDSTOP : 0 );
|
|
sigaction( iSig, &act, 0 );
|
|
}
|
|
|
|
#if 1
|
|
static void sig_handler( int signo )
|
|
{
|
|
int e = errno, stat;
|
|
pid_t pid;
|
|
|
|
if ( signo < MAX_SIGNO )
|
|
{
|
|
s_SignalTable[signo] = TRUE;
|
|
s_SignalFlag = TRUE;
|
|
}
|
|
|
|
switch ( signo )
|
|
{
|
|
case SIGCHLD:
|
|
while ( ( pid = waitpid( -1, &stat, WNOHANG ) ) > 0 ) ;
|
|
break;
|
|
case SIGWINCH:
|
|
s_WinSizeChangeFlag = TRUE;
|
|
break;
|
|
case SIGINT:
|
|
s_InetrruptFlag = TRUE;
|
|
break;
|
|
case SIGQUIT:
|
|
s_BreakFlag = TRUE;
|
|
break;
|
|
case SIGTSTP:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
errno = e;
|
|
return;
|
|
}
|
|
|
|
static void set_signals( void )
|
|
{
|
|
int i, sigs[] = { SIGINT, SIGQUIT, SIGTSTP, SIGWINCH, SIGCHLD, 0 };
|
|
|
|
s_SignalFlag = FALSE;
|
|
for ( i = 1; i < MAX_SIGNO; ++i )
|
|
{
|
|
s_SignalTable[i] = FALSE;
|
|
}
|
|
|
|
/* Ignore SIGPIPEs so they don't kill us. */
|
|
signal( SIGPIPE, SIG_IGN );
|
|
|
|
for ( i = 0; sigs[i]; ++i )
|
|
{
|
|
set_sig_handler( sigs[i] );
|
|
}
|
|
}
|
|
|
|
#else
|
|
static void sig_handler( int signo )
|
|
{
|
|
int e = errno, stat;
|
|
char *pszSig;
|
|
pid_t pid;
|
|
|
|
switch ( signo )
|
|
{
|
|
case SIGCHLD:
|
|
pszSig = "SIGCHLD";
|
|
while ( ( pid = waitpid( -1, &stat, WNOHANG ) ) > 0 ) ;
|
|
break;
|
|
case SIGWINCH:
|
|
pszSig = "SIGWINCH";
|
|
break;
|
|
case SIGPIPE:
|
|
pszSig = "SIGPIPE";
|
|
break;
|
|
case SIGTERM:
|
|
pszSig = "SIGTERM";
|
|
break;
|
|
case SIGINT:
|
|
pszSig = "SIGINT";
|
|
break;
|
|
case SIGQUIT:
|
|
pszSig = "SIGQUIT";
|
|
break;
|
|
case SIGCONT:
|
|
pszSig = "SIGCONT";
|
|
break;
|
|
case SIGTSTP:
|
|
pszSig = "SIGTSTP";
|
|
break;
|
|
case SIGTTOU:
|
|
pszSig = "SIGTTOU";
|
|
break;
|
|
default:
|
|
pszSig = "other signal";
|
|
break;
|
|
}
|
|
|
|
printf( "\nreceived signal: %d -> %s\n", signo, pszSig );
|
|
fflush( stdout );
|
|
|
|
errno = e;
|
|
return;
|
|
}
|
|
|
|
static void set_signals( void )
|
|
{
|
|
int i;
|
|
|
|
s_SignalFlag = FALSE;
|
|
for ( i = 1; i < MAX_SIGNO; ++i )
|
|
{
|
|
s_SignalTable[i] = FALSE;
|
|
set_sig_handler( i );
|
|
}
|
|
}
|
|
#endif
|
|
|
|
static int add_efds( InOutBase * ioBase, int fd, int mode,
|
|
int ( *eventFunc ) ( int, int, void * ), void *data )
|
|
{
|
|
struct evtFD *pefd = NULL;
|
|
int i, fl;
|
|
|
|
if ( eventFunc == NULL && mode != O_RDONLY )
|
|
return -1;
|
|
|
|
if ( ( fl = fcntl( fd, F_GETFL, 0 ) ) == -1 )
|
|
return -1;
|
|
|
|
fl &= O_ACCMODE;
|
|
if ( ( fl == O_RDONLY && mode == O_WRONLY ) ||
|
|
( fl == O_WRONLY && mode == O_RDONLY ) )
|
|
return -1;
|
|
|
|
for ( i = 0; i < ioBase->efds_no && !pefd; i++ )
|
|
if ( ioBase->event_fds[i]->fd == fd )
|
|
pefd = ioBase->event_fds[i];
|
|
|
|
if ( pefd )
|
|
{
|
|
pefd->mode = mode;
|
|
pefd->data = data;
|
|
pefd->eventFunc = eventFunc;
|
|
pefd->status = EVTFDSTAT_RUN;
|
|
}
|
|
else
|
|
{
|
|
if ( ioBase->efds_size <= ioBase->efds_no )
|
|
{
|
|
if ( ioBase->event_fds == NULL )
|
|
ioBase->event_fds = ( evtFD ** )
|
|
hb_xgrab( ( ioBase->efds_size += 10 ) * sizeof( evtFD * ) );
|
|
else
|
|
ioBase->event_fds = ( evtFD ** )
|
|
hb_xrealloc( ioBase->event_fds,
|
|
( ioBase->efds_size += 10 ) * sizeof( evtFD * ) );
|
|
}
|
|
|
|
pefd = ( evtFD * ) hb_xgrab( sizeof( evtFD ) );
|
|
pefd->fd = fd;
|
|
pefd->mode = mode;
|
|
pefd->data = data;
|
|
pefd->eventFunc = eventFunc;
|
|
pefd->status = EVTFDSTAT_RUN;
|
|
ioBase->event_fds[ioBase->efds_no++] = pefd;
|
|
}
|
|
|
|
return fd;
|
|
}
|
|
|
|
static void del_efds( InOutBase * ioBase, int fd )
|
|
{
|
|
int i, n = -1;
|
|
|
|
for ( i = 0; i < ioBase->efds_no && n == -1; i++ )
|
|
if ( ioBase->event_fds[i]->fd == fd )
|
|
n = i;
|
|
|
|
if ( n != -1 )
|
|
{
|
|
hb_xfree( ioBase->event_fds[n] );
|
|
ioBase->efds_no--;
|
|
for ( i = n; i < ioBase->efds_no; i++ )
|
|
ioBase->event_fds[i] = ioBase->event_fds[i + 1];
|
|
}
|
|
}
|
|
|
|
static void del_all_efds( InOutBase * ioBase )
|
|
{
|
|
int i;
|
|
|
|
if ( ioBase->event_fds != NULL )
|
|
{
|
|
for ( i = 0; i < ioBase->efds_no; i++ )
|
|
hb_xfree( ioBase->event_fds[i] );
|
|
|
|
hb_xfree( ioBase->event_fds );
|
|
|
|
ioBase->event_fds = NULL;
|
|
ioBase->efds_no = ioBase->efds_size = 0;
|
|
}
|
|
}
|
|
|
|
static int get_inch( InOutBase * ioBase, int milisec )
|
|
{
|
|
int nRet = 0, npfd = -1, nchk = ioBase->efds_no, lRead = 0;
|
|
int mode, i, n, counter;
|
|
struct timeval tv, *ptv;
|
|
struct evtFD *pefd = NULL;
|
|
fd_set rfds, wfds;
|
|
|
|
if ( milisec == 0 )
|
|
ptv = NULL;
|
|
else
|
|
{
|
|
if ( milisec < 0 )
|
|
milisec = 0;
|
|
tv.tv_sec = ( milisec / 1000 );
|
|
tv.tv_usec = ( milisec % 1000 ) * 1000;
|
|
ptv = &tv;
|
|
}
|
|
|
|
while ( nRet == 0 && lRead == 0 )
|
|
{
|
|
n = -1;
|
|
FD_ZERO( &rfds );
|
|
FD_ZERO( &wfds );
|
|
for ( i = 0; i < ioBase->efds_no; i++ )
|
|
{
|
|
if ( ioBase->event_fds[i]->status == EVTFDSTAT_RUN )
|
|
{
|
|
if ( ioBase->event_fds[i]->mode == O_RDWR
|
|
|| ioBase->event_fds[i]->mode == O_RDONLY )
|
|
{
|
|
FD_SET( ioBase->event_fds[i]->fd, &rfds );
|
|
if ( n < ioBase->event_fds[i]->fd )
|
|
n = ioBase->event_fds[i]->fd;
|
|
}
|
|
if ( ioBase->event_fds[i]->mode == O_RDWR
|
|
|| ioBase->event_fds[i]->mode == O_WRONLY )
|
|
{
|
|
FD_SET( ioBase->event_fds[i]->fd, &wfds );
|
|
if ( n < ioBase->event_fds[i]->fd )
|
|
n = ioBase->event_fds[i]->fd;
|
|
}
|
|
}
|
|
}
|
|
|
|
counter = ioBase->key_counter;
|
|
if ( select( n + 1, &rfds, &wfds, NULL, ptv ) > 0 )
|
|
{
|
|
for ( i = 0; i < ioBase->efds_no; i++ )
|
|
{
|
|
n = ( FD_ISSET( ioBase->event_fds[i]->fd, &rfds ) ? 1 : 0 ) |
|
|
( FD_ISSET( ioBase->event_fds[i]->fd, &wfds ) ? 2 : 0 );
|
|
if ( n != 0 )
|
|
{
|
|
if ( ioBase->event_fds[i]->eventFunc == NULL )
|
|
{
|
|
lRead = 1;
|
|
if ( STDIN_BUFLEN > ioBase->stdin_inbuf )
|
|
{
|
|
unsigned char buf[STDIN_BUFLEN];
|
|
|
|
n = read( ioBase->event_fds[i]->fd, buf,
|
|
STDIN_BUFLEN - ioBase->stdin_inbuf );
|
|
if ( n == 0 )
|
|
ioBase->event_fds[i]->status = EVTFDSTAT_STOP;
|
|
else
|
|
for ( i = 0; i < n; i++ )
|
|
{
|
|
ioBase->stdin_buf[ioBase->stdin_ptr_r++] = buf[i];
|
|
if ( ioBase->stdin_ptr_r == STDIN_BUFLEN )
|
|
ioBase->stdin_ptr_r = 0;
|
|
ioBase->stdin_inbuf++;
|
|
}
|
|
}
|
|
}
|
|
else if ( nRet == 0 && counter == ioBase->key_counter )
|
|
{
|
|
if ( n == 3 )
|
|
mode = O_RDWR;
|
|
else if ( n == 2 )
|
|
mode = O_WRONLY;
|
|
else
|
|
mode = O_RDONLY;
|
|
ioBase->event_fds[i]->status = EVTFDSTAT_STOP;
|
|
n = ( ioBase->event_fds[i]->eventFunc ) ( ioBase->
|
|
event_fds[i]->fd,
|
|
mode,
|
|
ioBase->
|
|
event_fds[i]->
|
|
data );
|
|
if ( IS_EVTFDSTAT( n ) )
|
|
{
|
|
ioBase->event_fds[i]->status = n;
|
|
if ( nchk > i )
|
|
nchk = i;
|
|
}
|
|
else
|
|
{
|
|
ioBase->event_fds[i]->status = EVTFDSTAT_RUN;
|
|
if ( IS_CLIPKEY( n ) )
|
|
{
|
|
nRet = n;
|
|
npfd = ioBase->event_fds[i]->fd;
|
|
if ( nchk > i )
|
|
nchk = i;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
lRead = 1;
|
|
}
|
|
|
|
for ( i = n = nchk; i < ioBase->efds_no; i++ )
|
|
{
|
|
if ( ioBase->event_fds[i]->status == EVTFDSTAT_DEL )
|
|
hb_xfree( ioBase->event_fds[i] );
|
|
else if ( ioBase->event_fds[i]->fd == npfd )
|
|
pefd = ioBase->event_fds[i];
|
|
else
|
|
{
|
|
if ( i > n )
|
|
ioBase->event_fds[n] = ioBase->event_fds[i];
|
|
n++;
|
|
}
|
|
}
|
|
if ( pefd )
|
|
ioBase->event_fds[n++] = pefd;
|
|
ioBase->efds_no = n;
|
|
|
|
return nRet;
|
|
}
|
|
|
|
static int test_bufch( InOutBase * ioBase, int n, int delay )
|
|
{
|
|
int nKey = 0;
|
|
|
|
if ( ioBase->stdin_inbuf == n )
|
|
nKey = get_inch( ioBase, delay );
|
|
|
|
return IS_CLIPKEY( nKey ) ? nKey :
|
|
( ioBase->stdin_inbuf > n ) ?
|
|
ioBase->stdin_buf[( ioBase->stdin_ptr_l + n ) % STDIN_BUFLEN] : -1;
|
|
}
|
|
|
|
static void free_bufch( InOutBase * ioBase, int n )
|
|
{
|
|
if ( n > ioBase->stdin_inbuf )
|
|
n = ioBase->stdin_inbuf;
|
|
ioBase->stdin_ptr_l = ( ioBase->stdin_ptr_l + n ) % STDIN_BUFLEN;
|
|
ioBase->stdin_inbuf -= n;
|
|
}
|
|
|
|
static int wait_key( InOutBase * ioBase, int milisec )
|
|
{
|
|
int nKey, esc, n, i, ch, counter;
|
|
struct keyTab *ptr;
|
|
|
|
if ( s_WinSizeChangeFlag )
|
|
{
|
|
s_WinSizeChangeFlag = FALSE;
|
|
return K_RESIZE;
|
|
}
|
|
|
|
counter = ++( ioBase->key_counter );
|
|
restart:
|
|
nKey = esc = n = i = 0;
|
|
again:
|
|
if ( ( nKey = getMouseKey( &ioBase->mLastEvt ) ) != 0 )
|
|
return nKey;
|
|
|
|
ch = test_bufch( ioBase, i,
|
|
ioBase->nTermMouseChars ? ioBase->esc_delay : milisec );
|
|
if ( counter != ioBase->key_counter )
|
|
goto restart;
|
|
|
|
if ( ch >= 0 && ch <= 255 )
|
|
{
|
|
++i;
|
|
if ( ioBase->nTermMouseChars )
|
|
{
|
|
ioBase->cTermMouseBuf[3 - ioBase->nTermMouseChars] = ch;
|
|
free_bufch( ioBase, i );
|
|
i = 0;
|
|
if ( --ioBase->nTermMouseChars == 0 )
|
|
set_tmevt( ioBase->cTermMouseBuf, &ioBase->mLastEvt );
|
|
goto again;
|
|
}
|
|
|
|
nKey = ch;
|
|
ptr = ioBase->pKeyTab;
|
|
if ( i == 1 && nKey == K_ESC && esc == 0 )
|
|
esc = 1;
|
|
while ( ch >= 0 && ch <= 255 && ptr != NULL )
|
|
{
|
|
if ( ptr->ch == ch )
|
|
{
|
|
if ( ptr->key != K_UNDEF )
|
|
{
|
|
nKey = ptr->key;
|
|
switch ( nKey )
|
|
{
|
|
case K_METAALT:
|
|
ioBase->key_flag |= KEY_ALTMASK;
|
|
break;
|
|
case K_METACTRL:
|
|
ioBase->key_flag |= KEY_CTRLMASK;
|
|
break;
|
|
case K_NATIONAL:
|
|
ioBase->nation_mode = !ioBase->nation_mode;
|
|
break;
|
|
case K_MOUSETERM:
|
|
ioBase->nTermMouseChars = 3;
|
|
break;
|
|
default:
|
|
n = i;
|
|
}
|
|
if ( n != i )
|
|
{
|
|
free_bufch( ioBase, i );
|
|
i = n = nKey = 0;
|
|
if ( esc == 2 )
|
|
break;
|
|
esc = 0;
|
|
goto again;
|
|
}
|
|
}
|
|
ptr = ptr->nextCh;
|
|
if ( ptr )
|
|
if ( ( ch = test_bufch( ioBase, i, ioBase->esc_delay ) ) != -1 )
|
|
++i;
|
|
if ( counter != ioBase->key_counter )
|
|
goto restart;
|
|
}
|
|
else
|
|
ptr = ptr->otherCh;
|
|
}
|
|
}
|
|
if ( ch == -1 && ioBase->nTermMouseChars )
|
|
ioBase->nTermMouseChars = 0;
|
|
|
|
if ( ch != -1 && IS_CLIPKEY( ch ) )
|
|
nKey = GET_CLIPKEY( ch );
|
|
else
|
|
{
|
|
if ( esc == 1 && n == 0 && ( ch != -1 || i >= 2 ) )
|
|
{
|
|
nKey = 0;
|
|
esc = 2;
|
|
i = n = 1;
|
|
goto again;
|
|
}
|
|
if ( esc == 2 )
|
|
{
|
|
if ( nKey != 0 )
|
|
ioBase->key_flag |= KEY_ALTMASK;
|
|
else
|
|
nKey = K_ESC;
|
|
if ( n == 1 && i > 1 )
|
|
n = 2;
|
|
}
|
|
else if ( n == 0 && i > 0 )
|
|
n = 1;
|
|
|
|
if ( n > 0 )
|
|
free_bufch( ioBase, n );
|
|
|
|
if ( ioBase->key_flag != 0 && nKey != 0 )
|
|
{
|
|
nKey |= ioBase->key_flag;
|
|
ioBase->key_flag = 0;
|
|
}
|
|
|
|
if ( ioBase->nation_transtbl && ioBase->nation_mode &&
|
|
nKey >= 32 && nKey < 128 && ioBase->nation_transtbl[nKey] )
|
|
nKey = ioBase->nation_transtbl[nKey];
|
|
if ( ioBase->in_transtbl && nKey >= 0 && nKey <= 255
|
|
&& ioBase->in_transtbl[nKey] )
|
|
nKey = ioBase->in_transtbl[nKey];
|
|
|
|
if ( nKey )
|
|
nKey = getClipKey( nKey );
|
|
}
|
|
|
|
return nKey;
|
|
}
|
|
|
|
static void write_ttyseq( InOutBase * ioBase, char *seq )
|
|
{
|
|
if ( ioBase->baseout != NULL )
|
|
{
|
|
fwrite( seq, strlen( seq ), 1, ioBase->baseout );
|
|
fflush( ioBase->baseout );
|
|
}
|
|
else
|
|
write( ioBase->base_outfd, seq, strlen( seq ) );
|
|
}
|
|
|
|
static int addKeyMap( InOutBase * ioBase, int nKey, const char *cdesc )
|
|
{
|
|
int ret = K_UNDEF, i = 0, c;
|
|
struct keyTab **ptr;
|
|
|
|
if ( cdesc == NULL )
|
|
return ret;
|
|
|
|
c = ( unsigned char ) cdesc[i++];
|
|
ptr = &ioBase->pKeyTab;
|
|
|
|
while ( c )
|
|
{
|
|
if ( *ptr == NULL )
|
|
{
|
|
*ptr = ( struct keyTab * ) hb_xgrab( sizeof( struct keyTab ) );
|
|
( *ptr )->ch = c;
|
|
( *ptr )->key = K_UNDEF;
|
|
( *ptr )->nextCh = NULL;
|
|
( *ptr )->otherCh = NULL;
|
|
}
|
|
if ( ( *ptr )->ch == c )
|
|
{
|
|
c = ( unsigned char ) cdesc[i++];
|
|
if ( c )
|
|
ptr = &( ( *ptr )->nextCh );
|
|
else
|
|
{
|
|
ret = ( *ptr )->key;
|
|
( *ptr )->key = nKey;
|
|
}
|
|
}
|
|
else
|
|
ptr = &( ( *ptr )->otherCh );
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static int removeKeyMap( InOutBase * ioBase, const char *cdesc )
|
|
{
|
|
int ret = K_UNDEF, i = 0, c;
|
|
struct keyTab **ptr;
|
|
|
|
c = ( unsigned char ) cdesc[i++];
|
|
ptr = &ioBase->pKeyTab;
|
|
|
|
while ( c && *ptr != NULL )
|
|
{
|
|
if ( ( *ptr )->ch == c )
|
|
{
|
|
c = ( unsigned char ) cdesc[i++];
|
|
if ( !c )
|
|
{
|
|
ret = ( *ptr )->key;
|
|
( *ptr )->key = K_UNDEF;
|
|
if ( ( *ptr )->nextCh == NULL && ( *ptr )->otherCh == NULL )
|
|
{
|
|
hb_xfree( *ptr );
|
|
*ptr = NULL;
|
|
}
|
|
}
|
|
else
|
|
ptr = &( ( *ptr )->nextCh );
|
|
}
|
|
else
|
|
ptr = &( ( *ptr )->otherCh );
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static void removeAllKeyMap( struct keyTab **ptr )
|
|
{
|
|
if ( ( *ptr )->nextCh != NULL )
|
|
removeAllKeyMap( &( ( *ptr )->nextCh ) );
|
|
if ( ( *ptr )->otherCh != NULL )
|
|
removeAllKeyMap( &( ( *ptr )->otherCh ) );
|
|
|
|
hb_xfree( *ptr );
|
|
*ptr = NULL;
|
|
}
|
|
|
|
static int getMouseKey( mouseEvent * mEvt )
|
|
{
|
|
int nKey = 0;
|
|
|
|
if ( mEvt->lbuttons != mEvt->buttonstate )
|
|
{
|
|
if ( mEvt->buttonstate & M_CURSOR_MOVE )
|
|
{
|
|
nKey = K_MOUSEMOVE;
|
|
mEvt->buttonstate &= ~M_CURSOR_MOVE;
|
|
}
|
|
else if ( mEvt->buttonstate & M_BUTTON_WHEELUP )
|
|
{
|
|
nKey = K_MWFORWARD;
|
|
mEvt->buttonstate &= ~M_BUTTON_WHEELUP;
|
|
}
|
|
else if ( mEvt->buttonstate & M_BUTTON_WHEELDOWN )
|
|
{
|
|
nKey = K_MWBACKWARD;
|
|
mEvt->buttonstate &= ~M_BUTTON_WHEELDOWN;
|
|
}
|
|
else
|
|
{
|
|
int butt = mEvt->lbuttons ^ mEvt->buttonstate;
|
|
|
|
if ( butt & M_BUTTON_LEFT )
|
|
{
|
|
if ( mEvt->buttonstate & M_BUTTON_LEFT )
|
|
{
|
|
mEvt->lbdn_row = mEvt->row;
|
|
mEvt->lbdn_col = mEvt->col;
|
|
}
|
|
else
|
|
{
|
|
mEvt->lbup_row = mEvt->row;
|
|
mEvt->lbup_col = mEvt->col;
|
|
}
|
|
nKey = ( mEvt->buttonstate & M_BUTTON_LEFT ) ?
|
|
( ( mEvt->buttonstate & M_BUTTON_LDBLCK ) ? K_LDBLCLK :
|
|
K_LBUTTONDOWN ) : K_LBUTTONUP;
|
|
mEvt->lbuttons ^= M_BUTTON_LEFT;
|
|
mEvt->buttonstate &= ~M_BUTTON_LDBLCK;
|
|
}
|
|
else if ( butt & M_BUTTON_RIGHT )
|
|
{
|
|
if ( mEvt->buttonstate & M_BUTTON_RIGHT )
|
|
{
|
|
mEvt->rbdn_row = mEvt->row;
|
|
mEvt->rbdn_col = mEvt->col;
|
|
}
|
|
else
|
|
{
|
|
mEvt->rbup_row = mEvt->row;
|
|
mEvt->rbup_col = mEvt->col;
|
|
}
|
|
nKey = ( mEvt->buttonstate & M_BUTTON_RIGHT ) ?
|
|
( ( mEvt->buttonstate & M_BUTTON_RDBLCK ) ? K_RDBLCLK :
|
|
K_RBUTTONDOWN ) : K_RBUTTONUP;
|
|
mEvt->lbuttons ^= M_BUTTON_RIGHT;
|
|
mEvt->buttonstate &= ~M_BUTTON_RDBLCK;
|
|
}
|
|
else if ( butt & M_BUTTON_MIDDLE )
|
|
{
|
|
if ( mEvt->buttonstate & M_BUTTON_MIDDLE )
|
|
{
|
|
mEvt->mbdn_row = mEvt->row;
|
|
mEvt->mbdn_col = mEvt->col;
|
|
}
|
|
else
|
|
{
|
|
mEvt->mbup_row = mEvt->row;
|
|
mEvt->mbup_col = mEvt->col;
|
|
}
|
|
nKey = ( mEvt->buttonstate & M_BUTTON_MIDDLE ) ?
|
|
( ( mEvt->buttonstate & M_BUTTON_MDBLCK ) ? K_MDBLCLK :
|
|
K_MBUTTONDOWN ) : K_MBUTTONUP;
|
|
mEvt->lbuttons ^= M_BUTTON_MIDDLE;
|
|
mEvt->buttonstate &= ~M_BUTTON_MDBLCK;
|
|
}
|
|
else
|
|
mEvt->lbuttons = mEvt->buttonstate;
|
|
}
|
|
}
|
|
|
|
return nKey;
|
|
}
|
|
|
|
static void chk_mevtdblck( mouseEvent * mEvt )
|
|
{
|
|
int newbuttons = ( mEvt->buttonstate & ~mEvt->lbuttons ) & M_BUTTON_KEYMASK;
|
|
|
|
if ( newbuttons != 0 )
|
|
{
|
|
struct timeval tv;
|
|
|
|
TIMEVAL_GET( tv );
|
|
if ( newbuttons & M_BUTTON_LEFT )
|
|
{
|
|
if ( TIMEVAL_LESS( tv, mEvt->BL_time ) )
|
|
mEvt->buttonstate |= M_BUTTON_LDBLCK;
|
|
TIMEVAL_ADD( mEvt->BL_time, tv, mEvt->click_delay );
|
|
}
|
|
if ( newbuttons & M_BUTTON_MIDDLE )
|
|
{
|
|
if ( TIMEVAL_LESS( tv, mEvt->BM_time ) )
|
|
mEvt->buttonstate |= M_BUTTON_MDBLCK;
|
|
TIMEVAL_ADD( mEvt->BM_time, tv, mEvt->click_delay );
|
|
}
|
|
if ( newbuttons & M_BUTTON_RIGHT )
|
|
{
|
|
if ( TIMEVAL_LESS( tv, mEvt->BR_time ) )
|
|
mEvt->buttonstate |= M_BUTTON_RDBLCK;
|
|
TIMEVAL_ADD( mEvt->BR_time, tv, mEvt->click_delay );
|
|
}
|
|
}
|
|
}
|
|
|
|
static void set_tmevt( unsigned char *cMBuf, mouseEvent * mEvt )
|
|
{
|
|
int row, col;
|
|
|
|
col = cMBuf[1] - 33;
|
|
row = cMBuf[2] - 33;
|
|
if( mEvt->row != row || mEvt->col != col )
|
|
{
|
|
mEvt->buttonstate |= M_CURSOR_MOVE;
|
|
mEvt->row = row;
|
|
mEvt->col = col;
|
|
}
|
|
|
|
switch ( cMBuf[0] & 0xC3 )
|
|
{
|
|
case 0x0:
|
|
mEvt->buttonstate |= M_BUTTON_LEFT;
|
|
break;
|
|
case 0x1:
|
|
mEvt->buttonstate |= M_BUTTON_MIDDLE;
|
|
break;
|
|
case 0x2:
|
|
mEvt->buttonstate |= M_BUTTON_RIGHT;
|
|
break;
|
|
case 0x3:
|
|
mEvt->buttonstate &= ~(M_BUTTON_KEYMASK|M_BUTTON_DBLMASK);
|
|
break;
|
|
case 0x40:
|
|
mEvt->buttonstate |= M_BUTTON_WHEELUP;
|
|
break;
|
|
case 0x41:
|
|
mEvt->buttonstate |= M_BUTTON_WHEELDOWN;
|
|
break;
|
|
}
|
|
chk_mevtdblck( mEvt );
|
|
/* printf("\n\rmouse event: %02x, %02x, %02x\n\r", cMBuf[0], cMBuf[1], cMBuf[2]); */
|
|
return;
|
|
}
|
|
|
|
#ifdef HAVE_GPM_H
|
|
static int set_gpmevt( int fd, int mode, void *data )
|
|
{
|
|
int nKey = 0;
|
|
mouseEvent *mEvt;
|
|
Gpm_Event gEvt;
|
|
|
|
HB_SYMBOL_UNUSED( fd );
|
|
HB_SYMBOL_UNUSED( mode );
|
|
|
|
mEvt = ( mouseEvent * ) data;
|
|
|
|
if ( Gpm_GetEvent( &gEvt ) > 0 )
|
|
{
|
|
mEvt->row = gEvt.y;
|
|
mEvt->col = gEvt.x;
|
|
if ( gEvt.type & GPM_MOVE )
|
|
mEvt->buttonstate |= M_CURSOR_MOVE;
|
|
if ( gEvt.type & GPM_DOWN )
|
|
{
|
|
if ( gEvt.buttons & GPM_B_LEFT )
|
|
mEvt->buttonstate |= M_BUTTON_LEFT;
|
|
if ( gEvt.buttons & GPM_B_MIDDLE )
|
|
mEvt->buttonstate |= M_BUTTON_MIDDLE;
|
|
if ( gEvt.buttons & GPM_B_RIGHT )
|
|
mEvt->buttonstate |= M_BUTTON_RIGHT;
|
|
}
|
|
else if ( gEvt.type & GPM_UP )
|
|
{
|
|
if ( gEvt.buttons & GPM_B_LEFT )
|
|
mEvt->buttonstate &= ~M_BUTTON_LEFT;
|
|
if ( gEvt.buttons & GPM_B_MIDDLE )
|
|
mEvt->buttonstate &= ~M_BUTTON_MIDDLE;
|
|
if ( gEvt.buttons & GPM_B_RIGHT )
|
|
mEvt->buttonstate &= ~M_BUTTON_RIGHT;
|
|
}
|
|
}
|
|
chk_mevtdblck( mEvt );
|
|
nKey = getMouseKey( mEvt );
|
|
|
|
return ( nKey ? SET_CLIPKEY( nKey ) : 0 );
|
|
}
|
|
|
|
static void flush_gpmevt( mouseEvent * mEvt )
|
|
{
|
|
if ( gpm_fd >= 0 )
|
|
{
|
|
struct timeval tv = { 0, 0 };
|
|
fd_set rfds;
|
|
|
|
FD_ZERO( &rfds );
|
|
FD_SET( gpm_fd, &rfds );
|
|
|
|
while ( select( gpm_fd + 1, &rfds, NULL, NULL, &tv ) > 0 )
|
|
set_gpmevt( gpm_fd, O_RDONLY, ( void * ) mEvt );
|
|
|
|
while ( getMouseKey( mEvt ) ) ;
|
|
}
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
static void disp_mousecursor( InOutBase * ioBase )
|
|
{
|
|
#ifdef HAVE_GPM_H
|
|
if ( ioBase->mouse_type == MOUSE_GPM && gpm_visiblepointer )
|
|
{
|
|
Gpm_DrawPointer( ioBase->mLastEvt.col, ioBase->mLastEvt.row,
|
|
gpm_consolefd );
|
|
}
|
|
#else
|
|
HB_SYMBOL_UNUSED( ioBase );
|
|
#endif
|
|
}
|
|
|
|
static void mouse_init( InOutBase * ioBase )
|
|
{
|
|
if ( ioBase->terminal_type == TERM_XTERM )
|
|
{
|
|
/* save old hilit tracking & enable mouse tracking */
|
|
write_ttyseq( ioBase, "\033[?1001s\033[?1002h" );
|
|
ioBase->mouse_type = MOUSE_XTERM;
|
|
memset( ( void * ) &ioBase->mLastEvt, 0, sizeof( ioBase->mLastEvt ) );
|
|
ioBase->mLastEvt.click_delay = DBLCLK_DELAY;
|
|
/* curses mouse buttons check */
|
|
ioBase->mButtons = tigetnum( "btns" );
|
|
if ( ioBase->mButtons < 1 )
|
|
ioBase->mButtons = 3;
|
|
}
|
|
#ifdef HAVE_GPM_H
|
|
else if ( ioBase->terminal_type == TERM_LINUX )
|
|
{
|
|
ioBase->Conn.eventMask =
|
|
GPM_MOVE | GPM_DRAG | GPM_UP | GPM_DOWN | GPM_DOUBLE;
|
|
/* give me move events but handle them anyway */
|
|
ioBase->Conn.defaultMask = GPM_MOVE | GPM_HARD;
|
|
/* only pure mouse events, no Ctrl,Alt,Shft events */
|
|
ioBase->Conn.minMod = ioBase->Conn.maxMod = 0;
|
|
gpm_zerobased = 1;
|
|
gpm_visiblepointer = 0;
|
|
if ( Gpm_Open( &ioBase->Conn, 0 ) >= 0 && gpm_fd >= 0 )
|
|
{
|
|
int flags;
|
|
|
|
if ( ( flags = fcntl( gpm_fd, F_GETFL, 0 ) ) != -1 )
|
|
fcntl( gpm_fd, F_SETFL, flags | O_NONBLOCK );
|
|
|
|
ioBase->mouse_type = MOUSE_GPM;
|
|
memset( ( void * ) &ioBase->mLastEvt, 0, sizeof( ioBase->mLastEvt ) );
|
|
ioBase->mLastEvt.click_delay = DBLCLK_DELAY;
|
|
flush_gpmevt( &ioBase->mLastEvt );
|
|
add_efds( ioBase, gpm_fd, O_RDONLY, set_gpmevt,
|
|
( void * ) &ioBase->mLastEvt );
|
|
|
|
/*
|
|
* In recent GPM versions it produce unpleasure noice on the screen
|
|
* so I covered it with this macro, [druzus]
|
|
*/
|
|
#ifdef HB_GPM_USE_XTRA
|
|
ioBase->mButtons = Gpm_GetSnapshot( NULL );
|
|
#else
|
|
ioBase->mButtons = 3;
|
|
#endif
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static void mouse_exit( InOutBase * ioBase )
|
|
{
|
|
if ( ioBase->mouse_type == MOUSE_XTERM )
|
|
{
|
|
/* disable mouse tracking & restore old hilit tracking */
|
|
write_ttyseq( ioBase, "\033[?1002l\033[?1001r" );
|
|
}
|
|
#ifdef HAVE_GPM_H
|
|
else if ( ioBase->mouse_type == MOUSE_GPM && gpm_fd >= 0 )
|
|
{
|
|
del_efds( ioBase, gpm_fd );
|
|
Gpm_Close();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static void disp_cursor( InOutBase * ioBase )
|
|
{
|
|
if ( ioBase->cursor != ioBase->lcursor )
|
|
{
|
|
int lcurs = -1;
|
|
char escseq[64], *cv = NULL;
|
|
|
|
switch ( ioBase->cursor )
|
|
{
|
|
case SC_NONE:
|
|
lcurs = 1;
|
|
cv = ioBase->civis;
|
|
break;
|
|
case SC_NORMAL:
|
|
lcurs = 2;
|
|
cv = ioBase->cnorm;
|
|
break;
|
|
case SC_INSERT:
|
|
lcurs = 4;
|
|
cv = ioBase->cvvis;
|
|
break;
|
|
case SC_SPECIAL1:
|
|
lcurs = 8;
|
|
cv = ioBase->cvvis;
|
|
break;
|
|
case SC_SPECIAL2:
|
|
/* TODO: find a proper sequqnce to set a cursor
|
|
to SC_SPECIAL2 under Linux console?
|
|
There is no such mode in current stable kernels (2.4.20)
|
|
*/
|
|
lcurs = 4;
|
|
cv = ioBase->cvvis;
|
|
break;
|
|
}
|
|
|
|
if ( lcurs != -1 )
|
|
{
|
|
if ( ioBase->terminal_type == TERM_LINUX )
|
|
{
|
|
snprintf( escseq, sizeof( escseq ) - 1, "\033[?25%c\033[?%hdc",
|
|
ioBase->cursor == SC_NONE ? 'l' : 'h', lcurs );
|
|
escseq[sizeof( escseq ) - 1] = '\0';
|
|
write_ttyseq( ioBase, escseq );
|
|
}
|
|
else if ( cv != NULL )
|
|
/* curses cursor shape set */
|
|
/* curs_set( ncurs ); */
|
|
write_ttyseq( ioBase, cv );
|
|
|
|
}
|
|
|
|
ioBase->lcursor = ioBase->cursor;
|
|
}
|
|
}
|
|
|
|
static void set_cursor( InOutBase * ioBase, int style )
|
|
{
|
|
switch ( style )
|
|
{
|
|
case SC_NONE:
|
|
case SC_NORMAL:
|
|
case SC_INSERT:
|
|
case SC_SPECIAL1:
|
|
case SC_SPECIAL2:
|
|
ioBase->cursor = style;
|
|
disp_cursor( ioBase );
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void gt_refresh( InOutBase * ioBase )
|
|
{
|
|
if ( ioBase->disp_count == 0 )
|
|
{
|
|
/*
|
|
if (ioBase->cursor == SC_NONE)
|
|
leaveok( ioBase->stdscr, TRUE );
|
|
else
|
|
leaveok( ioBase->stdscr, FALSE );
|
|
*/
|
|
/* if (ioBase->cursor != SC_NONE) */
|
|
wmove( ioBase->stdscr, ioBase->row, ioBase->col );
|
|
wrefresh( ioBase->stdscr );
|
|
disp_cursor( ioBase );
|
|
disp_mousecursor( ioBase );
|
|
}
|
|
}
|
|
|
|
static void gt_ttyset( InOutBase * ioBase )
|
|
{
|
|
if ( isatty( ioBase->base_infd ) )
|
|
tcsetattr( ioBase->base_infd, TCSANOW, &ioBase->curr_TIO );
|
|
}
|
|
|
|
static void gt_ttyrestore( InOutBase * ioBase )
|
|
{
|
|
if ( ioBase->lTIOsaved )
|
|
tcsetattr( ioBase->base_infd, TCSANOW, &ioBase->saved_TIO );
|
|
}
|
|
|
|
static void gt_outstr( InOutBase * ioBase, int fd, const unsigned char *str,
|
|
int len )
|
|
{
|
|
unsigned char *buf, c;
|
|
int i;
|
|
|
|
if ( ioBase->out_transtbl != NULL )
|
|
{
|
|
buf = ( unsigned char * ) hb_xgrab( len );
|
|
for ( i = 0; i < len; ++i )
|
|
{
|
|
c = str[i];
|
|
if ( c != 9 && c != 10 && c != 13 && ioBase->out_transtbl[c] )
|
|
buf[i] = ioBase->out_transtbl[c];
|
|
else
|
|
buf[i] = c;
|
|
}
|
|
write( fd, buf, len );
|
|
hb_xfree( buf );
|
|
}
|
|
else
|
|
write( fd, str, len );
|
|
}
|
|
|
|
static void gt_outstd( InOutBase * ioBase, unsigned const char *str, int len )
|
|
{
|
|
gt_outstr( ioBase, ioBase->stdoutfd, str, len );
|
|
}
|
|
|
|
static void gt_outerr( InOutBase * ioBase, const char *str, int len )
|
|
{
|
|
gt_outstr( ioBase, ioBase->stderrfd, ( unsigned char * ) str, len );
|
|
}
|
|
|
|
static char *tiGetS( char *capname )
|
|
{
|
|
char *ptr;
|
|
|
|
ptr = tigetstr( capname );
|
|
if ( ptr )
|
|
{
|
|
if ( ptr == ( char * ) -1 )
|
|
ptr = NULL;
|
|
else if ( !ptr[0] )
|
|
ptr = NULL;
|
|
}
|
|
return ptr;
|
|
}
|
|
|
|
static void get_acsc( InOutBase * ioBase, unsigned char c, chtype * pch )
|
|
{
|
|
unsigned char *ptr;
|
|
|
|
if ( ioBase->acsc != NULL )
|
|
for ( ptr = ( unsigned char * ) ioBase->acsc; *ptr && *( ptr + 1 ); ptr += 2 )
|
|
if ( *ptr == c )
|
|
{
|
|
*pch = *( ptr + 1 ) | A_ALTCHARSET;
|
|
return;
|
|
}
|
|
|
|
switch ( c )
|
|
{
|
|
case '.':
|
|
*pch = 'v' | A_NORMAL;
|
|
break;
|
|
case ',':
|
|
*pch = '<' | A_NORMAL;
|
|
break;
|
|
case '+':
|
|
*pch = '>' | A_NORMAL;
|
|
break;
|
|
case '-':
|
|
*pch = '^' | A_NORMAL;
|
|
break;
|
|
case 'a':
|
|
*pch = '#' | A_NORMAL;
|
|
break;
|
|
case '0':
|
|
case 'h':
|
|
get_acsc( ioBase, 'a', pch );
|
|
break;
|
|
default:
|
|
*pch = c | A_ALTCHARSET;
|
|
}
|
|
}
|
|
|
|
static void init_keys(InOutBase *ioBase)
|
|
{
|
|
/* virual CTRL/ALT sequences */
|
|
addKeyMap( ioBase, K_METACTRL, CTRL_SEQ );
|
|
addKeyMap( ioBase, K_METAALT, ALT_SEQ );
|
|
/* national mode key sequences */
|
|
#ifdef NATION_SEQ
|
|
addKeyMap( ioBase, K_NATIONAL, NATION_SEQ );
|
|
#endif
|
|
|
|
/* some harcoded sequences */
|
|
/* addKeyMap( ioBase, K_ESC, "\033\033" ); */
|
|
addKeyMap( ioBase, EXKEY_ENTER, "\r" );
|
|
addKeyMap( ioBase, K_MOUSETERM, "\033[M" );
|
|
|
|
if( ioBase->terminal_type == TERM_XTERM ) {
|
|
|
|
addKeyMap( ioBase, EXKEY_UP , "\033[A" );
|
|
addKeyMap( ioBase, EXKEY_DOWN , "\033[B" );
|
|
addKeyMap( ioBase, EXKEY_RIGHT , "\033[C" );
|
|
addKeyMap( ioBase, EXKEY_LEFT , "\033[D" );
|
|
addKeyMap( ioBase, EXKEY_CENTER, "\033[E" );
|
|
addKeyMap( ioBase, EXKEY_END , "\033[F" );
|
|
addKeyMap( ioBase, EXKEY_HOME , "\033[H" );
|
|
addKeyMap( ioBase, EXKEY_HOME , "\033[1~" );
|
|
addKeyMap( ioBase, EXKEY_END , "\033[4~" );
|
|
addKeyMap( ioBase, EXKEY_BS , "\177" );
|
|
|
|
addKeyMap( ioBase, EXKEY_F1 , "\033[11~" );
|
|
addKeyMap( ioBase, EXKEY_F2 , "\033[12~" );
|
|
addKeyMap( ioBase, EXKEY_F3 , "\033[13~" );
|
|
addKeyMap( ioBase, EXKEY_F4 , "\033[14~" );
|
|
addKeyMap( ioBase, EXKEY_F5 , "\033[15~" );
|
|
|
|
addKeyMap( ioBase, EXKEY_UP |KEY_CTRLMASK, "\033[5A" );
|
|
addKeyMap( ioBase, EXKEY_DOWN |KEY_CTRLMASK, "\033[5B" );
|
|
addKeyMap( ioBase, EXKEY_RIGHT |KEY_CTRLMASK, "\033[5C" );
|
|
addKeyMap( ioBase, EXKEY_LEFT |KEY_CTRLMASK, "\033[5D" );
|
|
addKeyMap( ioBase, EXKEY_CENTER|KEY_CTRLMASK, "\033[5E" );
|
|
addKeyMap( ioBase, EXKEY_END |KEY_CTRLMASK, "\033[5F" );
|
|
addKeyMap( ioBase, EXKEY_HOME |KEY_CTRLMASK, "\033[5H" );
|
|
addKeyMap( ioBase, EXKEY_INS |KEY_CTRLMASK, "\033[2;5~" );
|
|
addKeyMap( ioBase, EXKEY_PGUP |KEY_CTRLMASK, "\033[5;5~" );
|
|
addKeyMap( ioBase, EXKEY_PGDN |KEY_CTRLMASK, "\033[6;5~" );
|
|
|
|
addKeyMap( ioBase, EXKEY_F1 |KEY_CTRLMASK|KEY_ALTMASK, "\033O2P" );
|
|
addKeyMap( ioBase, EXKEY_F2 |KEY_CTRLMASK|KEY_ALTMASK, "\033O2Q" );
|
|
addKeyMap( ioBase, EXKEY_F3 |KEY_CTRLMASK|KEY_ALTMASK, "\033O2R" );
|
|
addKeyMap( ioBase, EXKEY_F4 |KEY_CTRLMASK|KEY_ALTMASK, "\033O2S" );
|
|
addKeyMap( ioBase, EXKEY_F5 |KEY_CTRLMASK|KEY_ALTMASK, "\033[15;2~" );
|
|
addKeyMap( ioBase, EXKEY_F6 |KEY_CTRLMASK|KEY_ALTMASK, "\033[17;2~" );
|
|
addKeyMap( ioBase, EXKEY_F7 |KEY_CTRLMASK|KEY_ALTMASK, "\033[18;2~" );
|
|
addKeyMap( ioBase, EXKEY_F8 |KEY_CTRLMASK|KEY_ALTMASK, "\033[19;2~" );
|
|
addKeyMap( ioBase, EXKEY_F9 |KEY_CTRLMASK|KEY_ALTMASK, "\033[20;2~" );
|
|
addKeyMap( ioBase, EXKEY_F10 |KEY_CTRLMASK|KEY_ALTMASK, "\033[21;2~" );
|
|
addKeyMap( ioBase, EXKEY_F11 |KEY_CTRLMASK|KEY_ALTMASK, "\033[23;2~" );
|
|
addKeyMap( ioBase, EXKEY_F12 |KEY_CTRLMASK|KEY_ALTMASK, "\033[24;2~" );
|
|
|
|
addKeyMap( ioBase, EXKEY_TAB |KEY_CTRLMASK|KEY_ALTMASK, "\033[Z" );
|
|
|
|
/* key added for gnome-terminal and teraterm */
|
|
|
|
addKeyMap( ioBase, EXKEY_ENTER |KEY_CTRLMASK, "\033[7;5~" );
|
|
addKeyMap( ioBase, EXKEY_DEL |KEY_CTRLMASK, "\033[3;5~" );
|
|
addKeyMap( ioBase, EXKEY_TAB |KEY_CTRLMASK, "\033[8;5~" );
|
|
|
|
addKeyMap( ioBase, EXKEY_UP |KEY_CTRLMASK|KEY_ALTMASK, "\033[6A" );
|
|
addKeyMap( ioBase, EXKEY_DOWN |KEY_CTRLMASK|KEY_ALTMASK, "\033[6B" );
|
|
addKeyMap( ioBase, EXKEY_RIGHT |KEY_CTRLMASK|KEY_ALTMASK, "\033[6C" );
|
|
addKeyMap( ioBase, EXKEY_LEFT |KEY_CTRLMASK|KEY_ALTMASK, "\033[6D" );
|
|
addKeyMap( ioBase, EXKEY_CENTER|KEY_CTRLMASK|KEY_ALTMASK, "\033[6E" );
|
|
addKeyMap( ioBase, EXKEY_END |KEY_CTRLMASK|KEY_ALTMASK, "\033[6F" );
|
|
addKeyMap( ioBase, EXKEY_HOME |KEY_CTRLMASK|KEY_ALTMASK, "\033[6H" );
|
|
addKeyMap( ioBase, EXKEY_ENTER |KEY_CTRLMASK|KEY_ALTMASK, "\033[7;6~" );
|
|
addKeyMap( ioBase, EXKEY_INS |KEY_CTRLMASK|KEY_ALTMASK, "\033[2;6~" );
|
|
addKeyMap( ioBase, EXKEY_DEL |KEY_CTRLMASK|KEY_ALTMASK, "\033[3;6~" );
|
|
addKeyMap( ioBase, EXKEY_PGUP |KEY_CTRLMASK|KEY_ALTMASK, "\033[5;6~" );
|
|
addKeyMap( ioBase, EXKEY_PGDN |KEY_CTRLMASK|KEY_ALTMASK, "\033[6;6~" );
|
|
|
|
addKeyMap( ioBase, EXKEY_BS |KEY_CTRLMASK|KEY_ALTMASK, "\033[W" );
|
|
|
|
/* end of added */
|
|
|
|
} else if( ioBase->terminal_type == TERM_LINUX ) {
|
|
|
|
addKeyMap( ioBase, EXKEY_F1 , "\033[[A" ); /* kf1 */
|
|
addKeyMap( ioBase, EXKEY_F2 , "\033[[B" ); /* kf2 */
|
|
addKeyMap( ioBase, EXKEY_F3 , "\033[[C" ); /* kf3 */
|
|
addKeyMap( ioBase, EXKEY_F4 , "\033[[D" ); /* kf4 */
|
|
addKeyMap( ioBase, EXKEY_F5 , "\033[[E" ); /* kf5 */
|
|
addKeyMap( ioBase, EXKEY_F6 , "\033[17~" ); /* kf6 */
|
|
addKeyMap( ioBase, EXKEY_F7 , "\033[18~" ); /* kf7 */
|
|
addKeyMap( ioBase, EXKEY_F8 , "\033[19~" ); /* kf8 */
|
|
addKeyMap( ioBase, EXKEY_F9 , "\033[20~" ); /* kf9 */
|
|
addKeyMap( ioBase, EXKEY_F10, "\033[21~" ); /* kf10 */
|
|
addKeyMap( ioBase, EXKEY_F11, "\033[23~" ); /* kf11 */
|
|
addKeyMap( ioBase, EXKEY_F12, "\033[24~" ); /* kf12 */
|
|
|
|
addKeyMap( ioBase, EXKEY_F1 |KEY_CTRLMASK|KEY_ALTMASK, "\033[25~" ); /* kf13 */
|
|
addKeyMap( ioBase, EXKEY_F2 |KEY_CTRLMASK|KEY_ALTMASK, "\033[26~" ); /* kf14 */
|
|
addKeyMap( ioBase, EXKEY_F3 |KEY_CTRLMASK|KEY_ALTMASK, "\033[28~" ); /* kf15 */
|
|
addKeyMap( ioBase, EXKEY_F4 |KEY_CTRLMASK|KEY_ALTMASK, "\033[29~" ); /* kf16 */
|
|
addKeyMap( ioBase, EXKEY_F5 |KEY_CTRLMASK|KEY_ALTMASK, "\033[31~" ); /* kf17 */
|
|
addKeyMap( ioBase, EXKEY_F6 |KEY_CTRLMASK|KEY_ALTMASK, "\033[32~" ); /* kf18 */
|
|
addKeyMap( ioBase, EXKEY_F7 |KEY_CTRLMASK|KEY_ALTMASK, "\033[33~" ); /* kf19 */
|
|
addKeyMap( ioBase, EXKEY_F8 |KEY_CTRLMASK|KEY_ALTMASK, "\033[34~" ); /* kf20 */
|
|
addKeyMap( ioBase, EXKEY_F9 |KEY_CTRLMASK|KEY_ALTMASK, "\033[35~" ); /* kf21 */
|
|
addKeyMap( ioBase, EXKEY_F10|KEY_CTRLMASK|KEY_ALTMASK, "\033[36~" ); /* kf22 */
|
|
addKeyMap( ioBase, EXKEY_F11|KEY_CTRLMASK|KEY_ALTMASK, "\033[37~" ); /* kf23 */
|
|
addKeyMap( ioBase, EXKEY_F12|KEY_CTRLMASK|KEY_ALTMASK, "\033[38~" ); /* kf24 */
|
|
|
|
addKeyMap( ioBase, EXKEY_F1 |KEY_CTRLMASK, "\033[39~" ); /* kf25 */
|
|
addKeyMap( ioBase, EXKEY_F2 |KEY_CTRLMASK, "\033[40~" ); /* kf26 */
|
|
addKeyMap( ioBase, EXKEY_F3 |KEY_CTRLMASK, "\033[41~" ); /* kf27 */
|
|
addKeyMap( ioBase, EXKEY_F4 |KEY_CTRLMASK, "\033[42~" ); /* kf28 */
|
|
addKeyMap( ioBase, EXKEY_F5 |KEY_CTRLMASK, "\033[43~" ); /* kf29 */
|
|
addKeyMap( ioBase, EXKEY_F6 |KEY_CTRLMASK, "\033[44~" ); /* kf30 */
|
|
addKeyMap( ioBase, EXKEY_F7 |KEY_CTRLMASK, "\033[45~" ); /* kf31 */
|
|
addKeyMap( ioBase, EXKEY_F8 |KEY_CTRLMASK, "\033[46~" ); /* kf32 */
|
|
addKeyMap( ioBase, EXKEY_F9 |KEY_CTRLMASK, "\033[47~" ); /* kf33 */
|
|
addKeyMap( ioBase, EXKEY_F10|KEY_CTRLMASK, "\033[48~" ); /* kf34 */
|
|
addKeyMap( ioBase, EXKEY_F11|KEY_CTRLMASK, "\033[49~" ); /* kf35 */
|
|
addKeyMap( ioBase, EXKEY_F12|KEY_CTRLMASK, "\033[50~" ); /* kf36 */
|
|
|
|
addKeyMap( ioBase, EXKEY_F1 |KEY_ALTMASK , "\033[51~" ); /* kf37 */
|
|
addKeyMap( ioBase, EXKEY_F2 |KEY_ALTMASK , "\033[52~" ); /* kf38 */
|
|
addKeyMap( ioBase, EXKEY_F3 |KEY_ALTMASK , "\033[53~" ); /* kf39 */
|
|
addKeyMap( ioBase, EXKEY_F4 |KEY_ALTMASK , "\033[54~" ); /* kf40 */
|
|
addKeyMap( ioBase, EXKEY_F5 |KEY_ALTMASK , "\033[55~" ); /* kf41 */
|
|
addKeyMap( ioBase, EXKEY_F6 |KEY_ALTMASK , "\033[56~" ); /* kf42 */
|
|
addKeyMap( ioBase, EXKEY_F7 |KEY_ALTMASK , "\033[57~" ); /* kf43 */
|
|
addKeyMap( ioBase, EXKEY_F8 |KEY_ALTMASK , "\033[58~" ); /* kf44 */
|
|
addKeyMap( ioBase, EXKEY_F9 |KEY_ALTMASK , "\033[59~" ); /* kf45 */
|
|
addKeyMap( ioBase, EXKEY_F10|KEY_ALTMASK , "\033[70~" ); /* kf46 */
|
|
addKeyMap( ioBase, EXKEY_F11|KEY_ALTMASK , "\033[71~" ); /* kf47 */
|
|
addKeyMap( ioBase, EXKEY_F12|KEY_ALTMASK , "\033[72~" ); /* kf48 */
|
|
}
|
|
|
|
|
|
/* (curses) termcap/terminfo sequences */
|
|
|
|
/* terminal mouse event */
|
|
addKeyMap( ioBase, K_MOUSETERM, "kmous" );
|
|
|
|
/* FlagShip extension */
|
|
addKeyMap( ioBase, EXKEY_HOME | KEY_CTRLMASK, tiGetS( "ked" ) );
|
|
addKeyMap( ioBase, EXKEY_END | KEY_CTRLMASK, tiGetS( "kel" ) );
|
|
addKeyMap( ioBase, EXKEY_PGUP | KEY_CTRLMASK, tiGetS( "kri" ) );
|
|
addKeyMap( ioBase, EXKEY_PGDN | KEY_CTRLMASK, tiGetS( "kind" ) );
|
|
addKeyMap( ioBase, EXKEY_RIGHT | KEY_CTRLMASK, tiGetS( "kctab" ) );
|
|
addKeyMap( ioBase, EXKEY_LEFT | KEY_CTRLMASK, tiGetS( "khts" ) );
|
|
|
|
/* some xterms extension */
|
|
addKeyMap( ioBase, EXKEY_HOME, tiGetS( "kfnd" ) );
|
|
addKeyMap( ioBase, EXKEY_END, tiGetS( "kslt" ) );
|
|
|
|
/* keypad */
|
|
addKeyMap( ioBase, EXKEY_CENTER, tiGetS( "kb2" ) );
|
|
addKeyMap( ioBase, EXKEY_HOME, tiGetS( "ka1" ) );
|
|
addKeyMap( ioBase, EXKEY_END, tiGetS( "kc1" ) );
|
|
addKeyMap( ioBase, EXKEY_PGUP, tiGetS( "ka3" ) );
|
|
addKeyMap( ioBase, EXKEY_PGDN, tiGetS( "kc3" ) );
|
|
|
|
/* other keys */
|
|
addKeyMap( ioBase, EXKEY_ENTER, tiGetS( "kent" ) );
|
|
addKeyMap( ioBase, EXKEY_END, tiGetS( "kend" ) );
|
|
addKeyMap( ioBase, EXKEY_PGUP, tiGetS( "kpp" ) );
|
|
addKeyMap( ioBase, EXKEY_PGDN, tiGetS( "knp" ) );
|
|
addKeyMap( ioBase, EXKEY_UP, tiGetS( "kcuu1" ) );
|
|
addKeyMap( ioBase, EXKEY_DOWN, tiGetS( "kcud1" ) );
|
|
addKeyMap( ioBase, EXKEY_RIGHT, tiGetS( "kcuf1" ) );
|
|
addKeyMap( ioBase, EXKEY_LEFT, tiGetS( "kcub1" ) );
|
|
addKeyMap( ioBase, EXKEY_HOME, tiGetS( "khome" ) );
|
|
addKeyMap( ioBase, EXKEY_INS, tiGetS( "kich1" ) );
|
|
addKeyMap( ioBase, EXKEY_DEL, tiGetS( "kdch1" ) );
|
|
addKeyMap( ioBase, EXKEY_TAB, tiGetS( "ht" ) );
|
|
addKeyMap( ioBase, EXKEY_BS, tiGetS( "kbs" ) );
|
|
addKeyMap( ioBase, EXKEY_TAB | KEY_ALTMASK, tiGetS( "kcbt" ) );
|
|
|
|
/* function keys */
|
|
addKeyMap( ioBase, EXKEY_F1, tiGetS( "kf1" ) );
|
|
addKeyMap( ioBase, EXKEY_F2, tiGetS( "kf2" ) );
|
|
addKeyMap( ioBase, EXKEY_F3, tiGetS( "kf3" ) );
|
|
addKeyMap( ioBase, EXKEY_F4, tiGetS( "kf4" ) );
|
|
addKeyMap( ioBase, EXKEY_F5, tiGetS( "kf5" ) );
|
|
addKeyMap( ioBase, EXKEY_F6, tiGetS( "kf6" ) );
|
|
addKeyMap( ioBase, EXKEY_F7, tiGetS( "kf7" ) );
|
|
addKeyMap( ioBase, EXKEY_F8, tiGetS( "kf8" ) );
|
|
addKeyMap( ioBase, EXKEY_F9, tiGetS( "kf9" ) );
|
|
addKeyMap( ioBase, EXKEY_F10, tiGetS( "kf10" ) );
|
|
addKeyMap( ioBase, EXKEY_F11, tiGetS( "kf11" ) );
|
|
addKeyMap( ioBase, EXKEY_F12, tiGetS( "kf12" ) );
|
|
|
|
/* shifted function keys */
|
|
addKeyMap( ioBase, EXKEY_F1 |KEY_CTRLMASK|KEY_ALTMASK, tiGetS( "kf13" ) );
|
|
addKeyMap( ioBase, EXKEY_F2 |KEY_CTRLMASK|KEY_ALTMASK, tiGetS( "kf14" ) );
|
|
addKeyMap( ioBase, EXKEY_F3 |KEY_CTRLMASK|KEY_ALTMASK, tiGetS( "kf15" ) );
|
|
addKeyMap( ioBase, EXKEY_F4 |KEY_CTRLMASK|KEY_ALTMASK, tiGetS( "kf16" ) );
|
|
addKeyMap( ioBase, EXKEY_F5 |KEY_CTRLMASK|KEY_ALTMASK, tiGetS( "kf17" ) );
|
|
addKeyMap( ioBase, EXKEY_F6 |KEY_CTRLMASK|KEY_ALTMASK, tiGetS( "kf18" ) );
|
|
addKeyMap( ioBase, EXKEY_F7 |KEY_CTRLMASK|KEY_ALTMASK, tiGetS( "kf19" ) );
|
|
addKeyMap( ioBase, EXKEY_F8 |KEY_CTRLMASK|KEY_ALTMASK, tiGetS( "kf20" ) );
|
|
addKeyMap( ioBase, EXKEY_F9 |KEY_CTRLMASK|KEY_ALTMASK, tiGetS( "kf21" ) );
|
|
addKeyMap( ioBase, EXKEY_F10|KEY_CTRLMASK|KEY_ALTMASK, tiGetS( "kf22" ) );
|
|
addKeyMap( ioBase, EXKEY_F11|KEY_CTRLMASK|KEY_ALTMASK, tiGetS( "kf23" ) );
|
|
addKeyMap( ioBase, EXKEY_F12|KEY_CTRLMASK|KEY_ALTMASK, tiGetS( "kf24" ) );
|
|
}
|
|
|
|
static void gt_tone( InOutBase * ioBase, double dFrequency, double dDuration )
|
|
{
|
|
char escseq[64];
|
|
|
|
if ( ioBase->terminal_type == TERM_LINUX && ioBase->beep != NULL )
|
|
{
|
|
snprintf( escseq, sizeof( escseq ) - 1, "\033[10;%hd]\033[11;%hd]%s",
|
|
( int ) dFrequency,
|
|
( int ) ( dDuration * 1000.0 / 18.2 ), ioBase->beep );
|
|
escseq[sizeof( escseq ) - 1] = '\0';
|
|
write_ttyseq( ioBase, escseq );
|
|
}
|
|
else
|
|
/* curses beep() */
|
|
if ( ioBase->beep != NULL )
|
|
write_ttyseq( ioBase, ioBase->beep );
|
|
else if ( ioBase->flash != NULL )
|
|
write_ttyseq( ioBase, ioBase->flash );
|
|
}
|
|
|
|
static void set_sig_keys( InOutBase * ioBase, int key_int, int key_brk,
|
|
int key_stp )
|
|
{
|
|
if ( isatty( ioBase->base_infd ) )
|
|
{
|
|
|
|
/* set SIGINT character, default ^C */
|
|
if ( key_int >= 0 && key_int <= 255 )
|
|
ioBase->curr_TIO.c_cc[VINTR] = key_int;
|
|
|
|
/* set SIGQUIT character, default ^D */
|
|
if ( key_brk >= 0 && key_brk <= 255 )
|
|
ioBase->curr_TIO.c_cc[VQUIT] = key_brk;
|
|
|
|
/* set SIGTSTP character, default ^Z */
|
|
if ( key_stp >= 0 && key_stp <= 255 )
|
|
ioBase->curr_TIO.c_cc[VSUSP] = key_stp;
|
|
|
|
/* enable siganls from terminal device */
|
|
if ( ioBase->curr_TIO.c_cc[VINTR] != 0 ||
|
|
ioBase->curr_TIO.c_cc[VQUIT] != 0 ||
|
|
ioBase->curr_TIO.c_cc[VSUSP] != 0 )
|
|
ioBase->curr_TIO.c_lflag |= ISIG;
|
|
|
|
/* ioctl( ioBase->base_infd, TIOCSCTTY, 0 ); */
|
|
gt_ttyset( ioBase );
|
|
}
|
|
}
|
|
|
|
static int gt_getsize( InOutBase * ioBase, int *rows, int *cols )
|
|
{
|
|
int ret = -1;
|
|
|
|
*rows = *cols = 0;
|
|
|
|
if ( isatty( ioBase->base_outfd ) )
|
|
{
|
|
struct winsize win;
|
|
|
|
if ( ioctl( ioBase->base_outfd, TIOCGWINSZ, ( char * ) &win ) != -1 )
|
|
{
|
|
*rows = win.ws_row;
|
|
*cols = win.ws_col;
|
|
}
|
|
}
|
|
if ( *rows <= 0 || *cols <= 0 )
|
|
{
|
|
char *env;
|
|
|
|
if ( ( env = getenv( "COLUMNS" ) ) )
|
|
*cols = atoi( env );
|
|
if ( ( env = getenv( "LINES" ) ) )
|
|
*rows = atoi( env );
|
|
}
|
|
if ( *rows > 0 && *cols > 0 )
|
|
ret = ( ioBase->maxrow == *rows && ioBase->maxcol == *cols ) ? 0 : 1;
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int gt_resize( InOutBase * ioBase )
|
|
{
|
|
int ret = -1;
|
|
int rows = 0, cols = 0;
|
|
|
|
if ( gt_getsize( ioBase, &rows, &cols ) >= 0 )
|
|
{
|
|
/*
|
|
#if defined(NCURSES_VERSION)
|
|
wresize( ioBase->stdscr, rows, cols );
|
|
#endif
|
|
*/
|
|
endwin();
|
|
gt_refresh( ioBase );
|
|
ret = 0;
|
|
/*
|
|
#if defined(NCURSES_VERSION)
|
|
if ( resize_term( rows, cols ) == OK ) {
|
|
ret = 0;
|
|
gt_refresh( ioBase );
|
|
}
|
|
#endif
|
|
*/
|
|
getmaxyx( ioBase->stdscr, ioBase->maxrow, ioBase->maxcol );
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static int gt_setsize( InOutBase * ioBase, int rows, int cols )
|
|
{
|
|
int ret = -1, r, c;
|
|
char escseq[64];
|
|
|
|
if ( ioBase->terminal_type == TERM_XTERM )
|
|
{
|
|
snprintf( escseq, sizeof( escseq ) - 1, "\033[8;%hd;%hdt", rows, cols );
|
|
escseq[sizeof( escseq ) - 1] = '\0';
|
|
write_ttyseq( ioBase, escseq );
|
|
/* dirty hack - wait for SIGWINCH */
|
|
if ( gt_getsize( ioBase, &r, &c ) > 0 )
|
|
sleep( 3 );
|
|
|
|
if ( s_WinSizeChangeFlag )
|
|
{
|
|
s_WinSizeChangeFlag = FALSE;
|
|
ret = gt_resize( ioBase );
|
|
}
|
|
else if ( isatty( ioBase->base_outfd ) )
|
|
{
|
|
struct winsize win;
|
|
|
|
if ( ioctl( ioBase->base_outfd, TIOCGWINSZ, ( char * ) &win ) != -1 )
|
|
{
|
|
win.ws_row = rows;
|
|
win.ws_col = cols;
|
|
ioctl( ioBase->base_outfd, TIOCSWINSZ, ( char * ) &win );
|
|
}
|
|
ret = gt_resize( ioBase );
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void setKeyTrans( InOutBase * ioBase, unsigned char *ksrc, unsigned char *kdst )
|
|
{
|
|
unsigned char c;
|
|
int n;
|
|
|
|
if ( ksrc && kdst )
|
|
{
|
|
if ( ioBase->in_transtbl == NULL )
|
|
ioBase->in_transtbl = ( unsigned char * ) hb_xgrab( 256 );
|
|
|
|
memset( ioBase->in_transtbl, 0, 256 );
|
|
|
|
for ( n = 0; n < 256 && ( c = ksrc[n] ); n++ )
|
|
ioBase->in_transtbl[c] = kdst[n];
|
|
|
|
}
|
|
else if ( ioBase->in_transtbl != NULL )
|
|
{
|
|
hb_xfree( ioBase->in_transtbl );
|
|
ioBase->in_transtbl = NULL;
|
|
}
|
|
}
|
|
|
|
static void setDispTrans( InOutBase * ioBase, char *src, char *dst, int box )
|
|
{
|
|
unsigned char c, d;
|
|
int i, aSet = 0;
|
|
chtype ch;
|
|
|
|
if ( src && dst )
|
|
aSet = 1;
|
|
|
|
for ( i = 0; i < 256; i++ )
|
|
{
|
|
ch = ioBase->charmap[i] & 0xffff;
|
|
switch ( ( ioBase->charmap[i] >> 16 ) & 0xff )
|
|
{
|
|
case 1:
|
|
ioBase->std_chmap[i] = ioBase->box_chmap[i] = A_NORMAL;
|
|
break;
|
|
case 2:
|
|
ioBase->std_chmap[i] = ioBase->box_chmap[i] = A_ALTCHARSET;
|
|
break;
|
|
case 3:
|
|
ioBase->std_chmap[i] = ioBase->box_chmap[i] = A_PROTECT;
|
|
break;
|
|
case 4:
|
|
ioBase->std_chmap[i] = ioBase->box_chmap[i] = A_ALTCHARSET | A_PROTECT;
|
|
break;
|
|
case 5:
|
|
get_acsc( ioBase, ch & 0xff, &ch );
|
|
ioBase->std_chmap[i] = ioBase->box_chmap[i] = ch & ~A_CHARTEXT;
|
|
ch &= A_CHARTEXT;
|
|
break;
|
|
case 0:
|
|
default:
|
|
ioBase->std_chmap[i] = aSet ? A_ALTCHARSET : A_NORMAL;
|
|
ioBase->box_chmap[i] = A_ALTCHARSET;
|
|
break;
|
|
}
|
|
ioBase->std_chmap[i] |= ch;
|
|
ioBase->box_chmap[i] |= ch;
|
|
|
|
if ( i != ( int ) ( ch & A_CHARTEXT ) &&
|
|
( ioBase->std_chmap[i] & A_ALTCHARSET ) == 0 )
|
|
{
|
|
if ( ioBase->out_transtbl == NULL )
|
|
{
|
|
ioBase->out_transtbl = ( unsigned char * ) hb_xgrab( 256 );
|
|
memset( ioBase->out_transtbl, 0, 256 );
|
|
}
|
|
ioBase->out_transtbl[i] = ch & A_CHARTEXT;
|
|
}
|
|
}
|
|
if ( aSet )
|
|
{
|
|
for( i = 0; i < 256 && ( c = ( unsigned char ) src[i] ); i++ )
|
|
{
|
|
d = ( unsigned char ) dst[i];
|
|
ioBase->std_chmap[c] = d | A_NORMAL;
|
|
if( box )
|
|
ioBase->box_chmap[c] = d | A_NORMAL;
|
|
if( c != d )
|
|
{
|
|
if( ioBase->out_transtbl == NULL )
|
|
{
|
|
ioBase->out_transtbl = ( unsigned char * )hb_xgrab( 256 );
|
|
memset( ioBase->out_transtbl, 0, 256 );
|
|
}
|
|
ioBase->out_transtbl[c] = d;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static InOutBase *create_ioBase( char *term, int infd, int outfd, int errfd,
|
|
pid_t termpid )
|
|
{
|
|
InOutBase *ioBase;
|
|
int bg, fg;
|
|
unsigned int i, n;
|
|
char buf[256], *ptr, *crsterm = NULL;
|
|
|
|
ioBase = ( InOutBase * ) hb_xgrab( sizeof( InOutBase ) );
|
|
memset( ioBase, 0, sizeof( InOutBase ) );
|
|
|
|
if ( !term || !*term )
|
|
term = getenv( "HB_TERM" );
|
|
if ( !term || !*term )
|
|
term = getenv( "TERM" );
|
|
|
|
if ( term && *term )
|
|
{
|
|
if ( strncmp( term, "linux", 5 ) == 0 )
|
|
ioBase->terminal_type = TERM_LINUX;
|
|
else if ( strstr( term, "xterm" ) != NULL ||
|
|
strncmp( term, "rxvt", 4 ) == 0 ||
|
|
strstr( term, "putty" ) == 0 )
|
|
ioBase->terminal_type = TERM_XTERM;
|
|
|
|
if ( ( ptr = strchr( term, '/' ) ) != NULL )
|
|
{
|
|
if ( ( i = ptr - term ) >= sizeof( buf ) )
|
|
i = sizeof( buf ) - 1;
|
|
strncpy( buf, term, i );
|
|
buf[i] = '\0';
|
|
if ( i )
|
|
crsterm = buf;
|
|
}
|
|
else
|
|
crsterm = term;
|
|
}
|
|
|
|
ioBase->esc_delay = ESC_DELAY;
|
|
ioBase->base_infd = infd;
|
|
ioBase->base_outfd = outfd;
|
|
ioBase->stdoutfd = outfd;
|
|
ioBase->stderrfd = errfd;
|
|
ioBase->termpid = termpid;
|
|
ioBase->cursor = ioBase->lcursor = SC_UNDEF;
|
|
|
|
if ( !isatty( ioBase->base_outfd ) && isatty( ioBase->base_infd ) )
|
|
ioBase->base_outfd = ioBase->base_infd;
|
|
|
|
if ( isatty( ioBase->stdoutfd ) )
|
|
ioBase->stdoutfd = -1;
|
|
if ( isatty( ioBase->stderrfd ) )
|
|
ioBase->stderrfd = -1;
|
|
|
|
if ( isatty( ioBase->base_infd ) )
|
|
{
|
|
tcgetattr( ioBase->base_infd, &ioBase->curr_TIO ); /* save current terminal settings */
|
|
memcpy( &ioBase->saved_TIO, &ioBase->curr_TIO, sizeof( struct termios ) );
|
|
ioBase->lTIOsaved = 1;
|
|
|
|
ioBase->curr_TIO.c_lflag &= ~( ECHO | ECHONL | ICANON | ISIG | IEXTEN );
|
|
ioBase->curr_TIO.c_lflag |= NOFLSH;
|
|
ioBase->curr_TIO.c_cflag &= ~( CSIZE | PARENB );
|
|
ioBase->curr_TIO.c_cflag |= CS8 | CREAD;
|
|
ioBase->curr_TIO.c_iflag &= ~( IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON );
|
|
ioBase->curr_TIO.c_oflag &= ~OPOST;
|
|
/* ioBase->curr_TIO.c_oflag |= ONLCR | OPOST; */
|
|
|
|
memset( ioBase->curr_TIO.c_cc, 0, NCCS );
|
|
}
|
|
|
|
|
|
/* curses SCREEN initialisation */
|
|
if ( ioBase->base_infd == fileno( stdin ) )
|
|
ioBase->basein = stdin;
|
|
else
|
|
ioBase->basein = fdopen( dup( ioBase->base_infd ), "r" );
|
|
|
|
if ( ioBase->base_outfd == fileno( stdout ) )
|
|
ioBase->baseout = stdout;
|
|
else
|
|
ioBase->baseout = fdopen( dup( ioBase->base_outfd ), "w" );
|
|
|
|
|
|
/* curses screen initialization */
|
|
ioBase->basescr = newterm( crsterm, ioBase->baseout, ioBase->basein );
|
|
/*
|
|
def_shell_mode();
|
|
def_prog_mode();
|
|
*/
|
|
curs_wrkaround();
|
|
|
|
if ( ioBase->basescr == NULL )
|
|
{
|
|
destroy_ioBase( ioBase );
|
|
return NULL;
|
|
}
|
|
|
|
ioBase->stdscr = stdscr;
|
|
|
|
ioBase->flash = tiGetS( "flash" );
|
|
ioBase->beep = tiGetS( "bel" );
|
|
ioBase->civis = tiGetS( "civis" );
|
|
ioBase->cnorm = tiGetS( "cnorm" );
|
|
ioBase->cvvis = tiGetS( "cvvis" );
|
|
if ( ioBase->cvvis == NULL )
|
|
ioBase->cvvis = ioBase->cnorm;
|
|
ioBase->acsc = tiGetS( "acsc" );
|
|
|
|
ioBase->charmap = ( int * ) hb_xgrab( 256 * sizeof( int ) );
|
|
hb_gt_crs_chrmapinit( ioBase->charmap, term );
|
|
setDispTrans( ioBase, NULL, NULL, 0 );
|
|
|
|
ioBase->attr_mask = ( chtype ) -1;
|
|
if ( has_colors() )
|
|
{
|
|
/* DOS->CURSES color maping
|
|
DOS -> curses
|
|
--------------------------------
|
|
0 black -> COLOR_BLACK
|
|
1 blue -> COLOR_BLUE
|
|
2 green -> COLOR_GREEN
|
|
3 cyan -> COLOR_CYAN
|
|
4 red -> COLOR_RED
|
|
5 magenta -> COLOR_MAGENTA
|
|
6 yellow -> COLOR_YELLOW
|
|
7 light gray -> COLOR_WHITE
|
|
|
|
8 gray -> BOLD/BLINK BLACK
|
|
9 light blue -> BOLD/BLINK BLUE
|
|
10 light green -> BOLD/BLINK GREEN
|
|
11 light cyan -> BOLD/BLINK CYAN
|
|
12 light red -> BOLD/BLINK RED
|
|
13 light magenta -> BOLD/BLINK MAGENTA
|
|
14 light yellow -> BOLD/BLINK YELLOW
|
|
15 white -> BOLD/BLINK WHITE
|
|
*/
|
|
static const char color_map[] = { COLOR_BLACK,
|
|
COLOR_BLUE,
|
|
COLOR_GREEN,
|
|
COLOR_CYAN,
|
|
COLOR_RED,
|
|
COLOR_MAGENTA,
|
|
COLOR_YELLOW,
|
|
COLOR_WHITE
|
|
};
|
|
|
|
start_color();
|
|
/*
|
|
for( bg = 0; bg < COLORS; bg++ )
|
|
for( fg = 0; fg < COLORS; fg++ )
|
|
{
|
|
i = bg * COLORS + fg;
|
|
if( i == 0 )
|
|
i = 7;
|
|
else if( i == 7 )
|
|
i = 0;
|
|
init_pair( i, color_map[ fg ], color_map[ bg ] );
|
|
}
|
|
*/
|
|
for ( i = 0; i < 256; i++ )
|
|
{
|
|
bg = ( i >> 4 ) & 0x07; /* extract background color bits 4-6 */
|
|
fg = ( i & 0x07 ); /* extract forground color bits 0-2 */
|
|
n = bg * 8 + fg;
|
|
/* n = bg * COLORS + fg */
|
|
if ( n == 0 )
|
|
n = 7;
|
|
else if ( n == 7 )
|
|
n = 0;
|
|
if ( ( i & 0x88 ) == 0 )
|
|
init_pair( n, color_map[fg], color_map[bg] );
|
|
ioBase->attr_map[i] = COLOR_PAIR( n );
|
|
if ( i & 0x08 ) /* highlight forground bit 3 */
|
|
ioBase->attr_map[i] |= A_BOLD;
|
|
if ( i & 0x80 ) /* blink/highlight background bit 7 */
|
|
ioBase->attr_map[i] |= A_BLINK;
|
|
}
|
|
ioBase->is_color = 1;
|
|
}
|
|
else
|
|
{
|
|
for ( i = 0; i < 256; i++ )
|
|
{
|
|
bg = ( i >> 4 ) & 0x07; /* extract background color bits 4-6 */
|
|
fg = ( i & 0x07 ); /* extract forground color bits 0-2 */
|
|
ioBase->attr_map[i] = 0;
|
|
if ( fg < bg )
|
|
ioBase->attr_map[i] |= A_REVERSE;
|
|
if ( fg == 1 ) /* underline? */
|
|
ioBase->attr_map[i] |= A_UNDERLINE;
|
|
if ( i & 0x08 ) /* highlight forground bit 3 */
|
|
ioBase->attr_map[i] |= A_BOLD;
|
|
if ( i & 0x80 ) /* blink/highlight background bit 7 */
|
|
ioBase->attr_map[i] |= A_BLINK;
|
|
ioBase->is_color = 0;
|
|
}
|
|
}
|
|
|
|
getmaxyx( ioBase->stdscr, ioBase->maxrow, ioBase->maxcol );
|
|
scrollok( ioBase->stdscr, FALSE );
|
|
/*
|
|
idlok( ioBase->stdscr, FALSE );
|
|
idcok( ioBase->stdscr, FALSE );
|
|
leaveok( ioBase->stdscr, FALSE );
|
|
*/
|
|
/*
|
|
* curses keyboard initialization
|
|
* we have our own keyboard routine so it's unnecessary now
|
|
* but we call raw() to inform some versions of curses that
|
|
* there is no OPOST translation
|
|
*/
|
|
raw();
|
|
|
|
leaveok( ioBase->stdscr, FALSE );
|
|
curs_set( 0 );
|
|
|
|
/*
|
|
nonl();
|
|
nodelay( ioBase->stdscr, TRUE);
|
|
keypad( ioBase->stdscr, FALSE);
|
|
timeout( 0 );
|
|
noecho();
|
|
curs_set( 0 );
|
|
*/
|
|
wclear( ioBase->stdscr );
|
|
wrefresh( ioBase->stdscr );
|
|
|
|
gt_ttyset( ioBase );
|
|
add_efds( ioBase, ioBase->base_infd, O_RDONLY, NULL, NULL );
|
|
|
|
init_keys( ioBase );
|
|
mouse_init( ioBase );
|
|
|
|
return ioBase;
|
|
}
|
|
|
|
static void destroy_ioBase( InOutBase * ioBase )
|
|
{
|
|
mouse_exit( ioBase );
|
|
del_all_efds( ioBase );
|
|
|
|
if ( ioBase->terminal_type == TERM_LINUX )
|
|
{
|
|
/* restore a standard bell frequency and duration */
|
|
write_ttyseq( ioBase, "\033[10]\033[11]" );
|
|
}
|
|
|
|
/* curses SCREEN delete */
|
|
if ( ioBase->stdscr != NULL )
|
|
{
|
|
ioBase->disp_count = 0;
|
|
/* on exit restore a cursor share and leave it visible
|
|
Marek's NOTE: This is incompatible with Clipper */
|
|
if ( ioBase->cursor != SC_UNDEF )
|
|
set_cursor( ioBase, SC_NORMAL );
|
|
gt_refresh( ioBase );
|
|
endwin();
|
|
}
|
|
if ( ioBase->basescr != NULL )
|
|
delscreen( ioBase->basescr );
|
|
if ( ioBase->basein != NULL && ioBase->basein != stdin )
|
|
fclose( ioBase->basein );
|
|
if ( ioBase->baseout != NULL && ioBase->baseout != stdout )
|
|
fclose( ioBase->baseout );
|
|
|
|
/* free allocated memory */
|
|
if ( ioBase->charmap != NULL )
|
|
hb_xfree( ioBase->charmap );
|
|
|
|
if ( ioBase->in_transtbl != NULL )
|
|
hb_xfree( ioBase->in_transtbl );
|
|
|
|
if ( ioBase->out_transtbl != NULL )
|
|
hb_xfree( ioBase->out_transtbl );
|
|
|
|
if ( ioBase->nation_transtbl != NULL )
|
|
hb_xfree( ioBase->nation_transtbl );
|
|
|
|
if ( ioBase->pKeyTab != NULL )
|
|
removeAllKeyMap( &ioBase->pKeyTab );
|
|
|
|
/* restore terminal settings */
|
|
gt_ttyrestore( ioBase );
|
|
|
|
/* kill terminal proces if any */
|
|
if ( ioBase->termpid > 0 )
|
|
{
|
|
kill( ioBase->termpid, SIGTERM );
|
|
waitpid( ioBase->termpid, NULL, 0 );
|
|
}
|
|
|
|
hb_xfree( ioBase );
|
|
}
|
|
|
|
static InOutBase *create_newXterm( void )
|
|
{
|
|
#if defined( HB_OS_LINUX ) || defined( HB_OS_BSD )
|
|
#if 0
|
|
int masterfd, slavefd, fd;
|
|
pid_t termpid;
|
|
char ptyname[64], buf[64], *ptr;
|
|
|
|
if ( !getenv( "DISPLAY" ) )
|
|
return NULL;
|
|
|
|
if ( openpty( &masterfd, &slavefd, ptyname, NULL, NULL ) == -1 )
|
|
return NULL;
|
|
|
|
tcsetpgrp( masterfd, getpgrp() );
|
|
|
|
if ( ( termpid = fork() ) == -1 )
|
|
{
|
|
close( masterfd );
|
|
close( slavefd );
|
|
return NULL;
|
|
}
|
|
|
|
if ( termpid == 0 )
|
|
{
|
|
if ( ( ptr = strrchr( ptyname, '/' ) ) )
|
|
++ptr;
|
|
else
|
|
ptr = ptyname;
|
|
snprintf( buf, sizeof( buf ), "-S%s/%d", ptr, masterfd );
|
|
buf[sizeof( buf ) - 1] = '\0';
|
|
/*
|
|
close(0);
|
|
close(1);
|
|
close(2);
|
|
*/
|
|
/*
|
|
dup2(masterfd, 0);
|
|
dup2(masterfd, 1);
|
|
#if 0
|
|
fd = open("/tmp/hb-xterm.log", O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
|
|
#endif
|
|
fd = open("/dev/null", O_WRONLY);
|
|
dup2(fd, 2);
|
|
*/
|
|
for ( fd = 3; fd < MAXFD; ++fd )
|
|
if ( fd != masterfd )
|
|
close( fd );
|
|
|
|
setuid( getuid() );
|
|
setgid( getgid() );
|
|
execlp( "xterm", "xterm", buf, "+sb",
|
|
"-fg", "white",
|
|
"-bg", "black", "-fn", "fixed", "-T", "HB-XTERM Window", NULL );
|
|
exit( 0 );
|
|
}
|
|
close( masterfd );
|
|
return create_ioBase( "xterm", slavefd, slavefd, slavefd, termpid );
|
|
#endif
|
|
#endif
|
|
return NULL;
|
|
}
|
|
|
|
static int set_active_ioBase( int iNO_ioBase )
|
|
{
|
|
int iPrev = s_iActive_ioBase;
|
|
|
|
if ( iNO_ioBase >= 0 && iNO_ioBase < s_iSize_ioBaseTab )
|
|
{
|
|
s_iActive_ioBase = iNO_ioBase;
|
|
s_ioBase = s_ioBaseTab[s_iActive_ioBase];
|
|
set_term( s_ioBase->basescr );
|
|
}
|
|
|
|
return iPrev;
|
|
}
|
|
|
|
static int add_new_ioBase( InOutBase * ioBase )
|
|
{
|
|
int i, n, add = 0;
|
|
|
|
for ( i = 0; i < s_iSize_ioBaseTab && !add; ++i )
|
|
if ( !s_ioBaseTab[i] )
|
|
{
|
|
s_ioBaseTab[i] = ioBase;
|
|
add = 1;
|
|
}
|
|
|
|
if ( !add )
|
|
{
|
|
if ( s_ioBaseTab == NULL )
|
|
s_ioBaseTab = ( InOutBase ** ) hb_xgrab(
|
|
( s_iSize_ioBaseTab += 10 ) * sizeof( InOutBase * ) );
|
|
else
|
|
s_ioBaseTab = ( InOutBase ** ) hb_xrealloc( s_ioBaseTab,
|
|
( s_iSize_ioBaseTab += 10 ) * sizeof( InOutBase * ) );
|
|
s_ioBaseTab[i] = ioBase;
|
|
for ( n = i + 1; n < s_iSize_ioBaseTab; n++ )
|
|
s_ioBaseTab[n] = NULL;
|
|
}
|
|
|
|
if ( !s_ioBase )
|
|
set_active_ioBase( i );
|
|
|
|
return i;
|
|
}
|
|
|
|
static int del_ioBase( int iNO_ioBase )
|
|
{
|
|
int i;
|
|
|
|
if ( iNO_ioBase >= 0 && iNO_ioBase < s_iSize_ioBaseTab )
|
|
{
|
|
destroy_ioBase( s_ioBaseTab[iNO_ioBase] );
|
|
s_ioBaseTab[iNO_ioBase] = NULL;
|
|
if ( s_iActive_ioBase == iNO_ioBase )
|
|
{
|
|
s_iActive_ioBase = -1;
|
|
s_ioBase = NULL;
|
|
for ( i = 0; i < s_iSize_ioBaseTab && !s_ioBase; ++i )
|
|
if ( s_ioBaseTab[i] )
|
|
set_active_ioBase( i );
|
|
}
|
|
}
|
|
|
|
return s_iActive_ioBase;
|
|
}
|
|
|
|
static void del_all_ioBase( void )
|
|
{
|
|
int i;
|
|
|
|
if ( s_ioBaseTab )
|
|
{
|
|
for ( i = 0; i < s_iSize_ioBaseTab; ++i )
|
|
if ( s_ioBaseTab[i] )
|
|
destroy_ioBase( s_ioBaseTab[i] );
|
|
hb_xfree( s_ioBaseTab );
|
|
s_ioBaseTab = NULL;
|
|
}
|
|
s_iActive_ioBase = -1;
|
|
s_ioBase = NULL;
|
|
}
|
|
|
|
|
|
/* *********************************************************************** */
|
|
|
|
|
|
BOOL HB_GT_FUNC( gt_AddEventHandle( int iFile, int iMode,
|
|
int ( *eventFunc ) ( int, int, void * ),
|
|
void *data ) )
|
|
{
|
|
return add_efds( s_ioBase, iFile, iMode, eventFunc, data ) == iFile;
|
|
}
|
|
|
|
void HB_GT_FUNC( gt_DelEventHandle( int iFileDes ) )
|
|
{
|
|
del_efds( s_ioBase, iFileDes );
|
|
}
|
|
|
|
int HB_GT_FUNC( gt_NewXTerm( void ) )
|
|
{
|
|
InOutBase *ioBase;
|
|
int iHandle = -1;
|
|
|
|
ioBase = create_newXterm();
|
|
if ( ioBase )
|
|
{
|
|
set_sig_keys( ioBase, 'C' - ( 'A' - 1 ), 'D' - ( 'A' - 1 ),
|
|
'Z' - ( 'A' - 1 ) );
|
|
iHandle = add_new_ioBase( ioBase );
|
|
}
|
|
return iHandle;
|
|
}
|
|
|
|
int HB_GT_FUNC( gt_SetTerm( int iHandle ) )
|
|
{
|
|
return set_active_ioBase( iHandle );
|
|
}
|
|
|
|
int HB_GT_FUNC( gt_CloseTerm( int iHandle ) )
|
|
{
|
|
return del_ioBase( iHandle );
|
|
}
|
|
|
|
int HB_GT_FUNC( gt_WaitKey( double dTimeOut ) )
|
|
{
|
|
return wait_key( s_ioBase, ( int ) ( dTimeOut * 1000.0 ) );
|
|
}
|
|
|
|
void HB_GT_FUNC( gt_SetKeyTrans( unsigned char *szSrc, unsigned char *szDst ) )
|
|
{
|
|
setKeyTrans( s_ioBase, szSrc, szDst );
|
|
}
|
|
|
|
int HB_GT_FUNC( gt_AddKeyMap( int iKey, char *szSequence ) )
|
|
{
|
|
return addKeyMap( s_ioBase, SET_CLIPKEY( iKey ), szSequence );
|
|
}
|
|
|
|
int HB_GT_FUNC( gt_RemoveKeyMap( char *szSequence ) )
|
|
{
|
|
return removeKeyMap( s_ioBase, szSequence );
|
|
}
|
|
|
|
int HB_GT_FUNC( gt_ESCdelay( int iDelay ) )
|
|
{
|
|
int iRet = s_ioBase->esc_delay;
|
|
|
|
s_ioBase->esc_delay = iDelay;
|
|
|
|
return iRet;
|
|
}
|
|
|
|
void HB_GT_FUNC( gt_SetInterruptKey( int iInterupt ) )
|
|
{
|
|
set_sig_keys( s_ioBase, iInterupt, -1, -1 );
|
|
}
|
|
|
|
void HB_GT_FUNC( gt_SetDebugKey( int iDebug ) )
|
|
{
|
|
set_sig_keys( s_ioBase, -1, iDebug, -1 );
|
|
}
|
|
|
|
BOOL HB_GT_FUNC( gt_GetSignalFlag( int iSig ) )
|
|
{
|
|
BOOL bRetVal = FALSE;
|
|
|
|
if ( iSig > 0 && iSig < MAX_SIGNO && s_SignalTable[iSig] )
|
|
{
|
|
bRetVal = TRUE;
|
|
s_SignalTable[iSig] = FALSE;
|
|
}
|
|
|
|
return bRetVal;
|
|
}
|
|
|
|
void HB_GT_FUNC( gt_CatchSignal( int iSig ) )
|
|
{
|
|
set_sig_handler( iSig );
|
|
}
|
|
|
|
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static void hb_gt_crs_Init( FHANDLE hFilenoStdin, FHANDLE hFilenoStdout, FHANDLE hFilenoStderr )
|
|
{
|
|
InOutBase *ioBase;
|
|
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_Init(%p,%p,%p)", hFilenoStdin, hFilenoStdout, hFilenoStderr ) );
|
|
|
|
if( !s_ioBase )
|
|
{
|
|
s_iStdIn = hFilenoStdin;
|
|
s_iStdOut = hFilenoStdout;
|
|
s_iStdErr = hFilenoStderr;
|
|
#ifdef HB_GT_CRS_TTYHACK
|
|
{
|
|
int ittyfd;
|
|
|
|
if( ( ittyfd = open( "/dev/tty", O_RDWR ) ) != -1 )
|
|
hFilenoStdin = hFilenoStdout = ittyfd;
|
|
}
|
|
#endif
|
|
set_signals();
|
|
ioBase = create_ioBase( NULL, hFilenoStdin, hFilenoStdout, hFilenoStderr, -1 );
|
|
if( ioBase )
|
|
{
|
|
add_new_ioBase( ioBase );
|
|
HB_GTSUPER_INIT( hFilenoStdin, hFilenoStdout, hFilenoStderr );
|
|
HB_GTSUPER_RESIZE( s_ioBase->maxrow, s_ioBase->maxcol );
|
|
hb_gt_SetFlag( GTI_COMPATBUFFER, FALSE );
|
|
hb_gt_SetBlink( TRUE );
|
|
}
|
|
}
|
|
|
|
if( !s_ioBase )
|
|
hb_errInternal( 9997, "Internal error: screen driver initialization failure", "", "" );
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static void hb_gt_crs_Exit( void )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_Exit()" ) );
|
|
|
|
HB_GTSUPER_EXIT();
|
|
|
|
del_all_ioBase();
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static BOOL hb_gt_crs_IsColor( void )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_IsColor()" ) );
|
|
|
|
return s_ioBase->is_color;
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static BOOL hb_gt_crs_SetMode( int iRows, int iCols )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_SetMode(%d, %d)", iRows, iCols ) );
|
|
|
|
if( gt_setsize( s_ioBase, iRows, iCols ) == 0 )
|
|
{
|
|
HB_GTSUPER_RESIZE( iRows, iCols );
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static void hb_gt_crs_SetBlink( BOOL fBlink )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_SetBlink(%d)", ( int ) fBlink ) );
|
|
|
|
if( fBlink )
|
|
s_ioBase->attr_mask |= A_BLINK;
|
|
else
|
|
s_ioBase->attr_mask &= ~A_BLINK;
|
|
|
|
HB_GTSUPER_SETBLINK( fBlink );
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static void hb_gt_crs_Tone( double dFrequency, double dDuration )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_Tone(%lf, %lf)", dFrequency, dDuration ) );
|
|
|
|
gt_tone( s_ioBase, dFrequency, dDuration );
|
|
|
|
if( s_ioBase->terminal_type == TERM_LINUX )
|
|
{
|
|
/* convert Clipper (DOS) timer tick units to seconds ( x / 18.2 ) */
|
|
hb_idleSleep( dDuration / 18.2 );
|
|
}
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static char * hb_gt_crs_Version( int iType )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_Version(%d)", iType ) );
|
|
|
|
if( iType == 0 )
|
|
return HB_GT_DRVNAME( HB_GT_NAME );
|
|
|
|
return "Harbour Terminal: nCurses";
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static void hb_gt_crs_OutStd( BYTE * pbyStr, ULONG ulLen )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_OutStd(%s, %hu)", pbyStr, ulLen ) );
|
|
|
|
if( s_ioBase )
|
|
{
|
|
if( s_ioBase->stdoutfd == -1 )
|
|
hb_gt_WriteCon( pbyStr, ulLen );
|
|
else
|
|
gt_outstd( s_ioBase, pbyStr, ulLen );
|
|
}
|
|
else
|
|
HB_GTSUPER_OUTSTD( pbyStr, ulLen );
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static void hb_gt_crs_OutErr( BYTE * pbyStr, ULONG ulLen )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_OutErr(%s, %hu)", pbyStr, ulLen ) );
|
|
if( s_ioBase )
|
|
{
|
|
if( s_ioBase->stderrfd == -1 )
|
|
hb_gt_WriteCon( pbyStr, ulLen );
|
|
else
|
|
gt_outerr( s_ioBase, ( char * ) pbyStr, ulLen );
|
|
}
|
|
else
|
|
HB_GTSUPER_OUTERR( pbyStr, ulLen );
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static BOOL hb_gt_crs_Suspend( void )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_Suspend()" ) );
|
|
|
|
if( s_ioBase )
|
|
{
|
|
gt_refresh( s_ioBase );
|
|
endwin();
|
|
gt_ttyrestore( s_ioBase );
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static BOOL hb_gt_crs_Resume( void )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_Resume()" ) );
|
|
|
|
if( s_ioBase )
|
|
{
|
|
s_ioBase->lcursor = SC_UNDEF;
|
|
wrefresh( s_ioBase->stdscr );
|
|
gt_ttyset( s_ioBase );
|
|
/* redrawwin( s_ioBase->stdscr ); */
|
|
gt_refresh( s_ioBase );
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static BOOL hb_gt_crs_PreExt( void )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_PreExt()" ) );
|
|
|
|
if( s_ioBase )
|
|
{
|
|
gt_refresh( s_ioBase );
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static BOOL hb_gt_crs_PostExt( void )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_PostExt()" ) );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static BOOL hb_gt_crs_mouse_IsPresent( void )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_mouse_IsPresent()" ) );
|
|
|
|
return s_ioBase->mouse_type != 0;
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static void hb_gt_crs_mouse_Show( void )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_mouse_Show()" ) );
|
|
|
|
#ifdef HAVE_GPM_H
|
|
if( s_ioBase->mouse_type == MOUSE_GPM )
|
|
gpm_visiblepointer = 1;
|
|
#endif
|
|
disp_mousecursor( s_ioBase );
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static void hb_gt_crs_mouse_Hide( void )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_mouse_Hide()" ) );
|
|
|
|
#ifdef HAVE_GPM_H
|
|
if( s_ioBase->mouse_type == MOUSE_GPM )
|
|
{
|
|
gpm_visiblepointer = 0;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static void hb_gt_crs_mouse_GetPos( int * piRow, int * piCol )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_mouse_Col(%p,%p)", piRow, piCol ) );
|
|
|
|
*piRow = s_ioBase->mLastEvt.row;
|
|
*piCol = s_ioBase->mLastEvt.col;
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static void hb_gt_crs_mouse_SetPos( int iRow, int iCol )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_mouse_SetPos(%i, %i)", iRow, iCol ) );
|
|
|
|
/* it does really nothing */
|
|
s_ioBase->mLastEvt.col = iCol;
|
|
s_ioBase->mLastEvt.row = iRow;
|
|
disp_mousecursor( s_ioBase );
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static BOOL hb_gt_crs_mouse_ButtonState( int iButton )
|
|
{
|
|
BOOL ret = FALSE;
|
|
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_mouse_ButtonState(%i)", iButton ) );
|
|
|
|
if( s_ioBase->mouse_type != 0 )
|
|
{
|
|
int mask;
|
|
|
|
if( iButton == 0 )
|
|
mask = M_BUTTON_LEFT;
|
|
else if( iButton == 1 )
|
|
mask = M_BUTTON_RIGHT;
|
|
else if( iButton == 2 )
|
|
mask = M_BUTTON_MIDDLE;
|
|
else
|
|
mask = 0;
|
|
|
|
ret = ( s_ioBase->mLastEvt.buttonstate & mask ) != 0;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static int hb_gt_crs_mouse_CountButton( void )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_mouse_CountButton()" ) );
|
|
|
|
return ( s_ioBase->mButtons );
|
|
}
|
|
|
|
static void hb_gt_crs_mouse_SetDoubleClickSpeed( int iSpeed )
|
|
{
|
|
HB_GTSUPER_MOUSESETDOUBLECLICKSPEED( iSpeed );
|
|
s_ioBase->mLastEvt.click_delay = iSpeed;
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static int hb_gt_crs_ReadKey( int iEventMask )
|
|
{
|
|
int iKey;
|
|
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_ReadKey(%d)", iEventMask ) );
|
|
|
|
HB_SYMBOL_UNUSED( iEventMask );
|
|
|
|
iKey = wait_key( s_ioBase, -1 );
|
|
|
|
if( iKey == K_RESIZE )
|
|
{
|
|
gt_resize( s_ioBase );
|
|
HB_GTSUPER_RESIZE( s_ioBase->maxrow, s_ioBase->maxcol );
|
|
iKey = 0;
|
|
}
|
|
|
|
return iKey;
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static BOOL hb_gt_crs_SetDispCP( char *pszTermCDP, char *pszHostCDP, BOOL fBox )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_SetDispCP(%s,%s,%d)", pszTermCDP, pszHostCDP, (int) fBox ) );
|
|
|
|
#ifndef HB_CDP_SUPPORT_OFF
|
|
if( !pszHostCDP || !*pszHostCDP )
|
|
{
|
|
pszHostCDP = hb_cdp_page->id;
|
|
if ( !pszHostCDP )
|
|
pszHostCDP = pszTermCDP;
|
|
}
|
|
if( !pszTermCDP || !*pszTermCDP )
|
|
pszTermCDP = pszHostCDP;
|
|
|
|
if( pszTermCDP && pszHostCDP && *pszTermCDP && *pszHostCDP )
|
|
{
|
|
PHB_CODEPAGE cdpTerm = hb_cdpFind( pszTermCDP ),
|
|
cdpHost = hb_cdpFind( pszHostCDP );
|
|
if( cdpTerm && cdpHost )
|
|
{
|
|
if( cdpTerm->nChars && cdpTerm->nChars == cdpHost->nChars )
|
|
{
|
|
char *pszHostLetters = ( char * ) hb_xgrab( cdpHost->nChars * 2 + 1 );
|
|
char *pszTermLetters = ( char * ) hb_xgrab( cdpTerm->nChars * 2 + 1 );
|
|
|
|
strncpy( pszHostLetters, cdpHost->CharsUpper, cdpHost->nChars + 1 );
|
|
strncat( pszHostLetters, cdpHost->CharsLower, cdpHost->nChars + 1 );
|
|
strncpy( pszTermLetters, cdpTerm->CharsUpper, cdpTerm->nChars + 1 );
|
|
strncat( pszTermLetters, cdpTerm->CharsLower, cdpTerm->nChars + 1 );
|
|
|
|
setDispTrans( s_ioBase, pszHostLetters, pszTermLetters, fBox ? 1 : 0 );
|
|
|
|
hb_xfree( pszHostLetters );
|
|
hb_xfree( pszTermLetters );
|
|
return TRUE;
|
|
}
|
|
else
|
|
setDispTrans( s_ioBase, "", "", fBox ? 1 : 0 );
|
|
}
|
|
}
|
|
#else
|
|
HB_SYMBOL_UNUSED( pszTermCDP );
|
|
HB_SYMBOL_UNUSED( pszHostCDP );
|
|
HB_SYMBOL_UNUSED( fBox );
|
|
#endif
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static BOOL hb_gt_crs_SetKeyCP( char *pszTermCDP, char *pszHostCDP )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_SetKeyCP(%s,%s)", pszTermCDP, pszHostCDP ) );
|
|
|
|
#ifndef HB_CDP_SUPPORT_OFF
|
|
if( !pszHostCDP || !*pszHostCDP )
|
|
{
|
|
pszHostCDP = hb_cdp_page->id;
|
|
}
|
|
|
|
if( pszTermCDP && pszHostCDP && *pszTermCDP && *pszHostCDP )
|
|
{
|
|
PHB_CODEPAGE cdpTerm = hb_cdpFind( pszTermCDP ),
|
|
cdpHost = hb_cdpFind( pszHostCDP );
|
|
if( cdpTerm && cdpHost && cdpTerm != cdpHost &&
|
|
cdpTerm->nChars && cdpTerm->nChars == cdpHost->nChars )
|
|
{
|
|
char *pszHostLetters = ( char * ) hb_xgrab( cdpHost->nChars * 2 + 1 );
|
|
char *pszTermLetters = ( char * ) hb_xgrab( cdpTerm->nChars * 2 + 1 );
|
|
|
|
strncpy( pszHostLetters, cdpHost->CharsUpper, cdpHost->nChars + 1 );
|
|
strncat( pszHostLetters, cdpHost->CharsLower, cdpHost->nChars + 1 );
|
|
strncpy( pszTermLetters, cdpTerm->CharsUpper, cdpTerm->nChars + 1 );
|
|
strncat( pszTermLetters, cdpTerm->CharsLower, cdpTerm->nChars + 1 );
|
|
|
|
setKeyTrans( s_ioBase, ( unsigned char * ) pszTermLetters,
|
|
( unsigned char * ) pszHostLetters );
|
|
|
|
hb_xfree( pszHostLetters );
|
|
hb_xfree( pszTermLetters );
|
|
return TRUE;
|
|
}
|
|
}
|
|
#else
|
|
HB_SYMBOL_UNUSED( pszTermCDP );
|
|
HB_SYMBOL_UNUSED( pszHostCDP );
|
|
#endif
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static BOOL hb_gt_crs_Info( int iType, PHB_GT_INFO pInfo )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_Info(%d,%p)", iType, pInfo ) );
|
|
|
|
if( s_ioBase )
|
|
{
|
|
switch ( iType )
|
|
{
|
|
case GTI_FULLSCREEN:
|
|
case GTI_KBDSUPPORT:
|
|
pInfo->pResult = hb_itemPutL( pInfo->pResult, TRUE );
|
|
break;
|
|
|
|
case GTI_ESCDELAY:
|
|
pInfo->pResult = hb_itemPutNI( pInfo->pResult, s_ioBase->esc_delay );
|
|
if( hb_itemType( pInfo->pNewVal ) & HB_IT_NUMERIC )
|
|
s_ioBase->esc_delay = hb_itemGetNI( pInfo->pNewVal );
|
|
break;
|
|
|
|
default:
|
|
return HB_GTSUPER_INFO( iType, pInfo );
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static void hb_gt_crs_Redraw( int iRow, int iCol, int iSize )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_Redraw(%d, %d, %d)", iRow, iCol, iSize ) );
|
|
|
|
if( s_ioBase )
|
|
{
|
|
BYTE bColor, bAttr;
|
|
USHORT usChar;
|
|
chtype ch;
|
|
|
|
wmove( s_ioBase->stdscr, iRow, iCol );
|
|
while( iSize-- > 0 )
|
|
{
|
|
if( !hb_gt_GetScrChar( iRow, iCol++, &bColor, &bAttr, &usChar ) )
|
|
break;
|
|
ch = ( s_ioBase->attr_map[ bColor ] & s_ioBase->attr_mask ) |
|
|
( bAttr & HB_GT_ATTR_BOX ? s_ioBase->box_chmap[ usChar & 0xff ] :
|
|
s_ioBase->std_chmap[ usChar & 0xff ] );
|
|
waddch( s_ioBase->stdscr, ch );
|
|
}
|
|
}
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static void hb_gt_crs_Refresh( void )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_Refresh()") );
|
|
|
|
HB_GTSUPER_REFRESH();
|
|
if( s_ioBase )
|
|
{
|
|
int iRow, iCol, iShape;
|
|
|
|
hb_gt_GetScrCursor( &iRow, &iCol, &iShape );
|
|
s_ioBase->row = iRow;
|
|
s_ioBase->col = iCol;
|
|
set_cursor( s_ioBase, iShape );
|
|
gt_refresh( s_ioBase );
|
|
}
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static BOOL hb_gt_FuncInit( PHB_GT_FUNCS pFuncTable )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_FuncInit(%p)", pFuncTable));
|
|
|
|
pFuncTable->Init = hb_gt_crs_Init;
|
|
pFuncTable->Exit = hb_gt_crs_Exit;
|
|
pFuncTable->IsColor = hb_gt_crs_IsColor;
|
|
pFuncTable->SetMode = hb_gt_crs_SetMode;
|
|
pFuncTable->Redraw = hb_gt_crs_Redraw;
|
|
pFuncTable->Refresh = hb_gt_crs_Refresh;
|
|
pFuncTable->SetBlink = hb_gt_crs_SetBlink;
|
|
pFuncTable->Version = hb_gt_crs_Version;
|
|
pFuncTable->Suspend = hb_gt_crs_Suspend;
|
|
pFuncTable->Resume = hb_gt_crs_Resume;
|
|
pFuncTable->PreExt = hb_gt_crs_PreExt;
|
|
pFuncTable->PostExt = hb_gt_crs_PostExt;
|
|
pFuncTable->OutStd = hb_gt_crs_OutStd;
|
|
pFuncTable->OutErr = hb_gt_crs_OutErr;
|
|
pFuncTable->Tone = hb_gt_crs_Tone;
|
|
pFuncTable->Info = hb_gt_crs_Info;
|
|
pFuncTable->SetDispCP = hb_gt_crs_SetDispCP;
|
|
pFuncTable->SetKeyCP = hb_gt_crs_SetKeyCP;
|
|
|
|
pFuncTable->ReadKey = hb_gt_crs_ReadKey;
|
|
|
|
pFuncTable->MouseIsPresent = hb_gt_crs_mouse_IsPresent;
|
|
pFuncTable->MouseShow = hb_gt_crs_mouse_Show;
|
|
pFuncTable->MouseHide = hb_gt_crs_mouse_Hide;
|
|
pFuncTable->MouseGetPos = hb_gt_crs_mouse_GetPos;
|
|
pFuncTable->MouseSetPos = hb_gt_crs_mouse_SetPos;
|
|
pFuncTable->MouseButtonState = hb_gt_crs_mouse_ButtonState;
|
|
pFuncTable->MouseCountButton = hb_gt_crs_mouse_CountButton;
|
|
pFuncTable->MouseSetDoubleClickSpeed = hb_gt_crs_mouse_SetDoubleClickSpeed;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* ********************************************************************** */
|
|
|
|
static HB_GT_INIT gtInit = { HB_GT_DRVNAME( HB_GT_NAME ),
|
|
hb_gt_FuncInit,
|
|
HB_GTSUPER };
|
|
|
|
HB_GT_ANNOUNCE( HB_GT_NAME )
|
|
|
|
HB_CALL_ON_STARTUP_BEGIN( _hb_startup_gt_Init_ )
|
|
hb_gtRegister( >Init );
|
|
HB_CALL_ON_STARTUP_END( _hb_startup_gt_Init_ )
|
|
|
|
#if defined( HB_PRAGMA_STARTUP )
|
|
#pragma startup _hb_startup_gt_Init_
|
|
#elif defined(HB_MSC_STARTUP)
|
|
#if _MSC_VER >= 1010
|
|
#pragma data_seg( ".CRT$XIY" )
|
|
#pragma comment( linker, "/Merge:.CRT=.data" )
|
|
#else
|
|
#pragma data_seg( "XIY" )
|
|
#endif
|
|
static HB_$INITSYM hb_vm_auto__hb_startup_gt_Init_ = _hb_startup_gt_Init_;
|
|
#pragma data_seg()
|
|
#endif
|
|
|
|
/* *********************************************************************** */
|
|
|
|
#if defined(HB_GT_CRS_BCEHACK) && defined(NCURSES_VERSION) && !defined(HB_NCURSES_194)
|
|
#include <term.h>
|
|
static void curs_wrkaround( void )
|
|
{
|
|
back_color_erase = FALSE;
|
|
/* cur_term->type.Booleans[28] = 0; */
|
|
}
|
|
#else
|
|
static void curs_wrkaround( void ) {;}
|
|
#endif
|