home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1998 May / Pcwk5b98.iso / Borland / Cplus45 / BC45 / FFIND.PAK / FFIND.C next >
Text File  |  1995-08-29  |  32KB  |  993 lines

  1. // Borland C++ - (C) Copyright 1991, 1992 by Borland International
  2.  
  3. //*******************************************************************
  4. //
  5. // program - Ffind.c
  6. // purpose - a Windows program to find files on system drives.
  7. //
  8. //*******************************************************************
  9.  
  10. #define  STRICT
  11. #include <windows.h>
  12. #pragma hdrstop
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <time.h>
  17. #include <ctype.h>
  18. #include <io.h>
  19. #include <dos.h>
  20. #include <dir.h>
  21. #include <windowsx.h>
  22.  
  23. #include "ffind.h"
  24.  
  25. #define MAX_QRT_LEN 100
  26.  
  27. // data initialized by first instance
  28. typedef struct tagSETUPDATA
  29.   {
  30.     char   szAppName[10]; // name of application
  31.   } SETUPDATA;
  32.  
  33. SETUPDATA SetUpData;
  34.  
  35. char buf[256];
  36.  
  37. // Data that can be referenced throughout the
  38. // program but not passed to other instances
  39.  
  40. HINSTANCE hInst;                              // hInstance of application
  41. HWND      hWndMain;                           // hWnd of main window
  42.  
  43. char      qrtxt[MAX_QRT_LEN];                 // dialog input string
  44.  
  45. char      file_name_pattern[MAX_QRT_LEN];     // file name search pattern
  46. long      file_count;                         // count of files found
  47.  
  48. int       xChar, yChar, yCharnl;              // character size
  49. int       xClient, yClient;                   // client window size
  50.  
  51. LOGFONT   cursfont;                           // font structure
  52. HFONT     holdsfont;                          // handle of original font
  53. HFONT     hnewsfont;                          // handle of new fixed font
  54.  
  55. HGLOBAL   hdlgr;                              // handle of dialog resource
  56.  
  57. int       ndrives;                            // number of drives in system
  58. char      fdrives[10];                        // letters of floppy drives
  59. char      hdrives[30];                        // letters of hard drives
  60.  
  61. FARPROC   lpModelessProc;                     // pointer to proc for modeless box
  62. HWND      hQryDlgBox;                         // handle of modeless dialog box
  63.  
  64. // function prototypes
  65.  
  66. int      PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  67.                         LPSTR lpszCmdLine, int cmdShow);
  68.  
  69. void            InitFfind(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  70.                           LPSTR lpszCmdLine, int cmdShow);
  71. void            InitFfindFirst(HINSTANCE hInstance);
  72. void            InitFfindAdded(HINSTANCE hPrevInstance);
  73. void            InitFfindEvery(HINSTANCE hInstance, int cmdShow);
  74. void            CloseFfind(void);
  75.  
  76. LRESULT CALLBACK _export  FfindWndProc(HWND hWnd, UINT message,
  77.                                 WPARAM wParam, LPARAM lParam);
  78.  
  79. void            InitMainDlg(HWND hWnd);
  80. BOOL CALLBACK   _export MainDlgBoxProc(HWND hDlg, UINT message,
  81.                            WPARAM wParam, LPARAM lParam);
  82.  
  83. long            FindFile(char *drives, char *pattern);
  84. int             DoADir(char *patternp, char *patternn, char *include);
  85. int             FnMatch(char *pat, char *name);
  86. void            FindDrives(char *fdrives, char *hdrives);
  87. char           *FmtEntry(char *buf, char *name, char *patternp,
  88.                          unsigned time, unsigned date, long size);
  89.  
  90. //*******************************************************************
  91. // WinMain - ffind main
  92. //
  93. // paramaters:
  94. //             hInstance     - The instance of this instance of this
  95. //                             application.
  96. //             hPrevInstance - The instance of the previous instance
  97. //                             of this application. This will be 0
  98. //                             if this is the first instance.
  99. //             lpszCmdLine   - A long pointer to the command line that
  100. //                             started this application.
  101. //             cmdShow       - Indicates how the window is to be shown
  102. //                             initially. ie. SW_SHOWNORMAL, SW_HIDE,
  103. //                             SW_MIMIMIZE.
  104. //
  105. // returns:
  106. //             wParam from last message.
  107. //
  108. //*******************************************************************
  109. int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  110.                    LPSTR lpszCmdLine, int cmdShow)
  111. {
  112.     MSG   msg;
  113.  
  114.     // Go init this application.
  115.     InitFfind(hInstance, hPrevInstance, lpszCmdLine, cmdShow);
  116.  
  117.     // Get and dispatch messages for this applicaton.
  118.     while (GetMessage(&msg, NULL, 0, 0))
  119.     {
  120.       if(!hQryDlgBox || !IsWindow(hQryDlgBox) ||
  121.          !IsDialogMessage( hQryDlgBox, &msg))
  122.       {
  123.         TranslateMessage(&msg);
  124.         DispatchMessage(&msg);
  125.       }
  126.     }
  127.  
  128.     return(msg.wParam);
  129. }
  130.  
  131. //*******************************************************************
  132.  
  133. //*******************************************************************
  134. // InitFfind - init the ffind application
  135. //
  136. // paramaters:
  137. //             hInstance     - The instance of this instance of this
  138. //                             application.
  139. //             hPrevInstance - The instance of the previous instance
  140. //                             of this application. This will be 0
  141. //                             if this is the first instance.
  142. //             lpszCmdLine   - A long pointer to the command line that
  143. //                             started this application.
  144. //             cmdShow       - Indicates how the window is to be shown
  145. //                             initially. ie. SW_SHOWNORMAL, SW_HIDE,
  146. //                             SW_MIMIMIZE.
  147. //
  148. //*******************************************************************
  149. #pragma argsused
  150. void InitFfind(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  151.                LPSTR lpszCmdLine, int cmdShow)
  152. {
  153.     if (!hPrevInstance)              // if no previous instance, this is first
  154.         InitFfindFirst(hInstance);
  155.     else
  156.         InitFfindAdded(hPrevInstance);   // this is not first instance
  157.  
  158.     InitFfindEvery(hInstance, cmdShow);  // initialization for all instances
  159.  
  160. }
  161.  
  162. //*******************************************************************
  163. // InitFfindFirst - done only for first instance of ffind
  164. //
  165. // paramaters:
  166. //             hInstance     - The instance of this instance of this
  167. //                             application.
  168. //
  169. //*******************************************************************
  170. void InitFfindFirst(HINSTANCE hInstance)
  171. {
  172.     WNDCLASS wcFfindClass;
  173.  
  174.     // Get string from resource with application name.
  175.     LoadString(hInstance, IDS_NAME, (LPSTR) SetUpData.szAppName, 10);
  176.  
  177.     // Define the window class for this application.
  178.     wcFfindClass.lpszClassName = SetUpData.szAppName;
  179.     wcFfindClass.hInstance     = hInstance;
  180.     wcFfindClass.lpfnWndProc   = FfindWndProc;
  181.     wcFfindClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
  182.     wcFfindClass.hIcon         = LoadIcon(hInstance, SetUpData.szAppName);
  183.     wcFfindClass.lpszMenuName  = (LPSTR) NULL;
  184.     wcFfindClass.hbrBackground = GetStockObject(WHITE_BRUSH);
  185.     wcFfindClass.style         = CS_HREDRAW | CS_VREDRAW;
  186.     wcFfindClass.cbClsExtra    = 0;
  187.     wcFfindClass.cbWndExtra    = 0;
  188.  
  189.     // Register the class
  190.     RegisterClass(&wcFfindClass);
  191. }
  192.  
  193. //*******************************************************************
  194. // InitFfindAdded - done only for added instances of ffind
  195. //
  196. // paramaters:
  197. //             hPrevInstance - The instance of the previous instance
  198. //                             of this application.
  199. //
  200. //*******************************************************************
  201. #pragma argsused
  202. void InitFfindAdded(HINSTANCE hPrevInstance)
  203. {
  204.     // get the results of the initialization of first instance
  205.     // GetInstanceData(hPrevInstance, (BYTE*) &SetUpData, sizeof(SETUPDATA));
  206. }
  207.  
  208. //*******************************************************************
  209. // InitFfindEvery - done for every instance of ffind
  210. //
  211. // paramaters:
  212. //             hInstance     - The instance of this instance of this
  213. //                             application.
  214. //             cmdShow       - Indicates how the window is to be shown
  215. //                             initially. ie. SW_SHOWNORMAL, SW_HIDE,
  216. //                             SW_MIMIMIZE.
  217. //
  218. //*******************************************************************
  219. #pragma argsused
  220. void InitFfindEvery(HINSTANCE hInstance, int cmdShow)
  221. {
  222.     TEXTMETRIC tm;
  223.     HDC        hDC;
  224.  
  225.     hInst = hInstance;       // save for use by window procs
  226.  
  227.     // Create applications main window.
  228.     hWndMain = CreateWindow(
  229.                   SetUpData.szAppName,
  230.                   SetUpData.szAppName,
  231.                     WS_BORDER |
  232.                     WS_CAPTION |
  233.                     WS_SYSMENU |
  234.                     WS_MINIMIZEBOX,
  235.                   10,
  236.                   19,
  237.                   256,
  238.                   123,
  239.                   NULL,
  240.                   NULL,
  241.                   hInstance,
  242.                   NULL
  243.                   );
  244.  
  245.     // Get the display context.
  246.     hDC = GetDC(hWndMain);
  247.  
  248.     // Build fixed screen font. Needed to display columinar report.
  249.     cursfont.lfHeight         =  14;
  250.     cursfont.lfWidth          =  9;
  251.     cursfont.lfEscapement     =  0;
  252.     cursfont.lfOrientation    =  0;
  253.     cursfont.lfWeight         =  FW_NORMAL;
  254.     cursfont.lfItalic         =  FALSE;
  255.     cursfont.lfUnderline      =  FALSE;
  256.     cursfont.lfStrikeOut      =  FALSE;
  257.     cursfont.lfCharSet        =  ANSI_CHARSET;
  258.     cursfont.lfOutPrecision   =  OUT_DEFAULT_PRECIS;
  259.     cursfont.lfClipPrecision  =  CLIP_DEFAULT_PRECIS;
  260.     cursfont.lfQuality        =  DEFAULT_QUALITY;
  261.     cursfont.lfPitchAndFamily =  FIXED_PITCH | FF_DONTCARE;
  262.     strcpy((char *)cursfont.lfFaceName, "System");
  263.  
  264.     hnewsfont = CreateFontIndirect( &cursfont);
  265.  
  266.     // Install the font in the current display context.
  267.     holdsfont = SelectObject(hDC, hnewsfont);
  268.  
  269.     // get text metrics for paint
  270.     GetTextMetrics(hDC, &tm);
  271.     xChar = tm.tmAveCharWidth;
  272.     yChar = tm.tmHeight + tm.tmExternalLeading;
  273.     yCharnl = tm.tmHeight;
  274.  
  275.     // Release the display context.
  276.     ReleaseDC(hWndMain, hDC);
  277.  
  278.     // Create a thunk for the main dialog box proc function.
  279.     lpModelessProc = MakeProcInstance((FARPROC)MainDlgBoxProc, hInst);
  280.  
  281.     // Find drive letters for all drives in system.
  282.     // We will only use the hard drives.
  283.     FindDrives(fdrives, hdrives);
  284.     hdrives[9] = 0; // limit drives to max of 9
  285.     ndrives = strlen(hdrives);
  286.  
  287.     InitMainDlg(hWndMain);
  288. }
  289.  
  290. //*******************************************************************
  291. // CloseFfind - done at termination of every instance of ffind
  292. //
  293. //*******************************************************************
  294. void CloseFfind()
  295. {
  296. }
  297.  
  298. //*******************************************************************
  299.  
  300. //*******************************************************************
  301. // FfindWndProc - handles messages for this application
  302. //
  303. // paramaters:
  304. //             hWnd          - The window handle for this message
  305. //             message       - The message number
  306. //             wParam        - The WPARAM parmater for this message
  307. //             lParam        - The LPARAM parmater for this message
  308. //
  309. // returns:
  310. //             depends on message.
  311. //
  312. //*******************************************************************
  313. LRESULT CALLBACK _export FfindWndProc(HWND hWnd, UINT message,
  314.                              WPARAM wParam, LPARAM lParam)
  315. {
  316.     switch (message)
  317.     {
  318.         case WM_MOVE:
  319.             // Move the dialog box on top of our main window every
  320.             // time the main window moves.
  321.             if (IsWindow(hQryDlgBox))
  322.                 SendMessage(hQryDlgBox, message, wParam, lParam);
  323.             break;
  324.  
  325.         case WM_SETFOCUS:
  326.             // Always set the input focus to the dialog box.
  327.             if (IsWindow(hQryDlgBox))
  328.                 SendMessage(hQryDlgBox, message, wParam, lParam);
  329.             break;
  330.  
  331.         case WM_CLOSE:
  332.             // Tell windows to destroy our window.
  333.             DestroyWindow(hWnd);
  334.             break;
  335.  
  336.         case WM_QUERYENDSESSION:
  337.             // If we return TRUE we are saying it's ok with us to end the
  338.                 // windows session.
  339.             return((long) TRUE);  // we agree to end session.
  340.  
  341.         case WM_ENDSESSION:
  342.             // If wParam is not zero, it meany every application said ok
  343.             // to WM_QUERYENDSESSION messages, so we are really ending.
  344.             if (wParam)           // if all apps aggreed to end session.
  345.                 CloseFfind();     // This is the end. We will not get a
  346.                                    // WM_DESTROY message on end session.
  347.             break;
  348.  
  349.         case WM_DESTROY:
  350.             // This is the end if we were closed by a DestroyWindow call.
  351.  
  352.             // Remove font
  353.             DeleteObject(hnewsfont);
  354.  
  355.             CloseFfind();
  356.                 PostQuitMessage(0);
  357.             break;
  358.  
  359.         default:
  360.             return(DefWindowProc(hWnd, message, wParam, lParam));
  361.     }
  362.  
  363.     return(0L);
  364. }
  365.  
  366. //*******************************************************************
  367.  
  368. //*******************************************************************
  369. // InitMainDlg - put up modeless dialog box
  370. //
  371. // paramaters:
  372. //             hWnd          - The window handle of the caller
  373. //
  374. //*******************************************************************
  375. void InitMainDlg(HWND hWnd)
  376. {
  377.     // This structure describes the fixed portion at the begining of a
  378.     // dialog template. The part we are going to modify is dtItemCount
  379.     // to cause the proper number of drive selector boxes to display.
  380.  
  381.     WORD numDrives;
  382.  
  383.     #if !defined(__FLAT__)
  384.  
  385.     // 16 bit dialog template
  386.      typedef struct tagDLGTEMPLATE
  387.     {
  388.         long dtStyle;
  389.         BYTE dtItemCount;
  390.           int  dtX;
  391.         int  dtY;
  392.           int  dtCX;
  393.           int  dtCY;
  394.         char dtResourceName[1];
  395.     }   DLGTEMPLATE;
  396.  
  397.     typedef LPSTR DLGPTR;
  398.  
  399.    #else
  400.  
  401.     // 32 bit dialog template
  402.      typedef struct tagDLGTEMPLATE
  403.      {
  404.         DWORD  dtStyle;
  405.         DWORD  dtExtStyle;
  406.         WORD   dtItemCount;
  407.           SHORT  dtX;
  408.           SHORT  dtY;
  409.           SHORT  dtCX;
  410.           SHORT  dtCY;
  411.      } DLGTEMPLATE;
  412.  
  413.      typedef LPCDLGTEMPLATEA DLGPTR;
  414.  
  415.     #endif
  416.  
  417.      DLGTEMPLATE FAR *dltp, *tempDlgPtr;
  418.  
  419.      LPCSTR resourceStr;
  420.      HRSRC resourceHndl;
  421.  
  422.      // Modifying dialog box parms on the fly.
  423.  
  424.      // Load the dialog box resource.
  425.      resourceStr = MAKEINTRESOURCE(MAIN);
  426.  
  427. //    CreateDialogIndirect(hInst,resourceStr,hWnd,(DLGPROC)lpModelessProc);
  428.  
  429.      resourceHndl = FindResource(hInst, resourceStr, RT_DIALOG);
  430.  
  431.      hdlgr = LoadResource(hInst, resourceHndl);
  432.  
  433.      if (hdlgr)
  434.      {
  435.           // Lock the resource so we have a pointer to it.
  436.           dltp = (DLGTEMPLATE FAR *) LockResource(hdlgr);
  437.           if (dltp)
  438.           {
  439.                 // Change the number of items to display. The drive boxes are
  440.                 // defined last so we can truncate the ones not needed.
  441.  
  442.                 // make a temporary copy of dialog template
  443.                 tempDlgPtr = malloc((size_t)SizeofResource(hInst, resourceHndl));
  444.  
  445. #if defined(__FLAT__)
  446.                 memcpy((void *)tempDlgPtr, (const void *)dltp, (size_t)SizeofResource(hInst, resourceHndl));
  447. #else
  448.                 _fmemcpy((void FAR *)tempDlgPtr, (const void FAR *)dltp, (size_t)SizeofResource(hInst, resourceHndl));
  449. #endif
  450.  
  451.                 numDrives = (WORD)(ndrives + QX_DRV1 - QX_1);
  452.  
  453. #if !defined(__FLAT__)
  454.                 tempDlgPtr->dtItemCount = (BYTE) numDrives;
  455. #else
  456.                 tempDlgPtr->dtItemCount = numDrives;
  457. #endif
  458.                 CreateDialogIndirect(hInst,
  459.                                                   (DLGPTR)tempDlgPtr,
  460.                                                   hWnd,
  461.                                                   (DLGPROC)lpModelessProc);
  462.  
  463.                 // free tempory copy of dialog template
  464.  
  465.                 free(tempDlgPtr);
  466.  
  467.  
  468.                 // Unlock dialog resource we locked above.
  469.  
  470. #if !defined(__FLAT__)
  471.                 UnlockResource(hdlgr);
  472. #endif
  473.  
  474.                 // Free it.
  475.                 FreeResource(hdlgr);
  476.  
  477.                 // Zero handle to it.
  478.                 hdlgr = 0;
  479.           }
  480.      }
  481.  
  482. }
  483.  
  484. //*******************************************************************
  485. // MainDlgBoxProc - handle Main dialog messages (modeless)
  486. //
  487. // This is a modeless dialog box procedure that controls this
  488. // entire application.
  489. //
  490. // paramaters:
  491. //             hDlg          - The window handle for this message
  492. //             message       - The message number
  493. //             wParam        - The WPARAM parameter for this message
  494. //             lParam        - The LPARAM parameter for this message
  495. //
  496. //*******************************************************************
  497. #pragma argsused
  498. BOOL CALLBACK _export MainDlgBoxProc(HWND hDlg, UINT message,
  499.                            WPARAM wParam, LPARAM lParam)
  500. {
  501.     static HWND   hlistwnd;
  502.     static RECT   wrect;
  503.  
  504.     int           x, y, w, h, i;
  505.     long          rc;
  506.     char         *cp, *cpd, tmp[30], sdrives[30];
  507.     HANDLE        hCursor;
  508.  
  509.     switch (message)
  510.     {
  511.         case WM_INITDIALOG:
  512.             // Save the handle of this proc for use by main window proc.
  513.             hQryDlgBox = hDlg;
  514.  
  515.             // Set names of drives in drive box text.
  516.             cp = hdrives;
  517.             for (i = 0; i < ndrives; i++)
  518.             {
  519.                 sprintf(tmp, "%c:", *cp++);
  520.                 SetDlgItemText(hDlg, QX_DRV1 + i, tmp);
  521.             }
  522.  
  523.             // Select the first drive.
  524.             SendMessage(GetDlgItem(hDlg, QX_DRV1), BM_SETCHECK, TRUE, 0L);
  525.  
  526.             // Get position of dialog box window.
  527.             GetWindowRect(hDlg, (LPRECT) &wrect);
  528.             w = wrect.right - wrect.left;
  529.             h = wrect.bottom - wrect.top;
  530.  
  531.             // Move main application window to same position.
  532.             SetWindowPos(hWndMain, hDlg,
  533.                          wrect.left, wrect.top, w, h,
  534.                          0);
  535.  
  536.             // Establish initial value of file name pattern box.
  537.             strcpy(file_name_pattern, "*.cpp");
  538.             SetDlgItemText(hDlg, QX_PATTERN, file_name_pattern);
  539.             SetFocus(GetDlgItem(hDlg, QX_PATTERN));
  540.  
  541.             // Save handle of list box control because we use it a lot.
  542.             hlistwnd = GetDlgItem(hDlg, QX_LIST);
  543.  
  544.             // Install fixed fonts for those controls that need it.
  545.             SendMessage(GetDlgItem(hDlg, QX_3), WM_SETFONT, (WPARAM)hnewsfont, FALSE);
  546.             SendMessage(GetDlgItem(hDlg, QX_LIST), WM_SETFONT, (WPARAM)hnewsfont, FALSE);
  547.             SendMessage(GetDlgItem(hDlg, QX_COUNT), WM_SETFONT, (WPARAM)hnewsfont, FALSE);
  548.             break;
  549.  
  550.         case WM_MOVE:
  551.             // Always keep this dialog box on top of main window.
  552.             GetWindowRect(hWndMain, (LPRECT) &wrect);
  553.             x = wrect.left;
  554.             y = wrect.top;
  555.             w = wrect.right - wrect.left;
  556.             h = wrect.bottom - wrect.top;
  557.             MoveWindow(hDlg, x, y, w, h, 1);
  558.             break;
  559.  
  560.         case WM_SYSCOMMAND:
  561.             // Pass WM_SYSCOMMAND messages on to main window so both
  562.             // main window and dialog box get iconized, minimized etc.
  563.             // in parallel.
  564.             SendMessage(hWndMain, message, wParam, lParam);
  565.             break;
  566.  
  567.         case WM_COMMAND:
  568.             switch (GET_WM_COMMAND_ID(wParam, lParam))
  569.             {
  570.                 case QX_PATTERN:                 // Pattern string
  571.                     GetDlgItemText(hDlg, GET_WM_COMMAND_ID(wParam, lParam),
  572.                                    qrtxt, MAX_QRT_LEN);
  573.                     break;
  574.  
  575.                 case QX_SEARCH:                  // File button
  576.                     strcpy(file_name_pattern, qrtxt);
  577.  
  578.                     // Build list of selected drives.
  579.                     cp = hdrives;
  580.                     cpd = sdrives;
  581.                     for ( i = 0; i < ndrives; i++)
  582.                     {
  583.                         if (SendMessage(GetDlgItem(hDlg, QX_DRV1 + i), BM_GETCHECK, 0, 0L))
  584.                             *cpd++ = *cp;
  585.                         cp++;
  586.                     }
  587.                     *cpd = 0;
  588.  
  589.                     // Clear any previous list and count.
  590.                     SendMessage(hDlg, WM_COMMAND, GET_WM_COMMAND_MPS(QX_CLEARW, 0, 0));
  591.  
  592.                     // Tell list control not to display till we are done
  593.                     SendDlgItemMessage(hDlg, QX_LIST, WM_SETREDRAW, FALSE, 0L);
  594.  
  595.                     // Load hour-glass cursor.
  596.                     hCursor = LoadCursor(NULL, IDC_WAIT);
  597.                     SetCursor(hCursor);
  598.  
  599.                     // Go find files matching pattern on selected drives.
  600.                     rc = FindFile(sdrives, file_name_pattern);
  601.  
  602.                     // Tell list control ok to redraw itself.
  603.                     SendDlgItemMessage(hDlg, QX_LIST, WM_SETREDRAW, TRUE, 0L);
  604.  
  605.                     // Reload arrow cursor.
  606.                     SetCursor(hCursor);
  607.  
  608.                     // See if out of memory error.
  609.                     if (rc < 0)
  610.                     {
  611.                         MessageBox(hDlg,
  612.                                    "Out of memory",
  613.                                    "--ERROR--",
  614.                                    MB_APPLMODAL | MB_ICONEXCLAMATION | MB_OK);
  615.                     }
  616.  
  617.                     // Show count of files fount.
  618.                     sprintf(tmp, "# %5ld", file_count);
  619.                     SetDlgItemText(hDlg, QX_COUNT, tmp);
  620.  
  621.                     // Show list window.
  622.                     InvalidateRect(hlistwnd, NULL, TRUE);
  623.                     UpdateWindow(hlistwnd);
  624.                     break;
  625.  
  626.                 case QX_CLEARW:
  627.                     // Clear list window.
  628.                     SendMessage(hlistwnd, LB_RESETCONTENT, 0L, 0L);
  629.                                         InvalidateRect(hlistwnd, NULL, TRUE);
  630.                     UpdateWindow(hlistwnd);
  631.  
  632.                     // Set count to 0.
  633.                     file_count = 0;
  634.                     sprintf(tmp, "# %5ld", file_count);
  635.                     SetDlgItemText(hDlg, QX_COUNT, tmp);
  636.                     break;
  637.  
  638.                 case QX_CANCEL:                  // Cancel button
  639.                     // Tell main application window we want to quit.
  640.                     SendMessage(hWndMain, WM_CLOSE, 0, 0L);
  641.                     break;
  642.  
  643.                 default:
  644.                     break;
  645.             }
  646.             break;
  647.  
  648.         case WM_CLOSE:
  649.             // Unlock dialog resource we locked above.
  650.  
  651.             #if !defined(__FLAT__)
  652.             UnlockResource(hdlgr);
  653.             #endif
  654.  
  655.             // Free it.
  656.             FreeResource(hdlgr);
  657.  
  658.             // Zero handle to it.
  659.             hdlgr = 0;
  660.  
  661.             // Zero handle to this dialog window.
  662.             hQryDlgBox = 0;
  663.  
  664.             // Tell main window to close.
  665.             PostMessage(hWndMain, WM_CLOSE, 0, 0L);
  666.  
  667.             // Destroy ourseleves.
  668.             DestroyWindow(hDlg);
  669.             break;
  670.  
  671.         default:
  672.             return FALSE;
  673.     }
  674.  
  675.     return(TRUE);
  676. }
  677.  
  678. //*******************************************************************
  679.  
  680. //*******************************************************************
  681. // FindFile - find files matching a pattern files on specified drives
  682. //
  683. // paramaters:
  684. //             drives   - An array of drive letters to search.
  685. //             pattern  - A file name pattern.
  686. //
  687. // returns:
  688. //             Number of files found matching pattern.
  689. //             If unable to add a name to listbox, number is returned as
  690. //             a negative.
  691. //
  692. //*******************************************************************
  693. long FindFile(char *drives, char *pattern)
  694. {
  695.     char     tree[3];
  696.     int      nfiles;
  697.     long      rc;
  698.  
  699.     rc = 0;
  700.     file_count = 0;
  701.     tree[1] = ':';
  702.     tree[2] = 0;
  703.     while (*drives)
  704.     {
  705.         tree[0] = *drives++;
  706.         nfiles = DoADir(tree, "*.*", pattern);
  707.         if (nfiles >= 0)
  708.             file_count += nfiles;
  709.         else
  710.         {
  711.             file_count -= nfiles;
  712.             rc = -file_count;
  713.             break;
  714.         }
  715.     }
  716.  
  717.     return(rc);
  718. }
  719.  
  720. //*******************************************************************
  721. // DoADir - search a directory for files matching a file name pattern
  722. //          recursivly search sub directories
  723. //
  724. // paramaters:
  725. //             patternp  - A path to search.
  726. //             patternn  - A file name pattern to use to find directories.
  727. //             include   - A file name pattern to use to select files.
  728. //
  729. // returns:
  730. //             Number of files found matching include.
  731. //             If unable to add a name to listbox, number is returned as
  732. //             a negative.
  733. //
  734. //*******************************************************************
  735. int DoADir(char *patternp, char *patternn, char *include)
  736. {
  737.     char          patternw[80];
  738.     char          npatternp[64];
  739.     char          buf[128];
  740.     int           mfiles;
  741.     int           have_subs;
  742.     int           nfiles;
  743.     LONG          lrc;
  744.     struct ffblk  fileinfo;
  745.  
  746.     strcpy(patternw, patternp);
  747.     strcat(patternw, "\\");
  748.  
  749.     strcat(patternw, patternn);
  750.  
  751.     mfiles = 0;
  752.     have_subs = 0;
  753.  
  754.     if (!findfirst(patternw, &fileinfo, FA_DIREC))
  755.     {
  756.         do
  757.         {
  758.             if (fileinfo.ff_attrib & FA_DIREC)  // subdirectory
  759.             {
  760.                 if (fileinfo.ff_name[0] != '.')  // ignore . and ..
  761.                     have_subs = 1;
  762.             }
  763.             else                              // file
  764.             {
  765.                 if (FnMatch(include, fileinfo.ff_name))
  766.                 {
  767.                     mfiles++;
  768.  
  769.                     FmtEntry(buf, fileinfo.ff_name, patternp,
  770.                              fileinfo.ff_ftime, fileinfo.ff_fdate, fileinfo.ff_fsize);
  771.  
  772.                     lrc = SendDlgItemMessage(hQryDlgBox, QX_LIST, LB_ADDSTRING, 0,
  773.                                             (LONG) ((LPSTR) buf));
  774.  
  775.                     if (lrc == LB_ERR || lrc == LB_ERRSPACE)
  776.                         return(-mfiles); // error return
  777.                 }
  778.             }
  779.         }
  780.         while (!findnext(&fileinfo));
  781.     }
  782.  
  783.     if (have_subs)
  784.     {
  785.         if (!findfirst(patternw, &fileinfo, FA_DIREC))
  786.         {
  787.             do
  788.             {
  789.                 if (fileinfo.ff_attrib & FA_DIREC)  // subdirectory
  790.                 {
  791.                     if (fileinfo.ff_name[0] != '.')  // ignore . and ..
  792.                     {
  793.                         strcpy(npatternp, patternp);
  794.                         strcat(npatternp, "\\");
  795.                         strcat(npatternp, fileinfo.ff_name);
  796.  
  797.                         nfiles = DoADir(npatternp, patternn, include);
  798.  
  799.                         if (nfiles >= 0)
  800.                             mfiles += nfiles;
  801.                         else
  802.                         {
  803.                                                         mfiles -= nfiles;
  804.                             return(-mfiles); // error return
  805.                         }
  806.                     }
  807.                 }
  808.             }
  809.             while (!findnext(&fileinfo));
  810.         }
  811.         }
  812.  
  813.         return(mfiles);
  814. }
  815.  
  816. //*******************************************************************
  817. // FindDrives - find floppy and hard drives in system
  818. //
  819. // paramaters:
  820. //             fdrives - An array to hold floppy drive letters.
  821. //             hdrives - An array to hold hard drive letters.
  822. //
  823. //*******************************************************************
  824. void FindDrives(char *fdrives, char *hdrives)
  825. {
  826.         unsigned int  savedriveno;
  827.           unsigned int  maxdriveno;
  828.           unsigned int  driveno;
  829.           unsigned int  drivetype;
  830.           int           nfdrives = 0;
  831.           int           nhdrives = 0;
  832. #ifdef __FLAT__
  833.           char driveroot[4];
  834. #endif
  835.  
  836.           savedriveno = getdisk() + 1;               // save current drive
  837.           maxdriveno = setdisk(savedriveno - 1);     // find max drive in system
  838.  
  839.  
  840.           for (driveno=0; driveno<maxdriveno; driveno++)
  841.                      {
  842. #ifdef __FLAT__
  843.                      strcpy(driveroot, " :\\");
  844.                      driveroot[0] = (char)('A'+driveno);
  845.                      drivetype = GetDriveType(driveroot);
  846. #else
  847.                      drivetype = GetDriveType(driveno);
  848. #endif
  849.                      if (drivetype == 0)
  850.                                 continue;
  851.                      else
  852.                                 if (drivetype == DRIVE_REMOVABLE)
  853.                                 {
  854.                         fdrives[nfdrives++] = (char) (driveno + 'A');
  855.                         }
  856.                         else
  857.                                 {
  858.                                 hdrives[nhdrives++] = (char) (driveno + 'A');
  859.                                 }
  860.                 }
  861.  
  862.         fdrives[nfdrives] = 0;
  863.         hdrives[nhdrives] = 0;
  864.  
  865.           setdisk(savedriveno - 1);                  // reset current drive
  866. }
  867.  
  868. //*******************************************************************
  869.  
  870. //*******************************************************************
  871. // FnMatch - test if a file name matches a file name pattern.
  872. //           handles * and ? wildcard characters.
  873. //
  874. // paramaters:
  875. //             pat   - A file name pattern (ie. xyz?.*)
  876. //             name  - A file name to test against pat (ie. xyz1.c)
  877. //
  878. // returns:
  879. //             1 - if match
  880. //             0 - if not a match
  881. //
  882. //*******************************************************************
  883. FnMatch(char *pat, char *name)
  884. {
  885.     int   match;
  886.     int   ndone;
  887.     char *cpp;
  888.     char *cpn;
  889.  
  890.     cpp = pat;
  891.     cpn = name;
  892.     match = 1;
  893.     ndone = 1;
  894.     while (ndone)
  895.     {
  896.         switch (*cpp)
  897.         {
  898.             case '*':
  899.                 // skip to . or end of pat
  900.                 while (*cpp && *cpp != '.')
  901.                     cpp++;
  902.  
  903.                 // skip to . or end of name
  904.                 while (*cpn && *cpn != '.')
  905.                     cpn++;
  906.                 break;
  907.  
  908.             case '?':
  909.                 cpp++;
  910.                 cpn++;
  911.                 break;
  912.  
  913.             case 0:
  914.                 if (*cpn != 0)
  915.                     match = 0;
  916.                 ndone = 0;
  917.                 break;
  918.  
  919.             default:
  920.                 if (tolower(*cpp) == tolower(*cpn))
  921.                 {
  922.                     cpp++;
  923.                     cpn++;
  924.                 }
  925.                 else
  926.                 {
  927.                     match = 0;
  928.                     ndone = 0;
  929.                 }
  930.                 break;
  931.         }
  932.     }
  933.  
  934.     return(match);
  935. }
  936.  
  937. //*******************************************************************
  938. // FmtEntry - format directory entry for report
  939. //
  940. // paramaters:
  941. //             buf      - A buffer to hold formated directory entry.
  942. //             name     - File name.
  943. //             patternp - Path on which file was found.
  944. //             time     - File time from directory.
  945. //             date     - File data from directory.
  946. //             szie     - File size from directory.
  947. //
  948. // returns:
  949. //             A pointer to buf.
  950. //
  951. //*******************************************************************
  952. char *FmtEntry(char *buf, char *name, char *patternp,
  953.                unsigned time, unsigned date, long size)
  954. {
  955.     char   *cp;
  956.     char    xname[10];
  957.     char    xext[10];
  958.     int     mo, dd, yy, hh, mi, ss;
  959.  
  960.     cp = strchr(name, '.');
  961.     if (cp)
  962.     {
  963.         *cp = 0;
  964.         strcpy(xname, name);
  965.         strcpy(xext, cp + 1);
  966.     }
  967.     else
  968.     {
  969.         strcpy(xname, name);
  970.         strcpy(xext, "");
  971.     }
  972.  
  973.     mo = (date >> 5) & 0x0f;
  974.     dd = date & 0x1f;
  975.     yy = ((date >> 9) & 0x7f) + 80;
  976.     hh = (time >> 11) & 0x1f;
  977.     mi = (time >> 5) & 0x3f;
  978.     ss = (time & 0x1f) * 2;
  979.  
  980.     sprintf(buf, "%-8s.%-3s %7ld %02d/%02d/%02d %02d:%02d:%02d %s",
  981.                   xname,
  982.                   xext,
  983.                   size,
  984.                   mo, dd, yy,
  985.                   hh, mi, ss,
  986.                   patternp);
  987.  
  988.     return(buf);
  989. }
  990.  
  991. //*******************************************************************
  992. 
  993.