home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frostbyte's 1980s DOS Shareware Collection
/
floppyshareware.zip
/
floppyshareware
/
SOUR
/
CGAZ5N2.ZIP
/
FF.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-12-10
|
27KB
|
756 lines
/************ Listing 1 ****************** FF.C ********************
** Author: John Rex
** Date: November, 1990
** Compiler: MSC 6.0
** Environment: Windows 3.0
** Switches: DEBUG - if defined, status messages are sent to a file
** Compile commands:
** rc -r ff.rc
** cl -qc -c -W2 -AS -Gsw -Oils -Zpe ff.c
** link /NOD ff.obj,, nul.map, libw.lib slibcew.lib, ff.def
** rc ff.res
**
** Object code may be used freely.
** Source code may be used freely if author/publication are acknowledged
*********************************************************************/
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <dos.h>
#include "ffdlg.h"
#if defined(DEBUG)
FILE *debugfile;
#define SHOW(x) x
#define SHOWF0(f) {fprintf(debugfile,f); flushall();}
#define SHOWF1(f,a1) {fprintf(debugfile,f,a1); flushall();}
#define SHOWF2(f,a1,a2) {fprintf(debugfile,f,a1,a2); flushall();}
#define SHOWF3(f,a1,a2,a3) {fprintf(debugfile,f,a1,a2,a3); flushall();}
#else
#define SHOW(x)
#define SHOWF0(f)
#define SHOWF1(f,a1)
#define SHOWF2(f,a1,a2)
#define SHOWF3(f,a1,a2,a3)
#endif
/*** common data ***/
#define FILEMAX 12
#define PATHMAX 80
/* some handles */
FARPROC fpFileListProc;
HANDLE hAppInstance;
HWND CurrentDialogBox;
HCURSOR hHourGlass; /* hour glass cursor */
int dotcount; /* for dancing dot display while searching */
int filecount; /* total number of files found */
/* access to the icon for the main window */
HICON HIcon;
/* The WinList structure is used to keep a linked list of all the dialog
* boxes. The handle of the main dialog box (SearchDialogProc) is kept in
* WinListHead.hWin, while the handles to all the secondary search result
* boxes (FileListProc) are kept in the body of the linked list. */
struct WinList {
HWND hWin;
struct WinList *next;
} WinListHead;
/* state variable used during file searching */
enum tagSearchState { Idle, Searching, Stop } SearchState;
/*** end common data ***/
#pragma page()
#pragma subtitle("Memory Routines")
/* out of memory error box */
void NoMemory(HWND hDlg)
{
MessageBox(hDlg, (LPSTR) "Out of memory!",
(LPSTR) "FileFind", MB_SYSTEMMODAL | MB_OK | MB_ICONEXCLAMATION);
}
void *mymalloc(HWND hDlg, size_t size)
{
void *p;
p = malloc(size);
if (p == NULL) {
NoMemory(hDlg);
SHOWF0("Mymalloc: out of memory\n");
}
return (p);
}
/* ffwalk: looks in directory specified by ppath for files matching
* spec. Recursively descends tree as it finds new
* subdirectories. */
int ffwalk(char *ppath, char *spec, HWND hDlg)
{
static struct find_t fileinfo;
char buffer[PATHMAX], *end_at;
unsigned found_one, errorcode;
int hour, am_pm, retval, index;
struct dirlist {
char *dirname;
struct dirlist *next;
} header, *temp, *last;
MSG Msg;
/* First, check for messages directed to our dialog box. The return
* value from IsDialogMessage is ignored because we know that the
* message must belong to our dialog box. */
while (PeekMessage((LPMSG) &Msg, hDlg, 0, 0, PM_REMOVE))
IsDialogMessage(hDlg, (LPMSG) &Msg);
if (SearchState == Stop) /* user wants out! */
{
if (SendDlgItemMessage(hDlg, IDC_FILELIST, LB_INSERTSTRING,
-1, (LONG) (LPSTR) " --Search Stopped--") < LB_OKAY)
NoMemory(hDlg);
return 1;
}
/* create a rotating dot display as we cycle through directories */
strcpy(buffer, " ");
buffer[dotcount++] = '*';
if (dotcount > 3)
dotcount = 0;
SendDlgItemMessage(hDlg, IDC_DOTS, WM_SETTEXT, 0, (LONG) (LPSTR) buffer);
/* save end of ppath so we can clip when needed */
end_at = ppath + strlen(ppath);
/* start by searching for matching files */
found_one = 0;
strcat(ppath, spec);
SHOWF1("ffwalk: searching for %s\n", ppath);
if ((errorcode = _dos_findfirst
(ppath, _A_NORMAL | _A_RDONLY | _A_ARCH, &fileinfo)) == 0)
{
*end_at = '\0';
do
{
filecount++;
/* output subdirectory name, if needed */
if (found_one++ == 0)
{
if (filecount > 1)
{ /* output a blank line first */
if ( SendDlgItemMessage(hDlg,
IDC_FILELIST, LB_INSERTSTRING, -1,
(LONG) (LPSTR) "") < LB_OKAY)
{
NoMemory(hDlg);
return 1;
}
}
if (SendDlgItemMessage(hDlg, IDC_FILELIST,
LB_INSERTSTRING, -1, (LONG) (LPSTR) ppath) < LB_OKAY)
{
NoMemory(hDlg);
return 1;
}
}
/* and now, output filename with size, date, time attached */
hour = (fileinfo.wr_time&0xF800) >> 11;
am_pm = 'a';
if (hour > 12)
{
hour -= 12;
am_pm = 'p';
}
sprintf(buffer, " %s\t%7ld\t%2u/%02u/%02u\t%2u:%02u%c",
fileinfo.name, fileinfo.size, /* name and size */
(fileinfo.wr_date & 0x01E0) >> 5, /* month */
fileinfo.wr_date & 0x001F, /* date */
((fileinfo.wr_date & 0xFE00) >> 9)+80, /* year */
hour, /* hour */
(fileinfo.wr_time&0x07E0) >> 5, /* minutes */
am_pm); /* am/pm */
strlwr(buffer);
if ((index = SendDlgItemMessage(hDlg, IDC_FILELIST,
LB_INSERTSTRING, -1, (LONG) (LPSTR) buffer)) < LB_OKAY)
{
NoMemory(hDlg);
return 1;
}
/* Check to see if we should force an update of the window.
* The list of names will update itself, but the scroll bars
* that get added will not be completed unless we force it.
* There are 13 rows in the box (0-12), so we force updates
* when index is in the range 13 thru 16 */
if (index >= 13 && index <= 16)
UpdateWindow(hDlg);
} while (_dos_findnext(&fileinfo) == 0);
}
if (errorcode)
{
SHOWF1("Error code was %#x\n", errorcode);
if (errorcode != 0x12) /* exit if anything but "No more files" */
return 1;
}
/* Look for subdirectories to search. */
*end_at = '\0';
strcat(ppath, "*.*");
header.dirname = NULL;
header.next = NULL;
retval = 0;
/* first, find all the names */
if (_dos_findfirst(ppath, _A_SUBDIR, &fileinfo) == 0)
{
*end_at = '\0';
do
{
if (fileinfo.attrib & _A_SUBDIR)
{
if (*fileinfo.name != '.') /* don't acccept . or .. */
{
strcpy(buffer, ppath);
strcat(buffer, fileinfo.name);
strcat(buffer, "\\");
if ((temp = mymalloc(hDlg, sizeof(struct dirlist)))
== NULL)
{
retval = 1;
break;
}
if ((temp -> dirname = mymalloc(hDlg,
strlen(buffer)+1+FILEMAX)) == NULL)
{
retval = 1;
break;
}
strcpy(temp->dirname, buffer);
temp->next = header.next;
header.next = temp;
}
}
*end_at = '\0';
} while (_dos_findnext(&fileinfo) == 0);
}
/* Search subdirectories. Clean up linked list as we go. */
for (temp = header.next; temp; )
{
if (!retval) /* if we've had a problem, stop searching but do
finish cleaning up linked list */
retval = ffwalk(temp->dirname, spec, hDlg);
last = temp;
temp = temp->next;
free (last->dirname);
free (last);
}
return (retval);
}
/* Draw icon for minimized windows */
BOOL ShowOurIcon(HWND hDlg)
{
HDC HDevContext;
PAINTSTRUCT ps;
RECT rcWindow;
HBRUSH hBrush;
if (IsIconic(hDlg))
{
/* get device context and size of display area */
HDevContext = BeginPaint(hDlg, &ps);
GetClientRect(hDlg, &rcWindow);
/* make background = desktop */
hBrush = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND));
FillRect(HDevContext, &rcWindow, hBrush);
DeleteObject(hBrush);
/* center icon in client window area. rcWindow.top and .left
* will always be zero, so we leave them out of the
* calculation. */
DrawIcon (HDevContext,
(rcWindow.right - GetSystemMetrics(SM_CXICON))/2,
(rcWindow.bottom - GetSystemMetrics(SM_CYICON))/2,
HIcon);
EndPaint(hDlg, &ps);
return (TRUE);
}
return (FALSE);
}
/* "About" dialog box procedure */
BOOL FAR PASCAL
AboutDlgProc (HWND hDlg, unsigned message, WORD wParam, LONG lParam)
{
switch (message)
{
case WM_ACTIVATE:
if (wParam)
CurrentDialogBox = NULL;
return (FALSE); /* continue with default processing */
case WM_INITDIALOG:
return (TRUE);
case WM_COMMAND:
if (wParam == IDOK || wParam == IDCANCEL)
{
EndDialog(hDlg, TRUE);
return (TRUE);
}
break;
}
return (FALSE);
}
/* File List dialog box procedure */
BOOL FAR PASCAL
FileListProc (HWND hDlg, unsigned message, WORD wParam, LONG lParam)
{
switch (message)
{
case WM_ACTIVATE:
if (wParam)
CurrentDialogBox = hDlg;
return (FALSE); /* continue with default processing */
case WM_PAINT:
return (ShowOurIcon(hDlg));
case WM_INITDIALOG:
{
int xSysDim, ySysDim, xDim, yDim, yHigh, yCaption;
RECT wRect;
struct WinList *t;
/* place new window */
yCaption = GetSystemMetrics(SM_CYCAPTION);
xSysDim = GetSystemMetrics(SM_CXSCREEN);
ySysDim = GetSystemMetrics(SM_CYSCREEN);
GetWindowRect(hDlg, (LPRECT) &wRect);
xDim = wRect.right - wRect.left;
yDim = wRect.bottom - wRect.top;
/* now, look at other active search windows and try to
put ourselves lower than they are. Set the starting point
so that the first window ends up at ySysDim*2/5 */
yHigh = (ySysDim*2)/5 - yCaption;
for (t=WinListHead.next; t; t=t->next)
{
if (t->hWin != hDlg && !IsIconic(t->hWin))
{
GetWindowRect(t->hWin, (LPRECT) &wRect);
yHigh = max(yHigh, wRect.top);
}
}
yHigh += yCaption; /* shift down by height of caption */
if (yHigh + yDim > ySysDim) /* make sure we're not off screen */
yHigh = ySysDim - yDim;
MoveWindow(hDlg, /* window to move */
(xSysDim - xDim)/2, /* new upper left x */
yHigh, /* new upper left y */
xDim, /* window height (unchanged) */
yDim, /* window width (unchanged) */
TRUE); /* please repaint */
}
return (TRUE);
case WM_LBUTTONDOWN:
/* Did user clicks mouse over "Stop" button during a search? */
if (SearchState == Searching)
{
POINT pMouse;
SHOWF3
("FileListProc: window %#x got left mouse button at (%u, %u)\n",
hDlg, LOWORD(lParam), HIWORD(lParam));
/* The mouse message returns coordinates relative to hDlg--what
* we need to know is whether these coordinates correspond to
* the location of the "Stop/Close" button/window... */
pMouse.x = LOWORD(lParam);
pMouse.y = HIWORD(lParam);
if ( ChildWindowFromPoint(hDlg, pMouse) == GetDlgItem(hDlg, 2))
{
SearchState = Stop;
return (TRUE);
}
}
/* otherwise, let Windows handle this */
return (FALSE);
case WM_COMMAND:
switch (wParam)
{
case IDOK:
case IDCANCEL:
if (SearchState == Searching) /* Stop ongoing search! */
SearchState = Stop;
else /* otherwise, close the dialog box */
{
struct WinList *t1, *t2;
DestroyWindow(hDlg); /* Remove dialog box. */
t1 = &WinListHead; /* and remove handle from list */
t2 = WinListHead.next;
for (; t2; t1=t2, t2=t2->next)
{
if (t2->hWin == hDlg)
{
SHOWF2
("FileListProc: Deleting handle %#x in structure at %p\n",
t2->hWin, t2);
t1->next = t2->next;
free (t2);
break;
}
}
}
return (TRUE);
default:
return (FALSE); /* Dialog message NOT processed. */
}
default:
return (FALSE);
}
}
/* Search control dialog box procedure */
BOOL FAR PASCAL
SearchDlgProc (HWND hDlg, unsigned message, WORD wParam, LONG lParam)
{
switch (message)
{
case WM_ACTIVATE:
if (wParam)
CurrentDialogBox = hDlg;
return (FALSE); /* continue with default processing */
case WM_PAINT:
return (ShowOurIcon(hDlg));
case WM_INITDIALOG:
{
int xSysDim, ySysDim, xDim, yDim;
int DriveCount, i, drive;
RECT wRect;
HWND hDirList;
char buffer[10];
/* move main window to upper, mid screen */
xSysDim = GetSystemMetrics(SM_CXSCREEN);
ySysDim = GetSystemMetrics(SM_CYSCREEN);
GetWindowRect(hDlg, (LPRECT) &wRect);
xDim = wRect.right - wRect.left;
yDim = wRect.bottom - wRect.top;
MoveWindow(hDlg, /* window to move */
(xSysDim - xDim)/2, /* new upper left x */
(ySysDim - yDim)/3, /* new upper left y */
xDim, /* window height (unchanged) */
yDim, /* window width (unchanged) */
TRUE); /* please repaint */
/* fill the drives box with available drives */
/* the 0x4000 | 0x8000 flag asks for drives ONLY */
DlgDirList(hDlg, "*.*", IDC_DIRLIST, 0, 0x4000 | 0x8000);
/* Select all fixed drives. Go through the listbox backwards
so that the selection box ends up on the first selected
drive rather than the last one. */
hDirList = GetDlgItem(hDlg, IDC_DIRLIST);
DriveCount = SendMessage(hDirList, LB_GETCOUNT, 0, (LONG) 0);
for (i=DriveCount-1; i>=0 ; i--)
{
SendMessage(hDirList, LB_GETTEXT, i, (LONG) (LPSTR) buffer);
drive = tolower(buffer[2]) - 'a';
if (GetDriveType(drive) == DRIVE_FIXED)
SendMessage(hDirList, LB_SETSEL, TRUE, (LONG) i);
}
/* set default file spec to "", limit it to FILEMAX
characters, and give it the focus */
SetDlgItemText(hDlg, IDC_FILESPEC, (LPSTR) "");
SendDlgItemMessage(hDlg, IDC_FILESPEC, EM_LIMITTEXT,
FILEMAX, NULL);
PostMessage(hDlg, WM_NEXTDLGCTL, IDC_FILESPEC, (LONG) 1);
/* and lastly, disable the "search" box */
EnableWindow(GetDlgItem(hDlg, 1), FALSE);
}
return (TRUE);
case WM_COMMAND:
switch (wParam)
{
case IDOK: /* Search! */
{
char buffer[11+FILEMAX]; /* for "FileFind: aabbccddee.xxx"*/
char buffer2[4+FILEMAX]; /* for "a:\aabbccddee.xxx" */
struct WinList *t;
static long TabStops[3] = {4*20, 4*30, 4*40};
int DriveCount, i;
HWND hDirList, hFileListBox, hFL;
HCURSOR hSaveCursor;
SearchState = Searching;
hFL = 0;
hFL = CreateDialog(hAppInstance, "FileListBox", NULL,
fpFileListProc);
if (!hFL) /* Oops! Couldn't create dialog box! */
{
MessageBox(hDlg, (LPSTR) "Can't open new window!",
(LPSTR) "FileFind", MB_SYSTEMMODAL
| MB_OK | MB_ICONEXCLAMATION);
SearchState = Idle;
return (TRUE);
}
strcpy(buffer, "FileFind: ");
SendDlgItemMessage(hDlg, IDC_FILESPEC, WM_GETTEXT,
FILEMAX+1, (LONG) (LPSTR) buffer + 10);
SetWindowText(hFL, (LPSTR) buffer);
SendDlgItemMessage(hFL, IDC_FILELIST, LB_SETTABSTOPS,
3, (LONG) (LPSTR) &TabStops);
/* put in our list of window handles */
if ((t = mymalloc(hDlg, sizeof(struct WinList))) == NULL)
{
DestroyWindow(hFL);
SearchState = Idle;
return (TRUE);
}
t->hWin = hFL;
t->next = WinListHead.next;
WinListHead.next = t;
SHOWF2
("SearchDlgProc: Adding handle %#x in structure at %p\n",
hFL, t);
/* Now, fill it up. Start by changing the cursor
* and letting the search results window capture the mouse.*/
hSaveCursor = SetCursor(hHourGlass);
SetCapture(hFL);
/* move basic pattern to beginning of buffer */
strcpy(buffer, buffer+10);
hDirList = GetDlgItem(hDlg, IDC_DIRLIST);
hFileListBox = GetDlgItem(hFL, IDC_FILELIST);
DriveCount = SendMessage(hDirList, LB_GETCOUNT, 0, (LONG) 0);
filecount = 0;
for (i=0; i < DriveCount; i++)
/* ask each entry if it is selected */
if (SendMessage(hDirList, LB_GETSEL, i, NULL))
{
/* If so, get the name of the drive ... */
SendMessage(hDirList, LB_GETTEXT, i,
(LONG) (LPSTR) buffer2);
buffer2[0] = toupper(buffer2[2]);
strcpy(buffer2+1, ":\\");
/* ... update our status messages ... */
SendDlgItemMessage(hFL, IDC_DRIVE, WM_SETTEXT, 0,
(LONG) (LPSTR) buffer2);
SendDlgItemMessage(hFL, IDC_DOTS, WM_SETTEXT, 0,
(LONG) (LPSTR) " ");
/* ... and search the drive. */
if (ffwalk(buffer2, buffer, hFL))
break; /* exit loop if error occurs */
}
/* Restore the cursor and mouse */
SetCursor(hSaveCursor);
ReleaseCapture();
/* display file count */
sprintf(buffer, "%d", filecount);
strcpy(buffer2, "Files");
if (filecount == 1)
buffer2[4] = '\0';
SendDlgItemMessage(hFL, IDC_DRIVE,
WM_SETTEXT, 0, (LONG) (LPSTR) buffer);
SendDlgItemMessage(hFL, IDC_DOTS, WM_SETTEXT, 0,
(LONG) (LPSTR) buffer2);
if (SendMessage(hFileListBox, LB_GETCOUNT, 0, 0L) == 0)
SendMessage(hFileListBox, LB_ADDSTRING, 0,
(LONG) (LPSTR) "-none-");
/* select first item in box */
SendDlgItemMessage(hDlg, IDC_FILELIST,
LB_SETCURSEL, 0, NULL);
/* and finally, change the Stop button to say Close */
SendDlgItemMessage(hFL, 2, WM_SETTEXT, 0,
(LONG) (LPSTR) "&Close");
}
SearchState = Idle;
return (TRUE);
case IDCANCEL:
{
struct WinList *t;
/* Destroy remaining filespec dialog boxes. */
for (t = WinListHead.next; t; t = t->next)
{
SHOWF1
("SearchDlgProc: Destroying window handle %#x\n",
t->hWin);
DestroyWindow(t->hWin);
}
DestroyWindow(hDlg); /* Remove main dialog box. */
PostQuitMessage(0);
}
return (TRUE);
case IDC_ABOUT: /* show AboutBox */
{
FARPROC lpAboutDlgProc;
lpAboutDlgProc =
MakeProcInstance(AboutDlgProc, hAppInstance);
DialogBox(hAppInstance, "AboutBox", hDlg, lpAboutDlgProc);
FreeProcInstance(lpAboutDlgProc);
}
return (TRUE);
case IDC_FILESPEC:
/* enable the "Search" button only when there is a FILESPEC */
if (HIWORD(lParam) == EN_CHANGE)
{
if (SendDlgItemMessage(hDlg, IDC_FILESPEC, WM_GETTEXTLENGTH,
0, 0L))
EnableWindow(GetDlgItem(hDlg, 1), TRUE);
else
EnableWindow(GetDlgItem(hDlg, 1), FALSE);
return (TRUE);
}
else return (FALSE);
default:
return (FALSE);
}
default:
return (FALSE);
}
}
/* "WinMain - program entry point */
/* program entry: WinMain
**
** The unusual feature of this program is that it does not create
** a main window. Instead, it creates a dialog box that completely
** controls the program. The only part of the control logic that is at
** the "main" level is a check for the F6 key which is used to switch
** between dialog boxes.
*/
int PASCAL
WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpCmdLine,
int nCmdShow)
{
FARPROC lpSearchDlgProc;
HWND hParent, hLast;
MSG Msg;
struct WinList *t;
#if defined(DEBUG)
if ((debugfile = fopen("debug.log", "w")) == NULL)
return (FALSE);
fprintf(debugfile, "FF: loaded\n");
#endif
/* initialization */
hAppInstance = hInstance;
WinListHead.next = NULL;
hHourGlass = LoadCursor(NULL, IDC_WAIT);
CurrentDialogBox = NULL;
HIcon = LoadIcon (hAppInstance,"ffIcon");
fpFileListProc = MakeProcInstance(FileListProc, hInstance);
lpSearchDlgProc = MakeProcInstance(SearchDlgProc, hInstance);
WinListHead.hWin =
CreateDialog(hInstance, "SearchDlg", NULL, lpSearchDlgProc);
SHOWF1
("WinMain: Handle to master dialog box is %#x\n", WinListHead.hWin);
while (GetMessage((LPMSG) &Msg, NULL, NULL, NULL))
{
/* watch for F6, the key that cycles between windows */
if (Msg.message == WM_KEYDOWN && Msg.wParam == VK_F6)
{
/* find top level window */
hLast = Msg.hwnd;
while (IsWindow(hParent = GetParent(hLast)))
hLast = hParent;
/* now, find that window in our window list */
for (t=&WinListHead; t; t=t->next)
{
if (t->hWin == hLast) /* found self in list */
{
/* now, find next window that isn't iconic */
for (t = t->next; t->hWin != hLast; t = t->next)
{
if (!t)
t = &WinListHead;
if (!IsIconic(t->hWin))
break;
}
SHOWF1("Setting focus to window %#x\n", t->hWin);
if (t->hWin != hLast)
SetFocus(t->hWin);
break;
}
}
}
/* see if the message belongs to a dialog box */
if (CurrentDialogBox != NULL &&
IsWindow(CurrentDialogBox) &&
IsDialogMessage(CurrentDialogBox, (LPMSG) &Msg))
;
/* if it didn't, give it standard processing */
else
{
TranslateMessage ((LPMSG) &Msg);
DispatchMessage ((LPMSG) &Msg);
}
}
/* when we get to here, all is done - cleanup & exit! */
#if defined(DEBUG)
fprintf(debugfile, "Dump of WinList:\n");
for (t = WinListHead.next; t; t=t->next)
fprintf(debugfile, "WinList structure at %p contains handle %#x\n",
t, t->hWin);
fclose(debugfile);
#endif
FreeProcInstance(lpSearchDlgProc);
FreeProcInstance(fpFileListProc);
return(FALSE);
}