--- /dev/null
+/**
+ * @file varprop.cpp
+ *
+ * @brief Implementation of generic named property classes
+ */
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "varprop.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+namespace varprop {
+
+/** @brief Construct empty property set */
+PropertySet::PropertySet(int hashsize)
+{
+ if (hashsize>0)
+ InitHashTable(hashsize);
+}
+/** @brief Construct object by copying specified source */
+PropertySet::PropertySet(const PropertySet & src)
+{
+ // delegate to CopyFrom, so we only have to write the code once
+ CopyFrom(src);
+}
+
+/** @brief Copy from other object (copy assignment operator) */
+PropertySet & PropertySet::operator=(const PropertySet & src)
+{
+ // delegate to CopyFrom, so we only have to write the code once
+ CopyFrom(src);
+ return *this;
+}
+
+/** @brief clean up contained memory */
+PropertySet::~PropertySet()
+{
+ // This looks the same as the base class, but this isn't a virtual method
+ // so we have to override the destructor to call it directly
+ // (Alternately, we could implement the DestructElements template helper)
+ RemoveAll();
+}
+
+/** @brief deallocate & remove elements */
+void PropertySet::RemoveAll()
+{
+ CString name;
+ Property * ptr=0;
+ for (POSITION pos = this->GetStartPosition(); pos; )
+ {
+ this->GetNextAssoc(pos, name, ptr);
+ delete ptr;
+ }
+ CTypedPtrMap<CMapStringToPtr, CString, Property*>::RemoveAll();
+}
+
+/** @brief Make this property set (to be) a copy of argument property set */
+void PropertySet::CopyFrom(const PropertySet & src)
+{
+ RemoveAll();
+ InitHashTable(src.GetHashTableSize());
+
+ CString name;
+ Property * ptr=0;
+ for (POSITION pos = src.GetStartPosition(); pos; )
+ {
+ src.GetNextAssoc(pos, name, ptr);
+ SetAt(name, new Property(*ptr));
+ }
+}
+
+/** @brief Assign a new property (or reassign existing) */
+void PropertySet::SetProperty(const Property & property)
+{
+ Property * ptr = 0;
+ if (Lookup(property.name, ptr))
+ *ptr = property;
+ else
+ {
+ if ((UINT)GetCount() > GetHashTableSize())
+ {
+ // TODO: enlarge hash table for better performance
+ }
+ SetAt(property.name, new Property(property));
+ }
+}
+/** Assign a new time-valued property (or reassign existing) */
+void PropertySet::SetProperty(LPCTSTR name, COleDateTime time)
+{
+ Property prop;
+ prop.name = name;
+ prop.value.SetTime(time);
+ SetProperty(prop);
+}
+/** Assign a new string-valued property (or reassign existing) */
+void PropertySet::SetProperty(LPCTSTR name, LPCTSTR value)
+{
+ Property prop;
+ prop.name = name;
+ prop.value.SetString(value);
+ SetProperty(prop);
+}
+/** Assign a new string-valued property (or reassign existing) */
+void PropertySet::SetProperty(LPCTSTR name, const CString & value)
+{
+ Property prop;
+ prop.name = name;
+ prop.value.SetString(value);
+ SetProperty(prop);
+}
+/** Assign a new int-valued property (or reassign existing) */
+void PropertySet::SetProperty(LPCTSTR name, int value)
+{
+ Property prop;
+ prop.name = name;
+ prop.value.SetInt(value);
+ SetProperty(prop);
+}
+
+/** @brief Retrieve a property by name (NULL if no such property) */
+Property * PropertySet::GetProperty(LPCTSTR szname)
+{
+ CString name = szname;
+ Property * ptr = 0;
+ Lookup(name, ptr);
+ return ptr;
+}
+
+/** @brief Retrieve a property by name (NULL if no such property) */
+const Property * PropertySet::GetProperty(LPCTSTR szname) const
+{
+ CString name = szname;
+ Property * ptr = 0;
+ Lookup(name, ptr);
+ return ptr;
+}
+
+} // namespace
--- /dev/null
+#ifndef varprop_h_included
+#define varprop_h_included
+
+namespace varprop {
+
+typedef enum { VT_NULL, VT_INT, VT_FLOAT, VT_STRING, VT_TIME } VT_TYPE;
+
+struct VariantValue
+{
+public:
+ VariantValue() : vtype(VT_NULL), ivalue(0), fvalue(0) { }
+ bool isInt() const { return vtype == VT_INT; }
+ bool isFloat() const { return vtype == VT_FLOAT; }
+ bool isString() const { return vtype == VT_STRING; }
+ bool isTime() const { return vtype == VT_TIME; }
+ VT_TYPE getType() const { return vtype; }
+
+ void SetInt(int v) { Clear(); vtype = VT_INT; ivalue = v; }
+ void SetFloat(double v) { Clear(); vtype = VT_FLOAT; fvalue = v; }
+ void SetString(LPCTSTR sz) { Clear(); vtype = VT_STRING; svalue = sz; }
+ void SetString(const CString & str) { Clear(); vtype = VT_STRING; svalue = str; }
+ void SetTime(const COleDateTime & v) { Clear(); vtype = VT_TIME; tvalue = v; }
+
+ void Clear() { vtype = VT_NULL; ivalue = 0; fvalue = 0; svalue = _T(""); tvalue.m_status = COleDateTime::null;}
+
+ int getInt() const { ASSERT(vtype == VT_INT); return ivalue; }
+ double getFloat() const { ASSERT(vtype == VT_FLOAT); return fvalue; }
+ CString getString() const { ASSERT(vtype == VT_STRING); return svalue; }
+ COleDateTime getTime() const { ASSERT(vtype == VT_TIME); return tvalue; }
+
+private:
+ VT_TYPE vtype;
+ int ivalue;
+ double fvalue;
+ CString svalue;
+ COleDateTime tvalue;
+};
+
+// Generic named property (name & value)
+struct Property { CString name; VariantValue value; };
+
+// Generic container of string properties, may be copied
+class PropertySet : private CTypedPtrMap<CMapStringToPtr, CString, Property*>
+{
+public:
+ // constructors, destructor, and copy operator
+ PropertySet(int hashsize=-1);
+ PropertySet(const PropertySet & src);
+ PropertySet & operator=(const PropertySet & src);
+ ~PropertySet();
+ void CopyFrom(const PropertySet & src);
+
+ // use
+ void SetProperty(const Property & property);
+ void SetProperty(LPCTSTR name, COleDateTime time);
+ void SetProperty(LPCTSTR name, LPCTSTR value);
+ void SetProperty(LPCTSTR name, const CString & value);
+ void SetProperty(LPCTSTR name, int value);
+ Property * GetProperty(LPCTSTR szname);
+ const Property * GetProperty(LPCTSTR szname) const;
+private:
+ void RemoveAll();
+};
+
+} // namespace
+
+#endif // varprop_h_included
Otherwise, sets out parameters diff (are files different?) and bin (are files binary?)
*/
bool
-just_compare_files (LPCTSTR filepath1, LPCTSTR filepath2, int depth, bool * diff, bool * bin)
+just_compare_files (LPCTSTR filepath1, LPCTSTR filepath2, int depth, bool * diff, bool * bin, int * ndiffs, int *ntrivialdiffs)
{
DiffFileData diffdata(filepath1, filepath2);
struct change *p,*e;
for (e = script; e; e = p)
{
+ (*ndiffs)++;
if (!e->trivial)
*diff = true;
+ else
+ (*ntrivialdiffs)++;
p = e->link;
free (e);
}
free(pNamesRight);
}
+
/**
* @brief Fetch & return the fixed file version as a dotted string
*/
return ver.GetFixedFileVersion();
}
+/** @brief Convert 64-bit time into COleDateTime */
+static COleDateTime TimeToOleDateTime(__int64 timval)
+{
+#if _MSC_VER < 1300
+ // MSVC6
+ COleDateTime odt = (time_t)timval;
+#else
+ // MSVC7 (VC.NET)
+ COleDateTime odt = timval;
+#endif
+ if (!timval)
+ odt.SetStatus(COleDateTime::null);
+ return odt;
+}
+
/**
* @brief Add new diffitem to CDiffContext array
*/
, __int64 lsize, __int64 rsize
, int diffcode
, int lattrs, int rattrs
+ , int ndiffs, int ntrivialdiffs
)
{
DIFFITEM di;
di.sSubdir = szSubdir;
di.left.spath = pszLeftDir;
di.right.spath = pszRightDir;
- di.left.mtime = lmtime;
- di.right.mtime = rmtime;
+ di.left.m_props.SetProperty(_T("mtime"), TimeToOleDateTime(lmtime));
+ di.right.m_props.SetProperty(_T("mtime"), TimeToOleDateTime(rmtime));
di.left.ctime = lctime;
di.right.ctime = rctime;
di.diffcode = diffcode;
UpdateFieldsNeededForNewItems(di, di.right);
di.left.flags.flags += lattrs;
di.right.flags.flags += rattrs;
+ if (ndiffs>=0 && ntrivialdiffs>=0)
+ {
+ di.shprops.SetProperty(_T("nsdiffs"), ndiffs-ntrivialdiffs);
+ di.shprops.SetProperty(_T("ndiffs"), ndiffs);
+ }
AddDiff(di);
}
/**
* @brief Add new diffitem to CDiffContext array
*/
-void CDiffContext::AddDiff(DIFFITEM di)
+void CDiffContext::AddDiff(DIFFITEM & di)
{
// BSP - Capture the extension; from the end of the file name to the last '.'
TCHAR *pDest = _tcsrchr(di.sfilename, _T('.') );
{
return m_pList->GetAt(diffpos);
}
+DIFFITEM & CDiffContext::GetDiffAt(POSITION diffpos)
+{
+ return m_pList->GetAt(diffpos);
+}
+
/**
* @brief Get number of items in CDiffContext array
WIN32_FIND_DATA wfd;
HANDLE h = FindFirstFile(filepath, &wfd);
+ __int64 mtime64 = 0;
if (h != INVALID_HANDLE_VALUE)
{
- dfi.mtime = FileTimeToInt64(wfd.ftLastWriteTime);
+ mtime64 = FileTimeToInt64(wfd.ftLastWriteTime);
dfi.flags.reset();
if (wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
dfi.flags.flags += FileFlags::RO;
}
else
{
- dfi.mtime = 0;
dfi.size = 0;
dfi.flags.reset();
}
+ dfi.m_props.SetProperty(_T("mtime"), TimeToOleDateTime(mtime64));
GuessEncoding(filepath, &dfi.unicoding, &dfi.codepage);
}
return right.spath;
}
+/**
+ * @brief Return generic property of specified name (or NULL if not found)
+ */
+const varprop::VariantValue * DIFFITEM::GetGenericProperty(LPCTSTR propname) const
+{
+ if (!propname)
+ return NULL;
+ // Is it a left property, right property, or shared?
+ const varprop::PropertySet * props = 0;
+ if (propname[0] == 'L')
+ props = &this->left.m_props;
+ else if (propname[0] == 'R')
+ props = &this->right.m_props;
+ else
+ props = &this->shprops;
+ // Look for property in property set we just figured out
+ // (real property name doesn't include first char)
+ const varprop::Property * prop = props->GetProperty(&propname[1]);
+ if (!prop)
+ return NULL;
+ return &prop->value;
+}
+
+/** @brief Return generic property of specified name, if found & a string (or _T("")) */
+CString DIFFITEM::GetGenericPropertyString(LPCTSTR propname) const
+{
+ const varprop::VariantValue * varval = GetGenericProperty(propname);
+ if (!varval || !varval->isString())
+ return _T("");
+ return varval->getString();
+}
+
+/** @brief Return generic property of specified name, if found & a string (or null time) */
+COleDateTime DIFFITEM::GetGenericPropertyTime(LPCTSTR propname) const
+{
+ const varprop::VariantValue * varval = GetGenericProperty(propname);
+ if (!varval || !varval->isTime())
+ {
+ COleDateTime time;
+ time.SetStatus(COleDateTime::null);
+ return time;
+ }
+ return varval->getTime();
+}
\ No newline at end of file
#include "RegExp.h"
+#ifndef varprop_h_included
+#include "varprop.h"
+#endif
+
struct dirdata
{
char const **names; /* Sorted names of files in dir, 0-terminated. */
struct DIFFITEM;
+
/**
* @brief information for file on one side of a diff
*/
{
// storing __time_t if MSVC6 (__MSC_VER<1300)
// storing __time64_t if MSVC7 (VC.NET)
- __int64 mtime; /**< time of last modification */
__int64 ctime; /**< time of creation */
__int64 size; /**< file size in bytes */
CString version; /**< string of fixed file version, eg, 1.2.3.4 */
FileFlags flags; /**< file attributes */
int codepage; /**< 8bit codepage, if applicable, 0 is unknown or N/A */
int unicoding; /**< Unicode encoding (ucr::CODESET) */
- DiffFileInfo() : mtime(0), ctime(0), size(0), codepage(0), unicoding(0) { }
+ varprop::PropertySet m_props;
+ DiffFileInfo() : ctime(0), size(0), codepage(0), unicoding(0) { }
+
CString getEncodingString() const;
// We could stash a pointer here to the parent DIFFITEM
// but, I ran into trouble with, I think, the DIFFITEM copy constructor
CString sSubdir; //*< Common subdirectory from root of comparison */
CString sext;
int diffcode;
+ varprop::PropertySet shprops; // shared properties
DIFFITEM() : diffcode(0) { }
bool isResultSkipped() const { return ((diffcode & DIFFCODE::COMPAREFLAGS) == DIFFCODE::SKIPPED); }
// type
bool isBin() const { return ((diffcode & DIFFCODE::TEXTFLAG) == DIFFCODE::BIN); }
+
+ // generic properties
+ const varprop::VariantValue * GetGenericProperty(LPCTSTR propname) const;
+ CString GetGenericPropertyString(LPCTSTR propname) const;
+ COleDateTime GetGenericPropertyTime(LPCTSTR propname) const;
};
// Interface for reporting current file, as diff traverses file tree
void AddDiff(LPCTSTR pszFilename, LPCTSTR szSubdir, LPCTSTR pszLeftDir, LPCTSTR pszRightDir
, __int64 lmtime, __int64 rmtime, __int64 lctime, __int64 rctime
, __int64 lsize, __int64 rsize, int diffcode
- , int lattrs=0, int rattrs=0);
- void AddDiff(DIFFITEM di);
+ , int lattrs=0, int rattrs=0
+ , int ndiffs=-1, int ntrivialdiffs=-1);
+ void AddDiff(DIFFITEM & di);
void RemoveDiff(POSITION diffpos);
void RemoveAll();
void UpdateFieldsNeededForNewItems(DIFFITEM & di, DiffFileInfo & dfi);
// to iterate over all differences on list
POSITION GetFirstDiffPosition();
DIFFITEM GetNextDiffPosition(POSITION & diffpos);
-// DIFFITEM GetDiffAt(POSITION diffpos);
+ DIFFITEM & GetDiffAt(POSITION diffpos);
const DIFFITEM & GetDiffAt(POSITION diffpos) const;
// int GetDiffStatus(POSITION diffpos);
int GetDiffCount();
m_pCtxt->UpdateStatusFromDisk(diffpos); // in case just copied (into existence) or modified
// Update view
- const DIFFITEM & updated = m_pCtxt->GetDiffAt(diffpos);
+ DIFFITEM & updated = m_pCtxt->GetDiffAt(diffpos);
m_pDirView->UpdateDiffItemStatus(nIdx, updated);
}
#include "paths.h"
#include "FileTransform.h"
-extern bool just_compare_files (LPCTSTR filepath1, LPCTSTR filepath2, int depth, bool * diff, bool * bin);
+extern bool just_compare_files (LPCTSTR filepath1, LPCTSTR filepath2, int depth, bool * diff, bool * bin, int * ndiffs, int *ntrivialdiffs);
extern CLogFile gLog;
#ifdef _DEBUG
void LoadAndSortFiles(const CString & sDir, fentryArray * dirs, fentryArray * files, bool casesensitive);
static void Sort(fentryArray * dirs, bool casesensitive);;
static int collstr(const CString & s1, const CString & s2, bool casesensitive);
-static void StoreDiffResult(const CString & sDir, const fentry * lent, const fentry *rent, int code, CDiffContext * pCtxt);
-static int prepAndCompareTwoFiles(const fentry & lent, const fentry & rent, const CString & sLeftDir, const CString & sRightDir);
+static void StoreDiffResult(const CString & sDir, const fentry * lent, const fentry *rent,
+ int code, CDiffContext * pCtxt, int ndiffs=-1, int ntrivialdiffs=-1);
+static int prepAndCompareTwoFiles(const fentry & lent, const fentry & rent, const CString & sLeftDir,
+ const CString & sRightDir, int * ndiffs, int * ntrivialdiffs);
/** @brief cmpmth is a typedef for a pointer to a method */
}
else
{
+ int ndiffs=0, ntrivialdiffs=0;
int code = prepAndCompareTwoFiles(leftFiles[i], rightFiles[j],
- sLeftDir, sRightDir);
+ sLeftDir, sRightDir, &ndiffs, &ntrivialdiffs);
// report result back to caller
- StoreDiffResult(subdir, &leftFiles[i], &rightFiles[j], code, pCtxt);
+ StoreDiffResult(subdir, &leftFiles[i], &rightFiles[j], code, pCtxt, ndiffs, ntrivialdiffs);
}
++i;
++j;
* @brief Prepare files (run plugins) & compare them, and return diffcode
*/
static int
-prepAndCompareTwoFiles(const fentry & lent, const fentry & rent,
- const CString & sLeftDir, const CString & sRightDir
+prepAndCompareTwoFiles(const fentry & lent, const fentry & rent,
+ const CString & sLeftDir, const CString & sRightDir,
+ int * ndiffs, int * ntrivialdiffs
+
)
{
// If options are binary equivalent, we could check for filesize
// just_compare_files is a fairly thin front-end to diffutils
bool diff=false, bin=false;
if (compareok)
- compareok = just_compare_files (filepathTransformed1, filepathTransformed2, 0, &diff, &bin);
+ {
+ compareok = just_compare_files (filepathTransformed1,
+ filepathTransformed2, 0, &diff, &bin, ndiffs, ntrivialdiffs);
+ }
// delete the temp files after comparison
if (filepathTransformed1 != filepath1)
/**
* @brief Send one file or directory result back through the diff context
*/
-static void StoreDiffResult(const CString & sDir, const fentry * lent, const fentry * rent, int code, CDiffContext * pCtxt)
+static void StoreDiffResult(const CString & sDir, const fentry * lent, const fentry * rent,
+ int code, CDiffContext * pCtxt, int ndiffs, int ntrivialdiffs)
{
CString name, leftdir, rightdir;
_int64 rmtime=0, lmtime=0, rctime=0, lctime=0;
gLog.Write(_T("name=<%s>, leftdir=<%s>, rightdir=<%s>, code=%d")
, (LPCTSTR)name, (LPCTSTR)leftdir, (LPCTSTR)rightdir, code);
pCtxt->AddDiff(name, sDir, leftdir, rightdir
- , lmtime, rmtime, lctime, rctime, lsize, rsize, code, lattrs, rattrs);
+ , lmtime, rmtime, lctime, rctime, lsize, rsize, code, lattrs, rattrs
+ , ndiffs, ntrivialdiffs);
}
class PackingInfo;
+namespace varprop { struct VariantValue; }
+
/** View displaying results of a diff, one row per file */
class CDirView : public CListViewEx
{
void UpdateColumnNames();
static int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
int AddDiffItem(int index, const DIFFITEM & di, LPCTSTR szPath, POSITION curdiffpos);
- void UpdateDiffItemStatus(UINT nIdx, const DIFFITEM & di);
+ void UpdateDiffItemStatus(UINT nIdx, DIFFITEM & di);
void ToDoDeleteThisValidateColumnOrdering() { ValidateColumnOrdering(); }
private:
void InitiateSort();
void MoveColumn(int psrc, int pdest);
CString GetColRegValueNameBase(int col) const;
int GetColDefaultOrder(int col) const;
+public:
+ static CString GetColItemDisplay(const varprop::VariantValue & var);
+ static int GenericSortItem(const varprop::VariantValue * lvar, const varprop::VariantValue * rvar);
+private:
// End DirViewCols.cpp
// Overrides
*/
static CString ColGet(int col, const DIFFITEM & di)
{
- return (*g_cols[col].getfnc)(di);
+ // Custom properties have custom get functions
+ ColGetFnc fnc = g_cols[col].getfnc;
+ if (fnc)
+ return (*fnc)(di);
+ // Ok, try to find it as a generic property
+ LPCTSTR propname = g_cols[col].regName;
+ const varprop::VariantValue * varval = di.GetGenericProperty(propname);
+ if (!varval)
+ return _T("");
+ // Format it as a string
+ return CDirView::GetColItemDisplay(*varval);
}
/**
*/
static int ColSort(int col, const DIFFITEM & ldi, const DIFFITEM &rdi)
{
- return (*g_cols[col].sortfnc)(ldi, rdi);
+ // Custom properties have custom sort functions
+ ColSortFnc fnc = g_cols[col].sortfnc;
+ if (fnc)
+ return (*fnc)(ldi, rdi);
+ // Ok, get generic properties, and then we'll use generic sort
+ LPCTSTR propname = g_cols[col].regName;
+ const varprop::VariantValue * lvar = ldi.GetGenericProperty(propname);
+ const varprop::VariantValue * rvar = rdi.GetGenericProperty(propname);
+ return CDirView::GenericSortItem(lvar, rvar);
}
/**
/// Update listview display of details for specified row
-void CDirView::UpdateDiffItemStatus(UINT nIdx, const DIFFITEM & di)
+void CDirView::UpdateDiffItemStatus(UINT nIdx, DIFFITEM & di)
{
BOOL bLeftNewer = FALSE;
BOOL bRightNewer = FALSE;
- // Determine if other side is newer
- if (di.left.mtime > 0 && di.right.mtime > 0)
+
+ COleDateTime lmtime = di.GetGenericPropertyTime(_T("Lmtime"));
+ COleDateTime rmtime = di.GetGenericPropertyTime(_T("Rmtime"));
+ if (lmtime.GetStatus() == COleDateTime::valid
+ && rmtime.GetStatus() == COleDateTime::valid)
{
- if (di.left.mtime > di.right.mtime)
+ if (lmtime > rmtime)
+ {
+ di.shprops.SetProperty(_T("Snewer"), _T("L"));
bLeftNewer = TRUE;
- else if (di.left.mtime < di.right.mtime)
+ }
+ else if (lmtime < rmtime)
+ {
+ di.shprops.SetProperty(_T("Snewer"), _T("R"));
bRightNewer = TRUE;
+ }
}
for (int i=0; i<g_ncols; ++i)
return i1>i2 ? 1 : -1;
}
/**
- * @brief Function to compare two diffcodes
+ * @brief Function to compare two diffcodes for a sort
*/
static int cmpdiffcode(int diffcode1, int diffcode2)
{
// TODO: How shall we order these ?
return diffcode1-diffcode2;
}
+/**
+ * @brief Function to compare two COleDateTimes for a sort
+ */
+static int cmptime(COleDateTime t1, COleDateTime t2)
+{
+ if (t1>t2)
+ return 1;
+ if (t1<t2)
+ return -1;
+ return 0;
+}
+/**
+ * @brief Function to compare two doubles for a sort
+ */
+static int cmpfloat(double v1, double v2)
+{
+ if (v1>v2)
+ return 1;
+ if (v1<v2)
+ return -1;
+ return 0;
+;
+}
/**
* @{ Functions to display each type of column info
}
return s;
}
-static CString ColLmtimeGet(const DIFFITEM & di)
-{
- if (di.left.mtime)
- return TimeString(&di.left.mtime);
- else
- return _T("");
-}
-static CString ColRmtimeGet(const DIFFITEM & di)
-{
- if (di.right.mtime)
- return TimeString(&di.right.mtime);
- else
- return _T("");
-}
static CString ColLctimeGet(const DIFFITEM & di)
{
if (di.left.ctime)
s.Format(_T("%I64d"), di.right.size);
return locality::GetLocaleStr(s);
}
+
static CString ColNewerGet(const DIFFITEM & di)
{
- if (di.left.mtime && di.right.mtime)
+ const varprop::Property * prop = di.shprops.GetProperty(_T("Snewer"));
+ if (prop && prop->value.isString())
{
- if (di.left.mtime > di.right.mtime)
+ CString newer = prop->value.getString();
+ if (newer == _T("L"))
return _T("<<<");
- if (di.left.mtime < di.right.mtime)
- return _T(">>>");
- return _T("===");
+ else if (newer == _T("R"))
+ return _T(">>");
+ else
+ return _T("==");
}
- else if (di.left.mtime)
+ else if (di.isSideLeft())
{
return _T("<*<");
}
- else if (di.right.mtime)
+ else if (di.isSideRight())
{
return _T(">*>");
}
{
return cmpdiffcode(rdi.diffcode, ldi.diffcode);
}
-static int ColLmtimeSort(const DIFFITEM & ldi, const DIFFITEM &rdi)
-{
- return cmp64(rdi.left.mtime, ldi.left.mtime);
-}
-static int ColRmtimeSort(const DIFFITEM & ldi, const DIFFITEM &rdi)
-{
- return cmp64(rdi.right.mtime, ldi.right.mtime);
-}
-static int ColLctimeSort(const DIFFITEM & ldi, const DIFFITEM &rdi)
-{
- return cmp64(rdi.left.ctime, ldi.left.ctime);
-}
-static int ColRctimeSort(const DIFFITEM & ldi, const DIFFITEM &rdi)
-{
- return cmp64(rdi.right.ctime, ldi.right.ctime);
-}
static int ColExtSort(const DIFFITEM & ldi, const DIFFITEM &rdi)
{
return ldi.sext.CompareNoCase(rdi.sext);
{ _T("Name"), IDS_COLHDR_FILENAME, -1, &ColNameGet, &ColNameSort, 0, true }
, { _T("Path"), IDS_COLHDR_DIR, -1, &ColPathGet, &ColPathSort, 1, true }
, { _T("Status"), IDS_COLHDR_RESULT, -1, &ColStatusGet, &ColStatusSort, 2, true}
- , { _T("Lmtime"), IDS_COLHDR_LTIMEM, -1, &ColLmtimeGet, &ColLmtimeSort, 3, false }
- , { _T("Rmtime"), IDS_COLHDR_RTIMEM, -1, &ColRmtimeGet, &ColRmtimeSort, 4, false }
- , { _T("Lctime"), IDS_COLHDR_LTIMEC, -1, &ColLctimeGet, &ColLctimeSort, -1, false }
- , { _T("Rctime"), IDS_COLHDR_RTIMEC, -1, &ColRctimeGet, &ColRctimeSort, -1, false }
+ , { _T("Lmtime"), IDS_COLHDR_LTIMEM, -1, NULL, NULL, 3, false }
+ , { _T("Rmtime"), IDS_COLHDR_RTIMEM, -1, NULL, NULL, 4, false }
+ , { _T("Lctime"), IDS_COLHDR_LTIMEC, -1, NULL, NULL, -1, false }
+ , { _T("Rctime"), IDS_COLHDR_RTIMEC, -1, NULL, NULL, -1, false }
, { _T("Ext"), IDS_COLHDR_EXTENSION, -1, &ColExtGet, &ColExtSort, 5, true }
, { _T("Lsize"), IDS_COLHDR_LSIZE, -1, &ColLsizeGet, &ColLsizeSort, -1, true }
, { _T("Rsize"), IDS_COLHDR_RSIZE, -1, &ColRsizeGet, &ColRsizeSort, -1, true }
, { _T("Rattr"), IDS_COLHDR_RATTRIBUTES, -1, &ColRattrGet, &ColRattrSort, -1, true }
, { _T("Lencoding"), IDS_COLHDR_LENCODING, -1, &ColLencodingGet, &ColLencodingSort, -1, true }
, { _T("Rencoding"), IDS_COLHDR_RENCODING, -1, &ColRencodingGet, &ColRencodingSort, -1, true }
+ , { _T("Sndiffs"), IDS_COLHDR_NDIFFS, -1, NULL, NULL, -1, false }
+ , { _T("Snsdiffs"), IDS_COLHDR_NSDIFFS, -1, NULL, NULL, -1, false }
};
/**
ASSERT(col>=0 && col<countof(g_cols));
return g_cols[col].physicalIndex;
}
+
+/**
+ * @brief Format and display a generic property
+ */
+CString CDirView::GetColItemDisplay(const varprop::VariantValue & var)
+{
+ if (var.isString())
+ {
+ return var.getString();
+ }
+ if (var.isInt())
+ {
+ CString str;
+ str.Format(_T("%d"), var.getInt());
+ return locality::GetLocaleStr(str);
+ }
+ if (var.isTime())
+ {
+ if (var.getTime().GetStatus() != COleDateTime::valid)
+ return _T("");
+ return var.getTime().Format();
+ }
+ if (var.isFloat())
+ {
+ CString str;
+ str.Format(_T("%lf"), var.getFloat());
+ return str;
+ }
+ return _T("?");
+}
+
+/**
+ * @brief Compare two generic property values (used in dirview sort)
+ */
+int CDirView::GenericSortItem(const varprop::VariantValue * lvar, const varprop::VariantValue * rvar)
+{
+ // If not the same type, simply compare types (this really shouldn't happen anyway)
+ if (!lvar)
+ return rvar ? 1 : 0;
+ if (!rvar)
+ return -1;
+ if (lvar->getType() > rvar->getType())
+ return 1;
+ else if (lvar->getType() < rvar->getType())
+ return -1;
+ // Ok, they're the same type, so we can compare their values
+ if (lvar->isString())
+ return lvar->getString().Compare(rvar->getString());
+ if (lvar->isInt())
+ return cmp64(lvar->getInt(), rvar->getInt());
+ if (lvar->isTime())
+ return cmptime(lvar->getTime(), rvar->getTime());
+ if (lvar->isFloat())
+ return cmpfloat(lvar->getFloat(), rvar->getFloat());
+ ASSERT(0);
+ return 0;
+}
+
# End Source File
# Begin Source File
+SOURCE=.\Common\varprop.cpp
+# End Source File
+# Begin Source File
+
SOURCE=.\Common\version.cpp
# End Source File
# Begin Source File
# End Source File
# Begin Source File
+SOURCE=.\Common\varprop.h
+# End Source File
+# Begin Source File
+
SOURCE=.\Common\version.h
# End Source File
# Begin Source File
IDS_STATUSBAR_READONLY "RO"
IDS_COLHDR_LENCODING "Left Encoding"
IDS_COLHDR_RENCODING "Right Encoding"
+ IDS_COLHDR_NDIFFS "#differences"
+ IDS_COLHDR_NSDIFFS "#sig. differences"
IDS_DIRECTORY_REPORT_TITLE "Compare %1 with %2"
END
+2004-01-21 Perry
+ PATCH: [ 878631 ] Add generic named properties to DiffContext
+ src: Diff.cpp DiffContext.cpp DiffContext.h DirDoc.cpp DirScan.cpp
+ DirView.h DirViewColHandler.cpp DirViewColItems.cpp Merge.dsp
+ Merge.rc resource.h
+ src/Common: varprop.cpp varprop.h
+
2004-01-21 Kimmo
PATCH: [ 880898 ] BCMenu update to v3.034
src: BCMenu.h BCMenu.cpp
#define IDC_WMGOTO_TOLINE 1111
#define IDC_WMGOTO_TODIFF 1112
#define IDC_WMGOTO_PARAM 1113
+#define IDS_COLHDR_NDIFFS 1114
+#define IDS_COLHDR_NSDIFFS 1115
#define IDS_NUM_REPLACED 8501
#define IDS_EDIT_TEXT_NOT_FOUND 8502
#define IDS_LINE_STATUS_INFO_EOL 8503
#define _APS_3D_CONTROLS 1
#define _APS_NEXT_RESOURCE_VALUE 121
#define _APS_NEXT_COMMAND_VALUE 32864
-#define _APS_NEXT_CONTROL_VALUE 1108
+#define _APS_NEXT_CONTROL_VALUE 1115
#define _APS_NEXT_SYMED_VALUE 108
#endif
#endif