cleanup .gitignore
[TortoiseGit.git] / src / TortoiseProc / GitStatusListCtrlHelpers.cpp
blob8cf87b9186e5121b00fd31f9044a5cc3b38a9343
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008 - TortoiseSVN
4 // Copyright (C) 2008-2011 - TortoiseGit
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software Foundation,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 #include "stdafx.h"
22 #include ".\resource.h"
23 #include "GitStatusListCtrl.h"
24 #include <iterator>
26 // registry version number of column-settings of GitLogListBase
27 #define BLAME_COLUMN_VERSION 4
29 #ifndef assert
30 #define assert(x) ATLASSERT(x)
31 #endif
32 // assign property list
33 #if 0
34 PropertyList&
35 PropertyList::operator= (const char* rhs)
37 // do you really want to replace the property list?
39 assert (properties.empty());
40 properties.clear();
42 // add all properties in the list
44 while ((rhs != NULL) && (*rhs != 0))
46 const char* next = strchr (rhs, ' ');
48 CString name (rhs, static_cast<int>(next == NULL ? strlen (rhs) : next - rhs));
49 properties.insert (std::make_pair (name, CString()));
51 rhs = next == NULL ? NULL : next+1;
54 // done
56 return *this;
59 // collect property names in a set
61 void PropertyList::GetPropertyNames (std::set<CString>& names)
63 for ( CIT iter = properties.begin(), end = properties.end()
64 ; iter != end
65 ; ++iter)
67 names.insert (iter->first);
71 // get a property value.
73 CString PropertyList::operator[](const CString& name) const
75 CIT iter = properties.find (name);
77 return iter == properties.end()
78 ? CString()
79 : iter->second;
82 // set a property value.
84 CString& PropertyList::operator[](const CString& name)
86 return properties[name];
89 /// check whether that property has been set on this item.
91 bool PropertyList::HasProperty (const CString& name) const
93 return properties.find (name) != properties.end();
96 // due to frequent use: special check for svn:needs-lock
98 bool PropertyList::IsNeedsLockSet() const
100 static const CString svnNeedsLock = _T("svn:needs-lock");
101 return HasProperty (svnNeedsLock);
104 #endif
105 // registry access
107 void ColumnManager::ReadSettings
108 ( DWORD defaultColumns
109 , DWORD hideColumns
110 , const CString& containerName
111 , int maxsize
112 , int * widthlist)
114 // defaults
115 DWORD selectedStandardColumns = defaultColumns & ~hideColumns;
116 m_dwDefaultColumns = defaultColumns & ~hideColumns;
118 columns.resize (maxsize);
119 int power = 1;
120 for (size_t i = 0; i < maxsize; ++i)
122 columns[i].index = static_cast<int>(i);
123 if(widthlist==NULL)
124 columns[i].width = 0;
125 else
126 columns[i].width = widthlist[i];
127 columns[i].visible = true;
128 columns[i].relevant = !(hideColumns & power);
129 power *= 2;
132 // userProps.clear();
134 // where the settings are stored within the registry
136 registryPrefix = _T("Software\\TortoiseGit\\StatusColumns\\") + containerName;
138 // we accept settings of current version only
139 bool valid = (DWORD)CRegDWORD (registryPrefix + _T("Version"), 0xff) == BLAME_COLUMN_VERSION;
140 if (valid)
142 // read (possibly different) column selection
144 selectedStandardColumns = CRegDWORD (registryPrefix, selectedStandardColumns) & ~hideColumns;
146 // read user-prop lists
148 CString userPropList = CRegString (registryPrefix + _T("UserProps"));
149 CString shownUserProps = CRegString (registryPrefix + _T("ShownUserProps"));
151 ParseUserPropSettings (userPropList, shownUserProps);
153 // read column widths
155 CString colWidths = CRegString (registryPrefix + _T("_Width"));
157 ParseWidths (colWidths);
160 // process old-style visibility setting
162 SetStandardColumnVisibility (selectedStandardColumns);
164 // clear all previously set header columns
166 int c = ((CHeaderCtrl*)(control->GetDlgItem(0)))->GetItemCount()-1;
167 while (c>=0)
168 control->DeleteColumn(c--);
170 // create columns
172 for (int i = 0, count = GetColumnCount(); i < count; ++i)
173 control->InsertColumn (i, GetName(i), LVCFMT_LEFT, IsVisible(i)&&IsRelevant(i) ? -1 : GetVisibleWidth(i, false));
175 // restore column ordering
177 if (valid)
178 ParseColumnOrder (CRegString (registryPrefix + _T("_Order")));
179 else
180 ParseColumnOrder (CString());
182 ApplyColumnOrder();
184 // auto-size the columns so we can see them while fetching status
185 // (seems the same values will not take affect in InsertColumn)
187 for (int i = 0, count = GetColumnCount(); i < count; ++i)
188 if (IsVisible(i))
189 control->SetColumnWidth (i, GetVisibleWidth (i, true));
192 void ColumnManager::WriteSettings() const
194 CRegDWORD regVersion (registryPrefix + _T("Version"), 0, TRUE);
195 regVersion = BLAME_COLUMN_VERSION;
197 // write (possibly different) column selection
199 CRegDWORD regStandardColumns (registryPrefix, 0, TRUE);
200 regStandardColumns = GetSelectedStandardColumns();
202 // write user-prop lists
204 CRegString regUserProps (registryPrefix + _T("UserProps"), CString(), TRUE);
205 regUserProps = GetUserPropList();
207 CRegString regShownUserProps (registryPrefix + _T("ShownUserProps"), CString(), TRUE);
208 regShownUserProps = GetShownUserProps();
210 // write column widths
212 CRegString regWidths (registryPrefix + _T("_Width"), CString(), TRUE);
213 regWidths = GetWidthString();
215 // write column ordering
217 CRegString regColumnOrder (registryPrefix + _T("_Order"), CString(), TRUE);
218 regColumnOrder = GetColumnOrderString();
221 // read column definitions
223 int ColumnManager::GetColumnCount() const
225 return static_cast<int>(columns.size());
228 bool ColumnManager::IsVisible (int column) const
230 size_t index = static_cast<size_t>(column);
231 assert (columns.size() > index);
233 return columns[index].visible;
236 int ColumnManager::GetInvisibleCount() const
238 int invisibleCount = 0;
239 for (std::vector<ColumnInfo>::const_iterator it = columns.begin(); it != columns.end(); ++it)
241 if (!it->visible)
242 invisibleCount++;
244 return invisibleCount;
247 bool ColumnManager::IsRelevant (int column) const
249 size_t index = static_cast<size_t>(column);
250 assert (columns.size() > index);
252 return columns[index].relevant;
255 bool ColumnManager::IsUserProp (int column) const
257 size_t index = static_cast<size_t>(column);
258 assert (columns.size() > index);
260 return columns[index].index >= GITSLC_USERPROPCOLOFFSET;
263 int ColumnManager::SetNames(UINT* buffer, int size)
265 itemName.clear();
266 for(int i=0;i<size;i++)
267 itemName.push_back(*buffer++);
268 return 0;
271 CString ColumnManager::GetName (int column) const
273 // standard columns
274 size_t index = static_cast<size_t>(column);
275 if (index < itemName.size())
277 CString result;
278 result.LoadString (itemName[index]);
279 return result;
282 // user-prop columns
284 // if (index < columns.size())
285 // return userProps[columns[index].index - SVNSLC_USERPROPCOLOFFSET].name;
287 // default: empty
289 return CString();
292 int ColumnManager::GetWidth (int column, bool useDefaults) const
294 size_t index = static_cast<size_t>(column);
295 assert (columns.size() > index);
297 int width = columns[index].width;
298 if ((width == 0) && useDefaults)
299 width = LVSCW_AUTOSIZE_USEHEADER;
301 return width;
304 int ColumnManager::GetVisibleWidth (int column, bool useDefaults) const
306 return IsVisible (column)
307 ? GetWidth (column, useDefaults)
308 : 0;
311 // switch columns on and off
313 void ColumnManager::SetVisible
314 ( int column
315 , bool visible)
317 size_t index = static_cast<size_t>(column);
318 assert (index < columns.size());
320 if (columns[index].visible != visible)
322 columns[index].visible = visible;
323 columns[index].relevant |= visible;
324 if (!visible)
325 columns[index].width = 0;
327 control->SetColumnWidth (column, GetVisibleWidth (column, true));
328 ApplyColumnOrder();
330 control->Invalidate (FALSE);
334 // tracking column modifications
336 void ColumnManager::ColumnMoved (int column, int position)
338 // in front of what column has it been inserted?
340 int index = columns[column].index;
342 std::vector<int> gridColumnOrder = GetGridColumnOrder();
344 size_t visiblePosition = static_cast<size_t>(position);
345 size_t columnCount = gridColumnOrder.size();
347 for (; (visiblePosition < columnCount)
348 && !columns[gridColumnOrder[visiblePosition]].visible
349 ; ++visiblePosition )
353 int next = -1;
354 if (visiblePosition != columnCount)
356 next = gridColumnOrder[visiblePosition];
359 // move logical column index just in front of that "next" column
361 columnOrder.erase (std::find ( columnOrder.begin(), columnOrder.end(), index));
362 columnOrder.insert ( std::find ( columnOrder.begin(), columnOrder.end(), next), index);
364 // make sure, invisible columns are still put in front of all others
366 ApplyColumnOrder();
369 void ColumnManager::ColumnResized (int column)
371 size_t index = static_cast<size_t>(column);
372 assert (index < columns.size());
373 assert (columns[index].visible);
375 int width = control->GetColumnWidth (column);
376 columns[index].width = width;
378 int propertyIndex = columns[index].index;
379 if (propertyIndex >= GITSLC_USERPROPCOLOFFSET)
380 userProps[propertyIndex - GITSLC_USERPROPCOLOFFSET].width = width;
382 control->Invalidate (FALSE);
385 // call these to update the user-prop list
386 // (will also auto-insert /-remove new list columns)
387 #if 0
388 void ColumnManager::UpdateUserPropList
389 (const std::vector<FileEntry*>& files)
391 // collect all user-defined props
393 std::set<CString> aggregatedProps;
394 for (size_t i = 0, count = files.size(); i < count; ++i)
395 files[i]->present_props.GetPropertyNames (aggregatedProps);
397 aggregatedProps.erase (_T("svn:needs-lock"));
398 itemProps = aggregatedProps;
400 // add new ones to the internal list
402 std::set<CString> newProps = aggregatedProps;
403 for (size_t i = 0, count = userProps.size(); i < count; ++i)
404 newProps.erase (userProps[i].name);
406 while (newProps.size() + userProps.size()
407 > SVNSLC_MAXCOLUMNCOUNT - SVNSLC_USERPROPCOLOFFSET)
408 newProps.erase (--newProps.end());
410 typedef std::set<CString>::const_iterator CIT;
411 for ( CIT iter = newProps.begin(), end = newProps.end()
412 ; iter != end
413 ; ++iter)
415 int index = static_cast<int>(userProps.size())
416 + SVNSLC_USERPROPCOLOFFSET;
417 columnOrder.push_back (index);
419 UserProp userProp;
420 userProp.name = *iter;
421 userProp.width = 0;
423 userProps.push_back (userProp);
426 // remove unused columns from control.
427 // remove used ones from the set of aggregatedProps.
429 for (size_t i = columns.size(); i > 0; --i)
430 if ((columns[i-1].index >= SVNSLC_USERPROPCOLOFFSET)
431 && (aggregatedProps.erase (GetName ((int)i-1)) == 0))
433 // this user-prop has not been set on any item
435 if (!columns[i-1].visible)
437 control->DeleteColumn (static_cast<int>(i-1));
438 columns.erase (columns.begin() + i-1);
442 // aggregatedProps now contains new columns only.
443 // we can't use newProps here because some props may have been used
444 // earlier but were not in the recent list of used props.
445 // -> they are neither in columns[] nor in newProps.
447 for ( CIT iter = aggregatedProps.begin(), end = aggregatedProps.end()
448 ; iter != end
449 ; ++iter)
451 // get the logical column index / ID
453 int index = -1;
454 int width = 0;
455 for (size_t i = 0, count = userProps.size(); i < count; ++i)
456 if (userProps[i].name == *iter)
458 index = static_cast<int>(i) + SVNSLC_USERPROPCOLOFFSET;
459 width = userProps[i].width;
460 break;
463 assert (index != -1);
465 // find insertion position
467 std::vector<ColumnInfo>::iterator columnIter = columns.begin();
468 std::vector<ColumnInfo>::iterator end = columns.end();
469 for (; (columnIter != end) && columnIter->index < index; ++columnIter);
470 int pos = static_cast<int>(columnIter - columns.begin());
472 ColumnInfo column;
473 column.index = index;
474 column.width = width;
475 column.visible = false;
477 columns.insert (columnIter, column);
479 // update control
481 int result = control->InsertColumn (pos, *iter, LVCFMT_LEFT, GetVisibleWidth(pos, false));
482 assert (result != -1);
483 UNREFERENCED_PARAMETER(result);
486 // update column order
488 ApplyColumnOrder();
490 #endif
491 #if 0
492 void ColumnManager::UpdateRelevance
493 ( const std::vector<FileEntry*>& files
494 , const std::vector<size_t>& visibleFiles)
496 // collect all user-defined props that belong to shown files
498 std::set<CString> aggregatedProps;
499 for (size_t i = 0, count = visibleFiles.size(); i < count; ++i)
500 files[visibleFiles[i]]->present_props.GetPropertyNames (aggregatedProps);
502 aggregatedProps.erase (_T("svn:needs-lock"));
503 itemProps = aggregatedProps;
505 // invisible columns for unused props are not relevant
507 for (int i = 0, count = GetColumnCount(); i < count; ++i)
508 if (IsUserProp(i) && !IsVisible(i))
510 columns[i].relevant
511 = aggregatedProps.find (GetName(i)) != aggregatedProps.end();
515 #endif
516 // don't clutter the context menu with irrelevant prop info
518 bool ColumnManager::AnyUnusedProperties() const
520 return columns.size() < userProps.size() + itemName.size();
523 void ColumnManager::RemoveUnusedProps()
525 // determine what column indexes / IDs to keep.
526 // map them onto new IDs (we may delete some IDs in between)
528 std::map<int, int> validIndices;
529 int userPropID = GITSLC_USERPROPCOLOFFSET;
531 for (size_t i = 0, count = columns.size(); i < count; ++i)
533 int index = columns[i].index;
535 if (itemProps.find (GetName((int)i)) != itemProps.end()
536 || columns[i].visible
537 || index < GITSLC_USERPROPCOLOFFSET)
539 validIndices[index] = index < GITSLC_USERPROPCOLOFFSET
540 ? index
541 : userPropID++;
545 // remove everything else:
547 // remove from columns and control.
548 // also update index values in columns
550 for (size_t i = columns.size(); i > 0; --i)
552 std::map<int, int>::const_iterator iter
553 = validIndices.find (columns[i-1].index);
555 if (iter == validIndices.end())
557 control->DeleteColumn (static_cast<int>(i-1));
558 columns.erase (columns.begin() + i-1);
560 else
562 columns[i-1].index = iter->second;
566 // remove from user props
568 for (size_t i = userProps.size(); i > 0; --i)
570 int index = static_cast<int>(i)-1 + GITSLC_USERPROPCOLOFFSET;
571 if (validIndices.find (index) == validIndices.end())
572 userProps.erase (userProps.begin() + i-1);
575 // remove from and update column order
577 for (size_t i = columnOrder.size(); i > 0; --i)
579 std::map<int, int>::const_iterator iter
580 = validIndices.find (columnOrder[i-1]);
582 if (iter == validIndices.end())
583 columnOrder.erase (columnOrder.begin() + i-1);
584 else
585 columnOrder[i-1] = iter->second;
589 // bring everything back to its "natural" order
591 void ColumnManager::ResetColumns (DWORD defaultColumns)
593 // update internal data
595 std::sort (columnOrder.begin(), columnOrder.end());
597 for (size_t i = 0, count = columns.size(); i < count; ++i)
599 columns[i].width = 0;
600 columns[i].visible = (i < 32) && (((defaultColumns >> i) & 1) != 0);
603 for (size_t i = 0, count = userProps.size(); i < count; ++i)
604 userProps[i].width = 0;
606 // update UI
608 for (int i = 0, count = GetColumnCount(); i < count; ++i)
609 control->SetColumnWidth (i, GetVisibleWidth (i, true));
611 ApplyColumnOrder();
613 control->Invalidate (FALSE);
616 // initialization utilities
618 void ColumnManager::ParseUserPropSettings(const CString& userPropList, const CString& shownUserProps)
620 assert (userProps.empty());
622 static CString delimiters (_T(" "));
624 // parse list of visible user-props
626 std::set<CString> visibles;
628 int pos = 0;
629 CString name = shownUserProps.Tokenize (delimiters, pos);
630 while (!name.IsEmpty())
632 visibles.insert (name);
633 name = shownUserProps.Tokenize (delimiters, pos);
636 // create list of all user-props
638 pos = 0;
639 name = userPropList.Tokenize (delimiters, pos);
640 while (!name.IsEmpty())
642 bool visible = visibles.find (name) != visibles.end();
644 UserProp newEntry;
645 newEntry.name = name;
646 newEntry.width = 0;
648 userProps.push_back (newEntry);
650 // auto-create columns for visible user-props
651 // (others may be added later)
653 if (visible)
655 ColumnInfo newColumn;
656 newColumn.width = 0;
657 newColumn.visible = true;
658 newColumn.relevant = true;
659 newColumn.index = static_cast<int>(userProps.size())
660 + GITSLC_USERPROPCOLOFFSET - 1;
662 columns.push_back (newColumn);
665 name = userPropList.Tokenize (delimiters, pos);
669 void ColumnManager::ParseWidths (const CString& widths)
671 for (int i = 0, count = widths.GetLength() / 8; i < count; ++i)
673 long width = _tcstol (widths.Mid (i*8, 8), NULL, 16);
674 if (i < itemName.size())
676 // a standard column
678 columns[i].width = width;
680 else if (i >= GITSLC_USERPROPCOLOFFSET)
682 // a user-prop column
684 size_t index = static_cast<size_t>(i - GITSLC_USERPROPCOLOFFSET);
685 assert (index < userProps.size());
686 userProps[index].width = width;
688 for (size_t k = 0, count = columns.size(); k < count; ++k)
689 if (columns[k].index == i)
690 columns[k].width = width;
692 else
694 // there is no such column
696 assert (width == 0);
701 void ColumnManager::SetStandardColumnVisibility
702 (DWORD visibility)
704 for (size_t i = 0; i < itemName.size(); ++i)
706 columns[i].visible = (visibility & 1) > 0;
707 visibility /= 2;
711 void ColumnManager::ParseColumnOrder
712 (const CString& widths)
714 std::set<int> alreadyPlaced;
715 columnOrder.clear();
717 // place columns according to valid entries in orderString
719 int limit = static_cast<int>(GITSLC_USERPROPCOLOFFSET + userProps.size());
720 for (int i = 0, count = widths.GetLength() / 2; i < count; ++i)
722 int index = _tcstol (widths.Mid (i*2, 2), NULL, 16);
723 if ((index < itemName.size())
724 || ((index >= GITSLC_USERPROPCOLOFFSET) && (index < limit)))
726 alreadyPlaced.insert (index);
727 columnOrder.push_back (index);
731 // place the remaining colums behind it
733 for (int i = 0; i < itemName.size(); ++i)
734 if (alreadyPlaced.find (i) == alreadyPlaced.end())
735 columnOrder.push_back (i);
737 for (int i = GITSLC_USERPROPCOLOFFSET; i < limit; ++i)
738 if (alreadyPlaced.find (i) == alreadyPlaced.end())
739 columnOrder.push_back (i);
742 // map internal column order onto visible column order
743 // (all invisibles in front)
745 std::vector<int> ColumnManager::GetGridColumnOrder()
747 // extract order of used columns from order of all columns
749 std::vector<int> result;
750 result.reserve (GITSLC_MAXCOLUMNCOUNT+1);
752 size_t colCount = columns.size();
753 bool visible = false;
757 // put invisible cols in front
759 for (size_t i = 0, count = columnOrder.size(); i < count; ++i)
761 int index = columnOrder[i];
762 for (size_t k = 0; k < colCount; ++k)
764 const ColumnInfo& column = columns[k];
765 if ((column.index == index) && (column.visible == visible))
766 result.push_back (static_cast<int>(k));
770 visible = !visible;
772 while (visible);
774 return result;
777 void ColumnManager::ApplyColumnOrder()
779 // extract order of used columns from order of all columns
781 int order[GITSLC_MAXCOLUMNCOUNT+1];
782 SecureZeroMemory (order, sizeof (order));
784 std::vector<int> gridColumnOrder = GetGridColumnOrder();
785 std::copy (gridColumnOrder.begin(), gridColumnOrder.end(), stdext::checked_array_iterator<int*>(&order[0], sizeof(order)));
787 // we must have placed all columns or something is really fishy ..
789 assert (gridColumnOrder.size() == columns.size());
790 assert (GetColumnCount() == ((CHeaderCtrl*)(control->GetDlgItem(0)))->GetItemCount());
792 // o.k., apply our column ordering
794 control->SetColumnOrderArray (GetColumnCount(), order);
797 // utilities used when writing data to the registry
799 DWORD ColumnManager::GetSelectedStandardColumns() const
801 DWORD result = 0;
802 for (size_t i = itemName.size(); i > 0; --i)
803 result = result * 2 + (columns[i-1].visible ? 1 : 0);
805 return result;
808 CString ColumnManager::GetUserPropList() const
810 CString result;
812 for (size_t i = 0, count = userProps.size(); i < count; ++i)
813 result += userProps[i].name + _T(' ');
815 return result;
818 CString ColumnManager::GetShownUserProps() const
820 CString result;
822 for (size_t i = 0, count = columns.size(); i < count; ++i)
824 size_t index = static_cast<size_t>(columns[i].index);
825 if (columns[i].visible && (index >= GITSLC_USERPROPCOLOFFSET))
826 result += userProps[index - GITSLC_USERPROPCOLOFFSET].name
827 + _T(' ');
830 return result;
833 CString ColumnManager::GetWidthString() const
835 CString result;
837 // regular columns
839 TCHAR buf[10];
840 for (size_t i = 0; i < itemName.size(); ++i)
842 _stprintf_s (buf, 10, _T("%08X"), columns[i].width);
843 result += buf;
846 // range with no column IDs
848 result += CString ('0', 8 * (GITSLC_USERPROPCOLOFFSET - itemName.size()));
850 // user-prop columns
852 for (size_t i = 0, count = userProps.size(); i < count; ++i)
854 _stprintf_s (buf, 10, _T("%08X"), userProps[i].width);
855 result += buf;
858 return result;
861 CString ColumnManager::GetColumnOrderString() const
863 CString result;
865 TCHAR buf[3];
866 for (size_t i = 0, count = columnOrder.size(); i < count; ++i)
868 _stprintf_s (buf, 3, _T("%02X"), columnOrder[i]);
869 result += buf;
872 return result;
875 // sorter utility class, only used by GitStatusList!
877 CSorter::CSorter ( ColumnManager* columnManager
878 , int sortedColumn
879 , bool ascending)
880 : columnManager (columnManager)
881 , sortedColumn (sortedColumn)
882 , ascending (ascending)
886 bool CSorter::operator() (const CTGitPath* entry1 , const CTGitPath* entry2) const
888 #define SGN(x) ((x)==0?0:((x)>0?1:-1))
890 int result = 0;
891 switch (sortedColumn)
893 case 5: //Del Number
895 if (result == 0)
897 // result = entry1->lock_comment.CompareNoCase(entry2->lock_comment);
898 result = A2L(entry1->m_StatDel)-A2L(entry2->m_StatDel);
901 case 4: //Add Number
903 if (result == 0)
905 //result = entry1->lock_owner.CompareNoCase(entry2->lock_owner);
906 result = A2L(entry1->m_StatAdd)-A2L(entry2->m_StatAdd);
910 case 3: // Status
912 if (result == 0)
914 result = entry1->GetActionName(entry1->m_Action).CompareNoCase(entry2->GetActionName(entry2->m_Action));
917 case 2: //Ext file
919 if (result == 0)
921 result = entry1->GetFileExtension().CompareNoCase(entry2->GetFileExtension());
924 case 1: // File name
926 if (result == 0)
928 result = entry1->GetFileOrDirectoryName().CompareNoCase(entry2->GetFileOrDirectoryName());
931 case 0: // Full path column
933 if (result == 0)
935 result = CTGitPath::Compare(entry1->GetGitPathString(), entry2->GetGitPathString());
938 default:
939 if ((result == 0) && (sortedColumn > 0))
941 // N/A props are "less than" empty props
943 // const CString& propName = columnManager->GetName (sortedColumn);
945 // bool entry1HasProp = entry1->present_props.HasProperty (propName);
946 // bool entry2HasProp = entry2->present_props.HasProperty (propName);
948 // if (entry1HasProp)
949 // {
950 // result = entry2HasProp
951 // ? entry1->present_props[propName].Compare
952 // (entry2->present_props[propName])
953 // : 1;
954 // }
955 // else
956 // {
957 // result = entry2HasProp ? -1 : 0;
958 // }
960 } // switch (m_nSortedColumn)
961 if (!ascending)
962 result = -result;
964 return result < 0;