3035 lines
90 KiB
C
3035 lines
90 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 int s_GtId;
|
|
static HB_GT_FUNCS SuperTable;
|
|
#define HB_GTSUPER (&SuperTable)
|
|
#define HB_GTID_PTR (&s_GtId)
|
|
|
|
/* 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 )
|
|
{
|
|
/* SA_NOCLDSTOP in #if is a hack to detect POSIX compatible environment */
|
|
#if defined( SA_NOCLDSTOP )
|
|
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 );
|
|
#endif
|
|
}
|
|
|
|
#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:
|
|
if( cMBuf[0] & 0x20 )
|
|
mEvt->buttonstate |= M_BUTTON_WHEELUP;
|
|
break;
|
|
case 0x41:
|
|
if( cMBuf[0] & 0x20 )
|
|
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 ), "\033[?25%c\033[?%hdc",
|
|
ioBase->cursor == SC_NONE ? 'l' : 'h', lcurs );
|
|
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 ), "\033[10;%hd]\033[11;%hd]%s",
|
|
( int ) dFrequency,
|
|
( int ) ( dDuration * 1000.0 / 18.2 ), ioBase->beep );
|
|
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 ), "\033[8;%hd;%hdt", rows, cols );
|
|
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_chrmapinit( ioBase->charmap, term, ioBase->terminal_type == TERM_XTERM );
|
|
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 );
|
|
/*
|
|
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( PHB_GT pGT, FHANDLE hFilenoStdin, FHANDLE hFilenoStdout, FHANDLE hFilenoStderr )
|
|
{
|
|
InOutBase *ioBase;
|
|
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_Init(%p,%p,%p,%p)", pGT, 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( pGT, hFilenoStdin, hFilenoStdout, hFilenoStderr );
|
|
HB_GTSELF_RESIZE( pGT, s_ioBase->maxrow, s_ioBase->maxcol );
|
|
HB_GTSELF_SETFLAG( pGT, HB_GTI_COMPATBUFFER, FALSE );
|
|
HB_GTSELF_SETBLINK( pGT, TRUE );
|
|
}
|
|
}
|
|
|
|
if( !s_ioBase )
|
|
hb_errInternal( 9997, "Internal error: screen driver initialization failure", NULL, NULL );
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static void hb_gt_crs_Exit( PHB_GT pGT )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_Exit(%p)", pGT ) );
|
|
|
|
HB_GTSUPER_EXIT( pGT );
|
|
|
|
del_all_ioBase();
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static BOOL hb_gt_crs_IsColor( PHB_GT pGT )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_IsColor(%p)", pGT ) );
|
|
|
|
HB_SYMBOL_UNUSED( pGT );
|
|
|
|
return s_ioBase->is_color;
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static BOOL hb_gt_crs_SetMode( PHB_GT pGT, int iRows, int iCols )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_SetMode(%p,%d,%d)", pGT, iRows, iCols ) );
|
|
|
|
if( gt_setsize( s_ioBase, iRows, iCols ) == 0 )
|
|
{
|
|
HB_GTSELF_RESIZE( pGT, iRows, iCols );
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static void hb_gt_crs_SetBlink( PHB_GT pGT, BOOL fBlink )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_SetBlink(%p, %d)", pGT, ( int ) fBlink ) );
|
|
|
|
if( fBlink )
|
|
s_ioBase->attr_mask |= A_BLINK;
|
|
else
|
|
s_ioBase->attr_mask &= ~A_BLINK;
|
|
|
|
HB_GTSUPER_SETBLINK( pGT, fBlink );
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static void hb_gt_crs_Tone( PHB_GT pGT, double dFrequency, double dDuration )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_Tone(%p,%lf,%lf)", pGT, dFrequency, dDuration ) );
|
|
|
|
HB_SYMBOL_UNUSED( pGT );
|
|
|
|
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( PHB_GT pGT, int iType )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_Version(%p,%d)", pGT, iType ) );
|
|
|
|
HB_SYMBOL_UNUSED( pGT );
|
|
|
|
if( iType == 0 )
|
|
return HB_GT_DRVNAME( HB_GT_NAME );
|
|
|
|
return "Harbour Terminal: nCurses";
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static void hb_gt_crs_OutStd( PHB_GT pGT, BYTE * pbyStr, ULONG ulLen )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_OutStd(%p,%s,%lu)", pGT, pbyStr, ulLen ) );
|
|
|
|
if( s_ioBase )
|
|
{
|
|
if( s_ioBase->stdoutfd == -1 )
|
|
HB_GTSELF_WRITECON( pGT, pbyStr, ulLen );
|
|
else
|
|
gt_outstd( s_ioBase, pbyStr, ulLen );
|
|
}
|
|
else
|
|
HB_GTSUPER_OUTSTD( pGT, pbyStr, ulLen );
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static void hb_gt_crs_OutErr( PHB_GT pGT, BYTE * pbyStr, ULONG ulLen )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_OutErr(%p,%s,%lu)", pGT, pbyStr, ulLen ) );
|
|
if( s_ioBase )
|
|
{
|
|
if( s_ioBase->stderrfd == -1 )
|
|
HB_GTSELF_WRITECON( pGT, pbyStr, ulLen );
|
|
else
|
|
gt_outerr( s_ioBase, ( char * ) pbyStr, ulLen );
|
|
}
|
|
else
|
|
HB_GTSUPER_OUTERR( pGT, pbyStr, ulLen );
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static BOOL hb_gt_crs_Suspend( PHB_GT pGT )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_Suspend(%p)", pGT ) );
|
|
|
|
HB_SYMBOL_UNUSED( pGT );
|
|
|
|
if( s_ioBase )
|
|
{
|
|
gt_refresh( s_ioBase );
|
|
endwin();
|
|
gt_ttyrestore( s_ioBase );
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static BOOL hb_gt_crs_Resume( PHB_GT pGT )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_Resume(%p)", pGT ) );
|
|
|
|
HB_SYMBOL_UNUSED( pGT );
|
|
|
|
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( PHB_GT pGT )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_PreExt(%p)", pGT ) );
|
|
|
|
HB_SYMBOL_UNUSED( pGT );
|
|
|
|
if( s_ioBase )
|
|
{
|
|
gt_refresh( s_ioBase );
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static BOOL hb_gt_crs_PostExt( PHB_GT pGT )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_PostExt(%p)", pGT ) );
|
|
|
|
HB_SYMBOL_UNUSED( pGT );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static BOOL hb_gt_crs_mouse_IsPresent( PHB_GT pGT )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_mouse_IsPresent(%p)", pGT ) );
|
|
|
|
HB_SYMBOL_UNUSED( pGT );
|
|
|
|
return s_ioBase->mouse_type != MOUSE_NONE;
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static void hb_gt_crs_mouse_Show( PHB_GT pGT )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_mouse_Show(%p)", pGT ) );
|
|
|
|
HB_SYMBOL_UNUSED( pGT );
|
|
|
|
#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( PHB_GT pGT )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_mouse_Hide(%p)", pGT ) );
|
|
|
|
HB_SYMBOL_UNUSED( pGT );
|
|
|
|
#ifdef HAVE_GPM_H
|
|
if( s_ioBase->mouse_type == MOUSE_GPM )
|
|
{
|
|
gpm_visiblepointer = 0;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static void hb_gt_crs_mouse_GetPos( PHB_GT pGT, int * piRow, int * piCol )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_mouse_Col(%p,%p,%p)", pGT, piRow, piCol ) );
|
|
|
|
HB_SYMBOL_UNUSED( pGT );
|
|
|
|
*piRow = s_ioBase->mLastEvt.row;
|
|
*piCol = s_ioBase->mLastEvt.col;
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static void hb_gt_crs_mouse_SetPos( PHB_GT pGT, int iRow, int iCol )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_mouse_SetPos(%p,%i,%i)", pGT, iRow, iCol ) );
|
|
|
|
HB_SYMBOL_UNUSED( pGT );
|
|
|
|
/* 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( PHB_GT pGT, int iButton )
|
|
{
|
|
BOOL ret = FALSE;
|
|
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_mouse_ButtonState(%p,%i)", pGT, iButton ) );
|
|
|
|
HB_SYMBOL_UNUSED( pGT );
|
|
|
|
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( PHB_GT pGT )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_mouse_CountButton(%p)", pGT ) );
|
|
|
|
HB_SYMBOL_UNUSED( pGT );
|
|
|
|
return ( s_ioBase->mButtons );
|
|
}
|
|
|
|
static void hb_gt_crs_mouse_SetDoubleClickSpeed( PHB_GT pGT, int iSpeed )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_mouse_SetDoubleClickSpeed(%p,%d)", pGT, iSpeed ) );
|
|
|
|
HB_GTSUPER_MOUSESETDOUBLECLICKSPEED( pGT, iSpeed );
|
|
s_ioBase->mLastEvt.click_delay = iSpeed;
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static int hb_gt_crs_ReadKey( PHB_GT pGT, int iEventMask )
|
|
{
|
|
int iKey;
|
|
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_ReadKey(%p,%d)", pGT, iEventMask ) );
|
|
|
|
HB_SYMBOL_UNUSED( iEventMask );
|
|
|
|
iKey = wait_key( s_ioBase, -1 );
|
|
|
|
if( iKey == K_RESIZE )
|
|
{
|
|
gt_resize( s_ioBase );
|
|
HB_GTSELF_RESIZE( pGT, s_ioBase->maxrow, s_ioBase->maxcol );
|
|
iKey = 0;
|
|
}
|
|
|
|
return iKey;
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static BOOL hb_gt_crs_SetDispCP( PHB_GT pGT, char *pszTermCDP, char *pszHostCDP, BOOL fBox )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_SetDispCP(%p,%s,%s,%d)", pGT, pszTermCDP, pszHostCDP, (int) fBox ) );
|
|
|
|
HB_GTSUPER_SETDISPCP( pGT, pszTermCDP, pszHostCDP, 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 );
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static BOOL hb_gt_crs_SetKeyCP( PHB_GT pGT, char *pszTermCDP, char *pszHostCDP )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_SetKeyCP(%p,%s,%s)", pGT, pszTermCDP, pszHostCDP ) );
|
|
|
|
HB_GTSUPER_SETKEYCP( pGT, 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;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static BOOL hb_gt_crs_Info( PHB_GT pGT, int iType, PHB_GT_INFO pInfo )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_Info(%p,%d,%p)", pGT, iType, pInfo ) );
|
|
|
|
if( s_ioBase )
|
|
{
|
|
switch ( iType )
|
|
{
|
|
case HB_GTI_FULLSCREEN:
|
|
case HB_GTI_KBDSUPPORT:
|
|
pInfo->pResult = hb_itemPutL( pInfo->pResult, TRUE );
|
|
break;
|
|
|
|
case HB_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( pGT, iType, pInfo );
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static void hb_gt_crs_Redraw( PHB_GT pGT, int iRow, int iCol, int iSize )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_Redraw(%p,%d,%d,%d)", pGT, iRow, iCol, iSize ) );
|
|
|
|
if( s_ioBase )
|
|
{
|
|
BYTE bColor, bAttr;
|
|
USHORT usChar;
|
|
chtype ch;
|
|
|
|
wmove( s_ioBase->stdscr, iRow, iCol );
|
|
while( iSize-- > 0 )
|
|
{
|
|
if( !HB_GTSELF_GETSCRCHAR( pGT, 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( PHB_GT pGT )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_crs_Refresh(%p)", pGT ) );
|
|
|
|
HB_GTSUPER_REFRESH( pGT );
|
|
if( s_ioBase )
|
|
{
|
|
int iRow, iCol, iShape;
|
|
|
|
HB_GTSELF_GETSCRCURSOR( pGT, &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 const HB_GT_INIT gtInit = { HB_GT_DRVNAME( HB_GT_NAME ),
|
|
hb_gt_FuncInit,
|
|
HB_GTSUPER,
|
|
HB_GTID_PTR };
|
|
|
|
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)
|
|
#pragma data_seg( HB_MSC_START_SEGMENT )
|
|
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
|