904 lines
26 KiB
C
904 lines
26 KiB
C
/*
|
|
* $Id$
|
|
*/
|
|
|
|
/*
|
|
* Harbour Project source code:
|
|
* Video subsystem for OS/2 compilers
|
|
*
|
|
* Copyright 1999 - 2001 Harbour Project
|
|
* 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 David G. Holm <dholm@jsd-llc.com>
|
|
* hb_gt_os2_ReadKey()
|
|
*
|
|
* Copyright 1999 Chen Kedem <niki@actcom.co.il>
|
|
* hb_gt_os2_mouse_Init()
|
|
* hb_gt_os2_mouse_Exit()
|
|
* hb_gt_os2_mouse_IsPresent()
|
|
* hb_gt_os2_mouse_Show()
|
|
* hb_gt_os2_mouse_Hide()
|
|
* hb_gt_os2_mouse_SetPos()
|
|
* hb_gt_os2_mouse_CountButton()
|
|
* hb_gt_os2_Tone()
|
|
* hb_gt_os2_IsColor()
|
|
* hb_gt_os2_SetCursorSize()
|
|
* hb_gt_os2_GetCharHeight()
|
|
* hb_gt_os2_GetCursorStyle()
|
|
* hb_gt_os2_SetCursorStyle()
|
|
* hb_gt_os2_GetBlink()
|
|
* hb_gt_os2_SetBlink()
|
|
*
|
|
* Copyright 2000 - 2001 Maurilio Longo <maurilio.longo@libero.it>
|
|
* hb_gt_DispBegin() / hb_gt_DispEnd()
|
|
* hb_gt_ScreenPtr() and hb_gt_xYYYY() functions and virtual screen support inside hb_gt_XXXX()s
|
|
* 16 bit KBD subsystem use inside hb_gt_os2_ReadKey()
|
|
*
|
|
* See doc/license.txt for licensing terms.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* This module is partially based on VIDMGR by Andrew Clarke and modified
|
|
* for the Harbour project
|
|
*/
|
|
|
|
/* NOTE: User programs should never call this layer directly! */
|
|
|
|
#define INCL_BASE
|
|
#define INCL_VIO
|
|
#define INCL_KBD
|
|
#define INCL_MOU
|
|
#define INCL_DOSMEMMGR
|
|
#define INCL_DOSPROCESS
|
|
#define INCL_NOPMAPI
|
|
|
|
#define HB_GT_NAME OS2
|
|
|
|
#include "hbgtcore.h"
|
|
#include "hbinit.h"
|
|
#include "hbapierr.h"
|
|
#include "hbapiitm.h"
|
|
#include "inkey.ch"
|
|
|
|
#ifdef _HB_OS2_H
|
|
#include "hbos2.h"
|
|
#endif
|
|
|
|
/* convert 16:16 address to 0:32 */
|
|
#define SELTOFLAT(ptr) (void *)(((((ULONG)(ptr))>>19)<<16)|(0xFFFF&((ULONG)(ptr))))
|
|
|
|
#if defined(HARBOUR_GCC_OS2)
|
|
/* 25/03/2000 - maurilio.longo@libero.it
|
|
OS/2 GCC hasn't got ToolKit headers available */
|
|
#include <stdlib.h>
|
|
#else
|
|
#include <bsedos.h>
|
|
#ifndef KBDTRF_EXTENDED_CODE
|
|
#define KBDTRF_EXTENDED_CODE 0x02
|
|
#endif
|
|
#endif
|
|
#include <conio.h>
|
|
|
|
static int s_GtId;
|
|
static HB_GT_FUNCS SuperTable;
|
|
#define HB_GTSUPER (&SuperTable)
|
|
#define HB_GTID_PTR (&s_GtId)
|
|
|
|
static int s_iCurRow;
|
|
static int s_iCurCol;
|
|
static int s_iCursorStyle;
|
|
|
|
/* buffer for single screen line */
|
|
static int s_iLineBufSize = 0;
|
|
static BYTE * s_sLineBuf;
|
|
|
|
/* Code page ID of active codepage at the time harbour program was start */
|
|
static USHORT s_usOldCodePage;
|
|
|
|
/* Instead of calling VioGetMode() every time I need MaxRow() or MaxCol() I
|
|
use this static which contains active mode info */
|
|
static VIOMODEINFO s_vi;
|
|
|
|
/* keyboard event record */
|
|
static PKBDKEYINFO s_key;
|
|
/* keyboard handle, 0 == default */
|
|
static PHKBD s_hk;
|
|
|
|
/* mouse logical handle */
|
|
static HMOU s_uMouHandle;
|
|
|
|
static void hb_gt_os2_mouse_Init( PHB_GT pGT )
|
|
{
|
|
USHORT fsEvents = MOUSE_MOTION_WITH_BN1_DOWN | MOUSE_BN1_DOWN |
|
|
MOUSE_MOTION_WITH_BN2_DOWN | MOUSE_BN2_DOWN |
|
|
MOUSE_MOTION_WITH_BN3_DOWN | MOUSE_BN3_DOWN ;
|
|
|
|
HB_SYMBOL_UNUSED( pGT );
|
|
|
|
if( MouOpen ( 0L, &s_uMouHandle ) ) /* try to open mouse */
|
|
s_uMouHandle = 0; /* no mouse found */
|
|
else
|
|
MouSetEventMask ( &fsEvents, s_uMouHandle ); /* mask some events */
|
|
}
|
|
|
|
static void hb_gt_os2_mouse_Exit( PHB_GT pGT )
|
|
{
|
|
HB_SYMBOL_UNUSED( pGT );
|
|
|
|
if( s_uMouHandle )
|
|
{
|
|
MouClose( s_uMouHandle ); /* relese mouse handle */
|
|
s_uMouHandle = 0;
|
|
}
|
|
}
|
|
|
|
static BOOL hb_gt_os2_mouse_IsPresent( PHB_GT pGT )
|
|
{
|
|
HB_SYMBOL_UNUSED( pGT );
|
|
|
|
return s_uMouHandle != 0;
|
|
}
|
|
|
|
static void hb_gt_os2_mouse_Show( PHB_GT pGT )
|
|
{
|
|
HB_SYMBOL_UNUSED( pGT );
|
|
|
|
if( s_uMouHandle )
|
|
MouDrawPtr( s_uMouHandle );
|
|
}
|
|
|
|
static void hb_gt_os2_mouse_Hide( PHB_GT pGT )
|
|
{
|
|
/*
|
|
NOTE: mouse cursor always visible if not in full screen
|
|
*/
|
|
HB_SYMBOL_UNUSED( pGT );
|
|
|
|
if( s_uMouHandle )
|
|
{
|
|
NOPTRRECT rect;
|
|
VIOMODEINFO vi; /* needed to get max Row/Col */
|
|
|
|
/*
|
|
QUESTION: should I call the GT MaxRow/Col function ?
|
|
pro: encapsulating of the GetScreen function
|
|
con: calling function from another module, GT must be linked in
|
|
con: VioGetMode is been called twice
|
|
*/
|
|
vi.cb = sizeof(VIOMODEINFO);
|
|
VioGetMode( &vi, 0 );
|
|
rect.row = 0; /* x-coordinate upper left */
|
|
rect.col = 0; /* y-coordinate upper left */
|
|
rect.cRow = vi.row - 1; /* x-coordinate lower right */
|
|
rect.cCol = vi.col - 1; /* y-coordinate lower right */
|
|
MouRemovePtr( &rect, s_uMouHandle );
|
|
}
|
|
}
|
|
|
|
static void hb_gt_os2_mouse_GetPos( PHB_GT pGT, int * row, int * col )
|
|
{
|
|
HB_SYMBOL_UNUSED( pGT );
|
|
|
|
if( s_uMouHandle )
|
|
{
|
|
PTRLOC pos;
|
|
MouGetPtrPos( &pos, s_uMouHandle );
|
|
*row = ( int ) pos.row;
|
|
*col = ( int ) pos.col;
|
|
}
|
|
}
|
|
|
|
static void hb_gt_os2_mouse_SetPos( PHB_GT pGT, int row, int col )
|
|
{
|
|
HB_SYMBOL_UNUSED( pGT );
|
|
|
|
if( s_uMouHandle )
|
|
{
|
|
PTRLOC pos;
|
|
pos.row = ( USHORT ) row;
|
|
pos.col = ( USHORT ) col;
|
|
MouSetPtrPos( &pos, s_uMouHandle );
|
|
}
|
|
}
|
|
|
|
typedef struct
|
|
{
|
|
BOOL fDown;
|
|
int iPressed;
|
|
int iPressRow;
|
|
int iPressCol;
|
|
ULONG ulPressTime;
|
|
int iReleased;
|
|
int iReleaseRow;
|
|
int iReleaseCol;
|
|
ULONG ulReleaseTime;
|
|
} HB_OS2_BUTTONSTATE;
|
|
|
|
static HB_OS2_BUTTONSTATE s_ButtonState[ 3 ];
|
|
static ULONG s_ButtonMask[ 3 ] =
|
|
{ MOUSE_BN1_DOWN, MOUSE_BN2_DOWN, MOUSE_BN3_DOWN };
|
|
static ULONG s_ulMouseLastState;
|
|
|
|
static void hb_gt_os2_mouse_ReadMouseState( void )
|
|
{
|
|
if( s_uMouHandle )
|
|
{
|
|
USHORT WaitOption = 0; /* 1 = wait until mouse event exist, 0 = don't */
|
|
MOUEVENTINFO MouEvent;
|
|
if( MouReadEventQue( &MouEvent, &WaitOption, s_uMouHandle ) == NO_ERROR )
|
|
{
|
|
ULONG ulDiff;
|
|
int i;
|
|
|
|
ulDiff = s_ulMouseLastState ^ MouEvent.fs;
|
|
s_ulMouseLastState = MouEvent.fs;
|
|
|
|
for( i = 0; i < 3; ++i )
|
|
{
|
|
if( ulDiff & s_ButtonMask[ i ] )
|
|
{
|
|
if( s_ulMouseLastState & s_ButtonMask[ i ] )
|
|
{
|
|
s_ButtonState[ i ].fDown = TRUE;
|
|
s_ButtonState[ i ].iPressed++;
|
|
s_ButtonState[ i ].iPressRow = MouEvent.row;
|
|
s_ButtonState[ i ].iPressCol = MouEvent.col;
|
|
s_ButtonState[ i ].ulPressTime = MouEvent.time;
|
|
}
|
|
else
|
|
{
|
|
s_ButtonState[ i ].fDown = FALSE;
|
|
s_ButtonState[ i ].iReleased++;
|
|
s_ButtonState[ i ].iReleaseRow = MouEvent.row;
|
|
s_ButtonState[ i ].iReleaseCol = MouEvent.col;
|
|
s_ButtonState[ i ].ulReleaseTime = MouEvent.time;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static BOOL hb_gt_os2_mouse_ButtonState( PHB_GT pGT, int iButton )
|
|
{
|
|
HB_SYMBOL_UNUSED( pGT );
|
|
|
|
hb_gt_os2_mouse_ReadMouseState();
|
|
|
|
if( s_uMouHandle && iButton >= 0 && iButton < 3 )
|
|
return s_ButtonState[ iButton ].fDown;
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
static BOOL hb_gt_os2_mouse_ButtonPressed( PHB_GT pGT, int iButton, int * piRow, int * piCol )
|
|
{
|
|
HB_SYMBOL_UNUSED( pGT );
|
|
|
|
hb_gt_os2_mouse_ReadMouseState();
|
|
|
|
if( s_uMouHandle && iButton >= 0 && iButton < 3 )
|
|
{
|
|
if( s_ButtonState[ iButton ].iPressed )
|
|
{
|
|
s_ButtonState[ iButton ].iPressed = 0;
|
|
*piRow = s_ButtonState[ iButton ].iPressRow;
|
|
*piCol = s_ButtonState[ iButton ].iPressCol;
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static BOOL hb_gt_os2_mouse_ButtonReleased( PHB_GT pGT, int iButton, int * piRow, int * piCol )
|
|
{
|
|
HB_SYMBOL_UNUSED( pGT );
|
|
|
|
hb_gt_os2_mouse_ReadMouseState();
|
|
|
|
if( s_uMouHandle && iButton >= 0 && iButton < 3 )
|
|
{
|
|
if( s_ButtonState[ iButton ].iReleased )
|
|
{
|
|
s_ButtonState[ iButton ].iReleased = 0;
|
|
*piRow = s_ButtonState[ iButton ].iReleaseRow;
|
|
*piCol = s_ButtonState[ iButton ].iReleaseCol;
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static int hb_gt_os2_mouse_CountButton( PHB_GT pGT )
|
|
{
|
|
USHORT usButtons = 0;
|
|
|
|
HB_SYMBOL_UNUSED( pGT );
|
|
|
|
if( s_uMouHandle )
|
|
MouGetNumButtons ( &usButtons, s_uMouHandle );
|
|
|
|
return ( int ) usButtons;
|
|
}
|
|
|
|
static void hb_gt_os2_GetCursorPosition( int * piRow, int * piCol )
|
|
{
|
|
USHORT y, x;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_os2_GetCursorPosition(%p, %p)", piRow, piCol));
|
|
|
|
VioGetCurPos( &y, &x, 0 );
|
|
|
|
*piRow = y;
|
|
*piCol = x;
|
|
}
|
|
|
|
static void hb_gt_os2_SetCursorPosition( int iRow, int iCol )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_os2_SetCursorPosition(%d, %d)", iRow, iCol));
|
|
|
|
if( s_iCurRow != iRow || s_iCurCol != iCol )
|
|
{
|
|
VioSetCurPos( ( USHORT ) iRow, ( USHORT ) iCol, 0 );
|
|
s_iCurRow = iRow;
|
|
s_iCurCol = iCol;
|
|
}
|
|
}
|
|
|
|
static void hb_gt_os2_SetCursorSize( char start, char end, int visible )
|
|
{
|
|
VIOCURSORINFO vi;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_os2_SetCursorSize(%d, %d, %d)", (int) start, (int) end, visible));
|
|
|
|
vi.yStart = start;
|
|
vi.cEnd = end;
|
|
vi.cx = 0;
|
|
vi.attr = ( visible ? 0 : -1 );
|
|
VioSetCurType( &vi, 0 );
|
|
}
|
|
|
|
static unsigned char hb_gt_os2_GetCharHeight()
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_os2_GetCharHeight()"));
|
|
|
|
return ( unsigned char )( s_vi.row ? ( s_vi.vres / s_vi.row ) - 1 : 0 );
|
|
}
|
|
|
|
static int hb_gt_os2_GetCursorStyle( void )
|
|
{
|
|
int iStyle;
|
|
VIOCURSORINFO vi;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_os2_GetCursorStyle()"));
|
|
|
|
VioGetCurType( &vi, 0 );
|
|
|
|
if( vi.attr )
|
|
iStyle = SC_NONE;
|
|
else
|
|
{
|
|
unsigned char charheight = hb_gt_os2_GetCharHeight();
|
|
|
|
if( vi.yStart == 0 && vi.cEnd == 0 )
|
|
iStyle = SC_NONE;
|
|
|
|
else if( ( vi.yStart == charheight - 1 || vi.yStart == charheight - 2 ) &&
|
|
vi.cEnd == charheight )
|
|
iStyle = SC_NORMAL;
|
|
|
|
else if( vi.yStart == charheight >> 1 && vi.cEnd == charheight )
|
|
iStyle = SC_INSERT;
|
|
|
|
else if( vi.yStart == 0 && vi.cEnd == charheight )
|
|
iStyle = SC_SPECIAL1;
|
|
|
|
else if( vi.yStart == 0 && vi.cEnd == charheight >> 1 )
|
|
iStyle = SC_SPECIAL2;
|
|
|
|
else
|
|
iStyle = -1;
|
|
}
|
|
|
|
return iStyle;
|
|
}
|
|
|
|
static void hb_gt_os2_SetCursorStyle( int iStyle )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_os2_SetCursorStyle(%d)", iStyle));
|
|
|
|
if( iStyle != s_iCursorStyle )
|
|
{
|
|
unsigned char charheight = hb_gt_os2_GetCharHeight();
|
|
|
|
switch( iStyle )
|
|
{
|
|
case SC_NONE:
|
|
hb_gt_os2_SetCursorSize( 0, 0, 0 );
|
|
break;
|
|
|
|
case SC_NORMAL:
|
|
hb_gt_os2_SetCursorSize( charheight - 1, charheight, 1 );
|
|
break;
|
|
|
|
case SC_INSERT:
|
|
hb_gt_os2_SetCursorSize( charheight >> 1, charheight, 1 );
|
|
break;
|
|
|
|
case SC_SPECIAL1:
|
|
hb_gt_os2_SetCursorSize( 0, charheight, 1 );
|
|
break;
|
|
|
|
case SC_SPECIAL2:
|
|
hb_gt_os2_SetCursorSize( 0, charheight >> 1, 1 );
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
s_iCursorStyle = iStyle;
|
|
}
|
|
}
|
|
|
|
static void hb_gt_os2_GetScreenContents( PHB_GT pGT )
|
|
{
|
|
int iRow, iCol;
|
|
BYTE * pBufPtr;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_os2_GetScreenContents(%p)", pGT));
|
|
|
|
for( iRow = 0; iRow < s_vi.row; ++iRow )
|
|
{
|
|
USHORT usSize = s_vi.col << 1;
|
|
VioReadCellStr( ( PCH ) s_sLineBuf, &usSize, iRow, 0, 0 );
|
|
|
|
for( iCol = 0, pBufPtr = s_sLineBuf; iCol < s_vi.col; ++iCol, pBufPtr += 2 )
|
|
{
|
|
HB_GTSELF_PUTSCRCHAR( pGT, iRow, iCol, pBufPtr[ 1 ], 0, pBufPtr[ 0 ] );
|
|
}
|
|
}
|
|
HB_GTSELF_COLDAREA( pGT, 0, 0, s_vi.row, s_vi.col );
|
|
}
|
|
|
|
static PVOID hb_gt_os2_allocMem( int iSize )
|
|
{
|
|
APIRET rc; /* return code from DosXXX api call */
|
|
PVOID pMem;
|
|
|
|
rc = DosAllocMem( &pMem, iSize, PAG_COMMIT | OBJ_TILE | PAG_WRITE );
|
|
if( rc != NO_ERROR )
|
|
hb_errInternal( HB_EI_XGRABALLOC, "hb_gt_os2_allocMem() memory allocation failure.", NULL, NULL );
|
|
|
|
return pMem;
|
|
}
|
|
|
|
static void hb_gt_os2_Init( PHB_GT pGT, FHANDLE hFilenoStdin, FHANDLE hFilenoStdout, FHANDLE hFilenoStderr )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_os2_Init(%p,%p,%p,%p)", pGT, hFilenoStdin, hFilenoStdout, hFilenoStderr ) );
|
|
|
|
s_vi.cb = sizeof( VIOMODEINFO );
|
|
VioGetMode( &s_vi, 0 ); /* fill structure with current video mode settings */
|
|
|
|
/* Alloc tileable memory for calling a 16 subsystem */
|
|
s_hk = ( PHKBD ) hb_gt_os2_allocMem( sizeof( HKBD ) );
|
|
/* it is a long after all, so I set it to zero only one time since it never changes */
|
|
memset( s_hk, 0, sizeof( HKBD ) );
|
|
s_key = ( PKBDKEYINFO ) hb_gt_os2_allocMem( sizeof( KBDKEYINFO ) );
|
|
|
|
/* TODO: Is anything else required to initialize the video subsystem?
|
|
I (Maurilio Longo) think that we should set correct codepage
|
|
|
|
COMMENT: The correct behaviour is to inherit the codepage that is
|
|
active when the program is started, which automatically
|
|
happens by not setting the codepage. If somebody wants to
|
|
change the codepage, there should be a separate function
|
|
to do that. (David G. Holm <dholm@jsd-llc.com>)
|
|
|
|
ANSWER: But I have a different code page than you and box drawing
|
|
chars are "wrong". So we need to set code page of
|
|
box drawing chars. (Maurilio Longo - maurilio.longo@libero.it)
|
|
*/
|
|
|
|
/* 21/08/2001 - <maurilio.longo@libero.it>
|
|
NOTE: Box drawing characters need page 437 to show correctly, so, in your
|
|
config.sys you need to have a CODEPAGE=x,y statement where x or y
|
|
is equal to 437
|
|
*/
|
|
|
|
VioGetCp( 0, &s_usOldCodePage, 0 );
|
|
|
|
/* If I could not set codepage 437 I reset previous codepage,
|
|
maybe I do not need to do this */
|
|
if( VioSetCp( 0, 437, 0 ) != NO_ERROR )
|
|
{
|
|
VioSetCp( 0, s_usOldCodePage, 0 );
|
|
}
|
|
|
|
hb_gt_os2_GetCursorPosition( &s_iCurRow, &s_iCurCol );
|
|
s_iCursorStyle = hb_gt_os2_GetCursorStyle();
|
|
|
|
HB_GTSUPER_INIT( pGT, hFilenoStdin, hFilenoStdout, hFilenoStderr );
|
|
HB_GTSELF_RESIZE( pGT, s_vi.row, s_vi.col );
|
|
HB_GTSELF_SETPOS( pGT, s_iCurRow, s_iCurCol );
|
|
if( s_iCursorStyle > 0 )
|
|
HB_GTSELF_SETCURSORSTYLE( pGT, s_iCursorStyle );
|
|
hb_gt_os2_GetScreenContents( pGT );
|
|
}
|
|
|
|
static void hb_gt_os2_Exit( PHB_GT pGT )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_os2_Exit(%p)", pGT));
|
|
|
|
HB_GTSUPER_EXIT( pGT );
|
|
|
|
if( s_iLineBufSize > 0 )
|
|
{
|
|
DosFreeMem( ( PVOID ) s_sLineBuf );
|
|
s_iLineBufSize = 0;
|
|
}
|
|
|
|
DosFreeMem( s_key );
|
|
DosFreeMem( s_hk );
|
|
VioSetCp( 0, s_usOldCodePage, 0 );
|
|
}
|
|
|
|
static int hb_gt_os2_ReadKey( PHB_GT pGT, int iEventMask )
|
|
{
|
|
int ch; /* next char if any */
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_os2_ReadKey(%p,%d)", pGT, iEventMask));
|
|
|
|
/* zero out keyboard event record */
|
|
memset( s_key, 0, sizeof( KBDKEYINFO ) );
|
|
|
|
/* Get next character without wait */
|
|
KbdCharIn( s_key, IO_NOWAIT, ( HKBD ) * s_hk );
|
|
|
|
/* extended key codes have 00h or E0h as chChar */
|
|
if( ( s_key->fbStatus & KBDTRF_EXTENDED_CODE ) &&
|
|
( s_key->chChar == 0x00 || s_key->chChar == 0xE0 ) )
|
|
{
|
|
/* It was an extended function key lead-in code, so read the actual function key and then offset it by 256,
|
|
unless extended keyboard events are allowed, in which case offset it by 512 */
|
|
if( ( s_key->chChar == 0xE0 ) && ( iEventMask & INKEY_RAW ) )
|
|
ch = ( int ) s_key->chScan + 512;
|
|
else
|
|
ch = ( int ) s_key->chScan + 256;
|
|
}
|
|
else if ( s_key->fbStatus & KBDTRF_FINAL_CHAR_IN )
|
|
ch = ( int ) s_key->chChar;
|
|
else
|
|
ch = 0;
|
|
|
|
ch = hb_gt_dos_keyCodeTranslate( ch );
|
|
|
|
if( ch == 0 )
|
|
ch = HB_GTSELF_MOUSEREADKEY( pGT, iEventMask );
|
|
|
|
return ch;
|
|
}
|
|
|
|
static BOOL hb_gt_os2_IsColor( PHB_GT pGT )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_os2_IsColor(%p)", pGT));
|
|
|
|
HB_SYMBOL_UNUSED( pGT );
|
|
|
|
return s_vi.fbType != 0; /* 0 = monochrom-compatible mode */
|
|
}
|
|
|
|
static BOOL hb_gt_os2_GetBlink( PHB_GT pGT )
|
|
{
|
|
VIOINTENSITY vi;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_os2_GetBlink(%p)", pGT));
|
|
|
|
HB_SYMBOL_UNUSED( pGT );
|
|
|
|
vi.cb = sizeof( VIOINTENSITY ); /* 6 */
|
|
vi.type = 2; /* get intensity/blink toggle */
|
|
VioGetState( &vi, 0 );
|
|
|
|
return vi.fs == 0; /* 0 = blink, 1 = intens */
|
|
}
|
|
|
|
static void hb_gt_os2_SetBlink( PHB_GT pGT, BOOL fBlink )
|
|
{
|
|
VIOINTENSITY vi;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_os2_SetBlink(%p,%d)", pGT, (int) fBlink));
|
|
|
|
HB_SYMBOL_UNUSED( pGT );
|
|
|
|
vi.cb = sizeof( VIOINTENSITY ); /* 6 */
|
|
vi.type = 2; /* set intensity/blink toggle */
|
|
vi.fs = ( fBlink ? 0 : 1 ); /* 0 = blink, 1 = intens */
|
|
VioSetState( &vi, 0 );
|
|
}
|
|
|
|
static void hb_gt_os2_Tone( PHB_GT pGT, double dFrequency, double dDuration )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_os2_Tone(%p,%lf,%lf)", pGT, dFrequency, dDuration));
|
|
|
|
HB_SYMBOL_UNUSED( pGT );
|
|
|
|
/* The conversion from Clipper timer tick units to
|
|
milliseconds is * 1000.0 / 18.2. */
|
|
|
|
dFrequency = HB_MIN( HB_MAX( 0.0, dFrequency ), 32767.0 );
|
|
dDuration = dDuration * 1000.0 / 18.2; /* milliseconds */
|
|
|
|
while( dDuration > 0.0 )
|
|
{
|
|
USHORT temp = ( USHORT ) HB_MIN( HB_MAX( 0, dDuration ), USHRT_MAX );
|
|
|
|
dDuration -= temp;
|
|
if( temp <= 0 )
|
|
{
|
|
/* Ensure that the loop gets terminated when
|
|
only a fraction of the delay time remains. */
|
|
dDuration = -1.0;
|
|
}
|
|
else
|
|
{
|
|
DosBeep( ( USHORT ) dFrequency, temp );
|
|
}
|
|
}
|
|
}
|
|
|
|
static char * hb_gt_os2_Version( PHB_GT pGT, int iType )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_os2_Version(%p,%d)", pGT, iType ) );
|
|
|
|
HB_SYMBOL_UNUSED( pGT );
|
|
|
|
if( iType == 0 )
|
|
return HB_GT_DRVNAME( HB_GT_NAME );
|
|
|
|
return "Harbour Terminal: OS/2 console";
|
|
}
|
|
|
|
static BOOL hb_gt_os2_Resize( PHB_GT pGT, int iRows, int iCols )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_os2_Resize(%p,%d,%d)", pGT, iRows, iCols));
|
|
|
|
if( HB_GTSUPER_RESIZE( pGT, iRows, iCols ) )
|
|
{
|
|
HB_GTSELF_GETSIZE( pGT, &iRows, &iCols );
|
|
iRows <<= 1;
|
|
if( s_iLineBufSize != iRows )
|
|
{
|
|
if( s_iLineBufSize != 0 )
|
|
DosFreeMem( ( PVOID ) s_sLineBuf );
|
|
if( iRows )
|
|
s_sLineBuf = ( BYTE * ) hb_gt_os2_allocMem( iRows );
|
|
s_iLineBufSize = iRows;
|
|
}
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static BOOL hb_gt_os2_SetMode( PHB_GT pGT, int iRows, int iCols )
|
|
{
|
|
BOOL fResult;
|
|
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_os2_SetMode(%p,%d,%d)", pGT, iRows, iCols));
|
|
|
|
s_vi.cb = sizeof( VIOMODEINFO );
|
|
VioGetMode( &s_vi, 0 ); /* fill structure with current settings */
|
|
s_vi.row = iRows;
|
|
s_vi.col = iCols;
|
|
fResult = VioSetMode( &s_vi, 0 ) == 0; /* 0 = Ok, other = Fail */
|
|
|
|
if( !fResult )
|
|
{
|
|
s_vi.cb = sizeof( VIOMODEINFO );
|
|
VioGetMode( &s_vi, 0 ); /* fill structure with current settings */
|
|
}
|
|
|
|
hb_gt_os2_GetCursorPosition( &s_iCurRow, &s_iCurCol );
|
|
s_iCursorStyle = hb_gt_os2_GetCursorStyle();
|
|
HB_GTSELF_RESIZE( pGT, s_vi.row, s_vi.col );
|
|
HB_GTSELF_SETPOS( pGT, s_iCurRow, s_iCurCol );
|
|
if( s_iCursorStyle > 0 )
|
|
HB_GTSELF_SETCURSORSTYLE( pGT, s_iCursorStyle );
|
|
hb_gt_os2_GetScreenContents( pGT );
|
|
|
|
return fResult;
|
|
}
|
|
|
|
static BOOL hb_gt_os2_PostExt( PHB_GT pGT )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_os2_PostExt(%p)", pGT));
|
|
|
|
hb_gt_os2_GetCursorPosition( &s_iCurRow, &s_iCurCol );
|
|
HB_GTSELF_SETPOS( pGT, s_iCurRow, s_iCurCol );
|
|
hb_gt_os2_GetScreenContents( pGT );
|
|
|
|
return HB_GTSUPER_POSTEXT( pGT );
|
|
}
|
|
|
|
static BOOL hb_gt_os2_Resume( PHB_GT pGT )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_os2_Resume(%p)", pGT));
|
|
|
|
s_vi.cb = sizeof( VIOMODEINFO );
|
|
VioGetMode( &s_vi, 0 ); /* fill structure with current settings */
|
|
hb_gt_os2_GetCursorPosition( &s_iCurRow, &s_iCurCol );
|
|
s_iCursorStyle = hb_gt_os2_GetCursorStyle();
|
|
HB_GTSELF_RESIZE( pGT, s_vi.row, s_vi.col );
|
|
HB_GTSELF_SETPOS( pGT, s_iCurRow, s_iCurCol );
|
|
if( s_iCursorStyle > 0 )
|
|
HB_GTSELF_SETCURSORSTYLE( pGT, s_iCursorStyle );
|
|
hb_gt_os2_GetScreenContents( pGT );
|
|
|
|
return HB_GTSUPER_RESUME( pGT );
|
|
}
|
|
|
|
static void hb_gt_os2_Redraw( PHB_GT pGT, int iRow, int iCol, int iSize )
|
|
{
|
|
BYTE *pBufPtr = s_sLineBuf, bColor, bAttr;
|
|
USHORT usChar;
|
|
int iLen = 0;
|
|
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_os2_Redraw(%p,%d,%d,%d)", pGT, iRow, iCol, iSize ) );
|
|
|
|
while( iLen < iSize )
|
|
{
|
|
if( !HB_GTSELF_GETSCRCHAR( pGT, iRow, iCol + iLen, &bColor, &bAttr, &usChar ) )
|
|
break;
|
|
|
|
*pBufPtr++ = ( BYTE ) usChar;
|
|
*pBufPtr++ = bColor;
|
|
++iLen;
|
|
}
|
|
|
|
VioWrtCellStr( ( PCH ) s_sLineBuf, iLen << 1, iRow, iCol, 0 );
|
|
}
|
|
|
|
static void hb_gt_os2_Refresh( PHB_GT pGT )
|
|
{
|
|
int iRow, iCol, iStyle;
|
|
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_os2_Refresh(%p)", pGT ) );
|
|
|
|
HB_GTSUPER_REFRESH( pGT );
|
|
|
|
HB_GTSELF_GETSCRCURSOR( pGT, &iRow, &iCol, &iStyle );
|
|
if( iStyle != SC_NONE )
|
|
{
|
|
if( iRow >= 0 && iCol >= 0 && iRow < s_vi.row && iCol < s_vi.col )
|
|
hb_gt_os2_SetCursorPosition( iRow, iCol );
|
|
else
|
|
iStyle = SC_NONE;
|
|
}
|
|
hb_gt_os2_SetCursorStyle( iStyle );
|
|
}
|
|
|
|
static BOOL hb_gt_os2_Info( PHB_GT pGT, int iType, PHB_GT_INFO pInfo )
|
|
{
|
|
HB_TRACE( HB_TR_DEBUG, ( "hb_gt_os2_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;
|
|
|
|
default:
|
|
return HB_GTSUPER_INFO( pGT, iType, pInfo );
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/* *********************************************************************** */
|
|
|
|
static BOOL hb_gt_FuncInit( PHB_GT_FUNCS pFuncTable )
|
|
{
|
|
HB_TRACE(HB_TR_DEBUG, ("hb_gt_FuncInit(%p)", pFuncTable));
|
|
|
|
pFuncTable->Init = hb_gt_os2_Init;
|
|
pFuncTable->Exit = hb_gt_os2_Exit;
|
|
pFuncTable->IsColor = hb_gt_os2_IsColor;
|
|
pFuncTable->Resize = hb_gt_os2_Resize;
|
|
pFuncTable->SetMode = hb_gt_os2_SetMode;
|
|
pFuncTable->Redraw = hb_gt_os2_Redraw;
|
|
pFuncTable->Refresh = hb_gt_os2_Refresh;
|
|
pFuncTable->SetBlink = hb_gt_os2_SetBlink;
|
|
pFuncTable->GetBlink = hb_gt_os2_GetBlink;
|
|
pFuncTable->Version = hb_gt_os2_Version;
|
|
pFuncTable->Resume = hb_gt_os2_Resume;
|
|
pFuncTable->PostExt = hb_gt_os2_PostExt;
|
|
pFuncTable->Tone = hb_gt_os2_Tone;
|
|
pFuncTable->Info = hb_gt_os2_Info;
|
|
|
|
pFuncTable->ReadKey = hb_gt_os2_ReadKey;
|
|
|
|
pFuncTable->MouseInit = hb_gt_os2_mouse_Init;
|
|
pFuncTable->MouseExit = hb_gt_os2_mouse_Exit;
|
|
pFuncTable->MouseIsPresent = hb_gt_os2_mouse_IsPresent;
|
|
pFuncTable->MouseShow = hb_gt_os2_mouse_Show;
|
|
pFuncTable->MouseHide = hb_gt_os2_mouse_Hide;
|
|
pFuncTable->MouseGetPos = hb_gt_os2_mouse_GetPos;
|
|
pFuncTable->MouseSetPos = hb_gt_os2_mouse_SetPos;
|
|
pFuncTable->MouseButtonState = hb_gt_os2_mouse_ButtonState;
|
|
pFuncTable->MouseButtonPressed = hb_gt_os2_mouse_ButtonPressed;
|
|
pFuncTable->MouseButtonReleased = hb_gt_os2_mouse_ButtonReleased;
|
|
pFuncTable->MouseCountButton = hb_gt_os2_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( >Init );
|
|
HB_CALL_ON_STARTUP_END( _hb_startup_gt_Init_ )
|
|
|
|
#if defined( HB_PRAGMA_STARTUP )
|
|
#pragma startup _hb_startup_gt_Init_
|
|
#elif defined(HB_MSC_STARTUP)
|
|
#pragma data_seg( HB_MSC_START_SEGMENT )
|
|
static HB_$INITSYM hb_vm_auto__hb_startup_gt_Init_ = _hb_startup_gt_Init_;
|
|
#pragma data_seg()
|
|
#endif
|