home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / drgthr.zip / srcrendr.c < prev    next >
C/C++ Source or Header  |  1993-07-18  |  21KB  |  456 lines

  1. /*********************************************************************
  2.  *                                                                   *
  3.  * MODULE NAME :  srcrendr.c             AUTHOR:  Rick Fishman       *
  4.  * DATE WRITTEN:  07-16-93                                           *
  5.  *                                                                   *
  6.  * MODULE DESCRIPTION:                                               *
  7.  *                                                                   *
  8.  *  Part of the 'DRGTHRND' drag/drop sample program.                 *
  9.  *                                                                   *
  10.  *  This module handles all the rendering for the source window.     *
  11.  *                                                                   *
  12.  * NOTES:                                                            *
  13.  *                                                                   *
  14.  * FUNCTIONS AVALABLE TO OTHER MODULES:                              *
  15.  *                                                                   *
  16.  *   srcRenderPrepare                                                *
  17.  *   srcCreateWindow                                                 *
  18.  *                                                                   *
  19.  * HISTORY:                                                          *
  20.  *                                                                   *
  21.  *  07-16-93 - Program coded.                                        *
  22.  *                                                                   *
  23.  *  Rick Fishman                                                     *
  24.  *  Code Blazers, Inc.                                               *
  25.  *  4113 Apricot                                                     *
  26.  *  Irvine, CA. 92720                                                *
  27.  *  CIS ID: 72251,750                                                *
  28.  *                                                                   *
  29.  *********************************************************************/
  30.  
  31. #pragma strings(readonly)   // used for debug version of memory mgmt routines
  32.  
  33. /*********************************************************************/
  34. /*------- Include relevant sections of the OS/2 header files --------*/
  35. /*********************************************************************/
  36.  
  37. #define  INCL_DOSERRORS
  38. #define  INCL_DOSPROCESS
  39. #define  INCL_WINDIALOGS
  40. #define  INCL_WINERRORS
  41. #define  INCL_WINFRAMEMGR
  42. #define  INCL_WINSTDCNR
  43. #define  INCL_WINSTDDRAG
  44. #define  INCL_WINWINDOWMGR
  45.  
  46. /**********************************************************************/
  47. /*----------------------------- INCLUDES -----------------------------*/
  48. /**********************************************************************/
  49.  
  50. #include <os2.h>
  51. #include <process.h>
  52. #include <stdio.h>
  53. #include <stdlib.h>
  54. #include <string.h>
  55. #include "drgthrnd.h"
  56.  
  57. /*********************************************************************/
  58. /*------------------- APPLICATION DEFINITIONS -----------------------*/
  59. /*********************************************************************/
  60.  
  61. #define STACKSIZE 0xE000                      // Stacksize for secondary threads
  62.  
  63. /**********************************************************************/
  64. /*---------------------------- STRUCTURES ----------------------------*/
  65. /**********************************************************************/
  66.  
  67. typedef struct _WINSTARTUP
  68. {
  69.     ULONG cb;
  70.     HWND  hwndFrame;
  71. } WINSTARTUP, *PWINSTARTUP;
  72.  
  73. /**********************************************************************/
  74. /*----------------------- FUNCTION PROTOTYPES ------------------------*/
  75. /**********************************************************************/
  76.  
  77. void    SourceThread   ( void *pvHwndFrame );
  78. MRESULT Render         ( HWND hwndFrame, PDRAGTRANSFER pDragXfer );
  79. void    DoTheRendering ( PDRAGTRANSFER pDragXfer );
  80. MRESULT EndConversation( HWND hwndFrame );
  81.  
  82. FNWP wpSource;
  83.  
  84. /**********************************************************************/
  85. /*------------------------ GLOBAL VARIABLES --------------------------*/
  86. /**********************************************************************/
  87.  
  88.  
  89. /**********************************************************************/
  90. /*----------------------- srcRenderPrepare ---------------------------*/
  91. /*                                                                    */
  92. /*  PROCESS A DM_RENDERPREPARE MESSAGE                                */
  93. /*                                                                    */
  94. /*  PARMS: frame window handle,                                       */
  95. /*         pointer to a DRAGTRANSFER structure                        */
  96. /*                                                                    */
  97. /*  NOTES: The source uses this message to create an object window    */
  98. /*         that will process all source render messages. It creates   */
  99. /*         this window in a separate thread so that the main container*/
  100. /*         window is available and it doesn't tie up the message      */
  101. /*         queue. It only needs to create one window that will be     */
  102. /*         used to process all items.                                 */
  103. /*                                                                    */
  104. /*  RETURNS: MRESULT explaining if it's ok to render                  */
  105. /*                                                                    */
  106. /*--------------------------------------------------------------------*/
  107. /**********************************************************************/
  108. MRESULT srcRenderPrepare( HWND hwndFrame, PDRAGTRANSFER pDragXfer )
  109. {
  110.     BOOL      fOkToRender = TRUE;
  111.     PINSTANCE pi = INSTDATA( hwndFrame );
  112.  
  113.     if( !pi->hwndRender )
  114.     {
  115.         pi->hwndRender = srcCreateWindow( hwndFrame );
  116.         if( !pi->hwndRender )
  117.             fOkToRender = FALSE;
  118.     }
  119.  
  120.     // Change the source window in the DRAGITEM structure so that the target
  121.     // automaticall routes the render messages to this window. The target
  122.     // always sends/posts render messages to pDragXfer->pditem->hwndItem.
  123.  
  124.     if( fOkToRender )
  125.         pDragXfer->pditem->hwndItem = pi->hwndRender;
  126.  
  127.     return (MRESULT) fOkToRender;
  128. }
  129.  
  130. /**********************************************************************/
  131. /*------------------------- srcCreateWindow --------------------------*/
  132. /*                                                                    */
  133. /*  CREATE A WINDOW IN ANOTHER THREAD THAT WILL PROCESS THE RENDERING */
  134. /*  FOR THE SOURCE.                                                   */
  135. /*                                                                    */
  136. /*  PARMS: frame window handle                                        */
  137. /*                                                                    */
  138. /*  NOTES:                                                            */
  139. /*                                                                    */
  140. /*  RETURNS: nothing                                                  */
  141. /*                                                                    */
  142. /*--------------------------------------------------------------------*/
  143. /**********************************************************************/
  144. HWND srcCreateWindow( HWND hwndFrame )
  145. {
  146.     HWND hwndRender = NULLHANDLE;
  147.     TID  tid;
  148.  
  149.     // Start the thread. Then wait for the thread's window to be created, at
  150.     // which point it will post a UM_WINDOW_CREATED message to this thread.
  151.     // We take over the message queue not just to catch this message but so
  152.     // that the message queue will not be tied up while this message is being
  153.     // created. It does act as a cheap semaphore mechanism though...
  154.  
  155.     tid = _beginthread( SourceThread, NULL, STACKSIZE, (void *) hwndFrame );
  156.  
  157.     if( (int) tid != -1 )
  158.     {
  159.         HAB  hab = ANCHOR( hwndFrame );
  160.         QMSG qmsg;
  161.  
  162.         while( WinGetMsg( hab, &qmsg, NULLHANDLE, 0, 0 ) )
  163.             if( qmsg.msg == UM_WINDOW_CREATED )
  164.             {
  165.                 hwndRender = (HWND) qmsg.mp1;
  166.                 break;
  167.             }
  168.             else
  169.                 WinDispatchMsg( hab, &qmsg );
  170.     }
  171.     else
  172.         Msg( "_beginthread for source window failed!" );
  173.  
  174.     return hwndRender;
  175. }
  176.  
  177. /**********************************************************************/
  178. /*-------------------------- SourceThread ----------------------------*/
  179. /*                                                                    */
  180. /*  THREAD THAT HANDLES THE RENDERING ON THE SOURCE WINDOW SIDE.      */
  181. /*                                                                    */
  182. /*  PARMS: frame window handle (this is passes as a void pointer to   */
  183. /*               satisfy the requirements of _beginthread())          */
  184. /*                                                                    */
  185. /*  NOTES: The UM_WINDOW_CREATED message is our way of letting the    */
  186. /*         creator of this thread know the window handle of the render*/
  187. /*         object window. It is our way of 'returning' that window    */
  188. /*         handle. We place it in mp1 of that message. If anything    */
  189. /*         happens to hurt the creation of that window we will pass   */
  190. /*         back a NULL in mp1.                                        */
  191. /*                                                                    */
  192. /*  RETURNS: nothing                                                  */
  193. /*                                                                    */
  194. /*--------------------------------------------------------------------*/
  195. /**********************************************************************/
  196. #define SOURCE_CLASS "ThisIsTheSourceClass"
  197.  
  198. void SourceThread( void *pvHwndFrame )
  199. {
  200.     HAB  hab = WinInitialize( 0 );
  201.     HMQ  hmq;
  202.     HWND hwndFrame = (HWND) pvHwndFrame;
  203.  
  204.     if( hab )
  205.         hmq = WinCreateMsgQueue( hab, 0 );
  206.     else
  207.     {
  208.         WinPostMsg( hwndFrame, UM_WINDOW_CREATED, NULL, NULL );
  209.         DosBeep( 1000, 100 );
  210.         fprintf( stderr, "WinInitialize failed!" );
  211.     }
  212.  
  213.     if( hmq )
  214.     {
  215.         WINSTARTUP WinStartup;
  216.         HWND       hwndObj;
  217.  
  218.         // Pass the frame window handle to the render window - it will need that
  219.         // handle to get at the frame window's window word. Remember that when
  220.         // passing a pointer to a structure via the pCtlData parameter, the
  221.         // first USHORT must be the size of the structure.
  222.  
  223.         WinStartup.cb        = sizeof WinStartup;
  224.         WinStartup.hwndFrame = hwndFrame;
  225.  
  226.         WinRegisterClass( hab, SOURCE_CLASS, wpSource, 0, sizeof( void * ) );
  227.  
  228.         hwndObj = WinCreateWindow( HWND_OBJECT, SOURCE_CLASS, NULL, 0, 0, 0, 0,
  229.                                    0, NULLHANDLE, HWND_TOP, 1, &WinStartup,
  230.                                    NULL );
  231.         if( hwndObj )
  232.         {
  233.             QMSG qmsg;
  234.  
  235.             WinPostMsg( hwndFrame, UM_WINDOW_CREATED, MPFROMHWND( hwndObj ),
  236.                         NULL );
  237.             while( WinGetMsg( hab, &qmsg, NULLHANDLE, 0, 0 ) )
  238.                 WinDispatchMsg( hab, &qmsg );
  239.  
  240.             WinDestroyWindow( hwndObj );
  241.         }
  242.         else
  243.         {
  244.             WinPostMsg( hwndFrame, UM_WINDOW_CREATED, NULL, NULL );
  245.             Msg( "WinCreateWindow( hwndObj ) RC(%X)", HABERR( hab ) );
  246.         }
  247.     }
  248.     else if( hab )
  249.     {
  250.         WinPostMsg( hwndFrame, UM_WINDOW_CREATED, NULL, NULL );
  251.         Msg( "WinCreateMsgQueue RC(%X)", HABERR( hab ) );
  252.     }
  253.  
  254.     if( hmq )
  255.         WinDestroyMsgQueue( hmq );
  256.  
  257.     if( hab )
  258.         WinTerminate( hab );
  259.  
  260.     _endthread();
  261. }
  262.  
  263. /**********************************************************************/
  264. /*---------------------------- wpSource ------------------------------*/
  265. /*                                                                    */
  266. /*  WINDOW PROCEDURE FOR THE SOURCE RENDERING OBJECT WINDOW.          */
  267. /*                                                                    */
  268. /*  PARMS: standard window procedure parameters                       */
  269. /*                                                                    */
  270. /*  NOTES:                                                            */
  271. /*                                                                    */
  272. /*  RETURNS: nothing                                                  */
  273. /*                                                                    */
  274. /*--------------------------------------------------------------------*/
  275. /**********************************************************************/
  276. MRESULT EXPENTRY wpSource( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
  277. {
  278.     HWND hwndFrame = (HWND) WinQueryWindowULong( hwnd, 0 );
  279.  
  280.     switch( msg )
  281.     {
  282.         case WM_CREATE:
  283.         {
  284.             WinSetWindowULong( hwnd, 0, ((PWINSTARTUP) mp1)->hwndFrame );
  285.             break;
  286.         }
  287.  
  288.         // Just figure out if we can render or not. If we can, all rendering
  289.         // will be done in the UM_DO_THE_RENDERING message.
  290.  
  291.         case DM_RENDER:
  292.         {
  293.             MRESULT mr = Render( hwndFrame, (PDRAGTRANSFER) mp1 );
  294.  
  295.             if( mr )
  296.                 WinPostMsg( hwnd, UM_DO_THE_RENDERING, mp1, NULL );
  297.  
  298.             return mr;
  299.         }
  300.  
  301.         case UM_DO_THE_RENDERING:
  302.             DoTheRendering( (PDRAGTRANSFER) mp1 );
  303.             return 0;
  304.  
  305.         // The target sends this when it is done processing the DM_RENDERCOMPLETE
  306.         // message that the source sent it. This means everything is complete
  307.         // on both sides.
  308.  
  309.         case DM_ENDCONVERSATION:
  310.             return EndConversation( hwndFrame );
  311.  
  312.         case DM_RENDERCOMPLETE:
  313.         {
  314.             PDRAGTRANSFER pDragXfer = (PDRAGTRANSFER) mp1;
  315.  
  316.             // If the source gets this message it means that it requested a
  317.             // a retry and the target said no. So complete the loop...
  318.  
  319.             DrgPostTransferMsg( pDragXfer->hwndClient, DM_RENDERCOMPLETE,
  320.                                 pDragXfer, DMFL_RENDERFAIL, 0, FALSE );
  321.  
  322.             return 0;
  323.         }
  324.     }
  325.  
  326.     return WinDefWindowProc( hwnd, msg, mp1, mp2 );
  327. }
  328.  
  329. /**********************************************************************/
  330. /*----------------------------- Render -------------------------------*/
  331. /*                                                                    */
  332. /*  PROCESS A DM_RENDER MESSAGE                                       */
  333. /*                                                                    */
  334. /*  PARMS: frame window handle,                                       */
  335. /*         pointer to a DRAGTRANSFER structure                        */
  336. /*                                                                    */
  337. /*  NOTES: This is a SOURCE window message                            */
  338. /*                                                                    */
  339. /*  RETURNS: MRESULT explaining the rendering availability            */
  340. /*                                                                    */
  341. /*--------------------------------------------------------------------*/
  342. /**********************************************************************/
  343. MRESULT Render( HWND hwndFrame, PDRAGTRANSFER pDragXfer )
  344. {
  345.     hwndFrame=hwndFrame;    // Keep the compiler happy
  346.     pDragXfer=pDragXfer;
  347.  
  348.     // Normally here we would check some things and return TRUE if everything
  349.     // looked OK or we would return FALSE and set pDragXfer->fsReply to the
  350.     // reason for the FALSE. A typical reason to return FALSE would be if
  351.     // pDragXfer->hstrSelectedRMF was something we couldn't support or
  352.     // pDragXfer->usOperation was something we didn't want to do. In that case
  353.     // we'd return FALSE and set fsReply to DMFL_RENDERRETRY. It would then be
  354.     // up to the target to change its parameters and send us another DM_RENDER.
  355.  
  356.     return (MRESULT) TRUE;
  357. }
  358.  
  359. /**********************************************************************/
  360. /*------------------------- DoTheRendering ---------------------------*/
  361. /*                                                                    */
  362. /*  DO THE RENDERING.                                                 */
  363. /*                                                                    */
  364. /*  PARMS: pointer to a DRAGTRANSFER structure                        */
  365. /*                                                                    */
  366. /*  NOTES: This is a SOURCE window message                            */
  367. /*                                                                    */
  368. /*  RETURNS: nothing                                                  */
  369. /*                                                                    */
  370. /*--------------------------------------------------------------------*/
  371. /**********************************************************************/
  372. void DoTheRendering( PDRAGTRANSFER pDragXfer )
  373. {
  374.     PSZ   pszTableName, pszFileName, pszLoc;
  375.     ULONG cbString, flStatus = DMFL_RENDEROK;
  376.  
  377.     // Form the 'database:table' string by combining the database name which
  378.     // is stored in hstrContainerName with the table name which is stored in
  379.     // hstrSourceName.
  380.  
  381.     cbString = DrgQueryStrNameLen( pDragXfer->pditem->hstrContainerName ) +
  382.                DrgQueryStrNameLen( pDragXfer->pditem->hstrSourceName ) +
  383.                2;  // Null terminator plus colon
  384.  
  385.     pszTableName = pszLoc = _alloca( cbString );
  386.  
  387.     DrgQueryStrName( pDragXfer->pditem->hstrContainerName, cbString, pszLoc );
  388.     strcat( pszTableName, ":" );
  389.     pszLoc += strlen( pszTableName );
  390.     cbString -= strlen( pszTableName );
  391.     DrgQueryStrName( pDragXfer->pditem->hstrSourceName, cbString, pszLoc );
  392.  
  393.     // Get the file name that we (the source) should be rendering to. This
  394.     // name was decided by the target before it sent us the DM_RENDER message.
  395.  
  396.     cbString = DrgQueryStrNameLen( pDragXfer->hstrRenderToName ) + 1;
  397.     pszFileName = _alloca( cbString );
  398.     DrgQueryStrName( pDragXfer->hstrRenderToName, cbString, pszFileName );
  399.  
  400.     // Call this function which will copy the database data into the file.
  401.  
  402.     if( !dbRenderToFile( pszTableName, pszFileName ) )
  403.         flStatus = DMFL_RENDERFAIL;
  404.  
  405.     // Tell the target that we're done.
  406.  
  407.     DrgPostTransferMsg( pDragXfer->hwndClient, DM_RENDERCOMPLETE, pDragXfer,
  408.                         flStatus, 0, FALSE );
  409.  
  410.     // Bot the target and the source must free this. Since we're done at the
  411.     // source, it is time to free it.
  412.  
  413.     DrgFreeDragtransfer( pDragXfer );
  414. }
  415.  
  416. /**********************************************************************/
  417. /*-------------------------- EndConversation -------------------------*/
  418. /*                                                                    */
  419. /*  FREE THE RESOURCES USED BY DRAG/DROP PROCESSING. ONLY DO THIS IF  */
  420. /*  THIS IS THE LAST ITEM (there is one end-conversation message sent */
  421. /*  to us for each item dropped).                                     */
  422. /*                                                                    */
  423. /*  PARMS: frame window handle                                        */
  424. /*                                                                    */
  425. /*  NOTES: This is a SOURCE window message that the target sends after*/
  426. /*         it is done processing the DM_RENDERCOMPLETE message that   */
  427. /*         the source sent it.                                        */
  428. /*                                                                    */
  429. /*  RETURNS: nothing                                                  */
  430. /*                                                                    */
  431. /*--------------------------------------------------------------------*/
  432. /**********************************************************************/
  433. MRESULT EndConversation( HWND hwndFrame )
  434. {
  435.     PINSTANCE pi = INSTDATA( hwndFrame );
  436.  
  437.     if( !pi )
  438.     {
  439.         Msg( "EndConversation cant get Inst data RC(%X)", HWNDERR(hwndFrame) );
  440.         return 0;
  441.     }
  442.  
  443.     // We need to keep a running total to know when all items in the drop have
  444.     // been processed. When that happens, it is time to free the resources that
  445.     // were allocated to the drag as a whole rather than to an indidvidual item.
  446.  
  447.     if( --pi->cDragItems == 0 )
  448.         dragSourceCleanup( hwndFrame );
  449.  
  450.     return 0;
  451. }
  452.  
  453. /*************************************************************************
  454.  *                     E N D     O F     S O U R C E                     *
  455.  *************************************************************************/
  456.