PTDLGS.C

#include "porttool.h" 
#include "port.h"

int DLGOFFSET = 100;

RESULTrIssue;

HANDLE hBkFileHeap;
extern HWND hDlgPort;
extern HWND hDlgPortStatus;


/* function prototypes for helper functions */
void WINAPI GrowDialog (HWND, BOOL);
BOOL WINAPI GetHelpFileName (char *);
BOOL WINAPI BuildFileList (char *, LPBKFILELIST *);
BOOL WINAPI AddFile (char *, char *, BKFILELIST *);
BOOL WINAPI RemoveFile (char *, LPBKFILELIST *);
BOOL WINAPI FreeFileList (BKFILELIST *);

BOOL MySetEvent (HWND hWnd, HANDLE hEvent);
BOOL MyResetEvent (HWND hWnd, HANDLE hEvent);

/* port options dialog */
BOOL WINAPI OptionsDlgProc (
HWND hDlg,
UINT uMsg,
UINT uParam,
LONG lParam)
{
BOOL bRet = TRUE;
static DWORD *dwPTFlags;
static HFONT hStrikeoutFont;
static HFONT hSystemFont;
LOGFONT lf;

switch (uMsg)
{
case WM_INITDIALOG:
/* create strikeout font for ignored tokens */
hSystemFont = GetStockObject (SYSTEM_FONT);
GetObject (hSystemFont, sizeof (LOGFONT), &lf);
lf.lfStrikeOut = TRUE;
hStrikeoutFont = CreateFontIndirect (&lf);

/* initialize token control with stock system font */
SendMessage (GetDlgItem (hDlg, IDC_CURTOKEN),
WM_SETFONT,
(UINT)hSystemFont,
FALSE);

/* save dwPTFlags from lParam */
dwPTFlags = (DWORD *)lParam;

/* initialize current token if any */
if (*(WORD *)rIssue.lpszToken != MAXTOKENLEN)
SetDlgItemText (hDlg, IDC_CURTOKEN, rIssue.lpszToken);
else
EnableWindow (GetDlgItem (hDlg, IDC_IGNORETOKEN), FALSE);

/* initialize search flag check boxes */
CheckDlgButton (hDlg, IDC_NOAPIS, (*dwPTFlags & PT_NOAPIS));
CheckDlgButton (hDlg, IDC_NOMESSAGES, (*dwPTFlags & PT_NOMESSAGES));
CheckDlgButton (hDlg, IDC_NOSTRUCTURES, (*dwPTFlags & PT_NOSTRUCTURES));
CheckDlgButton (hDlg, IDC_NOMACROS, (*dwPTFlags & PT_NOMACROS));
CheckDlgButton (hDlg, IDC_NOCONSTANTS, (*dwPTFlags & PT_NOCONSTANTS));
CheckDlgButton (hDlg, IDC_NOTYPES, (*dwPTFlags & PT_NOTYPES));
CheckDlgButton (hDlg, IDC_NOCUSTOM, (*dwPTFlags & PT_NOCUSTOM));
CheckDlgButton (hDlg, IDC_IGNORECASE, (*dwPTFlags & PT_IGNORECASE));

/* set focus to first check box, return FALSE */
SetFocus (GetDlgItem (hDlg, IDC_NOAPIS));
bRet = FALSE;
break;

case WM_COMMAND:
switch (LOWORD (uParam))
{
case IDOK:
/* get check box states and return as FLAGS in UM_PORT message */
*dwPTFlags = (*dwPTFlags & ~PT_IGNORECASE) ^
(IsDlgButtonChecked (hDlg, IDC_IGNORECASE) ? PT_IGNORECASE : 0);
*dwPTFlags = (*dwPTFlags & ~PT_NOAPIS) ^
(IsDlgButtonChecked (hDlg, IDC_NOAPIS) ? PT_NOAPIS : 0);
*dwPTFlags = (*dwPTFlags & ~PT_NOMESSAGES) ^
(IsDlgButtonChecked (hDlg, IDC_NOMESSAGES) ? PT_NOMESSAGES : 0);
*dwPTFlags = (*dwPTFlags & ~PT_NOSTRUCTURES) ^
(IsDlgButtonChecked (hDlg, IDC_NOSTRUCTURES) ? PT_NOSTRUCTURES : 0);
*dwPTFlags = (*dwPTFlags & ~PT_NOMACROS) ^
(IsDlgButtonChecked (hDlg, IDC_NOMACROS) ? PT_NOMACROS : 0);
*dwPTFlags = (*dwPTFlags & ~PT_NOCONSTANTS) ^
(IsDlgButtonChecked (hDlg, IDC_NOCONSTANTS) ? PT_NOCONSTANTS : 0);
*dwPTFlags = (*dwPTFlags & ~PT_NOTYPES) ^
(IsDlgButtonChecked (hDlg, IDC_NOTYPES) ? PT_NOTYPES : 0);
*dwPTFlags = (*dwPTFlags & ~PT_NOCUSTOM) ^
(IsDlgButtonChecked (hDlg, IDC_NOCUSTOM) ? PT_NOCUSTOM : 0);

case IDCANCEL:
SendMessage (GetDlgItem (hDlg, IDC_CURTOKEN), WM_SETFONT, 0, FALSE);
DeleteObject (hStrikeoutFont);
EndDialog (hDlg, LOWORD (uParam) == IDOK);
break;

case IDC_IGNORETOKEN:
/* toggle ignore bit */
*dwPTFlags ^= PT_IGNORETOKEN;

/* have control draw in strikeout if ignored */
if (*dwPTFlags & PT_IGNORETOKEN)
SendMessage (GetDlgItem (hDlg, IDC_CURTOKEN),
WM_SETFONT,
(UINT)hStrikeoutFont,
TRUE);
/* else draw in system font */
else
SendMessage (GetDlgItem (hDlg, IDC_CURTOKEN),
WM_SETFONT,
(UINT)hSystemFont,
TRUE);
break;
}
break;

default:
bRet = FALSE;
break;
}

/* return (message was processed); */
return bRet;
}



/* port options dialog */
BOOL WINAPI PortDlgProc (
HWND hDlg,
UINT uMsg,
UINT uParam,
LONG lParam)
{
BOOL bRet = TRUE;
static DWORD dwPTFlags;
static BOOL bSearching = TRUE;
static BOOL bHelpActive = FALSE, bIsHelpFile = FALSE;
static HBRUSH hBkBrush;
static HWND hWndEdit;
static HANDLE hEditData = NULL;
static int nIssues = 0;
static int iLineNo, iStartPos;
static HLOCAL hToken, hHelp, hIssue, hSuggest;
static HLOCAL hEditLine;

static UINT uLen = 0;


switch (uMsg)
{
case WM_INITDIALOG:
{
char lpszTitle[MAX_PATH];
char lpszFilename[MAX_PATH];
RECT rc;

HDC hDC;
HFONT hFont;
TEXTMETRIC tm;

hFont = GetStockObject(SYSTEM_FONT);
hDC = GetDC(NULL);
hFont = SelectObject(hDC, hFont);
GetTextMetrics(hDC, &tm);
SelectObject(hDC, hFont);
ReleaseDC(NULL, hDC);
DLGOFFSET = tm.tmHeight * 5;

/* reposition self on bottom of screen */
GetWindowRect (hDlg, &rc);
SetWindowPos (hDlg,
NULL,
rc.left,
GetSystemMetrics (SM_CYSCREEN) -
(rc.bottom - rc.top + DLGOFFSET),
rc.right-rc.left,
rc.bottom-rc.top,
SWP_NOZORDER | SWP_NOSIZE);

/* set help available flag */
if (GetHelpFileName (lpszTitle))
{
EnableWindow (GetDlgItem (hDlg, IDC_HELPM), TRUE);
bIsHelpFile = TRUE;
}

/* allocate strings for Issue struct from local heap to reduce stack overhead */
if (!(rIssue.lpszToken = LocalLock (hToken = LocalAlloc (LHND, MAXTOKENLEN))) ||
!(rIssue.lpszHelpStr = LocalLock (hHelp = LocalAlloc (LHND, MAXHELPLEN))) ||
!(rIssue.lpszIssue = LocalLock (hIssue = LocalAlloc (LHND, MAXISSUELEN))) ||
!(rIssue.lpszSuggest = LocalLock (hSuggest = LocalAlloc (LHND, MAXSUGGESTLEN))))
{
ErrorNotify (hDlg, IDS_MEMORYFAILED);
PostMessage (hDlg, WM_COMMAND, IDC_DONE, 0);
break;
}
/* initialize line and token offset position stuff */
iLineNo = 0;
iStartPos = 0;
rIssue.nPosToken = 0;

/* initialize background brush for use in WM_CTLCOLOR message */
hBkBrush = (HBRUSH)GetClassLong (hDlg, GCL_HBRBACKGROUND);

/* set initial search flags to default */
dwPTFlags = 0;

/* initialize filename in caption */
LoadString (GetModuleHandle (NULL), IDS_PORTFILE, lpszTitle, MAX_PATH);
GetFileFromPath (lpszFilePath, lpszFilename);
strcat (lpszTitle, lpszFilename);
SetWindowText (hDlg, lpszTitle);

/* IDC_SUGGESTION to SW_HIDE */
ShowWindow (GetDlgItem (hDlg, IDC_SUGGESTION), SW_HIDE);
ShowWindow (GetDlgItem (hDlg, IDC_SUGGESTLABEL), SW_HIDE);

/* get edit window and data handle */
hWndEdit = (HWND)GetWindowLong (GetParent (hDlg), WL_HWNDEDIT);

#if !defined (WIN32)

hEditData = (HANDLE)SendMessage (hWndEdit, EM_GETHANDLE, 0, 0);

#else
{
char *lpEditData;
char sz[80];
MEMORYSTATUS memstat;

uLen = GetWindowTextLength (hWndEdit);
hEditData = LocalAlloc (LHND, uLen+1);
if (hEditData == NULL) {
memstat.dwLength = sizeof(MEMORYSTATUS);
GlobalMemoryStatus (&memstat);
wsprintf (sz, "Failed Allocation: %u | %u (%u%%)", (UINT)uLen+1, (UINT)memstat.dwAvailPhys, memstat.dwMemoryLoad);
//MessageBox (GetFocus(), sz, "PortTool", MB_OK);
uLen = 500000;
while (hEditData == NULL && uLen > 1000) {
uLen -= 1000;
hEditData = LocalAlloc (LHND, uLen+1);
}
wsprintf (sz, "hEditData = %u : uLen = %u", (UINT)hEditData, (UINT)uLen);
//MessageBox (GetFocus(), sz, "PortTool", MB_OK);
}
lpEditData = LocalLock (hEditData);
if (lpEditData == NULL) {
MessageBox (GetFocus(), "Unalble To Lock Memory!", "PortTool", MB_OK);
} else {
UINT i;
i = GetWindowText (hWndEdit, lpEditData, uLen+1);
wsprintf (sz, "length: %u", i);
//MessageBox (GetFocus(), sz, "PortTool", MB_OK);
}
LocalUnlock (hEditData);
}
#endif

/* allocate here, reallocate later when needed */
hEditLine = LocalAlloc (LHND, 1);

/* post message to start ball rolling */
PostMessage (hDlg, WM_COMMAND, (UINT)IDC_CONTINUE, 0);

/* don't worry about focus here since were going to drive the search anyway */
bRet = TRUE;
}
//MessageBox (GetFocus(), "End Of Init", "PortTool", MB_OK);
break;

case WM_COMMAND:
switch (LOWORD (uParam))
{
case IDC_CONTINUE:
{
int iLastLine, nCharOffset, nLineLen;
MSG msg;
char lpszBuff[MAXTOKENLEN];
char *lpszLine;
char *lpLine;
char *lpEditData;

/* disable continue button */
EnableWindow (GetDlgItem (hDlg, IDC_CONTINUE), FALSE);
EnableWindow (GetDlgItem (hDlg, IDC_OPTIONS), FALSE);
EnableWindow (GetDlgItem (hDlg, IDCANCEL), TRUE);

/* set IDC_SEARCHFOUND to green searching */
LoadString (GetModuleHandle (NULL), IDS_SEARCHING,
lpszBuff,
sizeof (lpszBuff));
SetWindowText (GetDlgItem (hDlg, IDC_SEARCHFOUND), lpszBuff);
bSearching = TRUE;

/* set last line */
iLastLine = (int)SendMessage (hWndEdit, EM_GETLINECOUNT, 0, 0);

/* find next port issue */
while (TRUE)
{
if (iLineNo >= iLastLine)
{
/* no more issues found, so clean up and go away */
ErrorNotify (hDlg, IDS_NOMOREPORTISSUES);

/* nullify any selection in line edit control */
SendMessage (GetDlgItem (hDlg, IDC_LINE), EM_SETSEL, 0, 0);
break;
}

/* increment line no */
SetWindowText (GetDlgItem (hDlg, IDC_LINENO),
itoa (iLineNo, lpszBuff, 10));

/* get length and number of edit line */
nCharOffset = SendMessage (hWndEdit, EM_LINEINDEX, iLineNo, 0);
if ((nLineLen = SendMessage (hWndEdit, EM_LINELENGTH, nCharOffset, 0)) <= 2)
goto NEXT_LINE;

/* allocate enough memory for edit line */
if (!(hEditLine = LocalReAlloc (hEditLine,
nLineLen+1,
LHND)))
{
/* no more issues found, so clean up and go away */
ErrorNotify (hDlg, IDS_MEMORYFAILED);
PostMessage (hDlg, WM_COMMAND, IDC_DONE, 0);
break;
}

/* get line from edit control, and null terminate */

/* get edit window and data handle */

lpEditData = LocalLock (hEditData);

lpLine = lpszLine = LocalLock (hEditLine);

strncpy (lpszLine, lpEditData+nCharOffset, nLineLen);
lpszLine[nLineLen] = 0;

/* increment the token position for multiple errors in a line */
lpLine += iStartPos;
LocalUnlock (hEditData);

/* initialize line and hilight token */
SetWindowText (GetDlgItem (hDlg, IDC_LINE), lpszLine);

/* reinitialize rIssue strings lengths */
*(WORD *)rIssue.lpszToken = MAXTOKENLEN;
*(WORD *)rIssue.lpszHelpStr = MAXHELPLEN;
*(WORD *)rIssue.lpszIssue = MAXISSUELEN;
*(WORD *)rIssue.lpszSuggest = MAXSUGGESTLEN;

/* search next line */
if (CheckString (lpLine, dwPTFlags, &rIssue))
{
/* set SEARCHFOUND string to found */
LoadString (GetModuleHandle (NULL),
IDS_FOUND,
lpszBuff,
sizeof (lpszBuff));
strcat (lpszBuff, rIssue.lpszToken);
SetWindowText (GetDlgItem (hDlg, IDC_SEARCHFOUND), lpszBuff);

/* reenable options button */
EnableWindow (GetDlgItem (hDlg, IDC_OPTIONS), TRUE);

/* set searching flag off */
bSearching = FALSE;

/* increment issue cnt */
SetWindowText (GetDlgItem (hDlg, IDC_ISSUECNT),
itoa (++nIssues, lpszBuff, 10));

/* initialize Issue */
SetWindowText (GetDlgItem (hDlg, IDC_ISSUE), rIssue.lpszIssue);

/* if help, enble button */
EnableWindow (GetDlgItem (hDlg, IDC_HELPM),
((*(rIssue.lpszSuggest) != 0) && bIsHelpFile));

/* if suggest, show suggestion */
if (*(rIssue.lpszSuggest))
{
SetWindowText (GetDlgItem (hDlg, IDC_SUGGESTION),
rIssue.lpszSuggest);
if (!IsWindowVisible (GetDlgItem (hDlg, IDC_SUGGESTION)))
GrowDialog (hDlg, TRUE);
}

else if (IsWindowVisible (GetDlgItem (hDlg, IDC_SUGGESTION)))
GrowDialog (hDlg, FALSE);

/* scroll parent edit control and select offending text */
SendMessage (hWndEdit, EM_LINESCROLL, 0, iLineNo -
SendMessage (hWndEdit, EM_GETFIRSTVISIBLELINE, 0, 0));
SendMessage (hWndEdit,
EM_SETSEL,
iStartPos + nCharOffset + rIssue.nPosToken,
iStartPos + nCharOffset + rIssue.nPosToken +
strlen (rIssue.lpszToken));

/* select text in line edit control */
SendMessage (GetDlgItem (hDlg, IDC_LINE),
EM_SETSEL,
iStartPos + rIssue.nPosToken,
iStartPos + rIssue.nPosToken +
strlen (rIssue.lpszToken));

/* reset nPosToken to check rest of line */
iStartPos += (rIssue.nPosToken + strlen (rIssue.lpszToken));
LocalUnlock (hEditLine);
break;
}

/* call peek message to let user cancel if they choose */
if (PeekMessage (&msg,
GetDlgItem (hDlg, IDCANCEL),
WM_LBUTTONDOWN,
WM_LBUTTONDOWN,
PM_REMOVE))
{
/* reset appropriate buttons */
EnableWindow (GetDlgItem (hDlg, IDCANCEL), FALSE);
EnableWindow (GetDlgItem (hDlg, IDC_HELPM), FALSE);
EnableWindow (GetDlgItem (hDlg, IDC_OPTIONS), TRUE);

/* break to let message get delivered */
break;
}

/* also let the user exit from searching */
if (PeekMessage (&msg,
GetDlgItem (hDlg, IDC_DONE),
WM_LBUTTONDOWN,
WM_LBUTTONDOWN,
PM_REMOVE))
{
PostMessage (hDlg, WM_COMMAND, IDC_DONE, 0);
break;
}

/* unlock local edit line */
LocalUnlock (hEditLine);

/* reset token position */
rIssue.nPosToken = 0;
iStartPos = 0;
NEXT_LINE:
/* increment line and continue */
iLineNo++;
}

/* enable continue button unless at end of file */
if (iLineNo < iLastLine)
{
EnableWindow (GetDlgItem (hDlg, IDC_CONTINUE), TRUE);
SetFocus (GetDlgItem (hDlg, IDC_CONTINUE));
}
else
{
EnableWindow (GetDlgItem (hDlg, IDC_CONTINUE), FALSE);
EnableWindow (GetDlgItem (hDlg, IDCANCEL), FALSE);
SetFocus (GetDlgItem (hDlg, IDC_DONE));
}
}
break;

case WM_CLOSE:
case IDC_DONE:
{
char lpszFile[MAX_PATH];

if (bHelpActive &&
GetHelpFileName (lpszFile))
WinHelp (hDlg, lpszFile, HELP_QUIT, 0);

/* clean up and go away */
LocalUnlock (hToken); LocalFree (hToken);
LocalUnlock (hHelp); LocalFree (hHelp);
LocalUnlock (hIssue); LocalFree (hIssue);
LocalUnlock (hSuggest); LocalFree (hSuggest);
LocalFree (hEditLine);
DestroyWindow (hDlg);
hDlgPort = NULL;

}
break;

case IDC_OPTIONS:
{
DWORD dwOptions = dwPTFlags;

/* call dialog to start port process */
if (DialogBoxParam (GetModuleHandle (NULL),
IDD_OPTIONSDLG,
hDlg,
OptionsDlgProc,
(LPARAM)&dwOptions))
{
dwPTFlags = dwOptions;

/* if PT_IGNORETOKEN, call CheckString */
if (dwOptions & PT_IGNORETOKEN)
{
CheckString (rIssue.lpszToken, dwPTFlags, NULL);
dwPTFlags ^= PT_IGNORETOKEN;
}
}

}
break;

case IDC_HELPM:
{
char lpszFile[MAX_PATH];

if (bIsHelpFile && GetHelpFileName (lpszFile))
{
WinHelp (hDlg, lpszFile, HELP_KEY, (DWORD)rIssue.lpszHelpStr);
bHelpActive = TRUE;
}
}
break;

case IDC_RESTART:
iLineNo = 0;
rIssue.nPosToken = 0;
iStartPos = 0;
PostMessage (hDlg, WM_COMMAND, IDC_CONTINUE, 0);
break;
}
break;

default:
bRet = FALSE;
break;
}

/* return (message was processed); */
return bRet;
}




/* background porting status dialog */
BOOL WINAPI BkPortDlgProc (
HWND hDlg,
UINT uMsg,
UINT uParam,
LONG lParam)
{
BOOL bRet = TRUE;
char szFileName[MAX_PATH];
char szFilePath[MAX_PATH];
static BKFILELIST *lpbkFiles;
static int iCurThread;
static BOOL bStarted = FALSE;
BKFILELIST *lpNode;

//char szDebug[80];

// wsprintf (szDebug, "%i : [0x%X - 0x%X]", uMsg, uParam, lParam);
// OutputDebugString (szDebug);

switch (uMsg)
{
case WM_INITDIALOG:
{
HWND hIssues = GetDlgItem (hDlg, IDC_ISSUES);
HWND hLines = GetDlgItem (hDlg, IDC_LINES);
HWND hComplete = GetDlgItem (hDlg, IDC_COMPLETE);

/* set background icon to porttool background icon and start minimized */
SetClassLong (hDlg,
GCL_HICON,
(LONG)LoadIcon (GetModuleHandle (NULL), IDBkPort));

lpbkFiles = NULL;
iCurThread = -1;

/* build list of files to port from lParam */
if (lParam)
{
if (!BuildFileList ((char *)lParam, &lpbkFiles))
{
lpbkFiles = NULL;
break;
}
}

else
{
/* get file from user first */
*szFileName = 0;
*szFilePath = 0;

GetFileName (hDlg, szFileName, szFilePath);
if (!BuildFileList (szFilePath, &lpbkFiles))
{
lpbkFiles = NULL;
break;
}
}

lpNode = lpbkFiles;
/* initialize each file in list */
while (lpNode)
{
/* add filename to listbox */
SendMessage (GetDlgItem (hDlg, IDC_FILELIST),
LB_ADDSTRING,
0,
(LPARAM)lpNode->bkFile.szFile);

/* initialize some stuff */
lpNode->bkFile.hDlg = hDlg;
lpNode->bkFile.dwPTFlags = PT_DEFAULT;

/* start background thread on each file */
if (!StartBkPortThread (&lpNode->bkFile)) {
MessageBox(GetFocus(), "Failed to spawn background porting thread", "PortTool", MB_OK);
}

/* traverse list */
lpNode = lpNode->Next;
}

/* select first thread in listbox */
SendMessage (GetDlgItem (hDlg, IDC_FILELIST), LB_SETCURSEL, 0, 0);
SetDlgItemText (hDlg, IDC_FILEPATH, lpbkFiles->bkFile.szFilePath);

/* if started with /b switch */
if (!GetParent (hDlg))
ShowWindow (hDlg, SW_SHOWMINIMIZED);
else
MySetEvent (hDlg, lpbkFiles->hEvents[BKPORT_STATUS]);

iCurThread = 0;
bStarted = TRUE;
}
break;

case WM_SHOWWINDOW:
if (bStarted)
{
int i = 0;

lpNode = lpbkFiles;
while (i++ < iCurThread)
lpNode = lpNode->Next;

if (!uParam && lpNode)
MyResetEvent (hDlg, lpNode->hEvents[BKPORT_STATUS]);
else if(lpNode)
MySetEvent (hDlg, lpNode->hEvents[BKPORT_STATUS]);
}
break;

case WM_SIZE:
if (bStarted) {
int i = 0;

lpNode = lpbkFiles;

while (i++ < iCurThread) {
lpNode = lpNode->Next;
}

if (uParam == SIZEICONIC && lpNode) {
MyResetEvent (hDlg, lpNode->hEvents[BKPORT_STATUS]);
} else if(lpNode) {
MySetEvent (hDlg, lpNode->hEvents[BKPORT_STATUS]);
}
}
break;

case UM_STATUSUPDATE:
{
char Buff[10];

/* update status info controls */
SetDlgItemText (hDlg, IDC_ISSUES, itoa (LOWORD (uParam), Buff, 10));
SetDlgItemText (hDlg, IDC_COMPLETE, itoa (HIWORD (uParam), Buff, 10));
SetDlgItemText (hDlg, IDC_LINES, itoa (lParam, Buff, 10));
}
break;

case UM_THREADCOMPLETE:
{
int iThread = 0;

/* find handle in list */
lpNode = lpbkFiles;
while (lpNode)
{
if ((HANDLE)uParam == lpNode->bkFile.hThread)
break;
lpNode = lpNode->Next;
iThread++;
}

if (lpNode)
{
/* remove file list item */
RemoveFile (lpNode->bkFile.szFilePath, &lpbkFiles);

/* remove item from list box */
SendMessage (GetDlgItem (hDlg, IDC_FILELIST),
LB_DELETESTRING,
iThread,
0);

/* if current thread ended and more threads exist */
if (iThread == iCurThread &&
lpbkFiles &&
SendMessage (GetDlgItem (hDlg, IDC_FILELIST), LB_GETCOUNT, 0, 0))
{
SendMessage (GetDlgItem (hDlg, IDC_FILELIST), LB_SETCURSEL, 0, 0);
MySetEvent (hDlg, lpbkFiles->hEvents[BKPORT_STATUS]);
iCurThread = 0;
}

else if (iThread == iCurThread)
{
iCurThread = -1;
PostMessage (hDlg, WM_COMMAND, IDC_BKDONE, 0);
}

/* clean up controls */
SetDlgItemText (hDlg, IDC_FILEPATH, "");
PostMessage (hDlg, UM_STATUSUPDATE, 0, 0);
}

else
{
CHAR szBuf[MAX_PATH];
LoadString((HANDLE)GetModuleHandle(NULL),
IDS_ERR_INVALID_THREADHND,
szBuf,sizeof(szBuf));
MessageBox (hDlg, szBuf, NULL, MB_ICONSTOP | MB_OK);
ExitProcess (FALSE);
}

}
break;

case WM_COMMAND:
switch (LOWORD (uParam))
{
case IDC_FILELIST:
/* if new file selected change update signal to active thread */
if (HIWORD (uParam) == LBN_SELCHANGE)
{
int i = 0;
int iNewThread = SendMessage (GetDlgItem (hDlg, IDC_FILELIST),
LB_GETCURSEL,
0,
0);

/* reset current thread */
lpNode = lpbkFiles;
while (lpNode)
{
if (i == iCurThread)
MyResetEvent (hDlg, lpNode->hEvents[BKPORT_STATUS]);

if (i == iNewThread)
{
MySetEvent (hDlg, lpNode->hEvents[BKPORT_STATUS]);
SetDlgItemText (hDlg,
IDC_FILEPATH,
lpNode->bkFile.szFilePath);
}

lpNode = lpNode->Next;
i++;
}

iCurThread = iNewThread;
}
break;

case IDC_ABORTFILE:
{
int i = 0;
HCURSOR hOldCursor;

/* reset current thread */
lpNode = lpbkFiles;
while (lpNode)
{
if (i == iCurThread)
{
/* put hourglass cursor up */
hOldCursor = (HCURSOR)SetClassLong (hDlg, GCL_HCURSOR, 0);
SetCursor (LoadCursor (NULL, IDC_WAIT));

/* abort porting file where it is */
MySetEvent (hDlg, lpNode->hEvents[BKPORT_ABORT]);

/* remove file from list when thread is dead */
WaitForSingleObject (lpNode->bkFile.hThread, INFINITE);
RemoveFile (lpNode->bkFile.szFilePath, &lpbkFiles);

/* replace original cursor */
SetClassLong (hDlg, GCL_HCURSOR, (LONG)hOldCursor);
SetCursor (hOldCursor);

/* update listbox */
SendMessage (GetDlgItem (hDlg, IDC_FILELIST),
LB_DELETESTRING,
iCurThread,
0);

/* select new event if any in listbox */
if (SendMessage (GetDlgItem (hDlg, IDC_FILELIST),
LB_GETCOUNT,
0,
0))
{
SendMessage (GetDlgItem (hDlg, IDC_FILELIST),
LB_SETCURSEL,
0,
0);
MySetEvent (hDlg, lpbkFiles->hEvents[BKPORT_STATUS]);
iCurThread = 0;
}

else
{
iCurThread = -1;
PostMessage (hDlg, WM_COMMAND, IDC_DONE, 0);
}

/* clean up controls */
SetDlgItemText (hDlg, IDC_FILEPATH, "");
PostMessage (hDlg, UM_STATUSUPDATE, 0, 0);
break;
}

lpNode = lpNode->Next;
i++;
}
}
break;

case IDC_ADDFILE:
{
/* get file from user first */
*szFileName = 0;
*szFilePath = 0;

/* add a file to the list */
if (GetFileName (hDlg, szFileName, szFilePath))
{
/* if new list */
if (!lpbkFiles)
{
if (!BuildFileList (szFilePath, &lpbkFiles))
{
lpbkFiles = NULL;
break;
}
}
else if (!AddFile (szFilePath, szFileName, lpbkFiles))
break;

/* find node in list */
lpNode = lpbkFiles;
while (lpNode)
{
if (!strcmp (lpNode->bkFile.szFilePath, szFilePath))
break;
lpNode = lpNode->Next;
}

if (lpNode)
{
/* add filename to listbox */
SendMessage (GetDlgItem (hDlg, IDC_FILELIST),
LB_ADDSTRING,
0,
(LPARAM)lpNode->bkFile.szFile);

/* initialize some stuff */
lpNode->bkFile.hDlg = hDlg;
lpNode->bkFile.dwPTFlags = PT_DEFAULT;

/* start background thread on this file */
StartBkPortThread (&lpNode->bkFile);

/* if first thread */
if (iCurThread == -1 ||
SendMessage (GetDlgItem (hDlg, IDC_FILELIST),
LB_GETCOUNT, 0, 0) == 1)
{
iCurThread = 0;
SendMessage (GetDlgItem (hDlg, IDC_FILELIST),
LB_SETCURSEL,
0,
0);
SendMessage (hDlg,
WM_COMMAND,
MAKELONG (IDC_FILELIST, LBN_SELCHANGE),
0);
}
}
}
}
break;

case IDC_CHANGEOPTIONS:
{
DWORD dwFlags;

dwFlags = 0L;
dwFlags = (dwFlags & ~PT_IGNORECASE) ^
(IsDlgButtonChecked (hDlg, IDC_BKIGNORECASE) ? PT_IGNORECASE : 0);
dwFlags = (dwFlags & ~PT_NOAPIS) ^
(IsDlgButtonChecked (hDlg, IDC_BKNOAPIS) ? PT_NOAPIS : 0);
dwFlags = (dwFlags & ~PT_NOMESSAGES) ^
(IsDlgButtonChecked (hDlg, IDC_BKNOMESSAGES) ? PT_NOMESSAGES : 0);
dwFlags = (dwFlags & ~PT_NOSTRUCTURES) ^
(IsDlgButtonChecked (hDlg, IDC_BKNOSTRUCTURES) ? PT_NOSTRUCTURES : 0);
dwFlags = (dwFlags & ~PT_NOMACROS) ^
(IsDlgButtonChecked (hDlg, IDC_BKNOMACROS) ? PT_NOMACROS : 0);
dwFlags = (dwFlags & ~PT_NOCONSTANTS) ^
(IsDlgButtonChecked (hDlg, IDC_BKNOCONSTANTS) ? PT_NOCONSTANTS : 0);
dwFlags = (dwFlags & ~PT_NOTYPES) ^
(IsDlgButtonChecked (hDlg, IDC_BKNOTYPES) ? PT_NOTYPES : 0);
dwFlags = (dwFlags & ~PT_NOCUSTOM) ^
(IsDlgButtonChecked (hDlg, IDC_BKNOCUSTOM) ? PT_NOCUSTOM : 0);

/* change the options for the file being ported */
lpbkFiles->bkFile.dwPTFlags = dwFlags;
}
break;

case IDCANCEL:
{
HCURSOR hOldCursor;
HANDLE hThreads[MAXBKTHREADS];
int i = 0;
CHAR szText[MAX_PATH]; // for LoadString()
CHAR szTitle[MAX_PATH]; // for LoadString()
HMODULE hModule = GetModuleHandle(NULL);

/* put up confirm message */
LoadString((HANDLE)hModule,
IDS_CANCEL_BKGND_PROCESS,
szText,sizeof(szText));
LoadString((HANDLE)hModule,
IDS_ABORT_TITLE,
szTitle,sizeof(szTitle));
if (MessageBox (hDlg,
szText, szTitle,
MB_ICONQUESTION | MB_OKCANCEL) == IDOK)
{
/* put hourglass cursor up */
hOldCursor = (HCURSOR)SetClassLong (hDlg, GCL_HCURSOR, 0);
SetCursor (LoadCursor (NULL, IDC_WAIT));

/* if any files in list */
if (lpbkFiles)
{
/* abort all background threads and build thread handle array */
lpNode = lpbkFiles;
while (lpNode)
{
MySetEvent (hDlg, lpNode->hEvents[BKPORT_ABORT]);
hThreads[i++] = lpNode->bkFile.hThread;
lpNode = lpNode->Next;
}

/* wait on completion of background threads */
WaitForMultipleObjects (i, hThreads, TRUE, INFINITE);

/* free background port resources */
FreeFileList (lpbkFiles);
}

SetClassLong (hDlg, GCL_HCURSOR, (LONG)hOldCursor);
SetCursor (hOldCursor);
DestroyWindow (hDlg);
hDlgPortStatus = NULL;

}
}
break;

case IDC_BKDONE:
/* if file list post message to cancel */
if (lpbkFiles)
PostMessage (hDlg, WM_COMMAND, IDCANCEL, 0);
else
DestroyWindow (hDlg);
hDlgPortStatus = NULL;
break;

default:
bRet = FALSE;
break;
}
break;

case WM_DESTROY:
/* if no parent, post quit message */
if (GetParent (hDlg) == NULL)
PostQuitMessage (1);
break;

default:
bRet = FALSE;
break;
}

return bRet;
}



/* funtion retrieves the help filename from the ini file */

BOOL WINAPI GetHelpFileName ( 
char *lpszFile)
{
char szAppName[30];
char szWinHelp[30];
char szDefault[] = "Default";
OFSTRUCT of;

/* get help filename from ini file */
LoadString (GetModuleHandle (NULL), IDS_APPNAME, szAppName, 30);
LoadString (GetModuleHandle (NULL), IDS_WINHELP, szWinHelp, 30);
GetPrivateProfileString (szAppName,
szWinHelp,
szDefault,
lpszFile,
MAX_PATH,
lpszPortIniFilePath);

/* test to see if help file exists */
return (OpenFile (lpszFile, &of, OF_EXIST) != -1);
}




/* rearrange dialog and controls */
void WINAPI GrowDialog (
HWND hDlg,
BOOL bBigger)
{
RECT rc;
int nChange = (bBigger ? DLGOFFSET : -DLGOFFSET);

/* grow main dialog */
GetWindowRect (hDlg, &rc);
SetWindowPos (hDlg,
NULL,
rc.left,
rc.top,
rc.right-rc.left,
rc.bottom-rc.top + nChange,
SWP_NOMOVE | SWP_NOZORDER);

/* move stop button down */
GetWindowRect (GetDlgItem (hDlg, IDCANCEL), &rc);
ScreenToClient (hDlg, (LPPOINT)&rc);
ScreenToClient (hDlg, (LPPOINT)&rc.right);
SetWindowPos (GetDlgItem (hDlg, IDCANCEL),
NULL,
rc.left,
rc.top + nChange,
rc.right-rc.left,
rc.bottom-rc.top,
SWP_NOSIZE | SWP_NOZORDER);

/* move CONTINUE button down */
GetWindowRect (GetDlgItem (hDlg, IDC_CONTINUE), &rc);
ScreenToClient (hDlg, (LPPOINT)&rc);
ScreenToClient (hDlg, (LPPOINT)&rc.right);
SetWindowPos (GetDlgItem (hDlg, IDC_CONTINUE),
NULL,
rc.left,
rc.top + nChange,
rc.right-rc.left,
rc.bottom-rc.top,
SWP_NOSIZE | SWP_NOZORDER);

/* move restart button down */
GetWindowRect (GetDlgItem (hDlg, IDC_RESTART), &rc);
ScreenToClient (hDlg, (LPPOINT)&rc);
ScreenToClient (hDlg, (LPPOINT)&rc.right);
SetWindowPos (GetDlgItem (hDlg, IDC_RESTART),
NULL,
rc.left,
rc.top + nChange,
rc.right-rc.left,
rc.bottom-rc.top,
SWP_NOSIZE | SWP_NOZORDER);

/* move options button down */
GetWindowRect (GetDlgItem (hDlg, IDC_OPTIONS), &rc);
ScreenToClient (hDlg, (LPPOINT)&rc);
ScreenToClient (hDlg, (LPPOINT)&rc.right);
SetWindowPos (GetDlgItem (hDlg, IDC_OPTIONS),
NULL,
rc.left,
rc.top + nChange,
rc.right-rc.left,
rc.bottom-rc.top,
SWP_NOSIZE | SWP_NOZORDER);

/* move help button down */
GetWindowRect (GetDlgItem (hDlg, IDC_HELPM), &rc);
ScreenToClient (hDlg, (LPPOINT)&rc);
ScreenToClient (hDlg, (LPPOINT)&rc.right);
SetWindowPos (GetDlgItem (hDlg, IDC_HELPM),
NULL,
rc.left,
rc.top + nChange,
rc.right-rc.left,
rc.bottom-rc.top,
SWP_NOSIZE | SWP_NOZORDER);

/* move done button down */
GetWindowRect (GetDlgItem (hDlg, IDC_DONE), &rc);
ScreenToClient (hDlg, (LPPOINT)&rc);
ScreenToClient (hDlg, (LPPOINT)&rc.right);
SetWindowPos (GetDlgItem (hDlg, IDC_DONE),
NULL,
rc.left,
rc.top + nChange,
rc.right-rc.left,
rc.bottom-rc.top,
SWP_NOSIZE | SWP_NOZORDER);

/* show suggestion edit control and label when appropriate */
ShowWindow (GetDlgItem (hDlg, IDC_SUGGESTION), (bBigger ? SW_SHOW : SW_HIDE));
ShowWindow (GetDlgItem (hDlg, IDC_SUGGESTLABEL), (bBigger ? SW_SHOW : SW_HIDE));
}




BOOL WINAPI BuildFileList (
char *lpFileList,
LPBKFILELIST *lpList)
{
char *lpFile;
char szFilePath[MAX_PATH];
char szFile[MAX_PATH];
HFILE hFile;
OFSTRUCT of;
BOOL bList = FALSE;

/* create heap for up to 50 files at a time */
if (!(hBkFileHeap = HeapCreate (HEAP_NO_SERIALIZE,
sizeof (BKFILELIST),
MAXBKTHREADS * sizeof (BKFILELIST))))
return FALSE;

/* allocate first node in list */
*lpList = (BKFILELIST *)HeapAlloc (hBkFileHeap, 0, sizeof (BKFILELIST));
(*lpList)->hEvents[BKPORT_ABORT] = NULL;

/* parse first file in list */
lpFile = strtok (lpFileList, " ");

/* loop through all files in list */
while (lpFile)
{
strcpy (szFilePath, lpFile);

/* if no path, add current directory as path */
if (!GetFileFromPath (szFilePath, szFile))
{
strcpy (szFile, szFilePath);
GetCurrentDirectory (MAX_PATH, szFilePath);
strcat (szFilePath, "\\");
strcat (szFilePath, szFile);
}

/* verify file is available */
hFile = OpenFile (szFilePath, &of, OF_READWRITE);
if (hFile != -1)
{
/* added at least one file */
bList = TRUE;

/* close file */
CloseHandle ((HANDLE)hFile);

/* add file to list */
AddFile (szFilePath, szFile, *lpList);
}

/* get next file in list */
lpFile = strtok (NULL, " ");
}

/* if no valid files, cleanup */
if (!bList)
{
HeapDestroy (hBkFileHeap);
return FALSE;
}

return TRUE;
}




BOOL WINAPI AddFile (
char *lpFilePath,
char *lpFile,
BKFILELIST *lpbkFiles)
{
BKFILELIST *lpNode;


/* if first item in list don't need to allocate */
if (!lpbkFiles->hEvents[BKPORT_ABORT])
lpNode = lpbkFiles;
else
{
lpNode = (BKFILELIST *)HeapAlloc (hBkFileHeap, 0, sizeof (BKFILELIST));
if (!lpNode)
return FALSE;

/* find end of list then add new node */
while (lpbkFiles->Next)
lpbkFiles = lpbkFiles->Next;
lpbkFiles->Next = lpNode;
}

/* initialize node structure */
strcpy (lpNode->bkFile.szFile, lpFile);
strcpy (lpNode->bkFile.szFilePath, lpFilePath);
CreateEvents (lpNode->hEvents, &lpNode->bkFile);
lpNode->Next = NULL;

return TRUE;
}




BOOL WINAPI RemoveFile (
char *lpFilePath,
LPBKFILELIST *lpbkFiles)
{
BKFILELIST *pHead = *lpbkFiles;
BKFILELIST *pTail = *lpbkFiles;

/* loop thru list until file name matches */
while (pHead)
{
if (!strcmp (lpFilePath, pHead->bkFile.szFilePath))
{
/* special case remove first node */
if (pTail == pHead)
{
*lpbkFiles = pHead->Next;
DestroyEvents (pHead->hEvents);
HeapFree (hBkFileHeap, 0, (char *)(pHead));

/* if no more nodes, destroy heap */
if (!*lpbkFiles)
HeapDestroy (hBkFileHeap);
}

else
{
pTail->Next = pHead->Next;
DestroyEvents (pHead->hEvents);
HeapFree (hBkFileHeap, 0, (char *)pHead);
}

return TRUE;
}

pTail = pHead;
pHead = pHead->Next;
}

return FALSE;
}




BOOL WINAPI FreeFileList (
BKFILELIST *lpbkFiles)
{
/* loop thru each list item */
while (lpbkFiles)
{
/* destroy event handles */
DestroyEvents (lpbkFiles->hEvents);

lpbkFiles = lpbkFiles->Next;
}

/* release entire heap */
HeapDestroy (hBkFileHeap);

return TRUE;
}


BOOL MySetEvent (HWND hWnd, HANDLE hEvent)
{
if (SetEvent(hEvent)) {
return TRUE;
} else {
return PostMessage (hWnd, (UINT)hEvent, 0, 0L);
}
}

BOOL MyResetEvent (HWND hWnd, HANDLE hEvent)
{
MSG msg;

if (ResetEvent(hEvent)) {
return TRUE;
} else {
PeekMessage (&msg, hWnd, (UINT)hEvent, (UINT)hEvent, TRUE);
return TRUE;
}
}