From 1ad4e9c53a5abb0be408e4f2016d1ac16087db90 Mon Sep 17 00:00:00 2001 From: Przemyslaw Czerpak Date: Fri, 24 Oct 2008 10:00:30 +0000 Subject: [PATCH] 2008-10-24 12:00 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/source/rtl/gtxwc/gtxwc.c * added hack for problems with some XLIB versions in heavy stress MT tests * harbour/include/hbapigt.h * harbour/source/vm/thread.c * added parameter to hb_gtAlloc() C function * harbour/include/hbapigt.h * harbour/source/rtl/hbgtcore.c + added hb_gtCreate() and hb_gtSwap() C functions + added new .prg functions: HB_GTCREATE( ) -> HB_GTSELECT( ) -> Using this functions is possible to create many console window if GT supports such possibilities (f.e. GTXWC or GTWVT) even in single thread programs and switch between them. * harbour/source/rtl/box.c ! fixed one of recent DISPBOX() modifications - it should use: hb_gtBoxEx() instead of hb_gtDrawBox() to set cursor position. + harbour/tests/gtwin.prg + added demonstration/test code for using more then one console window also in single thread programs. --- harbour/ChangeLog | 27 ++++++++ harbour/include/hbapigt.h | 7 +- harbour/source/rtl/box.c | 12 ++-- harbour/source/rtl/gtxwc/gtxwc.c | 50 +++++++++++---- harbour/source/rtl/hbgtcore.c | 107 ++++++++++++++++++++++++++++++- harbour/source/vm/thread.c | 2 +- harbour/tests/gtwin.prg | 65 +++++++++++++++++++ 7 files changed, 248 insertions(+), 22 deletions(-) create mode 100644 harbour/tests/gtwin.prg diff --git a/harbour/ChangeLog b/harbour/ChangeLog index dac21e70c0..381f5a89f4 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,33 @@ 2008-12-31 13:59 UTC+0100 Foo Bar (foo.bar foobar.org) */ +2008-10-24 12:00 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/source/rtl/gtxwc/gtxwc.c + * added hack for problems with some XLIB versions in heavy stress + MT tests + + * harbour/include/hbapigt.h + * harbour/source/vm/thread.c + * added parameter to hb_gtAlloc() C function + + * harbour/include/hbapigt.h + * harbour/source/rtl/hbgtcore.c + + added hb_gtCreate() and hb_gtSwap() C functions + + added new .prg functions: + HB_GTCREATE( ) -> + HB_GTSELECT( ) -> + Using this functions is possible to create many console window + if GT supports such possibilities (f.e. GTXWC or GTWVT) even in + single thread programs and switch between them. + + * harbour/source/rtl/box.c + ! fixed one of recent DISPBOX() modifications - it should use: + hb_gtBoxEx() instead of hb_gtDrawBox() to set cursor position. + + + harbour/tests/gtwin.prg + + added demonstration/test code for using more then one console window + also in single thread programs. + 2008-10-24 10:48 UTC+0200 Viktor Szakats (harbour.01 syenar hu) * source/vm/arrayshb.c % Removed unnecessary pcount() calls. diff --git a/harbour/include/hbapigt.h b/harbour/include/hbapigt.h index d57dfaab61..a30912a9ab 100644 --- a/harbour/include/hbapigt.h +++ b/harbour/include/hbapigt.h @@ -153,13 +153,18 @@ typedef struct /* Public interface. These should never change, only be added to. */ extern HB_EXPORT void hb_gtStartupInit( void ); -extern HB_EXPORT void * hb_gtAlloc( void ); +extern HB_EXPORT void * hb_gtAlloc( void * hGT ); extern HB_EXPORT void hb_gtRelease( void * hGT ); extern HB_EXPORT void hb_gtAttach( void * hGT ); +extern HB_EXPORT void * hb_gtSwap( void * hGT ); extern HB_EXPORT BOOL hb_gtReload( const char * szGtName, HB_FHANDLE hFilenoStdin, HB_FHANDLE hFilenoStdout, HB_FHANDLE hFilenoStderr ); +extern HB_EXPORT void * hb_gtCreate( const char * szGtName, + HB_FHANDLE hFilenoStdin, + HB_FHANDLE hFilenoStdout, + HB_FHANDLE hFilenoStderr ); extern HB_EXPORT ERRCODE hb_gtInit( HB_FHANDLE hFilenoStdin, HB_FHANDLE hFilenoStdout, HB_FHANDLE hFilenoStderr ); extern HB_EXPORT ERRCODE hb_gtExit( void ); diff --git a/harbour/source/rtl/box.c b/harbour/source/rtl/box.c index 287d9f7f52..a45bf0da30 100644 --- a/harbour/source/rtl/box.c +++ b/harbour/source/rtl/box.c @@ -76,12 +76,12 @@ HB_FUNC( DISPBOX ) iColor = hb_parni( 6 ); else iColor = -1; - hb_gtDrawBox( ( SHORT ) hb_itemGetNI( pTop ), - ( SHORT ) hb_itemGetNI( pLeft), - ( SHORT ) hb_itemGetNI( pBottom ), - ( SHORT ) hb_itemGetNI( pRight ), - ( BYTE * ) ( *pszBox ? pszBox : " " ), - iColor ); + hb_gtBoxEx( hb_itemGetNI( pTop ), + hb_itemGetNI( pLeft), + hb_itemGetNI( pBottom ), + hb_itemGetNI( pRight ), + ( BYTE * ) ( *pszBox ? pszBox : " " ), + iColor ); } else { diff --git a/harbour/source/rtl/gtxwc/gtxwc.c b/harbour/source/rtl/gtxwc/gtxwc.c index b26c45db93..f9e632a13d 100644 --- a/harbour/source/rtl/gtxwc/gtxwc.c +++ b/harbour/source/rtl/gtxwc/gtxwc.c @@ -468,18 +468,26 @@ static int s_updateMode = XWC_ASYNC_UPDATE; #endif static int s_iUpdateCounter; +static BOOL s_fIgnoreErrors = FALSE; + /* *********************************************************************** */ static int s_errorHandler( Display *dpy, XErrorEvent *e ) { char errorText[1024]; - snprintf( errorText, sizeof( errorText ), "%s", "Xlib error: " ); - XGetErrorText( dpy, e->error_code, - errorText + strlen( errorText ), - sizeof(errorText) - strlen( errorText ) ); - s_fNoXServer = TRUE; - hb_errInternal( 10001, errorText, NULL, NULL ); + hb_strncpy( errorText, "Xlib error: ", sizeof( errorText ) - 1 ); + XGetErrorText( dpy, e->error_code, errorText + strlen( errorText ), + sizeof( errorText ) - strlen( errorText ) ); + + if( !s_fIgnoreErrors ) + { + s_fNoXServer = TRUE; + hb_errInternal( 10001, errorText, NULL, NULL ); + } + + fprintf( stderr, "%s\n", errorText ); + return 1; } @@ -2080,6 +2088,12 @@ static void hb_gt_xwc_WndProc( PXWND_DEF wnd, XEvent *evt ) break; } + case CreateNotify: +#ifdef XWC_DEBUG + printf( "Event: CreateNotify\r\n" ); fflush(stdout); +#endif + break; + case MappingNotify: #ifdef XWC_DEBUG printf( "Event: MappingNotify\r\n" ); fflush(stdout); @@ -2852,8 +2866,6 @@ static ULONG hb_gt_xwc_CurrentTime( void ) static void hb_gt_xwc_ProcessMessages( PXWND_DEF wnd ) { - XEvent evt; - if( wnd->cursorType != SC_NONE ) { if( wnd->cursorBlinkRate == 0 ) @@ -2886,6 +2898,7 @@ static void hb_gt_xwc_ProcessMessages( PXWND_DEF wnd ) { while( XEventsQueued( wnd->dpy, QueuedAfterFlush ) ) { + XEvent evt; XNextEvent( wnd->dpy, &evt ); hb_gt_xwc_WndProc( wnd, &evt ); } @@ -2900,6 +2913,7 @@ static void hb_gt_xwc_ProcessMessages( PXWND_DEF wnd ) BOOL fRepeat; do { + XEvent evt; fRepeat = FALSE; while( XCheckWindowEvent( wnd->dpy, wnd->window, XWC_STD_MASK, &evt ) ) { @@ -3109,13 +3123,13 @@ static void hb_gt_xwc_DissConnectX( PXWND_DEF wnd ) { HB_XWC_XLIB_LOCK - hb_gt_xwc_DestroyCharTrans( wnd ); - if( wnd->dpy != NULL ) { + hb_gt_xwc_DestroyCharTrans( wnd ); + if( wnd->pm ) { - XFreePixmap( wnd->dpy, wnd->pm); + XFreePixmap( wnd->dpy, wnd->pm ); wnd->pm = 0; } if( wnd->xfs ) @@ -3128,11 +3142,22 @@ static void hb_gt_xwc_DissConnectX( PXWND_DEF wnd ) XFreeGC( wnd->dpy, wnd->gc ); wnd->gc = 0; } + if( wnd->window ) + { + XDestroyWindow( wnd->dpy, wnd->window ); + wnd->window = 0; + } + XSync( wnd->dpy, True ); XCloseDisplay( wnd->dpy ); wnd->dpy = NULL; + /* Hack to avoid race condition inside some XLIB library - it looks + * in heavy stres MT tests that it can receive some events bound with + * destroyed objects and executes our error handler. + */ + s_fIgnoreErrors = TRUE; } HB_XWC_XLIB_UNLOCK @@ -3243,6 +3268,9 @@ static void hb_gt_xwc_CreateWindow( PXWND_DEF wnd ) XSetWMProtocols( wnd->dpy, wnd->window, &s_atomDelWin, 1 ); XSelectInput( wnd->dpy, wnd->window, XWC_STD_MASK ); +#ifdef XWC_DEBUG + printf( "Window created\r\n" ); fflush(stdout); +#endif HB_XWC_XLIB_UNLOCK } diff --git a/harbour/source/rtl/hbgtcore.c b/harbour/source/rtl/hbgtcore.c index 10ea3c6055..c3f448d7dd 100644 --- a/harbour/source/rtl/hbgtcore.c +++ b/harbour/source/rtl/hbgtcore.c @@ -3180,9 +3180,18 @@ HB_EXPORT PHB_GT hb_gtLoad( const char * szGtName, PHB_GT pGT, PHB_GT_FUNCS pSup return NULL; } -HB_EXPORT void * hb_gtAlloc( void ) +HB_EXPORT void * hb_gtAlloc( void * hGT ) { - PHB_GT pGT = hb_gt_Base(); + PHB_GT pGT; + + if( hGT ) + { + pGT = ( PHB_GT ) hGT; + if( !HB_GTSELF_LOCK( pGT ) ) + pGT = NULL; + } + else + pGT = hb_gt_Base(); if( pGT ) { @@ -3229,6 +3238,15 @@ HB_EXPORT void hb_gtAttach( void * hGT ) } } +HB_EXPORT void * hb_gtSwap( void * hGT ) +{ + void * hCurrGT = hb_stackGetGT(); + + hb_stackSetGT( hGT ); + + return hCurrGT; +} + HB_EXPORT BOOL hb_gtReload( const char * szGtName, HB_FHANDLE hFilenoStdin, HB_FHANDLE hFilenoStdout, @@ -3245,6 +3263,25 @@ HB_EXPORT BOOL hb_gtReload( const char * szGtName, return fResult; } +HB_EXPORT void * hb_gtCreate( const char * szGtName, + HB_FHANDLE hFilenoStdin, + HB_FHANDLE hFilenoStdout, + HB_FHANDLE hFilenoStderr ) +{ + void * hCurrGT = hb_gtSwap( NULL ); + + if( szGtName && hb_gt_FindEntry( szGtName ) != -1 ) + { + PHB_GT pGT = hb_gtLoad( szGtName, NULL, NULL ); + if( pGT ) + { + hb_stackSetGT( pGT ); + hb_gtInit( hFilenoStdin, hFilenoStdout, hFilenoStderr ); + } + } + return hb_gtSwap( hCurrGT ); +} + static BOOL hb_gtTryInit( const char * szGtName, BOOL fFree ) { if( szGtName ) @@ -3284,10 +3321,74 @@ HB_EXPORT void hb_gtStartupInit( void ) HB_GT_ANNOUNCE( HB_GT_NAME ) +static HB_GARBAGE_FUNC( hb_gt_Destructor ) +{ + void ** gtHolder = ( void ** ) Cargo; + + if( *gtHolder ) + { + hb_gtRelease( *gtHolder ); + *gtHolder = NULL; + } +} + +static void * hb_gtParam( int iParam ) +{ + void ** gtHolder = ( void ** ) hb_parptrGC( hb_gt_Destructor, iParam ); + + if( gtHolder && *gtHolder ) + return *gtHolder; + + hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); + return NULL; +} + HB_FUNC( HB_GTRELOAD ) { - hb_retl( hb_gtReload( hb_parc( 1 ), + hb_retl( hb_gtReload( hb_parc( 1 ), ISNUM( 2 ) ? hb_numToHandle( hb_parnint( 1 ) ) : HB_STDIN_HANDLE, ISNUM( 3 ) ? hb_numToHandle( hb_parnint( 2 ) ) : HB_STDOUT_HANDLE, ISNUM( 4 ) ? hb_numToHandle( hb_parnint( 3 ) ) : HB_STDERR_HANDLE ) ); } + +HB_FUNC( HB_GTCREATE ) +{ + void * hGT; + + hGT = hb_gtCreate( hb_parc( 1 ), + ISNUM( 2 ) ? hb_numToHandle( hb_parnint( 1 ) ) : HB_STDIN_HANDLE, + ISNUM( 3 ) ? hb_numToHandle( hb_parnint( 2 ) ) : HB_STDOUT_HANDLE, + ISNUM( 4 ) ? hb_numToHandle( hb_parnint( 3 ) ) : HB_STDERR_HANDLE ); + + if( hGT ) + { + void ** gtHolder = ( void ** ) hb_gcAlloc( sizeof( void * ), hb_gt_Destructor ); + *gtHolder = hGT; + hb_retptrGC( gtHolder ); + } +} + +HB_FUNC( HB_GTSELECT ) +{ + void * hGT; + + if( hb_pcount() > 0 ) + { + hGT = hb_gtParam( 1 ); + if( hGT ) + { + hGT = hb_gtAlloc( hGT ); + if( hGT ) + hGT = hb_gtSwap( hGT ); + } + } + else + hGT = hb_gtAlloc( NULL ); + + if( hGT ) + { + void ** gtHolder = ( void ** ) hb_gcAlloc( sizeof( void * ), hb_gt_Destructor ); + *gtHolder = hGT; + hb_retptrGC( gtHolder ); + } +} diff --git a/harbour/source/vm/thread.c b/harbour/source/vm/thread.c index 6ea5bbaecb..387b5f7873 100644 --- a/harbour/source/vm/thread.c +++ b/harbour/source/vm/thread.c @@ -577,7 +577,7 @@ PHB_THREADSTATE hb_threadStateNew( void ) pThread->pszCDP = HB_MACRO2STRING( HB_CODEPAGE_DEFAULT ); pThread->pszLang = HB_MACRO2STRING( HB_LANG_DEFAULT ); pThread->pThItm = pThItm; - pThread->hGT = hb_gtAlloc(); + pThread->hGT = hb_gtAlloc( NULL ); return pThread; } diff --git a/harbour/tests/gtwin.prg b/harbour/tests/gtwin.prg new file mode 100644 index 0000000000..be3a4ce858 --- /dev/null +++ b/harbour/tests/gtwin.prg @@ -0,0 +1,65 @@ +/* + * $Id$ + */ + +/* + * Harbour Project source code: + * demonstration/test code for using more then one console window. + * It needs GT driver which supports such functionality, i.e. + * GTWVT in MS-Windows or GTXWC in XWindow. + * + * Copyright 2008 Przemyslaw Czerpak + * www - http://www.harbour-project.org + * + */ + +#include "box.ch" + +#ifdef __PLATFORM__WINDOWS + REQUEST HB_GT_WVT_DEFAULT + #define THREAD_GT "WVT" +#else + REQUEST HB_GT_STD_DEFAULT + #define THREAD_GT "XWC" +#endif + +proc main() + local pGT, pGT1, pGT2 + + ? "This is small test for using more then one console window." + ? "It needs GT which supports such functionality i.e. GTWVT in" + ? "MS-Windows or GTXWC in XWindow" + wait + + ? "Create two new GTs:" + pGT1 := hb_gtCreate( THREAD_GT ) + ? "1 =>", pGT1 + pGT2 := hb_gtCreate( THREAD_GT ) + ? "2 =>", pGT1 + + pGT := hb_gtSelect( pGT1 ) + SetColor( "W+/R" ) + dispBox( 10, 10, 20, 50, B_DOUBLE + " " ) + ?? "This test is shown in 1-st GT window" + + hb_gtSelect( pGT2 ) + SetColor( "W+/B" ) + dispBox( 15, 30, 20, 70, B_DOUBLE + " " ) + ?? "This test is shown in 2-nd GT window" + + hb_gtSelect( pGT ) + ? "New console window should be visible now" + wait + + ? "Destroy 1-st window..." + pGT1 := NIL + ?? "done" + wait + + ? "Destroy 2-nd window..." + pGT2 := NIL + ?? "done" + + wait "Press any key to exit" + +return