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

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