home *** CD-ROM | disk | FTP | other *** search
/ Windows 95 v2.4 Fix / W95-v2.4fix.iso / ACADWIN / ADS / CPP / DDE / CONXCLNT.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-08  |  18.2 KB  |  642 lines

  1. /* 
  2.     CONXCLNT.CPP -
  3.     
  4.     This file:
  5.  
  6.         Defines DDE_CLIENT_CONNECTION object which is used to
  7.         support DDE client connection to talk to the servers.
  8.         
  9.  
  10.     (C) Copyright 1988-1994 by Autodesk, Inc.
  11.  
  12.     This program is copyrighted by Autodesk, Inc. and is  licensed
  13.     to you under the following conditions.  You may not distribute
  14.     or  publish the source code of this program in any form.   You
  15.     may  incorporate this code in object form in derivative  works
  16.     provided  such  derivative  works  are  (i.) are  designed and
  17.     intended  to  work  solely  with  Autodesk, Inc. products, and
  18.     (ii.)  contain  Autodesk's  copyright  notice  "(C)  Copyright
  19.     1988-1994 by Autodesk, Inc."
  20.  
  21.     AUTODESK  PROVIDES THIS PROGRAM "AS IS" AND WITH  ALL  FAULTS.
  22.     AUTODESK  SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF  MER-
  23.     CHANTABILITY OR FITNESS FOR A PARTICULAR USE.  AUTODESK,  INC.
  24.     DOES  NOT  WARRANT THAT THE OPERATION OF THE PROGRAM  WILL  BE
  25.     UNINTERRUPTED OR ERROR FREE.
  26.  
  27. */
  28. #include "ddeinc.h"
  29.  
  30. //-----------------------------------------------------------------------------
  31. ADS_INSTANCE    client_this;
  32. #ifdef DDEADS_DBG
  33. static char     dbg_string[256];
  34. #endif
  35.  
  36.  
  37. //-----------------------------------------------------------------------------
  38. DDE_CLIENT_CONNECTION::DDE_CLIENT_CONNECTION()
  39. {
  40.     SetUserBrk( FALSE );
  41.     transfer_result = 0;
  42.     ddedata = NULL;
  43. }
  44.  
  45.  
  46. //-----------------------------------------------------------------------------
  47. DDE_CLIENT_CONNECTION::DDE_CLIENT_CONNECTION( SERVER_INFO& _server )
  48. {
  49.     server = new SERVER_INFO( _server );
  50.     ddedata = NULL;
  51. }
  52.  
  53. //-----------------------------------------------------------------------------
  54. DDE_CLIENT_CONNECTION::~DDE_CLIENT_CONNECTION()
  55. {
  56.     if ( server ) 
  57.     { 
  58.         delete server; 
  59.     }
  60.     sending_string = "";
  61.  
  62.     //
  63.     // Before InstId becomes invalid RemoveConnection has to be
  64.     // called first.  Same applys to the DDEData
  65.     //
  66.     RemoveConnection();
  67. }
  68.  
  69. //-----------------------------------------------------------------------------
  70. WORD DDE_CLIENT_CONNECTION::ExcuteCommand( char* cmd )
  71. {
  72.     ASSERT ( cmd != NULL );
  73.     DdeClientTransaction( (LPBYTE)cmd
  74.                         , strlen ( cmd )
  75.                         , *cur_conv
  76.                         , NULL      // ignored
  77.                         , 0
  78.                         , XTYP_EXECUTE
  79.                         , TIMEOUT_ASYNC
  80.                         , &transfer_result);
  81.     transfer_result = DdeGetLastError( DDE_GLOBAL::GetInstId() );
  82.     if ( transfer_result != DMLERR_NO_ERROR )
  83.     {
  84.         return 0;
  85.     }
  86.     return 1;                        
  87. }
  88.  
  89. //-----------------------------------------------------------------------------
  90. BOOL DDE_CLIENT_CONNECTION::RemoveConnection()
  91. {
  92.     if ( client_this.RemoveInstance( this ) )
  93.     {
  94.         if ( DDE_CONNECTION::RemoveConnection() )
  95.         {
  96.             ReleaseDDEData();
  97.             connecting = FALSE;
  98.             return TRUE;
  99.         }
  100.     }
  101.     return FALSE;
  102. }
  103.  
  104. //-----------------------------------------------------------------------------
  105. //
  106. // Used to set up the cur_conv variable, the conversation handle variable
  107. //
  108. BOOL DDE_CLIENT_CONNECTION::SetupConnection()
  109. {
  110.     RemoveConnection();
  111.     CONVCONTEXT     tempCCFilter = 
  112.                     { 
  113.                         sizeof(CONVCONTEXT)
  114.                         , 0
  115.                         , 0
  116.                         , 0
  117.                         , 0L
  118.                         , 0L
  119.                         , {
  120.                             sizeof(SECURITY_QUALITY_OF_SERVICE)
  121.                             , SecurityImpersonation
  122.                             , SECURITY_STATIC_TRACKING
  123.                             , TRUE
  124.                           }
  125.                     };
  126.     if ( cur_conv->NewConv( this, server, &tempCCFilter ) )
  127.     {
  128.         client_this.AddInstanceIndex( this, *cur_conv );
  129.         connecting = TRUE;
  130.         return TRUE;
  131.     }
  132.     
  133.     return FALSE;
  134. }
  135.  
  136. //-----------------------------------------------------------------------------
  137. //
  138. // Flushsendingstring() uses the old service and topic handle, only
  139. // item has been changed.
  140. //
  141. BOOL DDE_CLIENT_CONNECTION::Flushsendingstring()
  142. {
  143.     if ( sending_string.Valid() && sending_string.Length() != 0 )
  144.     {
  145.         //
  146.         // To be used by DDEItem()
  147.         //
  148.         dde_item->ConstructDDEString( sending_string );
  149.         ASSERT( DDEItem() != NULL && (HCONV)*cur_conv );
  150.  
  151.         DdeClientTransaction( ( LPBYTE )sending_string.CString()
  152.                         , sending_string.Length()
  153.                         , *cur_conv
  154.                         , DDEItem()
  155.                         , cur_format
  156.                         , XTYP_POKE
  157.                         , TIMEOUT_ASYNC
  158.                         , &transfer_result);
  159.         transfer_result = DdeGetLastError( DDE_GLOBAL::GetInstId() );
  160.         if ( transfer_result != DMLERR_NO_ERROR )
  161.         {
  162.             return FALSE;
  163.         }
  164.         /*
  165.             According to the documentation, result should have DDE_FACK set
  166.             if operations success'd but, hell!
  167.     
  168.         if ( !( transfer_result & (DWORD)DDE_FACK ) )
  169.         {
  170.             MessageBox( GetFocus(), "POKE operation failed!", "INFO", MB_OK);
  171.             return FALSE;
  172.         }
  173.         else
  174.         {
  175.             return TRUE;
  176.         }
  177.         */
  178.     }
  179.     return TRUE;
  180. }
  181.  
  182. //-----------------------------------------------------------------------------
  183. BOOL DDE_CLIENT_CONNECTION::SendString( ADS_STRING& new_string )
  184. {
  185.     if ( ( new_string.Length() + sending_string.Length() ) < POKE_BUF_SIZE )
  186.     {
  187.         sending_string += new_string;
  188.         return TRUE;
  189.     }
  190.     else
  191.     {
  192.         Flushsendingstring();
  193.         sending_string = new_string;
  194.     }
  195.     return TRUE;
  196. }
  197.  
  198. //-----------------------------------------------------------------------------
  199. BOOL DDE_CLIENT_CONNECTION::BeginSend()
  200. {
  201.     if ( !connecting )
  202.     {
  203.         SetupConnection();
  204.     }
  205.  
  206.     sending_string = "";
  207.     ASSERT ( sending_string.Valid() != NULL );
  208.     return TRUE;
  209. }
  210.  
  211. //-----------------------------------------------------------------------------
  212. BOOL DDE_CLIENT_CONNECTION::EndSend()
  213. {
  214.     //
  215.     // If there are information left in the buffer, send it!
  216.     //
  217.     if ( sending_string.Valid() && sending_string.Length() == 0 )
  218.     {
  219.         return TRUE;
  220.     }
  221.     Flushsendingstring();
  222.     sending_string = "";
  223.  
  224.     return TRUE;
  225. }
  226.  
  227. //-----------------------------------------------------------------------------
  228. BOOL DDE_CLIENT_CONNECTION::Unlink()
  229. {
  230.     if ( !linking )
  231.     {
  232.         return TRUE;
  233.     }
  234.  
  235.     if ( !cur_conv->Valid() )
  236.     {
  237.         return FALSE;
  238.     }
  239.     
  240.     DdeClientTransaction( NULL
  241.                         , 0
  242.                         , *cur_conv
  243.                         , dde_item->Range()
  244.                         , cur_format
  245.                         , XTYP_ADVSTOP
  246.                         , TIMEOUT_ASYNC
  247.                         , &transfer_result  );
  248.     
  249.     linking = FALSE;
  250.     transfer_result = DdeGetLastError( DDE_GLOBAL::GetInstId() );
  251.     if ( transfer_result != DMLERR_NO_ERROR )
  252.     {
  253.         return FALSE;
  254.     }
  255.     return TRUE;
  256. }
  257.  
  258. //-----------------------------------------------------------------------------
  259. BOOL DDE_CLIENT_CONNECTION::Link()
  260. {
  261.     // Only supports hot link for now. ?????
  262.     ASSERT ( linkage == HOT_LINK );
  263.  
  264.     if ( linking )
  265.     {
  266.         Unlink();
  267.     }
  268.  
  269.     if ( !cur_conv->Valid() )
  270.     {
  271.         //
  272.         // Use the default service and topic name
  273.         //
  274.         SetupConnection();
  275.         return FALSE;
  276.     }
  277.  
  278.     if ( DdeClientTransaction( NULL
  279.                                 , 0
  280.                                 , *cur_conv
  281.                                 , dde_item->Range()
  282.                                 , CF_TEXT
  283.                                 , XTYP_ADVSTART
  284.                                 , TIMEOUT_ASYNC
  285.                                 , &transfer_result  ) == TRUE )
  286.     {
  287.         linking = TRUE;
  288.     }                                
  289.     transfer_result = DdeGetLastError( DDE_GLOBAL::GetInstId() );
  290.  
  291.     ASSERT( transfer_result == DMLERR_NO_ERROR );
  292.  
  293.     return linking;
  294. }
  295.  
  296. //-----------------------------------------------------------------------------
  297. HDDEDATA CALLBACK DDE_CLIENT_CONNECTION::ClientCallBack(WORD wType
  298.                                                         , WORD wFmt
  299.                                                         , HCONV hConv
  300.                                                         , HSZ hsz1
  301.                                                         , HSZ hsz2
  302.                                                         , HDDEDATA hData
  303.                                                         , DWORD lData1
  304.                                                         , DWORD lData2)
  305. {
  306.     if ( hConv == NULL )
  307.     {
  308.         return NULL;
  309.     }
  310.  
  311.     DDE_CLIENT_CONNECTION* This;
  312.     This = ( DDE_CLIENT_CONNECTION* )( client_this.This( hConv ) );
  313.  
  314.     if ( This == NULL )
  315.     {
  316.         return NULL;
  317.     }
  318.     
  319. #ifdef DDEADS_DBG
  320.     wsprintf( dbg_string
  321.             , " DDE_CLIENT_CONNECTION callback: this = %lx"
  322.             , This );
  323.     OutputDebugString( dbg_string );
  324. #endif
  325.     switch (wType) 
  326.     {
  327.         /*
  328.             As a client:
  329.         */
  330.         case XTYP_ADVDATA:      // hsz1 = topic, hsz2 = item
  331.         {
  332.             return This->XAdvdata( wFmt, hsz1, hsz2, hData );
  333.         }
  334.         break;
  335.         
  336.         case XTYP_DISCONNECT:   // hsz1 = not used, hsz2 not used
  337.         {
  338.             return This->XDisconnect( hsz1, lData2 );
  339.         }
  340.         break;
  341.         
  342.         case XTYP_ERROR:        // hsz1 = not used, hsz2 not used
  343.         {
  344.             return This->XError( lData1 );
  345.         }
  346.         break;
  347.         
  348.         case XTYP_REGISTER:     // hsz1 = base service name
  349.                                 // hsz2 = instance-specific service name
  350.         {
  351.             return This->XRegister( hsz1, hsz2 );
  352.         }
  353.         break;
  354.         
  355.         case XTYP_UNREGISTER:       // hsz1 = base service name
  356.                                     // hsz2 = instance-specific service name
  357.         {
  358.             return This->XUnregister( hsz1, hsz2 );
  359.         }
  360.         break;
  361.         
  362.         case XTYP_XACT_COMPLETE:    // hsz1 = topic, hsz2 = item
  363.         {
  364.             return This->XXactComplete( wFmt, hsz1, hsz2, hData, lData1, lData2 );
  365.         }
  366.         break;
  367.     }
  368.     return TRUE;
  369. }                                
  370.  
  371. //-----------------------------------------------------------------------------
  372. HDDEDATA DDE_CLIENT_CONNECTION::XAdvdata( WORD wFmt
  373.                                         , HSZ hsz1
  374.                                         , HSZ hsz2
  375.                                         , HDDEDATA hData )
  376. {
  377.     if ( linking 
  378.         && hsz1 == DDETopic()
  379.         && hsz2 == DDEItem()
  380.         && wFmt == cur_format )
  381.     {
  382.         CreateDDEData( hData );
  383.         RequestADSUpdate();
  384.         // MessageBox( GetFocus(), "XAdvdata called", "INFO", MB_OK );
  385.         return DDE_FACK;
  386.     }
  387.     return DDE_FNOTPROCESSED;
  388. }
  389.  
  390. //-----------------------------------------------------------------------------
  391. HDDEDATA DDE_CLIENT_CONNECTION::XDisconnect( HSZ hsz1
  392.                                         , DWORD lData2)
  393. {
  394.     RemoveConnection();
  395.     return 1;
  396. }
  397.                                         
  398. //-----------------------------------------------------------------------------
  399. HDDEDATA DDE_CLIENT_CONNECTION::XError( DWORD lData1 )
  400. {
  401.     return 1;
  402. }
  403.  
  404. //-----------------------------------------------------------------------------
  405. HDDEDATA DDE_CLIENT_CONNECTION::XRegister(  HSZ hsz1
  406.                                         , HSZ hsz2 )
  407. {
  408.     return 1;
  409. }
  410.                                         
  411. //-----------------------------------------------------------------------------
  412. HDDEDATA DDE_CLIENT_CONNECTION::XUnregister(  HSZ hsz1
  413.                                         , HSZ hsz2 )
  414. {
  415.     return 1;
  416. }
  417.                                         
  418. //-----------------------------------------------------------------------------
  419. HDDEDATA DDE_CLIENT_CONNECTION::XXactComplete( WORD wFmt
  420.                                         , HSZ hsz1
  421.                                         , HSZ hsz2
  422.                                         , HDDEDATA hData
  423.                                         , DWORD lData1
  424.                                         , DWORD lData2)
  425. {
  426.     return 0;
  427. }                                        
  428.  
  429. //-----------------------------------------------------------------------------
  430. void DDE_CLIENT_CONNECTION::ReleaseDDEData()
  431. {
  432.     if ( ddedata )
  433.     {
  434.         delete ddedata;
  435.         data_len = 0;
  436.         ddedata = NULL;
  437.     }
  438. }
  439.  
  440. //-----------------------------------------------------------------------------
  441. BOOL DDE_CLIENT_CONNECTION::CreateDDEData( const LPBYTE src_ddedata
  442.                                         , DWORD src_data_len )
  443. {
  444.     ReleaseDDEData();
  445.     if ( !src_ddedata || src_data_len <= 0 )
  446.     {
  447.         return FALSE;
  448.     }
  449.     ddedata = new BYTE [ src_data_len ];
  450.     data_len = src_data_len;
  451.     if ( ddedata )
  452.     {
  453.         if ( memcpy( ddedata, src_ddedata, data_len ) != ddedata )
  454.         {
  455.             delete ddedata;
  456.             data_len = 0;
  457.             return FALSE;
  458.         }
  459.         else
  460.         {
  461.             return TRUE;
  462.         }
  463.     }    
  464.     return FALSE;
  465. }
  466.  
  467. //-----------------------------------------------------------------------------
  468. //
  469. // This function should be called from DDEClientCallBack() to save the
  470. // hData which then can be used for ADS purposes.
  471. //
  472. BOOL DDE_CLIENT_CONNECTION::CreateDDEData( HDDEDATA hdata )
  473. {
  474.     LPBYTE  tempptr;
  475.     DWORD   len;
  476.     BOOL    ret_val;
  477.     
  478.     tempptr = DdeAccessData( hdata, &len );
  479.     
  480.     if ( tempptr && len )
  481.     {
  482.         ret_val = CreateDDEData( tempptr, len );
  483.         DdeUnaccessData( hdata );
  484.         return ret_val;
  485.     }
  486.     else
  487.     {
  488.         return FALSE;
  489.     }
  490. }
  491.  
  492. //-----------------------------------------------------------------------------
  493. int DDE_CLIENT_CONNECTION::SendAdsTable( char *tbl_name )
  494. {
  495.     char            *temp_buf;
  496.     struct resbuf   *rb = NULL;
  497.     ADS_TABLE_OBJ   *temp_obj;
  498.     BOOL            rewind = TRUE;
  499.     int             subtotal = 0;
  500.     
  501.     temp_buf = new char[ GENERAL_BUFFER_SIZE ];
  502.     wsprintf( temp_buf, "\nSending table %s, table #: ", tbl_name );
  503.     ads_printf( temp_buf );
  504.     ShowLife();
  505.     ShowLife( 0 );
  506.  
  507.     for ( rewind = TRUE
  508.         ; UserBrk() != TRUE && ( rb = ads_tblnext( tbl_name, rewind ) ) != NULL
  509.         ; rewind = FALSE )
  510.     {
  511.         subtotal++;
  512.         ShowLife( subtotal );
  513.         temp_obj = MakeAdsTable( rb );
  514.         if ( temp_obj )
  515.         {
  516.             if ( SendString( temp_obj->FormatTableString() ) != TRUE )
  517.             {
  518.                 subtotal = -1;
  519.                 break;
  520.             }
  521.             DeleteAdsTable( temp_obj );
  522.         }
  523.         ads_relrb( rb );
  524.         rb = NULL;
  525.     }
  526.     if ( rb != NULL )
  527.     {
  528.         ads_relrb( rb );
  529.     }
  530.     return subtotal;
  531. }
  532.  
  533. //-----------------------------------------------------------------------------
  534. int DDE_CLIENT_CONNECTION::SendAdsAllTables()
  535. {
  536.     int total = 0;
  537.  
  538.     total =   SendAdsTable( "LAYER" )
  539.             + SendAdsTable( "LTYPE" )
  540.             + SendAdsTable( "VIEW" )
  541.             + SendAdsTable( "STYLE" )
  542.             + SendAdsTable( "BLOCK" )
  543.             + SendAdsTable( "UCS" )
  544.             + SendAdsTable( "DIMSTYLE" )
  545.             + SendAdsTable( "VPORT" )
  546.             + SendAdsTable( "APPID" );
  547.     return total;
  548. }
  549.  
  550. //-----------------------------------------------------------------------------
  551. int DDE_CLIENT_CONNECTION::SendAdsAllEntities()
  552. {
  553.     int         total_ent = 0;
  554.     ads_name    ename;
  555.  
  556.     if ( ads_entnext( NULL, ename ) != RTERROR )
  557.     {
  558.         ads_printf("\nSending Ads entity #: ");
  559.         ShowLife();
  560.         do
  561.         {
  562.             total_ent++;
  563.             struct resbuf *rb;
  564.             rb = ads_entget( ename );
  565.             if ( ShowLife( total_ent ) )
  566.             {
  567.                 if ( SendAdsEntity( rb ) < 0 )
  568.                 {
  569.                     // Send entity failed
  570.                     return total_ent;
  571.                 }
  572.             }
  573.             ads_relrb( rb );
  574.         }
  575.         while ( UserBrk() == FALSE && ads_entnext( ename, ename ) != RTERROR );
  576.     }
  577.     return total_ent;
  578. }
  579.  
  580. //-----------------------------------------------------------------------------
  581. // Given the head of a resbuf of an entity, this function sends out the 
  582. // entity to the spread sheet and returns the number of entity sent out
  583. //
  584. int DDE_CLIENT_CONNECTION::SendAdsEntity( struct resbuf *rb )
  585. {
  586.     static  entity = 0;
  587.  
  588.     if ( rb == NULL 
  589.         || rb->restype != -1 
  590.         || rb->rbnext == NULL 
  591.         || rb->rbnext->restype != 0 )
  592.     {
  593.         return -1;
  594.     }
  595.  
  596.     ADS_ENT_OBJ* temp_obj = MakeAdsEntity( rb );
  597.     if ( temp_obj )
  598.     {
  599.         if ( SendString( temp_obj->FormatEntityString() ) != TRUE )
  600.         {
  601.             entity = -1;
  602.         }
  603.         DeleteAdsEntity( temp_obj );
  604.     }
  605.     else
  606.     {
  607.         SendString( (ADS_STRING)"\n\n\t!!!!! Entiity not supported !!!!!\n\n" );
  608.         entity = -1;
  609.     }
  610.  
  611.     return entity;
  612. }
  613.  
  614. //-----------------------------------------------------------------------------
  615. BOOL DDE_CLIENT_CONNECTION::ModifyDDEEntity( struct resbuf *rb )
  616. {
  617.     BOOL entity_modified = FALSE;
  618.  
  619.     if ( rb != NULL && ddedata != NULL )
  620.     {
  621.         ADS_ENT_OBJ* temp_obj = MakeAdsEntity( rb );
  622.         if ( temp_obj )
  623.         {
  624.             char *temp_buf = new char[ 256 ];
  625.             temp_obj->GetEntityName( temp_buf, 256 );
  626.             temp_obj->FormatEntityString();
  627.             char *temp_ptr = strstr( (char*)ddedata
  628.                                    , temp_obj->formatstring.CString() );
  629.             //
  630.             // temp_ptr is pointing at the data from DDE importing
  631.             // entity if it is not NULL, otherwise some weird
  632.             // format in the DDE data has encounter'd
  633.             //
  634.             delete temp_buf;
  635.         }
  636.     }
  637.  
  638.     return entity_modified;
  639. }
  640.  
  641.  
  642.