Add new items to top.
(This summarizes all changes to all files under Src, including Src\Languages.)
+2006-07-24 Kimmo
+ PATCH: [ 1526918 ] Detect which side file is binary file
+ Src: DiffItem.h DiffWrapper.cpp DiffWrapper.h
+ Src/diffutils/src: DIFF.H IO.c analyze.c
+
2006-07-20 WinMerge experimental release 2.5.5.4 (cvs)
2006-07-20 Kimmo
#endif
/**
+ * @brief Bitfield values for binary file sides.
+ * These values are used as bitfield values when determining which file(s)
+ * are binary files. There is no "both" -value since in bitfield "both" is
+ * when side1- and side2- bits are set (BINFILE_SIDE1 | BINFILE_SIDE2).
+ */
+enum BINFILE_SIDE
+{
+ BINFILE_NONE = 0, /**< No binary files detected. */
+ BINFILE_SIDE1, /**< First file was detected as binary file. */
+ BINFILE_SIDE2, /**< Second file was detected as binart file. */
+};
+
+/**
* @brief Status of one item comparison, stored as bitfields
*
* Bitmask can be seen as a 4 dimensional space; that is, there are four
// and each set of flags is in a different hex digit
// to make debugging easier
// These can always be packed down in the future
- TEXTFLAGS=0x3, TEXT=0x1, BIN=0x2,
+ TEXTFLAGS=0x7, TEXT=0x1, BINSIDE1=0x2, BINSIDE2=0x3, BIN=0x4,
DIRFLAGS=0x30, FILE=0x10, DIR=0x20,
SIDEFLAGS=0x300, LEFT=0x100, RIGHT=0x200, BOTH=0x300,
COMPAREFLAGS=0x7000, NOCMP=0x0000, SAME=0x1000, DIFF=0x2000, CMPERR=0x3000, CMPABORT=0x4000,
DIFFCODE(int diffcode = 0) : diffcode(diffcode) { }
-private:
+protected:
static bool Check(int code, int mask, int result) { return ((code & mask) == result); }
static bool CheckCompare(int code, int result) { return Check(code, DIFFCODE::COMPAREFLAGS, result); }
static bool CheckFilter(int code, int result) { return Check(code, DIFFCODE::FILTERFLAGS, result); }
// filter status
bool isResultFiltered() const { return CheckFilter(diffcode, DIFFCODE::SKIPPED); }
// type
- bool isBin() const { return Check(diffcode, DIFFCODE::TEXTFLAGS, DIFFCODE::BIN); }
+ bool isBin() const { return Check(diffcode, DIFFCODE::TEXTFLAGS, DIFFCODE::BIN) ||
+ Check(diffcode, DIFFCODE::TEXTFLAGS, DIFFCODE::BINSIDE1) ||
+ Check(diffcode, DIFFCODE::TEXTFLAGS, DIFFCODE::BINSIDE2); }
void setBin() { Set(DIFFCODE::TEXTFLAGS, DIFFCODE::BIN); }
// rescan
bool isScanNeeded() const { return ((diffcode & DIFFCODE::SCANFLAGS) == DIFFCODE::NEEDSCAN); }
return FALSE;
}
- /* Compare the files, if no error was found. */
+ // Compare the files, if no error was found.
+ // Last param (bin_file) is NULL since we don't
+ // (yet) need info about binary sides.
int bin_flag = 0;
struct change *script = NULL;
- bRet = Diff2Files(&script, &diffdata, &bin_flag);
+ bRet = Diff2Files(&script, &diffdata, &bin_flag, NULL);
// We don't anymore create diff-files for every rescan.
// User can create patch-file whenever one wants to.
/**
* @brief Compare two specified files.
*
- * @param [in] Current directory depth.
+ * @param [in] depth Current directory depth.
* @return Compare result as DIFFCODE.
*/
int DiffFileData::diffutils_compare_files(int depth)
{
int bin_flag = 0;
+ int bin_file = 0; // bitmap for binary files
// Do the actual comparison (generating a change script)
struct change *script = NULL;
- BOOL success = Diff2Files(&script, depth, &bin_flag, FALSE);
+ BOOL success = Diff2Files(&script, depth, &bin_flag, FALSE, &bin_file);
if (!success)
{
return DIFFCODE::FILE | DIFFCODE::TEXT | DIFFCODE::CMPERR;
{
// Clear text-flag, set binary flag
// We don't know diff counts for binary files
- code = code & ~DIFFCODE::TEXT | DIFFCODE::BIN;
+ code = code & ~DIFFCODE::TEXT;
+ switch (bin_file)
+ {
+ case BINFILE_SIDE1: code |= DIFFCODE::BINSIDE1;
+ break;
+ case BINFILE_SIDE2: code |= DIFFCODE::BINSIDE2;
+ break;
+ case BINFILE_SIDE1 | BINFILE_SIDE2: code |= DIFFCODE::BIN;
+ break;
+ default:
+ _RPTF1(_CRT_ERROR, "Invalid bin_file value: %d", bin_file);
+ break;
+ }
m_ndiffs = DiffFileData::DIFFS_UNKNOWN;
}
* @param [out] diffs Pointer to list of change structs where diffdata is stored.
* @param [in] diffData files to compare.
* @param [out] bin_status used to return binary status from compare.
+ * @param [out] bin_file Returns which file was binary file as bitmap.
+ So if first file is binary, first bit is set etc. Can be NULL if binary file
+ info is not needed (faster compare since diffutils don't bother checking
+ second file if first is binary).
* @return TRUE when compare succeeds, FALSE if error happened during compare.
*/
BOOL CDiffWrapper::Diff2Files(struct change ** diffs, DiffFileData *diffData,
- int * bin_status)
+ int * bin_status, int * bin_file)
{
BOOL bRet = TRUE;
__try
{
// Diff files. depth is zero because we are not comparing dirs
- *diffs = diff_2_files (diffData->m_inf, 0, bin_status, m_bDetectMovedBlocks);
+ *diffs = diff_2_files (diffData->m_inf, 0, bin_status,
+ m_bDetectMovedBlocks, bin_file);
CopyDiffutilTextStats(diffData->m_inf, diffData);
}
__except (EXCEPTION_EXECUTE_HANDLER)
return bRet;
}
+/**
+ * @brief Compare two files using diffutils.
+ *
+ * Compare two files (in DiffFileData param) using diffutils. Run diffutils
+ * inside SEH so we can trap possible error and exceptions. If error or
+ * execption is trapped, return compare failure.
+ * @param [out] diffs Pointer to list of change structs where diffdata is stored.
+ * @param [in] depth Depth in folder compare (we use 0).
+ * @param [out] bin_status used to return binary status from compare.
+ * @param [in] bMovedBlocks If TRUE moved blocks are analyzed.
+ * @param [out] bin_file Returns which file was binary file as bitmap.
+ So if first file is binary, first bit is set etc. Can be NULL if binary file
+ info is not needed (faster compare since diffutils don't bother checking
+ second file if first is binary).
+ * @return TRUE when compare succeeds, FALSE if error happened during compare.
+ */
BOOL DiffFileData::Diff2Files(struct change ** diffs, int depth,
- int * bin_status, BOOL bMovedBlocks)
+ int * bin_status, BOOL bMovedBlocks, int * bin_file)
{
BOOL bRet = TRUE;
__try
{
- *diffs = diff_2_files (m_inf, depth, bin_status, bMovedBlocks);
+ *diffs = diff_2_files (m_inf, depth, bin_status, bMovedBlocks, bin_file);
CopyDiffutilTextStats(m_inf, this);
}
__except (EXCEPTION_EXECUTE_HANDLER)
BOOL bBin0 = (m_textStats0.nzeros>0);
BOOL bBin1 = (m_textStats1.nzeros>0);
- if (bBin0 || bBin1)
- {
+
+ if (bBin0 && bBin1)
diffcode |= DIFFCODE::BIN;
- }
+ else if (bBin0)
+ diffcode |= DIFFCODE::BINSIDE1;
+ else if (bBin1)
+ diffcode |= DIFFCODE::BINSIDE2;
// If either unfinished, they differ
if (ptr0 != end0 || ptr1 != end1)
void SwapToGlobalSettings();
CString FormatSwitchString();
BOOL Diff2Files(struct change ** diffs, DiffFileData *diffData,
- int * bin_status);
+ int * bin_status, int * bin_file);
void LoadWinMergeDiffsFromDiffUtilsScript(struct change * script, const file_data * inf);
void WritePatchFile(struct change * script, file_data * inf);
int byte_compare_files(BOOL bStopAfterFirstDiff, const IAbortable * piAbortable);
int prepAndCompareTwoFiles(CDiffContext * pCtxt, DIFFITEM &di);
BOOL Diff2Files(struct change ** diffs, int depth,
- int * bin_status, BOOL bMovedBlocks);
+ int * bin_status, BOOL bMovedBlocks, int * bin_file);
bool Filepath_Transform(FileLocation & fpenc, const CString & filepath, CString & filepathTransformed,
const CString & filteredFilenames, PrediffingInfo * infoPrediffer, int fd);
void GuessEncoding_from_buffer_in_DiffContext(int side, CDiffContext * pCtxt);
/* Declare various functions. */
/* analyze.c */
-struct change * diff_2_files PARAMS((struct file_data[], int, int *, int));
+/* WinMerge: add last two params */
+struct change * diff_2_files PARAMS((struct file_data[], int, int *, int, int*));
/* context.c */
void print_context_header PARAMS((struct file_data[], int));
void print_ifdef_script PARAMS((struct change *));
/* io.c */
-int read_files PARAMS((struct file_data[], int));
+/* WinMerge: add last pointer param */
+int read_files PARAMS((struct file_data[], int, int *));
int sip PARAMS((struct file_data *, int));
void slurp PARAMS((struct file_data *));
with each one, and build the table of equivalence classes.
Return 1 if either file appears to be a binary file.
If PRETEND_BINARY is nonzero, pretend they are binary regardless. */
-
+/* WinMerge: Add int * bin_file param for getting actual binary file
+ If bin_file is given, then check both files for binary files,
+ otherwise check second file only if first wasn't binary */
int
-read_files (filevec, pretend_binary)
+read_files (filevec, pretend_binary, bin_file)
struct file_data filevec[];
int pretend_binary;
+ int * bin_file;
{
int i;
int skip_test = always_text_flag | pretend_binary;
- int appears_binary = pretend_binary | sip (&filevec[0], skip_test);
+ int appears_binary = 0;
+
+ if (bin_file)
+ *bin_file = 0;
+ appears_binary = pretend_binary | sip (&filevec[0], skip_test);
+ if (bin_file && appears_binary)
+ {
+ *bin_file = 1;
+ }
if (filevec[0].desc != filevec[1].desc)
- appears_binary |= sip (&filevec[1], skip_test | appears_binary);
+ {
+ if (bin_file)
+ {
+ appears_binary = pretend_binary | sip (&filevec[1], skip_test);
+ if (appears_binary)
+ *bin_file |= 0x2; // set second bit for second file
+ }
+ else
+ appears_binary |= sip (&filevec[1], skip_test | appears_binary);
+ }
else
{
filevec[1].buffer = filevec[0].buffer;
filevec[1].bufsize = filevec[0].bufsize;
filevec[1].buffered_chars = filevec[0].buffered_chars;
}
- if (appears_binary)
+ if (appears_binary || (bin_file && *bin_file > 0))
return 1;
find_identical_ends (filevec);
// Report the differences of two files. DEPTH is the current directory
// depth.
-struct change * diff_2_files (struct file_data filevec[], int depth, int * bin_status, int moved_blocks_flag)
+// WinMerge: add moved_blocks_flag for detecting moved blocks and
+// bin_file for getting info which file is binary file (can be NULL)
+struct change * diff_2_files (struct file_data filevec[], int depth, int * bin_status,
+ int moved_blocks_flag, int * bin_file)
{
int diags;
int i;
// Also, --brief without any --ignore-* options means
// we can speed things up by treating the files as binary.
- if (read_files (filevec, no_details_flag & ~ignore_some_changes))
+ if (read_files (filevec, no_details_flag & ~ignore_some_changes, bin_file))
{
// Files with different lengths must be different.
if (filevec[0].stat.st_size != filevec[1].stat.st_size