home *** CD-ROM | disk | FTP | other *** search
- //---------------------------------------------------------------------------
- // Borland C++Builder
- // Copyright (c) 1987, 1998 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"
-
- #pragma resource "*.res" //Contains the string resource used in this module
- #pragma warn -sig
- //---------------------------------------------------------------------------
- // 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)
- {
- unsigned short 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(TDatabase *Database)
- {
- bool Result;
- unsigned short 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(TDatabase *value)
- {
- if( value != FDatabase )
- {
- if( value != NULL && value->Connected )
- ValidateDatabase( value );
- FDatabase = value;
- }
- }
-
-
-
-
- void __fastcall TIBComponent::ValidateDatabase(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();
- }
- //except
- catch(...)
- {
- Application->HandleException( NULL );
- }
- return 0;
- }
-
-
-
- #pragma warn -rvl
- __cdecl IBEventCallback(Pointer ptr, short length, PChar updated)
- {
- DWORD ThreadID=0;
- // Handle events asynchronously in second thread
- EnterCriticalSection(&((TIBEventAlerter*)ptr)->CS);
- ((TIBEventAlerter*)ptr)->UpdateResultBuffer(length, updated);
- CloseHandle( CreateThread( (LPSECURITY_ATTRIBUTES)NULL, (DWORD)8192,
- (LPTHREAD_START_ROUTINE)HandleEvent,
- ptr, 0, &ThreadID) );
- LeaveCriticalSection(&((TIBEventAlerter*)ptr)->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 )
- 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;
- }
-
-
- #pragma argsused
- 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();
- ProcessingEvents = false;
- LeaveCriticalSection(&CS);
- } // 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());
-
-
- /*
-
- Although it would be easy to call IscEventBlock() only once from assembly
- with the variable number of parameters, we opted to do this entire function
- in C, so that it would not require assembler (TASM32).
-
- */
-
- switch (Events->Count)
- {
- case 1:
- EventBufferLen = IscEventBlock(&EventBuffer,
- &ResultBuffer,
- Events->Count,
- Buffer[0]);
- break;
-
- case 2:
- EventBufferLen = IscEventBlock(&EventBuffer,
- &ResultBuffer,
- Events->Count,
- Buffer[1],
- Buffer[0]);
- break;
-
- case 3:
- EventBufferLen = IscEventBlock(&EventBuffer,
- &ResultBuffer,
- Events->Count,
- Buffer[2],
- Buffer[1],
- Buffer[0]);
- break;
-
- case 4:
- EventBufferLen = IscEventBlock(&EventBuffer,
- &ResultBuffer,
- Events->Count,
- Buffer[3],
- Buffer[2],
- Buffer[1],
- Buffer[0]);
- break;
-
- case 5:
- EventBufferLen = IscEventBlock(&EventBuffer,
- &ResultBuffer,
- Events->Count,
- Buffer[4],
- Buffer[3],
- Buffer[2],
- Buffer[1],
- Buffer[0]);
- break;
-
- case 6:
- EventBufferLen = IscEventBlock(&EventBuffer,
- &ResultBuffer,
- Events->Count,
- Buffer[5],
- Buffer[4],
- Buffer[3],
- Buffer[2],
- Buffer[1],
- Buffer[0]);
- break;
-
- case 7:
- EventBufferLen = IscEventBlock(&EventBuffer,
- &ResultBuffer,
- Events->Count,
- Buffer[6],
- Buffer[5],
- Buffer[4],
- Buffer[3],
- Buffer[2],
- Buffer[1],
- Buffer[0]);
- break;
-
- case 8:
- EventBufferLen = IscEventBlock(&EventBuffer,
- &ResultBuffer,
- Events->Count,
- Buffer[7],
- Buffer[6],
- Buffer[5],
- Buffer[4],
- Buffer[3],
- Buffer[2],
- Buffer[1],
- Buffer[0]);
- break;
-
- case 9:
- EventBufferLen = IscEventBlock(&EventBuffer,
- &ResultBuffer,
- Events->Count,
- Buffer[8],
- Buffer[7],
- Buffer[6],
- Buffer[5],
- Buffer[4],
- Buffer[3],
- Buffer[2],
- Buffer[1],
- Buffer[0]);
- break;
-
- case 10:
- EventBufferLen = IscEventBlock(&EventBuffer,
- &ResultBuffer,
- Events->Count,
- Buffer[9],
- Buffer[8],
- Buffer[7],
- Buffer[6],
- Buffer[5],
- Buffer[4],
- Buffer[3],
- Buffer[2],
- Buffer[1],
- Buffer[0]);
- break;
-
- case 11:
- EventBufferLen = IscEventBlock(&EventBuffer,
- &ResultBuffer,
- Events->Count,
- Buffer[10],
- Buffer[9],
- Buffer[8],
- Buffer[7],
- Buffer[6],
- Buffer[5],
- Buffer[4],
- Buffer[3],
- Buffer[2],
- Buffer[1],
- Buffer[0]);
- break;
-
- case 12:
- EventBufferLen = IscEventBlock(&EventBuffer,
- &ResultBuffer,
- Events->Count,
- Buffer[11],
- Buffer[10],
- Buffer[9],
- Buffer[8],
- Buffer[7],
- Buffer[6],
- Buffer[5],
- Buffer[4],
- Buffer[3],
- Buffer[2],
- Buffer[1],
- Buffer[0]);
- break;
-
- case 13:
- EventBufferLen = IscEventBlock(&EventBuffer,
- &ResultBuffer,
- Events->Count,
- Buffer[12],
- Buffer[11],
- Buffer[10],
- Buffer[9],
- Buffer[8],
- Buffer[7],
- Buffer[6],
- Buffer[5],
- Buffer[4],
- Buffer[3],
- Buffer[2],
- Buffer[1],
- Buffer[0]);
- break;
-
- case 14:
- EventBufferLen = IscEventBlock(&EventBuffer,
- &ResultBuffer,
- Events->Count,
- Buffer[13],
- Buffer[12],
- Buffer[11],
- Buffer[10],
- Buffer[9],
- Buffer[8],
- Buffer[7],
- Buffer[6],
- Buffer[5],
- Buffer[4],
- Buffer[3],
- Buffer[2],
- Buffer[1],
- Buffer[0]);
- break;
-
- case 15:
- EventBufferLen = IscEventBlock(&EventBuffer,
- &ResultBuffer,
- Events->Count,
- Buffer[14],
- Buffer[13],
- Buffer[12],
- Buffer[11],
- Buffer[10],
- Buffer[9],
- Buffer[8],
- Buffer[7],
- Buffer[6],
- Buffer[5],
- Buffer[4],
- Buffer[3],
- Buffer[2],
- Buffer[1],
- Buffer[0]);
- break;
-
- }
-
-
- FRegistered = true;
- QueueEvents();
- }
- }
- #pragma warn .sig
-
-
-
-
- void __fastcall TIBEventAlerter::SetEvents(Classes::TStrings *value)
- {
- FEvents->Assign(value);
- }
-
-
- void __fastcall TIBEventAlerter::SetDatabase(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];
- }
-
-
-
-