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.
This commit is contained in:
Przemyslaw Czerpak
2010-06-24 21:21:48 +00:00
parent 73db2d44f1
commit 8434f5ab14
10 changed files with 184 additions and 114 deletions

View File

@@ -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

View File

@@ -81,6 +81,7 @@ PRG_SOURCES := \
xhbcomp.prg \
xhberr.prg \
xhbfunp.prg \
xhbinkey.prg \
xhbmt.prg \
xhbver.prg \
xthrow.prg \

View File

@@ -77,8 +77,8 @@
#xtranslate hb_FieldDec([<x>]) => FieldDec(<x>)
#xtranslate hb_FieldType([<x>]) => FieldType(<x>)
#xtranslate hb_InkeySetPreBlock([<x>]) => hb_SetInkeyBeforeBlock(<x>)
#xtranslate hb_InkeySetPostBlock([<x>]) => hb_SetInkeyAfterBlock(<x>)
#xtranslate hb_gtInfo( HB_GTI_INKEYREAD [, <x>] ) => hb_SetInkeyBeforeBlock([<x>]) <-x->
#xtranslate hb_gtInfo( HB_GTI_INKEYFILTER [, <x>] ) => hb_SetInkeyAfterBlock([<x>]) <-x->
#xtranslate hb_processOpen([<x,...>]) => hb_openProcess(<x>)
#xtranslate hb_processClose([<x,...>]) => hb_closeProcess(<x>)
@@ -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([<x>]) => hb_InkeySetPreBlock(<x>)
#xtranslate hb_SetInkeyAfterBlock([<x>]) => hb_InkeySetPostBlock(<x>)
#xtranslate hb_SetInkeyBeforeBlock([<x>]) => hb_gtInfo( HB_GTI_INKEYREAD [, <x>] ) <-x->
#xtranslate hb_SetInkeyAfterBlock([<x>]) => hb_gtInfo( HB_GTI_INKEYFILTER [, <x>] ) <-x->
#xtranslate gfxPrimitive([<x,...>]) => hb_gfxPrimitive(<x>)
#xtranslate gfxText([<x,...>]) => hb_gfxText(<x>)

View File

@@ -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 ); }

View File

@@ -0,0 +1,59 @@
/*
* $Id$
*/
/*
* Harbour Project source code:
* xHarbour compatible inkey block functions.
*
* Copyright 2010 Przemyslaw Czerpak <druzus / at / priv.onet.pl>
* 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, ... )

View File

@@ -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

View File

@@ -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 */

View File

@@ -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

View File

@@ -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 */

View File

@@ -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 )