home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / cnradv.zip / CREATE.C < prev    next >
C/C++ Source or Header  |  1993-06-06  |  22KB  |  495 lines

  1. /*********************************************************************
  2.  *                                                                   *
  3.  * MODULE NAME :  create.c               AUTHOR:  Rick Fishman       *
  4.  * DATE WRITTEN:  11-30-92                                           *
  5.  *                                                                   *
  6.  * DESCRIPTION:                                                      *
  7.  *                                                                   *
  8.  *  This module is part of CNRADV.EXE. It performs the function of   *
  9.  *  creating the container window and starting a thread that will    *
  10.  *  populate the window with file icons.                             *
  11.  *                                                                   *
  12.  *  The primary purpose of this module is to create the container    *
  13.  *  and set it up to be able to switch views easily. This is         *
  14.  *  accomplished by creating the column definitions for the Details  *
  15.  *  view. The Details view is really the only view that requires     *
  16.  *  any substantial setup.                                           *
  17.  *                                                                   *
  18.  *  We also set the base directory here. This directory will be      *
  19.  *  traversed in the PopulateContainer thread as will all its        *
  20.  *  subdirectories. If the user entered a directory name on the      *
  21.  *  command line we don't need to do anything. If not, we get the    *
  22.  *  current drive and directory and use it as the base.              *
  23.  *                                                                   *
  24.  * CALLABLE FUNCTIONS:                                               *
  25.  *                                                                   *
  26.  *   HWND CreateDirectoryWin( PSZ szDirectory, PCNRITEM pciParent ); *
  27.  *   HWND CreateContainer( HWND hwndClient, PSZ szDirectory );       *
  28.  *                                                                   *
  29.  * HISTORY:                                                          *
  30.  *                                                                   *
  31.  *  11-30-92 - Source copied from CNRMENU.EXE sample.                *
  32.  *             Added FCF_ICON to frame flags.                        *
  33.  *  12-05-92 - Added call to DrawSubclassCnr in CreateContainer.     *
  34.  *             Created a static FIELDINFO initializer array.         *
  35.  *             Used the initializer array in SetContainerColumns.    *
  36.  *             Added Attributes column to demonstrate Ownerdraw.     *
  37.  *  06-06-93 - Added WinSetFocus to container after window creation. *
  38.  *                                                                   *
  39.  *  Rick Fishman                                                     *
  40.  *  Code Blazers, Inc.                                               *
  41.  *  4113 Apricot                                                     *
  42.  *  Irvine, CA. 92720                                                *
  43.  *  CIS ID: 72251,750                                                *
  44.  *                                                                   *
  45.  *********************************************************************/
  46.  
  47. #pragma strings(readonly)   // used for debug version of memory mgmt routines
  48.  
  49. /*********************************************************************/
  50. /*------- Include relevant sections of the OS/2 header files --------*/
  51. /*********************************************************************/
  52.  
  53. #define  INCL_WINERRORS
  54. #define  INCL_WINFRAMEMGR
  55. #define  INCL_WINMENUS
  56. #define  INCL_WINSTDCNR
  57. #define  INCL_WINWINDOWMGR
  58.  
  59. /**********************************************************************/
  60. /*----------------------------- INCLUDES -----------------------------*/
  61. /**********************************************************************/
  62.  
  63. #include <os2.h>
  64. #include <process.h>
  65. #include <stdarg.h>
  66. #include <stddef.h>
  67. #include <stdio.h>
  68. #include <stdlib.h>
  69. #include <string.h>
  70. #include "cnradv.h"
  71.  
  72. /*********************************************************************/
  73. /*------------------- APPLICATION DEFINITIONS -----------------------*/
  74. /*********************************************************************/
  75.  
  76. #define FRAME_FLAGS         (FCF_TASKLIST | FCF_TITLEBAR   | FCF_SYSMENU | \
  77.                              FCF_MINMAX   | FCF_SIZEBORDER | FCF_ICON    | \
  78.                              FCF_SHELLPOSITION)
  79.  
  80. #define SPLITBAR_OFFSET     150         // Pixel offset of details splitbar
  81.  
  82. #define THREAD_STACKSIZE    65536       // Stacksize for secondary thread
  83.  
  84. /**********************************************************************/
  85. /*---------------------------- STRUCTURES ----------------------------*/
  86. /**********************************************************************/
  87.  
  88. /**********************************************************************/
  89. /*----------------------- FUNCTION PROTOTYPES ------------------------*/
  90. /**********************************************************************/
  91.  
  92. static BOOL SetContainerColumns  ( HWND hwndCnr );
  93. static VOID GetCurrentDirectory  ( PSZ pszDirectory );
  94. static VOID UseCmdLineDirectory  ( PSZ pszDirectoryOut, PSZ szDirectoryIn );
  95.  
  96. /**********************************************************************/
  97. /*------------------------ GLOBAL VARIABLES --------------------------*/
  98. /**********************************************************************/
  99.  
  100. FIELDINFO fldinfo[] =    // INFORMATION ABOUT EACH CONTAINER COLUMN
  101. {
  102.     { 0, CFA_BITMAPORICON | CFA_CENTER | CFA_HORZSEPARATOR | CFA_SEPARATOR,
  103.       CFA_CENTER | CFA_FITITLEREADONLY, "Icon",
  104.       offsetof( CNRITEM, rc.hptrIcon ), (PVOID) ICON_COLUMN },
  105.  
  106.     { 0, CFA_STRING | CFA_LEFT | CFA_HORZSEPARATOR,
  107.       CFA_CENTER | CFA_FITITLEREADONLY, "File Name",
  108.       offsetof( CNRITEM, rc.pszIcon ), (PVOID) FILENAME_COLUMN },
  109.  
  110.     { 0, CFA_ULONG | CFA_RIGHT | CFA_HORZSEPARATOR | CFA_SEPARATOR,
  111.       CFA_CENTER | CFA_FITITLEREADONLY, "File Size",
  112.       offsetof( CNRITEM, cbFile ), (PVOID) FILESIZE_COLUMN },
  113.  
  114.     { 0, CFA_DATE | CFA_RIGHT | CFA_HORZSEPARATOR | CFA_SEPARATOR,
  115.       CFA_CENTER | CFA_FITITLEREADONLY, "Date",
  116.       offsetof( CNRITEM, date ), (PVOID) DATE_COLUMN },
  117.  
  118.     { 0, CFA_TIME | CFA_RIGHT | CFA_HORZSEPARATOR | CFA_SEPARATOR,
  119.       CFA_CENTER | CFA_FITITLEREADONLY, "Time",
  120.       offsetof( CNRITEM, time ), (PVOID) TIME_COLUMN },
  121.  
  122.     { 0, CFA_OWNER | CFA_HORZSEPARATOR,
  123.       CFA_CENTER | CFA_FITITLEREADONLY, "Attributes\n(Ownerdraw)",
  124.       0, (PVOID) FILEATTR_COLUMN }
  125. };
  126.  
  127. #define COLUMN_COUNT (sizeof( fldinfo ) / sizeof( FIELDINFO ))
  128.  
  129. /**********************************************************************/
  130. /*----------------------- CreateDirectoryWin -------------------------*/
  131. /*                                                                    */
  132. /*  CREATE A DIRECTORY WINDOW MADE UP OF FRAME/CLIENT/CONTAINER.      */
  133. /*                                                                    */
  134. /*  INPUT: directory to represent in the window,                      */
  135. /*         window handle with which to share records, or NULLHANDLE,  */
  136. /*         pointer to CNRITEM if using shared records, or NULL        */
  137. /*                                                                    */
  138. /*  1.                                                                */
  139. /*                                                                    */
  140. /*  OUTPUT: window handle of created frame or NULLHANDLE if error     */
  141. /*                                                                    */
  142. /*--------------------------------------------------------------------*/
  143. /**********************************************************************/
  144. HWND CreateDirectoryWin( PSZ szDirectory, HWND hwndCnrShare, PCNRITEM pciParent)
  145. {
  146.     FRAMECDATA  fcdata;
  147.     HWND        hwndFrame, hwndClient = NULLHANDLE;
  148.  
  149.     (void) memset( &fcdata, 0, sizeof( FRAMECDATA ) );
  150.  
  151.     fcdata.cb               = sizeof( FRAMECDATA );
  152.     fcdata.flCreateFlags    = FRAME_FLAGS;
  153.     fcdata.idResources      = ID_RESOURCES;
  154.  
  155.     // Create the frame window. If we were creating multiple instances of
  156.     // this window, iWinCount would become useful.
  157.  
  158.     hwndFrame = WinCreateWindow( HWND_DESKTOP, WC_FRAME, NULL, 0, 0, 0, 0, 0,
  159.                                  NULLHANDLE, HWND_TOP,
  160.                                  ID_FIRST_DIRWINDOW + iWinCount, &fcdata,
  161.                                  NULL );
  162.  
  163.     // Create the client window which will create the container in its
  164.     // WM_CREATE processing. If that fails, hwndClient will be NULLHANDLE.
  165.     // We pass parameters in the CTLDATA parameter which will be received by the
  166.     // client in mp1 on WM_CREATE.
  167.  
  168.     if( hwndFrame )
  169.     {
  170.         // This memory block will be freed after WM_CREATE processing is
  171.         // complete by InitClient in cnradv.c
  172.  
  173.         PWINCREATE pwc = (PWINCREATE) malloc( sizeof( WINCREATE ) );
  174.  
  175.         if( pwc )
  176.         {
  177.             pwc->szDirectory  = szDirectory;
  178.             pwc->hwndCnrShare = hwndCnrShare;
  179.             pwc->pciParent    = pciParent;
  180.  
  181.             hwndClient = WinCreateWindow( hwndFrame, DIRECTORY_WINCLASS, NULL,
  182.                                           0, 0, 0, 0, 0, NULLHANDLE, HWND_TOP,
  183.                                           FID_CLIENT, pwc, NULL );
  184.         }
  185.         else
  186.             Msg( "Out of memory in CreateContainer!" );
  187.     }
  188.  
  189.     if( hwndClient )
  190.     {
  191.         // Show the frame window (it was created invisible)
  192.  
  193.         if( !WinSetWindowPos( hwndFrame, HWND_TOP, 0, 0, 0, 0,
  194.                               SWP_SHOW | SWP_ACTIVATE | SWP_ZORDER ) )
  195.         {
  196.             hwndFrame = NULLHANDLE;
  197.  
  198.             Msg( "hwndFrame WinSetWindowPos RC(%X)", HWNDERR( hwndClient ) );
  199.         }
  200.  
  201.         // Set focus to the container within the client window. Otherwise the
  202.         // user would have to click on the container first before using the
  203.         // keyboard.
  204.  
  205.         WinSetFocus( HWND_DESKTOP, WinWindowFromID(hwndClient, CNR_DIRECTORY));
  206.     }
  207.     else
  208.         hwndFrame = NULLHANDLE;
  209.  
  210.     return hwndFrame;
  211. }
  212.  
  213. /**********************************************************************/
  214. /*------------------------- CreateContainer --------------------------*/
  215. /*                                                                    */
  216. /*  CREATE THE CONTAINER AND CUSTOMIZE IT.                            */
  217. /*                                                                    */
  218. /*  INPUT: client window handle,                                      */
  219. /*         directory to display in the container,                     */
  220. /*         window handle with which to share records, or NULLHANDLE,  */
  221. /*         pointer to CNRITEM if using shared records, or NULL        */
  222. /*                                                                    */
  223. /*  1.                                                                */
  224. /*                                                                    */
  225. /*  OUTPUT: Container window handle                                   */
  226. /*                                                                    */
  227. /*--------------------------------------------------------------------*/
  228. /**********************************************************************/
  229. HWND CreateContainer( HWND hwndClient, PSZ szDirectory, HWND hwndCnrShare,
  230.                       PCNRITEM pciParent )
  231. {
  232.     PINSTANCE pi = INSTDATA( hwndClient );
  233.     HWND      hwndCnr = NULLHANDLE;
  234.  
  235.     if( !pi )
  236.     {
  237.         Msg( "CreateContainer cant get Inst data. RC(%X)", HWNDERR(hwndClient));
  238.  
  239.         return NULLHANDLE;
  240.     }
  241.  
  242.     // Create the container control. Indicate that we want to use
  243.     // MINIRECORDCORE structures rather than RECORDCORE structures. This
  244.     // saves memory. Also allow extended selection which essentially lets the
  245.     // user select multiple items. Allow the use of mini icons.
  246.  
  247.     hwndCnr = WinCreateWindow( hwndClient, WC_CONTAINER, NULL,
  248.                                CCS_EXTENDSEL | CCS_MINIRECORDCORE |
  249.                                CCS_MINIICONS | WS_VISIBLE,
  250.                                0, 0, 0, 0, hwndClient, HWND_TOP, CNR_DIRECTORY,
  251.                                NULL, NULL);
  252.  
  253.     if( hwndCnr )
  254.     {
  255.         // Subclass the container to get the CM_PAINTBACKGROUND message
  256.         // (function is in draw.c)
  257.  
  258.         DrawSubclassCnr( hwndClient );
  259.  
  260.         if( SetContainerColumns( hwndCnr ) )
  261.         {
  262.             // Start the thread that will populate the container. Allocate
  263.             // memory to pass the thread a structure of data.
  264.  
  265.             PTHREADPARMS ptp = malloc( sizeof( THREADPARMS ) );
  266.  
  267.             if( ptp )
  268.             {
  269.                 TID tid = 0;
  270.  
  271.                 ptp->hwndClient     = hwndClient;
  272.                 ptp->hwndCnrShare   = hwndCnrShare;
  273.                 ptp->pciParent      = pciParent;
  274.  
  275.                 // If no directory was passed to us, assume that the current
  276.                 // directory is to be displayed.
  277.  
  278.                 if( !szDirectory )
  279.                     GetCurrentDirectory( pi->szDirectory );
  280.                 else
  281.                     UseCmdLineDirectory( pi->szDirectory, szDirectory );
  282.  
  283.                 SetWindowTitle( hwndClient, "%s: Processing %s...",
  284.                                 PROGRAM_TITLE, pi->szDirectory );
  285.  
  286.                 // Start the thread that will populate the container with
  287.                 // file icons. This is a separate thread because it could
  288.                 // take a while if there are many subdirectories.
  289.  
  290.                 tid = _beginthread( PopulateContainer, NULL,
  291.                                     THREAD_STACKSIZE, (PVOID) ptp );
  292.  
  293.                 if( (INT) tid == -1 )
  294.                     Msg( "Cant start PopulateContainer thread!" );
  295.             }
  296.             else
  297.             {
  298.                 hwndCnr = NULLHANDLE;
  299.  
  300.                 Msg( "Out of Memory in CreateContainer!" );
  301.             }
  302.         }
  303.         else
  304.             hwndCnr = NULLHANDLE;
  305.     }
  306.     else
  307.         Msg( "Couldnt create container. RC(%X)", HWNDERR( hwndClient ) );
  308.  
  309.     return hwndCnr;
  310. }
  311.  
  312. /**********************************************************************/
  313. /*----------------------- SetContainerColumns ------------------------*/
  314. /*                                                                    */
  315. /*  SET THE COLUMNS OF THE CONTAINER FOR DETAIL VIEW                  */
  316. /*                                                                    */
  317. /*  INPUT: container window handle                                    */
  318. /*                                                                    */
  319. /*  1.                                                                */
  320. /*                                                                    */
  321. /*  OUTPUT: TRUE or FALSE if successful or not                        */
  322. /*                                                                    */
  323. /*--------------------------------------------------------------------*/
  324. /**********************************************************************/
  325. static BOOL SetContainerColumns( HWND hwndCnr )
  326. {
  327.     BOOL        fSuccess = TRUE;
  328.     PFIELDINFO  pfi, pfiLastLeftCol;
  329.  
  330.     // Allocate storage for container column data
  331.  
  332.     pfi = WinSendMsg( hwndCnr, CM_ALLOCDETAILFIELDINFO,
  333.                       MPFROMLONG( COLUMN_COUNT ), NULL );
  334.  
  335.     if( pfi )
  336.     {
  337.         PFIELDINFO      pfiFirst;
  338.         FIELDINFOINSERT fii;
  339.         INT             i;
  340.  
  341.         // Store original value of pfi so we won't lose it when it changes.
  342.         // This will be needed on the CM_INSERTDETAILFIELDINFO message.
  343.  
  344.         pfiFirst = pfi;
  345.  
  346.         // Fill in the column information from a static array at the top of
  347.         // this module
  348.  
  349.         for( i = 0; i < COLUMN_COUNT; i++ )
  350.         {
  351.             // Fill in values that were returned from CM_ALLOCDETAILFIELDINFO
  352.  
  353.             fldinfo[ i ].cb = pfi->cb;
  354.  
  355.             fldinfo[ i ].pNextFieldInfo = pfi->pNextFieldInfo;
  356.  
  357.             // Copy filled-in structure to container memory
  358.  
  359.             *pfi = fldinfo[ i ];
  360.  
  361.             // The last column before the splitbar is the filename column
  362.  
  363.             if( pfi->offStruct == FIELDOFFSET( CNRITEM, rc.pszIcon ) )
  364.                 pfiLastLeftCol = pfi;
  365.  
  366.             pfi = pfi->pNextFieldInfo;
  367.         }
  368.  
  369.         // Use the CM_INSERTDETAILFIELDINFO message to tell the container
  370.         // all the column information it needs to function properly. Place
  371.         // this column info first in the column list and update the display
  372.         // after they are inserted (fInvalidateFieldInfo = TRUE)
  373.  
  374.         (void) memset( &fii, 0, sizeof( FIELDINFOINSERT ) );
  375.  
  376.         fii.cb                   = sizeof( FIELDINFOINSERT );
  377.         fii.pFieldInfoOrder      = (PFIELDINFO) CMA_FIRST;
  378.         fii.cFieldInfoInsert     = (SHORT) COLUMN_COUNT;
  379.         fii.fInvalidateFieldInfo = TRUE;
  380.  
  381.         if( !WinSendMsg( hwndCnr, CM_INSERTDETAILFIELDINFO, MPFROMP( pfiFirst ),
  382.                          MPFROMP( &fii ) ) )
  383.         {
  384.             fSuccess = FALSE;
  385.  
  386.             Msg( "CM_INSERTDETAILFIELDINFO RC(%X)", HWNDERR( hwndCnr ) );
  387.         }
  388.     }
  389.     else
  390.     {
  391.         fSuccess = FALSE;
  392.  
  393.         Msg( "CM_ALLOCDETAILFIELDINFO failed. RC(%X)", HWNDERR( hwndCnr ) );
  394.     }
  395.  
  396.     if( fSuccess )
  397.     {
  398.         CNRINFO cnri;
  399.  
  400.         // Tell the container about the splitbar and where it goes
  401.  
  402.         cnri.cb             = sizeof( CNRINFO );
  403.         cnri.pFieldInfoLast = pfiLastLeftCol;
  404.         cnri.xVertSplitbar  = SPLITBAR_OFFSET;
  405.  
  406.         if( !WinSendMsg( hwndCnr, CM_SETCNRINFO, MPFROMP( &cnri ),
  407.                         MPFROMLONG( CMA_PFIELDINFOLAST | CMA_XVERTSPLITBAR ) ) )
  408.         {
  409.             fSuccess = FALSE;
  410.  
  411.             Msg( "SetContainerColumns CM_SETCNRINFO RC(%X)", HWNDERR(hwndCnr) );
  412.         }
  413.     }
  414.  
  415.     return fSuccess;
  416. }
  417.  
  418. /**********************************************************************/
  419. /*----------------------- GetCurrentDirectory ------------------------*/
  420. /*                                                                    */
  421. /*  GET THE CURRENT DIRECTORY AND STORE IT.                           */
  422. /*                                                                    */
  423. /*  INPUT: pointer to buffer in which to place path info              */
  424. /*                                                                    */
  425. /*  1.                                                                */
  426. /*                                                                    */
  427. /*  OUTPUT: nothing                                                   */
  428. /*                                                                    */
  429. /*--------------------------------------------------------------------*/
  430. /**********************************************************************/
  431. static VOID GetCurrentDirectory( PSZ pszDirectory )
  432. {
  433.     ULONG  cbDirPath = CCHMAXPATH;
  434.     APIRET rc;
  435.     ULONG  ulCurrDrive, ulDrvMap;
  436.  
  437.     // Set up the "d:\" string to which we will add the current directory.
  438.     // If we can get the current drive number, use it. Otherwise default to
  439.     // C:
  440.  
  441.     rc = DosQueryCurrentDisk( &ulCurrDrive, &ulDrvMap );
  442.  
  443.     if( !rc )
  444.     {
  445.         pszDirectory[ 0 ] = ulCurrDrive + ('A' - 1);
  446.  
  447.         (void) strcpy( pszDirectory + 1, ":\\" );
  448.     }
  449.     else
  450.         (void) strcpy( pszDirectory, "C:\\" );
  451.  
  452.     rc = DosQueryCurrentDir( 0, pszDirectory + 3, &cbDirPath );
  453.  
  454.     // If good retcode, DosQueryCurrentDir just returns the current
  455.     // directory without a trailing backslash. Of course there are always
  456.     // complications. The complication here is that if the current directory is
  457.     // the root, the string *will* end with a backslash. So if the trailing
  458.     // character is a backslash, remove it so we have a pure directory name.
  459.  
  460.     if( pszDirectory[ strlen( pszDirectory ) - 1 ] == '\\' )
  461.         pszDirectory[ strlen( pszDirectory ) - 1 ] = 0;
  462.  
  463.     if( rc )
  464.         Msg( "DosQueryCurrentDir RC(%X). Using Root Directory.", rc );
  465. }
  466.  
  467. /**********************************************************************/
  468. /*----------------------- UseCmdLineDirectory ------------------------*/
  469. /*                                                                    */
  470. /*  TAKE THE DIRECTORY FROM THE COMMANDLINE AND VALIDATE IT.          */
  471. /*                                                                    */
  472. /*  INPUT: pointer to buffer in which to place correct path,          */
  473. /*         directory input at the commandline                         */
  474. /*                                                                    */
  475. /*  1.                                                                */
  476. /*                                                                    */
  477. /*  OUTPUT: nothing                                                   */
  478. /*                                                                    */
  479. /*--------------------------------------------------------------------*/
  480. /**********************************************************************/
  481. static VOID UseCmdLineDirectory( PSZ pszDirectoryOut, PSZ szDirectoryIn )
  482. {
  483.     (void) strcpy( pszDirectoryOut, szDirectoryIn );
  484.  
  485.     // If the user ended their directory name with a backslash, take it off
  486.     // because this program needs to have just the base directory name here.
  487.  
  488.     if( pszDirectoryOut[ strlen( pszDirectoryOut ) - 1 ] == '\\' )
  489.         pszDirectoryOut[ strlen( pszDirectoryOut ) - 1 ] = 0;
  490. }
  491.  
  492. /*************************************************************************
  493.  *                     E N D     O F     S O U R C E                     *
  494.  *************************************************************************/
  495.