395 lines
13 KiB
C
395 lines
13 KiB
C
/*
|
|
* $Id$
|
|
*/
|
|
|
|
/*
|
|
* Harbour Project source code:
|
|
* Keyboard subsystem based on ncurses.
|
|
*
|
|
* Copyright 2000 Ryszard Glab <rglab@imid.med.pl>
|
|
* www - http://www.harbour-project.org
|
|
*
|
|
* 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.
|
|
*
|
|
*/
|
|
|
|
#include <curses.h>
|
|
#include <unistd.h>
|
|
|
|
#include "hbapigt.h"
|
|
#include "hbinit.h"
|
|
|
|
#include "inkey.ch"
|
|
|
|
/* functions defined in mousecrs.c
|
|
*/
|
|
extern int hb_mouse_xevent( char *, HB_inkey_enum );
|
|
extern int hb_mouse_key( void );
|
|
|
|
static void hb_gt_Add_terminfo_keymap( int, char * );
|
|
static void hb_gt_Add_keymap( int, char * );
|
|
|
|
/* max number of characters in a keymapped string */
|
|
#define HB_MAX_KEYMAP_CHARS 16
|
|
|
|
struct key_map_struc
|
|
{
|
|
int inkey_code;
|
|
int length;
|
|
char * key_string;
|
|
struct key_map_struc * Next;
|
|
};
|
|
|
|
#define HB_HASH_KEY 128
|
|
static struct key_map_struc * s_keymap_table[ HB_HASH_KEY ];
|
|
static BOOL s_under_xterm;
|
|
static char * s_mouse_event_seq;
|
|
static int s_mouse_event_len;
|
|
|
|
void hb_gt_keyboard_Init( void )
|
|
{
|
|
int i;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_Initialize_Keyboard()"));
|
|
|
|
/* Initialize keycode table */
|
|
for( i = 0; i < HB_HASH_KEY; i++ )
|
|
s_keymap_table[ i ] = NULL;
|
|
|
|
{
|
|
char * tmp = hb_getenv( "TERM" );
|
|
s_under_xterm = tmp && tmp[ 0 ] != '\0' && ( strncmp( tmp, "xterm", 5 ) == 0 );
|
|
if( tmp )
|
|
hb_xfree( ( void * ) tmp );
|
|
}
|
|
|
|
if( s_under_xterm )
|
|
{
|
|
/* NOTE: under xterm \E[M is used as a leading code for a mouse event
|
|
Events are as follows:
|
|
\E[M - prefix
|
|
b0 - a byte with buttons state
|
|
b1 - column position of a mouse pointer
|
|
b2 - row position of a mouse pointer
|
|
*/
|
|
s_mouse_event_seq = tigetstr( "kmous" );
|
|
if( s_mouse_event_seq == NULL || s_mouse_event_seq == ( char * ) -1 )
|
|
s_mouse_event_len = 0;
|
|
else
|
|
s_mouse_event_len = strlen( s_mouse_event_seq );
|
|
hb_gt_Add_terminfo_keymap( K_HOME, "kfnd" );
|
|
hb_gt_Add_terminfo_keymap( K_END, "kslt" );
|
|
/* workaraound for xterm bug */
|
|
hb_gt_Add_terminfo_keymap( K_UP, "cuu1" );
|
|
hb_gt_Add_terminfo_keymap( K_RIGHT, "cuf1" );
|
|
hb_gt_Add_keymap( K_LEFT, "\033[D" );
|
|
hb_gt_Add_keymap( K_DOWN, "\033[B" );
|
|
}
|
|
else
|
|
{
|
|
/* NOTE: ncurses doesn't report any mouse events when run under GPM
|
|
*/
|
|
s_mouse_event_len = 0;
|
|
}
|
|
|
|
hb_gt_Add_terminfo_keymap( K_ENTER, "kent" );
|
|
hb_gt_Add_terminfo_keymap( K_ENTER, "ind" );
|
|
hb_gt_Add_terminfo_keymap( K_TAB, "ht" );
|
|
hb_gt_Add_terminfo_keymap( K_DOWN, "kcud1" );
|
|
hb_gt_Add_terminfo_keymap( K_UP, "kcuu1" );
|
|
hb_gt_Add_terminfo_keymap( K_LEFT, "kcub1" );
|
|
hb_gt_Add_terminfo_keymap( K_RIGHT, "kcuf1" );
|
|
hb_gt_Add_terminfo_keymap( K_HOME, "khome" );
|
|
hb_gt_Add_terminfo_keymap( K_END, "kend" );
|
|
hb_gt_Add_terminfo_keymap( K_BS, "kbs" );
|
|
hb_gt_Add_terminfo_keymap( K_BS, "kcbt" );
|
|
hb_gt_Add_terminfo_keymap( K_INS, "kich1" );
|
|
hb_gt_Add_terminfo_keymap( K_DEL, "kdch1" );
|
|
hb_gt_Add_terminfo_keymap( K_PGDN, "knp" );
|
|
hb_gt_Add_terminfo_keymap( K_PGUP, "kpp" );
|
|
hb_gt_Add_terminfo_keymap( K_F1, "kf1" );
|
|
hb_gt_Add_terminfo_keymap( K_F2, "kf2" );
|
|
hb_gt_Add_terminfo_keymap( K_F3, "kf3" );
|
|
hb_gt_Add_terminfo_keymap( K_F4, "kf4" );
|
|
hb_gt_Add_terminfo_keymap( K_F5, "kf5" );
|
|
hb_gt_Add_terminfo_keymap( K_F6, "kf6" );
|
|
hb_gt_Add_terminfo_keymap( K_F7, "kf7" );
|
|
hb_gt_Add_terminfo_keymap( K_F8, "kf8" );
|
|
hb_gt_Add_terminfo_keymap( K_F9, "kf9" );
|
|
hb_gt_Add_terminfo_keymap( K_F10, "kf10" );
|
|
hb_gt_Add_terminfo_keymap( K_F11, "kf11" );
|
|
hb_gt_Add_terminfo_keymap( K_F12, "kf12" );
|
|
hb_gt_Add_terminfo_keymap( K_SH_F1, "kf13" );
|
|
hb_gt_Add_terminfo_keymap( K_SH_F2, "kf14" );
|
|
hb_gt_Add_terminfo_keymap( K_SH_F3, "kf15" );
|
|
hb_gt_Add_terminfo_keymap( K_SH_F4, "kf16" );
|
|
hb_gt_Add_terminfo_keymap( K_SH_F5, "kf17" );
|
|
hb_gt_Add_terminfo_keymap( K_SH_F6, "kf18" );
|
|
hb_gt_Add_terminfo_keymap( K_SH_F7, "kf19" );
|
|
hb_gt_Add_terminfo_keymap( K_SH_F8, "kf20" );
|
|
hb_gt_Add_terminfo_keymap( K_SH_F9, "kf21" );
|
|
hb_gt_Add_terminfo_keymap( K_SH_F10, "kf22" );
|
|
hb_gt_Add_terminfo_keymap( K_SH_F11, "kf23" );
|
|
hb_gt_Add_terminfo_keymap( K_SH_F12, "kf24" );
|
|
hb_gt_Add_terminfo_keymap( K_ALT_TAB, "kcbt" );
|
|
hb_gt_Add_terminfo_keymap( K_HOME, "ka1" );
|
|
hb_gt_Add_terminfo_keymap( K_PGUP, "ka3" );
|
|
hb_gt_Add_terminfo_keymap( K_END, "kc1" );
|
|
hb_gt_Add_terminfo_keymap( K_PGDN, "kc3" );
|
|
hb_gt_Add_keymap( K_ALT_A, "\033a" );
|
|
hb_gt_Add_keymap( K_ALT_A, "\033A" );
|
|
hb_gt_Add_keymap( K_ALT_B, "\033b" );
|
|
hb_gt_Add_keymap( K_ALT_B, "\033B" );
|
|
hb_gt_Add_keymap( K_ALT_C, "\033c" );
|
|
hb_gt_Add_keymap( K_ALT_C, "\033C" );
|
|
hb_gt_Add_keymap( K_ALT_D, "\033d" );
|
|
hb_gt_Add_keymap( K_ALT_D, "\033D" );
|
|
hb_gt_Add_keymap( K_ALT_E, "\033e" );
|
|
hb_gt_Add_keymap( K_ALT_E, "\033E" );
|
|
hb_gt_Add_keymap( K_ALT_F, "\033f" );
|
|
hb_gt_Add_keymap( K_ALT_F, "\033F" );
|
|
hb_gt_Add_keymap( K_ALT_G, "\033g" );
|
|
hb_gt_Add_keymap( K_ALT_G, "\033G" );
|
|
hb_gt_Add_keymap( K_ALT_H, "\033h" );
|
|
hb_gt_Add_keymap( K_ALT_H, "\033H" );
|
|
hb_gt_Add_keymap( K_ALT_I, "\033i" );
|
|
hb_gt_Add_keymap( K_ALT_I, "\033I" );
|
|
hb_gt_Add_keymap( K_ALT_J, "\033j" );
|
|
hb_gt_Add_keymap( K_ALT_J, "\033J" );
|
|
hb_gt_Add_keymap( K_ALT_K, "\033k" );
|
|
hb_gt_Add_keymap( K_ALT_K, "\033K" );
|
|
hb_gt_Add_keymap( K_ALT_L, "\033l" );
|
|
hb_gt_Add_keymap( K_ALT_L, "\033L" );
|
|
hb_gt_Add_keymap( K_ALT_M, "\033m" );
|
|
hb_gt_Add_keymap( K_ALT_M, "\033M" );
|
|
hb_gt_Add_keymap( K_ALT_N, "\033n" );
|
|
hb_gt_Add_keymap( K_ALT_N, "\033N" );
|
|
hb_gt_Add_keymap( K_ALT_O, "\033o" );
|
|
hb_gt_Add_keymap( K_ALT_O, "\033O" );
|
|
hb_gt_Add_keymap( K_ALT_P, "\033p" );
|
|
hb_gt_Add_keymap( K_ALT_P, "\033P" );
|
|
hb_gt_Add_keymap( K_ALT_Q, "\033q" );
|
|
hb_gt_Add_keymap( K_ALT_Q, "\033Q" );
|
|
hb_gt_Add_keymap( K_ALT_R, "\033r" );
|
|
hb_gt_Add_keymap( K_ALT_R, "\033R" );
|
|
hb_gt_Add_keymap( K_ALT_S, "\033s" );
|
|
hb_gt_Add_keymap( K_ALT_S, "\033S" );
|
|
hb_gt_Add_keymap( K_ALT_T, "\033t" );
|
|
hb_gt_Add_keymap( K_ALT_T, "\033T" );
|
|
hb_gt_Add_keymap( K_ALT_U, "\033u" );
|
|
hb_gt_Add_keymap( K_ALT_U, "\033U" );
|
|
hb_gt_Add_keymap( K_ALT_V, "\033v" );
|
|
hb_gt_Add_keymap( K_ALT_V, "\033V" );
|
|
hb_gt_Add_keymap( K_ALT_W, "\033w" );
|
|
hb_gt_Add_keymap( K_ALT_W, "\033W" );
|
|
hb_gt_Add_keymap( K_ALT_X, "\033x" );
|
|
hb_gt_Add_keymap( K_ALT_X, "\033X" );
|
|
hb_gt_Add_keymap( K_ALT_Y, "\033y" );
|
|
hb_gt_Add_keymap( K_ALT_Y, "\033Y" );
|
|
hb_gt_Add_keymap( K_ALT_Z, "\033z" );
|
|
hb_gt_Add_keymap( K_ALT_Z, "\033Z" );
|
|
hb_gt_Add_keymap( K_ALT_1, "\0331" );
|
|
hb_gt_Add_keymap( K_ALT_2, "\0332" );
|
|
hb_gt_Add_keymap( K_ALT_3, "\0333" );
|
|
hb_gt_Add_keymap( K_ALT_4, "\0334" );
|
|
hb_gt_Add_keymap( K_ALT_5, "\0335" );
|
|
hb_gt_Add_keymap( K_ALT_6, "\0336" );
|
|
hb_gt_Add_keymap( K_ALT_7, "\0337" );
|
|
hb_gt_Add_keymap( K_ALT_8, "\0338" );
|
|
hb_gt_Add_keymap( K_ALT_9, "\0339" );
|
|
hb_gt_Add_keymap( K_ALT_0, "\0330" );
|
|
hb_gt_Add_keymap( K_ALT_ENTER, "\033\n" );
|
|
hb_gt_Add_keymap( K_ALT_EQUALS, "\033=" );
|
|
}
|
|
|
|
void hb_gt_keyboard_Exit( void )
|
|
{
|
|
int i, k;
|
|
struct key_map_struc *tmp;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_kbd_Exit()"));
|
|
|
|
for( i = 0; i < HB_HASH_KEY; i++ )
|
|
{
|
|
tmp = s_keymap_table[ i ];
|
|
k = 0;
|
|
while( tmp )
|
|
{
|
|
s_keymap_table[ i ] = tmp->Next;
|
|
hb_xfree( tmp );
|
|
tmp = s_keymap_table[ i ];
|
|
k++;
|
|
}
|
|
}
|
|
}
|
|
|
|
int hb_gt_ExtendedKeySupport()
|
|
{
|
|
return 0;
|
|
}
|
|
int hb_gt_ReadKey( HB_inkey_enum eventmask )
|
|
{
|
|
static char key_codes[ HB_MAX_KEYMAP_CHARS + 1 ]; /* buffer for multi-characters keycodes */
|
|
static int key_waiting = -1; /* position of next character from buffer if > 0 */
|
|
int ch;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_ReadKey(%d)", (int) eventmask));
|
|
|
|
if( key_waiting >= 0 )
|
|
{
|
|
/* return next character from the buffer */
|
|
ch = key_codes[ key_waiting++ ];
|
|
if( key_codes[ key_waiting ] == 0 )
|
|
key_waiting = -1; /* the last character was retrieved */
|
|
return ch;
|
|
}
|
|
|
|
ch = getch();
|
|
if( ch == ERR )
|
|
ch = hb_mouse_key();
|
|
else
|
|
{
|
|
if( ch == 3 )
|
|
{
|
|
/* Ctrl-C was pressed */
|
|
ch = HB_BREAK_FLAG;
|
|
}
|
|
else
|
|
{
|
|
int i = 0;
|
|
BYTE sum;
|
|
|
|
key_codes[ 0 ] = sum = ch;
|
|
while( ( ch = getch() ) != ERR && i <= HB_MAX_KEYMAP_CHARS )
|
|
{
|
|
key_codes[ ++i ] = ch;
|
|
/*fprintf( stderr, "key%i=%i(%c)\n", i, ch, ch );
|
|
fflush( stderr );
|
|
*/
|
|
sum += ch;
|
|
}
|
|
key_codes[ ++i ] = 0;
|
|
sum &= HB_HASH_KEY - 1;
|
|
|
|
ch = 0;
|
|
if( s_keymap_table[ sum ] )
|
|
{
|
|
/* there is an entry in the hash table */
|
|
struct key_map_struc * tmp = s_keymap_table[ sum ];
|
|
|
|
while( ( ch == 0 ) && tmp )
|
|
{
|
|
/* now look for exact match */
|
|
if( ( i == tmp->length ) && ( memcmp( tmp->key_string, key_codes, i ) == 0 ) )
|
|
{
|
|
ch = tmp->inkey_code; /* keycode found */
|
|
tmp = NULL; /* NOTE: tmp->inkey_code can be set to 0 */
|
|
}
|
|
else
|
|
tmp = tmp->Next;
|
|
}
|
|
|
|
}
|
|
|
|
if( ch == 0 )
|
|
{
|
|
if( s_mouse_event_len )
|
|
{
|
|
/* check for mouse event */
|
|
if( memcmp( s_mouse_event_seq, key_codes, s_mouse_event_len ) == 0 )
|
|
{
|
|
/* Convert the mouse event into INKEY keycodes */
|
|
return hb_mouse_xevent( key_codes+s_mouse_event_len, eventmask );
|
|
}
|
|
}
|
|
/* keymap not found */
|
|
if( i == 1 )
|
|
ch = key_codes[ 0 ];
|
|
else
|
|
{
|
|
key_waiting = 0; /* return raw key sequence */
|
|
ch = HB_K_MULTICODE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ch;
|
|
}
|
|
|
|
|
|
static void hb_gt_Add_keymap( int InkeyCode, char *key_string )
|
|
{
|
|
struct key_map_struc * keymap;
|
|
int iLength = strlen( key_string );
|
|
int i = 0;
|
|
BYTE sum = 0;
|
|
|
|
if( iLength && iLength <= HB_MAX_KEYMAP_CHARS )
|
|
{
|
|
while( i < iLength )
|
|
sum += key_string[ i++ ];
|
|
sum &= HB_HASH_KEY - 1;
|
|
|
|
keymap = hb_xgrab( sizeof( struct key_map_struc ) );
|
|
keymap->inkey_code = InkeyCode;
|
|
keymap->key_string = key_string;
|
|
keymap->length = iLength;
|
|
keymap->Next = NULL;
|
|
|
|
if( s_keymap_table[ sum ] )
|
|
{
|
|
struct key_map_struc * tmp = s_keymap_table[ sum ];
|
|
while( tmp->Next )
|
|
tmp = tmp->Next;
|
|
tmp->Next = keymap;
|
|
}
|
|
else
|
|
s_keymap_table[ sum ] = keymap;
|
|
}
|
|
}
|
|
|
|
static void hb_gt_Add_terminfo_keymap( int InkeyCode, char * capname )
|
|
{
|
|
char * code;
|
|
|
|
code = tigetstr( capname );
|
|
if( ( code != NULL ) && ( code != ( char * ) -1 ) )
|
|
hb_gt_Add_keymap( InkeyCode, code );
|
|
} |