OSDN Git Service

PATCH: [ 878631 ] Add generic named properties to DiffContext
authorPerry Rapp <elsapo@users.sourceforge.net>
Wed, 21 Jan 2004 22:39:20 +0000 (22:39 +0000)
committerPerry Rapp <elsapo@users.sourceforge.net>
Wed, 21 Jan 2004 22:39:20 +0000 (22:39 +0000)
14 files changed:
Src/Common/varprop.cpp [new file with mode: 0644]
Src/Common/varprop.h [new file with mode: 0644]
Src/Diff.cpp
Src/DiffContext.cpp
Src/DiffContext.h
Src/DirDoc.cpp
Src/DirScan.cpp
Src/DirView.h
Src/DirViewColHandler.cpp
Src/DirViewColItems.cpp
Src/Merge.dsp
Src/Merge.rc
Src/readme.txt
Src/resource.h

diff --git a/Src/Common/varprop.cpp b/Src/Common/varprop.cpp
new file mode 100644 (file)
index 0000000..0722cf8
--- /dev/null
@@ -0,0 +1,143 @@
+/**
+ *  @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
diff --git a/Src/Common/varprop.h b/Src/Common/varprop.h
new file mode 100644 (file)
index 0000000..cab9b88
--- /dev/null
@@ -0,0 +1,67 @@
+#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
index ae077d3..7d61bf2 100644 (file)
@@ -64,7 +64,7 @@ int recursive;
   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);
@@ -91,8 +91,11 @@ just_compare_files (LPCTSTR filepath1, LPCTSTR filepath2, int depth, bool * diff
                struct change *p,*e;
                for (e = script; e; e = p)
                {
+                       (*ndiffs)++;
                        if (!e->trivial)
                                *diff = true;
+                       else
+                               (*ntrivialdiffs)++;
                        p = e->link;
                        free (e);
                }
index c2a86a2..8ececf9 100644 (file)
@@ -95,6 +95,7 @@ CDiffContext::~CDiffContext()
                free(pNamesRight);
 }
 
+
 /**
  * @brief Fetch & return the fixed file version as a dotted string
  */
@@ -104,6 +105,21 @@ static CString GetFixedFileVersion(const CString & path)
        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
  */
@@ -114,6 +130,7 @@ void CDiffContext::AddDiff(LPCTSTR pszFilename, LPCTSTR szSubdir
        , __int64 lsize, __int64 rsize
        , int diffcode
        , int lattrs, int rattrs
+       , int ndiffs, int ntrivialdiffs
        )
 {
        DIFFITEM di;
@@ -121,8 +138,8 @@ void CDiffContext::AddDiff(LPCTSTR pszFilename, LPCTSTR szSubdir
        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;
@@ -132,13 +149,18 @@ void CDiffContext::AddDiff(LPCTSTR pszFilename, LPCTSTR szSubdir
        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('.') );
@@ -205,6 +227,11 @@ const DIFFITEM & CDiffContext::GetDiffAt(POSITION diffpos) const
 {
        return m_pList->GetAt(diffpos);
 }
+DIFFITEM & CDiffContext::GetDiffAt(POSITION diffpos)
+{
+       return m_pList->GetAt(diffpos);
+}
+
 
 /**
  * @brief Get number of items in CDiffContext array
@@ -285,9 +312,10 @@ void CDiffContext::UpdateInfoFromDiskHalf(DIFFITEM & di, DiffFileInfo & dfi)
 
        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;
@@ -296,10 +324,10 @@ void CDiffContext::UpdateInfoFromDiskHalf(DIFFITEM & di, DiffFileInfo & dfi)
        }
        else
        {
-               dfi.mtime = 0;
                dfi.size = 0;
                dfi.flags.reset();
        }
+       dfi.m_props.SetProperty(_T("mtime"), TimeToOleDateTime(mtime64));
        GuessEncoding(filepath, &dfi.unicoding, &dfi.codepage);
 }
 
@@ -425,3 +453,47 @@ CString DIFFITEM::getRightFilepath() const
        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
index 238a7f8..ea68cd0 100644 (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.  */
@@ -58,6 +62,7 @@ struct FileFlags
 
 struct DIFFITEM;
 
+
 /**
  * @brief information for file on one side of a diff
  */
@@ -65,7 +70,6 @@ struct DiffFileInfo
 {
        // 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 */
@@ -73,7 +77,9 @@ struct DiffFileInfo
        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
@@ -104,6 +110,7 @@ struct DIFFITEM
        CString sSubdir; //*< Common subdirectory from root of comparison */
        CString sext;
        int diffcode;
+       varprop::PropertySet shprops; // shared properties
 
        DIFFITEM() : diffcode(0) { }
 
@@ -123,6 +130,11 @@ struct DIFFITEM
        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
@@ -153,8 +165,9 @@ public:
        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);
@@ -163,7 +176,7 @@ public:
        // 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();
index 07f0764..817c3dc 100644 (file)
@@ -395,7 +395,7 @@ void CDirDoc::ReloadItemStatus(UINT nIdx)
        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);
 }
 
index d1240e9..4ae05e2 100644 (file)
@@ -13,7 +13,7 @@
 #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
@@ -43,8 +43,10 @@ static void LoadFiles(const CString & sDir, fentryArray * dirs, fentryArray * fi
 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 */
@@ -196,11 +198,12 @@ int DirScan(const CString & subdir, CDiffContext * pCtxt, bool casesensitive,
                        }
                        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;
@@ -215,8 +218,10 @@ int DirScan(const CString & subdir, CDiffContext * pCtxt, bool casesensitive,
  * @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
@@ -292,7 +297,10 @@ prepAndCompareTwoFiles(const fentry & lent, const fentry & rent,
        // 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)
@@ -408,7 +416,8 @@ static int collstr(const CString & s1, const CString & s2, bool casesensitive)
 /**
  * @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;
@@ -440,5 +449,6 @@ static void StoreDiffResult(const CString & sDir, const fentry * lent, const fen
        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);
 }
index 7ae5750..e6c2c2e 100644 (file)
@@ -58,6 +58,8 @@ class CDirFrame;
 
 class PackingInfo;
 
+namespace varprop { struct VariantValue; }
+
 /** View displaying results of a diff, one row per file */
 class CDirView : public CListViewEx
 {
@@ -156,7 +158,7 @@ public:
        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();
@@ -175,6 +177,10 @@ private:
        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
index 6f99c7b..5fb8f10 100644 (file)
@@ -56,7 +56,17 @@ enum
  */
 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);
 }
 
 /**
@@ -64,7 +74,15 @@ static CString ColGet(int col, const DIFFITEM & di)
  */
 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);
 }
 
 /**
@@ -158,18 +176,27 @@ int CDirView::AddDiffItem(int index, const DIFFITEM & di, LPCTSTR szPath, POSITI
 
 
 /// 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)
index f2d6082..4cf3c6f 100644 (file)
@@ -69,13 +69,36 @@ static int cmp64(__int64 i1, __int64 i2)
        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
@@ -132,20 +155,6 @@ static CString ColStatusGet(const DIFFITEM & di)
        }
        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)
@@ -176,21 +185,25 @@ static CString ColRsizeGet(const DIFFITEM & di)
        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(">*>");
        }
@@ -287,22 +300,6 @@ static int ColStatusSort(const DIFFITEM & ldi, const DIFFITEM &rdi)
 {
        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);
@@ -361,10 +358,10 @@ DirColInfo g_cols[] =
        { _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 }
@@ -376,6 +373,8 @@ DirColInfo g_cols[] =
        , { _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 }
 };
 
 /**
@@ -402,3 +401,61 @@ int CDirView::GetColDefaultOrder(int col) const
        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;
+}
+
index c74dc2c..1644a12 100644 (file)
@@ -1392,6 +1392,10 @@ SOURCE=.\diffutils\src\UTIL.C
 # 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
@@ -1766,6 +1770,10 @@ SOURCE=.\Common\UniFile.h
 # 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
index 7cb754c..d53f0b1 100644 (file)
@@ -1279,6 +1279,8 @@ BEGIN
     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
 
index bafe210..1d71d2f 100644 (file)
@@ -1,3 +1,10 @@
+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
index 7bffec2..049b2e3 100644 (file)
 #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