diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 94170f6662..2dcc189100 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -16,6 +16,49 @@ The license applies to all entries newer than 2009-04-28. */ +2010-06-24 23:20 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/include/hbgtinfo.ch + * harbour/include/hbgtcore.h + * harbour/src/rtl/hbgtcore.c + + added HB_GTI_INKEYFILTER which allows to set/get codeblock used to + filter inkey key codes. This codeblock receives as 1-st parameter + actually processed inside INKEY() function key code. It should return + final inkey code (it can be the same or 0 if key should be ignored. + I.e. this code change key 'a' to 'B' and blocks 'c': + + hb_gtInfo( HB_GTI_INKEYFILTER, { | nKey | + SWITCH nKey + CASE ASC( 'a' ) + RETURN ASC( 'B' ) + CASE ASC( 'c' ) + RETURN '0' + ENDSWITCH + RETURN nKey + } ) + + + added HB_GTI_INKEYREAD which allows to set/get codeblock executed + just before INKEY() reads key code from the GT typeahead buffer. + If it returns non 0 numeric value then this value is returned instead + as inkey code. Otherwise standard inkey procedure is activated and + key code is read from the GT typeahead buffer. + + * harbour/include/hbextern.ch + * harbour/src/rtl/inkey.c + - removed HB_INKEYSETPREBLOCK() and HB_INKEYSETPOSTBLOCK() functions + + * harbour/contrib/xhb/Makefile + * harbour/contrib/xhb/xhbgt.c + + harbour/contrib/xhb/xhbinkey.prg + * harbour/contrib/xhb/hbcompat.ch + * updated emulation of xHarbour hb_SetInkeyBeforeBlock() and + hb_SetInkeyAfterBlock() functions to use new HB_GTI_* functionality. + Incompatibility warning! + In Harbour timeout value passed to inkey() is correctly respected + and not reset internally on each call to inkey after block. + If inkey before block returns non 0 numeric value then it's not + ignored but returned as INKEY() function result without touching + GT typeahead buffer. + 2010-06-24 18:31 UTC+0200 Viktor Szakats (harbour.01 syenar.hu) * src/rtl/inkey.c * include/hbextern.ch diff --git a/harbour/contrib/xhb/Makefile b/harbour/contrib/xhb/Makefile index 9095c217d2..ead1816071 100644 --- a/harbour/contrib/xhb/Makefile +++ b/harbour/contrib/xhb/Makefile @@ -81,6 +81,7 @@ PRG_SOURCES := \ xhbcomp.prg \ xhberr.prg \ xhbfunp.prg \ + xhbinkey.prg \ xhbmt.prg \ xhbver.prg \ xthrow.prg \ diff --git a/harbour/contrib/xhb/hbcompat.ch b/harbour/contrib/xhb/hbcompat.ch index 81160e3ccb..2df23715f5 100644 --- a/harbour/contrib/xhb/hbcompat.ch +++ b/harbour/contrib/xhb/hbcompat.ch @@ -77,8 +77,8 @@ #xtranslate hb_FieldDec([]) => FieldDec() #xtranslate hb_FieldType([]) => FieldType() - #xtranslate hb_InkeySetPreBlock([]) => hb_SetInkeyBeforeBlock() - #xtranslate hb_InkeySetPostBlock([]) => hb_SetInkeyAfterBlock() + #xtranslate hb_gtInfo( HB_GTI_INKEYREAD [, ] ) => hb_SetInkeyBeforeBlock([]) <-x-> + #xtranslate hb_gtInfo( HB_GTI_INKEYFILTER [, ] ) => hb_SetInkeyAfterBlock([]) <-x-> #xtranslate hb_processOpen([]) => hb_openProcess() #xtranslate hb_processClose([]) => hb_closeProcess() @@ -338,8 +338,8 @@ #xtranslate gtGetClipBoardSize() => Len( hb_gtInfo( HB_GTI_CLIPBOARDDATA ) ) #xtranslate gtPasteClipBoard() => hb_gtInfo( HB_GTI_CLIPBOARDPASTE ) #xtranslate gtProcessMessages() => NextKey() - #xtranslate hb_SetInkeyBeforeBlock([]) => hb_InkeySetPreBlock() - #xtranslate hb_SetInkeyAfterBlock([]) => hb_InkeySetPostBlock() + #xtranslate hb_SetInkeyBeforeBlock([]) => hb_gtInfo( HB_GTI_INKEYREAD [, ] ) <-x-> + #xtranslate hb_SetInkeyAfterBlock([]) => hb_gtInfo( HB_GTI_INKEYFILTER [, ] ) <-x-> #xtranslate gfxPrimitive([]) => hb_gfxPrimitive() #xtranslate gfxText([]) => hb_gfxText() diff --git a/harbour/contrib/xhb/xhbgt.c b/harbour/contrib/xhb/xhbgt.c index 9d199d08e7..c3de05afea 100644 --- a/harbour/contrib/xhb/xhbgt.c +++ b/harbour/contrib/xhb/xhbgt.c @@ -53,8 +53,6 @@ #include "hbapi.h" HB_FUNC_EXTERN( NEXTKEY ) ; HB_FUNC( GTPROCESSMESSAGES ) { HB_FUNC_EXEC( NEXTKEY ); } -HB_FUNC_EXTERN( HB_INKEYSETPREBLOCK ) ; HB_FUNC( HB_SETINKEYBEFOREBLOCK ) { HB_FUNC_EXEC( HB_INKEYSETPREBLOCK ); } -HB_FUNC_EXTERN( HB_INKEYSETPOSTBLOCK ) ; HB_FUNC( HB_SETINKEYAFTERBLOCK ) { HB_FUNC_EXEC( HB_INKEYSETPOSTBLOCK ); } HB_FUNC_EXTERN( HB_GFXPRIMITIVE ) ; HB_FUNC( GFXPRIMITIVE ) { HB_FUNC_EXEC( HB_GFXPRIMITIVE ); } HB_FUNC_EXTERN( HB_GFXTEXT ) ; HB_FUNC( GFXTEXT ) { HB_FUNC_EXEC( HB_GFXTEXT ); } HB_FUNC_EXTERN( HB_GTLOCK ) ; HB_FUNC( HBCONSOLELOCK ) { HB_FUNC_EXEC( HB_GTLOCK ); } diff --git a/harbour/contrib/xhb/xhbinkey.prg b/harbour/contrib/xhb/xhbinkey.prg new file mode 100644 index 0000000000..55ac4234a3 --- /dev/null +++ b/harbour/contrib/xhb/xhbinkey.prg @@ -0,0 +1,59 @@ +/* + * $Id$ + */ + +/* + * Harbour Project source code: + * xHarbour compatible inkey block functions. + * + * Copyright 2010 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 "hbgtinfo.ch" + +FUNCTION hb_SetInkeyBefore( ... ) + RETURN hb_gtInfo( HB_GTI_INKEYREAD, ... ) + +FUNCTION hb_SetInkeyAfterBlock( ... ) + RETURN hb_gtInfo( HB_GTI_INKEYFILTER, ... ) diff --git a/harbour/include/hbextern.ch b/harbour/include/hbextern.ch index 4ed0028ab2..37b0e3faec 100644 --- a/harbour/include/hbextern.ch +++ b/harbour/include/hbextern.ch @@ -913,8 +913,6 @@ EXTERNAL HB_PROCESSCLOSE EXTERNAL HB_PROCESSRUN EXTERNAL HB_GCSTEP EXTERNAL HB_GCALL -EXTERNAL HB_INKEYSETPREBLOCK -EXTERNAL HB_INKEYSETPOSTBLOCK EXTERNAL HB_KEYCLEAR EXTERNAL HB_KEYPUT EXTERNAL HB_KEYINS diff --git a/harbour/include/hbgtcore.h b/harbour/include/hbgtcore.h index 9098fecc60..1604981afa 100644 --- a/harbour/include/hbgtcore.h +++ b/harbour/include/hbgtcore.h @@ -333,6 +333,8 @@ typedef struct _HB_GT_BASE HB_SIZE StrBufferPos; PHB_ITEM pNotifierBlock; + PHB_ITEM pInkeyFilterBlock; + PHB_ITEM pInkeyReadBlock; PHB_ITEM pCargo; void * pGTData[ HB_GT_MAX_ ]; /* local GT data */ diff --git a/harbour/include/hbgtinfo.ch b/harbour/include/hbgtinfo.ch index fc1c146c89..c31910d449 100644 --- a/harbour/include/hbgtinfo.ch +++ b/harbour/include/hbgtinfo.ch @@ -138,6 +138,9 @@ #define HB_GTI_CARGO 58 /* Storage of any user defined value */ #define HB_GTI_FONTSEL 59 /* X11 style font selecting */ +#define HB_GTI_INKEYFILTER 60 /* Get/Set inkey keycodes filter */ +#define HB_GTI_INKEYREAD 61 /* Get/Set inkey read block */ + /* Font weights */ #define HB_GTI_FONTW_THIN 1 #define HB_GTI_FONTW_NORMAL 2 diff --git a/harbour/src/rtl/hbgtcore.c b/harbour/src/rtl/hbgtcore.c index 1f6e5a84d3..5534166dfc 100644 --- a/harbour/src/rtl/hbgtcore.c +++ b/harbour/src/rtl/hbgtcore.c @@ -167,6 +167,10 @@ static void hb_gt_def_Free( PHB_GT pGT ) if( pGT->pNotifierBlock ) hb_itemRelease( pGT->pNotifierBlock ); + if( pGT->pInkeyFilterBlock ) + hb_itemRelease( pGT->pInkeyFilterBlock ); + if( pGT->pInkeyReadBlock ) + hb_itemRelease( pGT->pInkeyReadBlock ); if( pGT->pCargo ) hb_itemRelease( pGT->pCargo ); @@ -183,6 +187,10 @@ static void hb_gt_def_Mark( PHB_GT pGT ) { if( pGT->pNotifierBlock ) hb_gcMark( pGT->pNotifierBlock ); + if( pGT->pInkeyFilterBlock ) + hb_gcMark( pGT->pInkeyFilterBlock ); + if( pGT->pInkeyReadBlock ) + hb_gcMark( pGT->pInkeyReadBlock ); if( pGT->pCargo ) hb_gcMark( pGT->pCargo ); if( pGT->pMutex ) @@ -1460,6 +1468,30 @@ static HB_BOOL hb_gt_def_SetKeyCP( PHB_GT pGT, const char * pszTermCDP, const ch return HB_FALSE; } +static void hb_gt_def_SetBlock( PHB_ITEM * pItemPtr, PHB_GT_INFO pInfo ) +{ + if( *pItemPtr ) + { + if( pInfo->pResult ) + hb_itemCopy( pInfo->pResult, *pItemPtr ); + else + pInfo->pResult = hb_itemNew( *pItemPtr ); + } + if( pInfo->pNewVal ) + { + if( *pItemPtr ) + { + hb_itemRelease( *pItemPtr ); + *pItemPtr = NULL; + } + if( hb_itemType( pInfo->pNewVal ) & HB_IT_BLOCK ) + { + *pItemPtr = hb_itemNew( pInfo->pNewVal ); + hb_gcUnlock( *pItemPtr ); + } + } +} + static HB_BOOL hb_gt_def_Info( PHB_GT pGT, int iType, PHB_GT_INFO pInfo ) { switch( iType ) @@ -1585,26 +1617,15 @@ static HB_BOOL hb_gt_def_Info( PHB_GT pGT, int iType, PHB_GT_INFO pInfo ) break; case HB_GTI_NOTIFIERBLOCK: - if( pGT->pNotifierBlock ) - { - if( pInfo->pResult ) - hb_itemCopy( pInfo->pResult, pGT->pNotifierBlock ); - else - pInfo->pResult = hb_itemNew( pGT->pNotifierBlock ); - } - if( pInfo->pNewVal ) - { - if( pGT->pNotifierBlock ) - { - hb_itemRelease( pGT->pNotifierBlock ); - pGT->pNotifierBlock = NULL; - } - if( hb_itemType( pInfo->pNewVal ) & HB_IT_BLOCK ) - { - pGT->pNotifierBlock = hb_itemNew( pInfo->pNewVal ); - hb_gcUnlock( pGT->pNotifierBlock ); - } - } + hb_gt_def_SetBlock( &pGT->pNotifierBlock, pInfo ); + break; + + case HB_GTI_INKEYFILTER: + hb_gt_def_SetBlock( &pGT->pInkeyFilterBlock, pInfo ); + break; + + case HB_GTI_INKEYREAD: + hb_gt_def_SetBlock( &pGT->pInkeyReadBlock, pInfo ); break; case HB_GTI_CARGO: @@ -2452,10 +2473,23 @@ static int hb_gt_def_InkeyNext( PHB_GT pGT, int iEventMask ) static int hb_gt_def_InkeyGet( PHB_GT pGT, HB_BOOL fWait, double dSeconds, int iEventMask ) { HB_MAXUINT end_timer; + PHB_ITEM pKey; HB_BOOL fPop; + int iKey; HB_TRACE(HB_TR_DEBUG, ("hb_gt_def_InkeyGet(%p,%d,%f,%d)", pGT, (int) fWait, dSeconds, iEventMask)); + pKey = NULL; + + if( pGT->pInkeyReadBlock ) + { + HB_GTSELF_UNLOCK( pGT ); + iKey = hb_itemGetNI( hb_vmEvalBlock( pGT->pInkeyReadBlock ) ); + HB_GTSELF_LOCK( pGT ); + if( iKey != 0 ) + return iKey; + } + /* Wait forever ?, Use fixed value 100 for strict Clipper compatibility */ if( fWait && dSeconds * 100 >= 1 ) end_timer = hb_dateMilliSeconds() + ( HB_MAXUINT ) ( dSeconds * 1000 ); @@ -2468,11 +2502,21 @@ static int hb_gt_def_InkeyGet( PHB_GT pGT, HB_BOOL fWait, double dSeconds, int i fPop = hb_gt_def_InkeyNextCheck( pGT, iEventMask, &pGT->inkeyLast ); if( fPop ) - break; + { + hb_gt_def_InkeyPop( pGT ); + if( !pGT->pInkeyFilterBlock ) + break; + pKey = hb_itemPutNI( pKey, pGT->inkeyLast ); + HB_GTSELF_UNLOCK( pGT ); + pGT->inkeyLast = hb_itemGetNI( hb_vmEvalBlockV( pGT->pInkeyFilterBlock, 1, pKey ) ); + HB_GTSELF_LOCK( pGT ); + if( pGT->inkeyLast != 0 ) + break; + } /* immediately break if a VM request is pending. */ if( !fWait || hb_vmRequestQuery() != 0 ) - return 0; + break; HB_GTSELF_UNLOCK( pGT ); hb_idleState(); @@ -2480,15 +2524,12 @@ static int hb_gt_def_InkeyGet( PHB_GT pGT, HB_BOOL fWait, double dSeconds, int i } while( end_timer == 0 || end_timer > hb_dateMilliSeconds() ); + if( pKey ) + hb_itemRelease( pKey ); + hb_idleReset(); - if( fPop ) - { - hb_gt_def_InkeyPop( pGT ); - return pGT->inkeyLast; - } - - return 0; + return fPop ? pGT->inkeyLast : 0; } /* Return the value of the last key that was extracted */ diff --git a/harbour/src/rtl/inkey.c b/harbour/src/rtl/inkey.c index e989bb97cc..81ce5a7b4d 100644 --- a/harbour/src/rtl/inkey.c +++ b/harbour/src/rtl/inkey.c @@ -77,87 +77,12 @@ #include "hbstack.h" #include "hbvm.h" -typedef struct -{ - PHB_ITEM before; - PHB_ITEM after; -} HB_INKEYBLOCK, * PHB_INKEYBLOCK; - -static void hb_inkeyBlockRelease( void * cargo ) -{ - PHB_INKEYBLOCK pInkeyBlock = ( PHB_INKEYBLOCK ) cargo; - - if( pInkeyBlock->before ) - hb_itemRelease( pInkeyBlock->before ); - if( pInkeyBlock->after ) - hb_itemRelease( pInkeyBlock->after ); -} - -static HB_TSD_NEW( s_inkeyBlock, sizeof( HB_INKEYBLOCK ), NULL, hb_inkeyBlockRelease ); - HB_FUNC( INKEY ) { - PHB_INKEYBLOCK pInkeyBlock = ( PHB_INKEYBLOCK ) hb_stackTestTSD( &s_inkeyBlock ); int iPCount = hb_pcount(); - PHB_ITEM pKey = NULL; - int iKey; - if( pInkeyBlock && pInkeyBlock->before ) - hb_vmEvalBlock( pInkeyBlock->before ); - - do - { - iKey = hb_inkey( iPCount == 1 || ( iPCount > 1 && HB_ISNUM( 1 ) ), - hb_parnd( 1 ), - HB_ISNUM( 2 ) ? hb_parni( 2 ) : hb_setGetEventMask() ); - - if( iKey == 0 || !pInkeyBlock || !pInkeyBlock->after ) - break; - - pKey = hb_itemPutNI( pKey, iKey ); - iKey = hb_itemGetNI( hb_vmEvalBlockV( pInkeyBlock->after, 1, pKey ) ); - hb_inkeySetLast( iKey ); - } - while( iKey == 0 ); - - if( pKey ) - hb_itemRelease( pKey ); - - hb_retni( iKey ); -} - -HB_FUNC( HB_INKEYSETPREBLOCK ) -{ - PHB_INKEYBLOCK pInkeyBlock = ( PHB_INKEYBLOCK ) hb_stackGetTSD( &s_inkeyBlock ); - - if( pInkeyBlock->before ) - hb_itemReturn( pInkeyBlock->before ); - - if( hb_pcount() > 0 ) - { - PHB_ITEM pBlock = hb_param( 1, HB_IT_BLOCK ); - - if( pInkeyBlock->before ) - hb_itemRelease( pInkeyBlock->before ); - pInkeyBlock->before = pBlock ? hb_itemNew( pBlock ) : pBlock; - } -} - -HB_FUNC( HB_INKEYSETPOSTBLOCK ) -{ - PHB_INKEYBLOCK pInkeyBlock = ( PHB_INKEYBLOCK ) hb_stackGetTSD( &s_inkeyBlock ); - - if( pInkeyBlock->after ) - hb_itemReturn( pInkeyBlock->after ); - - if( hb_pcount() > 0 ) - { - PHB_ITEM pBlock = hb_param( 1, HB_IT_BLOCK ); - - if( pInkeyBlock->after ) - hb_itemRelease( pInkeyBlock->after ); - pInkeyBlock->after = pBlock ? hb_itemNew( pBlock ) : pBlock; - } + hb_retni( hb_inkey( iPCount == 1 || ( iPCount > 1 && HB_ISNUM( 1 ) ), + hb_parnd( 1 ), hb_parnidef( 2, hb_setGetEventMask() ) ) ); } HB_FUNC( __KEYBOARD )