home *** CD-ROM | disk | FTP | other *** search
- //---------------------------------------------------------------------------
- // Borland C++Builder
- // Copyright (c) 1987, 1996 Borland International Inc. All Rights Reserved.
- //---------------------------------------------------------------------------
- // ibctrls.cpp
- // This file is #included in IBREG.CPP which #includes IBREG.H which
- // in turn #includes IBCTRLS.H. Hence #including IBCTRLS.H here is redundant with
- // no ramifications (there are sentries in the header file) but has been done
- // just to clarify that the function and class implementations in this file are
- // prototyped in IBCTRLS.H
- #include "ibctrls.h"
-
- //---------------------------------------------------------------------------
- // Dynamically Loaded InterBase API functions (gds32.dll)
- TIscQueEvents IscQueEvents;
- TIscFree IscFree;
- TIscEventBlock IscEventBlock;
- TIscEventCounts IscEventCounts;
- TIscCancelEvents IscCancelEvents;
- TIscInterprete IscInterprete;
-
- // TIBComponent class implementation
-
- Pointer __fastcall TIBComponent::GetNativeHandle(void)
- {
- int length = 0;
- isc_db_handle result = NULL;
- if( FDatabase != NULL && FDatabase->Connected )
- Check( DbiGetProp( (hDBIObj)FDatabase->Handle, dbNATIVEHNDL,
- &result, sizeof( isc_db_handle), length ) );
- else
- result = NULL;
- return result;
- }
-
-
- void __fastcall TIBComponent::HandleIBErrors(Ibproc32::pstatus_vector status)
- {
-
- char buffer[255];
- AnsiString errMsg = "";
- AnsiString lastMsg;
- isc_status errCode;
-
- do
- {
- errCode = IscInterprete( buffer, &status);
- if( lastMsg != AnsiString( buffer) )
- {
- lastMsg = AnsiString( buffer);
- if( errMsg.Length() != 0 )
- errMsg = errMsg+"\n";
- errMsg = errMsg+lastMsg;
- }
- } while( errCode != 0 );
- throw EIBError( errMsg );
- }
-
-
-
-
- bool __fastcall TIBComponent::IsInterbaseDatabase(Db::TDatabase *Database)
- {
- bool Result;
- int Length=0;
- char Buffer[63];
-
- Result = false;
- if( Database->Handle != NULL )
- {
- Check(DbiGetProp(hDBIObj(Database->Handle), dbDATABASETYPE, Buffer,
- sizeof(Buffer), Length));
- Result = ( stricmp(Buffer, "INTRBASE" ) == 0 );
- }
- return Result;
- }
-
-
-
-
-
- void __fastcall TIBComponent::SetDatabase(Db::TDatabase *value)
- {
- if( value != FDatabase )
- {
- if( value != NULL && value->Connected )
- ValidateDatabase( value );
- FDatabase = value;
- }
- }
-
-
-
-
- void __fastcall TIBComponent::ValidateDatabase(Db::TDatabase *Database)
- {
- if( Database == NULL || !Database->Connected )
- throw EIBError( SInvalidDBConnection );
- else
- {
- if( !IsInterbaseDatabase( Database) )
- throw EIBError( SInvalidDatabase, new TVarRec( Database->Name ), 1 );
- }
- }
-
-
-
- __stdcall HandleEvent( int param )
- {
- // don't let exceptions propogate out of thread
- try
- {
- //!! TIBEventAlerter( param )->HandleEvent;
- //!! TIBEventAlerter(this).HandleEvent();
- TIBEventAlerter(NULL).HandleEvent();
- }
- //except
- catch(...)
- {
- // Application.HandleException( nil);
- Application->HandleException( NULL );
- }
- return 0;
- }
-
-
-
- #pragma warn -rvl
- __cdecl IBEventCallback( Pointer ptr, short length, PChar updated )
- {
- int ThreadID=0;
- // Handle events asynchronously in second thread
- EnterCriticalSection(&TIBEventAlerter(NULL).CS );
- TIBEventAlerter( NULL).UpdateResultBuffer( length, updated);
- CloseHandle( CreateThread( (LPSECURITY_ATTRIBUTES)NULL, (DWORD)8192, (LPTHREAD_START_ROUTINE)HandleEvent,
- (LPVOID)ptr, (DWORD)0, (LPDWORD)ThreadID) );
- LeaveCriticalSection( &(TIBEventAlerter( NULL ).CS));
- }
- #pragma warn .rvl
-
-
-
-
-
- __fastcall TIBEventAlerter::TIBEventAlerter( TComponent* AOwner ):TIBComponent( AOwner )
- {
- InitializeCriticalSection(&CS);
- FEvents = new TStringList; //.Create;
- ((TStringList*)FEvents)->OnChange = EventChange;
- ((TStringList*)FEvents)->Duplicates = dupIgnore;
-
- // Attempt to load GDS32.DLL. If this fails then raise an exception.
- // This will cause the component not to be created
- LibHandle = (int) LoadLibrary("gds32.dll");
- if( LibHandle < 32 ) //then
- throw( EDLLLoadError("Unable to load gds32.dll") );
- IscQueEvents = (TIscQueEvents)GetProcAddress((HINSTANCE)LibHandle, "isc_que_events");
- if( IscQueEvents == NULL ) // then // !!must initialize to NULL?
- throw( EDLLLoadError("Failed to lookup isc_que_events") );
- IscInterprete = (TIscInterprete)GetProcAddress((HINSTANCE)LibHandle, "isc_interprete");
- if( IscInterprete == NULL ) // nil then
- throw EDLLLoadError("Failed to lookup isc_interprete");
-
- IscFree = (TIscFree)GetProcAddress((HINSTANCE)LibHandle, "isc_free");
- if( IscFree == NULL ) //nil then
- throw EDLLLoadError("Failed to lookup isc_free");
-
- IscEventBlock = (TIscEventBlock) GetProcAddress((HINSTANCE)LibHandle, "isc_event_block");
- if( IscEventBlock == NULL ) // nil then
- throw EDLLLoadError("Failed to lookup isc_event_block");
-
- IscEventCounts = (TIscEventCounts )GetProcAddress((HINSTANCE)LibHandle, "isc_event_counts");
- if( IscEventCounts == NULL ) // nil then
- throw EDLLLoadError("Failed to lookup isc_event_counts");
-
- IscCancelEvents = (TIscCancelEvents) GetProcAddress((HINSTANCE)LibHandle, "isc_cancel_events");
- if( IscCancelEvents == NULL ) // nil then
- throw EDLLLoadError("Failed to lookup isc_cancel_events");
- }
-
-
- __fastcall TIBEventAlerter::~TIBEventAlerter(void)
- {
- UnRegisterEvents();
- SetDatabase(NULL);
- ((TStringList*)FEvents)->OnChange = NULL;
- delete FEvents;
- DeleteCriticalSection( &CS);
- if( LibHandle >= 32 ) //then
- FreeLibrary((HINSTANCE)LibHandle);
- }
-
-
- void __fastcall TIBEventAlerter::CancelEvents(void)
- {
- status_vector status;
- isc_status errCode;
- isc_db_handle dbHandle;
-
- if( ProcessingEvents )
- throw EIBError(SInvalidCancellation);
- if( FQueued )
- {
- try
- {
- // wait for event handler to finish before cancelling events
- EnterCriticalSection(&CS);
- ValidateDatabase( Database);
- FQueued = false;
- Changing = true;
- dbHandle = GetNativeHandle();
- errCode = IscCancelEvents( &status, &dbHandle, &EventID);
- if( errCode != 0 )
- HandleIBErrors( &status );
- LeaveCriticalSection(&CS);
- }
- catch( ... ){
- LeaveCriticalSection(&CS);
- throw;
- } // !!end finally
- } // end Fqued
- }
-
-
-
-
-
- void __fastcall TIBEventAlerter::DoQueueEvents(void)
- {
- status_vector status;
- isc_status errCode;
- Pointer callback;
- isc_db_handle dbHandle;
-
- ValidateDatabase( Database);
- callback = IBEventCallback;
- dbHandle = GetNativeHandle();
- errCode = IscQueEvents( &status, &dbHandle, &EventID, EventBufferLen,
- EventBuffer, isc_callback(callback), this);
- if( errCode != 0 )
- HandleIBErrors( &status);
- FQueued = true;
- }
-
-
-
- void __fastcall TIBEventAlerter::EventChange(System::TObject *sender)
- {
- // check for blank event
- if( ((TStringList*)Events)->IndexOf("") != -1 )
- throw EIBError( SInvalidEvent);
- // check for too many events
- if( Events->Count > MaxEvents ) //then
- {
- ((TStringList*)Events)->OnChange = NULL;
- Events->Delete( MaxEvents);
- ((TStringList*)Events)->OnChange = EventChange;
- throw EIBError(SMaximumEvents);
- }
- if( Registered )
- RegisterEvents();
- }
-
-
-
- void __fastcall TIBEventAlerter::HandleEvent(void)
- {
- bool CancelAlerts;
- int i;
- status_vector status;
- try
- {
- // prevent modification of vital data structures while handling events
- EnterCriticalSection(&CS);
- ProcessingEvents = true;
- IscEventCounts( &status, EventBufferLen, EventBuffer, ResultBuffer);
- CancelAlerts = false;
- if( FOnEventAlert != NULL && !Changing )
- {
- for( i = 0; i < Events->Count; i++ ) // do
- {
- try
- {
- if(status[i] != 0 && !CancelAlerts ) //then
- FOnEventAlert( this,
- Events->Strings[Events->Count-i-1],
- status[i],
- CancelAlerts);
- }
- catch(...) //except
- {
- Application->HandleException( NULL);
- }
- }
- }
- Changing = false;
- if( !CancelAlerts && FQueued ) //then
- DoQueueEvents();
- } // end try
- catch(...)
- {
- ProcessingEvents = false;
- LeaveCriticalSection(&CS);
- throw;
- } // end finally?
- }
-
-
-
- void __fastcall TIBEventAlerter::Loaded(void)
- {
- TIBComponent::Loaded();
- try
- {
- if( RegisteredState ) //then
- RegisterEvents();
- }
- catch(...)// except
- {
- if( ComponentState.Contains( csDesigning ) )
- Application->HandleException( this );
- else
- throw;
- }
- }
-
-
- void __fastcall TIBEventAlerter::Notification(Classes::TComponent *AComponent, Classes::TOperation Operation )
- {
- TIBComponent::Notification( AComponent, Operation);
- if( Operation == opRemove && AComponent == Database)// then
- {
- UnRegisterEvents();
- Database = NULL;
- }
- }
-
-
-
- void __fastcall TIBEventAlerter::QueueEvents(void)
- {
- if( !FRegistered ) //then
- throw EIBError( SNoEventsRegistered);
- if( ProcessingEvents ) //then
- throw EIBError( SInvalidQueueing);
- if( !FQueued ) //then
- {
- try
- // wait until current event handler is finished before queuing events
- {
- EnterCriticalSection( &CS);
- DoQueueEvents();
- Changing = true;
- LeaveCriticalSection( &CS);
- }
- catch(...)
- {
- LeaveCriticalSection( &CS);
- throw;
- }
- }
- }
-
-
-
- void __fastcall TIBEventAlerter::RegisterEvents(void)
- {
- ValidateDatabase( Database);
- if( ComponentState.Contains( csDesigning ) )
- FRegistered = true;
- else
- {
- UnRegisterEvents();
- if( Events->Count == 0 )
- return;
- for(int i = 0; i < Events->Count; i++ )
- strcpy( Buffer[i], Events->Strings[i].c_str());
-
- EventBufferLen = IscEventBlock(EventBuffer,
- ResultBuffer,
- Events->Count,
- Buffer[0]);
- /*
- asm
- {
- mov ecx, dword ptr [i]
- mov eax, dword ptr [bufptr]
- @@1:
- push eax
- add eax, EventLength
- loop @@1
- push dword ptr [i]
- push dword ptr [resultBufPtr]
- push dword ptr [eventBufPtr]
- call [IscEventBlock]
- mov dword ptr [buflen], eax
- mov eax, dword ptr [i]
- shl eax, 2
- add eax, 12
- add esp, eax
- }*/ // end asm block
- FRegistered = true;
- QueueEvents();
- }
- }
-
-
-
-
-
- void __fastcall TIBEventAlerter::SetEvents(Classes::TStrings *value)
- {
- FEvents->Assign( value);
- }
-
-
- void __fastcall TIBEventAlerter::SetDatabase(Db::TDatabase *value)
- {
- if( value != Database )
- {
- UnRegisterEvents();
- if( value != NULL && value->Connected ) //!!assigned?
- ValidateDatabase( value);
- Database = value;
- }
- }
-
-
-
- void __fastcall TIBEventAlerter::SetRegistered( bool value )
- {
- if( ComponentState.Contains ( csReading ) )
- RegisteredState = value;
- else
- if( FRegistered != value )
- if( value )
- RegisterEvents();
- else
- UnRegisterEvents();
- }
-
-
-
- void __fastcall TIBEventAlerter::UnRegisterEvents(void)
- {
- if( ProcessingEvents )
- throw EIBError( SInvalidRegistration);
- if( ComponentState.Contains( csDesigning ) )
- FRegistered = false;
- else
- if( ComponentState.Contains( csLoading ) != true )
- {
- CancelEvents();
- if( FRegistered )
- {
- IscFree( EventBuffer);
- EventBuffer = NULL;
- IscFree( ResultBuffer);
- ResultBuffer = NULL;
- }
- FRegistered = false;
- }
- }
-
-
-
-
- void __fastcall TIBEventAlerter::UpdateResultBuffer(int length, System::PChar updated)
- {
- int i;
- for( i = 0; i< length; i++ )
- ResultBuffer[i] = updated[i];
- }
-
-
-
-