1386 lines
42 KiB
C
1386 lines
42 KiB
C
/*
|
|
* $Id$
|
|
*/
|
|
|
|
/*
|
|
* Harbour Project source code:
|
|
* Video subsystem for Win32 compilers
|
|
*
|
|
* Copyright 1999-2000 Paul Tucker <ptucker@sympatico.ca>
|
|
* (for functions marked ptucker)
|
|
* 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.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* 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.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* Portions of this module are based (somewhat) on VIDMGR by
|
|
* Andrew Clarke and modified for the Harbour project
|
|
*/
|
|
|
|
/* NOTE: User programs should never call this layer directly! */
|
|
|
|
/* #define HB_DEBUG_KEYBOARD */
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
|
|
#define HB_OS_WIN_32_USED
|
|
|
|
#include <hbapigt.h>
|
|
#include <hbset.h> /* For Ctrl+Break handling */
|
|
#include <hbvm.h> /* For Ctrl+Break handling */
|
|
#include <hbinkey.ch>
|
|
#include <inkey.ch>
|
|
|
|
#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 unsigned short int WORD;
|
|
|
|
#undef DWORD /* 4 bytes unsigned */
|
|
typedef unsigned long 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
|
|
|
|
#if 0
|
|
static HANDLE s_HOsave; /* work in progress */
|
|
static HANDLE s_HDOutput;
|
|
#endif
|
|
static HANDLE s_HOriginal;
|
|
static HANDLE s_HOutput;
|
|
static HANDLE s_HActive;
|
|
static HANDLE s_HInactive;
|
|
static HANDLE s_HInput;
|
|
static BOOL s_bOldCursor;
|
|
static BOOL s_bBreak;
|
|
|
|
static USHORT s_uiDispCount;
|
|
static CONSOLE_SCREEN_BUFFER_INFO s_csbi; /* to restore screen mode on exit */
|
|
|
|
#define INPUT_BUFFER_LEN 128
|
|
|
|
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 INPUT_RECORD s_irInBuf[ INPUT_BUFFER_LEN ];
|
|
static int s_mouseLast; /* Last mouse button to be pressed */
|
|
|
|
extern int hb_mouse_iCol;
|
|
extern int hb_mouse_iRow;
|
|
|
|
static BOOL WINAPI hb_gt_CtrlHandler( DWORD dwCtrlType )
|
|
{
|
|
BOOL bHandled;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_CtrlHandler(%lu)", (unsigned long) dwCtrlType));
|
|
|
|
switch( dwCtrlType )
|
|
{
|
|
case CTRL_C_EVENT:
|
|
bHandled = FALSE;
|
|
break;
|
|
|
|
case CTRL_BREAK_EVENT:
|
|
s_bBreak = TRUE;
|
|
bHandled = TRUE;
|
|
break;
|
|
|
|
case CTRL_CLOSE_EVENT:
|
|
case CTRL_LOGOFF_EVENT:
|
|
case CTRL_SHUTDOWN_EVENT:
|
|
default:
|
|
bHandled = FALSE;
|
|
}
|
|
|
|
return bHandled;
|
|
}
|
|
|
|
void hb_gt_Init( int iFilenoStdin, int iFilenoStdout, int iFilenoStderr )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_Init(): %d, %d, %d", iFilenoStdin, iFilenoStdout, iFilenoStderr));
|
|
|
|
HB_SYMBOL_UNUSED( iFilenoStdin );
|
|
HB_SYMBOL_UNUSED( iFilenoStdout );
|
|
HB_SYMBOL_UNUSED( iFilenoStderr );
|
|
|
|
#if 0
|
|
s_HOsave =
|
|
s_HDOutput = INVALID_HANDLE_VALUE;
|
|
#endif
|
|
|
|
s_cNumRead = 0;
|
|
s_cNumIndex = 0;
|
|
s_uiDispCount = 0;
|
|
|
|
s_bOldCursor = TRUE;
|
|
s_bBreak = FALSE;
|
|
|
|
/* Add Ctrl+Break handler [vszakats] */
|
|
SetConsoleCtrlHandler( hb_gt_CtrlHandler, TRUE );
|
|
|
|
if( ( s_HInput = GetStdHandle( STD_INPUT_HANDLE ) ) == INVALID_HANDLE_VALUE )
|
|
{
|
|
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 );
|
|
}
|
|
}
|
|
|
|
if( s_HInput != INVALID_HANDLE_VALUE )
|
|
SetConsoleMode( s_HInput, ENABLE_MOUSE_INPUT );
|
|
|
|
/* ptucker */
|
|
s_HOriginal = 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 );
|
|
|
|
s_HOutput = s_HOriginal;
|
|
s_HActive = s_HOutput;
|
|
|
|
{
|
|
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
|
|
|
GetConsoleScreenBufferInfo( s_HOriginal, &csbi );
|
|
|
|
/* save screen info to restore on exit */
|
|
memcpy( &s_csbi, &csbi, sizeof( csbi ) );
|
|
|
|
csbi.srWindow.Right = HB_MIN( csbi.srWindow.Right, csbi.dwSize.X-1 );
|
|
csbi.srWindow.Bottom = HB_MIN( csbi.srWindow.Bottom, csbi.dwSize.Y-1 );
|
|
|
|
csbi.srWindow.Top = csbi.srWindow.Left = 0;
|
|
|
|
SetConsoleWindowInfo( s_HOriginal, TRUE, &csbi.srWindow );
|
|
SetConsoleScreenBufferSize( s_HOriginal, csbi.dwSize );
|
|
|
|
s_HInactive = CreateConsoleScreenBuffer(
|
|
GENERIC_READ | GENERIC_WRITE, /* Access flag */
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE, /* Buffer share mode */
|
|
NULL, /* Security attribute */
|
|
CONSOLE_TEXTMODE_BUFFER, /* Type of buffer */
|
|
NULL ); /* reserved */
|
|
|
|
|
|
SetConsoleWindowInfo( s_HInactive, TRUE, &csbi.srWindow );
|
|
SetConsoleScreenBufferSize( s_HInactive, csbi.dwSize );
|
|
|
|
}
|
|
|
|
hb_mouse_Init();
|
|
/*
|
|
SetConsoleActiveScreenBuffer( s_HActive );
|
|
*/
|
|
}
|
|
|
|
void hb_gt_Exit( void )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_Exit()"));
|
|
|
|
hb_mouse_Exit();
|
|
if( s_HOutput != s_HOriginal )
|
|
{
|
|
/* ptucker */
|
|
/* because the current screen may not be the one that was active
|
|
when the app started, we need to restore that screen and update
|
|
it with the current image before quitting.
|
|
*/
|
|
/* easy fix ;-) */
|
|
|
|
hb_gt_DispBegin();
|
|
hb_gt_DispEnd();
|
|
}
|
|
/* NOTE: There's no need to close these explicitly, moreover if we close them
|
|
functions using stdout will not show anything.
|
|
CloseHandle( s_HInput );
|
|
s_HInput = INVALID_HANDLE_VALUE;
|
|
CloseHandle( s_HOutput );
|
|
s_HOutput = INVALID_HANDLE_VALUE;
|
|
*/
|
|
SetConsoleScreenBufferSize( s_HOriginal, s_csbi.dwSize );
|
|
SetConsoleWindowInfo( s_HOriginal, FALSE, &s_csbi.srWindow );
|
|
|
|
/* detected using NuMega BoundsChecker */
|
|
CloseHandle( s_HOriginal );
|
|
s_HOriginal = INVALID_HANDLE_VALUE;
|
|
|
|
CloseHandle( s_HInactive );
|
|
s_HInactive = INVALID_HANDLE_VALUE;
|
|
|
|
/* Remove Ctrl+Break handler [vszakats] */
|
|
SetConsoleCtrlHandler( hb_gt_CtrlHandler, FALSE );
|
|
|
|
}
|
|
|
|
static int StdFnKeys( WORD wKey, BOOL bEnhanced )
|
|
{
|
|
int ch;
|
|
/* Normal function key */
|
|
ch = wKey + HB_INKEY_NONE;
|
|
if( bEnhanced ) ch += HB_INKEY_ENHANCED;
|
|
return ch;
|
|
}
|
|
|
|
static int IgnoreKeyCodes( int wKey )
|
|
{
|
|
int ignore = 0;
|
|
switch( wKey )
|
|
{
|
|
/* Virtual scan codes to ignore */
|
|
case 29: /* Ctrl */
|
|
case 40: /* Circle Accent */
|
|
case 41: /* Tick Accent */
|
|
case 42: /* Left Shift */
|
|
case 43: /* Reverse Tick Accent */
|
|
case 54: /* Right Shift */
|
|
case 56: /* Alt */
|
|
case 58: /* Caps Lock */
|
|
case 69: /* Num Lock */
|
|
case 70: /* Pause or Scroll Lock */
|
|
ignore = -1;
|
|
}
|
|
return ignore;
|
|
}
|
|
|
|
int hb_gt_ExtendedKeySupport()
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
int hb_gt_ReadKey( HB_inkey_enum eventmask )
|
|
{
|
|
int ch = 0, extended = 0;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_ReadKey(%d)", (int) eventmask));
|
|
|
|
/* 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_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;
|
|
}
|
|
}
|
|
/* Only process one keyboard event at a time. */
|
|
if( s_cNumRead > s_cNumIndex )
|
|
{
|
|
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 key code */
|
|
DWORD dwState = s_irInBuf[ s_cNumIndex ].Event.KeyEvent.dwControlKeyState;
|
|
WORD wChar = s_irInBuf[ s_cNumIndex ].Event.KeyEvent.wVirtualKeyCode;
|
|
WORD wKey = s_irInBuf[ s_cNumIndex ].Event.KeyEvent.wVirtualScanCode;
|
|
ch = s_irInBuf[ s_cNumIndex ].Event.KeyEvent.uChar.AsciiChar;
|
|
#ifdef HB_DEBUG_KEYBOARD
|
|
/* if( dwState & ENHANCED_KEY ) ch = -32; */
|
|
fprintf( stdout, "\n\nhb_gt_ReadKey(): dwState is %ld, wChar is %d, wKey is %d, ch is %d", dwState, wChar, wKey, ch );
|
|
if( dwState & CAPSLOCK_ON ) fprintf( stdout, " CL" );
|
|
if( dwState & ENHANCED_KEY ) fprintf( stdout, " EK" );
|
|
if( dwState & LEFT_ALT_PRESSED ) fprintf( stdout, " LA" );
|
|
if( dwState & RIGHT_ALT_PRESSED ) fprintf( stdout, " RA" );
|
|
if( dwState & LEFT_CTRL_PRESSED ) fprintf( stdout, " LC" );
|
|
if( dwState & RIGHT_CTRL_PRESSED ) fprintf( stdout, " RC" );
|
|
if( dwState & NUMLOCK_ON ) fprintf( stdout, " NL" );
|
|
if( dwState & SCROLLLOCK_ON ) fprintf( stdout, " SL" );
|
|
if( dwState & SHIFT_PRESSED ) fprintf( stdout, " SH" );
|
|
fprintf( stdout, " " );
|
|
#endif
|
|
if( ch == 224 )
|
|
{
|
|
/* Strip extended key lead-in codes */
|
|
ch = 0;
|
|
#ifdef HB_DEBUG_KEYBOARD
|
|
fprintf( stdout, "-" );
|
|
#endif
|
|
}
|
|
else if( ch < 0 && ch != -32 && ch != -16 && !IgnoreKeyCodes( wKey ) )
|
|
{
|
|
/* Process international key codes */
|
|
ch += 256;
|
|
#ifdef HB_DEBUG_KEYBOARD
|
|
fprintf( stdout, "+" );
|
|
#endif
|
|
}
|
|
else if( ch < 0 && ch != -32 && ch != -16 )
|
|
{
|
|
/* Ignore any negative character codes that didn't get handled
|
|
by the international keyboard processing and don't signify
|
|
extended key codes */
|
|
ch = 0;
|
|
}
|
|
else
|
|
{
|
|
#ifdef HB_DEBUG_KEYBOARD
|
|
fprintf( stdout, "0" );
|
|
#endif
|
|
if( ( ( ch == 0 || ch == -32 || ch == -16 ) && ( dwState & ( SHIFT_PRESSED | LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED ) ) )
|
|
|| ( ( dwState & ( ENHANCED_KEY | LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED ) ) ) )
|
|
{
|
|
extended = 1;
|
|
#ifdef HB_DEBUG_KEYBOARD
|
|
fprintf( stdout, "1" );
|
|
#endif
|
|
}
|
|
else if( ch == 0 )
|
|
{
|
|
if( eventmask & INKEY_RAW )
|
|
{
|
|
extended = 1;
|
|
#ifdef HB_DEBUG_KEYBOARD
|
|
fprintf( stdout, "2" );
|
|
#endif
|
|
}
|
|
else if( IgnoreKeyCodes( wKey ) )
|
|
{
|
|
#ifdef HB_DEBUG_KEYBOARD
|
|
fprintf( stdout, "!" );
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
ch = StdFnKeys( wKey, 0 );
|
|
#ifdef HB_DEBUG_KEYBOARD
|
|
fprintf( stdout, "3" );
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
if( extended )
|
|
{
|
|
#ifdef HB_DEBUG_KEYBOARD
|
|
fprintf( stdout, "4" );
|
|
#endif
|
|
/* Process non-ASCII key codes */
|
|
if( eventmask & INKEY_RAW ) wKey = wChar;
|
|
/* Discard standalone state key presses for normal mode only */
|
|
if( ( eventmask & INKEY_RAW ) == 0 && IgnoreKeyCodes( wKey ) )
|
|
{
|
|
wKey = 0;
|
|
#ifdef HB_DEBUG_KEYBOARD
|
|
fprintf( stdout, "5" );
|
|
#endif
|
|
}
|
|
if( wKey == 0 ) ch = 0;
|
|
else
|
|
{
|
|
#ifdef HB_DEBUG_KEYBOARD
|
|
fprintf( stdout, "6" );
|
|
#endif
|
|
if( eventmask & INKEY_RAW )
|
|
{
|
|
/* Pass along all virtual key codes with all
|
|
enhanced and state indicators accounted for */
|
|
wKey += 256;
|
|
if( dwState & ENHANCED_KEY ) wKey += 512;
|
|
if( dwState & SHIFT_PRESSED ) wKey += 1024;
|
|
if( dwState & LEFT_CTRL_PRESSED ) wKey += 2048;
|
|
if( dwState & RIGHT_CTRL_PRESSED ) wKey += 4096;
|
|
if( dwState & LEFT_ALT_PRESSED ) wKey += 8192;
|
|
if( dwState & RIGHT_ALT_PRESSED ) wKey += 16384;
|
|
ch = wKey;
|
|
#ifdef HB_DEBUG_KEYBOARD
|
|
fprintf( stdout, "7" );
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
/* Translate virtual scan codes to Clipper codes */
|
|
BOOL bAlt = dwState & ( LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED );
|
|
BOOL bCtrl = dwState & ( LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED );
|
|
BOOL bShift = dwState & SHIFT_PRESSED;
|
|
BOOL bAltGr = ( dwState & ( LEFT_CTRL_PRESSED | RIGHT_ALT_PRESSED ) ) == ( LEFT_CTRL_PRESSED | RIGHT_ALT_PRESSED );
|
|
BOOL bEnhanced = dwState & ENHANCED_KEY;
|
|
#ifdef HB_DEBUG_KEYBOARD
|
|
fprintf( stdout, "8" );
|
|
#endif
|
|
|
|
HB_TRACE(HB_TR_INFO, ("hb_gt_ReadKey(): wKey is %d, dwState is %d, ch is %d", wKey, dwState, ch));
|
|
|
|
if( bAlt )
|
|
{
|
|
#ifdef HB_DEBUG_KEYBOARD
|
|
fprintf( stdout, "9" );
|
|
#endif
|
|
/* Alt key held */
|
|
if( bAltGr && ch ) { /* It's actually Alt+Gr */ }
|
|
else
|
|
{
|
|
#ifdef HB_DEBUG_KEYBOARD
|
|
fprintf( stdout, "a" );
|
|
#endif
|
|
ch = wKey + HB_INKEY_ALT;
|
|
if( bEnhanced ) ch += HB_INKEY_ENHANCED;
|
|
}
|
|
}
|
|
else if( bCtrl )
|
|
{
|
|
#ifdef HB_DEBUG_KEYBOARD
|
|
fprintf( stdout, "b" );
|
|
#endif
|
|
/* Ctrl key held */
|
|
if( ch == 0 || bEnhanced ) ch = wKey + HB_INKEY_CTRL;
|
|
if( bEnhanced ) ch += HB_INKEY_ENHANCED;
|
|
}
|
|
else if( bShift )
|
|
{
|
|
#ifdef HB_DEBUG_KEYBOARD
|
|
fprintf( stdout, "c" );
|
|
#endif
|
|
/* Shift key held */
|
|
if( ch == 0 || bEnhanced ) ch = wKey + HB_INKEY_SHIFT;
|
|
if( bEnhanced ) ch += HB_INKEY_ENHANCED;
|
|
}
|
|
else
|
|
{
|
|
#ifdef HB_DEBUG_KEYBOARD
|
|
fprintf( stdout, "d" );
|
|
#endif
|
|
ch = StdFnKeys( wKey, bEnhanced );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
/* Debug code: */
|
|
else
|
|
{
|
|
WORD wKey;
|
|
if( eventmask & INKEY_RAW )
|
|
wKey = s_irInBuf[ s_cNumIndex ].Event.KeyEvent.wVirtualKeyCode;
|
|
else
|
|
wKey = s_irInBuf[ s_cNumIndex ].Event.KeyEvent.wVirtualScanCode;
|
|
HB_TRACE(HB_TR_INFO, ("hb_gt_ReadKey(): wKey is %d", wKey));
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
else if( eventmask & ~( INKEY_KEYBOARD | INKEY_RAW )
|
|
&& s_irInBuf[ s_cNumIndex ].EventType == MOUSE_EVENT )
|
|
{
|
|
|
|
hb_mouse_iCol = s_irInBuf[ s_cNumIndex ].Event.MouseEvent.dwMousePosition.X;
|
|
hb_mouse_iRow = s_irInBuf[ s_cNumIndex ].Event.MouseEvent.dwMousePosition.Y;
|
|
|
|
if( eventmask & INKEY_MOVE && s_irInBuf[ s_cNumIndex ].Event.MouseEvent.dwEventFlags == MOUSE_MOVED )
|
|
ch = K_MOUSEMOVE;
|
|
|
|
else if( eventmask & 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( eventmask & 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( eventmask & INKEY_LUP && s_mouseLast == K_LBUTTONDOWN )
|
|
ch = K_LBUTTONUP;
|
|
else if( eventmask & INKEY_RUP && s_mouseLast == K_RBUTTONDOWN )
|
|
ch = K_RBUTTONUP;
|
|
}
|
|
}
|
|
/* Set up to process the next input event (if any) */
|
|
s_cNumIndex++;
|
|
}
|
|
|
|
return ch;
|
|
}
|
|
|
|
BOOL hb_gt_AdjustPos( BYTE * pStr, ULONG ulLen )
|
|
{
|
|
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_AdjustPos(%s, %lu)", pStr, ulLen ));
|
|
|
|
HB_SYMBOL_UNUSED( pStr );
|
|
HB_SYMBOL_UNUSED( ulLen );
|
|
|
|
GetConsoleScreenBufferInfo( s_HActive, &csbi );
|
|
|
|
hb_gt_SetPos( csbi.dwCursorPosition.Y, csbi.dwCursorPosition.X, HB_GT_SET_POS_AFTER );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL hb_gt_IsColor( void )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_IsColor()"));
|
|
|
|
/* TODO: need to call something to do this instead of returning TRUE */
|
|
return TRUE;
|
|
}
|
|
|
|
USHORT hb_gt_GetScreenWidth( void )
|
|
{
|
|
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_GetScreenWidth()"));
|
|
|
|
GetConsoleScreenBufferInfo( s_HOutput, &csbi );
|
|
/* return csbi.dwMaximumWindowSize.X; */
|
|
/* return HB_MAX( csbi.srWindow.Right - csbi.srWindow.Left + 1, 40 ); */
|
|
return HB_MAX( csbi.dwSize.X, 40 );
|
|
}
|
|
|
|
USHORT hb_gt_GetScreenHeight( void )
|
|
{
|
|
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_GetScreenHeight()"));
|
|
|
|
GetConsoleScreenBufferInfo( s_HOutput, &csbi );
|
|
/* return csbi.dwMaximumWindowSize.Y; */
|
|
/* return HB_MAX( csbi.srWindow.Bottom - csbi.srWindow.Top + 1, 25 ); */
|
|
return HB_MAX( csbi.dwSize.Y, 25 );
|
|
}
|
|
|
|
void hb_gt_SetPos( SHORT iRow, SHORT iCol, SHORT iMethod )
|
|
{
|
|
COORD dwCursorPosition;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_SetPos(%hd, %hd, %hd)", iRow, iCol, iMethod));
|
|
|
|
HB_SYMBOL_UNUSED( iMethod );
|
|
|
|
dwCursorPosition.X = iCol;
|
|
dwCursorPosition.Y = iRow;
|
|
|
|
SetConsoleCursorPosition( s_HActive, dwCursorPosition );
|
|
}
|
|
|
|
USHORT hb_gt_GetCursorStyle( void )
|
|
{
|
|
CONSOLE_CURSOR_INFO cci;
|
|
USHORT uiCursorShape;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_GetCursorStyle()"));
|
|
|
|
GetConsoleCursorInfo( s_HActive, &cci );
|
|
|
|
if( ! cci.bVisible )
|
|
{
|
|
uiCursorShape = SC_NONE;
|
|
}
|
|
else
|
|
{
|
|
switch( cci.dwSize )
|
|
{
|
|
case 50:
|
|
uiCursorShape = SC_INSERT; /* half block in clipper */
|
|
break;
|
|
|
|
case 99:
|
|
uiCursorShape = SC_SPECIAL1; /* full block in clipper */
|
|
break;
|
|
|
|
case 66:
|
|
uiCursorShape = SC_SPECIAL2; /* upper half block in clipper */
|
|
break;
|
|
/* TODO: cannot tell if the block is upper or lower for cursor */
|
|
/* Answer: Supposed to be upper third, but ms don't support it. */
|
|
|
|
default:
|
|
uiCursorShape = SC_NORMAL; /* anything else, we'll call it normal */
|
|
break;
|
|
}
|
|
}
|
|
|
|
return uiCursorShape;
|
|
}
|
|
|
|
void hb_gt_SetCursorStyle( USHORT style )
|
|
{
|
|
CONSOLE_CURSOR_INFO cci;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_SetCursorStyle(%hu)", style));
|
|
|
|
GetConsoleCursorInfo( s_HActive, &cci );
|
|
|
|
switch( style )
|
|
{
|
|
case SC_NONE:
|
|
cci.bVisible = FALSE;
|
|
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: /* traps for invalid values */
|
|
cci.bVisible = TRUE;
|
|
cci.dwSize = 25; /* this was 12, but when used in full screen dos window
|
|
cursor state is erratic - doesn't turn off, etc. */
|
|
break;
|
|
}
|
|
|
|
s_bOldCursor = cci.bVisible;
|
|
|
|
SetConsoleCursorInfo( s_HActive, &cci );
|
|
}
|
|
|
|
static void hb_gt_xPutch( USHORT uiRow, USHORT uiCol, BYTE attr, BYTE byChar )
|
|
{
|
|
DWORD dwWritten;
|
|
COORD coord;
|
|
char tmp[ 2 ];
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_xPutch(%hu, %hu, %d, %i)", uiRow, uiCol, (int) attr, byChar));
|
|
|
|
/* TOFIX: add correct support for a single byte instead of a string
|
|
*/
|
|
tmp[ 0 ] = byChar;
|
|
tmp[ 1 ] = '\0';
|
|
|
|
coord.X = ( SHORT ) uiCol;
|
|
coord.Y = ( SHORT ) uiRow;
|
|
|
|
FillConsoleOutputAttribute( s_HOutput, ( WORD )( attr & 0xFF ), ( DWORD ) 1, coord, &dwWritten );
|
|
WriteConsoleOutputCharacterA( s_HOutput, tmp, 1, coord, &dwWritten );
|
|
}
|
|
|
|
void hb_gt_Puts( USHORT uiRow, USHORT uiCol, BYTE attr, BYTE * str, ULONG len )
|
|
{
|
|
DWORD dwWritten;
|
|
COORD coord;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_Puts(%hu, %hu, %d, %p, %lu)", uiRow, uiCol, (int) attr, str, len));
|
|
|
|
coord.X = ( SHORT ) uiCol;
|
|
coord.Y = ( SHORT ) uiRow;
|
|
|
|
FillConsoleOutputAttribute( s_HOutput, ( WORD )( attr & 0xFF ), ( DWORD ) len, coord, &dwWritten );
|
|
WriteConsoleOutputCharacterA( s_HOutput, ( char * ) str, ( DWORD ) len, coord, &dwWritten );
|
|
}
|
|
|
|
int hb_gt_RectSize( USHORT rows, USHORT cols )
|
|
{
|
|
return rows * cols * 2;
|
|
}
|
|
|
|
void hb_gt_GetText( USHORT uiTop, USHORT uiLeft, USHORT uiBottom, USHORT uiRight, BYTE * dest )
|
|
{
|
|
LPWORD pwattr;
|
|
BYTE * pstr;
|
|
USHORT width;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_GetText(%hu, %hu, %hu, %hu, %p)", uiTop, uiLeft, uiBottom, uiRight, dest));
|
|
|
|
width = ( uiRight - uiLeft + 1 );
|
|
pwattr = ( LPWORD ) hb_xgrab( width * sizeof( *pwattr ) );
|
|
pstr = ( BYTE * ) hb_xgrab( width );
|
|
|
|
for( ; uiTop <= uiBottom; uiTop++ )
|
|
{
|
|
COORD coord;
|
|
USHORT i;
|
|
DWORD dwWritten;
|
|
|
|
coord.X = ( SHORT ) uiLeft;
|
|
coord.Y = ( SHORT ) uiTop;
|
|
ReadConsoleOutputCharacterA( s_HOutput, ( char * ) pstr, width, coord, &dwWritten );
|
|
ReadConsoleOutputAttribute( s_HOutput, pwattr, width, coord, &dwWritten );
|
|
for( i = 0; i < width; i++ )
|
|
{
|
|
*dest = *( pstr + i );
|
|
dest++;
|
|
*dest = ( BYTE ) *( pwattr + i ) & 0xFF;
|
|
dest++;
|
|
}
|
|
}
|
|
|
|
hb_xfree( pstr );
|
|
hb_xfree( pwattr );
|
|
}
|
|
|
|
void hb_gt_PutText( USHORT uiTop, USHORT uiLeft, USHORT uiBottom, USHORT uiRight, BYTE * srce )
|
|
{
|
|
LPWORD pwattr;
|
|
BYTE * pstr;
|
|
USHORT width;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_PutText(%hu, %hu, %hu, %hu, %p)", uiTop, uiLeft, uiBottom, uiRight, srce));
|
|
|
|
width = ( uiRight - uiLeft + 1 );
|
|
pwattr = ( LPWORD ) hb_xgrab( width * sizeof( *pwattr ) );
|
|
pstr = ( BYTE * ) hb_xgrab( width );
|
|
|
|
for( ; uiTop <= uiBottom; uiTop++ )
|
|
{
|
|
COORD coord;
|
|
USHORT i;
|
|
DWORD dwWritten;
|
|
|
|
for( i = 0; i < width; i++ )
|
|
{
|
|
*( pstr + i ) = *srce;
|
|
srce++;
|
|
*( pwattr + i ) = ( ( WORD )( ( BYTE ) *srce ) & 0xFF );
|
|
srce++;
|
|
}
|
|
coord.X = ( SHORT ) uiLeft;
|
|
coord.Y = ( SHORT ) uiTop;
|
|
WriteConsoleOutputAttribute( s_HOutput, pwattr, width, coord, &dwWritten );
|
|
WriteConsoleOutputCharacterA( s_HOutput, ( char * ) pstr, width, coord, &dwWritten );
|
|
}
|
|
|
|
hb_xfree( pstr );
|
|
hb_xfree( pwattr );
|
|
}
|
|
|
|
void hb_gt_SetAttribute( USHORT uiTop, USHORT uiLeft, USHORT uiBottom, USHORT uiRight, BYTE attr )
|
|
{
|
|
/* ptucker */
|
|
|
|
COORD coord;
|
|
USHORT width;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_SetAttribute(%hu, %hu, %hu, %hu, %d)", uiTop, uiLeft, uiBottom, uiRight, (int) attr));
|
|
|
|
width = uiRight - uiLeft + 1;
|
|
|
|
coord.X = ( SHORT ) uiLeft;
|
|
|
|
for( ; uiTop <= uiBottom; uiTop++ )
|
|
{
|
|
DWORD dwWritten;
|
|
|
|
coord.Y = uiTop;
|
|
FillConsoleOutputAttribute( s_HOutput, ( WORD )( attr & 0xFF ), width, coord, &dwWritten );
|
|
}
|
|
}
|
|
|
|
SHORT hb_gt_Col( void )
|
|
{
|
|
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_Col()"));
|
|
|
|
GetConsoleScreenBufferInfo( s_HActive, &csbi );
|
|
|
|
return csbi.dwCursorPosition.X;
|
|
}
|
|
|
|
SHORT hb_gt_Row( void )
|
|
{
|
|
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_Row()"));
|
|
|
|
GetConsoleScreenBufferInfo( s_HActive, &csbi );
|
|
|
|
return csbi.dwCursorPosition.Y;
|
|
}
|
|
|
|
void hb_gt_Scroll( USHORT uiTop, USHORT uiLeft, USHORT uiBottom, USHORT uiRight, BYTE attr, SHORT iVert, SHORT iHoriz )
|
|
{
|
|
/* ptucker */
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_Scroll(%hu, %hu, %hu, %hu, %d, %hd, %hd)", uiTop, uiLeft, uiBottom, uiRight, (int) attr, iVert, iHoriz));
|
|
|
|
if( ( iHoriz | iVert ) == 0 ) /* both zero? */
|
|
{
|
|
COORD coord;
|
|
USHORT width = uiRight - uiLeft + 1;
|
|
|
|
coord.X = ( SHORT ) uiLeft;
|
|
|
|
for( ; uiTop <= uiBottom; uiTop++ )
|
|
{
|
|
DWORD dwWritten;
|
|
|
|
coord.Y = uiTop;
|
|
FillConsoleOutputAttribute( s_HOutput, ( WORD )( attr & 0xFF ), width, coord, &dwWritten );
|
|
FillConsoleOutputCharacter( s_HOutput, ' ', width, coord, &dwWritten );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SMALL_RECT Source, Clip;
|
|
COORD Target;
|
|
CHAR_INFO FillChar;
|
|
|
|
Source.Top = uiTop;
|
|
Source.Left = uiLeft;
|
|
Source.Bottom = uiBottom;
|
|
Source.Right = uiRight;
|
|
|
|
memcpy( &Clip, &Source, sizeof( SMALL_RECT ) );
|
|
|
|
Target.Y = uiTop - iVert;
|
|
Target.X = uiLeft - iHoriz;
|
|
|
|
FillChar.Char.AsciiChar = ' ';
|
|
FillChar.Attributes = ( WORD )( attr & 0xFF );
|
|
|
|
ScrollConsoleScreenBuffer( s_HOutput, &Source, &Clip, Target, &FillChar );
|
|
}
|
|
}
|
|
|
|
void hb_gt_DispBegin( void )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_DispBegin()"));
|
|
|
|
/* ptucker */
|
|
|
|
if( ++s_uiDispCount == 1 )
|
|
{
|
|
COORD coDest = { 0, 0 };
|
|
COORD coBuf; /* the size of the buffer to read into */
|
|
CHAR_INFO * pCharInfo; /* buffer to store info from ReadConsoleOutput */
|
|
SMALL_RECT srWin; /* source rectangle to read from */
|
|
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
|
|
|
GetConsoleScreenBufferInfo( s_HOutput, &csbi );
|
|
srWin.Top = srWin.Left = 0;
|
|
srWin.Bottom = ( coBuf.Y = csbi.dwSize.Y ) - 1;
|
|
srWin.Right = ( coBuf.X = csbi.dwSize.X ) - 1;
|
|
|
|
/* allocate a buffer for the screen rectangle */
|
|
pCharInfo = ( CHAR_INFO * ) hb_xgrab( coBuf.Y * coBuf.X * sizeof( CHAR_INFO ) );
|
|
|
|
/* read the screen rectangle into the buffer */
|
|
ReadConsoleOutput( s_HOutput, /* current screen handle */
|
|
pCharInfo, /* transfer area */
|
|
coBuf, /* size of destination buffer */
|
|
coDest, /* upper-left cell to write data to */
|
|
&srWin ); /* screen buffer rectangle to read from */
|
|
|
|
WriteConsoleOutput( s_HInactive, /* output handle */
|
|
pCharInfo, /* data to write */
|
|
coBuf, /* col/row size of source buffer */
|
|
coDest, /* upper-left cell to write data from in src */
|
|
&srWin ); /* screen buffer rect to write data to */
|
|
|
|
s_HOutput = s_HInactive;
|
|
|
|
{
|
|
CONSOLE_CURSOR_INFO cci;
|
|
|
|
GetConsoleCursorInfo( s_HActive, &cci );
|
|
s_bOldCursor = cci.bVisible;
|
|
cci.bVisible = FALSE;
|
|
SetConsoleCursorInfo( s_HActive, &cci );
|
|
}
|
|
|
|
hb_xfree( pCharInfo );
|
|
}
|
|
}
|
|
|
|
void hb_gt_DispEnd( void )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_DispEnd()"));
|
|
|
|
/* ptucker */
|
|
|
|
if( --s_uiDispCount == 0 )
|
|
{
|
|
s_HInactive = s_HActive;
|
|
s_HActive = s_HOutput;
|
|
SetConsoleActiveScreenBuffer( s_HActive );
|
|
|
|
{
|
|
CONSOLE_CURSOR_INFO cci;
|
|
|
|
GetConsoleCursorInfo( s_HActive, &cci );
|
|
cci.bVisible = s_bOldCursor;
|
|
SetConsoleCursorInfo( s_HActive, &cci );
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOL hb_gt_SetMode( USHORT uiRows, USHORT uiCols )
|
|
{
|
|
/* ptucker */
|
|
BOOL bRetVal = TRUE;
|
|
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
|
SMALL_RECT srWin;
|
|
COORD coBuf;
|
|
USHORT uiDispCount = s_uiDispCount;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_SetMode(%hu, %hu)", uiRows, uiCols));
|
|
|
|
while( s_uiDispCount )
|
|
hb_gt_DispEnd();
|
|
|
|
GetConsoleScreenBufferInfo( s_HOutput, &csbi );
|
|
coBuf = GetLargestConsoleWindowSize( s_HOutput );
|
|
|
|
/* new console window size and scroll position */
|
|
srWin.Top = srWin.Left = 0;
|
|
srWin.Bottom = ( SHORT ) ( HB_MIN( uiRows, coBuf.Y ) - 1 );
|
|
srWin.Right = ( SHORT ) ( HB_MIN( uiCols, coBuf.X ) - 1 );
|
|
|
|
/* new console buffer size */
|
|
coBuf.Y = uiRows;
|
|
coBuf.X = uiCols;
|
|
|
|
/* if the current buffer is larger than what we want, resize the */
|
|
/* console window first, then the buffer */
|
|
if( ( DWORD ) csbi.dwSize.X * csbi.dwSize.Y > ( DWORD ) uiCols * uiRows )
|
|
{
|
|
/* TODO: these calls are a temporary solution */
|
|
SetConsoleWindowInfo( s_HActive, TRUE, &srWin );
|
|
SetConsoleScreenBufferSize( s_HActive, coBuf );
|
|
SetConsoleWindowInfo( s_HInactive, TRUE, &srWin );
|
|
SetConsoleScreenBufferSize( s_HInactive, coBuf );
|
|
if( !SetConsoleWindowInfo( s_HOutput, TRUE, &srWin ) ||
|
|
!SetConsoleScreenBufferSize( s_HOutput, coBuf ) )
|
|
bRetVal = FALSE;
|
|
}
|
|
else if( ( DWORD ) csbi.dwSize.X * csbi.dwSize.Y < ( DWORD ) uiCols * uiRows )
|
|
{
|
|
/* TODO: these calls are a temporary solution */
|
|
SetConsoleScreenBufferSize( s_HActive, coBuf );
|
|
SetConsoleWindowInfo( s_HActive, TRUE, &srWin );
|
|
SetConsoleScreenBufferSize( s_HInactive, coBuf );
|
|
SetConsoleWindowInfo( s_HInactive, TRUE, &srWin );
|
|
if( !SetConsoleScreenBufferSize( s_HOutput, coBuf ) ||
|
|
!SetConsoleWindowInfo( s_HOutput, TRUE, &srWin ) )
|
|
bRetVal = FALSE;
|
|
}
|
|
|
|
while( s_uiDispCount < uiDispCount )
|
|
hb_gt_DispBegin();
|
|
|
|
return bRetVal;
|
|
}
|
|
|
|
void hb_gt_Replicate( USHORT uiRow, USHORT uiCol, BYTE byAttr, BYTE byChar, ULONG ulLength )
|
|
{
|
|
|
|
/* ptucker */
|
|
COORD coBuf;
|
|
DWORD dwWritten;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_Replicate(%hu, %hu, %i, %i, %lu)", uiRow, uiCol, byAttr, byChar, ulLength));
|
|
|
|
coBuf.Y = uiRow;
|
|
coBuf.X = uiCol;
|
|
|
|
FillConsoleOutputAttribute( s_HOutput, ( WORD )( byAttr & 0xFF ), ( DWORD )ulLength, coBuf, &dwWritten );
|
|
FillConsoleOutputCharacter(
|
|
s_HOutput, /* handle to screen buffer */
|
|
byChar, /* character to write */
|
|
( DWORD ) ulLength, /* number of cells to write */
|
|
coBuf, /* coordinates of first cell */
|
|
&dwWritten /* receives actual number written */
|
|
);
|
|
|
|
}
|
|
|
|
BOOL hb_gt_GetBlink()
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_GetBlink()"));
|
|
|
|
/* TODO */
|
|
return FALSE;
|
|
}
|
|
|
|
void hb_gt_SetBlink( BOOL bBlink )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_SetBlink(%d)", (int) bBlink));
|
|
|
|
/* TODO: set the bit if it's supported */
|
|
HB_SYMBOL_UNUSED( bBlink );
|
|
}
|
|
|
|
#if 0
|
|
|
|
static void hb_gt_DebugScreen( BOOL bActivate )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_DebugScreen(%d)", (int) bActivate));
|
|
|
|
/* ptucker */
|
|
/* TODO: This is not used and is still a work in progress */
|
|
if( bActivate )
|
|
{
|
|
if( s_HDOutput == INVALID_HANDLE_VALUE )
|
|
{
|
|
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
|
SMALL_RECT srWin;
|
|
|
|
s_HDOutput = CreateConsoleScreenBuffer(
|
|
GENERIC_READ | GENERIC_WRITE, /* Access flag */
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE, /* Buffer share mode */
|
|
NULL, /* Security attribute */
|
|
CONSOLE_TEXTMODE_BUFFER, /* Type of buffer */
|
|
NULL ); /* reserved */
|
|
|
|
|
|
GetConsoleScreenBufferInfo( s_HOutput, &csbi );
|
|
|
|
/* new console window size and scroll position */
|
|
srWin.Top = srWin.Left = 0;
|
|
srWin.Bottom = csbi.dwSize.Y - 1;
|
|
srWin.Right = csbi.dwSize.X - 1;
|
|
|
|
SetConsoleScreenBufferSize( s_HDOutput, csbi.dwSize );
|
|
SetConsoleWindowInfo( s_HDOutput, TRUE, &csbi.srWindow );
|
|
SetConsoleWindowInfo( s_HDOutput, FALSE, &srWin );
|
|
}
|
|
s_HOsave = s_HOutput;
|
|
s_HOutput = s_HActive = s_HDOutput;
|
|
|
|
hb_gt_DispBegin();
|
|
hb_gt_DispEnd();
|
|
}
|
|
else
|
|
{
|
|
s_HOutput = s_HOsave;
|
|
s_HActive = s_HOriginal;
|
|
}
|
|
SetConsoleActiveScreenBuffer( s_HOutput );
|
|
}
|
|
|
|
#endif
|
|
|
|
void hb_gt_Tone( double dFrequency, double dDuration )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_Tone(%lf, %lf)", dFrequency, dDuration));
|
|
|
|
/* The conversion from Clipper timer tick units to
|
|
milliseconds is * 1000.0 / 18.2. */
|
|
|
|
dDuration = dDuration * 1000.0 / 18.2; /* milliseconds */
|
|
dDuration = HB_MIN( HB_MAX( 0, dDuration ), ULONG_MAX );
|
|
|
|
if( dDuration > 0.0 ) {
|
|
/* Bad news for non-NT Windows platforms: Beep() ignores
|
|
both parameters and either generates the default sound
|
|
event or the standard system beep. */
|
|
Beep( ( ULONG ) HB_MIN( HB_MAX( 0.0, dFrequency ), 32767.0 ),
|
|
( ULONG ) dDuration );
|
|
}
|
|
}
|
|
|
|
char * hb_gt_Version( void )
|
|
{
|
|
return "Harbour Terminal: Win32 console";
|
|
}
|
|
|
|
USHORT hb_gt_DispCount()
|
|
{
|
|
return s_uiDispCount;
|
|
}
|
|
|
|
USHORT hb_gt_Box( SHORT Top, SHORT Left, SHORT Bottom, SHORT Right,
|
|
BYTE * szBox, BYTE byAttr )
|
|
{
|
|
USHORT ret = 1;
|
|
SHORT Row;
|
|
SHORT Col;
|
|
SHORT Height;
|
|
SHORT Width;
|
|
|
|
if( Left >= 0 || Left < hb_gt_GetScreenWidth()
|
|
|| Right >= 0 || Right < hb_gt_GetScreenWidth()
|
|
|| Top >= 0 || Top < hb_gt_GetScreenHeight()
|
|
|| Bottom >= 0 || Bottom < hb_gt_GetScreenHeight() )
|
|
{
|
|
|
|
/* Ensure that box is drawn from top left to bottom right. */
|
|
if( Top > Bottom )
|
|
{
|
|
SHORT tmp = Top;
|
|
Top = Bottom;
|
|
Bottom = tmp;
|
|
}
|
|
if( Left > Right )
|
|
{
|
|
SHORT tmp = Left;
|
|
Left = Right;
|
|
Right = tmp;
|
|
}
|
|
|
|
/* Draw the box or line as specified */
|
|
Height = Bottom - Top + 1;
|
|
Width = Right - Left + 1;
|
|
|
|
hb_gt_DispBegin();
|
|
|
|
if( Height > 1 && Width > 1 && Top >= 0 && Top < hb_gt_GetScreenHeight() && Left >= 0 && Left < hb_gt_GetScreenWidth() )
|
|
hb_gt_xPutch( Top, Left, byAttr, szBox[ 0 ] ); /* Upper left corner */
|
|
|
|
Col = ( Height > 1 ? Left + 1 : Left );
|
|
if(Col < 0 )
|
|
{
|
|
Width += Col;
|
|
Col = 0;
|
|
}
|
|
if( Right >= hb_gt_GetScreenWidth() )
|
|
{
|
|
Width -= Right - hb_gt_GetScreenWidth();
|
|
}
|
|
|
|
if( Col <= Right && Col < hb_gt_GetScreenWidth() && Top >= 0 && Top < hb_gt_GetScreenHeight() )
|
|
hb_gt_Replicate( Top, Col, byAttr, szBox[ 1 ], Width + ( (Right - Left) > 1 ? -2 : 0 ) ); /* Top line */
|
|
|
|
if( Height > 1 && (Right - Left) > 1 && Right < hb_gt_GetScreenWidth() && Top >= 0 && Top < hb_gt_GetScreenHeight() )
|
|
hb_gt_xPutch( Top, Right, byAttr, szBox[ 2 ] ); /* Upper right corner */
|
|
|
|
if( szBox[ 8 ] && Height > 2 && Width > 2 )
|
|
{
|
|
for( Row = Top + 1; Row < Bottom; Row++ )
|
|
{
|
|
if( Row >= 0 && Row < hb_gt_GetScreenHeight() )
|
|
{
|
|
Col = Left;
|
|
if( Col < 0 )
|
|
Col = 0; /* The width was corrected earlier. */
|
|
else
|
|
hb_gt_xPutch( Row, Col++, byAttr, szBox[ 7 ] ); /* Left side */
|
|
hb_gt_Replicate( Row, Col, byAttr, szBox[ 8 ], Width - 2 ); /* Fill */
|
|
if( Right < hb_gt_GetScreenWidth() )
|
|
hb_gt_xPutch( Row, Right, byAttr, szBox[ 3 ] ); /* Right side */
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for( Row = ( Width > 1 ? Top + 1 : Top ); Row < ( (Right - Left ) > 1 ? Bottom : Bottom + 1 ); Row++ )
|
|
{
|
|
if( Row >= 0 && Row < hb_gt_GetScreenHeight() )
|
|
{
|
|
if( Left >= 0 && Left < hb_gt_GetScreenWidth() )
|
|
hb_gt_xPutch( Row, Left, byAttr, szBox[ 7 ] ); /* Left side */
|
|
if( ( Width > 1 || Left < 0 ) && Right < hb_gt_GetScreenWidth() )
|
|
hb_gt_xPutch( Row, Right, byAttr, szBox[ 3 ] ); /* Right side */
|
|
}
|
|
}
|
|
}
|
|
|
|
if( Height > 1 && Width > 1 )
|
|
{
|
|
if( Left >= 0 && Bottom < hb_gt_GetScreenHeight() )
|
|
hb_gt_xPutch( Bottom, Left, byAttr, szBox[ 6 ] ); /* Bottom left corner */
|
|
|
|
Col = Left + 1;
|
|
if( Col < 0 )
|
|
Col = 0; /* The width was corrected earlier. */
|
|
|
|
if( Col <= Right && Bottom < hb_gt_GetScreenHeight() )
|
|
hb_gt_Replicate( Bottom, Col, byAttr, szBox[ 5 ], Width - 2 ); /* Bottom line */
|
|
|
|
if( Right < hb_gt_GetScreenWidth() && Bottom < hb_gt_GetScreenHeight() )
|
|
hb_gt_xPutch( Bottom, Right, byAttr, szBox[ 4 ] ); /* Bottom right corner */
|
|
}
|
|
hb_gt_DispEnd();
|
|
ret = 0;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
USHORT hb_gt_BoxD( SHORT Top, SHORT Left, SHORT Bottom, SHORT Right, BYTE * pbyFrame, BYTE byAttr )
|
|
{
|
|
return hb_gt_Box( Top, Left, Bottom, Right, pbyFrame, byAttr );
|
|
}
|
|
|
|
USHORT hb_gt_BoxS( SHORT Top, SHORT Left, SHORT Bottom, SHORT Right, BYTE * pbyFrame, BYTE byAttr )
|
|
{
|
|
return hb_gt_Box( Top, Left, Bottom, Right, pbyFrame, byAttr );
|
|
}
|
|
|
|
USHORT hb_gt_HorizLine( SHORT Row, SHORT Left, SHORT Right, BYTE byChar, BYTE byAttr )
|
|
{
|
|
USHORT ret = 1;
|
|
if( Row >= 0 && Row < hb_gt_GetScreenHeight() )
|
|
{
|
|
if( Left < 0 )
|
|
Left = 0;
|
|
else if( Left >= hb_gt_GetScreenWidth() )
|
|
Left = hb_gt_GetScreenWidth() - 1;
|
|
|
|
if( Right < 0 )
|
|
Right = 0;
|
|
else if( Right >= hb_gt_GetScreenWidth() )
|
|
Right = hb_gt_GetScreenWidth() - 1;
|
|
|
|
if( Left < Right )
|
|
hb_gt_Replicate( Row, Left, byAttr, byChar, Right - Left + 1 );
|
|
else
|
|
hb_gt_Replicate( Row, Right, byAttr, byChar, Left - Right + 1 );
|
|
ret = 0;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
USHORT hb_gt_VertLine( SHORT Col, SHORT Top, SHORT Bottom, BYTE byChar, BYTE byAttr )
|
|
{
|
|
USHORT ret = 1;
|
|
USHORT Row;
|
|
|
|
if( Col >= 0 && Col < hb_gt_GetScreenWidth() )
|
|
{
|
|
if( Top < 0 )
|
|
Top = 0;
|
|
else if( Top >= hb_gt_GetScreenHeight() )
|
|
Top = hb_gt_GetScreenHeight() - 1;
|
|
|
|
if( Bottom < 0 )
|
|
Bottom = 0;
|
|
else if( Bottom >= hb_gt_GetScreenHeight() )
|
|
Bottom = hb_gt_GetScreenHeight() - 1;
|
|
|
|
if( Top <= Bottom )
|
|
Row = Top;
|
|
else
|
|
{
|
|
Row = Bottom;
|
|
Bottom = Top;
|
|
}
|
|
while( Row <= Bottom )
|
|
hb_gt_xPutch( Row++, Col, byAttr, byChar );
|
|
ret = 0;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
BOOL hb_gt_PreExt()
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL hb_gt_PostExt()
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL hb_gt_Suspend()
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL hb_gt_Resume()
|
|
{
|
|
return TRUE;
|
|
}
|