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