home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / cnradv.zip / cnradv.C next >
C/C++ Source or Header  |  1993-07-19  |  33KB  |  779 lines

  1. /*********************************************************************
  2.  *                                                                   *
  3.  * MODULE NAME :  cnradv.c               AUTHOR:  Rick Fishman       *
  4.  * DATE WRITTEN:  11-30-92                                           *
  5.  *                                                                   *
  6.  * HOW TO RUN THIS PROGRAM:                                          *
  7.  *                                                                   *
  8.  *  By just entering CNRADV on the command line, a container will be *
  9.  *  created that will contain the files in the current directory.    *
  10.  *  Any subdirectories will be included and expandable in Tree view. *
  11.  *  The container starts in Tree view. You can switch to the other   *
  12.  *  supported views.                                                 *
  13.  *                                                                   *
  14.  *  Optionally enter 'CNRADV directory' and that directory will be   *
  15.  *  displayed.                                                       *
  16.  *                                                                   *
  17.  * MODULE DESCRIPTION:                                               *
  18.  *                                                                   *
  19.  *  Root module for CNRADV.EXE, a program that demonstrates the      *
  20.  *  base functionality of a container control. This module contains  *
  21.  *  the client window procedure and some supporting functions for    *
  22.  *  the container messages. It builds on the CNRMENU.EXE sample      *
  23.  *  program by adding container drag/drop functionality.             *
  24.  *                                                                   *
  25.  *  The container is populated with records from a secondary thread. *
  26.  *  This is done not to complicate things but to let the user        *
  27.  *  interact with the container before it is completely filled if we *
  28.  *  are traversing a directory with many subdirectories.             *
  29.  *                                                                   *
  30.  *  Deltas are not demonstrated in this sample program.              *                                           *
  31.  *                                                                   *
  32.  * OTHER MODULES:                                                    *
  33.  *                                                                   *
  34.  *  create.c -   contains the code used to create and tailor a       *
  35.  *               container. These functions are called for each      *
  36.  *               container that is created.                          *
  37.  *                                                                   *
  38.  *  populate.c - contains the code for the thread used to fill the   *
  39.  *               container with records.                             *
  40.  *                                                                   *
  41.  *  common.c -   contains common support routines for CNRADV.EXE.    *
  42.  *                                                                   *
  43.  *  ctxtmenu.c - contains context menu routines.                     *
  44.  *                                                                   *
  45.  *  edit.c -     contains direct editing routines.                   *
  46.  *                                                                   *
  47.  *  sort.c -     contains container sorting routines.                *
  48.  *                                                                   *
  49.  * NOTES:                                                            *
  50.  *                                                                   *
  51.  *  This program has gotten pretty complex as new aspects of the     *
  52.  *  container were added. This makes it a pretty difficult program   *
  53.  *  to follow. I believe it is most useful for exploring the         *
  54.  *  different areas from a working program perspective. I don't      *
  55.  *  think it would be a good idea to try and follow this program     *
  56.  *  through its whole operation as you will quickly get lost in the  *
  57.  *  details.                                                         *
  58.  *                                                                   *
  59.  *  I hope this code proves useful for other PM programmers. The     *
  60.  *  more of us the better!                                           *
  61.  *                                                                   *
  62.  * HISTORY:                                                          *
  63.  *                                                                   *
  64.  *  11-30-92 - Source copied from CNRMENU.EXE sample.                *
  65.  *             Added ProgInit and ProgTerm to load and destroy the   *
  66.  *               global folder icon handle.                          *
  67.  *  12-05-92   Changed wmControl to return an MRESULT.               *
  68.  *             Added drag/drop message processing, including         *
  69.  *               WM_CONTROL messages.                                *
  70.  *             Took out the client's WM_ERASEBACKGROUND processing   *
  71.  *               to avoid flicker while container paints its         *
  72.  *               background. Client is never exposed anyway.         *
  73.  *             Put the load of hbmBackground in ProgInit.            *
  74.  *             Put the delete of hbmBackground in ProgTerm.          *
  75.  *             Process WM_DRAWITEM message by calling DrawItem.      *
  76.  *  12-26-92   Added a WinDestroyWindow of hwndMenu in WM_MENUEND.   *
  77.  *  01-01-93   Initialize fTrue for all while( fTrue ) loops.        *
  78.  *  03-27-93   Changed PSZ szArg to char *szArg  - compiler bug.     *
  79.  *  07-19-93   Took out the loading of hptrFolder. It appears that   *
  80.  *             OS/2 2.1 fixed the problem of WinLoadFileIcon not     *
  81.  *             loading the folder icon for directories.              *
  82.  *                                                                   *
  83.  *  Rick Fishman                                                     *
  84.  *  Code Blazers, Inc.                                               *
  85.  *  4113 Apricot                                                     *
  86.  *  Irvine, CA. 92720                                                *
  87.  *  CIS ID: 72251,750                                                *
  88.  *                                                                   *
  89.  *********************************************************************/
  90.  
  91. #pragma strings(readonly)   // used for debug version of memory mgmt routines
  92.  
  93. /*********************************************************************/
  94. /*------- Include relevant sections of the OS/2 header files --------*/
  95. /*********************************************************************/
  96.  
  97. #define INCL_DEV
  98. #define INCL_DOSERRORS
  99. #define INCL_GPI_BITMAPS
  100. #define INCL_GPI_CONTROL
  101. #define INCL_WINDIALOGS
  102. #define INCL_WINERRORS
  103. #define INCL_WINFRAMEMGR
  104. #define INCL_WINMENUS
  105. #define INCL_WINPOINTERS
  106. #define INCL_WINSTDCNR
  107. #define INCL_WINSTDDLGS
  108. #define INCL_WINWINDOWMGR
  109.  
  110. #define GLOBALS_DEFINED        // This module defines the globals in cnradv.h
  111.  
  112. /**********************************************************************/
  113. /*----------------------------- INCLUDES -----------------------------*/
  114. /**********************************************************************/
  115.  
  116. #include <os2.h>
  117. #include <stdarg.h>
  118. #include <stdio.h>
  119. #include <stdlib.h>
  120. #include <string.h>
  121. #include "cnradv.h"
  122.  
  123. /*********************************************************************/
  124. /*------------------- APPLICATION DEFINITIONS -----------------------*/
  125. /*********************************************************************/
  126.  
  127. #define DEFAULT_VIEW  (CV_TREE | CV_ICON)
  128.  
  129. /**********************************************************************/
  130. /*---------------------------- STRUCTURES ----------------------------*/
  131. /**********************************************************************/
  132.  
  133. /**********************************************************************/
  134. /*----------------------- FUNCTION PROTOTYPES ------------------------*/
  135. /**********************************************************************/
  136.  
  137.        INT      main            ( INT iArgc, char *szArg[] );
  138. static VOID     ProgInit        ( HAB hab );
  139. static BOOL     InitClient      ( HWND hwndClient, PWINCREATE pwc );
  140. static MRESULT  wmControl       ( HWND hwndClient, MPARAM mp1, MPARAM mp2 );
  141. static VOID     RecordSelected  ( HWND hwndClient, PNOTIFYRECORDENTER pnre );
  142. static VOID     ContainerFilled ( HWND hwndClient );
  143. static VOID     UserWantsToClose( HWND hwndClient );
  144. static VOID     FreeResources   ( HWND hwndClient );
  145. static VOID     ProgTerm        ( HAB hab );
  146.  
  147. FNWP wpClient;
  148.  
  149. /**********************************************************************/
  150. /*------------------------ GLOBAL VARIABLES --------------------------*/
  151. /**********************************************************************/
  152.  
  153. /**********************************************************************/
  154. /*------------------------------ MAIN --------------------------------*/
  155. /*                                                                    */
  156. /*  PROGRAM ENTRYPOINT                                                */
  157. /*                                                                    */
  158. /*  INPUT: command line                                               */
  159. /*                                                                    */
  160. /*  1.                                                                */
  161. /*                                                                    */
  162. /*  OUTPUT: return code                                               */
  163. /*                                                                    */
  164. /*--------------------------------------------------------------------*/
  165. /**********************************************************************/
  166. INT main( INT iArgc, char *szArg[] )
  167. {
  168.     BOOL  fSuccess = FALSE;
  169.     HAB   hab;
  170.     HMQ   hmq = NULLHANDLE;
  171.     QMSG  qmsg;
  172.     PSZ   szStartingDir = NULL;
  173.     HWND  hwndFrame = NULLHANDLE;
  174.  
  175.     // This macro is defined for the debug version of the C Set/2 Memory
  176.     // Management routines. Since the debug version writes to stderr, we
  177.     // send all stderr output to a debuginfo file. Look in MAKEFILE to see how
  178.     // to enable the debug version of those routines.
  179.  
  180. #ifdef __DEBUG_ALLOC__
  181.     freopen( DEBUG_FILENAME, "w", stderr );
  182. #endif
  183.  
  184.     // Get the directory to display from the command line if specified.
  185.  
  186.     if( iArgc > 1 )
  187.         szStartingDir = szArg[ 1 ];
  188.  
  189.     hab = WinInitialize( 0 );
  190.  
  191.     if( hab )
  192.         hmq = WinCreateMsgQueue( hab, 0 );
  193.     else
  194.     {
  195.         DosBeep( 1000, 100 );
  196.  
  197.         (void) fprintf( stderr, "WinInitialize failed!" );
  198.     }
  199.  
  200.     if( hmq )
  201.     {
  202.         ProgInit( hab );
  203.  
  204.         // CS_SIZEREDRAW needed for initial display of the container in the
  205.         // client window. Allocate enough extra bytes for 1 window word.
  206.  
  207.         fSuccess = WinRegisterClass( hab, DIRECTORY_WINCLASS, wpClient,
  208.                                      CS_SIZEREDRAW, sizeof( PVOID ) );
  209.     }
  210.     else
  211.     {
  212.         DosBeep( 1000, 100 );
  213.  
  214.         (void) fprintf( stderr, "WinCreateMsgQueue RC(%X)", HABERR( hab ) );
  215.     }
  216.  
  217.     if( fSuccess )
  218.  
  219.         // CreateDirectoryWin is in CREATE.C
  220.  
  221.         hwndFrame = CreateDirectoryWin( szStartingDir, NULLHANDLE, NULL );
  222.     else
  223.         Msg( "WinRegisterClass RC(%X)", HABERR( hab ) );
  224.  
  225.     if( hwndFrame )
  226.         while( WinGetMsg( hab, &qmsg, NULLHANDLE, 0, 0 ) )
  227.             (void) WinDispatchMsg( hab, &qmsg );
  228.  
  229.     if( hmq )
  230.         (void) WinDestroyMsgQueue( hmq );
  231.  
  232.     if( hab )
  233.         (void) WinTerminate( hab );
  234.  
  235.     ProgTerm( hab );
  236.  
  237. #ifdef __DEBUG_ALLOC__
  238.     _dump_allocated( -1 );
  239. #endif
  240.  
  241.     return 0;
  242. }
  243.  
  244. /**********************************************************************/
  245. /*----------------------------- ProgInit -----------------------------*/
  246. /*                                                                    */
  247. /*  PERFORM PROGRAM INITIALIZATION                                    */
  248. /*                                                                    */
  249. /*  INPUT: anchor block handle                                        */
  250. /*                                                                    */
  251. /*  1.                                                                */
  252. /*                                                                    */
  253. /*  OUTPUT: nothing                                                   */
  254. /*                                                                    */
  255. /*--------------------------------------------------------------------*/
  256. /**********************************************************************/
  257. static VOID ProgInit( HAB hab )
  258. {
  259.     HDC   hdc;
  260.     HPS   hps;
  261.     SIZEL sizl = {0,0};
  262.  
  263.     // fTrue will be used for all while( fTrue ) loops. The C Set/2++ compiler
  264.     // took away the ability to use while( TRUE ) and for( ; ; ) constructs.
  265.  
  266.     fTrue = TRUE;
  267.  
  268.     // Create the bitmap that will be used if the user selects Bitmap from the
  269.     // context menu's Background menu. It will be stored in a global variable.
  270.  
  271.     hdc = DevOpenDC( hab, OD_MEMORY, "*", 0L, NULL, NULLHANDLE );
  272.  
  273.     if( hdc != DEV_ERROR )
  274.     {
  275.          hps = GpiCreatePS( hab, hdc, &sizl, PU_PELS | GPIF_DEFAULT |
  276.                            GPIT_MICRO | GPIA_ASSOC );
  277.  
  278.         if( hps != GPI_ERROR )
  279.         {
  280.             hbmBackground = GpiLoadBitmap( hps, 0, ID_BMP_BACKGROUND, 0, 0 );
  281.  
  282.             if( hbmBackground == GPI_ERROR )
  283.             {
  284.                 hbmBackground = NULLHANDLE;
  285.  
  286.                 Msg( "ProgInit GpiLoadBitmap RC(%X)", HABERR( hab ) );
  287.             }
  288.  
  289.             if( !GpiDestroyPS( hps ) )
  290.                 Msg( "ProgInit GpiDestroyPS RC(%X)", HABERR( hab ) );
  291.         }
  292.         else
  293.             Msg( "ProgInit GpiCreatePS RC(%X)", HABERR( hab ) );
  294.  
  295.         if( DEV_ERROR == DevCloseDC( hdc ) )
  296.             Msg( "ProgInit DevCloseDC RC(%X)", HABERR( hab ) );
  297.     }
  298.     else
  299.         Msg( "ProgInit DevOpenDC RC(%X)", HABERR( hab ) );
  300. }
  301.  
  302. /**********************************************************************/
  303. /*---------------------------- wpClient ------------------------------*/
  304. /*                                                                    */
  305. /*  CLIENT WINDOW PROCEDURE FOR THE DIRECTORY WINDOW.                 */
  306. /*                                                                    */
  307. /*  NOTE: This window is created by CreateDirectoryWin in CREATE.C    */
  308. /*                                                                    */
  309. /*  INPUT: standard window procedure parameters                       */
  310. /*                                                                    */
  311. /*  1.                                                                */
  312. /*                                                                    */
  313. /*  OUTPUT: result of message processing                              */
  314. /*                                                                    */
  315. /*--------------------------------------------------------------------*/
  316. /**********************************************************************/
  317. MRESULT EXPENTRY wpClient( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
  318. {
  319.     // Process all DM_ messages in drag.c
  320.  
  321.     if( msg >= WM_DRAGFIRST && msg <= WM_DRAGLAST )
  322.         return DragMessage( hwnd, msg, mp1, mp2 );
  323.  
  324.     switch( msg )
  325.     {
  326.         case WM_CREATE:
  327.  
  328.             // If window initialization fails, don't create window
  329.  
  330.             if( InitClient( hwnd, (PWINCREATE) mp1 ) )
  331.             {
  332.                 iWinCount++;
  333.  
  334.                 break;
  335.             }
  336.             else
  337.                 return (MRESULT) TRUE;
  338.  
  339.  
  340.         case WM_SIZE:
  341.  
  342.             // Size the container with the client window
  343.  
  344.             if( !WinSetWindowPos( WinWindowFromID( hwnd, CNR_DIRECTORY ),
  345.                                   NULLHANDLE, 0, 0, SHORT1FROMMP( mp2 ),
  346.                                   SHORT2FROMMP( mp2 ), SWP_MOVE | SWP_SIZE ) )
  347.                 Msg( "WM_SIZE WinSetWindowPos RC(%X)", HWNDERR( hwnd ) );
  348.  
  349.             return 0;
  350.  
  351.  
  352.         case WM_COMMAND:    // Context Menu messages (in ctxtmenu.c)
  353.  
  354.             CtxtmenuCommand( hwnd, SHORT1FROMMP( mp1 ), SHORT1FROMMP( mp2 ) );
  355.  
  356.             return 0;
  357.  
  358.  
  359.         case WM_CONTROL:
  360.  
  361.             return wmControl( hwnd, mp1, mp2 );
  362.  
  363.  
  364.         case WM_DRAWITEM:
  365.  
  366.             // In draw.c
  367.  
  368.             return DrawItem( hwnd, (POWNERITEM) mp2 );
  369.  
  370.  
  371.         case WM_MENUEND:
  372.  
  373.             // This function in ctxtmenu.c. Interestingly enough, even though
  374.             // we give the menu the id of ID_CONTEXT_MENU, the ID that is
  375.             // actually assigned to the popup menu as a whole is FID_MENU.
  376.             // Since we get WM_MENUEND messages for the submenus of the popup
  377.             // also and we only care when the whole popup is gone, just call
  378.             // this function if it is the popup menu.
  379.  
  380.             if( SHORT1FROMMP( mp1 ) == FID_MENU )
  381.             {
  382.                 CtxtmenuEnd( hwnd );
  383.  
  384.                 // Destroy the window so its resources are freed up for the next
  385.                 // time we do a WinLoadMenu in ctxtmenu.c
  386.  
  387.                 if( !WinDestroyWindow( (HWND) mp2 ) )
  388.                     Msg( "WM_MENUEND WinDestroyWindow RC(%X)", HWNDERR( hwnd ));
  389.             }
  390.  
  391.             break;
  392.  
  393.  
  394.         case WM_CLOSE:
  395.  
  396.             // Don't let the WM_QUIT message get posted. *We* will decide
  397.             // when to shut down the message queue.
  398.  
  399.             UserWantsToClose( hwnd );
  400.  
  401.             return 0;
  402.  
  403.  
  404.         case WM_DESTROY:
  405.  
  406.             FreeResources( hwnd );
  407.  
  408.             // If this is the last window open, shut down the message queue
  409.             // which will kill the process.
  410.  
  411.             if( --iWinCount == 0 )
  412.                 (void) WinPostMsg( NULLHANDLE, WM_QUIT, NULL, NULL );
  413.  
  414.             break;
  415.  
  416.  
  417.         case UM_CONTAINER_FILLED:
  418.  
  419.             // This message is posted to us by the thread that fills the
  420.             // container with records. This indicates that the container is
  421.             // now filled. Posted in populate.c.
  422.  
  423.             ContainerFilled( hwnd );
  424.  
  425.             return 0;
  426.     }
  427.  
  428.     return WinDefWindowProc( hwnd, msg, mp1, mp2 );
  429. }
  430.  
  431. /**********************************************************************/
  432. /*--------------------------- InitClient -----------------------------*/
  433. /*                                                                    */
  434. /*  PROCESS WM_CREATE FOR THE CLIENT WINDOW.                          */
  435. /*                                                                    */
  436. /*  INPUT: client window handle,                                      */
  437. /*         pointer to window creation parameters                      */
  438. /*                                                                    */
  439. /*  1.                                                                */
  440. /*                                                                    */
  441. /*  OUTPUT: TRUE or FALSE if successful or not                        */
  442. /*                                                                    */
  443. /*--------------------------------------------------------------------*/
  444. /**********************************************************************/
  445. static BOOL InitClient( HWND hwndClient, PWINCREATE pwc )
  446. {
  447.     BOOL      fSuccess = TRUE;
  448.     PINSTANCE pi = (PINSTANCE) malloc( sizeof( INSTANCE ) );
  449.  
  450.     if( pi )
  451.     {
  452.         (void) memset( pi, 0, sizeof( INSTANCE ) );
  453.  
  454.         if( WinSetWindowPtr( hwndClient, 0, pi ) )
  455.         {
  456.             // CreateContainer is located in CREATE.C
  457.  
  458.             HWND hwndCnr = CreateContainer( hwndClient, pwc->szDirectory,
  459.                                             pwc->hwndCnrShare, pwc->pciParent );
  460.  
  461.             if( hwndCnr )
  462.             {
  463.                 // Set the initial container view to a default view. This
  464.                 // function is in CTXTMENU.C
  465.  
  466.                 CtxtmenuSetView( hwndClient, DEFAULT_VIEW );
  467.  
  468.                 // Set default background color of container to be white. The
  469.                 // user can change this via the context menu.
  470.  
  471.                 pi->clrBackground = CLR_WHITE;
  472.             }
  473.             else
  474.                 fSuccess = FALSE;
  475.  
  476.             // This was allocated in create.c in the CreateDirectoryWin function
  477.  
  478.             free( pwc );
  479.         }
  480.         else
  481.         {
  482.             fSuccess = FALSE;
  483.  
  484.             Msg( "InitClient WinSetWindowPtr RC(%X)", HWNDERR( hwndClient ) );
  485.         }
  486.     }
  487.     else
  488.     {
  489.         fSuccess = FALSE;
  490.  
  491.         Msg( "InitClient out of memory!" );
  492.     }
  493.  
  494.     return fSuccess;
  495. }
  496.  
  497. /**********************************************************************/
  498. /*---------------------------- wmControl -----------------------------*/
  499. /*                                                                    */
  500. /*  PROCESS WM_CONTROL MESSAGES FOR THE CLIENT WINDOW.                */
  501. /*                                                                    */
  502. /*  INPUT: client window handle,                                      */
  503. /*         notify code,                                               */
  504. /*         2nd WM_CONTROL message parameter                           */
  505. /*                                                                    */
  506. /*  1.                                                                */
  507. /*                                                                    */
  508. /*  OUTPUT: return code from message                                  */
  509. /*                                                                    */
  510. /*--------------------------------------------------------------------*/
  511. /**********************************************************************/
  512. static MRESULT wmControl( HWND hwndClient, MPARAM mp1, MPARAM mp2 )
  513. {
  514.     USHORT usNotifyCode = SHORT2FROMMP( mp1 );
  515.  
  516.     switch( usNotifyCode )
  517.     {
  518.         case CN_ENTER:
  519.  
  520.             RecordSelected( hwndClient, (PNOTIFYRECORDENTER) mp2 );
  521.  
  522.             return 0;
  523.  
  524.  
  525.         case CN_CONTEXTMENU:
  526.  
  527.             // In ctxtmenu.c
  528.  
  529.             CtxtmenuCreate( hwndClient, (PCNRITEM) mp2 );
  530.  
  531.             return 0;
  532.  
  533.  
  534.         case CN_BEGINEDIT:
  535.  
  536.             // In edit.c
  537.  
  538.             EditBegin( hwndClient, (PCNREDITDATA) mp2 );
  539.  
  540.             return 0;
  541.  
  542.  
  543.         case CN_ENDEDIT:
  544.  
  545.             // In edit.c
  546.  
  547.             EditEnd( hwndClient, (PCNREDITDATA) mp2 );
  548.  
  549.             return 0;
  550.  
  551.  
  552.         case CN_INITDRAG:
  553.  
  554.             // In drag.c
  555.  
  556.             DragInit( hwndClient, (PCNRDRAGINIT) mp2 );
  557.  
  558.             return 0;
  559.  
  560.  
  561.         case CN_DRAGAFTER:
  562.         case CN_DRAGOVER:
  563.  
  564.             // In drag.c
  565.  
  566.             return DragOver( hwndClient, (PCNRDRAGINFO) mp2 );
  567.  
  568.  
  569.         case CN_DROP:
  570.  
  571.             // In drag.c
  572.  
  573.             DragDrop( hwndClient, (PCNRDRAGINFO) mp2 );
  574.  
  575.             return 0;
  576.     }
  577.  
  578.     return WinDefWindowProc( hwndClient, WM_CONTROL, mp1, mp2 );
  579. }
  580.  
  581. /**********************************************************************/
  582. /*-------------------------- RecordSelected --------------------------*/
  583. /*                                                                    */
  584. /*  PROCESS CN_ENTER NOTIFY MESSAGE.                                  */
  585. /*                                                                    */
  586. /*  INPUT: client window handle,                                      */
  587. /*         pointer to the NOTIFYRECORDENTER structure                 */
  588. /*                                                                    */
  589. /*  1.                                                                */
  590. /*                                                                    */
  591. /*  OUTPUT: nothing                                                   */
  592. /*                                                                    */
  593. /*--------------------------------------------------------------------*/
  594. /**********************************************************************/
  595. static VOID RecordSelected( HWND hwndClient, PNOTIFYRECORDENTER pnre )
  596. {
  597.     PCNRITEM  pci = (PCNRITEM) pnre->pRecord;
  598.     PINSTANCE pi = INSTDATA( hwndClient );
  599.  
  600.     if( !pi )
  601.     {
  602.         Msg( "RecordSelected cant get Inst data. RC(%X)", HWNDERR(hwndClient) );
  603.  
  604.         return;
  605.     }
  606.  
  607.     // If the user selected a directory, create another directory window for it.
  608.     // Don't do anything if the directory is '..' (parent directory) or '.'
  609.     // (current directory) as this program is not equipped to handle them.
  610.  
  611.     if( pci && (pci->attrFile & FILE_DIRECTORY) && pci->szFileName[0] != '.' )
  612.     {
  613.         // Set the selected CNRITEM container record so other functions can get
  614.         // at it.
  615.  
  616.         pi->pciSelected = pci;
  617.  
  618.         // Simulate a IDM_CREATE_NEWWIN menuitem being selected. This allows
  619.         // us to reuse the code that is processed when that menu item is pressed
  620.         // Specify CMDSRC_OTHER so the code that processes the IDM_CREATE_NEWWIN
  621.         // message can differentiate this message from one legitimately sent
  622.         // from the context menu.
  623.  
  624.         WinSendMsg( hwndClient, WM_COMMAND,
  625.                     MPFROM2SHORT( IDM_CREATE_NEWWIN, 0 ),
  626.                     MPFROM2SHORT( CMDSRC_OTHER, 0 ) );
  627.     }
  628. }
  629.  
  630. /**********************************************************************/
  631. /*------------------------- ContainerFilled --------------------------*/
  632. /*                                                                    */
  633. /*  THE FILL THREAD HAS COMPLETED.                                    */
  634. /*                                                                    */
  635. /*  INPUT: client window handle                                       */
  636. /*                                                                    */
  637. /*  1.                                                                */
  638. /*                                                                    */
  639. /*  OUTPUT: nothing                                                   */
  640. /*                                                                    */
  641. /*--------------------------------------------------------------------*/
  642. /**********************************************************************/
  643. static VOID ContainerFilled( HWND hwndClient )
  644. {
  645.     PINSTANCE pi = INSTDATA( hwndClient );
  646.  
  647.     if( !pi )
  648.     {
  649.         Msg( "ContainerFilled cant get Inst data. RC(%X)", HWNDERR(hwndClient));
  650.  
  651.         return;
  652.     }
  653.  
  654.     // If the user closed the window while the Fill thread was executing, we
  655.     // want to shut down this window now.
  656.  
  657.     if( pi->fShutdown )
  658.         WinDestroyWindow( PARENT( hwndClient ) );
  659.     else
  660.     {
  661.         // Set a flag so the window will know the Fill thread has finished
  662.  
  663.         pi->fContainerFilled = TRUE;
  664.  
  665.         // Set the titlebar to the program title. We do this because while
  666.         // the container was being filled, the titlebar text was changed
  667.         // to indicate progress.
  668.  
  669.         SetWindowTitle( hwndClient, "%s [%s]", PROGRAM_TITLE, pi->szDirectory );
  670.     }
  671. }
  672.  
  673. /**********************************************************************/
  674. /*------------------------- UserWantsToClose -------------------------*/
  675. /*                                                                    */
  676. /*  PROCESS THE WM_CLOSE MESSAGE.                                     */
  677. /*                                                                    */
  678. /*  INPUT: client window handle                                       */
  679. /*                                                                    */
  680. /*  1.                                                                */
  681. /*                                                                    */
  682. /*  OUTPUT: nothing                                                   */
  683. /*                                                                    */
  684. /*--------------------------------------------------------------------*/
  685. /**********************************************************************/
  686. static VOID UserWantsToClose( HWND hwndClient )
  687. {
  688.     PINSTANCE pi = INSTDATA( hwndClient );
  689.  
  690.     if( !pi )
  691.     {
  692.         Msg( "UserWantsToClose cant get Inst data. RC(%X)",HWNDERR(hwndClient));
  693.  
  694.         return;
  695.     }
  696.  
  697.     // If the Fill thread has completed, destroy the frame window.
  698.     // If the Fill thread has not completed, set a flag that will cause it to
  699.     // terminate, then the destroy will occur under the UM_CONTAINER_FILLED
  700.     // message.
  701.  
  702.     if( pi->fContainerFilled )
  703.         WinDestroyWindow( PARENT( hwndClient ) );
  704.     else
  705.     {
  706.         // Indicate in the titlebar that the window is in the process of
  707.         // closing.
  708.  
  709.         SetWindowTitle( hwndClient, "%s: CLOSING...", PROGRAM_TITLE );
  710.  
  711.         // Set a flag that will tell the Fill thread to shut down
  712.  
  713.         pi->fShutdown = TRUE;
  714.     }
  715. }
  716.  
  717. /**********************************************************************/
  718. /*-------------------------- FreeResources ---------------------------*/
  719. /*                                                                    */
  720. /*  FREE PROGRAM RESOURCES.                                           */
  721. /*                                                                    */
  722. /*  INPUT: client window handle                                       */
  723. /*                                                                    */
  724. /*  1.                                                                */
  725. /*                                                                    */
  726. /*  OUTPUT: nothing                                                   */
  727. /*                                                                    */
  728. /*--------------------------------------------------------------------*/
  729. /**********************************************************************/
  730. static VOID FreeResources( HWND hwndClient )
  731. {
  732.     PINSTANCE pi = INSTDATA( hwndClient );
  733.  
  734.     if( pi )
  735.         free( pi );
  736.     else
  737.         Msg( "FreeResources cant get Inst data. RC(%X)", HWNDERR( hwndClient ));
  738.  
  739.     // Free the memory that was allocated with CM_ALLOCDETAILFIELDINFO. The
  740.     // zero in the first SHORT of mp2 says to free memory for all columns
  741.  
  742.     if( -1 == (INT) WinSendDlgItemMsg( hwndClient, CNR_DIRECTORY,
  743.                                        CM_REMOVEDETAILFIELDINFO, NULL,
  744.                                        MPFROM2SHORT( 0, CMA_FREE ) ) )
  745.         Msg( "CM_REMOVEDETAILFIELDINFO failed! RC(%X)", HWNDERR( hwndClient ) );
  746.  
  747.     // Free the memory allocated by the CM_INSERTRECORD messages. The zero
  748.     // in the first SHORT of mp2 says to free memory for all records
  749.  
  750.     if( -1 == (INT) WinSendDlgItemMsg( hwndClient, CNR_DIRECTORY,
  751.                                        CM_REMOVERECORD, NULL,
  752.                                        MPFROM2SHORT( 0, CMA_FREE ) ) )
  753.         Msg( "CM_REMOVERECORD failed! RC(%X)", HWNDERR( hwndClient ) );
  754. }
  755.  
  756. /**********************************************************************/
  757. /*----------------------------- ProgTerm -----------------------------*/
  758. /*                                                                    */
  759. /*  PERFORM PROGRAM TERMINATION                                       */
  760. /*                                                                    */
  761. /*  INPUT: anchor block handle                                        */
  762. /*                                                                    */
  763. /*  1.                                                                */
  764. /*                                                                    */
  765. /*  OUTPUT: nothing                                                   */
  766. /*                                                                    */
  767. /*--------------------------------------------------------------------*/
  768. /**********************************************************************/
  769. static VOID ProgTerm( HAB hab )
  770. {
  771.     if( hbmBackground )
  772.         if( !GpiDeleteBitmap( hbmBackground ) )
  773.             Msg( "ProgTerm GpiDeleteBitmap RC(%X)", HABERR( hab ) );
  774. }
  775.  
  776. /*************************************************************************
  777.  *                     E N D     O F     S O U R C E                     *
  778.  ************************************************* ************************/
  779.