Files
harbour-core/harbour/source/rtl/gtwin/gtwin.c

1827 lines
61 KiB
C
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* $Id$
*/
/*
* Harbour Project source code:
* Video subsystem for Win32 compilers ver.2
* Copyright 2002 Przemys³aw Czerpak <druzus@polbox.com>
*
* based on
* Bcc ConIO Video subsystem by
* Copyright 2002 Marek Paliwoda <paliwoda@inteia.pl>
* Copyright 2002 Przemys³aw Czerpak <druzus@polbox.com>
* Video subsystem for Win32 compilers
* Copyright 1999-2000 Paul Tucker <ptucker@sympatico.ca>
* (with 2004 work on Readkey)
*
* The following parts are Copyright of the individual authors.
* www - http://www.harbour-project.org
*
* Copyright 1999-2001 Viktor Szakats <viktor.szakats@syenar.hu>
* hb_gt_CtrlHandler()
*
* Copyright 1999 David G. Holm <dholm@jsd-llc.com>
* hb_gt_Tone()
* hb_gt_ReadKey()
*
* See doc/license.txt for licensing terms.
*
* 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.
*
*/
/* NOTE: User programs should never call this layer directly! */
#define HB_GT_NAME WIN
/* TODO: include any standard headers here */
/* *********************************************************************** */
#define HB_OS_WIN_32_USED
#include "hbgtcore.h"
#include "hbinit.h"
#include "hbapiitm.h"
#include "hbapierr.h"
#ifndef HB_CDP_SUPPORT_OFF
# include "hbapicdp.h"
#endif
#if !defined( HB_NO_WIN_CONSOLE )
#if !defined( __LCC__ )
# include <wincon.h>
#endif
#if defined( _MSC_VER ) || defined(__WATCOMC__)
# include <conio.h>
#endif
#ifndef MOUSE_WHEELED
# define MOUSE_WHEELED 0x0004
#endif
/*
To disable mouse, initialization was made in cmdarg.c
*/
static BOOL b_MouseEnable = TRUE;
/* *********************************************************************** */
#if defined(__IBMCPP__)
#undef WORD /* 2 bytes unsigned */
typedef unsigned short int WORD;
#else
#if ! defined(HB_DONT_DEFINE_BASIC_TYPES)
#undef WORD /* 2 bytes unsigned */
typedef USHORT WORD;
#undef DWORD /* 4 bytes unsigned */
typedef ULONG DWORD;
#endif
#endif
#if ! defined(__GNUC__) && defined(__CYGWIN__)
typedef WORD far * LPWORD;
#endif
#if defined(__RSXNT__)
#ifndef FROM_LEFT_1ST_BUTTON_PRESSED
#define FROM_LEFT_1ST_BUTTON_PRESSED 0x0001
#endif
#ifndef RIGHTMOST_BUTTON_PRESSED
#define RIGHTMOST_BUTTON_PRESSED 0x0002
#endif
#ifndef MOUSE_MOVED
#define MOUSE_MOVED 0x0001
#endif
#ifndef DOUBLE_CLICK
#define DOUBLE_CLICK 0x0002
#endif
#endif
/* *********************************************************************** */
static int s_GtId;
static HB_GT_FUNCS SuperTable;
#define HB_GTSUPER (&SuperTable)
#define HB_GTID_PTR (&s_GtId)
static BOOL s_bSpecialKeyHandling;
static BOOL s_bAltKeyHandling;
static DWORD s_dwAltGrBits; /* JC: used to verify ALT+GR on different platforms */
static BOOL s_bBreak; /* Used to signal Ctrl+Break to hb_inkeyPoll() */
static USHORT s_uiDispCount;
static USHORT s_usCursorStyle;
static USHORT s_usOldCurStyle;
static SHORT s_sCurRow;
static SHORT s_sCurCol;
static USHORT s_usUpdtTop;
static USHORT s_usUpdtBottom;
static USHORT s_usUpdtLeft;
static USHORT s_usUpdtRight;
static CHAR_INFO * s_pCharInfoScreen = NULL;
static ULONG s_ulScreenBuffSize = 0;
static FHANDLE s_hStdIn, s_hStdOut, s_hStdErr;
static HANDLE s_HInput = INVALID_HANDLE_VALUE;
static HANDLE s_HOutput = INVALID_HANDLE_VALUE;
static DWORD s_dwimode, s_dwomode;
static CONSOLE_SCREEN_BUFFER_INFO s_csbi, /* active screen mode */
s_origCsbi; /* to restore screen mode on exit */
/* faster macro version for use inside this module */
#define _GetScreenWidth() ( s_csbi.dwSize.X )
#define _GetScreenHeight() ( s_csbi.dwSize.Y )
#define INPUT_BUFFER_LEN 32
static DWORD s_cNumRead; /* Ok to use DWORD here, because this is specific... */
static DWORD s_cNumIndex; /* ...to the Windows API, which defines DWORD, etc. */
static WORD s_wRepeated = 0; /* number of times the event (key) was repeated */
static INPUT_RECORD s_irInBuf[ INPUT_BUFFER_LEN ];
static BYTE s_charTransRev[ 256 ];
static BYTE s_charTrans[ 256 ];
static BYTE s_keyTrans[ 256 ];
static int s_altisdown = 0;
static int s_altnum = 0;
static int s_mouseLast; /* Last mouse button to be pressed */
static int hb_mouse_iCol;
static int hb_mouse_iRow;
static OSVERSIONINFO s_osv;
typedef struct _ClipKeyCode {
int key;
int alt_key;
int ctrl_key;
int shift_key;
int altgr_key;
} ClipKeyCode;
#define CLIP_STDKEY_COUNT 96
#define CLIP_EXTKEY_COUNT 34
/* Keypad keys */
static const ClipKeyCode stdKeyTab[CLIP_STDKEY_COUNT] = {
{ 32, 0, 0, 0, 0}, /* ' ' */
{ 33, 0, 0, 0, 0}, /* '!' */
{ 34, 0, 0, 0, 0}, /* '"' */
{ 35, 0, 0, 0, 0}, /* '#' */
{ 36, 0, 0, 0, 0}, /* '$' */
{ 37, 0, 0, 0, 0}, /* '%' */
{ 38, 0, 0, 0, 0}, /* '&' */
{ 39, K_ALT_QUOTE, 7, 0, 0}, /* ''' */
{ 40, 0, 0, 0, 0}, /* '(' */
{ 41, 0, 0, 0, 0}, /* ')' */
{ 42, 0, 0, 0, 0}, /* '*' */
{ 43, 0, 0, 0, 0}, /* '+' */
{ 44, K_ALT_COMMA, 0, 0, 0}, /* ',' */
{ 45, K_ALT_MINUS, 398, 0, 0}, /* '-' */
{ 46, K_ALT_PERIOD, 0, 0, 0}, /* '.' */
{ 47, K_ALT_SLASH, 0, 0, 0}, /* '/' */
{ 48, K_ALT_0, 0, 0, K_ALT_0}, /* '0' */
{ 49, K_ALT_1, 0, 0, K_ALT_1}, /* '1' */
{ 50, K_ALT_2, 259, 0, K_ALT_2}, /* '2' */
{ 51, K_ALT_3, 27, 0, K_ALT_3}, /* '3' */
{ 52, K_ALT_4, 28, 0, K_ALT_4}, /* '4' */
{ 53, K_ALT_5, 29, 0, K_ALT_5}, /* '5' */
{ 54, K_ALT_6, 30, 0, K_ALT_6}, /* '6' */
{ 55, K_ALT_7, 31, 0, K_ALT_7}, /* '7' */
{ 56, K_ALT_8, 127, 0, K_ALT_8}, /* '8' */
{ 57, K_ALT_9, 0, 0, K_ALT_9}, /* '9' */
{ 58, 0, 0, 0, 0}, /* ':' */
{ 59, K_ALT_SC, 0, 0, 0}, /* ';' */
{ 60, 0, 0, 0, 0}, /* '<' */
{ 61, K_ALT_EQUALS, 0, 0, 0}, /* '=' */
{ 62, 0, 0, 0, 0}, /* '>' */
{ 63, 0, K_CTRL_QUESTION, 0, 0}, /* '?' */
{ 64, 0, 0, 0, 0}, /* '@' */
{ 65, K_ALT_A, K_CTRL_A, 0, K_ALT_A}, /* 'A' */
{ 66, K_ALT_B, K_CTRL_B, 0, K_ALT_B}, /* 'B' */
{ 67, K_ALT_C, K_CTRL_C, 0, K_ALT_C}, /* 'C' */
{ 68, K_ALT_D, K_CTRL_D, 0, K_ALT_D}, /* 'D' */
{ 69, K_ALT_E, K_CTRL_E, 0, K_ALT_E}, /* 'E' */
{ 70, K_ALT_F, K_CTRL_F, 0, K_ALT_F}, /* 'F' */
{ 71, K_ALT_G, K_CTRL_G, 0, K_ALT_G}, /* 'G' */
{ 72, K_ALT_H, K_CTRL_H, 0, K_ALT_H}, /* 'H' */
{ 73, K_ALT_I, K_CTRL_I, 0, K_ALT_I}, /* 'I' */
{ 74, K_ALT_J, K_CTRL_J, 0, K_ALT_J}, /* 'J' */
{ 75, K_ALT_K, K_CTRL_K, 0, K_ALT_K}, /* 'K' */
{ 76, K_ALT_L, K_CTRL_L, 0, K_ALT_L}, /* 'L' */
{ 77, K_ALT_M, K_CTRL_M, 0, K_ALT_M}, /* 'M' */
{ 78, K_ALT_N, K_CTRL_N, 0, K_ALT_N}, /* 'N' */
{ 79, K_ALT_O, K_CTRL_O, 0, K_ALT_O}, /* 'O' */
{ 80, K_ALT_P, K_CTRL_P, 0, K_ALT_P}, /* 'P' */
{ 81, K_ALT_Q, K_CTRL_Q, 0, K_ALT_Q}, /* 'Q' */
{ 82, K_ALT_R, K_CTRL_R, 0, K_ALT_R}, /* 'R' */
{ 83, K_ALT_S, K_CTRL_S, 0, K_ALT_S}, /* 'S' */
{ 84, K_ALT_T, K_CTRL_T, 0, K_ALT_T}, /* 'T' */
{ 85, K_ALT_U, K_CTRL_U, 0, K_ALT_U}, /* 'U' */
{ 86, K_ALT_V, K_CTRL_V, 0, K_ALT_V}, /* 'V' */
{ 87, K_ALT_W, K_CTRL_W, 0, K_ALT_W}, /* 'W' */
{ 88, K_ALT_X, K_CTRL_X, 0, K_ALT_X}, /* 'X' */
{ 89, K_ALT_Y, K_CTRL_Y, 0, K_ALT_Y}, /* 'Y' */
{ 90, K_ALT_Z, K_CTRL_Z, 0, K_ALT_Z}, /* 'Z' */
{ 91, K_ALT_OSB, 0, 0, 0}, /* '[' */
{ 92, K_ALT_BACKSLASH, 0, 0, 0}, /* '\' */
{ 93, K_ALT_CSB, 0, 0, 0}, /* ']' */
{ 94, K_ALT_6, 0, 0, 0}, /* '^' */
{ 95, 0, 0, 0, 0}, /* '_' */
{ 96, K_ALT_BACKQUOTE, 0, 0, 0}, /* '`' */
{ 97, K_ALT_A, K_CTRL_A, 0, K_ALT_A}, /* 'a' */
{ 98, K_ALT_B, K_CTRL_B, 0, K_ALT_B}, /* 'b' */
{ 99, K_ALT_C, K_CTRL_C, 0, K_ALT_C}, /* 'c' */
{100, K_ALT_D, K_CTRL_D, 0, K_ALT_D}, /* 'd' */
{101, K_ALT_E, K_CTRL_E, 0, K_ALT_E}, /* 'e' */
{102, K_ALT_F, K_CTRL_F, 0, K_ALT_F}, /* 'f' */
{103, K_ALT_G, K_CTRL_G, 0, K_ALT_G}, /* 'g' */
{104, K_ALT_H, K_CTRL_H, 0, K_ALT_H}, /* 'h' */
{105, K_ALT_I, K_CTRL_I, 0, K_ALT_I}, /* 'i' */
{106, K_ALT_J, K_CTRL_J, 0, K_ALT_J}, /* 'j' */
{107, K_ALT_K, K_CTRL_K, 0, K_ALT_K}, /* 'k' */
{108, K_ALT_L, K_CTRL_L, 0, K_ALT_L}, /* 'l' */
{109, K_ALT_M, K_CTRL_M, 0, K_ALT_M}, /* 'm' */
{110, K_ALT_N, K_CTRL_N, 0, K_ALT_N}, /* 'n' */
{111, K_ALT_O, K_CTRL_O, 0, K_ALT_O}, /* 'o' */
{112, K_ALT_P, K_CTRL_P, 0, K_ALT_P}, /* 'p' */
{113, K_ALT_Q, K_CTRL_Q, 0, K_ALT_Q}, /* 'q' */
{114, K_ALT_R, K_CTRL_R, 0, K_ALT_R}, /* 'r' */
{115, K_ALT_S, K_CTRL_S, 0, K_ALT_S}, /* 's' */
{116, K_ALT_T, K_CTRL_T, 0, K_ALT_T}, /* 't' */
{117, K_ALT_U, K_CTRL_U, 0, K_ALT_U}, /* 'u' */
{118, K_ALT_V, K_CTRL_V, 0, K_ALT_V}, /* 'v' */
{119, K_ALT_W, K_CTRL_W, 0, K_ALT_W}, /* 'w' */
{120, K_ALT_X, K_CTRL_X, 0, K_ALT_X}, /* 'x' */
{121, K_ALT_Y, K_CTRL_Y, 0, K_ALT_Y}, /* 'y' */
{122, K_ALT_Z, K_CTRL_Z, 0, K_ALT_Z}, /* 'z' */
{123, 282, 27, 0, 0}, /* '{' */
{124, 299, 28, 0, 0}, /* '|' */
{125, 283, 29, 0, 0}, /* '}' */
{126, 297, 297, 0, 0}, /* '~' */
{127, K_ALT_BS, 127, 0, K_ALT_BS}, /* '' */
};
#define EXKEY_F1 ( 0)
#define EXKEY_F2 ( 1)
#define EXKEY_F3 ( 2)
#define EXKEY_F4 ( 3)
#define EXKEY_F5 ( 4)
#define EXKEY_F6 ( 5)
#define EXKEY_F7 ( 6)
#define EXKEY_F8 ( 7)
#define EXKEY_F9 ( 8)
#define EXKEY_F10 ( 9)
#define EXKEY_F11 (10)
#define EXKEY_F12 (11)
#define EXKEY_UP (12)
#define EXKEY_DOWN (13)
#define EXKEY_LEFT (14)
#define EXKEY_RIGHT (15)
#define EXKEY_INS (16)
#define EXKEY_DEL (17)
#define EXKEY_HOME (18)
#define EXKEY_END (19)
#define EXKEY_PGUP (20)
#define EXKEY_PGDN (21)
#define EXKEY_BS (22)
#define EXKEY_TAB (23)
#define EXKEY_ESC (24)
#define EXKEY_ENTER (25)
#define EXKEY_KPENTER (26)
#define EXKEY_CENTER (27)
#define EXKEY_PRTSCR (28)
#define EXKEY_PAUSE (29)
#define EXKEY_KPASTERISK (30)
#define EXKEY_KPPLUS (31)
#define EXKEY_KPMINUS (32)
#define EXKEY_KPDIVIDE (33)
/* xHarbour compatible definitions */
#if !defined( K_SH_LEFT )
#define K_SH_LEFT K_LEFT /* Shift-Left == Left */
#define K_SH_UP K_UP /* Shift-Up == Up */
#define K_SH_RIGHT K_RIGHT /* Shift-Right == Right */
#define K_SH_DOWN K_DOWN /* Shift-Down == Down */
#define K_SH_INS K_INS /* Shift-Ins == Ins */
#define K_SH_DEL K_DEL /* Shift-Del == Del */
#define K_SH_HOME K_HOME /* Shift-Home == Home */
#define K_SH_END K_END /* Shift-End == End */
#define K_SH_PGUP K_PGUP /* Shift-PgUp == PgUp */
#define K_SH_PGDN K_PGDN /* Shift-PgDn == PgDn */
#define K_SH_RETURN K_RETURN /* Shift-Enter == Enter */
#define K_SH_ENTER K_ENTER /* Shift-Enter == Enter */
#endif
static const ClipKeyCode extKeyTab[CLIP_EXTKEY_COUNT] = {
{K_F1, K_ALT_F1, K_CTRL_F1, K_SH_F1, K_ALT_F1}, /* 00 */
{K_F2, K_ALT_F2, K_CTRL_F2, K_SH_F2, K_ALT_F2}, /* 01 */
{K_F3, K_ALT_F3, K_CTRL_F3, K_SH_F3, K_ALT_F3}, /* 02 */
{K_F4, K_ALT_F4, K_CTRL_F4, K_SH_F4, K_ALT_F4}, /* 03 */
{K_F5, K_ALT_F5, K_CTRL_F5, K_SH_F5, K_ALT_F5}, /* 04 */
{K_F6, K_ALT_F6, K_CTRL_F6, K_SH_F6, K_ALT_F6}, /* 05 */
{K_F7, K_ALT_F7, K_CTRL_F7, K_SH_F7, K_ALT_F7}, /* 06 */
{K_F8, K_ALT_F8, K_CTRL_F8, K_SH_F8, K_ALT_F8}, /* 07 */
{K_F9, K_ALT_F9, K_CTRL_F9, K_SH_F9, K_ALT_F9}, /* 08 */
{K_F10, K_ALT_F10, K_CTRL_F10, K_SH_F10, K_ALT_F10}, /* 09 */
{K_F11, K_ALT_F11, K_CTRL_F11, K_SH_F11, K_ALT_F11}, /* 10 */
{K_F12, K_ALT_F12, K_CTRL_F12, K_SH_F12, K_ALT_F12}, /* 11 */
{K_UP, K_ALT_UP, K_CTRL_UP, K_SH_UP, K_ALT_UP}, /* 12 */
{K_DOWN, K_ALT_DOWN, K_CTRL_DOWN, K_SH_DOWN, K_ALT_DOWN}, /* 13 */
{K_LEFT, K_ALT_LEFT, K_CTRL_LEFT, K_SH_LEFT, K_ALT_LEFT}, /* 14 */
{K_RIGHT, K_ALT_RIGHT, K_CTRL_RIGHT,K_SH_RIGHT, K_ALT_RIGHT}, /* 15 */
{K_INS, K_ALT_INS, K_CTRL_INS, K_SH_INS, K_ALT_INS}, /* 16 */
{K_DEL, K_ALT_DEL, K_CTRL_DEL, K_SH_DEL, K_ALT_DEL}, /* 17 */
{K_HOME, K_ALT_HOME, K_CTRL_HOME, K_SH_HOME, K_ALT_HOME}, /* 18 */
{K_END, K_ALT_END, K_CTRL_END, K_SH_END, K_ALT_END}, /* 19 */
{K_PGUP, K_ALT_PGUP, K_CTRL_PGUP, K_SH_PGUP, K_ALT_PGUP}, /* 20 */
{K_PGDN, K_ALT_PGDN, K_CTRL_PGDN, K_SH_PGDN, K_ALT_PGDN}, /* 21 */
{K_BS, K_ALT_BS, 127, 0, K_ALT_BS}, /* 22 */
{K_TAB, K_ALT_TAB, K_CTRL_TAB, K_SH_TAB, K_ALT_TAB}, /* 23 */
{K_ESC, K_ALT_ESC, K_ESC, 0, K_ALT_TAB}, /* 24 */
{K_ENTER, K_ALT_ENTER, K_CTRL_ENTER,K_SH_ENTER, K_ALT_ENTER}, /* 25 */
{K_ENTER, KP_ALT_ENTER, K_CTRL_ENTER, 0,KP_ALT_ENTER}, /* 26 */
{KP_CENTER, 0, KP_CTRL_5, 0, 0}, /* 27 */
{0, 0, K_CTRL_PRTSCR, 0, 0}, /* 28 */
{0, 0, HB_BREAK_FLAG, 0, 0}, /* 29 */
/* under win98 it seems that these keypad keys are 'enhanced' */
{42, KP_ALT_ASTERISK,KP_CTRL_ASTERISK, 0,KP_ALT_ASTERISK}, /* 30 */
{43, KP_ALT_PLUS, KP_CTRL_PLUS, 0, KP_ALT_PLUS}, /* 31 */
{45, KP_ALT_MINUS, KP_CTRL_MINUS, 0,KP_ALT_MINUS}, /* 32 */
{47, KP_ALT_SLASH, KP_CTRL_SLASH, 0,KP_ALT_SLASH} /* 33 */
};
/* *********************************************************************** */
static void hb_gt_win_xSetCursorPos( void )
{
HB_TRACE(HB_TR_DEBUG, ("hb_gt_win_xSetCursorPos()"));
s_csbi.dwCursorPosition.Y = s_sCurRow;
s_csbi.dwCursorPosition.X = s_sCurCol;
SetConsoleCursorPosition( s_HOutput, s_csbi.dwCursorPosition );
}
/* *********************************************************************** */
static void hb_gt_win_xSetCursorStyle( void )
{
CONSOLE_CURSOR_INFO cci;
HB_TRACE(HB_TR_DEBUG, ("hb_gt_win_xSetCursorStyle()"));
switch( s_usCursorStyle )
{
case SC_NONE:
cci.bVisible = FALSE;
cci.dwSize = 13;
break;
case SC_INSERT:
cci.bVisible = TRUE;
cci.dwSize = 50;
break;
case SC_SPECIAL1:
cci.bVisible = TRUE;
cci.dwSize = 99;
break;
case SC_SPECIAL2:
cci.bVisible = TRUE;
cci.dwSize = 66;
/* In their infinite wisdom, MS doesn't support cursors that
don't start at the bottom of the cell */
break;
case SC_NORMAL:
default:
cci.bVisible = TRUE;
cci.dwSize = 13;
break;
}
s_usOldCurStyle = s_usCursorStyle;
SetConsoleCursorInfo( s_HOutput, &cci );
}
/* *********************************************************************** */
static void hb_gt_win_xScreenUpdate( void )
{
HB_TRACE(HB_TR_DEBUG, ("hb_gt_win_xScreenUpdate()"));
if( s_pCharInfoScreen != NULL )
{
if( s_uiDispCount == 0 && s_usUpdtTop <= s_usUpdtBottom )
{
COORD coDest, coSize;
SMALL_RECT srWin;
coSize.Y = _GetScreenHeight();
coSize.X = _GetScreenWidth();
coDest.Y = s_usUpdtTop;
coDest.X = s_usUpdtLeft;
srWin.Top = ( SHORT ) s_usUpdtTop;
srWin.Left = ( SHORT ) s_usUpdtLeft;
srWin.Bottom = ( SHORT ) s_usUpdtBottom;
srWin.Right = ( SHORT ) s_usUpdtRight;
s_usUpdtTop = _GetScreenHeight();
s_usUpdtLeft = _GetScreenWidth();
s_usUpdtBottom = s_usUpdtRight = 0;
WriteConsoleOutput( s_HOutput, /* output handle */
s_pCharInfoScreen, /* data to write */
coSize, /* col/row size of source buffer */
coDest, /* upper-left cell to write data from in src */
&srWin ); /* screen buffer rect to write data to */
}
if( s_usOldCurStyle != s_usCursorStyle &&
( s_uiDispCount == 0 || s_usCursorStyle == SC_NONE ) )
hb_gt_win_xSetCursorStyle();
if( s_usCursorStyle != SC_NONE && s_uiDispCount == 0 &&
( s_csbi.dwCursorPosition.Y != s_sCurRow ||
s_csbi.dwCursorPosition.X != s_sCurCol ) )
hb_gt_win_xSetCursorPos();
}
}
/* *********************************************************************** */
static void hb_gt_win_xUpdtSet( USHORT usTop, USHORT usLeft, USHORT usBottom, USHORT usRight )
{
HB_TRACE(HB_TR_DEBUG, ("hb_gt_win_xUpdtSet(%hu, %hu, %hu, %hu)", usTop, usLeft, usBottom, usRight));
if( usTop < s_usUpdtTop )
s_usUpdtTop = usTop;
if( usLeft < s_usUpdtLeft )
s_usUpdtLeft = usLeft;
if( usBottom > s_usUpdtBottom )
s_usUpdtBottom = HB_MIN( usBottom, ( USHORT ) _GetScreenHeight() - 1 );
if( usRight > s_usUpdtRight )
s_usUpdtRight = HB_MIN( usRight, ( USHORT ) _GetScreenWidth() - 1 );
}
/* *********************************************************************** */
static BOOL WINAPI hb_gt_win_CtrlHandler( DWORD dwCtrlType )
{
BOOL bHandled;
HB_TRACE(HB_TR_DEBUG, ("hb_gt_win_CtrlHandler(%lu)", ( ULONG ) dwCtrlType));
switch( dwCtrlType )
{
case CTRL_C_EVENT:
bHandled = FALSE;
break;
case CTRL_CLOSE_EVENT:
case CTRL_BREAK_EVENT:
s_bBreak = TRUE;
bHandled = TRUE;
break;
case CTRL_LOGOFF_EVENT:
case CTRL_SHUTDOWN_EVENT:
default:
#if 0
printf(" Event %ld ", dwCtrlType );
#endif
bHandled = FALSE;
}
return bHandled;
}
/* *********************************************************************** */
static void hb_gt_win_xGetScreenContents( PHB_GT pGT, SMALL_RECT * psrWin )
{
int iRow, iCol, i;
HB_TRACE(HB_TR_DEBUG, ("hb_gt_win_xGetScreenContents(%p,%p)", pGT, psrWin));
for( iRow = psrWin->Top; iRow <= psrWin->Bottom; ++iRow )
{
i = iRow * _GetScreenWidth() + psrWin->Left;
for( iCol = psrWin->Left; iCol <= psrWin->Right; ++iCol )
{
HB_GTSELF_PUTSCRCHAR( pGT, iRow, iCol, ( BYTE ) s_pCharInfoScreen[i].Attributes, 0,
s_charTransRev[ ( BYTE ) s_pCharInfoScreen[i].Char.AsciiChar ] );
++i;
}
}
HB_GTSELF_COLDAREA( pGT, psrWin->Top, psrWin->Left, psrWin->Bottom, psrWin->Right );
}
/* *********************************************************************** */
static void hb_gt_win_xInitScreenParam( PHB_GT pGT )
{
HB_TRACE(HB_TR_DEBUG, ("hb_gt_win_xInitScreenParam(%p)", pGT));
if( GetConsoleScreenBufferInfo( s_HOutput, &s_csbi ) )
{
COORD coDest;
SMALL_RECT srWin;
ULONG ulSize = ( ULONG ) _GetScreenWidth() * _GetScreenHeight() *
sizeof( CHAR_INFO );
HB_GTSELF_RESIZE( pGT, _GetScreenHeight(), _GetScreenWidth() );
if( s_pCharInfoScreen == NULL || ulSize != s_ulScreenBuffSize )
{
if( s_pCharInfoScreen != NULL )
hb_xfree( s_pCharInfoScreen );
s_ulScreenBuffSize = ulSize;
s_pCharInfoScreen = ( CHAR_INFO * ) hb_xgrab( s_ulScreenBuffSize );
}
s_sCurRow = s_csbi.dwCursorPosition.Y;
s_sCurCol = s_csbi.dwCursorPosition.X;
s_usUpdtTop = s_csbi.dwSize.Y;
s_usUpdtLeft = s_csbi.dwSize.X;
s_usUpdtBottom = s_usUpdtRight = 0;
/*
* Unfortunatelly Windows refuse to read to big area :-(
* (I do not know why) so we cannot read the whole console
* buffer { 0, 0, s_csbi.dwSize.Y - 1, s_csbi.dwSize.X - 1 }
* because it reads nothing, [druzus]
*/
#if 0
srWin.Top = 0;
srWin.Left = 0;
srWin.Bottom = s_csbi.dwSize.Y - 1;
srWin.Right = s_csbi.dwSize.X - 1;
#else
srWin.Top = s_csbi.srWindow.Top;
srWin.Left = s_csbi.srWindow.Left;
srWin.Bottom = s_csbi.srWindow.Bottom;
srWin.Right = s_csbi.srWindow.Right;
#endif
coDest.Y = srWin.Top;
coDest.X = srWin.Left;
/* read the screen rectangle into the buffer */
if( ReadConsoleOutput( s_HOutput, /* screen handle */
s_pCharInfoScreen, /* transfer area */
s_csbi.dwSize, /* size of destination buffer */
coDest, /* upper-left cell to write data to */
&srWin ) ) /* screen buffer rectangle to read from */
{
hb_gt_win_xGetScreenContents( pGT, &srWin );
}
HB_GTSELF_SETPOS( pGT, s_sCurRow, s_sCurCol );
}
else if( s_pCharInfoScreen != NULL )
{
hb_xfree( s_pCharInfoScreen );
s_ulScreenBuffSize = 0;
}
}
/* *********************************************************************** */
static void hb_gt_win_Init( PHB_GT pGT, FHANDLE hFilenoStdin, FHANDLE hFilenoStdout, FHANDLE hFilenoStderr )
{
HB_TRACE(HB_TR_DEBUG, ("hb_gt_win_Init(%p,%p,%p,%p)", pGT, hFilenoStdin, hFilenoStdout, hFilenoStderr));
s_osv.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
GetVersionEx( &s_osv );
if( s_osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )
{
s_dwAltGrBits = RIGHT_ALT_PRESSED;
}
else
{
s_dwAltGrBits = LEFT_CTRL_PRESSED | RIGHT_ALT_PRESSED;
}
/* stdin && stdout && stderr */
s_hStdIn = hFilenoStdin;
s_hStdOut = hFilenoStdout;
s_hStdErr = hFilenoStderr;
s_bBreak = FALSE;
s_cNumRead = 0;
s_cNumIndex = 0;
s_uiDispCount = 0;
s_usOldCurStyle = s_usCursorStyle = SC_NORMAL;
s_bSpecialKeyHandling = FALSE;
s_bAltKeyHandling = TRUE;
/* initialize code page translation */
HB_GTSELF_SETDISPCP( pGT, NULL, NULL, FALSE );
HB_GTSELF_SETKEYCP( pGT, NULL, NULL );
/* Add Ctrl+Break handler [vszakats] */
SetConsoleCtrlHandler( hb_gt_win_CtrlHandler, TRUE );
#ifndef HB_NO_ALLOC_CONSOLE
/*
* This is a hack for MSYS console. It does not support full screen output
* so nothing can be seen on the screen and we have to close the MSYS
* console to be able to allocate the MS-Windows one.
* Unfortunatelly I do not know any method to detect the MSYS console
* so I used this hack with checking OSTYPE environemnt variable. [druzus]
*/
{
char * pszOsType;
pszOsType = hb_getenv( "OSTYPE" );
if( pszOsType )
{
if( strcmp( pszOsType, "msys" ) == 0 )
FreeConsole();
hb_xfree( pszOsType );
}
}
/* Try to allocate console if we haven't inherited any */
AllocConsole();
#endif
if( ( s_HInput = GetStdHandle( STD_INPUT_HANDLE ) ) == INVALID_HANDLE_VALUE )
{
#ifdef HB_NO_ALLOC_CONSOLE
/* allocate console only when debugger is linked */
if( hb_dynsymFind( "__DBGENTRY" ) )
{
AllocConsole(); /* It is a Windows app without a console, so we create one */
s_HInput = GetStdHandle( STD_INPUT_HANDLE );
}
#endif
if( s_HInput == INVALID_HANDLE_VALUE )
{
hb_errInternal( 10001, "Can't allocate console", NULL, NULL );
}
}
HB_GTSUPER_INIT( pGT, hFilenoStdin, hFilenoStdout, hFilenoStderr );
s_HOutput = CreateFile( TEXT( "CONOUT$" ), /* filename */
GENERIC_READ | GENERIC_WRITE, /* Access flag */
FILE_SHARE_READ | FILE_SHARE_WRITE, /* share mode */
NULL, /* security attributes */
OPEN_EXISTING, /* create mode */
0, 0 );
if( s_HOutput == INVALID_HANDLE_VALUE )
hb_errInternal( 10001, "Can't allocate console (output)", NULL, NULL );
s_HInput = CreateFile( TEXT( "CONIN$" ), /* filename */
GENERIC_READ | GENERIC_WRITE, /* Access flag */
FILE_SHARE_READ | FILE_SHARE_WRITE, /* share mode */
NULL, /* security attributes */
OPEN_EXISTING, /* create mode */
0, 0 );
if( s_HInput == INVALID_HANDLE_VALUE )
hb_errInternal( 10001, "Can't allocate console (input)", NULL, NULL );
GetConsoleScreenBufferInfo( s_HOutput, &s_csbi );
/* save screen info to restore on exit */
memcpy( &s_origCsbi, &s_csbi, sizeof( s_csbi ) );
s_csbi.srWindow.Top = s_csbi.srWindow.Left = 0;
s_csbi.srWindow.Right = HB_MIN( s_csbi.srWindow.Right, _GetScreenWidth()-1 );
s_csbi.srWindow.Bottom = HB_MIN( s_csbi.srWindow.Bottom, _GetScreenHeight()-1 );
SetConsoleWindowInfo( s_HOutput, TRUE, &s_csbi.srWindow );
SetConsoleScreenBufferSize( s_HOutput, s_csbi.dwSize );
hb_gt_win_xInitScreenParam( pGT );
GetConsoleMode( s_HOutput, &s_dwomode );
GetConsoleMode( s_HInput, &s_dwimode );
SetConsoleMode( s_HInput, b_MouseEnable ? ENABLE_MOUSE_INPUT : 0x0000 );
}
/* *********************************************************************** */
static void hb_gt_win_Exit( PHB_GT pGT )
{
HB_TRACE(HB_TR_DEBUG, ("hb_gt_win_Exit(%p)", pGT));
HB_GTSELF_REFRESH( pGT );
if( s_pCharInfoScreen != NULL )
{
hb_xfree( s_pCharInfoScreen );
s_pCharInfoScreen = NULL;
}
if( s_HOutput != INVALID_HANDLE_VALUE )
{
SetConsoleScreenBufferSize( s_HOutput, s_origCsbi.dwSize );
s_origCsbi.srWindow.Right -= s_origCsbi.srWindow.Left;
s_origCsbi.srWindow.Bottom -= s_origCsbi.srWindow.Top;
s_origCsbi.srWindow.Top = s_origCsbi.srWindow.Left = 0;
SetConsoleWindowInfo( s_HOutput, TRUE, &s_origCsbi.srWindow );
CloseHandle( s_HOutput );
}
/* Remove Ctrl+Break handler */
SetConsoleCtrlHandler( hb_gt_win_CtrlHandler, FALSE );
HB_GTSUPER_EXIT( pGT );
}
/* *********************************************************************** */
static BOOL hb_gt_win_SetMode( PHB_GT pGT, int iRows, int iCols )
{
BOOL fRet = FALSE;
HB_TRACE(HB_TR_DEBUG, ("hb_gt_win_SetMode(%p,%d,%d)", pGT, iRows, iCols));
if( s_HOutput != INVALID_HANDLE_VALUE && iRows > 0 && iCols > 0 )
{
SMALL_RECT srWin;
COORD coBuf;
coBuf = GetLargestConsoleWindowSize( s_HOutput );
if( iRows > coBuf.Y )
iRows = coBuf.Y;
else
coBuf.Y = iRows;
if( iCols > coBuf.X )
iCols = coBuf.X;
else
coBuf.X = iCols;
/* new console window size and scroll position */
srWin.Top = srWin.Left = 0;
srWin.Bottom = ( SHORT ) ( iRows - 1 );
srWin.Right = ( SHORT ) ( iCols - 1 );
/* if the current buffer is larger than what we want, resize the */
/* console window first, then the buffer */
if( ( DWORD ) _GetScreenWidth() * _GetScreenHeight() > ( DWORD ) iCols * iRows )
{
if( SetConsoleWindowInfo( s_HOutput, TRUE, &srWin ) )
{
SetConsoleScreenBufferSize( s_HOutput, coBuf );
fRet = TRUE;
}
}
else
{
if( SetConsoleScreenBufferSize( s_HOutput, coBuf ) )
{
SetConsoleWindowInfo( s_HOutput, TRUE, &srWin );
fRet = TRUE;
}
}
if( fRet )
hb_gt_win_xInitScreenParam( pGT );
}
return fRet;
}
/* *********************************************************************** */
static char * hb_gt_win_Version( PHB_GT pGT, int iType )
{
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_win_Version(%p,%d)", pGT, iType ) );
HB_SYMBOL_UNUSED( pGT );
if( iType == 0 )
return HB_GT_DRVNAME( HB_GT_NAME );
return "Harbour Terminal: Windows native console";
}
/* *********************************************************************** */
static BOOL hb_gt_win_PostExt( PHB_GT pGT )
{
HB_TRACE(HB_TR_DEBUG, ("hb_gt_win_PostExt(%p)", pGT));
HB_GTSUPER_POSTEXT( pGT );
if( s_pCharInfoScreen )
hb_gt_win_xInitScreenParam( pGT );
return TRUE;
}
/* *********************************************************************** */
static BOOL hb_gt_win_Suspend( PHB_GT pGT )
{
HB_TRACE(HB_TR_DEBUG, ("hb_gt_win_Suspend(%p)", pGT));
HB_SYMBOL_UNUSED( pGT );
if( s_pCharInfoScreen )
{
SetConsoleCtrlHandler( hb_gt_win_CtrlHandler, FALSE );
SetConsoleCtrlHandler( NULL, TRUE );
SetConsoleMode( s_HOutput, s_dwomode );
SetConsoleMode( s_HInput, s_dwimode );
}
return TRUE;
}
static BOOL hb_gt_win_Resume( PHB_GT pGT )
{
HB_TRACE(HB_TR_DEBUG, ("hb_gt_win_Resume(%p)", pGT));
if( s_pCharInfoScreen )
{
SetConsoleCtrlHandler( NULL, FALSE );
SetConsoleCtrlHandler( hb_gt_win_CtrlHandler, TRUE );
SetConsoleMode( s_HOutput, s_dwomode );
SetConsoleMode( s_HInput, b_MouseEnable ? ENABLE_MOUSE_INPUT : 0x0000 );
hb_gt_win_xInitScreenParam( pGT );
hb_gt_win_xSetCursorStyle();
}
return TRUE;
}
/* *********************************************************************** */
static int Handle_Alt_Key( int * paltisdown, int * paltnum, unsigned short wKey, int ch )
{
if( s_irInBuf[ s_cNumIndex ].Event.KeyEvent.bKeyDown )
{
/*
on Keydown, it better be the alt or a numpad key,
or bail out.
*/
switch(wKey)
{
case 0x38:
case 0x47:
case 0x48:
case 0x49:
case 0x4b:
case 0x4c:
case 0x4d:
case 0x4f:
case 0x50:
case 0x51:
case 0x52:
break;
default:
*paltisdown=0;
break;
}
}
else
{
/* Keypad handling is done during Key up */
unsigned short nm = 10;
switch(wKey)
{
case 0x38:
/* Alt key ... */
#if 0
printf( " the state %ld ",s_irInBuf[ s_cNumIndex ].Event.KeyEvent.dwControlKeyState );
#endif
if( s_irInBuf[ s_cNumIndex ].Event.KeyEvent.dwControlKeyState &
0x04000000 )
/* ... has been released after a numpad entry */
{
ch = *paltnum & 0xff;
++s_cNumIndex;
}
else
/* ... has been released after no numpad entry */
{
s_irInBuf[ s_cNumIndex ].Event.KeyEvent.bKeyDown = 1;
}
*paltisdown = *paltnum = 0;
break;
case 0x52: --nm;
case 0x4f: --nm;
case 0x50: --nm;
case 0x51: --nm;
case 0x4b: --nm;
case 0x4c: --nm;
case 0x4d: --nm;
case 0x47: --nm;
case 0x48: --nm;
case 0x49: --nm;
*paltnum = ((*paltnum * 10) & 0xff) + nm;
break;
default:
*paltisdown = 0;
break;
}
}
return ch;
}
static int SpecialHandling( WORD * wChar, unsigned short wKey, int ch, BOOL lReverse )
{
if( lReverse )
{
switch( wKey )
{
case 2: /* 1 to 9 */
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
ch = wKey + 31;
break;
case 11: /* 0 */
ch = 41;
break;
case 12: /* - */
ch = 95;
break;
case 13: /* = */
ch = 43;
break;
case 26: /* [ */
ch = 123;
break;
case 27: /* ] */
ch = 125;
break;
case 39: /* ; */
ch = 58;
break;
case 40: /* ' */
ch = 34;
break;
case 41: /* ` */
ch = 126;
break;
case 43: /* \ */
ch = 124;
break;
case 51: /* , */
ch = 60;
break;
case 52: /* . */
ch = 62;
break;
case 53: /* / */
ch = 63;
break;
default:
break;
}
}
else
{
switch( wKey )
{
case 2: /* 1 to 9 */
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
*wChar = ch = wKey + 47;
break;
case 11: /* 0 */
*wChar = ch = 48;
break;
case 12: /* - */
ch = 45;
break;
case 13: /* = */
*wChar = ch = 61;
break;
case 26: /* [ */
*wChar = ch = 91;
break;
case 27: /* ] */
*wChar = ch = 93;
break;
case 39: /* ; */
*wChar = ch = 59;
break;
case 40: /* ' */
ch = 39;
break;
case 41: /* ` */
*wChar = ch = 96;
break;
case 43: /* \ */
*wChar = ch = 92;
break;
case 51: /* , */
*wChar = ch = 44;
break;
case 52: /* . */
*wChar = ch = 46;
break;
case 53: /* / */
ch = 47;
break;
default:
break;
}
}
return ch;
}
static int hb_gt_win_ReadKey( PHB_GT pGT, int iEventMask )
{
int ch = 0,
extKey = -1;
const ClipKeyCode *clipKey = NULL;
HB_TRACE(HB_TR_DEBUG, ("hb_gt_win_ReadKey(%p,%d)", pGT, iEventMask));
HB_SYMBOL_UNUSED( pGT );
/* First check for Ctrl+Break, which is handled by gt/gtwin.c */
if( s_bBreak )
{
/* Reset the global Ctrl+Break flag */
s_bBreak = FALSE;
ch = HB_BREAK_FLAG; /* Indicate that Ctrl+Break was pressed */
}
/* Check for events only when the event buffer is exhausted. */
else if( s_wRepeated == 0 && s_cNumRead <= s_cNumIndex )
{
/* Check for keyboard input */
s_cNumRead = 0;
GetNumberOfConsoleInputEvents( s_HInput, &s_cNumRead );
if( s_cNumRead )
{
/* Read keyboard input */
ReadConsoleInput( s_HInput, /* input buffer handle */
s_irInBuf, /* buffer to read into */
INPUT_BUFFER_LEN, /* size of read buffer */
&s_cNumRead); /* number of records read */
/* Set up to process the first input event */
s_cNumIndex = 0;
if( s_irInBuf[ s_cNumIndex ].EventType == KEY_EVENT )
{
unsigned short wKey = s_irInBuf[ s_cNumIndex ].Event.KeyEvent.wVirtualScanCode;
#if 0
if( s_irInBuf[ s_cNumIndex ].Event.KeyEvent.bKeyDown )
{
printf("\n scan %ld key %ld char %ld state %ld alt %d %d %d %d %d",
wKey, /* scan code */
s_irInBuf[ s_cNumIndex ].Event.KeyEvent.wVirtualKeyCode, /* key code */
s_irInBuf[ s_cNumIndex ].Event.KeyEvent.uChar.AsciiChar, /* char */
s_irInBuf[ s_cNumIndex ].Event.KeyEvent.dwControlKeyState, /* state */
s_altisdown, s_wRepeated, s_cNumRead, s_cNumIndex, (int) s_bAltKeyHandling);
}
#endif
if( s_bAltKeyHandling )
{
if( s_altisdown )
{
ch = Handle_Alt_Key( &s_altisdown, &s_altnum, wKey, ch );
}
else
{
if( wKey == 0x38 &&
s_irInBuf[ s_cNumIndex ].Event.KeyEvent.bKeyDown &&
( s_irInBuf[ s_cNumIndex ].Event.KeyEvent.dwControlKeyState
& NUMLOCK_ON ) )
{
s_altisdown = 1;
}
}
}
}
}
}
/* Only process one keyboard event at a time. */
if( s_wRepeated > 0 || s_cNumRead > s_cNumIndex )
{
#if 0
printf( " event %ld ",s_irInBuf[ s_cNumIndex ].EventType );
#endif
if( s_irInBuf[ s_cNumIndex ].EventType == KEY_EVENT )
{
/* Only process key down events */
if( s_irInBuf[ s_cNumIndex ].Event.KeyEvent.bKeyDown )
{
/* Save the keyboard state and ASCII,scan, key code */
WORD wKey = s_irInBuf[ s_cNumIndex ].Event.KeyEvent.wVirtualScanCode;
WORD wChar = s_irInBuf[ s_cNumIndex ].Event.KeyEvent.wVirtualKeyCode;
DWORD dwState= s_irInBuf[ s_cNumIndex ].Event.KeyEvent.dwControlKeyState;
ch = s_irInBuf[ s_cNumIndex ].Event.KeyEvent.uChar.AsciiChar;
/*
* Under Win9x, Upper row keys are affected by caps-lock
* and should not be. There are 2 solutions - the first
* is to enable the calling of SpecialHandling below - which
* will only be activated under Win9x (Preferrably under user
* control, since they know if their keyboard isn't working), or
* just enable KeyB handling in config.sys, and do not enable the
* following call.
* 2004-11-26 Vicente Guerra
* (With some clarification by Paul Tucker)
* If making this fix the default under Win98, then it doesn't
* work for non-US keyboards. (The default has now been changed)
* I tried to replicate the problem under Win98SE (spanish),
* but it works fine. I hope someone could tell me how the
* problem appears, for try to fix it.
* "Microsoft has confirmed this to be a bug in the Microsoft
* products " Windows 95 & Windows 98 (According to MSDN)
*
*/
if( s_bSpecialKeyHandling &&
( dwState & CAPSLOCK_ON ) &&
s_osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )
{
ch = SpecialHandling( &wChar, wKey, ch, (dwState & SHIFT_PRESSED) );
}
if( s_wRepeated == 0 )
{
s_wRepeated = s_irInBuf[ s_cNumIndex ].Event.KeyEvent.wRepeatCount;
}
if( s_wRepeated > 0 ) /* Might not be redundant */
{
s_wRepeated--;
}
#if 0
printf( "\n\nhb_gt_ReadKey(): dwState is %ld, wChar is %d, wKey is %d, ch is %d", dwState, wChar, wKey, ch );
#endif
if( wChar == 8 ) /* VK_BACK */
{
extKey = EXKEY_BS;
}
else if( wChar == 9 ) /* VK_TAB */
{
extKey = EXKEY_TAB;
}
else if( wChar == 13 ) /* VK_RETURN */
{
extKey = EXKEY_ENTER;
}
else if( wChar == 27 ) /* VK_ESCAPE */
{
extKey = EXKEY_ESC;
}
else if( wChar == 33 ) /* VK_PRIOR */
{
extKey = EXKEY_PGUP;
}
else if( wChar == 34 ) /* VK_NEXT */
{
extKey = EXKEY_PGDN;
}
else if( wChar == 35 ) /* VK_END */
{
extKey = EXKEY_END;
}
else if( wChar == 36 ) /* VK_HOME */
{
extKey = EXKEY_HOME;
}
else if( wChar == 37 ) /* VK_LEFT */
{
extKey = EXKEY_LEFT;
}
else if( wChar == 38 ) /* VK_UP */
{
extKey = EXKEY_UP;
}
else if( wChar == 39 ) /* VK_RIGHT */
{
extKey = EXKEY_RIGHT;
}
else if( wChar == 40 ) /* VK_DOWN */
{
extKey = EXKEY_DOWN;
}
else if( wChar == 45 ) /* VK_INSERT */
{
extKey = EXKEY_INS;
}
else if( wChar == 46 && (!(ch==46)) ) /* VK_DELETE */
{
/* International keyboard under Win98 - when VirtualKey and Ascii
char are both 46, then it's keypad del key, but numlock is on,
so treat as '.' else DEL
*/
extKey = EXKEY_DEL;
}
else if( wChar == 191 && ch == 63 && ( dwState & ENHANCED_KEY ))
{ /* numpad '/' always */
/* This is the Win98 test */
ch = 47;
}
else if( wChar == 106 ) /* VK_MULTIPLY */
{
extKey = EXKEY_KPASTERISK;
}
else if( wChar == 107 ) /* VK_ADD */
{
extKey = EXKEY_KPPLUS;
}
else if( wChar == 109 ) /* VK_SUBTRACT */
{
extKey = EXKEY_KPMINUS;
}
else if( wChar == 111 || /* VK_DIVIDE */
( wChar == 191 && ( dwState & ENHANCED_KEY )))
{
/* This should be for other than Win98 */
extKey = EXKEY_KPDIVIDE;
}
else if( wChar >= 112 && wChar <= 123 ) /* F1-F12 VK_F1-VK_F12 */
{
extKey = wChar - 112;
}
else if( ch >= K_SPACE && ch <= K_CTRL_BS )
{
clipKey = &stdKeyTab[ ch - K_SPACE ];
}
else if( ch > 0 && ch < K_SPACE && ( dwState & ( LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED ) ) )
{
clipKey = &stdKeyTab[ ch + '@' ];
}
else if( ch < 0 ) /* international keys */
{
ch += 256;
}
if( extKey > -1 )
{
clipKey = &extKeyTab[ extKey ];
}
if( clipKey != NULL )
{
if( ( dwState & SHIFT_PRESSED ) && ( dwState & ( LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED ) ) )
{
if( clipKey->key == K_TAB )
{
ch = K_CTRL_SH_TAB;
}
}
else if( dwState & LEFT_ALT_PRESSED )
{
ch = clipKey->alt_key;
}
else if( dwState & RIGHT_ALT_PRESSED )
{
ch = clipKey->altgr_key;
}
else if( dwState & ( LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED ) )
{
ch = clipKey->ctrl_key;
}
else if( dwState & SHIFT_PRESSED )
{
ch = clipKey->shift_key;
}
else
{
ch = clipKey->key;
}
if( ch == 0 ) /* for keys that are only on shift or AltGr */
{
ch = clipKey->key;
}
}
/* national codepage translation */
if( ch > 0 && ch <= 255 )
{
ch = s_keyTrans[ ch ];
}
}
}
else if( b_MouseEnable &&
s_irInBuf[ s_cNumIndex ].EventType == MOUSE_EVENT &&
iEventMask & ~( INKEY_KEYBOARD | INKEY_RAW ) )
{
hb_mouse_iCol = s_irInBuf[ s_cNumIndex ].Event.MouseEvent.dwMousePosition.X;
hb_mouse_iRow = s_irInBuf[ s_cNumIndex ].Event.MouseEvent.dwMousePosition.Y;
if( iEventMask & INKEY_MOVE &&
s_irInBuf[ s_cNumIndex ].Event.MouseEvent.dwEventFlags == MOUSE_MOVED )
{
ch = K_MOUSEMOVE;
}
else if( iEventMask & INKEY_MWHEEL &&
s_irInBuf[ s_cNumIndex ].Event.MouseEvent.dwEventFlags == MOUSE_WHEELED )
{
ch = s_irInBuf[ s_cNumIndex ].Event.MouseEvent.dwButtonState & 0xFF000000 ?
K_MWBACKWARD : K_MWFORWARD;
}
else if( iEventMask & INKEY_LDOWN &&
s_irInBuf[ s_cNumIndex ].Event.MouseEvent.dwButtonState &
FROM_LEFT_1ST_BUTTON_PRESSED )
{
ch = s_irInBuf[ s_cNumIndex ].Event.MouseEvent.dwEventFlags == DOUBLE_CLICK ?
K_LDBLCLK : K_LBUTTONDOWN;
s_mouseLast = K_LBUTTONDOWN;
}
else if( iEventMask & INKEY_RDOWN &&
s_irInBuf[ s_cNumIndex ].Event.MouseEvent.dwButtonState &
RIGHTMOST_BUTTON_PRESSED )
{
ch = s_irInBuf[ s_cNumIndex ].Event.MouseEvent.dwEventFlags == DOUBLE_CLICK ?
K_RDBLCLK : K_RBUTTONDOWN;
s_mouseLast = K_RBUTTONDOWN;
}
else if( s_irInBuf[ s_cNumIndex ].Event.MouseEvent.dwEventFlags == 0 &&
s_irInBuf[ s_cNumIndex ].Event.MouseEvent.dwButtonState == 0 )
{
if( iEventMask & INKEY_LUP && s_mouseLast == K_LBUTTONDOWN )
{
ch = K_LBUTTONUP;
s_mouseLast = 0;
}
else if( iEventMask & INKEY_RUP && s_mouseLast == K_RBUTTONDOWN )
{
ch = K_RBUTTONUP;
s_mouseLast = 0;
}
}
}
/* Set up to process the next input event (if any) */
if( s_wRepeated == 0 )
{
s_cNumIndex++;
}
}
#if 0
if( ch )
{
printf(" %ld:%ld",ch,extKey);
}
#endif
return ch;
}
/* *********************************************************************** */
/* *********************************************************************** */
/* dDuration is in 'Ticks' (18.2 per second) */
static void hb_gt_win_Tone( PHB_GT pGT, double dFrequency, double dDuration )
{
HB_TRACE(HB_TR_DEBUG, ("hb_gt_win_Tone(%p,%lf,%lf)", pGT, dFrequency, dDuration));
HB_SYMBOL_UNUSED( pGT );
hb_gt_w32_tone( dFrequency, dDuration );
}
/* *********************************************************************** */
static BOOL hb_gt_win_SetDispCP( PHB_GT pGT, char *pszTermCDP, char *pszHostCDP, BOOL fBox )
{
int i;
HB_TRACE(HB_TR_DEBUG, ("hb_gt_win_SetDispCP(%p,%s,%s,%d)", pGT, pszTermCDP, pszHostCDP, (int) fBox));
HB_GTSUPER_SETDISPCP( pGT, pszTermCDP, pszHostCDP, fBox );
for( i = 0; i < 256; i++ )
s_charTrans[ i ] = ( BYTE ) i;
#ifndef HB_CDP_SUPPORT_OFF
if( !pszHostCDP )
pszHostCDP = hb_cdp_page->id;
if( pszTermCDP && pszHostCDP )
{
PHB_CODEPAGE cdpTerm = hb_cdpFind( pszTermCDP ),
cdpHost = hb_cdpFind( pszHostCDP );
if( cdpTerm && cdpHost && cdpTerm != cdpHost &&
cdpTerm->nChars && cdpTerm->nChars == cdpHost->nChars )
{
for( i = 0; i < cdpHost->nChars; ++i )
{
s_charTrans[ ( BYTE ) cdpHost->CharsUpper[ i ] ] =
( BYTE ) cdpTerm->CharsUpper[ i ];
s_charTrans[ ( BYTE ) cdpHost->CharsLower[ i ] ] =
( BYTE ) cdpTerm->CharsLower[ i ];
}
}
}
#endif
for( i = 0; i < 256; i++ )
s_charTransRev[ s_charTrans[ i ] ] = ( BYTE ) i;
return TRUE;
}
/* *********************************************************************** */
static BOOL hb_gt_win_SetKeyCP( PHB_GT pGT, char *pszTermCDP, char *pszHostCDP )
{
int i;
HB_TRACE(HB_TR_DEBUG, ("hb_gt_win_SetKeyCP(%p,%s,%s)", pGT, pszTermCDP, pszHostCDP));
HB_GTSUPER_SETKEYCP( pGT, pszTermCDP, pszHostCDP );
for( i = 0; i < 256; i++ )
s_keyTrans[ i ] = ( BYTE ) i;
#ifndef HB_CDP_SUPPORT_OFF
if( !pszHostCDP )
{
pszHostCDP = hb_cdp_page->id;
}
if( pszTermCDP && pszHostCDP )
{
PHB_CODEPAGE cdpTerm = hb_cdpFind( pszTermCDP ),
cdpHost = hb_cdpFind( pszHostCDP );
if( cdpTerm && cdpHost && cdpTerm != cdpHost &&
cdpTerm->nChars && cdpTerm->nChars == cdpHost->nChars )
{
for( i = 0; i < cdpHost->nChars; ++i )
{
s_keyTrans[ ( BYTE ) cdpHost->CharsUpper[ i ] ] =
( BYTE ) cdpTerm->CharsUpper[ i ];
s_keyTrans[ ( BYTE ) cdpHost->CharsLower[ i ] ] =
( BYTE ) cdpTerm->CharsLower[ i ];
}
}
}
#endif
return TRUE;
}
/* *********************************************************************** */
static BOOL hb_gt_win_Info( PHB_GT pGT, int iType, PHB_GT_INFO pInfo )
{
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_win_Info(%p,%d,%p)", pGT, iType, pInfo ) );
switch( iType )
{
case HB_GTI_FULLSCREEN:
case HB_GTI_KBDSUPPORT:
pInfo->pResult = hb_itemPutL( pInfo->pResult, TRUE );
break;
case HB_GTI_WINTITLE:
{
TCHAR buff[ 256 ];
char * szTitle;
DWORD dwLen;
dwLen = GetConsoleTitle( buff, sizeof( buff ) / sizeof( TCHAR ) );
szTitle = ( char * ) hb_xgrab( dwLen + 1 );
HB_TCHAR_GETFROM( szTitle, buff, dwLen );
pInfo->pResult = hb_itemPutCLPtr( pInfo->pResult, szTitle, dwLen );
if( hb_itemType( pInfo->pNewVal ) & HB_IT_STRING )
{
LPTSTR lpTitle = HB_TCHAR_CONVTO( hb_itemGetCPtr( pInfo->pNewVal ) );
SetConsoleTitle( lpTitle );
HB_TCHAR_FREE( lpTitle );
}
break;
}
case HB_GTI_VIEWMAXHEIGHT:
{
COORD coBuf = GetLargestConsoleWindowSize( s_HOutput );
pInfo->pResult = hb_itemPutNI( pInfo->pResult, coBuf.Y - 1 );
break;
}
case HB_GTI_VIEWMAXWIDTH:
{
COORD coBuf = GetLargestConsoleWindowSize( s_HOutput );
pInfo->pResult = hb_itemPutNI( pInfo->pResult, coBuf.X - 1 );
break;
}
case HB_GTI_VIEWPORTHEIGHT:
pInfo->pResult = hb_itemPutNI( pInfo->pResult, s_csbi.srWindow.Bottom -
s_csbi.srWindow.Top );
break;
case HB_GTI_VIEWPORTWIDTH:
pInfo->pResult = hb_itemPutNI( pInfo->pResult, s_csbi.srWindow.Right -
s_csbi.srWindow.Left );
break;
case HB_GTI_KBDSHIFTS:
pInfo->pResult = hb_itemPutNI( pInfo->pResult, hb_gt_w32_getKbdState() );
if( hb_itemType( pInfo->pNewVal ) & HB_IT_NUMERIC )
hb_gt_w32_setKbdState( hb_itemGetNI( pInfo->pNewVal ) );
break;
case HB_GTI_KBDSPECIAL:
pInfo->pResult = hb_itemPutL( pInfo->pResult, s_bSpecialKeyHandling );
if( hb_itemType( pInfo->pNewVal ) & HB_IT_LOGICAL )
s_bSpecialKeyHandling = hb_itemGetL( pInfo->pNewVal );
break;
case HB_GTI_KBDALT:
pInfo->pResult = hb_itemPutL( pInfo->pResult, s_bAltKeyHandling );
if( hb_itemType( pInfo->pNewVal ) & HB_IT_LOGICAL )
s_bAltKeyHandling = hb_itemGetL( pInfo->pNewVal );
break;
case HB_GTI_CLIPBOARDDATA:
if( hb_itemType( pInfo->pNewVal ) & HB_IT_STRING )
{
hb_gt_w32_setClipboard( CF_OEMTEXT, hb_itemGetCPtr( pInfo->pNewVal ),
hb_itemGetCLen( pInfo->pNewVal ) );
}
else
{
char * szClipboardData;
ULONG ulLen;
if( hb_gt_w32_getClipboard( CF_OEMTEXT, &szClipboardData, &ulLen ) )
{
pInfo->pResult = hb_itemPutCLPtr( pInfo->pResult,
szClipboardData,
ulLen );
}
else
{
pInfo->pResult = hb_itemPutC( pInfo->pResult, NULL );
}
}
break;
default:
return HB_GTSUPER_INFO( pGT, iType, pInfo );
}
return TRUE;
}
/* *********************************************************************** */
static BOOL hb_gt_win_mouse_IsPresent( PHB_GT pGT )
{
HB_SYMBOL_UNUSED( pGT );
return b_MouseEnable;
}
static void hb_gt_win_mouse_GetPos( PHB_GT pGT, int * piRow, int * piCol )
{
HB_SYMBOL_UNUSED( pGT );
*piRow = hb_mouse_iRow;
*piCol = hb_mouse_iCol;
}
static BOOL hb_gt_win_mouse_ButtonState( PHB_GT pGT, int iButton )
{
BOOL fReturn = FALSE;
HB_SYMBOL_UNUSED( pGT );
if( iButton == 0 )
fReturn = ( GetKeyState( VK_LBUTTON ) & 0x8000 ) != 0;
else if( iButton== 1 )
fReturn = ( GetKeyState( VK_RBUTTON ) & 0x8000 ) != 0;
else if( iButton == 2 )
fReturn = ( GetKeyState( VK_MBUTTON ) & 0x8000 ) != 0;
return fReturn;
}
static int hb_gt_win_mouse_CountButton( PHB_GT pGT )
{
DWORD dwCount = 0;
HB_SYMBOL_UNUSED( pGT );
GetNumberOfConsoleMouseButtons( &dwCount );
return ( int ) dwCount;
}
/* *********************************************************************** */
static void hb_gt_win_Redraw( PHB_GT pGT, int iRow, int iCol, int iSize )
{
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_win_Redraw(%p,%d,%d,%d)", pGT, iRow, iCol, iSize ) );
if( iSize > 0 && s_pCharInfoScreen != NULL &&
iRow < ( int ) _GetScreenHeight() && iCol < ( int ) _GetScreenWidth() )
{
BYTE bColor, bAttr;
USHORT usChar;
int iFirst = iCol;
int i = ( iRow * _GetScreenWidth() + iCol );
while( iSize-- > 0 )
{
if( !HB_GTSELF_GETSCRCHAR( pGT, iRow, iCol++, &bColor, &bAttr, &usChar ) )
break;
s_pCharInfoScreen[i].Char.AsciiChar = ( CHAR ) s_charTrans[ usChar & 0xFF ];
s_pCharInfoScreen[i].Attributes = ( WORD ) ( bColor & 0xFF );
++i;
}
hb_gt_win_xUpdtSet( iRow, iFirst, iRow, iCol - 1 );
}
}
/* *********************************************************************** */
static void hb_gt_win_Refresh( PHB_GT pGT )
{
HB_TRACE( HB_TR_DEBUG, ("hb_gt_win_Refresh(%p)", pGT) );
HB_GTSUPER_REFRESH( pGT );
if( s_pCharInfoScreen )
{
int iRow, iCol, iStyle;
HB_GTSELF_GETSCRCURSOR( pGT, &iRow, &iCol, &iStyle );
s_sCurRow = iRow;
s_sCurCol = iCol;
if( iRow < 0 || iCol < 0 ||
iRow >= ( int ) _GetScreenHeight() ||
iCol >= ( int ) _GetScreenWidth() )
{
s_usCursorStyle = SC_NONE;
}
else
{
s_usCursorStyle = iStyle;
}
hb_gt_win_xScreenUpdate();
}
}
/* *********************************************************************** */
static BOOL hb_gt_FuncInit( PHB_GT_FUNCS pFuncTable )
{
HB_TRACE(HB_TR_DEBUG, ("hb_gt_FuncInit(%p)", pFuncTable));
pFuncTable->Init = hb_gt_win_Init;
pFuncTable->Exit = hb_gt_win_Exit;
pFuncTable->SetMode = hb_gt_win_SetMode;
pFuncTable->Redraw = hb_gt_win_Redraw;
pFuncTable->Refresh = hb_gt_win_Refresh;
pFuncTable->Version = hb_gt_win_Version;
pFuncTable->PostExt = hb_gt_win_PostExt;
pFuncTable->Suspend = hb_gt_win_Suspend;
pFuncTable->Resume = hb_gt_win_Resume;
pFuncTable->Tone = hb_gt_win_Tone;
pFuncTable->Info = hb_gt_win_Info;
pFuncTable->SetDispCP = hb_gt_win_SetDispCP;
pFuncTable->SetKeyCP = hb_gt_win_SetKeyCP;
pFuncTable->ReadKey = hb_gt_win_ReadKey;
pFuncTable->MouseIsPresent = hb_gt_win_mouse_IsPresent;
pFuncTable->MouseGetPos = hb_gt_win_mouse_GetPos;
pFuncTable->MouseButtonState = hb_gt_win_mouse_ButtonState;
pFuncTable->MouseCountButton = hb_gt_win_mouse_CountButton;
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( &gtInit );
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
#endif /* HB_NO_WIN_CONSOLE */