mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1015 lines
41 KiB
1015 lines
41 KiB
//*-----------------------------------------------------------------------
|
|
//| MODULE: MATCH.C
|
|
//| PROJECT: Windows Comparison Tool
|
|
//|
|
|
//| PURPOSE: This module contains the comparison routines used to
|
|
//| compare the contents of dialogs/menus from the file or
|
|
//| dynamically created information.
|
|
//|
|
|
//| REVISION HISTORY:
|
|
//| 04-16-92 w-steves TestDlgs (2.0) code Complete
|
|
//| 12-13-90 garysp Fixed up error codes see wcterr.h
|
|
//|
|
|
//| 11-27-90 randyki Implemented new comparison scheme,
|
|
//| clarified logged results
|
|
//| 11-07-90 randyki Cleaned up, incorporate coding
|
|
//| standards, created rev history
|
|
//| 10-09-90 garysp Created file
|
|
//*-----------------------------------------------------------------------
|
|
#include "enghdr.h"
|
|
#pragma hdrstop ("engpch.pch")
|
|
|
|
//------------------------------------------------------------------------
|
|
// Define the OutDebug macro on definition of the DEBUG macro
|
|
//------------------------------------------------------------------------
|
|
#ifdef DEBUG
|
|
#define OutDebug(N) OutputDebugString(N)
|
|
#else
|
|
#define OutDebug(N)
|
|
#endif
|
|
|
|
//------------------------------------------------------------------------
|
|
// Define the szFormat and RC macros depending on the operating
|
|
// environment (RC stands for Rect Coords)
|
|
//------------------------------------------------------------------------
|
|
#ifdef WIN
|
|
#define szFormat "%%s(%%d,%%d)x(%%d,%%d) "
|
|
#define RC(var) var.xLeft, var.yMin, var.xRight, var.yLast
|
|
#else
|
|
#define szFormat "%%s(%%ld,%%ld)x(%%ld,%%ld) "
|
|
#define RC(var) var.xLeft, var.yLast, var.xRight, var.yMin
|
|
#endif
|
|
|
|
//------------------------------------------------------------------------
|
|
// Define the fClose macro (invert the return value of _lclose())
|
|
//------------------------------------------------------------------------
|
|
#define fClose(x) (!_lclose(x))
|
|
|
|
//------------------------------------------------------------------------
|
|
// Define the EndCompare macro - spit out the footer and return the given
|
|
// value
|
|
//------------------------------------------------------------------------
|
|
#define EndCompare(rv) {OutputFooter(lpLog); return rv;}
|
|
|
|
//------------------------------------------------------------------------
|
|
// MATCH.C specific constants
|
|
//------------------------------------------------------------------------
|
|
#define CR_FUZZY 1 // fuzzy match
|
|
#define CR_MIC 2 // more in comp dialog
|
|
#define CR_CNF 4 // control(s) not found
|
|
|
|
//------------------------------------------------------------------------
|
|
// Function Prototypes
|
|
//------------------------------------------------------------------------
|
|
INT CompareControls (LPCTLDEF, LPCTLDEF, INT, INT, INT);
|
|
VOID LogControl (HFILE, LPCTLDEF, LPSTR);
|
|
VOID LogFuzzyMatch (HFILE, LPCTLDEF, LPCTLDEF);
|
|
|
|
//------------------------------------------------------------------------
|
|
// MATCH.C specific global variables
|
|
//------------------------------------------------------------------------
|
|
INT fCompFull; // Full Dlg Compare flag
|
|
INT fCompRes; // Comparison results
|
|
INT nCtlBase; // # controls in base dialog
|
|
INT nCtlComp; // # controls in compare dialog
|
|
INT nCtlFuzzy; // # fuzzy matched controls
|
|
INT nCtlExcess; // # excess controls (more in comp)
|
|
INT nCtlNotFnd; // # base controls not found
|
|
|
|
//*------------------------------------------------------------------------
|
|
//| FileLength
|
|
//|
|
|
//| PURPOSE: Determine the length of a file.
|
|
//|
|
|
//| ENTRY: hFile - Handle to file whose size is to be found
|
|
//|
|
|
//| EXIT: (long) Size of file in bytes
|
|
//*------------------------------------------------------------------------
|
|
LONG FileLength(HFILE hFile)
|
|
{
|
|
LONG lCurPos;
|
|
LONG lFileLen;
|
|
|
|
// Find the current file position so we don't screw it up
|
|
//--------------------------------------------------------------
|
|
lCurPos = M_llseek(hFile, 0L, 1);
|
|
|
|
// Find the end of the file
|
|
//--------------------------------------------------------------
|
|
lFileLen = M_llseek(hFile, 0L, 2);
|
|
|
|
// Seek back to the original file position
|
|
//--------------------------------------------------------------
|
|
M_llseek(hFile, lCurPos, 0);
|
|
|
|
return ( lFileLen );
|
|
}
|
|
|
|
|
|
//*------------------------------------------------------------------------
|
|
//| fOpenFile
|
|
//|
|
|
//| PURPOSE: Opens file and moves to the end of the file
|
|
//| if _lopen fails then do a _lcreat()
|
|
//|
|
|
//| ENTRY: lpsz - Name of file to open
|
|
//|
|
|
//| EXIT: Handle of opened file, or -1 if failed
|
|
//*------------------------------------------------------------------------
|
|
HFILE fOpenFile(LPSTR lpsz)
|
|
{
|
|
HFILE hFile;
|
|
|
|
// Attempt a normal open
|
|
//--------------------------------------------------------------
|
|
hFile = M_lopen(lpsz, OF_READWRITE);
|
|
|
|
// If normal open failed, do the _lcreat call
|
|
//--------------------------------------------------------------
|
|
if (hFile == -1)
|
|
hFile = M_lcreat(lpsz, 0);;
|
|
|
|
// Seek to end of file (if one of the above opens worked
|
|
//--------------------------------------------------------------
|
|
if (hFile != -1)
|
|
M_llseek(hFile, 0L, 2);
|
|
|
|
return( hFile );
|
|
}
|
|
|
|
//*------------------------------------------------------------------------
|
|
//| fLogStrToFile
|
|
//|
|
|
//| PURPOSE: Output a line of text into an open file.
|
|
//|
|
|
//| ENTRY: hFile - Handle of file to write string to
|
|
//| lpszOutText - String to write to file
|
|
//|
|
|
//| EXIT: TRUE if all characters in the string are written to the
|
|
//| file, or FALSE if not. File pointer is left at the end
|
|
//| of the file after the write.
|
|
//*------------------------------------------------------------------------
|
|
BOOL fLogStrToFile(HFILE hFile, LPSTR lpszOutText)
|
|
{
|
|
INT i;
|
|
LPSTR lpszTmp = lpszOutText;
|
|
|
|
// Output the string to the debug terminal....
|
|
//--------------------------------------------------------------
|
|
OutDebug( lpszOutText );
|
|
|
|
// Make sure the file handle is valid
|
|
// (CONSIDER: make a real check for a bad handle here?)
|
|
//--------------------------------------------------------------
|
|
if (hFile == -1)
|
|
return ( FALSE );
|
|
|
|
// Write the text to the file at the current file position
|
|
//--------------------------------------------------------------
|
|
i = M_lwrite(hFile, lpszOutText, lstrlen(lpszOutText));
|
|
|
|
// Put the file position
|
|
//--------------------------------------------------------------
|
|
M_llseek(hFile, 0L, 2);
|
|
|
|
// Return the success of the operation
|
|
//--------------------------------------------------------------
|
|
return (i < lstrlen(lpszOutText)) ? FALSE: TRUE;
|
|
}
|
|
|
|
//*------------------------------------------------------------------------
|
|
//| LogControl
|
|
//|
|
|
//| PURPOSE: Log a control to the log file -- output all the
|
|
//| information contained in the given control
|
|
//|
|
|
//| ENTRY: hFile - Handle of log file to write information to
|
|
//| pctrl - control to log to file
|
|
//| lpszInfo - text to send to log file before control
|
|
//|
|
|
//| EXIT: NONE
|
|
//*------------------------------------------------------------------------
|
|
VOID LogControl(HFILE hFile, LPCTLDEF pctrl, LPSTR lpszInfo)
|
|
{
|
|
INT i=0;
|
|
CHAR szTmpBuf[cchTextMac * 2];
|
|
CHAR szFmt[80];
|
|
|
|
// Output Header, Text Names, and Class names
|
|
//--------------------------------------------------------------
|
|
i += fLogStrToFile(hFile, lpszInfo);
|
|
i += fLogStrToFile(hFile, "\tTEXT : ");
|
|
i += fLogStrToFile(hFile, (LPSTR)pctrl->rgText);
|
|
i += fLogStrToFile(hFile, (LPSTR)"\r\n\tCLASS: ");
|
|
i += fLogStrToFile(hFile, (LPSTR)pctrl->rgClass);
|
|
i += fLogStrToFile(hFile, (LPSTR)"\r\n");
|
|
|
|
// Create the format string using the szFormat macro
|
|
//--------------------------------------------------------------
|
|
wsprintf(szFmt, szFormat);
|
|
|
|
// Output the rectangle using the RC macro
|
|
//--------------------------------------------------------------
|
|
wsprintf(szTmpBuf, szFmt, (LPSTR)"\tRECT : ", RC(pctrl->dcr) );
|
|
i += fLogStrToFile(hFile, (LPSTR)szTmpBuf);
|
|
i += fLogStrToFile(hFile, (LPSTR)"\r\n");
|
|
|
|
// Output the state and flags
|
|
//--------------------------------------------------------------
|
|
if (!lstrcmpi((LPSTR)(pctrl->rgClass), "MenuItem"))
|
|
wsprintf(szTmpBuf,"\tCHECKED: %d, GRAYED: %d, INACTIVE: %d\r\n\r\n",
|
|
(INT)(pctrl->nState & MF_CHECKED),
|
|
(INT)(pctrl->nState & MF_GRAYED) ,
|
|
(INT)(pctrl->nState & MF_ENABLED));
|
|
else
|
|
wsprintf(szTmpBuf,"\tCHECKED: %d, VISIBLE: %d, ENABLED: %d\r\n\r\n",
|
|
(pctrl->nState & STATE_CHECKED) ? 1 : 0,
|
|
(pctrl->nState & STATE_VISIBLE) ? 1 : 0,
|
|
(pctrl->nState & STATE_ENABLED) ? 1 : 0);
|
|
|
|
i += fLogStrToFile(hFile, (LPSTR)szTmpBuf);
|
|
}
|
|
|
|
//*---------------------------------------------------------------------
|
|
//| LogFuzzyMatch
|
|
//|
|
|
//| PURPOSE: Log a fuzzy match to the log file. Output information
|
|
//| contained in both the Base Control and the Compare
|
|
//| Control.
|
|
//|
|
|
//| ENTRY: hFile - Handle of log file
|
|
//| pctrlBase - base control
|
|
//| pctrlCmp - compare control
|
|
//|
|
|
//| EXIT: NONE
|
|
//*---------------------------------------------------------------------
|
|
VOID LogFuzzyMatch(HFILE hFile, LPCTLDEF pctrlBase, LPCTLDEF pctrlCmp)
|
|
{
|
|
INT i=0;
|
|
CHAR szTmpBuf[cchTextMac * 2];
|
|
CHAR szFmt[80];
|
|
INT wCompareErr;
|
|
|
|
// Compare the Control again to determine what has failed
|
|
// Compare every field except Tab Order because Tab order
|
|
// check can only be done with all other controls. If
|
|
// everything passes then Tab Order Check failed in the
|
|
// exact match pass. (not always though. If something fails,
|
|
// we cannot tell whether tab order check failed or not)
|
|
//-----------------------------------------------------------
|
|
wCompareErr = CompareControls (pctrlBase, pctrlCmp, 0, 0,
|
|
MATCH_CASE|MATCH_CLASS|MATCH_NAME|
|
|
MATCH_RECT|MATCH_STATE);
|
|
|
|
// Output Text Names
|
|
//-----------------------------------------------------------
|
|
i += fLogStrToFile(hFile, "FUZZY MATCH (base => cmp):\r\n ");
|
|
if (lstrcmp (pctrlBase->rgText, pctrlCmp->rgText))
|
|
i += fLogStrToFile(hFile, "*");
|
|
i += fLogStrToFile(hFile, "\tTEXT : '");
|
|
i += fLogStrToFile(hFile, pctrlBase->rgText);
|
|
i += fLogStrToFile(hFile, "' => '");
|
|
i += fLogStrToFile(hFile, pctrlCmp->rgText);
|
|
i += fLogStrToFile(hFile, "'\r\n ");
|
|
|
|
// Output Class names
|
|
//-----------------------------------------------------------
|
|
if (lstrcmp (pctrlBase->rgClass, pctrlBase->rgClass))
|
|
i += fLogStrToFile(hFile, "*");
|
|
i += fLogStrToFile(hFile, "\tCLASS : '");
|
|
i += fLogStrToFile(hFile, (LPSTR)pctrlBase->rgClass);
|
|
i += fLogStrToFile(hFile, (LPSTR) "' => '");
|
|
i += fLogStrToFile(hFile, (LPSTR)pctrlCmp->rgClass);
|
|
i += fLogStrToFile(hFile, (LPSTR) "'\r\n ");
|
|
|
|
// Create the format string using the szFormat macro
|
|
//--------------------------------------------------------------
|
|
wsprintf(szFmt, szFormat);
|
|
|
|
// Output the base rectangle, using the RC macro
|
|
//--------------------------------------------------------------
|
|
if (memcmp ((LPSTR)&pctrlBase->dcr, (LPSTR)&pctrlCmp->dcr,
|
|
sizeof(DCR)))
|
|
i += fLogStrToFile(hFile, "*");
|
|
wsprintf(szTmpBuf, szFmt, (LPSTR)"\tRECT : ", RC(pctrlBase->dcr) );
|
|
i += fLogStrToFile(hFile, szTmpBuf);
|
|
|
|
// Output the compare rectangle, again using the RC macro
|
|
//--------------------------------------------------------------
|
|
wsprintf(szTmpBuf, szFmt, (LPSTR)"=> ", RC(pctrlCmp->dcr) );
|
|
i += fLogStrToFile(hFile, szTmpBuf);
|
|
i += fLogStrToFile(hFile, "\r\n");
|
|
|
|
// Output the state and flags for each control. Under the current
|
|
// implementation, since this is a fuzzy match these will always
|
|
// be the same, but the checking for the difference flagging is
|
|
// still implemented for changes in the future (UNDONE:)
|
|
//--------------------------------------------------------------
|
|
if (!lstrcmpi((LPSTR)(pctrlBase->rgClass), "MenuItem"))
|
|
wsprintf(szTmpBuf, " %c\tChecked : %d => %d\r\n"
|
|
" %c\tGrayed : %d => %d\r\n"
|
|
" %c\tEnabled : %d => %d\r\n",
|
|
(pctrlBase->nState & MF_CHECKED) ==
|
|
(pctrlCmp->nState & MF_CHECKED) ? ' ' : '*',
|
|
(INT)(pctrlBase->nState & MF_CHECKED),
|
|
(INT)(pctrlCmp->nState & MF_CHECKED),
|
|
(pctrlBase->nState & MF_GRAYED) ==
|
|
(pctrlCmp->nState & MF_GRAYED) ? ' ' : '*',
|
|
(INT)(pctrlBase->nState & MF_GRAYED) ,
|
|
(INT)(pctrlCmp->nState & MF_GRAYED) ,
|
|
(pctrlBase->nState & MF_ENABLED) ==
|
|
(pctrlCmp->nState & MF_ENABLED) ? ' ' : '*',
|
|
(INT)(pctrlBase->nState & MF_ENABLED) ,
|
|
(INT)(pctrlCmp->nState & MF_ENABLED));
|
|
else
|
|
wsprintf(szTmpBuf, " %c\tChecked : %d => %d\r\n"
|
|
" %c\tVisible : %d => %d\r\n"
|
|
" %c\tEnabled : %d => %d\r\n",
|
|
(pctrlBase->nState & STATE_CHECKED) ==
|
|
(pctrlCmp->nState & STATE_CHECKED) ? ' ' : '*',
|
|
(pctrlBase->nState & STATE_CHECKED) ? 1 : 0,
|
|
(pctrlCmp->nState & STATE_CHECKED) ? 1 : 0,
|
|
(pctrlBase->nState & STATE_VISIBLE) ==
|
|
(pctrlCmp->nState & STATE_VISIBLE) ? ' ' : '*',
|
|
(pctrlBase->nState & STATE_VISIBLE) ? 1 : 0 ,
|
|
(pctrlCmp->nState & STATE_VISIBLE) ? 1 : 0 ,
|
|
(pctrlBase->nState & STATE_ENABLED) ==
|
|
(pctrlCmp->nState & STATE_ENABLED) ? ' ' : '*',
|
|
(pctrlBase->nState & STATE_ENABLED) ? 1 : 0 ,
|
|
(pctrlCmp->nState & STATE_ENABLED) ? 1 : 0);
|
|
|
|
i += fLogStrToFile(hFile, szTmpBuf);
|
|
|
|
// Output what has fail during the Exact Match Compare
|
|
//----------------------------------------------------
|
|
if (wCompareErr & MATCH_CLASS)
|
|
{
|
|
wsprintf(szTmpBuf, "-- Class names do not match.\r\n");
|
|
i += fLogStrToFile(hFile, szTmpBuf);
|
|
}
|
|
if (wCompareErr & MATCH_NAME)
|
|
{
|
|
if (wCompareErr & MATCH_CASE)
|
|
{
|
|
wsprintf(szTmpBuf,"-- Case sensitive name check failed.\r\n");
|
|
i += fLogStrToFile(hFile, szTmpBuf);
|
|
}
|
|
else
|
|
{
|
|
wsprintf(szTmpBuf,"-- Case insensitive name check failed.\r\n");
|
|
i += fLogStrToFile(hFile, szTmpBuf);
|
|
}
|
|
}
|
|
if (wCompareErr & MATCH_RECT)
|
|
{
|
|
wsprintf(szTmpBuf, "-- Controls are of different size.\r\n");
|
|
i += fLogStrToFile(hFile, szTmpBuf);
|
|
}
|
|
if (wCompareErr == 0)
|
|
{
|
|
wsprintf(szTmpBuf, "-- Tab order check failed.\r\n");
|
|
i += fLogStrToFile(hFile, szTmpBuf);
|
|
}
|
|
if (wCompareErr & MATCH_STATE)
|
|
{
|
|
wsprintf(szTmpBuf, "-- Control States do not match.\r\n");
|
|
i += fLogStrToFile(hFile, szTmpBuf);
|
|
}
|
|
|
|
// Output one blank line
|
|
//----------------------------------
|
|
wsprintf(szTmpBuf, "\r\n");
|
|
i += fLogStrToFile(hFile, szTmpBuf);
|
|
}
|
|
|
|
|
|
//*-------------------------------------------------------------------------
|
|
//| CompareControls
|
|
//|
|
|
//| PURPOSE: Compare two controls.
|
|
//|
|
|
//| ENTRY: pctrlBase - base control to compare against
|
|
//| pctrlCmp - control to compare
|
|
//| wMatchStyle - Match Preference Bits
|
|
//|
|
|
//| EXIT: 0 if Successful; otherwise Error Code
|
|
//*-------------------------------------------------------------------------
|
|
INT CompareControls (LPCTLDEF pctrlBase, LPCTLDEF pctrlCmp,
|
|
INT wOrderBase, INT wOrderCmp, INT wMatchStyle)
|
|
{
|
|
INT i = 0;
|
|
static INT cOrderBase = 0;
|
|
static INT cOrderCmp = 0;
|
|
|
|
// Used for Tab order and Control order Check
|
|
//---------------------------------------------------
|
|
if (wOrderBase == 0) cOrderBase = 0;
|
|
if (wOrderCmp == 0) cOrderCmp = 0;
|
|
if (pctrlBase->lStyleBits & WS_TABSTOP) cOrderBase++;
|
|
if (pctrlCmp ->lStyleBits & WS_TABSTOP) cOrderCmp++;
|
|
|
|
// Compare Control Class (Always case insensitive)
|
|
//---------------------------------------------------------------
|
|
if (wMatchStyle & MATCH_CLASS)
|
|
if (_fstricmp(pctrlBase->rgClass, pctrlCmp->rgClass))
|
|
i += MATCH_CLASS;
|
|
|
|
// Compare Control Name
|
|
//---------------------------------------------------------------
|
|
if (wMatchStyle & MATCH_CASE)
|
|
{
|
|
// Case Sensitive
|
|
//----------------------------
|
|
if (wMatchStyle & MATCH_NAME)
|
|
{
|
|
// Compare Text Values - Must be identical
|
|
//-------------------------------------------------------
|
|
if (lstrcmp((LPSTR)pctrlBase->rgText,(LPSTR)pctrlCmp->rgText))
|
|
{
|
|
i += MATCH_CASE;
|
|
i += MATCH_NAME;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
// Case Insensitive
|
|
//---------------------------
|
|
if (wMatchStyle & MATCH_NAME)
|
|
if (_fstricmp(pctrlBase->rgText, pctrlCmp->rgText))
|
|
i += MATCH_NAME;
|
|
|
|
// Compare Control Rectangle Coor
|
|
//-------------------------------------------------------------
|
|
if (wMatchStyle & MATCH_RECT)
|
|
// Compare Rectangles
|
|
//-------------------------------------------------------
|
|
if (memcmp ((LPSTR)&pctrlBase->dcr, (LPSTR)&pctrlCmp->dcr,
|
|
SIZEOF_DCR))
|
|
i += MATCH_RECT;
|
|
|
|
// Compare Control Tab Order
|
|
//-------------------------------------------------------------
|
|
if (wMatchStyle & MATCH_TAB)
|
|
// Compare TabOrder
|
|
//-------------------------------------------------------
|
|
if ((pctrlBase->lStyleBits & WS_TABSTOP) &&
|
|
(pctrlCmp ->lStyleBits & WS_TABSTOP) &&
|
|
(i == 0))
|
|
if (cOrderBase != cOrderCmp)
|
|
i += MATCH_TAB;
|
|
|
|
if (wMatchStyle & MATCH_STATE)
|
|
// Compare State, Visible, and Enabled -- these must be the same
|
|
// in any case.
|
|
//---------------------------------------------------------------
|
|
if (pctrlBase->nState != pctrlCmp->nState)
|
|
i += MATCH_STATE;
|
|
|
|
return ( (i == 0)? 0 : i );
|
|
}
|
|
|
|
//*-------------------------------------------------------------------------
|
|
//| OutputFooter
|
|
//|
|
|
//| PURPOSE: Output a comparison footer to the given log file, complete
|
|
//| with all results of the prior comparison.
|
|
//|
|
|
//| ENTRY: lpszLog - Pointer to name of log file to write footer to
|
|
//|
|
|
//| EXIT: None
|
|
//*-------------------------------------------------------------------------
|
|
VOID FARPRIVATE OutputFooter (LPSTR lpszLog)
|
|
{
|
|
HFILE hFile;
|
|
CHAR szStrBuf[256];
|
|
|
|
// File i/o errors during logging are ignored
|
|
//------------------------------------------------------------------
|
|
hFile = fOpenFile (lpszLog);
|
|
|
|
// If the comparison was a full dialog comparison, then the output
|
|
// format strings are a different set
|
|
//------------------------------------------------------------------
|
|
if (fCompFull)
|
|
{
|
|
// The first case is an exact match - if exact, then only
|
|
// one line is output -- the rest of the if's will fail
|
|
// UNDONE: Make this more efficient
|
|
//----------------------------------------------------------
|
|
if (fCompRes == WCT_NOERR)
|
|
{
|
|
wsprintf (szStrBuf,
|
|
">> EXACT MATCH: %d controls compared\r\n",
|
|
nCtlBase);
|
|
fLogStrToFile (hFile, szStrBuf);
|
|
}
|
|
|
|
// The rest can be a combination
|
|
//----------------------------------------------------------
|
|
if (fCompRes & CR_FUZZY)
|
|
{
|
|
wsprintf (szStrBuf,
|
|
">> FUZZY MATCH: %d of %d controls fuzzy\r\n",
|
|
nCtlFuzzy, nCtlBase);
|
|
fLogStrToFile (hFile, szStrBuf);
|
|
}
|
|
if (fCompRes & CR_MIC)
|
|
{
|
|
wsprintf (szStrBuf,
|
|
">> MORE CONTROLS IN COMPARE DIALOG: "
|
|
"%d compared, %d excess\r\n",
|
|
nCtlBase, nCtlExcess);
|
|
fLogStrToFile (hFile, szStrBuf);
|
|
}
|
|
if (fCompRes & CR_CNF)
|
|
{
|
|
wsprintf (szStrBuf,
|
|
">> %d OF %d CONTROLS NOT FOUND\r\n",
|
|
nCtlNotFnd, nCtlBase);
|
|
fLogStrToFile (hFile, szStrBuf);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// The first case is an exact match - if exact, then only
|
|
// one line is output -- the rest of the if's will fail
|
|
// UNDONE: Make this more efficient
|
|
//----------------------------------------------------------
|
|
if (fCompRes == WCT_NOERR)
|
|
{
|
|
wsprintf (szStrBuf,
|
|
">> EXACT MATCH: %d controls found in "
|
|
"%d total compare controls\r\n",
|
|
nCtlBase, nCtlComp);
|
|
fLogStrToFile (hFile, szStrBuf);
|
|
}
|
|
|
|
// The rest can be a combination
|
|
//----------------------------------------------------------
|
|
if (fCompRes & CR_FUZZY)
|
|
{
|
|
wsprintf (szStrBuf,
|
|
">> FUZZY MATCH: %d controls found in "
|
|
"%d total compare controls, %d fuzzy\r\n",
|
|
nCtlBase, nCtlComp, nCtlFuzzy);
|
|
fLogStrToFile (hFile, szStrBuf);
|
|
}
|
|
if (fCompRes & CR_CNF)
|
|
{
|
|
wsprintf (szStrBuf,
|
|
">> CONTROLS NOT FOUND: "
|
|
"%d of %d base controls not found in "
|
|
"%d compare controls\r\n",
|
|
nCtlNotFnd, nCtlBase, nCtlComp);
|
|
fLogStrToFile (hFile, szStrBuf);
|
|
}
|
|
}
|
|
|
|
fLogStrToFile (hFile, "--------------------------------");
|
|
fLogStrToFile (hFile, "--------------------------------\r\n");
|
|
fClose (hFile);
|
|
}
|
|
|
|
|
|
//*-------------------------------------------------------------------------
|
|
//| OutputHeader
|
|
//|
|
|
//| PURPOSE: Output a header to the given log file, complete with time
|
|
//| and date of compare.
|
|
//|
|
|
//| ENTRY: lpszLog - Pointer to name of log file to write header to
|
|
//|
|
|
//| EXIT: None
|
|
//*-------------------------------------------------------------------------
|
|
VOID FARPRIVATE OutputHeader (LPSTR lpszLog)
|
|
{
|
|
HFILE hFile;
|
|
static CHAR szDTBuf[16]; // STATIC to ensure DS points to it
|
|
CHAR szStrBuf[80];
|
|
|
|
hFile = fOpenFile(lpszLog);
|
|
wsprintf (szStrBuf, "----------------------%sDIALOG COMPARISON: ",
|
|
(LPSTR)(fCompFull ? "FULL " : "-----"));
|
|
fLogStrToFile (hFile, szStrBuf);
|
|
_strdate (szDTBuf);
|
|
fLogStrToFile (hFile, szDTBuf);
|
|
fLogStrToFile (hFile, " ");
|
|
_strtime (szDTBuf);
|
|
fLogStrToFile (hFile, szDTBuf);
|
|
fLogStrToFile (hFile, "\r\n");
|
|
fClose(hFile);
|
|
}
|
|
|
|
|
|
//*-------------------------------------------------------------------------
|
|
//| fCompareMem
|
|
//|
|
|
//| PURPOSE: Perform the comparison of two control arrays
|
|
//|
|
|
//| ENTRY: lpBase - Pointer to base (source) control array
|
|
//| cBase - Number of controls in base array
|
|
//| lpComp - Pointer to compare (target) control array
|
|
//| cComp - Number of controls in compare array
|
|
//| fFull - Full dialog comparison flag (TRUE -> full dialog)
|
|
//| lpLog - Pointer to error log file
|
|
//|
|
|
//| EXIT: The return value indicates the result of the comparison
|
|
//*-------------------------------------------------------------------------
|
|
INT FARPUBLIC fCompareMem(LPCTLDEF lpBase, INT cBase,
|
|
LPCTLDEF lpComp, INT cComp,
|
|
INT fFull, LPSTR lpLog)
|
|
{
|
|
INT i, j;
|
|
HANDLE hMatchBuf = NULL, hCompBuf = NULL;
|
|
HFILE hFile;
|
|
LONG FAR *lpMatchBuf;
|
|
LPSTR lpCompBuf;
|
|
INT cMatchCount=0;
|
|
|
|
// Set up the comparison variables
|
|
//--------------------------------------------------------------
|
|
fCompFull = fFull;
|
|
fCompRes = WCT_NOERR;
|
|
nCtlBase = cBase;
|
|
nCtlComp = cComp;
|
|
nCtlFuzzy = 0;
|
|
nCtlExcess = 0;
|
|
nCtlNotFnd = 0;
|
|
|
|
// Output the comparison header to the log file
|
|
//--------------------------------------------------------------
|
|
OutputHeader (lpLog);
|
|
|
|
// If there are no controls in the base array, return WCT_NOERR
|
|
//--------------------------------------------------------------
|
|
if (!cBase)
|
|
EndCompare (WCT_NOERR);
|
|
|
|
// Setup match buffer; (array of long integers)
|
|
// use to keep track of which elements match which
|
|
// LOWORD(lpMatchBuf[x]) = Element number in lpComp.
|
|
// HIWORD(lpMatchBuf[x]) = Match type 0 - none, 1 - exact, 2 fuzzy
|
|
// where x is the corresponding element in lpBase
|
|
//--------------------------------------------------------------
|
|
hMatchBuf = GlobalAlloc( GMEM_ZEROINIT | GMEM_MOVEABLE,
|
|
cBase * sizeof(LONG) );
|
|
if (hMatchBuf == NULL)
|
|
return (WCT_OUTOFMEMORY);
|
|
lpMatchBuf = (LONG FAR *)GlobalLock(hMatchBuf);
|
|
if (lpMatchBuf == NULL)
|
|
{
|
|
GlobalFree (hMatchBuf);
|
|
return (WCT_OUTOFMEMORY);
|
|
}
|
|
|
|
// Bug fix: TestDlgs1.0
|
|
// if cComp = 0, this routine will return 0, forgot to check
|
|
// the number of control in array.
|
|
// If there are no control in the comp array, return WCT_CTLNOTFOUND
|
|
//------------------------------------------------------------------
|
|
if(!cComp)
|
|
{
|
|
fCompRes |= CR_CNF;
|
|
nCtlNotFnd = cBase;
|
|
EndCompare (WCT_CTLNOTFOUND);
|
|
}
|
|
|
|
// Set up compare buffer - (array of characters) used to keep
|
|
// track of the compare controls which are matched (exact OR
|
|
// fuzzy) and which are not.
|
|
//--------------------------------------------------------------
|
|
hCompBuf = GlobalAlloc (GMEM_ZEROINIT | GMEM_MOVEABLE,
|
|
cComp * sizeof(CHAR));
|
|
if (hCompBuf == NULL)
|
|
{
|
|
GlobalUnlock (hMatchBuf);
|
|
GlobalFree (hMatchBuf);
|
|
return (WCT_OUTOFMEMORY);
|
|
}
|
|
lpCompBuf = (LPSTR)GlobalLock (hCompBuf);
|
|
if (lpCompBuf == NULL)
|
|
{
|
|
GlobalUnlock (hMatchBuf);
|
|
GlobalFree (hMatchBuf);
|
|
GlobalFree (hCompBuf);
|
|
return (WCT_OUTOFMEMORY);
|
|
}
|
|
|
|
// Loop through finding exact matches and marking them
|
|
// accordingly.
|
|
//--------------------------------------------------------------
|
|
for (i = 0; i < cComp; i++)
|
|
if (!lpCompBuf[i])
|
|
for (j = 0; j < cBase; j++)
|
|
if ( (lpMatchBuf[j] == 0) &&
|
|
!CompareControls(lpBase+j, lpComp+i, j, i,
|
|
(INT)(lMatchPref >> 16)) )
|
|
{
|
|
lpMatchBuf[j] = (LONG)i | (1L << 16);
|
|
lpCompBuf[i] = (CHAR)1;
|
|
cMatchCount ++;
|
|
break;
|
|
}
|
|
|
|
// If not all controls in the base array were found, loop
|
|
// through looking for fuzzy matches and marking them
|
|
//--------------------------------------------------------------
|
|
if (cMatchCount != cBase)
|
|
{
|
|
for (i = 0; i < cComp; i++)
|
|
if (!lpCompBuf[i])
|
|
for (j = 0; j < cBase; j++)
|
|
if ( (lpMatchBuf[j] == 0) &&
|
|
!CompareControls(lpBase+j, lpComp+i,
|
|
j, i, (INT)lMatchPref) )
|
|
{
|
|
lpMatchBuf[j] = (LONG)i | (2L << 16);
|
|
lpCompBuf[i] = (CHAR)1;
|
|
cMatchCount ++;
|
|
nCtlFuzzy++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Open the log file
|
|
//--------------------------------------------------------------
|
|
hFile = fOpenFile (lpLog);
|
|
|
|
// Log all fuzzy matches in MatchBuf (if any)
|
|
//--------------------------------------------------------------
|
|
if (nCtlFuzzy)
|
|
{
|
|
for (i=0; i < cBase; i++)
|
|
if (HIWORD(lpMatchBuf[i]) == (WORD)2)
|
|
LogFuzzyMatch (hFile, lpBase+i,
|
|
lpComp+LOWORD(lpMatchBuf[i]));
|
|
fCompRes |= CR_FUZZY;
|
|
}
|
|
|
|
// If this is a full dialog compare, log out all unmatched
|
|
// controls in the compare dialog
|
|
//--------------------------------------------------------------
|
|
if (fFull)
|
|
{
|
|
nCtlExcess = cComp - cBase;
|
|
if (nCtlExcess)
|
|
fCompRes |= CR_MIC;
|
|
for (i=0; i < cComp; i++)
|
|
if (!lpCompBuf[i])
|
|
LogControl (hFile, lpComp+i,
|
|
"UNMATCHED COMPARE CONTROL:\r\n");
|
|
}
|
|
|
|
// Log all base controls not found (if any)
|
|
//--------------------------------------------------------------
|
|
if (cMatchCount < cBase)
|
|
{
|
|
fCompRes |= CR_CNF;
|
|
nCtlNotFnd = cBase - cMatchCount;
|
|
for (i=0; i < cBase; i++)
|
|
if (!lpMatchBuf[i])
|
|
LogControl (hFile, lpBase+i,
|
|
"BASE CONTROL NOT FOUND:\r\n");
|
|
}
|
|
|
|
// Close the log file
|
|
//--------------------------------------------------------------
|
|
if (hFile != -1)
|
|
fClose(hFile);
|
|
|
|
// Release buffer memory, log the footer, and return appropriate
|
|
// result code
|
|
//--------------------------------------------------------------
|
|
GlobalUnlock(hMatchBuf);
|
|
GlobalFree(hMatchBuf);
|
|
GlobalUnlock(hCompBuf);
|
|
GlobalFree(hCompBuf);
|
|
|
|
OutputFooter (lpLog);
|
|
|
|
if (fCompRes == 0)
|
|
return (WCT_NOERR);
|
|
if (fCompRes & CR_CNF)
|
|
return (WCT_CTLNOTFOUND);
|
|
if (fCompRes & CR_MIC)
|
|
return (WCT_EXCESS);
|
|
return (WCT_FUZZY);
|
|
}
|
|
|
|
//*--------------------------------------------------------------------------
|
|
//| fDoCompare
|
|
//|
|
|
//| PURPOSE: Given a handle to a window and an index into the dialog
|
|
//| file, compare the two as dialogs. This means capturing
|
|
//| the CHILDREN of the hWnd window and, if the fTotal flag is
|
|
//| set, the window itself, into the hGTarget buffer, and
|
|
//| reading the dialog information (offset nDlg) from the file
|
|
//| into the hGSource buffer. Then, the two arrays are compared.
|
|
//|
|
|
//| First, however, the dialog info in the file is checked to see
|
|
//| if it is menu information. If so, we remember that fact, so
|
|
//| that we pump the window handle given for the right information.
|
|
//|
|
|
//| NOTE: nDlg is 1-based.
|
|
//|
|
|
//| OTHER NOTE: If nDlg = 0, the controls in the array indicated
|
|
//| by hDynDlg are used in the comparison (as the source)
|
|
//|
|
|
//| ENTRY: szFullFName - Name of dialog file
|
|
//| hWnd - Handle of window to compare (target)
|
|
//| nDlg - Index into the file of source (0 -> dynamic)
|
|
//| fTotal - TRUE -> parent hWnd is added to target
|
|
//| szLogFile - Name of results log file
|
|
//| hDynDlg - Handle of dynamic dialog control array
|
|
//| nDynCount - Number of controls in the dynamic dialog
|
|
//|
|
|
//| EXIT: Result of comparison
|
|
//*--------------------------------------------------------------------------
|
|
INT FARPUBLIC fDoCompare (LPSTR szFullFName, HWND hWnd, INT nDlg, INT fTotal,
|
|
LPSTR szLogFile, HANDLE hDynDlg, INT nDynCount)
|
|
{
|
|
INT nTargetCount = 0;
|
|
INT nSourceCount = 0;
|
|
INT fFullDlg, retval, i, j, cbMax, nGrabType;
|
|
CHAR szDsc[cchMaxDsc];
|
|
HANDLE hGSource, hGTarget;
|
|
LPCTLDEF lpSrcCtl, lpTrgCtl;
|
|
|
|
// First, get the dialog information from the dialog file, at
|
|
// index nDlg. This includes whether or not this is a full
|
|
// dialog compare. Note that we don't have to do this if we
|
|
// are doing a dynamic dialog compare.
|
|
//-----------------------------------------------------------
|
|
if (nDlg)
|
|
{
|
|
i = fDialogInfo(szFullFName, nDlg, (LPSTR)szDsc,
|
|
(INT FAR *)&nSourceCount, (INT FAR *)&fFullDlg);
|
|
if (i != WCT_NOERR)
|
|
{
|
|
OutDebug ("Unable to get dialog information");
|
|
return (WCT_OUTOFMEMORY);
|
|
}
|
|
|
|
// Allocate memory for source (add 1 to ensure + size)
|
|
//-------------------------------------------------------
|
|
i = fInitBlock((HANDLE FAR *)&hGSource, nSourceCount+1);
|
|
if (i != WCT_NOERR)
|
|
{
|
|
OutDebug ("Could not allocate for hGSource");
|
|
return (WCT_OUTOFMEMORY);
|
|
}
|
|
|
|
// Read the information from the file into the source
|
|
// array. Note that lpSrcCtl is locked from this point
|
|
// to the end of this routine.
|
|
//-------------------------------------------------------
|
|
lpSrcCtl = (LPCTLDEF)GlobalLock (hGSource);
|
|
if (!lpSrcCtl)
|
|
{
|
|
OutDebug ("Can't lock hGSource!");
|
|
GlobalFree (hGSource);
|
|
return (WCT_OUTOFMEMORY);
|
|
}
|
|
cbMax = nSourceCount * sizeof(CTLDEF);
|
|
i = fGetControls ((LPSTR) szFullFName, nDlg,
|
|
(WORD) cbMax, (LPSTR) lpSrcCtl);
|
|
if (i != nSourceCount)
|
|
{
|
|
OutDebug ("fGetControls failed");
|
|
GlobalUnlock (hGSource);
|
|
GlobalFree (hGSource);
|
|
return (WCT_OUTOFMEMORY);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// nDlg = 0 means this is a dynamic dialog compare. All
|
|
// we have to do here is lock down the handle we were
|
|
// given (and make sure to check for the success of the
|
|
// lock, in case the user passed in an invalid handle).
|
|
// We also have to check the sign of the dynamic dialog
|
|
// count -- if negative, treat this as a "full dialog"
|
|
// comparison.
|
|
//-------------------------------------------------------
|
|
lpSrcCtl = (LPCTLDEF)GlobalLock (hDynDlg);
|
|
if (lpSrcCtl == NULL)
|
|
{
|
|
OutDebug ("Can't lock dynamic handle!\n\r");
|
|
return (WCT_OUTOFMEMORY);
|
|
}
|
|
nSourceCount = abs(nDynCount);
|
|
fFullDlg = (nSourceCount < 0);
|
|
}
|
|
|
|
// Check to see if the class name of the first control in the
|
|
// array is "MenuItem". If so, this is a menu, not a dialog
|
|
// type, so set the nGrabType variable accordingly
|
|
//------------------------------------------------------------
|
|
if (!lstrcmpi(((LPCTLDEF)lpSrcCtl)[0].rgClass, "MenuItem"))
|
|
nGrabType = PUMP_MENU;
|
|
else
|
|
nGrabType = PUMP_ALL;
|
|
|
|
// All the information in the source array is set up and
|
|
// locked. Next, allocate memory for the target (just 1 - it
|
|
// will grow as we grab children with fPumpHandleForInfo)
|
|
//------------------------------------------------------------
|
|
j = fInitBlock ((HANDLE FAR *)&hGTarget, 1);
|
|
if (j != WCT_NOERR)
|
|
{
|
|
OutDebug ("Could not allocate for hGTarget");
|
|
if (nDlg)
|
|
{
|
|
GlobalUnlock (hGSource);
|
|
GlobalFree (hGSource);
|
|
}
|
|
return (WCT_OUTOFMEMORY);
|
|
}
|
|
|
|
// Grab all the child windows from hWnd with fPumpHandleForInfo
|
|
//-------------------------------------------------------------
|
|
i=fPumpHandleForInfo (hWnd, hGTarget, (INT FAR *)&nTargetCount,
|
|
nGrabType);
|
|
if (i != WCT_NOERR)
|
|
{
|
|
OutDebug ("PumpHandle failed");
|
|
GlobalFree (hGTarget);
|
|
if (nDlg)
|
|
{
|
|
GlobalUnlock (hGSource);
|
|
GlobalFree (hGSource);
|
|
}
|
|
return ( i );
|
|
}
|
|
|
|
// Check the fTotal flag - if TRUE, and we are NOT comparing menu
|
|
// information, add the parent (hWnd) to the list
|
|
//--------------------------------------------------------------
|
|
if ( (fTotal) && (nGrabType != PUMP_MENU) )
|
|
{
|
|
i = fAddControlToList (hWnd, hGTarget, (INT FAR *)&nTargetCount,
|
|
NULL);
|
|
if (i != WCT_NOERR)
|
|
{
|
|
OutDebug ("Error adding parent to hGSource");
|
|
GlobalFree( hGTarget );
|
|
if (nDlg)
|
|
{
|
|
GlobalUnlock( hGSource );
|
|
GlobalFree (hGSource );
|
|
}
|
|
return ( i );
|
|
}
|
|
}
|
|
|
|
// The hGTarget buffer is established. Lock it down for the
|
|
// comparison
|
|
//--------------------------------------------------------------
|
|
lpTrgCtl = (LPCTLDEF)GlobalLock (hGTarget);
|
|
|
|
// Okay, it's time to do the comparison. Pass everything off to
|
|
// fCompareMem.
|
|
//--------------------------------------------------------------
|
|
retval = fCompareMem(lpSrcCtl, nSourceCount, lpTrgCtl, nTargetCount,
|
|
fFullDlg, szLogFile);
|
|
|
|
// Unlock and free up memory, and exit
|
|
//--------------------------------------------------------------
|
|
GlobalUnlock (hGTarget);
|
|
GlobalFree (hGTarget);
|
|
if (nDlg)
|
|
{
|
|
GlobalUnlock (hGSource);
|
|
GlobalFree (hGSource);
|
|
}
|
|
|
|
return (retval);
|
|
}
|
|
|
|
//*-------------------------------------------------------------------------
|
|
//| fPutMatchPref
|
|
//|
|
|
//| PURPOSE: Save Match Preference to wMatchPref globol variable
|
|
//|
|
|
//| ENTRY: wMatchBits - Preference bits
|
|
//|
|
|
//| EXIT: None
|
|
//*-------------------------------------------------------------------------
|
|
VOID FARPUBLIC fPutMatchPref(LONG lMatchBits)
|
|
{
|
|
lMatchPref = lMatchBits;
|
|
}
|
|
|
|
//*-------------------------------------------------------------------------
|
|
//| fGetMatchPref
|
|
//|
|
|
//| PURPOSE: Export Match Preference from wMatchPref globol variable
|
|
//|
|
|
//| ENTRY: None
|
|
//|
|
|
//| EXIT: Match Bits (WORD)
|
|
//*-------------------------------------------------------------------------
|
|
LONG FARPUBLIC fGetMatchPref(VOID)
|
|
{
|
|
return lMatchPref;
|
|
}
|