Files
harbour-core/harbour/source/rtl/gtwin/gtwin.c
Przemyslaw Czerpak 6649576008 2006-02-09 03:08 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
* harbour/source/rtl/gtapi.c
    * minor modifications for GTs which may no flush data in PreExt()

  * harbour/source/rtl/gtwin/gtwin.c
    ! fixed Init() code by adding missing SUPER_INIT()
    * modified a little bit PreExt() and PostExt() methods
2006-02-09 02:11:07 +00:00

1898 lines
62 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( _MSC_VER ) || defined(__WATCOMC__)
# include <conio.h>
#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 HB_GT_FUNCS SuperTable;
#define HB_GTSUPER (&SuperTable)
static BOOL s_bSpecialKeyHandling;
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_iRelCount;
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 */
#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 */
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( SMALL_RECT * psrWin )
{
int iRow, iCol, i;
HB_TRACE(HB_TR_DEBUG, ("hb_gt_win_GetScreenContents()"));
for( iRow = psrWin->Top; iRow <= psrWin->Bottom; ++iRow )
{
i = iRow * _GetScreenWidth() + psrWin->Left;
for( iCol = psrWin->Left; iCol <= psrWin->Right; ++iCol )
{
hb_gt_PutChar( iRow, iCol, ( BYTE ) s_pCharInfoScreen[i].Attributes, 0,
s_charTransRev[ ( BYTE ) s_pCharInfoScreen[i].Char.AsciiChar ] );
++i;
}
}
}
/* *********************************************************************** */
static void hb_gt_win_xInitScreenParam( void )
{
HB_TRACE(HB_TR_DEBUG, ("hb_gt_win_xInitScreenParam()"));
if( GetConsoleScreenBufferInfo( s_HOutput, &s_csbi ) )
{
COORD coDest;
SMALL_RECT srWin;
ULONG ulSize = ( ULONG ) _GetScreenWidth() * _GetScreenHeight() *
sizeof( CHAR_INFO );
HB_GTSUPER_RESIZE( _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( &srWin );
hb_gt_ExposeArea( srWin.Top, srWin.Left, srWin.Bottom, srWin.Right );
}
hb_gt_SetPos( s_sCurRow, s_sCurCol );
}
else if( s_pCharInfoScreen != NULL )
{
hb_xfree( s_pCharInfoScreen );
s_ulScreenBuffSize = 0;
}
}
/* *********************************************************************** */
static void hb_gt_win_Init( FHANDLE hFilenoStdin, FHANDLE hFilenoStdout, FHANDLE hFilenoStderr )
{
HB_TRACE(HB_TR_DEBUG, ("hb_gt_win_Init(%p,%p,%p)", hFilenoStdin, hFilenoStdout, hFilenoStderr));
/* If Windows 95 or 98, use w9xTone for BCC32, MSVC */
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_iRelCount = 0;
/* initialize code page translation */
hb_gt_SetDispCP( NULL, NULL, FALSE );
hb_gt_SetKeyCP( NULL, NULL );
/* Add Ctrl+Break handler [vszakats] */
SetConsoleCtrlHandler( hb_gt_win_CtrlHandler, TRUE );
if( ( s_HInput = GetStdHandle( STD_INPUT_HANDLE ) ) == INVALID_HANDLE_VALUE )
{
#ifdef HB_ALLOC_CONSOLE
AllocConsole(); /* It is a Windows app without a console, so we create one */
s_HInput = GetStdHandle( STD_INPUT_HANDLE );
if( s_HInput == INVALID_HANDLE_VALUE )
{
hb_errInternal( 10001, "Can't allocate console", "", "" );
}
#else
if( hb_dynsymFindName( "__DBGENTRY" ) ) /* the debugger is linked */
{
AllocConsole(); /* It is a Windows app without a console, so we create one */
s_HInput = GetStdHandle( STD_INPUT_HANDLE );
}
#endif
}
HB_GTSUPER_INIT( hFilenoStdin, hFilenoStdout, hFilenoStderr );
s_HOutput = CreateFile( "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 )
{
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();
}
if( s_HInput != INVALID_HANDLE_VALUE )
{
if( b_MouseEnable )
{
/* With Mouse */
SetConsoleMode( s_HInput, ENABLE_MOUSE_INPUT );
}
else
{
/* NOMOUSE */
DWORD dwmode;
GetConsoleMode( s_HInput, &dwmode );
SetConsoleMode( s_HInput, dwmode & ~ENABLE_MOUSE_INPUT );
}
}
}
/* *********************************************************************** */
static void hb_gt_win_Exit( void )
{
HB_TRACE(HB_TR_DEBUG, ("hb_gt_win_Exit()"));
hb_gt_Refresh();
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();
}
/* *********************************************************************** */
static BOOL hb_gt_win_SetMode( int iRows, int iCols )
{
BOOL fRet = FALSE;
HB_TRACE(HB_TR_DEBUG, ("hb_gt_win_SetMode(%d, %d)", 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();
}
return fRet;
}
/* *********************************************************************** */
static char * hb_gt_win_Version( int iType )
{
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_win_Version(%d)", iType ) );
if ( iType == 0 )
return HB_GT_DRVNAME( HB_GT_NAME );
return "Harbour Terminal: Win32 buffered console";
}
/* *********************************************************************** */
static BOOL hb_gt_win_PreExt()
{
HB_TRACE(HB_TR_DEBUG, ("hb_gt_win_PreExt()"));
return HB_GTSUPER_PREEXT();
}
static BOOL hb_gt_win_PostExt()
{
HB_TRACE(HB_TR_DEBUG, ("hb_gt_win_PostExt()"));
HB_GTSUPER_POSTEXT();
if( s_pCharInfoScreen )
hb_gt_win_xInitScreenParam();
return TRUE;
}
/* *********************************************************************** */
static BOOL hb_gt_win_Suspend()
{
HB_TRACE(HB_TR_DEBUG, ("hb_gt_win_Suspend()"));
if( s_pCharInfoScreen )
{
GetConsoleMode( s_HInput, &s_dwimode );
GetConsoleMode( s_HOutput, &s_dwomode );
SetConsoleCtrlHandler( hb_gt_win_CtrlHandler, FALSE );
SetConsoleCtrlHandler( NULL, TRUE );
if( b_MouseEnable )
{
SetConsoleMode( s_HInput, s_dwimode & ~ENABLE_MOUSE_INPUT );
}
}
return TRUE;
}
static BOOL hb_gt_win_Resume()
{
HB_TRACE(HB_TR_DEBUG, ("hb_gt_win_Resume()"));
if( s_pCharInfoScreen )
{
SetConsoleCtrlHandler( NULL, FALSE );
SetConsoleCtrlHandler( hb_gt_win_CtrlHandler, TRUE );
SetConsoleMode( s_HInput, s_dwimode );
SetConsoleMode( s_HOutput, s_dwomode );
hb_gt_win_xInitScreenParam();
hb_gt_win_xSetCursorStyle();
}
return TRUE;
}
/* *********************************************************************** */
static void Handle_Alt_Key( int * paltisdown, int * paltnum, unsigned short wKey, int * pch )
{
// if( s_irInBuf[ s_cNumIndex ].Event.KeyEvent.dwControlKeyState & ~ (LEFT_ALTENHANCED_KEY)
// {
// *paltisdown = 0;
// }
// else
{
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 */
{
*pch = *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;
}
}
}
}
static int SpecialHandling( WORD * wChar, int wKey, int ch )
{
switch (wKey)
{
case 2:
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;
default:
break;
}
return ch;
}
static int hb_gt_win_ReadKey( int iEventMask )
{
int ch = 0,
extKey = -1;
const ClipKeyCode *clipKey = NULL;
HB_TRACE(HB_TR_DEBUG, ("hb_gt_win_ReadKey(%d)", iEventMask));
/* 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 )
{
int altisdown = 0;
int altnum = 0;
/* Check for keyboard input */
do
{
if( ++s_iRelCount > 100 )
{
s_iRelCount = 0;
hb_idleSleep( 0.01 );
}
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",
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 */
altisdown, s_wRepeated, s_cNumRead, s_cNumIndex);
}
#endif
if( altisdown )
{
Handle_Alt_Key( &altisdown, &altnum, wKey, &ch );
}
else
{
// if ( wKey == 0x38 &&
// s_irInBuf[ s_cNumIndex ].Event.KeyEvent.bKeyDown )
if ( wKey == 0x38 &&
s_irInBuf[ s_cNumIndex ].Event.KeyEvent.bKeyDown &&
s_irInBuf[ s_cNumIndex ].Event.KeyEvent.dwControlKeyState & ((RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED) & !(LEFT_CTRL_PRESSED) ))
{
altisdown = 1;
}
}
}
}
} while (altisdown);
}
/* 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 )
ch = SpecialHandling( &wChar, wKey, ch );
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_LDOWN &&
s_irInBuf[ s_cNumIndex ].Event.MouseEvent.dwButtonState &
FROM_LEFT_1ST_BUTTON_PRESSED )
{
if( s_irInBuf[ s_cNumIndex ].Event.MouseEvent.dwEventFlags == DOUBLE_CLICK )
{
ch = K_LDBLCLK;
}
else
{
ch = K_LBUTTONDOWN;
}
s_mouseLast = K_LBUTTONDOWN;
}
else if( iEventMask & INKEY_RDOWN &&
s_irInBuf[ s_cNumIndex ].Event.MouseEvent.dwButtonState &
RIGHTMOST_BUTTON_PRESSED )
{
if( s_irInBuf[ s_cNumIndex ].Event.MouseEvent.dwEventFlags == DOUBLE_CLICK )
{
ch = K_RDBLCLK;
}
else
{
ch = 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;
}
else if( iEventMask & INKEY_RUP && s_mouseLast == K_RBUTTONDOWN )
{
ch = K_RBUTTONUP;
}
}
}
/* 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;
}
/* *********************************************************************** */
#if defined( HB_ARCH_32BIT ) && \
( defined(__BORLANDC__) || defined(_MSC_VER) || \
defined(__WATCOMC__) || defined(__MINGW32__) )
static int hb_Inp9x( USHORT usPort )
{
USHORT usVal;
HB_TRACE(HB_TR_DEBUG, ("hb_Inp9x(%hu)", usPort));
#if defined( __BORLANDC__ ) || defined(__DMC__)
_DX = usPort;
__emit__(0xEC); /* ASM IN AL, DX */
__emit__(0x32,0xE4); /* ASM XOR AH, AH */
usVal = _AX;
#elif defined( __XCC__ )
__asm {
mov dx, usPort
xor ax, ax
in al, dx
mov usVal, ax
}
#elif defined( __MINGW32__ )
__asm__ __volatile__ ("inb %w1,%b0":"=a" (usVal):"Nd" (usPort));
#elif defined( __WATCOMC__ )
usVal = inp( usPort );
#else
usVal = _inp( usPort );
#endif
return usVal;
}
/* *********************************************************************** */
static int hb_Outp9x( USHORT usPort, USHORT usVal )
{
HB_TRACE(HB_TR_DEBUG, ("hb_Outp9x(%hu, %hu)", usPort, usVal));
#if defined( __BORLANDC__ ) || defined(__DMC__)
_DX = usPort;
_AL = usVal;
__emit__(0xEE); /* ASM OUT DX, AL */
#elif defined( __XCC__ )
__asm {
mov dx, usPort
mov ax, usVal
out dx, al
}
#elif defined( __MINGW32__ )
__asm__ __volatile__ ("outb %b0,%w1": :"a" (usVal), "Nd" (usPort));
#elif defined( __WATCOMC__ )
outp( usPort, usVal );
#else
_outp( usPort, usVal );
#endif
return usVal;
}
/* *********************************************************************** */
/* dDurat is in seconds */
static void hb_gt_win_w9xTone( double dFreq, double dDurat )
{
INT uLSB,uMSB;
ULONG lAdjFreq;
HB_TRACE(HB_TR_DEBUG, ("hb_gt_win_w9xtone(%lf, %lf)", dFreq, dDurat));
/* sync with internal clock with very small time period */
hb_idleSleep( 0.01 );
/* Clipper ignores Tone() requests (but delays anyway) if Frequency is
less than < 20 hz (and so should we) to maintain compatibility .. */
if( dFreq >= 20.0 )
{
/* Setup Sound Control Port Registers and timer channel 2 */
hb_Outp9x(67, 182) ;
lAdjFreq = (ULONG)( 1193180 / dFreq ) ;
if( (LONG) lAdjFreq < 0 )
uLSB = lAdjFreq + 65536;
else
uLSB = lAdjFreq % 256;
if( (LONG) lAdjFreq < 0 )
uMSB = lAdjFreq + 65536;
else
uMSB = lAdjFreq / 256;
/* set the frequency (LSB,MSB) */
hb_Outp9x(66, uLSB);
hb_Outp9x(66, uMSB);
/* Get current Port setting */
/* enable Speaker Data & Timer gate bits */
/* (00000011B is bitmask to enable sound) */
/* Turn on Speaker - sound Tone for duration.. */
hb_Outp9x(97, hb_Inp9x( 97 ) | 3);
hb_idleSleep( dDurat );
/* Read back current Port value for Reset */
/* disable Speaker Data & Timer gate bits */
/* (11111100B is bitmask to disable sound) */
/* Turn off the Speaker ! */
hb_Outp9x(97, hb_Inp9x( 97 ) & 0xFC);
}
else
{
hb_idleSleep( dDurat );
}
}
#endif
/* *********************************************************************** */
/* dDurat is in seconds */
static void hb_gt_win_wNtTone( double dFreq, double dDurat )
{
HB_TRACE(HB_TR_DEBUG, ("hb_gt_win_wNtTone(%lf, %lf)", dFreq, dDurat));
/* Clipper ignores Tone() requests (but delays anyway) if Frequency is
less than < 20 hz. Windows NT minimum is 37... */
if( dFreq >= 37.0 )
{
Beep( (ULONG) dFreq, (ULONG) ( dDurat * 1000 ) ); /* Beep wants Milliseconds */
}
else
{
hb_idleSleep( dDurat );
}
}
/* *********************************************************************** */
/* dDuration is in 'Ticks' (18.2 per second) */
static void hb_gt_win_Tone( double dFrequency, double dDuration )
{
HB_TRACE(HB_TR_DEBUG, ("hb_gt_win_Tone(%lf, %lf)", dFrequency, dDuration));
/*
* According to the Clipper NG, the duration in 'ticks' is truncated to the
* interger portion ... Depending on the platform, xHarbour allows a finer
* resolution, but the minimum is 1 tick (for compatibility)
*/
/* Convert from ticks to seconds */
dDuration = ( HB_MIN( HB_MAX( 1.0, dDuration ), ULONG_MAX ) ) / 18.2;
/* keep the frequency in an acceptable range */
dFrequency = HB_MIN( HB_MAX( 0.0, dFrequency ), 32767.0 );
/* If Windows 95 or 98, use w9xTone for BCC32, MSVC */
if( s_osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )
{
#if defined( HB_ARCH_32BIT ) && \
( defined( __BORLANDC__ ) || defined( _MSC_VER ) || \
defined( __WATCOMC__ ) || defined(__MINGW32__) )
hb_gt_win_w9xTone( dFrequency, dDuration );
#else
hb_gt_win_wNtTone( dFrequency, dDuration );
#endif
}
/* If Windows NT or NT2k, use wNtTone, which provides TONE()
reset sequence support (new) */
else /* if( s_osv.dwPlatformId == VER_PLATFORM_WIN32_NT ) */
{
hb_gt_win_wNtTone( dFrequency, dDuration );
}
}
/* *********************************************************************** */
static BOOL hb_gt_win_SetDispCP( char *pszTermCDP, char *pszHostCDP, BOOL fBox )
{
int i;
HB_TRACE(HB_TR_DEBUG, ("hb_gt_win_SetDispCP(%s,%s,%d)", pszTermCDP, pszHostCDP, (int) fBox));
HB_SYMBOL_UNUSED( 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 ];
}
}
}
#else
HB_SYMBOL_UNUSED( pszTermCDP );
HB_SYMBOL_UNUSED( pszHostCDP );
#endif
for( i = 0; i < 256; i++ )
s_charTransRev[ s_charTrans[ i ] ] = ( BYTE ) i;
return TRUE;
}
/* *********************************************************************** */
static BOOL hb_gt_win_SetKeyCP( char *pszTermCDP, char *pszHostCDP )
{
int i;
HB_TRACE(HB_TR_DEBUG, ("hb_gt_win_SetKeyCP(%s,%s)", 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 ];
}
}
}
#else
HB_SYMBOL_UNUSED( pszTermCDP );
HB_SYMBOL_UNUSED( pszHostCDP );
#endif
return TRUE;
}
static int kbdShiftsState( void )
{
int kbdShifts = 0;
if ( GetKeyState( VK_SHIFT ) & 0x80 ) kbdShifts |= GTI_KBD_SHIFT;
if ( GetKeyState( VK_CONTROL ) & 0x80 ) kbdShifts |= GTI_KBD_CTRL;
//if ( GetKeyState( VK_MENU ) & 0x80 ) kbdShifts |= GTI_KBD_ALT;
if ( GetKeyState( VK_LWIN ) & 0x80 ) kbdShifts |= GTI_KBD_LWIN;
if ( GetKeyState( VK_RWIN ) & 0x80 ) kbdShifts |= GTI_KBD_RWIN;
if ( GetKeyState( VK_APPS ) & 0x80 ) kbdShifts |= GTI_KBD_MENU;
if ( GetKeyState( VK_SCROLL ) & 0x01 ) kbdShifts |= GTI_KBD_SCROLOCK;
if ( GetKeyState( VK_NUMLOCK ) & 0x01 ) kbdShifts |= GTI_KBD_NUMLOCK;
if ( GetKeyState( VK_CAPITAL ) & 0x01 ) kbdShifts |= GTI_KBD_CAPSLOCK;
return kbdShifts;
}
/* *********************************************************************** */
static BOOL hb_gt_win_Info( int iType, PHB_GT_INFO pInfo )
{
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_win_Info(%d,%p)", iType, pInfo ) );
switch ( iType )
{
case GTI_WINTITLE:
{
char szBuff[ 256 ];
DWORD dwLen;
dwLen = GetConsoleTitle( ( LPSTR ) szBuff, sizeof( szBuff ) );
pInfo->pResult = hb_itemPutCL( pInfo->pResult, szBuff, dwLen );
if( hb_itemType( pInfo->pNewVal ) & HB_IT_STRING )
SetConsoleTitle( ( LPCSTR ) hb_itemGetCPtr( pInfo->pNewVal ) );
break;
}
case GTI_VIEWMAXHEIGHT:
{
COORD coBuf = GetLargestConsoleWindowSize( s_HOutput );
pInfo->pResult = hb_itemPutNI( pInfo->pResult, coBuf.Y - 1 );
break;
}
case GTI_VIEWMAXWIDTH:
{
COORD coBuf = GetLargestConsoleWindowSize( s_HOutput );
pInfo->pResult = hb_itemPutNI( pInfo->pResult, coBuf.X - 1 );
break;
}
case GTI_VIEWPORTHEIGHT:
pInfo->pResult = hb_itemPutNI( pInfo->pResult, s_csbi.srWindow.Bottom -
s_csbi.srWindow.Top );
break;
case GTI_VIEWPORTWIDTH:
pInfo->pResult = hb_itemPutNI( pInfo->pResult, s_csbi.srWindow.Right -
s_csbi.srWindow.Left );
break;
case GTI_KBDSHIFTS:
pInfo->pResult = hb_itemPutNI( pInfo->pResult, kbdShiftsState() );
break;
case 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;
default:
return HB_GTSUPER_INFO( iType, pInfo );
}
return TRUE;
}
/* *********************************************************************** */
static BOOL hb_gt_win_mouse_IsPresent( void )
{
return b_MouseEnable;
}
static void hb_gt_win_mouse_GetPos( int * piRow, int * piCol )
{
*piRow = hb_mouse_iRow;
*piCol = hb_mouse_iCol;
}
static BOOL hb_gt_win_mouse_ButtonState( int iButton )
{
BOOL fReturn = FALSE;
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( void )
{
DWORD dwCount = 0;
GetNumberOfConsoleMouseButtons( &dwCount );
return ( int ) dwCount;
}
/* *********************************************************************** */
static void hb_gt_win_Redraw( int iRow, int iCol, int iSize )
{
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_win_Redraw(%d, %d, %d)", 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_gt_GetScrChar( 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( void )
{
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_win_Refresh()") );
HB_GTSUPER_REFRESH();
if( s_pCharInfoScreen )
{
int iRow, iCol, iStyle;
hb_gt_GetScrCursor( &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->PreExt = hb_gt_win_PreExt;
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 HB_GT_INIT gtInit = { HB_GT_DRVNAME( HB_GT_NAME ),
hb_gt_FuncInit,
HB_GTSUPER };
HB_GT_ANNOUNCE( HB_GT_NAME );
HB_CALL_ON_STARTUP_BEGIN( _hb_startup_gt_Init_ )
hb_gtRegister( &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)
#if _MSC_VER >= 1010
#pragma data_seg( ".CRT$XIY" )
#pragma comment( linker, "/Merge:.CRT=.data" )
#else
#pragma data_seg( "XIY" )
#endif
static HB_$INITSYM hb_vm_auto__hb_startup_gt_Init_ = _hb_startup_gt_Init_;
#pragma data_seg()
#endif