home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2002 May
/
Chip_2002-05_cd1.bin
/
chplus
/
cpp
/
5
/
Komponety.exe
/
ibctrls.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1998-02-09
|
21KB
|
675 lines
//---------------------------------------------------------------------------
// 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];
}