From 62ed0059797e4dfce0ef6541a2ed7d06864c7ddb Mon Sep 17 00:00:00 2001 From: Przemyslaw Czerpak Date: Mon, 3 Dec 2007 21:36:22 +0000 Subject: [PATCH] 2007-12-03 22:35 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/common.mak * harbour/source/rtl/Makefile * harbour/include/hbgtcore.h * harbour/source/rtl/hbgtcore.c * harbour/source/rtl/inkey.c + harbour/source/rtl/inkeyapi.c * moved hb_inkey*() functions to GT subsystem so now they can be overloaded by GT drivers and/or operate on different GT context * harbour/source/rtl/mouse53.c * eliminated to unused static variables * harbour/source/rtl/mouseapi.c * do not include unnecessary header files * harbour/source/rtl/gtchrmap.c * replaced // comment by /* ... */ --- harbour/ChangeLog | 19 ++ harbour/common.mak | 1 + harbour/include/hbgtcore.h | 31 +++ harbour/source/rtl/Makefile | 1 + harbour/source/rtl/gtchrmap.c | 2 +- harbour/source/rtl/hbgtcore.c | 435 +++++++++++++++++++++++++++++++++- harbour/source/rtl/inkey.c | 394 +++--------------------------- harbour/source/rtl/inkeyapi.c | 121 ++++++++++ harbour/source/rtl/mouse53.c | 17 +- harbour/source/rtl/mouseapi.c | 4 +- 10 files changed, 649 insertions(+), 376 deletions(-) create mode 100644 harbour/source/rtl/inkeyapi.c diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 867d477a39..234ffcca7f 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,25 @@ 2002-12-01 13:30 UTC+0100 Foo Bar */ +2007-12-03 22:35 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/common.mak + * harbour/source/rtl/Makefile + * harbour/include/hbgtcore.h + * harbour/source/rtl/hbgtcore.c + * harbour/source/rtl/inkey.c + + harbour/source/rtl/inkeyapi.c + * moved hb_inkey*() functions to GT subsystem so now they can be + overloaded by GT drivers and/or operate on different GT context + + * harbour/source/rtl/mouse53.c + * eliminated to unused static variables + + * harbour/source/rtl/mouseapi.c + * do not include unnecessary header files + + * harbour/source/rtl/gtchrmap.c + * replaced // comment by /* ... */ + 2007-12-03 21:40 UTC+0100 Marek Paliwoda (mpaliwoda at interia pl) * harbour/common.mak * harbour/make_gcc.sh diff --git a/harbour/common.mak b/harbour/common.mak index a565b31e71..5b4b605f71 100644 --- a/harbour/common.mak +++ b/harbour/common.mak @@ -501,6 +501,7 @@ RTL_LIB_OBJS = \ $(OBJ_DIR)\hbtoken$(OBJEXT) \ $(OBJ_DIR)\idle$(OBJEXT) \ $(OBJ_DIR)\inkey$(OBJEXT) \ + $(OBJ_DIR)\inkeyapi$(OBJEXT) \ $(OBJ_DIR)\is$(OBJEXT) \ $(OBJ_DIR)\isprint$(OBJEXT) \ $(OBJ_DIR)\itemseri$(OBJEXT) \ diff --git a/harbour/include/hbgtcore.h b/harbour/include/hbgtcore.h index c1805963e2..94d4c792fd 100644 --- a/harbour/include/hbgtcore.h +++ b/harbour/include/hbgtcore.h @@ -193,6 +193,16 @@ typedef struct /* keyboard */ int (* ReadKey) ( int ); + int (* InkeyGet) ( BOOL fWait, double dSeconds, int iEventMask ); + void (* InkeyPut) ( int iKey ); + int (* InkeyLast) ( int iEventMask ); + int (* InkeyNext) ( int iEventMask ); + void (* InkeyPoll) ( void ); + void (* InkeySetText) ( const char * szText, ULONG ulLen ); + int (* InkeySetLast) ( int iKey ); + void (* InkeyReset) ( void ); + void (* InkeyExit) ( void ); + /* mouse */ void (* MouseInit) ( void ); void (* MouseExit) ( void ); @@ -336,6 +346,18 @@ typedef struct HB_LONG iMouseRightTimer; HB_LONG iMouseMiddleTimer; + int defaultKeyBuffer[ HB_DEFAULT_INKEY_BUFSIZE + 1 ]; + + int * inkeyBuffer; + int inkeyBufferSize; + int inkeyHead; + int inkeyTail; + int iLastPut; + int inkeyLast; + BYTE * StrBuffer; + ULONG StrBufferSize; + ULONG StrBufferPos; + void ** pGTData; /* */ } HB_GT_BASE; typedef HB_GT_BASE * PHB_GT_BASE, * PHB_GT; @@ -420,6 +442,15 @@ extern BOOL hb_gt_Info( int iType, PHB_GT_INFO pInfo ); extern int hb_gt_Alert( PHB_ITEM pMessage, PHB_ITEM pOptions, int iClrNorm, int iClrHigh, double dDelay ); extern int hb_gt_SetFlag( int iType, int iNewValue ); extern int hb_gt_ReadKey( int iEventMask ); +extern int hb_inkey_Get( BOOL bWait, double dSeconds, int iEventMask ); +extern void hb_inkey_Put( int iKey ); +extern int hb_inkey_Last( int iEventMask ); +extern int hb_inkey_Next( int iEventMask ); +extern void hb_inkey_Poll( void ); +extern void hb_inkey_SetText( const char * szText, ULONG ulLen ); +extern int hb_inkey_SetLast( int iKey ); +extern void hb_inkey_Reset( void ); +extern void hb_inkey_Exit( void ); extern void hb_mouse_Init( void ); extern void hb_mouse_Exit( void ); extern BOOL hb_mouse_IsPresent( void ); diff --git a/harbour/source/rtl/Makefile b/harbour/source/rtl/Makefile index c9fe28a938..92c1702581 100644 --- a/harbour/source/rtl/Makefile +++ b/harbour/source/rtl/Makefile @@ -66,6 +66,7 @@ C_SOURCES=\ hbtoken.c \ idle.c \ inkey.c \ + inkeyapi.c \ is.c \ isprint.c \ itemseri.c \ diff --git a/harbour/source/rtl/gtchrmap.c b/harbour/source/rtl/gtchrmap.c index 03cbbb9d59..da922dc693 100644 --- a/harbour/source/rtl/gtchrmap.c +++ b/harbour/source/rtl/gtchrmap.c @@ -473,4 +473,4 @@ int main(int argc, char **argv) } */ -#endif // HB_OS_UNIX +#endif /* HB_OS_UNIX */ diff --git a/harbour/source/rtl/hbgtcore.c b/harbour/source/rtl/hbgtcore.c index 8e266c8f8d..bb973594aa 100644 --- a/harbour/source/rtl/hbgtcore.c +++ b/harbour/source/rtl/hbgtcore.c @@ -64,10 +64,21 @@ #include "hbapierr.h" #include "hbapicdp.h" #include "hbdate.h" +#include "hbset.h" +#include "hbvm.h" +/* these variables are used for stdout/stderr output when GT subsystem + * is not initialized + */ +static FHANDLE s_hStdIn = 0, s_hStdOut = 1, s_hStdErr = 2; + +/* base GT strucure */ static PHB_GT_BASE s_curGT = NULL; -static FHANDLE s_hStdOut = 1, s_hStdErr = 2; +PHB_GT hb_gt_Base( void ) +{ + return s_curGT; +} /* helper internal function */ static void hb_gt_def_BaseInit( PHB_GT_BASE pGT ) @@ -82,11 +93,14 @@ static void hb_gt_def_BaseInit( PHB_GT_BASE pGT ) pGT->uiExtCount = 0; pGT->uiClearChar = ' '; pGT->bClearColor = 0x07; - pGT->hStdIn = 0; - pGT->hStdOut = 1; - pGT->hStdErr = 2; + pGT->hStdIn = s_hStdIn; + pGT->hStdOut = s_hStdOut; + pGT->hStdErr = s_hStdErr; pGT->iDoubleClickSpeed = 168; /* In milliseconds */ + + pGT->inkeyBuffer = pGT->defaultKeyBuffer; + pGT->inkeyBufferSize = HB_DEFAULT_INKEY_BUFSIZE; } static void * hb_gt_def_New( void ) @@ -143,6 +157,9 @@ static void hb_gt_def_Free( void * pGtPtr ) hb_xfree( pGT->szClipboardData ); if( pGT->iColorCount > 0 ) hb_xfree( pGT->pColor ); + if( pGT->pGTData ) + hb_xfree( pGT->pGTData ); + hb_xfree( pGT ); } @@ -162,6 +179,7 @@ static void hb_gt_def_Init( FHANDLE hStdIn, FHANDLE hStdOut, FHANDLE hStdErr ) static void hb_gt_def_Exit( void ) { hb_mouse_Exit(); + hb_inkey_Exit(); if( s_curGT ) { @@ -2173,6 +2191,352 @@ static int hb_gt_def_ReadKey( int iEventMask ) return hb_mouse_ReadKey( iEventMask ); } +/* helper internal function */ +static int hb_gt_def_InkeyFilter( int iKey, int iEventMask ) +{ + int iMask; + + HB_TRACE(HB_TR_DEBUG, ("hb_gt_def_InkeyFilter(%d,%d)", iKey, iEventMask)); + + switch( iKey ) + { + case K_MOUSEMOVE: + case K_MMLEFTDOWN: + case K_MMRIGHTDOWN: + case K_MMMIDDLEDOWN: + case K_NCMOUSEMOVE: + iMask = INKEY_MOVE; + break; + case K_LBUTTONDOWN: + case K_LDBLCLK: + iMask = INKEY_LDOWN; + break; + case K_LBUTTONUP: + iMask = INKEY_LUP; + break; + case K_RBUTTONDOWN: + case K_RDBLCLK: + iMask = INKEY_RDOWN; + break; + case K_RBUTTONUP: + iMask = INKEY_RUP; + break; + case K_MBUTTONDOWN: + case K_MBUTTONUP: + case K_MDBLCLK: + iMask = INKEY_MMIDDLE; + break; + case K_MWFORWARD: + case K_MWBACKWARD: + iMask = INKEY_MWHEEL; + break; + default: + iMask = INKEY_KEYBOARD; + break; + } + + if( ( iMask & iEventMask ) == 0 ) + return 0; + + return iKey; +} + +/* helper internal function: drop the next key in keyboard buffer */ +static void hb_gt_def_InkeyPop( void ) +{ + if( s_curGT ) + { + if( s_curGT->StrBuffer ) + { + if( ++s_curGT->StrBufferPos >= s_curGT->StrBufferSize ) + { + hb_xfree( s_curGT->StrBuffer ); + s_curGT->StrBuffer = NULL; + } + } + else if( s_curGT->inkeyHead != s_curGT->inkeyTail ) + { + if( ++s_curGT->inkeyTail >= s_curGT->inkeyBufferSize ) + s_curGT->inkeyTail = 0; + } + } +} + +/* Put the key into keyboard buffer */ +static void hb_gt_def_InkeyPut( int iKey ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_gt_def_InkeyPut(%d)", iKey)); + + if( s_curGT ) + { + int iHead = s_curGT->inkeyHead; + + if( iKey == K_MOUSEMOVE ) + { + /* + * Clipper does not store in buffer repeated mouse movement + * IMHO it's good idea to reduce unnecessary inkey buffer + * overloading so I also implemented it, [druzus] + */ + if( s_curGT->iLastPut == iKey && s_curGT->inkeyHead != s_curGT->inkeyTail ) + return; + } + + /* + * When the buffer is full new event overwrite the last one + * in the buffer - it's Clipper behavior, [druzus] + */ + s_curGT->inkeyBuffer[ iHead++ ] = s_curGT->iLastPut = iKey; + if( iHead >= s_curGT->inkeyBufferSize ) + iHead = 0; + + if( iHead != s_curGT->inkeyTail ) + s_curGT->inkeyHead = iHead; + } +} + +/* helper internal function */ +static BOOL hb_gt_def_InkeyNextCheck( int iEventMask, int * iKey ) +{ + HB_TRACE( HB_TR_DEBUG, ("hb_gt_def_InkeyNextCheck(%p)", iKey) ); + + if( s_curGT ) + { + if( s_curGT->StrBuffer ) + { + *iKey = s_curGT->StrBuffer[ s_curGT->StrBufferPos ]; + } + else if( s_curGT->inkeyHead != s_curGT->inkeyTail ) + { + *iKey = hb_gt_def_InkeyFilter( s_curGT->inkeyBuffer[ s_curGT->inkeyTail ], iEventMask ); + } + else + { + return FALSE; + } + + if( *iKey == 0 ) + { + hb_gt_def_InkeyPop(); + return FALSE; + } + } + + return TRUE; +} + +/* helper internal function */ +static void hb_gt_def_InkeyPollDo( void ) +{ + int iKey; + + HB_TRACE( HB_TR_DEBUG, ("hb_gt_def_InkeyPollDo()") ); + + iKey = hb_gt_ReadKey( INKEY_ALL ); + + if( iKey ) + { + switch( iKey ) + { + case HB_BREAK_FLAG: /* Check for Ctrl+Break */ + case K_ALT_C: /* Check for normal Alt+C */ + if( hb_set.HB_SET_CANCEL ) + { + hb_vmRequestCancel(); /* Request cancellation */ + return; + } + break; + case K_ALT_D: /* Check for Alt+D */ + if( hb_set.HB_SET_DEBUG ) + { + hb_vmRequestDebug(); /* Request the debugger */ + return; + } + } + hb_inkey_Put( iKey ); + } +} + +/* Poll the console keyboard to stuff the Harbour buffer */ +static void hb_gt_def_InkeyPoll( void ) +{ + HB_TRACE( HB_TR_DEBUG, ("hb_gt_def_InkeyPoll()") ); + + /* + * Clipper 5.3 always poll events without respecting + * hb_set.HB_SET_TYPEAHEAD when CL5.2 only when it's non zero. + * IMHO keeping CL5.2 behavior will be more accurate for xharbour + * because it allow to control it by user what some times could be + * necessary due to different low level GT behavior on some platforms + */ + if( hb_set.HB_SET_TYPEAHEAD ) + { + hb_gt_def_InkeyPollDo(); + } +} + +/* Return the next key without extracting it */ +static int hb_gt_def_InkeyNext( int iEventMask ) +{ + int iKey = 0; + + HB_TRACE(HB_TR_DEBUG, ("hb_gt_def_InkeyNext(%d)", iEventMask)); + + hb_inkey_Poll(); + hb_gt_def_InkeyNextCheck( iEventMask, &iKey ); + + return iKey; +} + +/* Wait for keyboard input */ +static int hb_gt_def_InkeyGet( BOOL fWait, double dSeconds, int iEventMask ) +{ + HB_ULONG end_timer; + BOOL fPop; + + HB_TRACE(HB_TR_DEBUG, ("hb_gt_def_InkeyGet(%d, %f, %d)", (int) fWait, dSeconds, iEventMask)); + + if( s_curGT ) + { + /* Wait forever ?, Use fixed value 100 for strict Clipper compatibility */ + if( fWait && dSeconds * 100 >= 1 ) + end_timer = hb_dateMilliSeconds() + ( HB_ULONG ) ( dSeconds * 1000 ); + else + end_timer = 0; + + do + { + hb_gt_def_InkeyPollDo(); + fPop = hb_gt_def_InkeyNextCheck( iEventMask, &s_curGT->inkeyLast ); + + if( fPop ) + break; + + /* immediately break if a VM request is pending. */ + if( !fWait || hb_vmRequestQuery() != 0 ) + return 0; + + hb_idleState(); + } + while( end_timer == 0 || end_timer > hb_dateMilliSeconds() ); + + hb_idleReset(); + + if( fPop ) + { + hb_gt_def_InkeyPop(); + return s_curGT->inkeyLast; + } + } + + return 0; +} + +/* Return the value of the last key that was extracted */ +static int hb_gt_def_InkeyLast( int iEventMask ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_gt_def_InkeyLast(%d)", iEventMask)); + + hb_inkey_Poll(); + + return s_curGT ? hb_gt_def_InkeyFilter( s_curGT->inkeyLast, iEventMask ) : 0; +} + +/* Set LastKey() value and return previous value */ +static int hb_gt_def_InkeySetLast( int iKey ) +{ + int iLast = 0; + HB_TRACE(HB_TR_DEBUG, ("hb_gt_def_InkeySetLast(%d)", iKey)); + + if( s_curGT ) + { + iLast = s_curGT->inkeyLast; + s_curGT->inkeyLast = iKey; + } + + return iLast; +} + +/* Set text into inkey buffer */ +static void hb_gt_def_InkeySetText( const char * szText, ULONG ulLen ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_gt_def_InkeySetText(%s,%lu)", szText, ulLen)); + + if( s_curGT ) + { + if( s_curGT->StrBuffer ) + { + hb_xfree( s_curGT->StrBuffer ); + s_curGT->StrBuffer = NULL; + } + + if( szText && ulLen ) + { + s_curGT->StrBuffer = ( BYTE * ) hb_xgrab( ulLen ); + memcpy( s_curGT->StrBuffer, szText, ulLen ); + s_curGT->StrBufferSize = ulLen; + s_curGT->StrBufferPos = 0; + } + } +} + +/* Reset the keyboard buffer */ +static void hb_gt_def_InkeyReset( void ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_gt_def_InkeyReset()")); + + if( s_curGT ) + { + if( s_curGT->StrBuffer ) + { + hb_xfree( s_curGT->StrBuffer ); + s_curGT->StrBuffer = NULL; + } + + s_curGT->inkeyHead = 0; + s_curGT->inkeyTail = 0; + + if( hb_set.HB_SET_TYPEAHEAD != s_curGT->inkeyBufferSize ) + { + if( s_curGT->inkeyBufferSize > HB_DEFAULT_INKEY_BUFSIZE ) + hb_xfree( s_curGT->inkeyBuffer ); + + if( hb_set.HB_SET_TYPEAHEAD > HB_DEFAULT_INKEY_BUFSIZE ) + { + s_curGT->inkeyBufferSize = hb_set.HB_SET_TYPEAHEAD; + s_curGT->inkeyBuffer = ( int * ) hb_xgrab( s_curGT->inkeyBufferSize * sizeof( int ) ); + } + else + { + s_curGT->inkeyBufferSize = HB_DEFAULT_INKEY_BUFSIZE; + s_curGT->inkeyBuffer = s_curGT->defaultKeyBuffer; + } + } + } +} + +/* reset inkey pool to default state and free any allocated resources */ +static void hb_gt_def_InkeyExit( void ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_gt_def_InkeyExit()")); + + if( s_curGT ) + { + if( s_curGT->StrBuffer ) + { + hb_xfree( s_curGT->StrBuffer ); + s_curGT->StrBuffer = NULL; + } + if( s_curGT->inkeyBufferSize > HB_DEFAULT_INKEY_BUFSIZE ) + { + hb_xfree( s_curGT->inkeyBuffer ); + s_curGT->inkeyBufferSize = HB_DEFAULT_INKEY_BUFSIZE; + s_curGT->inkeyBuffer = s_curGT->defaultKeyBuffer; + } + + } +} + static void hb_gt_def_MouseInit( void ) { ; @@ -2525,6 +2889,15 @@ static HB_GT_FUNCS gtCoreFunc = SetDispCP : hb_gt_def_SetDispCP , SetKeyCP : hb_gt_def_SetKeyCP , ReadKey : hb_gt_def_ReadKey , + InkeyGet : hb_gt_def_InkeyGet , + InkeyPut : hb_gt_def_InkeyPut , + InkeyLast : hb_gt_def_InkeyLast , + InkeyNext : hb_gt_def_InkeyNext , + InkeyPoll : hb_gt_def_InkeyPoll , + InkeySetText : hb_gt_def_InkeySetText , + InkeySetLast : hb_gt_def_InkeySetLast , + InkeyReset : hb_gt_def_InkeyReset , + InkeyExit : hb_gt_def_InkeyExit , MouseInit : hb_gt_def_MouseInit , MouseExit : hb_gt_def_MouseExit , MouseIsPresent : hb_gt_def_MouseIsPresent , @@ -2633,6 +3006,15 @@ static HB_GT_FUNCS gtCoreFunc = hb_gt_def_SetDispCP , hb_gt_def_SetKeyCP , hb_gt_def_ReadKey , + hb_gt_def_InkeyGet , + hb_gt_def_InkeyPut , + hb_gt_def_InkeyLast , + hb_gt_def_InkeyNext , + hb_gt_def_InkeyPoll , + hb_gt_def_InkeySetText , + hb_gt_def_InkeySetLast , + hb_gt_def_InkeyReset , + hb_gt_def_InkeyExit , hb_gt_def_MouseInit , hb_gt_def_MouseExit , hb_gt_def_MouseIsPresent , @@ -3054,6 +3436,51 @@ int hb_gt_ReadKey( int iEventMask ) return gtCoreFunc.ReadKey( iEventMask ); } +int hb_inkey_Get( BOOL fWait, double dSeconds, int iEventMask ) +{ + return gtCoreFunc.InkeyGet( fWait, dSeconds, iEventMask ); +} + +void hb_inkey_Put( int iKey ) +{ + gtCoreFunc.InkeyPut( iKey ); +} + +int hb_inkey_Last( int iEventMask ) +{ + return gtCoreFunc.InkeyLast( iEventMask ); +} + +int hb_inkey_Next( int iEventMask ) +{ + return gtCoreFunc.InkeyNext( iEventMask ); +} + +void hb_inkey_Poll( void ) +{ + gtCoreFunc.InkeyPoll(); +} + +void hb_inkey_SetText( const char * szText, ULONG ulLen ) +{ + gtCoreFunc.InkeySetText( szText, ulLen ); +} + +int hb_inkey_SetLast( int iKey ) +{ + return gtCoreFunc.InkeySetLast( iKey ); +} + +void hb_inkey_Reset( void ) +{ + gtCoreFunc.InkeyReset(); +} + +void hb_inkey_Exit( void ) +{ + gtCoreFunc.InkeyExit(); +} + void hb_mouse_Init( void ) { gtCoreFunc.MouseInit(); diff --git a/harbour/source/rtl/inkey.c b/harbour/source/rtl/inkey.c index 0c6cc98c05..4447a57d80 100644 --- a/harbour/source/rtl/inkey.c +++ b/harbour/source/rtl/inkey.c @@ -71,371 +71,14 @@ * */ -#include "hbapi.h" -#include "hbapiitm.h" #include "hbapigt.h" -#include "hbvm.h" +#include "hbapiitm.h" #include "hbset.h" -#include "hbdate.h" -#include "inkey.ch" - -static int s_defaultKeyBuffer[ HB_DEFAULT_INKEY_BUFSIZE + 1 ]; - -static int * s_inkeyBuffer = s_defaultKeyBuffer; -static int s_inkeyBufferSize = HB_DEFAULT_INKEY_BUFSIZE; -static int s_inkeyHead = 0; -static int s_inkeyTail = 0; -static int s_iLastPut = 0; - -static BYTE * s_StrBuffer = NULL; -static ULONG s_StrBufferSize; -static ULONG s_StrBufferPos; - -static int s_inkeyLast = 0; +#include "hbvm.h" static PHB_ITEM s_inKeyBlockBefore = NULL; static PHB_ITEM s_inKeyBlockAfter = NULL; - -static int hb_inkeyFilter( int iKey, int iEventMask ) -{ - int iMask; - - HB_TRACE(HB_TR_DEBUG, ("hb_inkeyFilter(%d,%d)", iKey, iEventMask)); - - switch( iKey ) - { - case K_MOUSEMOVE: - case K_MMLEFTDOWN: - case K_MMRIGHTDOWN: - case K_MMMIDDLEDOWN: - case K_NCMOUSEMOVE: - iMask = INKEY_MOVE; - break; - case K_LBUTTONDOWN: - case K_LDBLCLK: - iMask = INKEY_LDOWN; - break; - case K_LBUTTONUP: - iMask = INKEY_LUP; - break; - case K_RBUTTONDOWN: - case K_RDBLCLK: - iMask = INKEY_RDOWN; - break; - case K_RBUTTONUP: - iMask = INKEY_RUP; - break; - case K_MBUTTONDOWN: - case K_MBUTTONUP: - case K_MDBLCLK: - iMask = INKEY_MMIDDLE; - break; - case K_MWFORWARD: - case K_MWBACKWARD: - iMask = INKEY_MWHEEL; - break; - default: - iMask = INKEY_KEYBOARD; - break; - } - - if( ( iMask & iEventMask ) == 0 ) - return 0; - - return iKey; -} - -/* drop the next key in keyboard buffer */ -static void hb_inkeyPop( void ) -{ - if( s_StrBuffer ) - { - if( ++s_StrBufferPos >= s_StrBufferSize ) - { - hb_xfree( s_StrBuffer ); - s_StrBuffer = NULL; - } - } - else if( s_inkeyHead != s_inkeyTail ) - { - if( ++s_inkeyTail >= s_inkeyBufferSize ) - s_inkeyTail = 0; - } -} - -/* Put the key into keyboard buffer */ -HB_EXPORT void hb_inkeyPut( int iKey ) -{ - int iHead = s_inkeyHead; - - HB_TRACE(HB_TR_DEBUG, ("hb_inkeyPut(%d)", iKey)); - - if( iKey == K_MOUSEMOVE ) - { - /* - * Clipper does not store in buffer repeated mouse movement - * IMHO it's good idea to reduce unnecessary inkey buffer - * overloading so I also implemented it, [druzus] - */ - if( s_iLastPut == iKey && s_inkeyHead != s_inkeyTail ) - return; - } - - /* - * When the buffer is full new event overwrite the last one - * in the buffer - it's Clipper behavior, [druzus] - */ - s_inkeyBuffer[ iHead++ ] = s_iLastPut = iKey; - if( iHead >= s_inkeyBufferSize ) - iHead = 0; - - if( iHead != s_inkeyTail ) - s_inkeyHead = iHead; -} - -static BOOL hb_inkeyNextCheck( int iEventMask, int * iKey ) -{ - HB_TRACE( HB_TR_DEBUG, ("hb_inkeyNextCheck(%p)", iKey) ); - - if( s_StrBuffer ) - { - *iKey = s_StrBuffer[ s_StrBufferPos ]; - } - else if( s_inkeyHead != s_inkeyTail ) - { - *iKey = hb_inkeyFilter( s_inkeyBuffer[ s_inkeyTail ], iEventMask ); - } - else - { - return FALSE; - } - - if( *iKey == 0 ) - { - hb_inkeyPop(); - return FALSE; - } - - return TRUE; -} - -static void hb_inkeyPollDo( void ) -{ - int iKey; - - HB_TRACE( HB_TR_DEBUG, ("hb_inkeyPollDo()") ); - - iKey = hb_gtReadKey( INKEY_ALL ); - - if( iKey ) - { - switch( iKey ) - { - case HB_BREAK_FLAG: /* Check for Ctrl+Break */ - case K_ALT_C: /* Check for normal Alt+C */ - if( hb_set.HB_SET_CANCEL ) - { - hb_vmRequestCancel(); /* Request cancellation */ - return; - } - break; - case K_ALT_D: /* Check for Alt+D */ - if( hb_set.HB_SET_DEBUG ) - { - hb_vmRequestDebug(); /* Request the debugger */ - return; - } - } - hb_inkeyPut( iKey ); - } -} - -/* Poll the console keyboard to stuff the Harbour buffer */ -HB_EXPORT void hb_inkeyPoll( void ) -{ - HB_TRACE( HB_TR_DEBUG, ("hb_inkeyPoll()") ); - - /* - * Clipper 5.3 always poll events without respecting - * hb_set.HB_SET_TYPEAHEAD when CL5.2 only when it's non zero. - * IMHO keeping CL5.2 behavior will be more accurate for xharbour - * because it allow to control it by user what some times could be - * necessary due to different low level GT behavior on some platforms - */ - if( hb_set.HB_SET_TYPEAHEAD ) - { - hb_inkeyPollDo(); - } -} - -/* Return the next key without extracting it */ -HB_EXPORT int hb_inkeyNext( int iEventMask ) -{ - int iKey = 0; - - HB_TRACE(HB_TR_DEBUG, ("hb_inkeyNext(%d)", iEventMask)); - - hb_inkeyPoll(); - hb_inkeyNextCheck( iEventMask, &iKey ); - - return iKey; -} - -/* Wait for keyboard input */ -HB_EXPORT int hb_inkey( BOOL fWait, double dSeconds, int iEventMask ) -{ - HB_ULONG end_timer = 0; - BOOL fPop; - - HB_TRACE(HB_TR_DEBUG, ("hb_inkey(%d, %f, %d)", (int) fWait, dSeconds, iEventMask)); - - /* Wait forever ?, Use fixed value 100 for strict Clipper compatibility */ - if( fWait && dSeconds * 100 >= 1 ) - end_timer = hb_dateMilliSeconds() + ( HB_ULONG ) ( dSeconds * 1000 ); - - do - { - hb_inkeyPollDo(); - fPop = hb_inkeyNextCheck( iEventMask, &s_inkeyLast ); - - if( fPop ) - break; - - /* immediately break if a VM request is pending. */ - if( !fWait || hb_vmRequestQuery() != 0 ) - return 0; - - hb_idleState(); - } - while( end_timer == 0 || end_timer > hb_dateMilliSeconds() ); - - hb_idleReset(); - - if( fPop ) - { - hb_inkeyPop(); - return s_inkeyLast; - } - - return 0; -} - -/* Return the value of the last key that was extracted */ -HB_EXPORT int hb_inkeyLast( int iEventMask ) -{ - HB_TRACE(HB_TR_DEBUG, ("hb_inkeyLast(%d)", iEventMask)); - - hb_inkeyPoll(); - - return hb_inkeyFilter( s_inkeyLast, iEventMask ); -} - -/* Force a value to s_inkeyLast and return previous value */ -HB_EXPORT int hb_inkeySetLast( int iKey ) -{ - int iLast = s_inkeyLast; - - HB_TRACE(HB_TR_DEBUG, ("hb_inkeySetLast(%d)", iKey)); - - s_inkeyLast = iKey; - - return iLast; -} - -/* Set text into inkey buffer */ -HB_EXPORT void hb_inkeySetText( const char * szText, ULONG ulLen ) -{ - HB_TRACE(HB_TR_DEBUG, ("hb_inkeySetText(%s,%lu)", szText, ulLen)); - - if( s_StrBuffer ) - { - hb_xfree( s_StrBuffer ); - s_StrBuffer = NULL; - } - - if( szText && ulLen ) - { - s_StrBuffer = ( BYTE * ) hb_xgrab( ulLen ); - memcpy( s_StrBuffer, szText, ulLen ); - s_StrBufferSize = ulLen; - s_StrBufferPos = 0; - } -} - -/* Reset the keyboard buffer */ -HB_EXPORT void hb_inkeyReset( void ) -{ - HB_TRACE(HB_TR_DEBUG, ("hb_inkeyReset()")); - - if( s_StrBuffer ) - { - hb_xfree( s_StrBuffer ); - s_StrBuffer = NULL; - } - - s_inkeyHead = 0; - s_inkeyTail = 0; - - if( hb_set.HB_SET_TYPEAHEAD != s_inkeyBufferSize ) - { - if( s_inkeyBufferSize > HB_DEFAULT_INKEY_BUFSIZE ) - hb_xfree( s_inkeyBuffer ); - - if( hb_set.HB_SET_TYPEAHEAD > HB_DEFAULT_INKEY_BUFSIZE ) - { - s_inkeyBufferSize = hb_set.HB_SET_TYPEAHEAD; - s_inkeyBuffer = ( int * ) hb_xgrab( s_inkeyBufferSize * sizeof( int ) ); - } - else - { - s_inkeyBufferSize = HB_DEFAULT_INKEY_BUFSIZE; - s_inkeyBuffer = s_defaultKeyBuffer; - } - } -} - -/* reset inkey pool to default state and free any allocated resources */ -HB_EXPORT void hb_inkeyExit( void ) -{ - HB_TRACE(HB_TR_DEBUG, ("hb_inkeyExit()")); - - if( s_inKeyBlockBefore ) - { - hb_itemRelease( s_inKeyBlockBefore ); - s_inKeyBlockBefore = NULL; - } - if( s_inKeyBlockAfter ) - { - hb_itemRelease( s_inKeyBlockAfter ); - s_inKeyBlockAfter = NULL; - } - - if( s_StrBuffer ) - { - hb_xfree( s_StrBuffer ); - s_StrBuffer = NULL; - } - if( s_inkeyBufferSize > HB_DEFAULT_INKEY_BUFSIZE ) - { - hb_xfree( s_inkeyBuffer ); - s_inkeyBufferSize = HB_DEFAULT_INKEY_BUFSIZE; - s_inkeyBuffer = s_defaultKeyBuffer; - } -} - -HB_EXPORT void hb_inkeySetCancelKeys( int CancelKey, int CancelKeyEx ) -{ - HB_TRACE(HB_TR_DEBUG, ("hb_inkeySetCancelKeys(%d,%d)", CancelKey, CancelKeyEx)); - -/* - s_InkeyAltC = CancelKey; - s_InkeyAltCEx = CancelKeyEx; -*/ - HB_SYMBOL_UNUSED( CancelKey ); - HB_SYMBOL_UNUSED( CancelKeyEx ); -} - HB_FUNC( INKEY ) { USHORT uiPCount = hb_pcount(); @@ -468,6 +111,33 @@ HB_FUNC( INKEY ) /* temporary disabled */ #if 0 +static BOOL s_fInit = FALSE; + +static void hb_inKeyBlockFree( void * cargo ) +{ + HB_SYMBOL_UNUSED( cargo ); + + if( s_inKeyBlockBefore ) + { + hb_itemRelease( s_inKeyBlockBefore ); + s_inKeyBlockBefore = NULL; + } + if( s_inKeyBlockAfter ) + { + hb_itemRelease( s_inKeyBlockAfter ); + s_inKeyBlockAfter = NULL; + } +} + +static void hb_inKeySetDestructor( void ) +{ + if( !s_fInit ) + { + s_fInit = TRUE; + hb_vmAtExit( hb_inKeyBlockFree, NULL ); + } +} + HB_FUNC( HB_SETINKEYBEFOREBLOCK ) { if( s_inKeyBlockBefore ) @@ -478,7 +148,10 @@ HB_FUNC( HB_SETINKEYBEFOREBLOCK ) PHB_ITEM pBlock = hb_param( 1, HB_IT_BLOCK ); if( pBlock ) + { + hb_inKeySetDestructor(); pBlock = hb_itemNew( pBlock ); + } if( s_inKeyBlockBefore ) hb_itemRelease( s_inKeyBlockBefore ); @@ -496,7 +169,10 @@ HB_FUNC( HB_SETINKEYAFTERBLOCK ) PHB_ITEM pBlock = hb_param( 1, HB_IT_BLOCK ); if( pBlock ) + { + hb_inKeySetDestructor(); pBlock = hb_itemNew( pBlock ); + } if( s_inKeyBlockAfter ) hb_itemRelease( s_inKeyBlockAfter ); diff --git a/harbour/source/rtl/inkeyapi.c b/harbour/source/rtl/inkeyapi.c new file mode 100644 index 0000000000..7813aa01db --- /dev/null +++ b/harbour/source/rtl/inkeyapi.c @@ -0,0 +1,121 @@ +/* + * $Id$ + */ + +/* + * Harbour Project source code: + * Inkey GT API + * + * Copyright 2007 Przemyslaw Czerpak + * www - http://www.harbour-project.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/). + * + * As a special exception, the Harbour Project gives permission for + * additional uses of the text contained in its release of Harbour. + * + * The exception is that, if you link the Harbour libraries with other + * files to produce an executable, this does not by itself cause the + * resulting executable to be covered by the GNU General Public License. + * Your use of that executable is in no way restricted on account of + * linking the Harbour library code into it. + * + * This exception does not however invalidate any other reasons why + * the executable file might be covered by the GNU General Public License. + * + * This exception applies only to the code released by the Harbour + * Project under the name Harbour. If you copy code from other + * Harbour Project or Free Software Foundation releases into a copy of + * Harbour, as the General Public License permits, the exception does + * not apply to the code that you add in this way. To avoid misleading + * anyone as to the status of such modified files, you must delete + * this exception notice from them. + * + * If you write modifications of your own for Harbour, it is your choice + * whether to permit this exception to apply to your modifications. + * If you do not wish that, delete this exception notice. + * + */ + +#include "hbgtcore.h" + +HB_EXPORT int hb_inkey( BOOL fWait, double dSeconds, int iEventMask ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_inkey(%d, %f, %d)", (int) fWait, dSeconds, iEventMask)); + + return hb_inkey_Get( fWait, dSeconds, iEventMask ); +} + +HB_EXPORT void hb_inkeyPut( int iKey ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_inkeyPut(%d)", iKey)); + + hb_inkey_Put( iKey ); +} + +HB_EXPORT int hb_inkeyLast( int iEventMask ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_inkeyLast(%d)", iEventMask)); + + return hb_inkey_Last( iEventMask ); +} + +HB_EXPORT int hb_inkeyNext( int iEventMask ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_inkeyNext(%d)", iEventMask)); + + return hb_inkey_Next( iEventMask ); +} + +HB_EXPORT void hb_inkeyPoll( void ) +{ + HB_TRACE( HB_TR_DEBUG, ("hb_inkeyPoll()") ); + + hb_inkey_Poll(); +} + +HB_EXPORT int hb_inkeySetLast( int iKey ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_inkeySetLast(%d)", iKey)); + + return hb_inkey_SetLast( iKey ); +} + +HB_EXPORT void hb_inkeySetText( const char * szText, ULONG ulLen ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_inkeySetText(%s,%lu)", szText, ulLen)); + + hb_inkey_SetText( szText, ulLen ); +} + +HB_EXPORT void hb_inkeyReset( void ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_inkeyReset()")); + + hb_inkey_Reset(); +} + +HB_EXPORT void hb_inkeySetCancelKeys( int iCancelKey, int iCancelKeyEx ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_inkeySetCancelKeys(%d,%d)", iCancelKey, iCancelKeyEx)); + +/* + s_InkeyAltC = iCancelKey; + s_InkeyAltCEx = iCancelKeyEx; +*/ + HB_SYMBOL_UNUSED( iCancelKey ); + HB_SYMBOL_UNUSED( iCancelKeyEx ); +} diff --git a/harbour/source/rtl/mouse53.c b/harbour/source/rtl/mouse53.c index 15105cf5e0..5acaaf54ed 100644 --- a/harbour/source/rtl/mouse53.c +++ b/harbour/source/rtl/mouse53.c @@ -50,15 +50,14 @@ * */ -#include "hbapi.h" #include "hbapigt.h" /* HARBOUR callable interface */ #ifdef HB_COMPAT_C53 -static int s_iLeftButton = 0; -static int s_iRightButton = 1; +#define M_BUTTON_LEFT 0 +#define M_BUTTON_RIGHT 1 HB_FUNC( MPRESENT ) { @@ -115,14 +114,14 @@ HB_FUNC( MSETPOS ) hb_mouseSetPos( hb_parni( 1 ), hb_parni( 2 ) ); } -HB_FUNC( MRIGHTDOWN ) -{ - hb_retl( hb_mouseButtonState( s_iRightButton ) ); -} - HB_FUNC( MLEFTDOWN ) { - hb_retl( hb_mouseButtonState( s_iLeftButton ) ); + hb_retl( hb_mouseButtonState( M_BUTTON_LEFT ) ); +} + +HB_FUNC( MRIGHTDOWN ) +{ + hb_retl( hb_mouseButtonState( M_BUTTON_RIGHT ) ); } HB_FUNC( MDBLCLK ) diff --git a/harbour/source/rtl/mouseapi.c b/harbour/source/rtl/mouseapi.c index 8f854bb445..a264bdd3bb 100644 --- a/harbour/source/rtl/mouseapi.c +++ b/harbour/source/rtl/mouseapi.c @@ -61,15 +61,13 @@ * */ -#include "hbapi.h" -#include "hbapiitm.h" #include "hbgtcore.h" /* NOTE: Mouse initialization is called directly from low level GT driver * because it possible that mouse subsystem can depend on the terminal * (for example, mouse subsystem cannot be initialized before ncurses * driver is initialized). -*/ + */ /* C callable interface */ HB_EXPORT BOOL hb_mouseIsPresent( void )