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

  1. //---------------------------------------------------------------------------
  2. // Borland C++Builder
  3. // Copyright (c) 1987, 1998 Borland International Inc.  All Rights Reserved.
  4. //---------------------------------------------------------------------------
  5. // ibctrls.cpp
  6. // This file is #included in IBREG.CPP which #includes IBREG.H which
  7. // in turn #includes IBCTRLS.H.  Hence #including IBCTRLS.H here is redundant with
  8. // no ramifications (there are sentries in the header file) but has been done
  9. // just to clarify that the function and class implementations in this file are
  10. // prototyped in IBCTRLS.H
  11.  
  12. #include  "ibctrls.h"
  13.  
  14. #pragma resource "*.res"  //Contains the string resource used in this module
  15. #pragma warn -sig
  16. //---------------------------------------------------------------------------
  17. // Dynamically Loaded InterBase API functions (gds32.dll)
  18. TIscQueEvents IscQueEvents;
  19. TIscFree IscFree;
  20. TIscEventBlock IscEventBlock;
  21. TIscEventCounts IscEventCounts;
  22. TIscCancelEvents IscCancelEvents;
  23. TIscInterprete IscInterprete;
  24.  
  25. // TIBComponent class implementation
  26.  
  27. Pointer __fastcall TIBComponent::GetNativeHandle(void)
  28. {
  29.   unsigned short length = 0;
  30.   isc_db_handle result = NULL;
  31.   if( FDatabase != NULL  && FDatabase->Connected )
  32.       Check( DbiGetProp( (hDBIObj)FDatabase->Handle, dbNATIVEHNDL,
  33.                         &result, sizeof( isc_db_handle), length ) );
  34.   else
  35.     result = NULL;
  36.  return result;
  37.  }
  38.  
  39.  
  40. void __fastcall TIBComponent::HandleIBErrors(Ibproc32::pstatus_vector status)
  41. {
  42.  
  43.   char buffer[255];
  44.   AnsiString errMsg = " ";
  45.   AnsiString lastMsg;
  46.   isc_status errCode;
  47.  
  48.   do
  49.   {
  50.     errCode = IscInterprete( buffer, &status);
  51.     if( lastMsg != AnsiString( buffer) )
  52.     {
  53.       lastMsg = AnsiString( buffer);
  54.       if( errMsg.Length() !=  0 )
  55.         errMsg = errMsg+"\n";
  56.       errMsg = errMsg+lastMsg;
  57.     }
  58.   } while( errCode != 0 );
  59.   throw EIBError( errMsg );
  60. }
  61.  
  62.  
  63.  
  64.  
  65. bool __fastcall TIBComponent::IsInterbaseDatabase(TDatabase *Database)
  66. {
  67.   bool Result;
  68.   unsigned short Length=0;
  69.   char Buffer[63];
  70.  
  71.   Result = false;
  72.   if( Database->Handle != NULL )
  73.   {
  74.     Check(DbiGetProp(hDBIObj(Database->Handle), dbDATABASETYPE, Buffer,
  75.       sizeof(Buffer), Length));
  76.     Result = ( stricmp(Buffer, "INTRBASE" ) == 0 );
  77.   }
  78.   return Result;
  79. }
  80.  
  81.  
  82.  
  83.  
  84.  
  85. void __fastcall TIBComponent::SetDatabase(TDatabase *value)
  86. {
  87.   if( value != FDatabase )
  88.   {
  89.     if( value != NULL && value->Connected )
  90.         ValidateDatabase( value );
  91.     FDatabase = value;
  92.   }
  93. }
  94.  
  95.  
  96.  
  97.  
  98. void __fastcall TIBComponent::ValidateDatabase(TDatabase *Database)
  99. {
  100.   if( Database == NULL  || !Database->Connected  )
  101.           throw EIBError( SInvalidDBConnection );
  102.   else
  103.   {
  104.    if( !IsInterbaseDatabase( Database)  )
  105.     throw EIBError( SInvalidDatabase, new TVarRec( Database->Name ), 1 );
  106.   }
  107. }
  108.  
  109.  
  110.  
  111. __stdcall HandleEvent( int param )
  112. {
  113.   // don't let exceptions propogate out of thread
  114.   try
  115.   {
  116.     ((TIBEventAlerter*)param)->HandleEvent();
  117.   }
  118.   //except
  119.   catch(...)
  120.   {
  121.     Application->HandleException( NULL );
  122.   }
  123.   return 0;
  124. }
  125.  
  126.  
  127.  
  128. #pragma warn -rvl
  129. __cdecl IBEventCallback(Pointer ptr, short length, PChar updated)
  130. {
  131.   DWORD ThreadID=0;
  132.   // Handle events asynchronously in second thread
  133.   EnterCriticalSection(&((TIBEventAlerter*)ptr)->CS);
  134.   ((TIBEventAlerter*)ptr)->UpdateResultBuffer(length, updated);
  135.   CloseHandle( CreateThread( (LPSECURITY_ATTRIBUTES)NULL, (DWORD)8192,
  136.                              (LPTHREAD_START_ROUTINE)HandleEvent,
  137.                              ptr, 0, &ThreadID) );
  138.   LeaveCriticalSection(&((TIBEventAlerter*)ptr)->CS);
  139.  }
  140. #pragma warn .rvl
  141.  
  142.  
  143.  
  144.  
  145.  
  146. __fastcall TIBEventAlerter::TIBEventAlerter( TComponent* AOwner ):TIBComponent( AOwner )
  147. {
  148.   InitializeCriticalSection(&CS);
  149.   FEvents = new TStringList; //.Create;
  150.   ((TStringList*)FEvents)->OnChange = EventChange;
  151.   ((TStringList*)FEvents)->Duplicates = dupIgnore;
  152.  
  153.   // Attempt to load GDS32.DLL.  If this fails then raise an exception.
  154.   // This will cause the component not to be created
  155.   LibHandle = (int) LoadLibrary("gds32.dll");
  156.   if( LibHandle < 32 ) //then
  157.       throw( EDLLLoadError("Unable to load gds32.dll") );
  158.   IscQueEvents = (TIscQueEvents)GetProcAddress((HINSTANCE)LibHandle, "isc_que_events");
  159.   if( IscQueEvents == NULL ) // then            // !!must initialize to NULL?
  160.       throw( EDLLLoadError("Failed to lookup isc_que_events") );
  161.   IscInterprete = (TIscInterprete)GetProcAddress((HINSTANCE)LibHandle, "isc_interprete");
  162.   if( IscInterprete == NULL ) // nil then
  163.       throw EDLLLoadError("Failed to lookup isc_interprete");
  164.  
  165.   IscFree = (TIscFree)GetProcAddress((HINSTANCE)LibHandle, "isc_free");
  166.   if( IscFree ==  NULL ) //nil then
  167.     throw EDLLLoadError("Failed to lookup isc_free");
  168.  
  169.   IscEventBlock = (TIscEventBlock) GetProcAddress((HINSTANCE)LibHandle, "isc_event_block");
  170.   if( IscEventBlock == NULL ) // nil then
  171.      throw EDLLLoadError("Failed to lookup isc_event_block");
  172.  
  173.   IscEventCounts = (TIscEventCounts )GetProcAddress((HINSTANCE)LibHandle, "isc_event_counts");
  174.   if( IscEventCounts == NULL ) // nil then
  175.      throw EDLLLoadError("Failed to lookup isc_event_counts");
  176.  
  177.   IscCancelEvents = (TIscCancelEvents) GetProcAddress((HINSTANCE)LibHandle, "isc_cancel_events");
  178.   if( IscCancelEvents == NULL ) // nil then
  179.       throw EDLLLoadError("Failed to lookup isc_cancel_events");
  180.   }
  181.  
  182.  
  183. __fastcall TIBEventAlerter::~TIBEventAlerter(void)
  184. {
  185.   UnRegisterEvents();
  186.   SetDatabase(NULL);
  187.   ((TStringList*)FEvents)->OnChange = NULL;
  188.   delete FEvents;
  189.   DeleteCriticalSection( &CS);
  190.   if( LibHandle >= 32 )
  191.     FreeLibrary((HINSTANCE)LibHandle);
  192. }
  193.  
  194.  
  195. void __fastcall TIBEventAlerter::CancelEvents(void)
  196. {
  197.   status_vector status;
  198.   isc_status errCode;
  199.   isc_db_handle dbHandle;
  200.  
  201.   if( ProcessingEvents )
  202.       throw EIBError(SInvalidCancellation);
  203.   if( FQueued )
  204.   {
  205.     try
  206.     {
  207.       // wait for event handler to finish before cancelling events
  208.       EnterCriticalSection(&CS);
  209.       ValidateDatabase( Database);
  210.       FQueued = false;
  211.       Changing = true;
  212.       dbHandle = GetNativeHandle();
  213.       errCode = IscCancelEvents( &status, &dbHandle, &EventID);
  214.       if( errCode != 0 )
  215.          HandleIBErrors( &status );
  216.       LeaveCriticalSection(&CS);
  217.     }
  218.     catch( ... ){
  219.       LeaveCriticalSection(&CS);
  220.       throw;
  221.     } //   !!end finally
  222.   } // end Fqued
  223. }
  224.  
  225. void __fastcall TIBEventAlerter::DoQueueEvents(void)
  226. {
  227.   status_vector status;
  228.   isc_status errCode;
  229.   Pointer callback;
  230.   isc_db_handle dbHandle;
  231.  
  232.   ValidateDatabase( Database);
  233.   callback = IBEventCallback;
  234.   dbHandle = GetNativeHandle();
  235.   errCode = IscQueEvents( &status, &dbHandle, &EventID, EventBufferLen,
  236.                           EventBuffer, isc_callback(callback), this);
  237.   if( errCode != 0 )
  238.     HandleIBErrors( &status);
  239.   FQueued = true;
  240.  }
  241.  
  242.  
  243. #pragma argsused
  244. void __fastcall TIBEventAlerter::EventChange(System::TObject *sender)
  245. {
  246.  // check for blank event
  247.  if( ((TStringList*)Events)->IndexOf(" ") !=  -1 )
  248.      throw EIBError( SInvalidEvent);
  249.   // check for too many events
  250.  if( Events->Count > MaxEvents ) //then
  251.  {
  252.     ((TStringList*)Events)->OnChange = NULL;
  253.     Events->Delete( MaxEvents);
  254.     ((TStringList*)Events)->OnChange = EventChange;
  255.     throw EIBError(SMaximumEvents);
  256.  }
  257.  if( Registered )
  258.      RegisterEvents();
  259. }
  260.  
  261.  
  262.  
  263. void __fastcall TIBEventAlerter::HandleEvent(void)
  264. {
  265.   bool CancelAlerts;
  266.   int i;
  267.   status_vector status;
  268.   try
  269.   {
  270.     // prevent modification of vital data structures while handling events
  271.     EnterCriticalSection(&CS);
  272.     ProcessingEvents = true;
  273.     IscEventCounts( &status, EventBufferLen, EventBuffer, ResultBuffer);
  274.     CancelAlerts = false;
  275.     if( FOnEventAlert != NULL && !Changing )
  276.     {
  277.        for( i = 0; i < Events->Count; i++ ) // do
  278.        {
  279.          try
  280.          {
  281.            if(status[i] != 0 && !CancelAlerts ) //then
  282.              FOnEventAlert( this,
  283.                             Events->Strings[Events->Count-i-1],
  284.                             status[i],
  285.                             CancelAlerts);
  286.          }
  287.          catch(...) //except
  288.          {
  289.            Application->HandleException( NULL);
  290.          }
  291.        }
  292.     }
  293.     Changing = false;
  294.     if( !CancelAlerts && FQueued ) //then
  295.         DoQueueEvents();
  296.     ProcessingEvents = false;
  297.     LeaveCriticalSection(&CS);
  298.   } //  end try
  299.   catch(...)
  300.   {
  301.     ProcessingEvents = false;
  302.     LeaveCriticalSection(&CS);
  303.     throw;
  304.   }  //  end finally?
  305. }
  306.  
  307.  
  308.  
  309. void __fastcall TIBEventAlerter::Loaded(void)
  310. {
  311.   TIBComponent::Loaded();
  312.   try
  313.   {
  314.    if( RegisteredState ) //then
  315.      RegisterEvents();
  316.    }
  317.   catch(...)//  except
  318.   {
  319.     if( ComponentState.Contains( csDesigning ) )
  320.       Application->HandleException( this );
  321.     else
  322.       throw;
  323.   }
  324. }
  325.  
  326.  
  327. void __fastcall TIBEventAlerter::Notification(Classes::TComponent *AComponent, Classes::TOperation Operation )
  328. {
  329.   TIBComponent::Notification( AComponent, Operation);
  330.   if( Operation == opRemove && AComponent == Database)// then
  331.   {
  332.     UnRegisterEvents();
  333.     Database = NULL;
  334.   }
  335. }
  336.  
  337.  
  338.  
  339. void __fastcall TIBEventAlerter::QueueEvents(void)
  340. {
  341.   if( !FRegistered ) //then
  342.     throw EIBError( SNoEventsRegistered);
  343.   if( ProcessingEvents ) //then
  344.     throw EIBError( SInvalidQueueing);
  345.   if( !FQueued ) //then
  346.   {
  347.     try
  348.       // wait until current event handler is finished before queuing events
  349.     {
  350.       EnterCriticalSection( &CS);
  351.       DoQueueEvents();
  352.       Changing = true;
  353.       LeaveCriticalSection( &CS);
  354.     }
  355.     catch(...)
  356.     {
  357.       LeaveCriticalSection( &CS);
  358.       throw;
  359.     }
  360.   }
  361. }
  362.  
  363.  
  364.  
  365. void __fastcall TIBEventAlerter::RegisterEvents(void)
  366. {
  367.   ValidateDatabase( Database);
  368.   if( ComponentState.Contains( csDesigning )  )
  369.     FRegistered = true;
  370.   else
  371.   {
  372.     UnRegisterEvents();
  373.     if( Events->Count == 0 )
  374.        return;
  375.     for(int i = 0; i < Events->Count; i++ )
  376.       strcpy( Buffer[i], Events->Strings[i].c_str());
  377.  
  378.  
  379. /*
  380.  
  381.  Although it would be easy to call IscEventBlock() only once from assembly
  382.  with the variable number of parameters, we opted to do this entire function
  383.  in C, so that it would not require assembler (TASM32).
  384.  
  385. */
  386.  
  387.     switch (Events->Count)
  388.     {
  389.       case 1:
  390.         EventBufferLen = IscEventBlock(&EventBuffer,
  391.                                        &ResultBuffer,
  392.                                        Events->Count,
  393.                                        Buffer[0]);
  394.         break;
  395.  
  396.       case 2:
  397.         EventBufferLen = IscEventBlock(&EventBuffer,
  398.                                        &ResultBuffer,
  399.                                        Events->Count,
  400.                                        Buffer[1],
  401.                                        Buffer[0]);
  402.         break;
  403.  
  404.       case 3:
  405.         EventBufferLen = IscEventBlock(&EventBuffer,
  406.                                        &ResultBuffer,
  407.                                        Events->Count,
  408.                                        Buffer[2],
  409.                                        Buffer[1],
  410.                                        Buffer[0]);
  411.         break;
  412.  
  413.       case 4:
  414.         EventBufferLen = IscEventBlock(&EventBuffer,
  415.                                        &ResultBuffer,
  416.                                        Events->Count,
  417.                                        Buffer[3],
  418.                                        Buffer[2],
  419.                                        Buffer[1],
  420.                                        Buffer[0]);
  421.         break;
  422.  
  423.       case 5:
  424.         EventBufferLen = IscEventBlock(&EventBuffer,
  425.                                        &ResultBuffer,
  426.                                        Events->Count,
  427.                                        Buffer[4],
  428.                                        Buffer[3],
  429.                                        Buffer[2],
  430.                                        Buffer[1],
  431.                                        Buffer[0]);
  432.         break;
  433.  
  434.       case 6:
  435.         EventBufferLen = IscEventBlock(&EventBuffer,
  436.                                        &ResultBuffer,
  437.                                        Events->Count,
  438.                                        Buffer[5],
  439.                                        Buffer[4],
  440.                                        Buffer[3],
  441.                                        Buffer[2],
  442.                                        Buffer[1],
  443.                                        Buffer[0]);
  444.         break;
  445.  
  446.       case 7:
  447.         EventBufferLen = IscEventBlock(&EventBuffer,
  448.                                        &ResultBuffer,
  449.                                        Events->Count,
  450.                                        Buffer[6],
  451.                                        Buffer[5],
  452.                                        Buffer[4],
  453.                                        Buffer[3],
  454.                                        Buffer[2],
  455.                                        Buffer[1],
  456.                                        Buffer[0]);
  457.         break;
  458.  
  459.       case 8:
  460.         EventBufferLen = IscEventBlock(&EventBuffer,
  461.                                        &ResultBuffer,
  462.                                        Events->Count,
  463.                                        Buffer[7],
  464.                                        Buffer[6],
  465.                                        Buffer[5],
  466.                                        Buffer[4],
  467.                                        Buffer[3],
  468.                                        Buffer[2],
  469.                                        Buffer[1],
  470.                                        Buffer[0]);
  471.         break;
  472.  
  473.       case 9:
  474.         EventBufferLen = IscEventBlock(&EventBuffer,
  475.                                        &ResultBuffer,
  476.                                        Events->Count,
  477.                                        Buffer[8],
  478.                                        Buffer[7],
  479.                                        Buffer[6],
  480.                                        Buffer[5],
  481.                                        Buffer[4],
  482.                                        Buffer[3],
  483.                                        Buffer[2],
  484.                                        Buffer[1],
  485.                                        Buffer[0]);
  486.         break;
  487.  
  488.       case 10:
  489.         EventBufferLen = IscEventBlock(&EventBuffer,
  490.                                        &ResultBuffer,
  491.                                        Events->Count,
  492.                                        Buffer[9],
  493.                                        Buffer[8],
  494.                                        Buffer[7],
  495.                                        Buffer[6],
  496.                                        Buffer[5],
  497.                                        Buffer[4],
  498.                                        Buffer[3],
  499.                                        Buffer[2],
  500.                                        Buffer[1],
  501.                                        Buffer[0]);
  502.         break;
  503.  
  504.       case 11:
  505.         EventBufferLen = IscEventBlock(&EventBuffer,
  506.                                        &ResultBuffer,
  507.                                        Events->Count,
  508.                                        Buffer[10],
  509.                                        Buffer[9],
  510.                                        Buffer[8],
  511.                                        Buffer[7],
  512.                                        Buffer[6],
  513.                                        Buffer[5],
  514.                                        Buffer[4],
  515.                                        Buffer[3],
  516.                                        Buffer[2],
  517.                                        Buffer[1],
  518.                                        Buffer[0]);
  519.         break;
  520.  
  521.       case 12:
  522.         EventBufferLen = IscEventBlock(&EventBuffer,
  523.                                        &ResultBuffer,
  524.                                        Events->Count,
  525.                                        Buffer[11],
  526.                                        Buffer[10],
  527.                                        Buffer[9],
  528.                                        Buffer[8],
  529.                                        Buffer[7],
  530.                                        Buffer[6],
  531.                                        Buffer[5],
  532.                                        Buffer[4],
  533.                                        Buffer[3],
  534.                                        Buffer[2],
  535.                                        Buffer[1],
  536.                                        Buffer[0]);
  537.         break;
  538.  
  539.       case 13:
  540.         EventBufferLen = IscEventBlock(&EventBuffer,
  541.                                        &ResultBuffer,
  542.                                        Events->Count,
  543.                                        Buffer[12],
  544.                                        Buffer[11],
  545.                                        Buffer[10],
  546.                                        Buffer[9],
  547.                                        Buffer[8],
  548.                                        Buffer[7],
  549.                                        Buffer[6],
  550.                                        Buffer[5],
  551.                                        Buffer[4],
  552.                                        Buffer[3],
  553.                                        Buffer[2],
  554.                                        Buffer[1],
  555.                                        Buffer[0]);
  556.         break;
  557.  
  558.       case 14:
  559.         EventBufferLen = IscEventBlock(&EventBuffer,
  560.                                        &ResultBuffer,
  561.                                        Events->Count,
  562.                                        Buffer[13],
  563.                                        Buffer[12],
  564.                                        Buffer[11],
  565.                                        Buffer[10],
  566.                                        Buffer[9],
  567.                                        Buffer[8],
  568.                                        Buffer[7],
  569.                                        Buffer[6],
  570.                                        Buffer[5],
  571.                                        Buffer[4],
  572.                                        Buffer[3],
  573.                                        Buffer[2],
  574.                                        Buffer[1],
  575.                                        Buffer[0]);
  576.         break;
  577.  
  578.       case 15:
  579.         EventBufferLen = IscEventBlock(&EventBuffer,
  580.                                        &ResultBuffer,
  581.                                        Events->Count,
  582.                                        Buffer[14],
  583.                                        Buffer[13],
  584.                                        Buffer[12],
  585.                                        Buffer[11],
  586.                                        Buffer[10],
  587.                                        Buffer[9],
  588.                                        Buffer[8],
  589.                                        Buffer[7],
  590.                                        Buffer[6],
  591.                                        Buffer[5],
  592.                                        Buffer[4],
  593.                                        Buffer[3],
  594.                                        Buffer[2],
  595.                                        Buffer[1],
  596.                                        Buffer[0]);
  597.         break;
  598.  
  599.     }
  600.  
  601.  
  602.     FRegistered = true;
  603.     QueueEvents();
  604.   }
  605. }
  606. #pragma warn .sig
  607.  
  608.  
  609.  
  610.  
  611. void __fastcall TIBEventAlerter::SetEvents(Classes::TStrings *value)
  612. {
  613.   FEvents->Assign(value);
  614. }
  615.  
  616.  
  617. void __fastcall TIBEventAlerter::SetDatabase(TDatabase *value)
  618. {
  619.   if( value != Database )
  620.   {
  621.     UnRegisterEvents();
  622.     if( value != NULL  && value->Connected ) //!!assigned?
  623.        ValidateDatabase( value);
  624.     Database = value;
  625.   }
  626. }
  627.  
  628.  
  629.  
  630. void __fastcall TIBEventAlerter::SetRegistered( bool value )
  631. {
  632.   if( ComponentState.Contains ( csReading  ) )
  633.     RegisteredState = value;
  634.   else
  635.     if( FRegistered != value )
  636.       if( value )
  637.         RegisterEvents();
  638.       else
  639.         UnRegisterEvents();
  640. }
  641.  
  642.  
  643.  
  644. void __fastcall TIBEventAlerter::UnRegisterEvents(void)
  645. {
  646.   if( ProcessingEvents )
  647.      throw EIBError( SInvalidRegistration);
  648.   if( ComponentState.Contains( csDesigning  ) )
  649.     FRegistered = false;
  650.   else
  651.    if( ComponentState.Contains( csLoading  ) != true )
  652.    {
  653.     CancelEvents();
  654.     if( FRegistered )
  655.     {
  656.       IscFree( EventBuffer);
  657.       EventBuffer = NULL;
  658.       IscFree( ResultBuffer);
  659.       ResultBuffer = NULL;
  660.     }
  661.     FRegistered = false;
  662.    }
  663. }
  664.  
  665.  
  666. void __fastcall TIBEventAlerter::UpdateResultBuffer(int length, System::PChar updated)
  667. {
  668.   int i;
  669.   for( i = 0; i < length; i++ )
  670.     ResultBuffer[i] = updated[i];
  671. }
  672.  
  673.  
  674.  
  675.