Ticket #9402: 0001-Support-sensitive-insensitive-and-natural-name-sort.3.patch

File 0001-Support-sensitive-insensitive-and-natural-name-sort.3.patch, 51.0 KB (added by Francois Ferrand, 6 years ago)
  • src/interface/LocalListView.cpp

    From 7376b6b6072fa90e618d53182c45ccbe8e5a4dcd Mon Sep 17 00:00:00 2001
    From: Francois Ferrand <thetypz@gmail.com>
    Date: Wed, 12 Mar 2014 19:17:29 +0100
    Subject: [PATCH] Support sensitive, insensitive and natural name sort.
    
    ---
     src/interface/LocalListView.cpp                  |  67 ++++++-----
     src/interface/LocalTreeView.cpp                  |  48 +++++---
     src/interface/LocalTreeView.h                    |   2 +
     src/interface/Options.cpp                        |  10 ++
     src/interface/Options.h                          |   1 +
     src/interface/RemoteListView.cpp                 |  81 +++++++------
     src/interface/RemoteTreeView.cpp                 |  48 +++++---
     src/interface/RemoteTreeView.h                   |   3 +
     src/interface/filelistctrl.cpp                   |  22 ++++
     src/interface/filelistctrl.h                     |  81 +++++++++++++
     src/interface/resources/settings.xrc             |  22 +++-
     src/interface/search.cpp                         |  89 +++++++-------
     src/interface/settings/optionspage_filelists.cpp |   2 +
     tests/Makefile.am                                |   3 +-
     tests/cmpnatural.cpp                             | 142 +++++++++++++++++++++++
     15 files changed, 479 insertions(+), 142 deletions(-)
     create mode 100644 tests/cmpnatural.cpp
    
    diff --git a/src/interface/LocalListView.cpp b/src/interface/LocalListView.cpp
    index 2f4796f..2472219 100644
    a b bool CLocalListView::IsItemValid(unsigned int item) const 
    799799class CLocalListViewSort : public CListViewSort
    800800{
    801801public:
    802     CLocalListViewSort(std::vector<CLocalFileData>& fileData, enum DirSortMode dirSortMode)
    803         : m_fileData(fileData), m_dirSortMode(dirSortMode)
     802    CLocalListViewSort(std::vector<CLocalFileData>& fileData, enum DirSortMode dirSortMode, enum NameSortMode nameSortMode)
     803        : m_fileData(fileData), m_dirSortMode(dirSortMode), m_nameSortMode(nameSortMode)
    804804    {
    805805    }
    806806
    public: 
    811811    #define CMP(f, data1, data2) \
    812812        {\
    813813            int res = f(data1, data2);\
    814             if (res == -1)\
     814            if (res < 0)\
    815815                return true;\
    816             else if (res == 1)\
     816            else if (res > 0)\
    817817                return false;\
    818818        }
    819819
    820820    #define CMP_LESS(f, data1, data2) \
    821821        {\
    822822            int res = f(data1, data2);\
    823             if (res == -1)\
     823            if (res < 0)\
    824824                return true;\
    825825            else\
    826826                return false;\
    public: 
    868868
    869869    inline int CmpName(const CLocalFileData &data1, const CLocalFileData &data2) const
    870870    {
    871 #ifdef __WXMSW__
    872         return data1.name.CmpNoCase(data2.name);
    873 #else
    874         return data1.name.Cmp(data2.name);
    875 #endif
     871        switch (m_nameSortMode)
     872        {
     873        case namesort_casesensitive:
     874            return CmpCase(data1.name, data2.name);
     875
     876        default:
     877        case namesort_caseinsensitive:
     878            return CmpNoCase(data1.name, data2.name);
     879
     880        case namesort_natural:
     881            return CmpNatural(data1.name, data2.name);
     882        }
    876883    }
    877884
    878885    inline int CmpSize(const CLocalFileData &data1, const CLocalFileData &data2) const
    public: 
    907914protected:
    908915    std::vector<CLocalFileData>& m_fileData;
    909916
    910     DirSortMode m_dirSortMode;
     917    const enum DirSortMode m_dirSortMode;
     918    const enum NameSortMode m_nameSortMode;
    911919};
    912920
    913921template<class T> class CReverseSort : public T
    914922{
    915923public:
    916     CReverseSort(std::vector<CLocalFileData>& fileData, enum CLocalListViewSort::DirSortMode dirSortMode, CLocalListView* pListView)
    917         : T(fileData, dirSortMode, pListView)
     924    CReverseSort(std::vector<CLocalFileData>& fileData, enum CLocalListViewSort::DirSortMode dirSortMode, enum CLocalListViewSort::NameSortMode nameSortMode, CLocalListView* pListView)
     925        : T(fileData, dirSortMode, nameSortMode, pListView)
    918926    {
    919927    }
    920928
    public: 
    927935class CLocalListViewSortName : public CLocalListViewSort
    928936{
    929937public:
    930     CLocalListViewSortName(std::vector<CLocalFileData>& fileData, enum DirSortMode dirSortMode, CLocalListView* pListView)
    931         : CLocalListViewSort(fileData, dirSortMode)
     938    CLocalListViewSortName(std::vector<CLocalFileData>& fileData, enum DirSortMode dirSortMode, enum NameSortMode nameSortMode, CLocalListView* pListView)
     939        : CLocalListViewSort(fileData, dirSortMode, nameSortMode)
    932940    {
    933941    }
    934942
    typedef CReverseSort<CLocalListViewSortName> CLocalListViewSortName_Reverse; 
    947955class CLocalListViewSortSize : public CLocalListViewSort
    948956{
    949957public:
    950     CLocalListViewSortSize(std::vector<CLocalFileData>& fileData, enum DirSortMode dirSortMode, CLocalListView* pListView)
    951         : CLocalListViewSort(fileData, dirSortMode)
     958    CLocalListViewSortSize(std::vector<CLocalFileData>& fileData, enum DirSortMode dirSortMode, enum NameSortMode nameSortMode, CLocalListView* pListView)
     959        : CLocalListViewSort(fileData, dirSortMode, nameSortMode)
    952960    {
    953961    }
    954962
    typedef CReverseSort<CLocalListViewSortSize> CLocalListViewSortSize_Reverse; 
    969977class CLocalListViewSortType : public CLocalListViewSort
    970978{
    971979public:
    972     CLocalListViewSortType(std::vector<CLocalFileData>& fileData, enum DirSortMode dirSortMode, CLocalListView* pListView)
    973         : CLocalListViewSort(fileData, dirSortMode)
     980    CLocalListViewSortType(std::vector<CLocalFileData>& fileData, enum DirSortMode dirSortMode, enum NameSortMode nameSortMode, CLocalListView* pListView)
     981        : CLocalListViewSort(fileData, dirSortMode, nameSortMode)
    974982    {
    975983        m_pListView = pListView;
    976984    }
    typedef CReverseSort<CLocalListViewSortType> CLocalListViewSortType_Reverse; 
    10001008class CLocalListViewSortTime : public CLocalListViewSort
    10011009{
    10021010public:
    1003     CLocalListViewSortTime(std::vector<CLocalFileData>& fileData, enum DirSortMode dirSortMode, CLocalListView* pListView)
    1004         : CLocalListViewSort(fileData, dirSortMode)
     1011    CLocalListViewSortTime(std::vector<CLocalFileData>& fileData, enum DirSortMode dirSortMode, enum NameSortMode nameSortMode, CLocalListView* pListView)
     1012        : CLocalListViewSort(fileData, dirSortMode, nameSortMode)
    10051013    {
    10061014    }
    10071015
    typedef CReverseSort<CLocalListViewSortTime> CLocalListViewSortTime_Reverse; 
    10221030CFileListCtrl<CLocalFileData>::CSortComparisonObject CLocalListView::GetSortComparisonObject()
    10231031{
    10241032    CLocalListViewSort::DirSortMode dirSortMode = GetDirSortMode();
     1033    CLocalListViewSort::NameSortMode nameSortMode = GetNameSortMode();
    10251034
    10261035    if (!m_sortDirection)
    10271036    {
    10281037        if (m_sortColumn == 1)
    1029             return CFileListCtrl<CLocalFileData>::CSortComparisonObject(new CLocalListViewSortSize(m_fileData, dirSortMode, this));
     1038            return CFileListCtrl<CLocalFileData>::CSortComparisonObject(new CLocalListViewSortSize(m_fileData, dirSortMode, nameSortMode, this));
    10301039        else if (m_sortColumn == 2)
    1031             return CFileListCtrl<CLocalFileData>::CSortComparisonObject(new CLocalListViewSortType(m_fileData, dirSortMode, this));
     1040            return CFileListCtrl<CLocalFileData>::CSortComparisonObject(new CLocalListViewSortType(m_fileData, dirSortMode, nameSortMode, this));
    10321041        else if (m_sortColumn == 3)
    1033             return CFileListCtrl<CLocalFileData>::CSortComparisonObject(new CLocalListViewSortTime(m_fileData, dirSortMode, this));
     1042            return CFileListCtrl<CLocalFileData>::CSortComparisonObject(new CLocalListViewSortTime(m_fileData, dirSortMode, nameSortMode, this));
    10341043        else
    1035             return CFileListCtrl<CLocalFileData>::CSortComparisonObject(new CLocalListViewSortName(m_fileData, dirSortMode, this));
     1044            return CFileListCtrl<CLocalFileData>::CSortComparisonObject(new CLocalListViewSortName(m_fileData, dirSortMode, nameSortMode, this));
    10361045    }
    10371046    else
    10381047    {
    10391048        if (m_sortColumn == 1)
    1040             return CFileListCtrl<CLocalFileData>::CSortComparisonObject(new CLocalListViewSortSize_Reverse(m_fileData, dirSortMode, this));
     1049            return CFileListCtrl<CLocalFileData>::CSortComparisonObject(new CLocalListViewSortSize_Reverse(m_fileData, dirSortMode, nameSortMode, this));
    10411050        else if (m_sortColumn == 2)
    1042             return CFileListCtrl<CLocalFileData>::CSortComparisonObject(new CLocalListViewSortType_Reverse(m_fileData, dirSortMode, this));
     1051            return CFileListCtrl<CLocalFileData>::CSortComparisonObject(new CLocalListViewSortType_Reverse(m_fileData, dirSortMode, nameSortMode, this));
    10431052        else if (m_sortColumn == 3)
    1044             return CFileListCtrl<CLocalFileData>::CSortComparisonObject(new CLocalListViewSortTime_Reverse(m_fileData, dirSortMode, this));
     1053            return CFileListCtrl<CLocalFileData>::CSortComparisonObject(new CLocalListViewSortTime_Reverse(m_fileData, dirSortMode, nameSortMode, this));
    10451054        else
    1046             return CFileListCtrl<CLocalFileData>::CSortComparisonObject(new CLocalListViewSortName_Reverse(m_fileData, dirSortMode, this));
     1055            return CFileListCtrl<CLocalFileData>::CSortComparisonObject(new CLocalListViewSortName_Reverse(m_fileData, dirSortMode, nameSortMode, this));
    10471056    }
    10481057}
    10491058
  • src/interface/LocalTreeView.cpp

    diff --git a/src/interface/LocalTreeView.cpp b/src/interface/LocalTreeView.cpp
    index 4f32eaf..3e4c5e9 100644
    a b  
    99#include "inputdialog.h"
    1010#include "local_filesys.h"
    1111#include "dragdropmanager.h"
     12#include "Options.h"
    1213
    1314#ifdef _DEBUG
    1415#define new DEBUG_NEW
    struct t_dir 
    701702    wxTreeItemId item;
    702703};
    703704
    704 static bool sortfunc(const wxString& a, const wxString& b)
    705 {
    706 #ifdef __WXMSW__
    707     return b.CmpNoCase(a) > 0;
    708 #else
    709     return b.Cmp(a) > 0;
    710 #endif
    711 }
    712 
    713705void CLocalTreeView::Refresh()
    714706{
    715707    wxLogNull nullLog;
    void CLocalTreeView::Refresh() 
    718710
    719711    std::list<t_dir> dirsToCheck;
    720712
     713    switch (COptions::Get()->GetOptionVal(OPTION_FILELIST_NAMESORT))
     714    {
     715    case 0:
     716    default:
     717        m_nameSortMode = CListViewSort::namesort_caseinsensitive;
     718        break;
     719    case 1:
     720        m_nameSortMode = CListViewSort::namesort_casesensitive;
     721        break;
     722    case 2:
     723        m_nameSortMode = CListViewSort::namesort_natural;
     724        break;
     725    }
     726
    721727#ifdef __WXMSW__
    722728    int prevErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
    723729
    void CLocalTreeView::Refresh() 
    775781        }
    776782
    777783        // Step 2: Enumerate subdirectories on disk and sort them
    778         std::list<wxString> dirs;
     784        wxArrayString dirs;
    779785
    780786        wxString file;
    781787        const wxLongLong size(-1);
    void CLocalTreeView::Refresh() 
    796802
    797803            dirs.push_back(file);
    798804        }
    799         dirs.sort(sortfunc);
     805        dirs.Sort(CListViewSort::GetCmpFunction(m_nameSortMode));
    800806
    801807        bool inserted = false;
    802808
    803809        // Step 3: Merge list of subdirectories with subtree.
    804810        wxTreeItemId child = GetLastChild(dir.item);
    805         std::list<wxString>::reverse_iterator iter = dirs.rbegin();
     811        wxArrayString::reverse_iterator iter = dirs.rbegin();
    806812        while (child || iter != dirs.rend())
    807813        {
    808814            int cmp;
    int CLocalTreeView::OnCompareItems(const wxTreeItemId& item1, const wxTreeItemId 
    911917{
    912918    wxString label1 = GetItemText(item1);
    913919    wxString label2 = GetItemText(item2);
    914 #ifdef __WXMSW__
    915     return label1.CmpNoCase(label2);
    916 #else
    917     return label1.Cmp(label2);
    918 #endif
     920
     921    switch (m_nameSortMode)
     922    {
     923    case CListViewSort::namesort_casesensitive:
     924        return CListViewSort::CmpCase(label1, label2);
     925
     926    default:
     927    case CListViewSort::namesort_caseinsensitive:
     928        return CListViewSort::CmpNoCase(label1, label2);
     929
     930    case CListViewSort::namesort_natural:
     931        return CListViewSort::CmpNatural(label1, label2);
     932    }
    919933}
    920934
    921935void CLocalTreeView::OnStateChange(CState* pState, enum t_statechange_notifications notification, const wxString& data, const void* data2)
  • src/interface/LocalTreeView.h

    diff --git a/src/interface/LocalTreeView.h b/src/interface/LocalTreeView.h
    index baace0b..4fdc52e 100644
    a b  
    44#include "systemimagelist.h"
    55#include "state.h"
    66#include "treectrlex.h"
     7#include "filelistctrl.h"
    78
    89class CQueueView;
    910
    protected: 
    8889
    8990    wxTreeItemId m_contextMenuItem;
    9091    wxTreeItemId m_dropHighlight;
     92    enum CListViewSort::NameSortMode m_nameSortMode;
    9193};
    9294
    9395#endif
  • src/interface/Options.cpp

    diff --git a/src/interface/Options.cpp b/src/interface/Options.cpp
    index a238bb1..3b691c4 100644
    a b struct t_Option 
    4646    const Flags flags; // internal items won't get written to settings file nor loaded from there
    4747};
    4848
     49#ifdef __WXMSW__
     50//case insensitive
     51#define DEFAULT_FILENAME_SORT   _T("0")
     52#else
     53//case sensitive
     54#define DEFAULT_FILENAME_SORT   _T("1")
     55#endif
     56
    4957static const t_Option options[OPTIONS_NUM] =
    5058{
    5159    // Note: A few options are versioned due to a changed
    static const t_Option options[OPTIONS_NUM] = 
    126134    { "File Pane Swap", number, _T("0"), normal },
    127135    { "Last local directory", string, _T(""), normal },
    128136    { "Filelist directory sort", number, _T("0"), normal },
     137    { "Filelist name sort", number, DEFAULT_FILENAME_SORT, normal },
    129138    { "Queue successful autoclear", number, _T("0"), normal },
    130139    { "Queue column widths", string, _T(""), normal },
    131140    { "Local filelist colwidths", string, _T(""), normal },
    int COptions::Validate(unsigned int nID, int value) 
    456465            value = 0;
    457466        break;
    458467    case OPTION_FILELIST_DIRSORT:
     468    case OPTION_FILELIST_NAMESORT:
    459469        if (value < 0 || value > 2)
    460470            value = 0;
    461471        break;
  • src/interface/Options.h

    diff --git a/src/interface/Options.h b/src/interface/Options.h
    index 12339f4..1a20528 100644
    a b enum interfaceOptions 
    3131    OPTION_FILEPANE_SWAP,
    3232    OPTION_LASTLOCALDIR,
    3333    OPTION_FILELIST_DIRSORT,
     34    OPTION_FILELIST_NAMESORT,
    3435    OPTION_QUEUE_SUCCESSFUL_AUTOCLEAR,
    3536    OPTION_QUEUE_COLUMN_WIDTHS,
    3637    OPTION_LOCALFILELIST_COLUMN_WIDTHS,
  • src/interface/RemoteListView.cpp

    diff --git a/src/interface/RemoteListView.cpp b/src/interface/RemoteListView.cpp
    index 8030dbf..73c7bbf 100644
    a b void CRemoteListView::SetDirectoryListing(const CSharedPointer<const CDirectoryL 
    901901class CRemoteListViewSort : public CListViewSort
    902902{
    903903public:
    904     CRemoteListViewSort(const CDirectoryListing* const pDirectoryListing, enum DirSortMode dirSortMode)
    905         : m_pDirectoryListing(pDirectoryListing), m_dirSortMode(dirSortMode)
     904    CRemoteListViewSort(const CDirectoryListing* const pDirectoryListing, enum DirSortMode dirSortMode, enum NameSortMode nameSortMode)
     905        : m_pDirectoryListing(pDirectoryListing), m_dirSortMode(dirSortMode), m_nameSortMode(nameSortMode)
    906906    {
    907907    }
    908908
    909909    #define CMP(f, data1, data2) \
    910910        {\
    911911            int res = f(data1, data2);\
    912             if (res == -1)\
     912            if (res < 0)\
    913913                return true;\
    914             else if (res == 1)\
     914            else if (res > 0)\
    915915                return false;\
    916916        }
    917917
    918918    #define CMP_LESS(f, data1, data2) \
    919919        {\
    920920            int res = f(data1, data2);\
    921             if (res == -1)\
     921            if (res < 0)\
    922922                return true;\
    923923            else\
    924924                return false;\
    public: 
    966966
    967967    inline int CmpName(const CDirentry &data1, const CDirentry &data2) const
    968968    {
    969 #ifdef __WXMSW__
    970         return data1.name.CmpNoCase(data2.name);
    971 #else
    972         return data1.name.Cmp(data2.name);
    973 #endif
     969        switch (m_nameSortMode)
     970        {
     971        case namesort_casesensitive:
     972            return CmpCase(data1.name, data2.name);
     973
     974        default:
     975        case namesort_caseinsensitive:
     976            return CmpNoCase(data1.name, data2.name);
     977
     978        case namesort_natural:
     979            return CmpNatural(data1.name, data2.name);
     980        }
    974981    }
    975982
    976983    inline int CmpSize(const CDirentry &data1, const CDirentry &data2) const
    protected: 
    10061013    const CDirectoryListing* const m_pDirectoryListing;
    10071014
    10081015    const enum DirSortMode m_dirSortMode;
     1016    const enum NameSortMode m_nameSortMode;
    10091017};
    10101018
    10111019template<class T> class CReverseSort : public T
    10121020{
    10131021public:
    1014     CReverseSort(const CDirectoryListing* const pDirectoryListing, std::vector<CGenericFileData>& fileData, enum CRemoteListViewSort::DirSortMode dirSortMode, CRemoteListView* const pRemoteListView)
    1015         : T(pDirectoryListing, fileData, dirSortMode, pRemoteListView)
     1022    CReverseSort(const CDirectoryListing* const pDirectoryListing, std::vector<CGenericFileData>& fileData, enum CRemoteListViewSort::DirSortMode dirSortMode, enum CRemoteListViewSort::NameSortMode nameSortMode, CRemoteListView* const pRemoteListView)
     1023        : T(pDirectoryListing, fileData, dirSortMode, nameSortMode, pRemoteListView)
    10161024    {
    10171025    }
    10181026
    public: 
    10251033class CRemoteListViewSortName : public CRemoteListViewSort
    10261034{
    10271035public:
    1028     CRemoteListViewSortName(const CDirectoryListing* const pDirectoryListing, std::vector<CGenericFileData>& fileData, enum DirSortMode dirSortMode, CRemoteListView* const pRemoteListView)
    1029         : CRemoteListViewSort(pDirectoryListing, dirSortMode)
     1036    CRemoteListViewSortName(const CDirectoryListing* const pDirectoryListing, std::vector<CGenericFileData>& fileData, enum DirSortMode dirSortMode, enum NameSortMode nameSortMode, CRemoteListView* const pRemoteListView)
     1037        : CRemoteListViewSort(pDirectoryListing, dirSortMode, nameSortMode)
    10301038    {
    10311039    }
    10321040
    typedef CReverseSort<CRemoteListViewSortName> CRemoteListViewSortName_Reverse; 
    10451053class CRemoteListViewSortSize : public CRemoteListViewSort
    10461054{
    10471055public:
    1048     CRemoteListViewSortSize(const CDirectoryListing* const pDirectoryListing, std::vector<CGenericFileData>& fileData, enum DirSortMode dirSortMode, CRemoteListView* const pRemoteListView)
    1049         : CRemoteListViewSort(pDirectoryListing, dirSortMode)
     1056    CRemoteListViewSortSize(const CDirectoryListing* const pDirectoryListing, std::vector<CGenericFileData>& fileData, enum DirSortMode dirSortMode, enum NameSortMode nameSortMode, CRemoteListView* const pRemoteListView)
     1057        : CRemoteListViewSort(pDirectoryListing, dirSortMode, nameSortMode)
    10501058    {
    10511059    }
    10521060
    typedef CReverseSort<CRemoteListViewSortSize> CRemoteListViewSortSize_Reverse; 
    10671075class CRemoteListViewSortType : public CRemoteListViewSort
    10681076{
    10691077public:
    1070     CRemoteListViewSortType(const CDirectoryListing* const pDirectoryListing, std::vector<CGenericFileData>& fileData, enum DirSortMode dirSortMode, CRemoteListView* const pRemoteListView)
    1071         : CRemoteListViewSort(pDirectoryListing, dirSortMode), m_pRemoteListView(pRemoteListView), m_fileData(fileData)
     1078    CRemoteListViewSortType(const CDirectoryListing* const pDirectoryListing, std::vector<CGenericFileData>& fileData, enum DirSortMode dirSortMode, enum NameSortMode nameSortMode, CRemoteListView* const pRemoteListView)
     1079        : CRemoteListViewSort(pDirectoryListing, dirSortMode, nameSortMode), m_pRemoteListView(pRemoteListView), m_fileData(fileData)
    10721080    {
    10731081    }
    10741082
    typedef CReverseSort<CRemoteListViewSortType> CRemoteListViewSortType_Reverse; 
    11001108class CRemoteListViewSortTime : public CRemoteListViewSort
    11011109{
    11021110public:
    1103     CRemoteListViewSortTime(const CDirectoryListing* const pDirectoryListing, std::vector<CGenericFileData>& fileData, enum DirSortMode dirSortMode, CRemoteListView* const pRemoteListView)
    1104         : CRemoteListViewSort(pDirectoryListing, dirSortMode)
     1111    CRemoteListViewSortTime(const CDirectoryListing* const pDirectoryListing, std::vector<CGenericFileData>& fileData, enum DirSortMode dirSortMode, enum NameSortMode nameSortMode, CRemoteListView* const pRemoteListView)
     1112        : CRemoteListViewSort(pDirectoryListing, dirSortMode, nameSortMode)
    11051113    {
    11061114    }
    11071115
    typedef CReverseSort<CRemoteListViewSortTime> CRemoteListViewSortTime_Reverse; 
    11221130class CRemoteListViewSortPermissions : public CRemoteListViewSort
    11231131{
    11241132public:
    1125     CRemoteListViewSortPermissions(const CDirectoryListing* const pDirectoryListing, std::vector<CGenericFileData>& fileData, enum DirSortMode dirSortMode, CRemoteListView* const pRemoteListView)
    1126         : CRemoteListViewSort(pDirectoryListing, dirSortMode)
     1133    CRemoteListViewSortPermissions(const CDirectoryListing* const pDirectoryListing, std::vector<CGenericFileData>& fileData, enum DirSortMode dirSortMode, enum NameSortMode nameSortMode, CRemoteListView* const pRemoteListView)
     1134        : CRemoteListViewSort(pDirectoryListing, dirSortMode, nameSortMode)
    11271135    {
    11281136    }
    11291137
    typedef CReverseSort<CRemoteListViewSortPermissions> CRemoteListViewSortPermissi 
    11441152class CRemoteListViewSortOwnerGroup : public CRemoteListViewSort
    11451153{
    11461154public:
    1147     CRemoteListViewSortOwnerGroup(const CDirectoryListing* const pDirectoryListing, std::vector<CGenericFileData>& fileData, enum DirSortMode dirSortMode, CRemoteListView* const pRemoteListView)
    1148         : CRemoteListViewSort(pDirectoryListing, dirSortMode)
     1155    CRemoteListViewSortOwnerGroup(const CDirectoryListing* const pDirectoryListing, std::vector<CGenericFileData>& fileData, enum DirSortMode dirSortMode, enum NameSortMode nameSortMode, CRemoteListView* const pRemoteListView)
     1156        : CRemoteListViewSort(pDirectoryListing, dirSortMode, nameSortMode)
    11491157    {
    11501158    }
    11511159
    wxString CRemoteListView::GetItemText(int item, unsigned int column) 
    29562964CFileListCtrl<CGenericFileData>::CSortComparisonObject CRemoteListView::GetSortComparisonObject()
    29572965{
    29582966    CRemoteListViewSort::DirSortMode dirSortMode = GetDirSortMode();
     2967    CRemoteListViewSort::NameSortMode nameSortMode = GetNameSortMode();
    29592968
    29602969    const CDirectoryListing* pDirectoryListing = m_pDirectoryListing.Value();
    29612970    if (!m_sortDirection)
    29622971    {
    29632972        if (m_sortColumn == 1)
    2964             return CFileListCtrl<CGenericFileData>::CSortComparisonObject(new CRemoteListViewSortSize(pDirectoryListing, m_fileData, dirSortMode, this));
     2973            return CFileListCtrl<CGenericFileData>::CSortComparisonObject(new CRemoteListViewSortSize(pDirectoryListing, m_fileData, dirSortMode, nameSortMode, this));
    29652974        else if (m_sortColumn == 2)
    2966             return CFileListCtrl<CGenericFileData>::CSortComparisonObject(new CRemoteListViewSortType(pDirectoryListing, m_fileData, dirSortMode, this));
     2975            return CFileListCtrl<CGenericFileData>::CSortComparisonObject(new CRemoteListViewSortType(pDirectoryListing, m_fileData, dirSortMode, nameSortMode, this));
    29672976        else if (m_sortColumn == 3)
    2968             return CFileListCtrl<CGenericFileData>::CSortComparisonObject(new CRemoteListViewSortTime(pDirectoryListing, m_fileData, dirSortMode, this));
     2977            return CFileListCtrl<CGenericFileData>::CSortComparisonObject(new CRemoteListViewSortTime(pDirectoryListing, m_fileData, dirSortMode, nameSortMode, this));
    29692978        else if (m_sortColumn == 4)
    2970             return CFileListCtrl<CGenericFileData>::CSortComparisonObject(new CRemoteListViewSortPermissions(pDirectoryListing, m_fileData, dirSortMode, this));
     2979            return CFileListCtrl<CGenericFileData>::CSortComparisonObject(new CRemoteListViewSortPermissions(pDirectoryListing, m_fileData, dirSortMode, nameSortMode, this));
    29712980        else if (m_sortColumn == 5)
    2972             return CFileListCtrl<CGenericFileData>::CSortComparisonObject(new CRemoteListViewSortOwnerGroup(pDirectoryListing, m_fileData, dirSortMode, this));
     2981            return CFileListCtrl<CGenericFileData>::CSortComparisonObject(new CRemoteListViewSortOwnerGroup(pDirectoryListing, m_fileData, dirSortMode, nameSortMode, this));
    29732982        else
    2974             return CFileListCtrl<CGenericFileData>::CSortComparisonObject(new CRemoteListViewSortName(pDirectoryListing, m_fileData, dirSortMode, this));
     2983            return CFileListCtrl<CGenericFileData>::CSortComparisonObject(new CRemoteListViewSortName(pDirectoryListing, m_fileData, dirSortMode, nameSortMode, this));
    29752984    }
    29762985    else
    29772986    {
    29782987        if (m_sortColumn == 1)
    2979             return CFileListCtrl<CGenericFileData>::CSortComparisonObject(new CRemoteListViewSortSize_Reverse(pDirectoryListing, m_fileData, dirSortMode, this));
     2988            return CFileListCtrl<CGenericFileData>::CSortComparisonObject(new CRemoteListViewSortSize_Reverse(pDirectoryListing, m_fileData, dirSortMode, nameSortMode, this));
    29802989        else if (m_sortColumn == 2)
    2981             return CFileListCtrl<CGenericFileData>::CSortComparisonObject(new CRemoteListViewSortType_Reverse(pDirectoryListing, m_fileData, dirSortMode, this));
     2990            return CFileListCtrl<CGenericFileData>::CSortComparisonObject(new CRemoteListViewSortType_Reverse(pDirectoryListing, m_fileData, dirSortMode, nameSortMode, this));
    29822991        else if (m_sortColumn == 3)
    2983             return CFileListCtrl<CGenericFileData>::CSortComparisonObject(new CRemoteListViewSortTime_Reverse(pDirectoryListing, m_fileData, dirSortMode, this));
     2992            return CFileListCtrl<CGenericFileData>::CSortComparisonObject(new CRemoteListViewSortTime_Reverse(pDirectoryListing, m_fileData, dirSortMode, nameSortMode, this));
    29842993        else if (m_sortColumn == 4)
    2985             return CFileListCtrl<CGenericFileData>::CSortComparisonObject(new CRemoteListViewSortPermissions_Reverse(pDirectoryListing, m_fileData, dirSortMode, this));
     2994            return CFileListCtrl<CGenericFileData>::CSortComparisonObject(new CRemoteListViewSortPermissions_Reverse(pDirectoryListing, m_fileData, dirSortMode, nameSortMode, this));
    29862995        else if (m_sortColumn == 5)
    2987             return CFileListCtrl<CGenericFileData>::CSortComparisonObject(new CRemoteListViewSortOwnerGroup_Reverse(pDirectoryListing, m_fileData, dirSortMode, this));
     2996            return CFileListCtrl<CGenericFileData>::CSortComparisonObject(new CRemoteListViewSortOwnerGroup_Reverse(pDirectoryListing, m_fileData, dirSortMode, nameSortMode, this));
    29882997        else
    2989             return CFileListCtrl<CGenericFileData>::CSortComparisonObject(new CRemoteListViewSortName_Reverse(pDirectoryListing, m_fileData, dirSortMode, this));
     2998            return CFileListCtrl<CGenericFileData>::CSortComparisonObject(new CRemoteListViewSortName_Reverse(pDirectoryListing, m_fileData, dirSortMode, nameSortMode, this));
    29902999    }
    29913000}
    29923001
  • src/interface/RemoteTreeView.cpp

    diff --git a/src/interface/RemoteTreeView.cpp b/src/interface/RemoteTreeView.cpp
    index 6958757..ad49e29 100644
    a b  
    1111#include "queue.h"
    1212#include "QueueView.h"
    1313#include "themeprovider.h"
     14#include "Options.h"
    1415
    1516#ifdef _DEBUG
    1617#define new DEBUG_NEW
    void CRemoteTreeView::SetDirectoryListing(const CSharedPointer<const CDirectoryL 
    281282{
    282283    m_busy = true;
    283284
     285    switch (COptions::Get()->GetOptionVal(OPTION_FILELIST_NAMESORT))
     286    {
     287    case 0:
     288    default:
     289        m_nameSortMode = CListViewSort::namesort_caseinsensitive;
     290        break;
     291    case 1:
     292        m_nameSortMode = CListViewSort::namesort_casesensitive;
     293        break;
     294    case 2:
     295        m_nameSortMode = CListViewSort::namesort_natural;
     296        break;
     297    }
     298
    284299    if (!pListing)
    285300    {
    286301        m_ExpandAfterList = wxTreeItemId();
    void CRemoteTreeView::DisplayItem(wxTreeItemId parent, const CDirectoryListing& 
    555570    SortChildren(parent);
    556571}
    557572
    558 static bool sortfunc(const wxString& a, const wxString& b)
    559 {
    560     int cmp = a.CmpNoCase(b);
    561 
    562     if (!cmp)
    563         cmp = a.Cmp(b);
    564 
    565     return cmp < 0;
    566 }
    567 
    568 
    569573void CRemoteTreeView::RefreshItem(wxTreeItemId parent, const CDirectoryListing& listing, bool will_select_parent)
    570574{
    571575    SetItemImages(parent, false);
    void CRemoteTreeView::RefreshItem(wxTreeItemId parent, const CDirectoryListing& 
    582586
    583587    const wxString path = listing.path.GetPath();
    584588
    585     std::list<wxString> dirs;
     589    wxArrayString dirs;
    586590    for (unsigned int i = 0; i < listing.GetCount(); i++)
    587591    {
    588592        if (!listing[i].is_dir())
    void CRemoteTreeView::RefreshItem(wxTreeItemId parent, const CDirectoryListing& 
    592596            dirs.push_back(listing[i].name);
    593597    }
    594598
    595     dirs.sort(sortfunc);
     599    dirs.Sort(CListViewSort::GetCmpFunction(m_nameSortMode));
    596600
    597601    bool inserted = false;
    598602    child = GetLastChild(parent);
    599     std::list<wxString>::reverse_iterator iter = dirs.rbegin();
     603    wxArrayString::reverse_iterator iter = dirs.rbegin();
    600604    while (child && iter != dirs.rend())
    601605    {
    602606        int cmp = GetItemText(child).CmpNoCase(*iter);
    int CRemoteTreeView::OnCompareItems(const wxTreeItemId& item1, const wxTreeItemI 
    702706    wxString label1 = GetItemText(item1);
    703707    wxString label2 = GetItemText(item2);
    704708
    705     int cmp = label1.CmpNoCase(label2);
    706     if (cmp)
    707         return cmp;
    708     return label1.Cmp(label2);
     709    switch (m_nameSortMode)
     710    {
     711    case CListViewSort::namesort_casesensitive:
     712        return CListViewSort::CmpCase(label1, label2);
     713
     714    default:
     715    case CListViewSort::namesort_caseinsensitive:
     716        return CListViewSort::CmpNoCase(label1, label2);
     717
     718    case CListViewSort::namesort_natural:
     719        return CListViewSort::CmpNatural(label1, label2);
     720    }
    709721}
    710722
    711723void CRemoteTreeView::OnItemExpanding(wxTreeEvent& event)
  • src/interface/RemoteTreeView.h

    diff --git a/src/interface/RemoteTreeView.h b/src/interface/RemoteTreeView.h
    index 90c8f7c..7800359 100644
    a b  
    55#include "state.h"
    66#include "filter.h"
    77#include "treectrlex.h"
     8#include "filelistctrl.h"
    89
    910class CQueueView;
    1011class CRemoteTreeView : public wxTreeCtrlEx, CSystemImageList, CStateEventHandler
    protected: 
    7172    void OnMenuGeturl(wxCommandEvent& event);
    7273
    7374    wxTreeItemId m_contextMenuItem;
     75    enum CListViewSort::NameSortMode m_nameSortMode;
     76
    7477};
    7578
    7679#endif
  • src/interface/filelistctrl.cpp

    diff --git a/src/interface/filelistctrl.cpp b/src/interface/filelistctrl.cpp
    index 43d3505..93dcb1d 100644
    a b template<class CFileData> CListViewSort::DirSortMode CFileListCtrl<CFileData>::G 
    433433    return dirSortMode;
    434434}
    435435
     436template<class CFileData> CListViewSort::NameSortMode CFileListCtrl<CFileData>::GetNameSortMode()
     437{
     438    const int nameSortOption = COptions::Get()->GetOptionVal(OPTION_FILELIST_NAMESORT);
     439
     440    enum CListViewSort::NameSortMode nameSortMode;
     441    switch (nameSortOption)
     442    {
     443    case 0:
     444    default:
     445        nameSortMode = CListViewSort::namesort_caseinsensitive;
     446        break;
     447    case 1:
     448        nameSortMode = CListViewSort::namesort_casesensitive;
     449        break;
     450    case 2:
     451        nameSortMode = CListViewSort::namesort_natural;
     452        break;
     453    }
     454
     455    return nameSortMode;
     456}
     457
    436458template<class CFileData> void CFileListCtrl<CFileData>::OnColumnClicked(wxListEvent &event)
    437459{
    438460    int col = m_pVisibleColumnMapping[event.GetColumn()];
  • src/interface/filelistctrl.h

    diff --git a/src/interface/filelistctrl.h b/src/interface/filelistctrl.h
    index bba2279..0ea82ff 100644
    a b public: 
    3333        dirsort_onbottom,
    3434        dirsort_inline
    3535    };
     36    enum NameSortMode
     37    {
     38        namesort_caseinsensitive,
     39        namesort_casesensitive,
     40        namesort_natural
     41    };
    3642
    3743    virtual bool operator()(int a, int b) const = 0;
    3844    virtual ~CListViewSort() {} // Without this empty destructor GCC complains
     45
     46    static int CmpCase(const wxString& str1, const wxString& str2)
     47    {
     48        return str1.Cmp(str2);
     49    }
     50
     51    static int CmpNoCase(const wxString& str1, const wxString& str2)
     52    {
     53        int cmp = str1.CmpNoCase(str2);
     54        if (cmp)
     55            return cmp;
     56        return str1.Cmp(str2);
     57    }
     58
     59    static int CmpNatural(const wxString& str1, const wxString& str2)
     60    {
     61        wxString::const_iterator p1 = str1.begin();
     62        wxString::const_iterator p2 = str2.begin();
     63
     64        int res = 0;
     65        int zeroCount = 0;
     66        bool isNumber = false;
     67        for (; p1 != str1.end() && p2 != str2.end(); ++p1, ++p2) {
     68            int diff = (int)wxTolower(*p1) - (int)wxTolower(*p2);
     69            if (isNumber) {
     70                if (res == 0)
     71                    res = diff;
     72                int nbDigits = (wxIsdigit(*p1) ? 1 : 0) + (wxIsdigit(*p2) ? 1 : 0);
     73                if (nbDigits == 0 && res == 0) {
     74                    if (zeroCount)
     75                        break;
     76                    isNumber = false;
     77                } else if (nbDigits != 2)
     78                    break;
     79            } else if (wxIsdigit(*p1) && wxIsdigit(*p2)) {
     80                zeroCount = 0;
     81                for(; *p1 == '0' && p1+1 != str1.end() && wxIsdigit(*(p1+1)); ++p1)
     82                    zeroCount++;
     83                for(; *p2 == '0' && p2+1 != str2.end() && wxIsdigit(*(p2+1)); ++p2)
     84                    zeroCount--;
     85                res = *p1 - *p2;
     86                isNumber = true;
     87            } else if (diff)
     88                return diff;
     89        }
     90
     91        if (res == 0 && isNumber)
     92            res = zeroCount;
     93
     94        if (p1 == str1.end() && p2 == str2.end())
     95            return res;
     96        if (!isNumber || res == 0)
     97             return p1 == str1.end() ? -1 : 1;
     98        if (p1 != str1.end() && wxIsdigit(*p1))
     99            return 1;       //more digits
     100        if (p2 != str2.end() && wxIsdigit(*p2))
     101            return -1;      //fewer digits
     102        return res;         //same length, compare first different digit in the sequence
     103    }
     104
     105    typedef int (* CompareFunction)(const wxString&, const wxString&);
     106    static CompareFunction GetCmpFunction(NameSortMode mode)
     107    {
     108        switch (mode)
     109        {
     110        default:
     111        case CListViewSort::namesort_caseinsensitive:
     112            return &CListViewSort::CmpNoCase;
     113        case CListViewSort::namesort_casesensitive:
     114            return &CListViewSort::CmpCase;
     115        case CListViewSort::namesort_natural:
     116            return &CListViewSort::CmpNatural;
     117        }
     118    }
    39119};
    40120
    41121namespace genericTypes {
    protected: 
    100180    void InitSort(int optionID); // Has to be called after initializing columns
    101181    void SortList(int column = -1, int direction = -1, bool updateSelections = true);
    102182    enum CListViewSort::DirSortMode GetDirSortMode();
     183    enum CListViewSort::NameSortMode GetNameSortMode();
    103184    virtual CSortComparisonObject GetSortComparisonObject() = 0;
    104185
    105186    // An empty path denotes a virtual file
  • src/interface/resources/settings.xrc

    diff --git a/src/interface/resources/settings.xrc b/src/interface/resources/settings.xrc
    index 5645d71..a3f6d87 100644
    a b  
    16871687                </object>
    16881688                <flag>wxALIGN_CENTRE_VERTICAL</flag>
    16891689              </object>
     1690                <object class="sizeritem">
     1691                  <object class="wxStaticText">
     1692                    <label>_Name sorting mode:</label>
     1693                  </object>
     1694                  <flag>wxALIGN_CENTRE_VERTICAL</flag>
     1695                </object>
     1696                  <object class="sizeritem">
     1697                    <object class="wxChoice" name="ID_NAMESORTMODE">
     1698                      <selection>0</selection>
     1699                      <content>
     1700                        <item platform="win">Case insensitive (default)</item>
     1701                        <item platform="mac|unix">Case insensitive</item>
     1702                        <item platform="win">Case sensitive</item>
     1703                        <item platform="mac|unix">Case sensitive (default)</item>
     1704                        <item>Natural sort</item>
     1705                      </content>
     1706                    </object>
     1707                    <flag>wxALIGN_CENTRE_VERTICAL</flag>
     1708                </object>
     1709              <vgap>5</vgap>
    16901710              <hgap>5</hgap>
    16911711            </object>
    16921712            <flag>wxBOTTOM|wxLEFT|wxRIGHT</flag>
     
    22152235      </object>
    22162236    </object>
    22172237  </object>
    2218 </resource>
    2219  No newline at end of file
     2238</resource>
  • src/interface/search.cpp

    diff --git a/src/interface/search.cpp b/src/interface/search.cpp
    index 93e2040..7c6bd13 100644
    a b class CSearchDialogFileList; 
    6363class CSearchSort : public CListViewSort
    6464{
    6565public:
    66     CSearchSort(CSearchDialogFileList* pListCtrl, std::vector<CSearchFileData> &fileData, enum DirSortMode dirSortMode)
    67         : m_fileData(fileData), m_dirSortMode(dirSortMode), m_pListCtrl(pListCtrl)
     66    CSearchSort(CSearchDialogFileList* pListCtrl, std::vector<CSearchFileData> &fileData, enum DirSortMode dirSortMode, enum NameSortMode nameSortMode)
     67        : m_fileData(fileData), m_dirSortMode(dirSortMode), m_nameSortMode(nameSortMode), m_pListCtrl(pListCtrl)
    6868    {
    6969    }
    7070
    7171    #define CMP(f, data1, data2) \
    7272        {\
    7373            int res = f(data1, data2);\
    74             if (res == -1)\
     74            if (res < 0)\
    7575                return true;\
    76             else if (res == 1)\
     76            else if (res > 0)\
    7777                return false;\
    7878        }
    7979
    8080    #define CMP_LESS(f, data1, data2) \
    8181        {\
    8282            int res = f(data1, data2);\
    83             if (res == -1)\
     83            if (res < 0)\
    8484                return true;\
    8585            else\
    8686                return false;\
    public: 
    128128
    129129    inline int CmpName(const CDirentry &data1, const CDirentry &data2) const
    130130    {
    131 #ifdef __WXMSW__
    132         return data1.name.CmpNoCase(data2.name);
    133 #else
    134         return data1.name.Cmp(data2.name);
    135 #endif
     131        switch (m_nameSortMode)
     132        {
     133        case namesort_casesensitive:
     134            return CmpCase(data1.name, data2.name);
     135
     136        default:
     137        case namesort_caseinsensitive:
     138            return CmpNoCase(data1.name, data2.name);
     139
     140        case namesort_natural:
     141            return CmpNatural(data1.name, data2.name);
     142        }
    136143    }
    137144
    138145    inline int CmpSize(const CDirentry &data1, const CDirentry &data2) const
    protected: 
    168175    std::vector<CSearchFileData> &m_fileData;
    169176
    170177    const enum DirSortMode m_dirSortMode;
     178    const enum NameSortMode m_nameSortMode;
    171179
    172180    CSearchDialogFileList* m_pListCtrl;
    173181};
    protected: 
    175183template<class T> class CReverseSort : public T
    176184{
    177185public:
    178     CReverseSort(CSearchDialogFileList* pListCtrl, std::vector<CSearchFileData>& fileData, enum CSearchSort::DirSortMode dirSortMode)
    179         : T(pListCtrl, fileData, dirSortMode)
     186    CReverseSort(CSearchDialogFileList* pListCtrl, std::vector<CSearchFileData>& fileData, enum CSearchSort::DirSortMode dirSortMode, enum CSearchSort::NameSortMode nameSortMode)
     187        : T(pListCtrl, fileData, dirSortMode, nameSortMode)
    180188    {
    181189    }
    182190
    public: 
    189197class CSearchSortName : public CSearchSort
    190198{
    191199public:
    192     CSearchSortName(CSearchDialogFileList* pListCtrl, std::vector<CSearchFileData>& fileData, enum CSearchSort::DirSortMode dirSortMode)
    193         : CSearchSort(pListCtrl, fileData, dirSortMode)
     200    CSearchSortName(CSearchDialogFileList* pListCtrl, std::vector<CSearchFileData>& fileData, enum CSearchSort::DirSortMode dirSortMode, enum NameSortMode nameSortMode)
     201        : CSearchSort(pListCtrl, fileData, dirSortMode, nameSortMode)
    194202    {
    195203    }
    196204
    typedef CReverseSort<CSearchSortName> CSearchSortName_Reverse; 
    209217class CSearchSortPath : public CSearchSort
    210218{
    211219public:
    212     CSearchSortPath(CSearchDialogFileList* pListCtrl, std::vector<CSearchFileData>& fileData, enum CSearchSort::DirSortMode dirSortMode)
    213         : CSearchSort(pListCtrl, fileData, dirSortMode)
     220    CSearchSortPath(CSearchDialogFileList* pListCtrl, std::vector<CSearchFileData>& fileData, enum CSearchSort::DirSortMode dirSortMode, enum NameSortMode nameSortMode)
     221        : CSearchSort(pListCtrl, fileData, dirSortMode, nameSortMode)
    214222    {
    215223    }
    216224
    typedef CReverseSort<CSearchSortPath> CSearchSortPath_Reverse; 
    232240class CSearchSortSize : public CSearchSort
    233241{
    234242public:
    235     CSearchSortSize(CSearchDialogFileList* pListCtrl, std::vector<CSearchFileData>& fileData, enum CSearchSort::DirSortMode dirSortMode)
    236         : CSearchSort(pListCtrl, fileData, dirSortMode)
     243    CSearchSortSize(CSearchDialogFileList* pListCtrl, std::vector<CSearchFileData>& fileData, enum CSearchSort::DirSortMode dirSortMode, enum NameSortMode nameSortMode)
     244        : CSearchSort(pListCtrl, fileData, dirSortMode, nameSortMode)
    237245    {
    238246    }
    239247
    typedef CReverseSort<CSearchSortSize> CSearchSortSize_Reverse; 
    254262class CSearchSortType : public CSearchSort
    255263{
    256264public:
    257     CSearchSortType(CSearchDialogFileList* pListCtrl, std::vector<CSearchFileData>& fileData, enum CSearchSort::DirSortMode dirSortMode)
    258         : CSearchSort(pListCtrl, fileData, dirSortMode)
     265    CSearchSortType(CSearchDialogFileList* pListCtrl, std::vector<CSearchFileData>& fileData, enum CSearchSort::DirSortMode dirSortMode, enum NameSortMode nameSortMode)
     266        : CSearchSort(pListCtrl, fileData, dirSortMode, nameSortMode)
    259267    {
    260268    }
    261269
    typedef CReverseSort<CSearchSortType> CSearchSortType_Reverse; 
    281289class CSearchSortTime : public CSearchSort
    282290{
    283291public:
    284     CSearchSortTime(CSearchDialogFileList* pListCtrl, std::vector<CSearchFileData>& fileData, enum CSearchSort::DirSortMode dirSortMode)
    285         : CSearchSort(pListCtrl, fileData, dirSortMode)
     292    CSearchSortTime(CSearchDialogFileList* pListCtrl, std::vector<CSearchFileData>& fileData, enum CSearchSort::DirSortMode dirSortMode, enum NameSortMode nameSortMode)
     293        : CSearchSort(pListCtrl, fileData, dirSortMode, nameSortMode)
    286294    {
    287295    }
    288296
    typedef CReverseSort<CSearchSortTime> CSearchSortTime_Reverse; 
    303311class CSearchSortPermissions : public CSearchSort
    304312{
    305313public:
    306     CSearchSortPermissions(CSearchDialogFileList* pListCtrl, std::vector<CSearchFileData>& fileData, enum CSearchSort::DirSortMode dirSortMode)
    307         : CSearchSort(pListCtrl, fileData, dirSortMode)
     314    CSearchSortPermissions(CSearchDialogFileList* pListCtrl, std::vector<CSearchFileData>& fileData, enum CSearchSort::DirSortMode dirSortMode, enum NameSortMode nameSortMode)
     315        : CSearchSort(pListCtrl, fileData, dirSortMode, nameSortMode)
    308316    {
    309317    }
    310318
    typedef CReverseSort<CSearchSortPermissions> CSearchSortPermissions_Reverse; 
    325333class CSearchSortOwnerGroup : public CSearchSort
    326334{
    327335public:
    328     CSearchSortOwnerGroup(CSearchDialogFileList* pListCtrl, std::vector<CSearchFileData>& fileData, enum CSearchSort::DirSortMode dirSortMode)
    329         : CSearchSort(pListCtrl, fileData, dirSortMode)
     336    CSearchSortOwnerGroup(CSearchDialogFileList* pListCtrl, std::vector<CSearchFileData>& fileData, enum CSearchSort::DirSortMode dirSortMode, enum NameSortMode nameSortMode)
     337        : CSearchSort(pListCtrl, fileData, dirSortMode, nameSortMode)
    330338    {
    331339    }
    332340
    wxLongLong CSearchDialogFileList::ItemGetSize(int index) const 
    389397CFileListCtrl<CSearchFileData>::CSortComparisonObject CSearchDialogFileList::GetSortComparisonObject()
    390398{
    391399    CSearchSort::DirSortMode dirSortMode = GetDirSortMode();
     400    CSearchSort::NameSortMode nameSortMode = GetNameSortMode();
    392401
    393402    if (!m_sortDirection)
    394403    {
    395404        if (m_sortColumn == 1)
    396             return CFileListCtrl<CSearchFileData>::CSortComparisonObject(new CSearchSortPath(this, m_fileData, dirSortMode));
     405            return CFileListCtrl<CSearchFileData>::CSortComparisonObject(new CSearchSortPath(this, m_fileData, dirSortMode, nameSortMode));
    397406        else if (m_sortColumn == 2)
    398             return CFileListCtrl<CSearchFileData>::CSortComparisonObject(new CSearchSortSize(this, m_fileData, dirSortMode));
     407            return CFileListCtrl<CSearchFileData>::CSortComparisonObject(new CSearchSortSize(this, m_fileData, dirSortMode, nameSortMode));
    399408        else if (m_sortColumn == 3)
    400             return CFileListCtrl<CSearchFileData>::CSortComparisonObject(new CSearchSortType(this, m_fileData, dirSortMode));
     409            return CFileListCtrl<CSearchFileData>::CSortComparisonObject(new CSearchSortType(this, m_fileData, dirSortMode, nameSortMode));
    401410        else if (m_sortColumn == 4)
    402             return CFileListCtrl<CSearchFileData>::CSortComparisonObject(new CSearchSortTime(this, m_fileData, dirSortMode));
     411            return CFileListCtrl<CSearchFileData>::CSortComparisonObject(new CSearchSortTime(this, m_fileData, dirSortMode, nameSortMode));
    403412        else if (m_sortColumn == 5)
    404             return CFileListCtrl<CSearchFileData>::CSortComparisonObject(new CSearchSortPermissions(this, m_fileData, dirSortMode));
     413            return CFileListCtrl<CSearchFileData>::CSortComparisonObject(new CSearchSortPermissions(this, m_fileData, dirSortMode, nameSortMode));
    405414        else if (m_sortColumn == 6)
    406             return CFileListCtrl<CSearchFileData>::CSortComparisonObject(new CSearchSortOwnerGroup(this, m_fileData, dirSortMode));
     415            return CFileListCtrl<CSearchFileData>::CSortComparisonObject(new CSearchSortOwnerGroup(this, m_fileData, dirSortMode, nameSortMode));
    407416        else
    408             return CFileListCtrl<CSearchFileData>::CSortComparisonObject(new CSearchSortName(this, m_fileData, dirSortMode));
     417            return CFileListCtrl<CSearchFileData>::CSortComparisonObject(new CSearchSortName(this, m_fileData, dirSortMode, nameSortMode));
    409418    }
    410419    else
    411420    {
    412421        if (m_sortColumn == 1)
    413             return CFileListCtrl<CSearchFileData>::CSortComparisonObject(new CSearchSortPath_Reverse(this, m_fileData, dirSortMode));
     422            return CFileListCtrl<CSearchFileData>::CSortComparisonObject(new CSearchSortPath_Reverse(this, m_fileData, dirSortMode, nameSortMode));
    414423        else if (m_sortColumn == 2)
    415             return CFileListCtrl<CSearchFileData>::CSortComparisonObject(new CSearchSortSize_Reverse(this, m_fileData, dirSortMode));
     424            return CFileListCtrl<CSearchFileData>::CSortComparisonObject(new CSearchSortSize_Reverse(this, m_fileData, dirSortMode, nameSortMode));
    416425        else if (m_sortColumn == 3)
    417             return CFileListCtrl<CSearchFileData>::CSortComparisonObject(new CSearchSortType_Reverse(this, m_fileData, dirSortMode));
     426            return CFileListCtrl<CSearchFileData>::CSortComparisonObject(new CSearchSortType_Reverse(this, m_fileData, dirSortMode, nameSortMode));
    418427        else if (m_sortColumn == 4)
    419             return CFileListCtrl<CSearchFileData>::CSortComparisonObject(new CSearchSortTime_Reverse(this, m_fileData, dirSortMode));
     428            return CFileListCtrl<CSearchFileData>::CSortComparisonObject(new CSearchSortTime_Reverse(this, m_fileData, dirSortMode, nameSortMode));
    420429        else if (m_sortColumn == 5)
    421             return CFileListCtrl<CSearchFileData>::CSortComparisonObject(new CSearchSortPermissions_Reverse(this, m_fileData, dirSortMode));
     430            return CFileListCtrl<CSearchFileData>::CSortComparisonObject(new CSearchSortPermissions_Reverse(this, m_fileData, dirSortMode, nameSortMode));
    422431        else if (m_sortColumn == 6)
    423             return CFileListCtrl<CSearchFileData>::CSortComparisonObject(new CSearchSortOwnerGroup_Reverse(this, m_fileData, dirSortMode));
     432            return CFileListCtrl<CSearchFileData>::CSortComparisonObject(new CSearchSortOwnerGroup_Reverse(this, m_fileData, dirSortMode, nameSortMode));
    424433        else
    425             return CFileListCtrl<CSearchFileData>::CSortComparisonObject(new CSearchSortName_Reverse(this, m_fileData, dirSortMode));
     434            return CFileListCtrl<CSearchFileData>::CSortComparisonObject(new CSearchSortName_Reverse(this, m_fileData, dirSortMode, nameSortMode));
    426435    }
    427436}
    428437
  • src/interface/settings/optionspage_filelists.cpp

    diff --git a/src/interface/settings/optionspage_filelists.cpp b/src/interface/settings/optionspage_filelists.cpp
    index caa80d7..174d8bd 100644
    a b bool COptionsPageFilelists::LoadPage() 
    1010    bool failure = false;
    1111
    1212    SetChoice(XRCID("ID_SORTMODE"), m_pOptions->GetOptionVal(OPTION_FILELIST_DIRSORT), failure);
     13    SetChoice(XRCID("ID_NAMESORTMODE"), m_pOptions->GetOptionVal(OPTION_FILELIST_NAMESORT), failure);
    1314
    1415    SetTextFromOption(XRCID("ID_COMPARISON_THRESHOLD"), OPTION_COMPARISON_THRESHOLD, failure);
    1516
    bool COptionsPageFilelists::LoadPage() 
    2223bool COptionsPageFilelists::SavePage()
    2324{
    2425    m_pOptions->SetOption(OPTION_FILELIST_DIRSORT, GetChoice(XRCID("ID_SORTMODE")));
     26    m_pOptions->SetOption(OPTION_FILELIST_NAMESORT, GetChoice(XRCID("ID_NAMESORTMODE")));
    2527
    2628    SetOptionFromText(XRCID("ID_COMPARISON_THRESHOLD"), OPTION_COMPARISON_THRESHOLD);
    2729
  • tests/Makefile.am

    diff --git a/tests/Makefile.am b/tests/Makefile.am
    index 96e1294..101954c 100644
    a b test_SOURCES = test.cpp \ 
    1010        ipaddress.cpp \
    1111        dirparsertest.cpp \
    1212        localpathtest.cpp \
    13         serverpathtest.cpp
     13        serverpathtest.cpp \
     14        cmpnatural.cpp
    1415
    1516test_CPPFLAGS = $(WX_CPPFLAGS)
    1617test_CXXFLAGS = $(WX_CXXFLAGS_ONLY) $(CPPUNIT_CFLAGS)
  • new file tests/cmpnatural.cpp

    diff --git a/tests/cmpnatural.cpp b/tests/cmpnatural.cpp
    new file mode 100644
    index 0000000..89e7852
    - +  
     1#include <libfilezilla.h>
     2#include <wx/imaglist.h>
     3#include <wx/scrolwin.h>
     4#include <wx/listctrl.h>
     5#include <../interface/filelistctrl.h>
     6
     7#include <cppunit/extensions/HelperMacros.h>
     8#include <list>
     9
     10/*
     11 * This testsuite asserts the correctness of the
     12 * functions handling natural sort
     13 */
     14
     15class CNaturalSortTest : public CppUnit::TestFixture
     16{
     17    CPPUNIT_TEST_SUITE(CNaturalSortTest);
     18    CPPUNIT_TEST(testEmpty);
     19    CPPUNIT_TEST(testCaseInsensitive);
     20    CPPUNIT_TEST(testString);
     21    CPPUNIT_TEST(testNumber);
     22    CPPUNIT_TEST(testMixed);
     23    CPPUNIT_TEST(testSeq);
     24    CPPUNIT_TEST(testPair);
     25    CPPUNIT_TEST(testFractional);
     26    CPPUNIT_TEST_SUITE_END();
     27
     28public:
     29    void setUp() {}
     30    void tearDown() {}
     31
     32    void testEmpty();
     33    void testCaseInsensitive();
     34    void testString();
     35    void testNumber();
     36    void testMixed();
     37    void testSeq();
     38    void testPair();
     39    void testFractional();
     40};
     41
     42CPPUNIT_TEST_SUITE_REGISTRATION(CNaturalSortTest);
     43
     44void CNaturalSortTest::testEmpty()
     45{
     46    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T(""), _T("")) == 0);
     47    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T(""), _T("x")) < 0);
     48    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("x"), _T("")) > 0);
     49}
     50
     51void CNaturalSortTest::testCaseInsensitive()
     52{
     53    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("a"), _T("A")) == 0);
     54    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("B"), _T("b")) == 0);
     55    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("a"), _T("B")) < 0);
     56    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("A"), _T("b")) < 0);
     57    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("afFasFAc"), _T("aFfaSFaC")) == 0);
     58}
     59
     60void CNaturalSortTest::testString()
     61{
     62    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("a"), _T("b")) < 0);
     63    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("b"), _T("a")) > 0);
     64    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("a"), _T("ab")) < 0);
     65    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("ab"), _T("a")) > 0);
     66    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("affasfac"), _T("affasfac")) == 0);
     67}
     68
     69void CNaturalSortTest::testNumber()
     70{
     71    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("1"), _T("1")) == 0);
     72    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("1"), _T("2")) < 0);
     73    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("2"), _T("1")) > 0);
     74    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("15"), _T("25")) < 0);
     75    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("25"), _T("15")) > 0);
     76    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("15"), _T("17")) < 0);
     77    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("17"), _T("15")) > 0);
     78    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("1"), _T("10")) < 0);
     79    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("10"), _T("1")) > 0);
     80    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("2"), _T("17")) < 0);
     81    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("17"), _T("2")) > 0);
     82    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("2"), _T("02")) < 0);
     83    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("02"), _T("2")) > 0);
     84    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("02"), _T("1")) > 0);
     85    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("1"), _T("02")) < 0);
     86    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("02"), _T("3")) < 0);
     87    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("3"), _T("02")) > 0);
     88    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("25"), _T("021")) > 0);
     89    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("021"), _T("25")) < 0);
     90    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("2100"), _T("02005")) > 0);
     91    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("02005"), _T("2100")) < 0);
     92    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("010"), _T("02")) > 0);
     93}
     94
     95void CNaturalSortTest::testMixed()
     96{
     97    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("0"), _T("a")) < 0);
     98    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("a"), _T("0")) > 0);
     99    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("abc1xx"), _T("abc2xx")) < 0);
     100    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("abc1bb"), _T("abc2aa")) < 0);
     101    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("abc2"), _T("1")) > 0);
     102    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("10abc"), _T("10def")) < 0);
     103    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("10def"), _T("10abc")) > 0);
     104    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("10abc2"), _T("10abc3")) < 0);
     105    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("10abc3"), _T("10abc2")) > 0);
     106    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("10abc"), _T("10abc3")) < 0);
     107    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("10abc3"), _T("10abc")) > 0);
     108    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("1"), _T("1abc")) < 0);
     109    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("1abc"), _T("1")) > 0);
     110    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("2"), _T("1abc")) > 0);
     111    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("1abc"), _T("2")) < 0);
     112    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("1def"), _T("10abc")) < 0);
     113    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("10abc"), _T("1def")) > 0);
     114}
     115
     116void CNaturalSortTest::testSeq()
     117{
     118    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("a"), _T("a0")) < 0);
     119    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("a0"), _T("a1")) < 0);
     120    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("a1"), _T("a1a")) < 0);
     121    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("a1a"), _T("a1b")) < 0);
     122    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("a1b"), _T("a2")) < 0);
     123    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("a2"), _T("a10")) < 0);
     124    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("a10"), _T("a20")) < 0);
     125}
     126
     127void CNaturalSortTest::testPair()
     128{
     129    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("x2-g8"), _T("x2-y7")) < 0);
     130    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("x2-y7"), _T("x2-y08")) < 0);
     131    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("x2-y08"), _T("x8-y8")) < 0);
     132}
     133
     134void CNaturalSortTest::testFractional()
     135{
     136    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("1.001"), _T("1.002")) < 0);
     137    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("1.002"), _T("1.010")) < 0);
     138    //CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("1.010"), _T("1.02")) < 0);   //this fraction case would break 010 > 02
     139    //CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("1.02"), _T("1.1")) < 0);     //this fraction case would break 02 > 1
     140    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("1.1"), _T("1.3")) < 0);
     141    CPPUNIT_ASSERT(CListViewSort::CmpNatural(_T("1.3"), _T("1.15")) < 0);
     142}