OSDN Git Service

PATCH: [ 781529 ] Make column info array, and add new columns
authorPerry Rapp <elsapo@users.sourceforge.net>
Sat, 23 Aug 2003 18:09:14 +0000 (18:09 +0000)
committerPerry Rapp <elsapo@users.sourceforge.net>
Sat, 23 Aug 2003 18:09:14 +0000 (18:09 +0000)
Src/DirColsDlg.cpp [new file with mode: 0644]
Src/DirColsDlg.h [new file with mode: 0644]
Src/DirViewColHandler.cpp [new file with mode: 0644]
Src/DirViewColItems.cpp [new file with mode: 0644]
Src/DirViewColItems.h [new file with mode: 0644]

diff --git a/Src/DirColsDlg.cpp b/Src/DirColsDlg.cpp
new file mode 100644 (file)
index 0000000..8ff1089
--- /dev/null
@@ -0,0 +1,224 @@
+/** 
+ * @file  DirColsDlg.cpp
+ *
+ * @brief Implementation file for CDirColsDlg
+ *
+ * @date  Created: 2003-08-19
+ */
+// RCS ID line follows -- this is updated by CVS
+// $Id$
+
+
+#include "stdafx.h"
+#include "merge.h"
+#include "DirColsDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CDirColsDlg dialog
+
+
+CDirColsDlg::CDirColsDlg(CWnd* pParent /*=NULL*/)
+       : CDialog(CDirColsDlg::IDD, pParent)
+{
+       //{{AFX_DATA_INIT(CDirColsDlg)
+       //}}AFX_DATA_INIT
+}
+
+
+void CDirColsDlg::DoDataExchange(CDataExchange* pDX)
+{
+       CDialog::DoDataExchange(pDX);
+       //{{AFX_DATA_MAP(CDirColsDlg)
+       DDX_Control(pDX, IDC_LIST_SHOW, m_list_show);
+       DDX_Control(pDX, IDC_LIST_HIDE, m_list_hide);
+       //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CDirColsDlg, CDialog)
+       //{{AFX_MSG_MAP(CDirColsDlg)
+       ON_BN_CLICKED(IDC_UP, OnUp)
+       ON_BN_CLICKED(IDC_DOWN, OnDown)
+       ON_BN_CLICKED(IDC_ADD, OnAdd)
+       ON_BN_CLICKED(IDC_REMOVE, OnRemove)
+       //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CDirColsDlg message handlers
+
+BOOL CDirColsDlg::OnInitDialog() 
+{
+       CDialog::OnInitDialog();
+
+       LoadLists();
+       
+       return TRUE;  // return TRUE unless you set the focus to a control
+                     // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+/**
+ * @brief Load listboxes on screen from column array
+ */
+void CDirColsDlg::LoadLists()
+{
+       for (int i=0; i<m_cols.GetSize(); ++i)
+       {
+               const column & c = m_cols[i];
+               CListBox * list = (c.phy_col >= 0) ? &m_list_show : &m_list_hide;
+               int x = list->AddString(m_cols[i].name);
+               list->SetItemData(x, c.log_col);
+       }
+       SortArrayToLogicalOrder();
+       UpdateEnables();
+}
+
+/**
+ * @brief Sort m_cols so that it is in logical column order.
+ */
+void CDirColsDlg::SortArrayToLogicalOrder()
+{
+       qsort(m_cols.GetData(), m_cols.GetSize(), sizeof(m_cols[0]), &cmpcols);
+}
+
+int __cdecl CDirColsDlg::cmpcols(const void * el1, const void * el2)
+{
+       const column * col1 = reinterpret_cast<const column *>(el1);
+       const column * col2 = reinterpret_cast<const column *>(el2);
+       return col1->log_col - col2->log_col;
+}
+
+/**
+ * @brief Move selected items up (in show list)
+ */
+void CDirColsDlg::OnUp()
+{
+       CListBox * list = &m_list_show;
+       // find the first item not selected
+       for (int i=0; i<list->GetCount(); ++i)
+       {
+               if (!list->GetSel(i))
+                       break;
+       }
+       // continue down, moving up all selected items 
+       for (++i; i<list->GetCount(); ++i)
+       {
+               if (list->GetSel(i))
+               {
+                       int data = list->GetItemData(i);
+                       CString str;
+                       list->GetText(i, str);
+                       list->DeleteString(i);
+                       int inew = i-1;
+                       list->InsertString(inew, str);
+                       list->SetItemData(inew, data);
+                       list->SetSel(inew);
+               }
+       }
+}
+
+/**
+ * @brief Move selected items down (in show list)
+ */
+void CDirColsDlg::OnDown() 
+{
+       CListBox * list = &m_list_show;
+       // find the lst item not selected
+       for (int i=list->GetCount()-1; i>=0; --i)
+       {
+               if (!list->GetSel(i))
+                       break;
+       }
+       // continue down, moving up all selected items 
+       for (--i; i>=0; --i)
+       {
+               if (list->GetSel(i))
+               {
+                       int data = list->GetItemData(i);
+                       CString str;
+                       list->GetText(i, str);
+                       list->DeleteString(i);
+                       int inew = i+1;
+                       list->InsertString(inew, str);
+                       list->SetItemData(inew, data);
+                       list->SetSel(inew);
+               }
+       }
+}
+
+/**
+ * @brief Move selected items from hide list to show list
+ */
+void CDirColsDlg::OnAdd() 
+{
+       MoveItems(&m_list_hide, &m_list_show, false);
+}
+
+/**
+ * @brief Move selected items from show list to hide list
+ */
+void CDirColsDlg::OnRemove() 
+{
+       MoveItems(&m_list_show, &m_list_hide, true);
+}
+
+/**
+ * @brief Move selected items from list1 to list2, putting at top if top==true
+ */
+void CDirColsDlg::MoveItems(CListBox * list1, CListBox * list2, bool top)
+{
+       for (int i=0; i<list1->GetCount(); ++i)
+       {
+               if (list1->GetSel(i))
+               {
+                       int data = list1->GetItemData(i);
+                       CString str;
+                       list1->GetText(i, str);
+                       list1->DeleteString(i);
+                       --i; // new item promoted to slot#i in list1, we need to check it next
+                       int inew = top ? 0 : list2->GetCount();
+                       list2->InsertString(inew, str);
+                       list2->SetItemData(inew, data);
+                       list2->SetSel(inew);
+               }
+       }
+       UpdateEnables();
+}
+
+/**
+ * @brief Enable/disable the Add/Remove buttons appropriately
+ */
+void CDirColsDlg::UpdateEnables()
+{
+       // TODO: We could enable/disable Up/Down buttons also, but
+       // we'd have to trap selection events
+
+       GetDlgItem(IDC_ADD)->EnableWindow(m_list_hide.GetCount() > 0);
+       GetDlgItem(IDC_REMOVE)->EnableWindow(m_list_show.GetCount() > 0);
+}
+
+/**
+ * @brief User clicked ok, so we update m_cols and close
+ */
+void CDirColsDlg::OnOK() 
+{
+       // Update all the data in m_cols according to layout on screen
+       for (int i=0; i<m_list_show.GetCount(); ++i)
+       {
+               column * col1 = &m_cols[m_list_show.GetItemData(i)];
+               col1->phy_col = i;
+       }
+       for (i=0; i<m_list_hide.GetCount(); ++i)
+       {
+               column * col1 = &m_cols[m_list_hide.GetItemData(i)];
+               col1->phy_col = -1;
+       }
+       
+       CDialog::OnOK();
+}
diff --git a/Src/DirColsDlg.h b/Src/DirColsDlg.h
new file mode 100644 (file)
index 0000000..093425e
--- /dev/null
@@ -0,0 +1,85 @@
+/** 
+ * @file  DirColsDlg.h
+ *
+ * @brief Declaration file for CDirColsDlg
+ *
+ * @date  Created: 2003-08-19
+ */
+// RCS ID line follows -- this is updated by CVS
+// $Id$
+
+
+#if !defined(AFX_DIRCOLSDLG_H__2FCB576C_C609_4623_8C55_F3870F22CA0B__INCLUDED_)
+#define AFX_DIRCOLSDLG_H__2FCB576C_C609_4623_8C55_F3870F22CA0B__INCLUDED_
+#pragma once
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CDirColsDlg dialog
+
+/**
+ * @brief Dialog to choose & order columns to be shown in dirview of differing files
+ */
+class CDirColsDlg : public CDialog
+{
+// Public types
+public:
+       struct column {
+               CString name;
+               int log_col;
+               int phy_col;
+               column() : log_col(-1), phy_col(-1) { } /**< default constructor for use in CArray */
+               column(LPCTSTR sz, int log, int phy) : name(sz), log_col(log), phy_col(phy) { } 
+       };
+       typedef CArray<column, column> ColumnArray;
+
+// Construction
+public:
+       CDirColsDlg(CWnd* pParent = NULL);   // standard constructor
+       void AddColumn(CString name, int log, int phy=-1)
+               { column c(name, log, phy); m_cols.Add(c); }
+       const ColumnArray & GetColumns() const { return m_cols; }
+
+// Dialog Data
+       //{{AFX_DATA(CDirColsDlg)
+       enum { IDD = IDD_DIRCOLS };
+       CListBox        m_list_show;
+       CListBox        m_list_hide;
+       //}}AFX_DATA
+
+
+// Overrides
+       // ClassWizard generated virtual function overrides
+       //{{AFX_VIRTUAL(CDirColsDlg)
+       protected:
+       virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+       //}}AFX_VIRTUAL
+
+// Implementation methods
+protected:
+       void LoadLists();
+       void MoveItems(CListBox * list1, CListBox * list2, bool top);
+       void UpdateEnables();
+       void SortArrayToLogicalOrder();
+       static int cmpcols(const void * el1, const void * el2);
+
+// Implementation data
+private:
+       ColumnArray m_cols;
+
+       // Generated message map functions
+       //{{AFX_MSG(CDirColsDlg)
+       virtual BOOL OnInitDialog();
+       afx_msg void OnUp();
+       afx_msg void OnDown();
+       afx_msg void OnAdd();
+       afx_msg void OnRemove();
+       virtual void OnOK();
+       //}}AFX_MSG
+       DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_DIRCOLSDLG_H__2FCB576C_C609_4623_8C55_F3870F22CA0B__INCLUDED_)
diff --git a/Src/DirViewColHandler.cpp b/Src/DirViewColHandler.cpp
new file mode 100644 (file)
index 0000000..f56e9f6
--- /dev/null
@@ -0,0 +1,401 @@
+/** 
+ * @file  DirViewColHandler.cpp
+ *
+ * @brief Methods of CDirView dealing with the listview (of file results)
+ *
+ * @date  Created: 2003-08-19
+ */
+// RCS ID line follows -- this is updated by CVS
+// $Id$
+
+
+#include "stdafx.h"
+#include "Merge.h"
+#include "DirView.h"
+#include "DirDoc.h"
+#include "MainFrm.h"
+#include "resource.h"
+#include "coretools.h"
+#include "dllver.h"
+#include "DirViewColItems.h"
+#include "DirColsDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+/**
+ * @brief Get text for specified column (forwards to specific column handler)
+ */
+static CString ColGet(int col, const DIFFITEM & di)
+{
+       return (*g_cols[col].getfnc)(di);
+}
+
+/**
+ * @brief Sort two items on specified column (forwards to specific column handler)
+ */
+static int ColSort(int col, const DIFFITEM & ldi, const DIFFITEM &rdi)
+{
+       return (*g_cols[col].sortfnc)(ldi, rdi);
+}
+
+/**
+ * @brief return whether column normally sorts ascending (dates do not)
+ */
+bool CDirView::IsDefaultSortAscending(int col) const
+{
+       return g_cols[col].defSortUp;
+}
+
+/// Assign column name, using string resource & current column ordering
+void CDirView::NameColumn(int id, int subitem)
+{
+       int phys = ColLogToPhys(subitem);
+       if (phys>=0)
+       {
+               CString s;
+               VERIFY(s.LoadString(id));
+               LV_COLUMN lvc;
+               lvc.mask = LVCF_TEXT;
+               lvc.pszText = (LPTSTR)((LPCTSTR)s);
+               m_pList->SetColumn(m_colorder[subitem], &lvc);
+       }
+}
+
+/// Load column names from string table
+void CDirView::UpdateColumnNames()
+{
+       for (int i=0; i<g_ncols; ++i)
+       {
+               const DirColInfo & col = g_cols[i];
+               NameColumn(col.idName, i);
+       }
+}
+
+/// Compare two specified rows during a sort operation (windows callback)
+int CALLBACK CDirView::CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
+{
+       // initialize structures to obtain required information
+       CDirView* pView = reinterpret_cast<CDirView*>(lParamSort);
+       POSITION diffposl = pView->GetItemKeyFromData(lParam1);
+       POSITION diffposr = pView->GetItemKeyFromData(lParam2);
+       DIFFITEM ldi = pView->GetDiffContext()->GetDiffAt(diffposl);
+       DIFFITEM rdi = pView->GetDiffContext()->GetDiffAt(diffposr);
+
+       // compare 'left' and 'right' parameters as appropriate
+       int retVal = ColSort(pView->m_sortColumn, ldi, rdi);
+
+       // return compare result, considering sort direction
+       return (pView->m_bSortAscending)?retVal:-retVal;
+}
+
+// Add new item to list view
+int CDirView::AddNewItem(int i)
+{
+       LV_ITEM lvItem;
+       memset(&lvItem, 0, sizeof(lvItem));
+       lvItem.iItem = i;
+       return GetListCtrl().InsertItem(&lvItem);
+  
+}
+
+// Set a subitem on an existing item
+void CDirView::SetSubitem(int item, int phy, LPCTSTR sz)
+{
+       LV_ITEM lvItem;
+       memset(&lvItem, 0, sizeof(lvItem));
+       lvItem.mask = LVIF_TEXT;
+       lvItem.iItem = item;
+       lvItem.iSubItem = phy;
+       lvItem.pszText = const_cast<LPTSTR>(sz);
+       GetListCtrl().SetItem(&lvItem);
+}
+
+
+// Add a new diff item to dir view
+int CDirView::AddDiffItem(int index, const DIFFITEM & di, LPCTSTR szPath, POSITION curdiffpos)
+{
+       int i = AddNewItem(index);
+       SetItemKey(i, curdiffpos);
+       SetImage(i, FILE_ERROR);
+       return i;
+}
+
+/**
+ * @brief Return image index appropriate for this row
+ */
+static int GetColImage(const DIFFITEM & di)
+{
+       switch (di.code)
+       {
+       case FILE_DIFF: return FILE_DIFF;
+       case FILE_BINDIFF: return FILE_BINDIFF;
+       case FILE_BINSAME: return FILE_BINSAME;
+       case FILE_LUNIQUE:
+       case FILE_LDIRUNIQUE:
+               return di.code;
+       case FILE_RUNIQUE:
+       case FILE_RDIRUNIQUE:
+               return di.code;
+               break;
+       case FILE_SAME: return FILE_SAME;
+       default: return FILE_ERROR;
+       }
+}
+
+// Update listview display of details for specified row
+void CDirView::UpdateDiffItemStatus(UINT nIdx, const DIFFITEM & di)
+{
+       for (int i=0; i<g_ncols; ++i)
+       {
+               const DirColInfo & col = g_cols[i];
+               int phy = ColLogToPhys(i);
+               if (phy>=0)
+                       SetSubitem(nIdx, phy, ColGet(i, di));
+       }
+       SetImage(nIdx, GetColImage(di));
+}
+
+/// store current column orders into registry
+void CDirView::SaveColumnOrders()
+{
+       ASSERT(m_colorder.GetSize() == m_numcols);
+       ASSERT(m_invcolorder.GetSize() == m_numcols);
+       int cols = GetListCtrl().GetHeaderCtrl()->GetItemCount();
+       for (int i=0; i < m_numcols; i++)
+       {
+               CString RegName = GetColRegValueNameBase(i) + _T("_Order");
+               int ord = m_colorder[i];
+               theApp.WriteProfileInt(_T("DirView"), RegName, ord);
+       }
+}
+
+
+/**
+ * @brief Load column orders from registry
+ */
+void CDirView::LoadColumnOrders()
+{
+       ASSERT(m_numcols == -1);
+       m_numcols = GetColLogCount();
+       ClearColumnOrders();
+       m_dispcols = 0;
+
+       // Load column orders
+       // Break out if one is missing
+       // Break out & mark failure (m_dispcols == -1) if one is invalid
+       for (int i=0; i<m_numcols; ++i)
+       {
+               CString RegName = GetColRegValueNameBase(i) + _T("_Order");
+               int ord = theApp.GetProfileInt(_T("DirView"), RegName, -2);
+               if (ord<-1 || ord >= m_numcols)
+                       break;
+               m_colorder[i] = ord;
+               if (ord>=0)
+               {
+                       ++m_dispcols;
+                       if (m_invcolorder[ord] != -1)
+                       {
+                               m_dispcols = -1;
+                               break;
+                       }
+                       m_invcolorder[ord] = i;
+               }
+       }
+       // Check that a contiguous range was set
+       for (i=0; i<m_dispcols; ++i)
+       {
+               if (m_invcolorder[i] < 0)
+               {
+                       m_dispcols = -1;
+                       break;
+               }
+       }
+       // Must have at least one column
+       if (m_dispcols<=1)
+       {
+               ResetColumnOrdering();
+       }
+
+       ValidateColumnOrdering();
+}
+
+/**
+ * @brief Sanity check column ordering
+ */
+void CDirView::ValidateColumnOrdering()
+{
+TRACE(" <%s>\n", COleDateTime::GetCurrentTime().Format());
+for (int k=0; k<m_invcolorder.GetSize();++k)
+       TRACE("invcolorder[%d]=%d\n", k, m_invcolorder[k]);
+for (k=0; k<m_colorder.GetSize();++k)
+       TRACE("colorder[%d]=%d\n", k, m_colorder[k]);
+
+#if _DEBUG
+       ASSERT(m_invcolorder[0]>=0);
+       ASSERT(m_numcols == GetColLogCount());
+       // Check that any logical->physical mapping is reversible
+       for (int i=0; i<m_numcols; ++i)
+       {
+               int phy = m_colorder[i];
+               if (phy >= 0)
+               {
+                       int log = m_invcolorder[phy];
+                       ASSERT(i == log);
+               }
+       }
+       // Bail out if header doesn't exist yet
+       int hdrcnt = GetListCtrl().GetHeaderCtrl()->GetItemCount();
+       if (hdrcnt)
+       {
+               ASSERT(hdrcnt == m_dispcols);
+       }
+               return;
+       // Check that all physical columns map to logical columns
+       for (i=0; i<m_dispcols; ++i)
+       {
+               ASSERT(m_invcolorder[i]>=0);
+       }
+       // Check that no columns beyond end have physical mappings
+       for ( /* existing i */; i<m_numcols; ++i)
+       {
+               ASSERT(m_invcolorder[i]==-1);
+       }
+#endif
+}
+
+/**
+ * @brief Set column ordering to default initial order
+ */
+void CDirView::ResetColumnOrdering()
+{
+       ClearColumnOrders();
+       m_dispcols = 0;
+       for (int i=0; i<m_numcols; ++i)
+       {
+               int phy = GetColDefaultOrder(i);
+               m_colorder[i] = phy;
+               if (phy>=0)
+               {
+                       m_invcolorder[phy] = i;
+                       ++m_dispcols;
+               }
+       }
+       ValidateColumnOrdering();
+}
+
+/**
+ * @brief Reset all current column ordering information
+ */
+void CDirView::ClearColumnOrders()
+{
+       m_colorder.SetSize(m_numcols);
+       m_invcolorder.SetSize(m_numcols);
+       for (int i=0; i<m_numcols; ++i)
+       {
+               m_colorder[i] = -1;
+               m_invcolorder[i] = -1;
+       }
+}
+
+/**
+ * @brief Return display name of column
+ */
+CString CDirView::GetColDisplayName(int col) const
+{
+       const DirColInfo & colinfo = g_cols[col];
+       CString s;
+       s.LoadString(colinfo.idName);
+       return s;
+}
+
+/**
+ * @brief Return total number of known columns
+ */
+int CDirView::GetColLogCount() const
+{
+       return g_ncols;
+}
+
+/**
+ * @brief Remove any windows reordering of columns (params are physical columns)
+ */
+void CDirView::MoveColumn(int psrc, int pdest)
+{
+       // actually moved column
+       m_colorder[m_invcolorder[psrc]] = pdest;
+       // shift all other affected columns
+       int dir = psrc > pdest ? +1 : -1;
+       for (int i=pdest; i!=psrc; i += dir)
+       {
+               m_colorder[m_invcolorder[i]] = i+dir;
+       }
+       // fix inverse mapping
+       for (i=0; i<m_numcols; ++i)
+       {
+               if (m_colorder[i] >= 0)
+                       m_invcolorder[m_colorder[i]] = i;
+       }
+       ValidateColumnOrdering();
+       InitiateSort();
+       ValidateColumnOrdering();
+}
+
+/**
+ * @brief User examines & edits which columns are displayed in dirview, and in which order
+ */
+void CDirView::OnEditColumns()
+{
+ToDoDeleteThisValidateColumnOrdering();
+       CDirColsDlg dlg;
+       // List all the currently displayed columns
+       for (int col=0; col<GetListCtrl().GetHeaderCtrl()->GetItemCount(); ++col)
+       {
+               int l = ColPhysToLog(col);
+               dlg.AddColumn(GetColDisplayName(l), l, col);
+       }
+       // Now add all the columns not currently displayed
+       for (int l=0; l<GetColLogCount(); ++l)
+       {
+               if (ColLogToPhys(l)==-1)
+               {
+                       dlg.AddColumn(GetColDisplayName(l), l);
+               }
+       }
+       if (dlg.DoModal() != IDOK)
+               return;
+
+       // Reset our data to reflect the new data from the dialog
+       const CDirColsDlg::ColumnArray & cols = dlg.GetColumns();
+       ClearColumnOrders();
+       m_dispcols = 0;
+       for (int i=0; i<cols.GetSize(); ++i)
+       {
+               int log = cols[i].log_col;
+               int phy = cols[i].phy_col;
+               m_colorder[log] = phy;
+               if (phy>=0)
+               {
+                       ++m_dispcols;
+                       m_invcolorder[phy] = log;
+               }
+       }
+       if (m_dispcols < 1)
+       {
+               // Ignore them if they didn't leave a column showing
+               ResetColumnOrdering();
+       }
+       else
+       {
+               ReloadColumns();
+               GetDocument()->Redisplay();
+       }
+       ValidateColumnOrdering();
+}
diff --git a/Src/DirViewColItems.cpp b/Src/DirViewColItems.cpp
new file mode 100644 (file)
index 0000000..0a5132b
--- /dev/null
@@ -0,0 +1,306 @@
+/** 
+ * @file  DirViewColItems.cpp
+ *
+ * @brief Code for individual columns in the DirView
+ *
+ * @date  Created: 2003-08-19
+ */
+// RCS ID line follows -- this is updated by CVS
+// $Id$
+
+
+#include "stdafx.h"
+#include "Merge.h"
+#include "DirView.h"
+#include "DirDoc.h"
+#include "MainFrm.h"
+#include "resource.h"
+//#include "coretools.h"
+//#include "dllver.h"
+#include "DirViewColItems.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/**
+ * @brief Return time displayed appropriately, as string
+ */
+static CString
+TimeString(const time_t * tim)
+{
+       if (!tim) return _T("---");
+       // _tcsftime does not respect user date customizations from
+       // Regional Options/Configuration Regional; COleDateTime::Format does so.
+       COleDateTime odt = *tim;
+       return odt.Format();
+}
+
+/**
+ * @{ Functions to display each type of column info
+ */
+static CString ColNameGet(const DIFFITEM & di)
+{
+       return di.sfilename;
+}
+static CString ColPathGet(const DIFFITEM & di)
+{
+       CString s = _T(".");
+       s += di.sSubdir;
+       return s;
+}
+static CString ColStatusGet(const DIFFITEM & di)
+{
+       CString s;
+       switch (di.code)
+       {
+       case FILE_DIFF:
+               VERIFY(s.LoadString(IDS_FILES_ARE_DIFFERENT));
+               break;
+       case FILE_BINDIFF:
+               VERIFY(s.LoadString(IDS_BIN_FILES_DIFF));
+               break;
+       case FILE_BINSAME:
+               VERIFY(s.LoadString(IDS_BIN_FILES_SAME));
+               break;
+       case FILE_LUNIQUE:
+       case FILE_LDIRUNIQUE:
+               AfxFormatString1(s, IDS_ONLY_IN_FMT, di.getLeftFilepath());
+               break;
+       case FILE_RUNIQUE:
+       case FILE_RDIRUNIQUE:
+               AfxFormatString1(s, IDS_ONLY_IN_FMT, di.getRightFilepath());
+               break;
+       case FILE_SAME:
+               VERIFY(s.LoadString(IDS_IDENTICAL));
+               break;
+       default: // error
+               VERIFY(s.LoadString(IDS_CANT_COMPARE_FILES));
+               break;
+       }
+       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)
+               return TimeString(&di.left.ctime);
+       else
+               return _T("");
+}
+static CString ColRctimeGet(const DIFFITEM & di)
+{
+       if (di.right.ctime)
+               return TimeString(&di.right.ctime);
+       else
+               return _T("");
+}
+static CString ColExtGet(const DIFFITEM & di)
+{
+       return di.sext;
+}
+static CString ColLsizeGet(const DIFFITEM & di)
+{
+       CString s;
+       s.Format(_T("%I64d"), di.left.size);
+       return s;
+}
+static CString ColRsizeGet(const DIFFITEM & di)
+{
+       CString s;
+       s.Format(_T("%I64d"), di.right.size);
+       return s;
+}
+static CString ColNewerGet(const DIFFITEM & di)
+{
+       if (di.left.mtime && di.right.mtime)
+       {
+               if (di.left.mtime > di.right.mtime)
+                       return _T("<<<");
+               if (di.left.mtime < di.right.mtime)
+                       return _T(">>>");
+               return _T("===");
+       }
+       else if (di.left.mtime)
+       {
+               return _T("<*<");
+       }
+       else if (di.right.mtime)
+       {
+               return _T(">*>");
+       }
+       else
+       {
+               return _T("***");
+       }
+}
+static CString ColLverGet(const DIFFITEM & di)
+{
+       return di.left.version;
+}
+static CString ColRverGet(const DIFFITEM & di)
+{
+       return di.right.version;
+}
+static CString ColStatusAbbrGet(const DIFFITEM & di)
+{
+       int id;
+       switch (di.code)
+       {
+       case FILE_DIFF: id = IDS_FILES_ARE_DIFFERENT; break;
+       case FILE_BINDIFF: id = IDS_BIN_FILES_DIFF; break;
+       case FILE_BINSAME: id = IDS_BIN_FILES_SAME; break;
+       case FILE_LUNIQUE:
+       case FILE_LDIRUNIQUE:
+               id = IDS_LEFTONLY; break;
+       case FILE_RUNIQUE:
+       case FILE_RDIRUNIQUE:
+               id = IDS_RIGHTONLY; break;
+       case FILE_SAME: id = IDS_IDENTICAL; break;
+       default: id = IDS_CANT_COMPARE_FILES;
+       }
+       CString s;
+       VERIFY(s.LoadString(id));
+       return s;
+}
+static CString ColLattrGet(const DIFFITEM & di)
+{
+       return di.left.flags.toString();
+}
+static CString ColRattrGet(const DIFFITEM & di)
+{
+       return di.right.flags.toString();
+}
+/**
+ * @}
+ */
+
+/**
+ * @{ Functions to sort each type of column info
+ */
+static int ColNameSort(const DIFFITEM & ldi, const DIFFITEM &rdi)
+{
+       return ldi.sfilename.CompareNoCase(rdi.sfilename);
+}
+static int ColPathSort(const DIFFITEM & ldi, const DIFFITEM &rdi)
+{
+       return ldi.sSubdir.CompareNoCase(rdi.sSubdir);
+}
+static int ColStatusSort(const DIFFITEM & ldi, const DIFFITEM &rdi)
+{
+       return rdi.code-ldi.code;
+}
+static int ColLmtimeSort(const DIFFITEM & ldi, const DIFFITEM &rdi)
+{
+       return rdi.left.mtime-ldi.left.mtime;
+}
+static int ColRmtimeSort(const DIFFITEM & ldi, const DIFFITEM &rdi)
+{
+       return rdi.right.mtime-ldi.right.mtime;
+}
+static int ColLctimeSort(const DIFFITEM & ldi, const DIFFITEM &rdi)
+{
+       return rdi.left.ctime-ldi.left.ctime;
+}
+static int ColRctimeSort(const DIFFITEM & ldi, const DIFFITEM &rdi)
+{
+       return rdi.right.ctime-ldi.right.ctime;
+}
+static int ColExtSort(const DIFFITEM & ldi, const DIFFITEM &rdi)
+{
+       return ldi.sext.CompareNoCase(rdi.sext);
+}
+static int ColLsizeSort(const DIFFITEM & ldi, const DIFFITEM &rdi)
+{
+       return rdi.left.size - ldi.left.size;
+}
+static int ColRsizeSort(const DIFFITEM & ldi, const DIFFITEM &rdi)
+{
+       return rdi.right.size - ldi.right.size;
+}
+static int ColNewerSort(const DIFFITEM & ldi, const DIFFITEM &rdi)
+{
+       return ColNewerGet(ldi).Compare(ColNewerGet(rdi));
+}
+static int ColLverSort(const DIFFITEM & ldi, const DIFFITEM &rdi)
+{
+       return ldi.left.version.Compare(rdi.left.version);
+}
+static int ColRverSort(const DIFFITEM & ldi, const DIFFITEM &rdi)
+{
+       return ldi.right.version.Compare(rdi.right.version);
+}
+static int ColLattrSort(const DIFFITEM & ldi, const DIFFITEM &rdi)
+{
+       return ldi.left.flags.toString().Compare(rdi.left.flags.toString());
+}
+static int ColRattrSort(const DIFFITEM & ldi, const DIFFITEM &rdi)
+{
+       return ldi.right.flags.toString().Compare(rdi.right.flags.toString());
+}
+/**
+ * @}
+ */
+
+/**
+ * @brief All existing columns
+ */
+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("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("Newer"), IDS_COLHDR_NEWER, -1, &ColNewerGet, &ColNewerSort, -1, true }
+       , { _T("Lversion"), IDS_COLHDR_LVERSION, -1, &ColLverGet, &ColLverSort, -1, true }
+       , { _T("Rversion"), IDS_COLHDR_RVERSION, -1, &ColRverGet, &ColRverSort, -1, true }
+       , { _T("StatusAbbr"), IDS_COLHDR_RESULT_ABBR, -1, &ColStatusAbbrGet, &ColStatusSort, -1, true }
+       , { _T("Lattr"), IDS_COLHDR_LATTRIBUTES, -1, &ColLattrGet, &ColLattrSort, -1, true }
+       , { _T("Rattr"), IDS_COLHDR_RATTRIBUTES, -1, &ColRattrGet, &ColRattrSort, -1, true }
+};
+
+/**
+ * @brief Count of all known columns
+ */
+int g_ncols = countof(g_cols);
+
+/**
+ * @brief Registry base value name for saving/loading info for this column
+ */
+CString CDirView::GetColRegValueNameBase(int col) const
+{
+       ASSERT(col>=0 && col<countof(g_cols));
+       CString regName;
+       regName.Format(_T("WDirHdr_%s"), g_cols[col].regName);
+       return regName;
+}
+
+/**
+ * @brief Get default physical order for specified logical column
+ */
+int CDirView::GetColDefaultOrder(int col) const
+{
+       ASSERT(col>=0 && col<countof(g_cols));
+       return g_cols[col].physicalIndex;
+}
diff --git a/Src/DirViewColItems.h b/Src/DirViewColItems.h
new file mode 100644 (file)
index 0000000..fc8f49d
--- /dev/null
@@ -0,0 +1,37 @@
+/** 
+ * @file  DirViewColItems.h
+ *
+ * @brief Declaration file for DirColInfo
+ *
+ * @date  Created: 2003-08-19
+ */
+// RCS ID line follows -- this is updated by CVS
+// $Id$
+
+#ifndef DirViewColItems_h
+#define DirViewColItems_h
+
+
+typedef CString (*ColGetFnc)(const DIFFITEM & di);
+typedef int (*ColSortFnc)(const DIFFITEM & ldi, const DIFFITEM &rdi);
+
+/**
+ * @brief Information about one column of dirview list info
+ */
+struct DirColInfo
+{
+       LPCTSTR regName;
+       // localized string resources
+       int idName;
+       int idDesc;
+       ColGetFnc getfnc; /**< Handler giving display string */
+       ColSortFnc sortfnc; /**< Handler for sorting this column */
+       int physicalIndex; /**< Current physical index, -1 if not displayed */
+       bool defSortUp; /**< Does column start with ascending sort (most do) */
+};
+
+extern DirColInfo g_cols[];
+extern int g_ncols;
+
+
+#endif // DirViewColItems_h