home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / CNRBAS.ZIP / CREATE.C < prev    next >
Text File  |  1993-01-02  |  21KB  |  454 lines

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