From ce8480f2a8d998aff92726c30d520784c5c828a7 Mon Sep 17 00:00:00 2001 From: "David G. Holm" Date: Sat, 18 Aug 2001 00:09:25 +0000 Subject: [PATCH] See ChangeLog entry 2001-08-17 18:10 UTC-0400 David G. Holm --- harbour/ChangeLog | 7 ++ harbour/doc/en/hb_set.txt | 131 ++++++++++++++++++++++++++++++++++++++ harbour/include/hbset.h | 11 ++++ harbour/source/rtl/set.c | 89 ++++++++++++++++++++++++++ 4 files changed, 238 insertions(+) diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 4c664b19d7..e3b9e64c9e 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -1,3 +1,10 @@ +2001-08-17 18:10 UTC-0400 David G. Holm + + * doc/en/hb_set.txt + * include/hbset.h + * source/rtl/set.h + + Added a primitive SET listener API. + 2001-08-18 00:11 GMT+2 Maurilio Longo * source/rtl/tbrowse.prg * source/rtl/tbcolumn.prg diff --git a/harbour/doc/en/hb_set.txt b/harbour/doc/en/hb_set.txt index 5c54bcd46a..99485ccca2 100644 --- a/harbour/doc/en/hb_set.txt +++ b/harbour/doc/en/hb_set.txt @@ -79,3 +79,134 @@ * $END$ */ +/* $DOC$ + * $FUNCNAME$ + * hb_setListenerAdd() + * $CATEGORY$ + * Set API + * $ONELINER$ + * + * $SYNTAX$ + * C Prototype + * + * #include + * hb_setListenerAdd( PHB_SET_LISTENER_CALLBACK callback ) --> int + * $ARGUMENTS$ + * + * A pointer to a function taking two enum parameters and returning + * no value. The first parameter identifies the SET parameter that is + * to be changed and the second parameter identifies whether the call + * is from before or after the value is changed. The callback function + * will be called twice whenever a SET parameter is changed using the + * Harbour SET function. The first call takes place before the SET + * value is changed and the second one is after the SET parameter has + * been changed. + * $RETURNS$ + * An integer value representing the callback handle, in case the + * caller needs to deactivate the callback function. + * $DESCRIPTION$ + * This function allows a subsystem that needs to track the status + * of some SET parameters to be notified whenever a SET parameter gets + * changed. + * $EXAMPLES$ + * void callback_function( HB_set_enum set, HB_set_listener_enum when ) + * { + * printf("\nCalled for SET parameter %d %s changing.", + * set, (when ? "after" : "before")); + * } + * int handle = hb_setListenerAdd( callback_function ); + * $STATUS$ + * R + * $COMPLIANCE$ + * Compliance is not applicable to API calls. + * $FILES$ + * Library is rtl + * $PLATFORMS$ + * All + * $SEEALSO$ + * hb_setListenerRemove() + * $END$ + */ + +/* $DOC$ + * $FUNCNAME$ + * hb_setListenerNotify() + * $CATEGORY$ + * Set API + * $ONELINER$ + * + * $SYNTAX$ + * C Prototype + * + * #include + * hb_setListenerNotify( HB_set_enum set, HB_set_listener_enum + * when ) --> int + * $ARGUMENTS$ + * + * The number of the SET parameter that is to be or was changed. + * + * Set to HB_SET_LISTENER_BEFORE when called before the SET parameter + * is to be changed and set to HB_SET_LISTENER_AFTER when called + * after the SET parameter has been changed. + * $RETURNS$ + * + * $DESCRIPTION$ + * This function notifies all SET listener callback functions. It + * must be called any time you change the value of a SET parameter + * directly instead of using the Harbour SET function. Both before + * and after the change. + * $EXAMPLES$ + * hb_setListenerNotify( HB_SET_DECIMALS, HB_SET_LISTENER_BEFORE ); + * hb_set.HB_SET_DECIMALS = 3; + * hb_setListenerNotify( HB_SET_DECIMALS, HB_SET_LISTENER_AFTER ); + * $STATUS$ + * R + * $COMPLIANCE$ + * Compliance is not applicable to API calls. + * $FILES$ + * Library is rtl + * $PLATFORMS$ + * All + * $SEEALSO$ + * hb_setListenerAdd() + * $END$ + */ + + +/* $DOC$ + * $FUNCNAME$ + * hb_setListenerRemove() + * $CATEGORY$ + * Set API + * $ONELINER$ + * + * $SYNTAX$ + * C Prototype + * + * #include + * hb_setListenerRemove( int handle ) --> int + * $ARGUMENTS$ + * + * The handle for the SET listener callback function to be removed. + * $RETURNS$ + * The handle if the callback function could not be located or the + * negative value of the handle if the callback function was removed. + * $DESCRIPTION$ + * This function removes a SET listener callback function. + * $EXAMPLES$ + * int handle = hb_setListenerAdd( callback_function ); + * ... + * hb_setListenerRemove( handle ); + * $STATUS$ + * R + * $COMPLIANCE$ + * Compliance is not applicable to API calls. + * $FILES$ + * Library is rtl + * $PLATFORMS$ + * All + * $SEEALSO$ + * hb_setListenerAdd() + * $END$ + */ + diff --git a/harbour/include/hbset.h b/harbour/include/hbset.h index f86220f995..71af2a1b21 100644 --- a/harbour/include/hbset.h +++ b/harbour/include/hbset.h @@ -191,6 +191,17 @@ extern HB_SET_STRUCT hb_set; extern void hb_setInitialize( void ); extern void hb_setRelease( void ); +typedef enum +{ + HB_SET_LISTENER_BEFORE, + HB_SET_LISTENER_AFTER +} HB_set_listener_enum; +typedef void HB_SET_LISTENER_CALLBACK( HB_set_enum, HB_set_listener_enum ); + +extern int hb_setListenerAdd( HB_SET_LISTENER_CALLBACK * ); +extern void hb_setListenerNotify( HB_set_enum, HB_set_listener_enum ); +extern int hb_setListenerRemove( int ); + #if defined(HB_EXTERN_C) } #endif diff --git a/harbour/source/rtl/set.c b/harbour/source/rtl/set.c index 3a6c457e9e..b5025da28b 100644 --- a/harbour/source/rtl/set.c +++ b/harbour/source/rtl/set.c @@ -62,6 +62,17 @@ HB_SET_STRUCT hb_set; +typedef struct HB_SET_LISTENER_ +{ + int listener; + HB_SET_LISTENER_CALLBACK * callback; + struct HB_SET_LISTENER_ * next; +} HB_SET_LISTENER, * PHB_SET_LISTENER; + +static PHB_SET_LISTENER sp_sl_first; +static PHB_SET_LISTENER sp_sl_last; +static int s_next_listener; + static BOOL set_logical( PHB_ITEM pItem ) { BOOL bLogical = FALSE; @@ -344,6 +355,8 @@ HB_FUNC( SET ) PHB_ITEM pArg2 = ( args > 1 ) ? hb_param( 2, HB_IT_ANY ) : NULL; PHB_ITEM pArg3 = ( args > 2 ) ? hb_param( 3, HB_IT_ANY ) : NULL; + if( args > 1 ) hb_setListenerNotify( set_specifier, HB_SET_LISTENER_BEFORE ); + switch ( set_specifier ) { case HB_SET_ALTERNATE : @@ -642,8 +655,16 @@ HB_FUNC( SET ) /* Return NIL if called with invalid SET specifier */ break; } + if( args > 1 ) hb_setListenerNotify( set_specifier, HB_SET_LISTENER_AFTER ); } +/* Listener test (1 of 2) +static void test_callback( HB_set_enum set, HB_set_listener_enum when ) +{ + printf("\ntest_callback( %d, %d )", set, when); +} +End listener test (1 of 2) */ + void hb_setInitialize( void ) { HB_TRACE(HB_TR_DEBUG, ("hb_setInitialize()")); @@ -707,6 +728,22 @@ void hb_setInitialize( void ) hb_set.HB_SET_UNIQUE = FALSE; hb_set.HB_SET_VIDEOMODE = 0; hb_set.HB_SET_WRAP = FALSE; + + sp_sl_first = sp_sl_last = NULL; + s_next_listener = 1; + + /* Listener test (2 of 2) + { + int temp = hb_setListenerAdd( test_callback ); + printf("\nSet listener test handle is %d", temp); + { + int temp2 = hb_setListenerAdd( test_callback ); + printf("\nSet listener test handle is %d", temp2); + temp2 = hb_setListenerRemove( temp2 ); + printf("\nSet listener remove result is %d", temp2); + } + } + End listener test (2 of 2) */ } void hb_setRelease( void ) @@ -728,4 +765,56 @@ void hb_setRelease( void ) if( hb_set.HB_SET_PRINTFILE ) hb_xfree( hb_set.HB_SET_PRINTFILE ); hb_set.HB_SET_TYPEAHEAD = -1; hb_inkeyReset( TRUE ); /* Free keyboard typeahead buffer */ + + while( sp_sl_first ) + { + /* Free all set listeners */ + sp_sl_last = sp_sl_first->next; + hb_xfree( sp_sl_first ); + sp_sl_first = sp_sl_last; + } +} + +int hb_setListenerAdd( HB_SET_LISTENER_CALLBACK * callback ) +{ + PHB_SET_LISTENER p_sl = (PHB_SET_LISTENER) hb_xgrab( sizeof( HB_SET_LISTENER ) ); + p_sl->callback = callback; + p_sl->listener = s_next_listener++; + if( sp_sl_last ) sp_sl_last->next = p_sl; + else if( ! sp_sl_first ) sp_sl_first = p_sl; + sp_sl_last = p_sl; + return p_sl->listener; +} + +void hb_setListenerNotify( HB_set_enum set, HB_set_listener_enum when ) +{ + PHB_SET_LISTENER p_sl = sp_sl_first; + while( p_sl ) + { + (* p_sl->callback)( set, when ); + p_sl = p_sl->next; + } +} + +int hb_setListenerRemove( int listener ) +{ + PHB_SET_LISTENER p_sl = sp_sl_first; + PHB_SET_LISTENER p_sl_prev = NULL; + while( p_sl ) + { + if( listener == p_sl->listener ) + { + listener = -listener; + if( p_sl_prev ) p_sl_prev->next = p_sl->next; + else sp_sl_first = p_sl->next; + hb_xfree( p_sl ); + p_sl = NULL; + } + if( p_sl ) + { + p_sl_prev = p_sl; + p_sl = p_sl->next; + } + } + return listener; }