From c2523d8b4411efc1224fdff0dd19dddc0e434868 Mon Sep 17 00:00:00 2001 From: Perry Rapp Date: Sat, 23 Aug 2003 18:09:14 +0000 Subject: [PATCH] PATCH: [ 781529 ] Make column info array, and add new columns --- Src/DirColsDlg.cpp | 224 ++++++++++++++++++++++++++ Src/DirColsDlg.h | 85 ++++++++++ Src/DirViewColHandler.cpp | 401 ++++++++++++++++++++++++++++++++++++++++++++++ Src/DirViewColItems.cpp | 306 +++++++++++++++++++++++++++++++++++ Src/DirViewColItems.h | 37 +++++ 5 files changed, 1053 insertions(+) create mode 100644 Src/DirColsDlg.cpp create mode 100644 Src/DirColsDlg.h create mode 100644 Src/DirViewColHandler.cpp create mode 100644 Src/DirViewColItems.cpp create mode 100644 Src/DirViewColItems.h diff --git a/Src/DirColsDlg.cpp b/Src/DirColsDlg.cpp new file mode 100644 index 000000000..8ff1089ec --- /dev/null +++ b/Src/DirColsDlg.cpp @@ -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= 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(el1); + const column * col2 = reinterpret_cast(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; iGetCount(); ++i) + { + if (!list->GetSel(i)) + break; + } + // continue down, moving up all selected items + for (++i; iGetCount(); ++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; iGetCount(); ++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; iphy_col = i; + } + for (i=0; iphy_col = -1; + } + + CDialog::OnOK(); +} diff --git a/Src/DirColsDlg.h b/Src/DirColsDlg.h new file mode 100644 index 000000000..093425e92 --- /dev/null +++ b/Src/DirColsDlg.h @@ -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 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 index 000000000..f56e9f6ea --- /dev/null +++ b/Src/DirViewColHandler.cpp @@ -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(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(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=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) + 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\n", COleDateTime::GetCurrentTime().Format()); +for (int k=0; k=0); + ASSERT(m_numcols == GetColLogCount()); + // Check that any logical->physical mapping is reversible + for (int i=0; i= 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=0); + } + // Check that no columns beyond end have physical mappings + for ( /* existing i */; i=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 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= 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; colGetItemCount(); ++col) + { + int l = ColPhysToLog(col); + dlg.AddColumn(GetColDisplayName(l), l, col); + } + // Now add all the columns not currently displayed + for (int l=0; l=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 index 000000000..0a5132b18 --- /dev/null +++ b/Src/DirViewColItems.cpp @@ -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=0 && col