Browse Source

Bug 1293: Option to turn off Natural order numerical sorting

https://winscp.net/tracker/1293

Source commit: db9b5105caa232c79ff6575200816851d90aa01b
Martin Prikryl 8 years ago
parent
commit
3251009b94

+ 5 - 5
source/components/UnixDirView.cpp

@@ -681,7 +681,7 @@ int __stdcall CompareFile(TListItem * Item1, TListItem * Item2, TUnixDirView * D
         // Duplicated in uvType branch
         if (!File1->IsDirectory)
         {
-          Result = CompareLogicalText(File1->Extension, File2->Extension);
+          Result = CompareLogicalText(File1->Extension, File2->Extension, DirView->NaturalOrderNumericalSorting);
         }
         else
         {
@@ -690,15 +690,15 @@ int __stdcall CompareFile(TListItem * Item1, TListItem * Item2, TUnixDirView * D
         break;
 
       case uvLinkTarget:
-        Result = CompareLogicalText(File1->LinkTo, File2->LinkTo);
+        Result = CompareLogicalText(File1->LinkTo, File2->LinkTo, DirView->NaturalOrderNumericalSorting);
         break;
 
       case uvType:
-        Result = CompareLogicalText(File1->TypeName, File2->TypeName);
+        Result = CompareLogicalText(File1->TypeName, File2->TypeName, DirView->NaturalOrderNumericalSorting);
         // fallback to uvExt
         if ((Result == 0) && !File1->IsDirectory)
         {
-          Result = CompareLogicalText(File1->Extension, File2->Extension);
+          Result = CompareLogicalText(File1->Extension, File2->Extension, DirView->NaturalOrderNumericalSorting);
         }
         break;
 
@@ -708,7 +708,7 @@ int __stdcall CompareFile(TListItem * Item1, TListItem * Item2, TUnixDirView * D
 
     if (Result == 0)
     {
-      Result = CompareLogicalText(File1->FileName, File2->FileName);
+      Result = CompareLogicalText(File1->FileName, File2->FileName, DirView->NaturalOrderNumericalSorting);
     }
 
     if (!DirView->UnixColProperties->SortAscending)

+ 10 - 2
source/core/Common.cpp

@@ -812,9 +812,17 @@ bool __fastcall SamePaths(const UnicodeString & Path1, const UnicodeString & Pat
   return AnsiSameText(IncludeTrailingBackslash(Path1), IncludeTrailingBackslash(Path2));
 }
 //---------------------------------------------------------------------------
-int __fastcall CompareLogicalText(const UnicodeString & S1, const UnicodeString & S2)
+int __fastcall CompareLogicalText(
+  const UnicodeString & S1, const UnicodeString & S2, bool NaturalOrderNumericalSorting)
 {
-  return StrCmpLogicalW(S1.c_str(), S2.c_str());
+  if (NaturalOrderNumericalSorting)
+  {
+    return StrCmpLogicalW(S1.c_str(), S2.c_str());
+  }
+  else
+  {
+    return lstrcmpi(S1.c_str(), S2.c_str());
+  }
 }
 //---------------------------------------------------------------------------
 bool __fastcall IsReservedName(UnicodeString FileName)

+ 2 - 1
source/core/Common.h

@@ -86,7 +86,8 @@ UnicodeString __fastcall EscapePuttyCommandParam(UnicodeString Param);
 UnicodeString __fastcall ExpandEnvironmentVariables(const UnicodeString & Str);
 bool __fastcall SamePaths(const UnicodeString & Path1, const UnicodeString & Path2);
 bool __fastcall IsPathToSameFile(const UnicodeString & Path1, const UnicodeString & Path2);
-int __fastcall CompareLogicalText(const UnicodeString & S1, const UnicodeString & S2);
+int __fastcall CompareLogicalText(
+  const UnicodeString & S1, const UnicodeString & S2, bool NaturalOrderNumericalSorting);
 bool __fastcall IsReservedName(UnicodeString FileName);
 UnicodeString __fastcall ApiPath(UnicodeString Path);
 UnicodeString __fastcall DisplayableStr(const RawByteString & Str);

+ 1 - 1
source/core/NamedObjs.cpp

@@ -36,7 +36,7 @@ int __fastcall TNamedObject::Compare(TNamedObject * Other)
   }
   else
   {
-    Result = CompareLogicalText(Name, Other->Name);
+    Result = CompareLogicalText(Name, Other->Name, true);
   }
   return Result;
 }

+ 1 - 0
source/forms/CustomScpExplorer.cpp

@@ -945,6 +945,7 @@ void __fastcall TCustomScpExplorerForm::ConfigurationChanged()
   RemoteDirView->ShowHiddenFiles = WinConfiguration->ShowHiddenFiles;
   RemoteDirView->FormatSizeBytes = WinConfiguration->FormatSizeBytes;
   RemoteDirView->ShowInaccesibleDirectories = WinConfiguration->ShowInaccesibleDirectories;
+  RemoteDirView->NaturalOrderNumericalSorting = WinConfiguration->NaturalOrderNumericalSorting;
 
   if (RemoteDirView->RowSelect != WinConfiguration->FullRowSelect)
   {

+ 1 - 1
source/forms/Login.cpp

@@ -2098,7 +2098,7 @@ void __fastcall TLoginDialog::SessionTreeCompare(TObject * /*Sender*/,
   }
   else if (Node1IsWorkspace || Node1IsFolder)
   {
-    Compare = CompareLogicalText(Node1->Text, Node2->Text);
+    Compare = CompareLogicalText(Node1->Text, Node2->Text, true);
   }
   else
   {

+ 2 - 0
source/forms/Preferences.cpp

@@ -267,6 +267,7 @@ void __fastcall TPreferencesDialog::LoadConfiguration()
     BOOLPROP(TemporaryDirectoryCleanup);
     BOOLPROP(ConfirmTemporaryDirectoryCleanup);
     BOOLPROP(FullRowSelect);
+    BOOLPROP(NaturalOrderNumericalSorting);
 
     ConfirmClosingSessionCheck2->Checked = WinConfiguration->ConfirmClosingSession;
 
@@ -649,6 +650,7 @@ void __fastcall TPreferencesDialog::SaveConfiguration()
     BOOLPROP(TemporaryDirectoryCleanup);
     BOOLPROP(ConfirmTemporaryDirectoryCleanup);
     BOOLPROP(FullRowSelect);
+    BOOLPROP(NaturalOrderNumericalSorting);
 
     WinConfiguration->ConfirmClosingSession = ConfirmClosingSessionCheck2->Checked;
 

+ 17 - 7
source/forms/Preferences.dfm

@@ -588,16 +588,16 @@ object PreferencesDialog: TPreferencesDialog
           Left = 8
           Top = 8
           Width = 389
-          Height = 171
+          Height = 195
           Anchors = [akLeft, akTop, akRight]
           Caption = 'Common'
           TabOrder = 0
           DesignSize = (
             389
-            171)
+            195)
           object Label1: TLabel
             Left = 16
-            Top = 143
+            Top = 167
             Width = 84
             Height = 13
             Caption = 'Show file si&zes in:'
@@ -656,23 +656,33 @@ object PreferencesDialog: TPreferencesDialog
           end
           object FormatSizeBytesCombo: TComboBox
             Left = 264
-            Top = 140
+            Top = 164
             Width = 108
             Height = 21
             Style = csDropDownList
             Anchors = [akTop, akRight]
             MaxLength = 1
-            TabOrder = 5
+            TabOrder = 6
             OnChange = ControlChange
             Items.Strings = (
               'Bytes'
               'Kilobytes'
               'Short format')
           end
+          object NaturalOrderNumericalSortingCheck: TCheckBox
+            Left = 16
+            Top = 141
+            Width = 357
+            Height = 17
+            Anchors = [akLeft, akTop, akRight]
+            Caption = '&Use &natural order numerical sorting'
+            TabOrder = 5
+            OnClick = ControlChange
+          end
         end
         object DoubleClickGroup: TGroupBox
           Left = 8
-          Top = 185
+          Top = 209
           Width = 389
           Height = 74
           Anchors = [akLeft, akTop, akRight]
@@ -717,7 +727,7 @@ object PreferencesDialog: TPreferencesDialog
         end
         object PanelFontGroup: TGroupBox
           Left = 8
-          Top = 265
+          Top = 289
           Width = 389
           Height = 82
           Anchors = [akLeft, akRight, akBottom]

+ 1 - 0
source/forms/Preferences.h

@@ -319,6 +319,7 @@ __published:
   TRadioButton *CustomIniFileStorageButton;
   TFilenameEdit *CustomIniFileStorageEdit;
   TPathLabel *AutomaticIniFileStorageLabel;
+  TCheckBox *NaturalOrderNumericalSortingCheck;
   void __fastcall FormShow(TObject *Sender);
   void __fastcall ControlChange(TObject *Sender);
   void __fastcall EditorFontButtonClick(TObject *Sender);

+ 2 - 0
source/forms/ScpCommander.cpp

@@ -563,6 +563,8 @@ void __fastcall TScpCommanderForm::ConfigurationChanged()
   LocalDirView->NortonLike = WinConfiguration->ScpCommander.NortonLikeMode;
   RemoteDirView->NortonLike = WinConfiguration->ScpCommander.NortonLikeMode;
 
+  LocalDirView->NaturalOrderNumericalSorting = WinConfiguration->NaturalOrderNumericalSorting;
+
   if (LocalDirView->RowSelect != WinConfiguration->FullRowSelect)
   {
     LocalDirView->RowSelect = WinConfiguration->FullRowSelect;

+ 13 - 0
source/packages/filemng/CustomDirView.pas

@@ -165,6 +165,7 @@ type
     FOnMatchMask: TMatchMaskEvent;
     FOnGetOverlay: TDirViewGetOverlayEvent;
     FMask: string;
+    FNaturalOrderNumericalSorting: Boolean;
     FScrollOnDragOver: TListViewScrollOnDragOver;
     FStatusFileInfo: TStatusFileInfo;
     FDoubleBufferedScrollingWorkaround: Boolean;
@@ -304,6 +305,7 @@ type
     function FileNameMatchesMasks(FileName: string; Directory: Boolean; Size: Int64; Modification: TDateTime; Masks: string; AllowImplicitMatches: Boolean): Boolean;
     function EnableDragOnClick: Boolean; override;
     procedure SetMask(Value: string); virtual;
+    procedure SetNaturalOrderNumericalSorting(Value: Boolean);
     procedure ScrollOnDragOverBeforeUpdate(ObjectToValidate: TObject);
     procedure ScrollOnDragOverAfterUpdate;
     procedure DoHistoryGo(Index: Integer);
@@ -412,6 +414,7 @@ type
     property SelectedNamesSaved: Boolean read GetSelectedNamesSaved;
     {filemask, multiple filters are possible: '*.pas;*.dfm'}
     property Mask: string read FMask write SetMask;
+    property NaturalOrderNumericalSorting: Boolean read FNaturalOrderNumericalSorting write SetNaturalOrderNumericalSorting;
 
     property OnContextPopup;
     property OnStartLoading: TNotifyEvent read FOnStartLoading write FOnStartLoading;
@@ -863,6 +866,7 @@ begin
   FDragDrive := #0;
   FExeDrag := False;
   FMask := '';
+  FNaturalOrderNumericalSorting := True;
   FDoubleBufferedScrollingWorkaround := not IsVistaHard();
 
   FOnHistoryChange := nil;
@@ -3196,6 +3200,15 @@ begin
   end;
 end;{SetMask}
 
+procedure TCustomDirView.SetNaturalOrderNumericalSorting(Value: Boolean);
+begin
+  if NaturalOrderNumericalSorting <> Value then
+  begin
+    FNaturalOrderNumericalSorting := Value;
+    SortItems;
+  end;
+end;
+
 // WM_SETFOCUS works even when focus is moved to another window/app,
 // while .Enter works only when focus is moved to order control of the same window.
 procedure TCustomDirView.WMSetFocus(var Message: TWMSetFocus);

+ 9 - 5
source/packages/filemng/DirView.pas

@@ -1955,9 +1955,12 @@ end; {DeleteSelectedFiles}
 
 function StrCmpLogicalW(const sz1, sz2: UnicodeString): Integer; stdcall; external 'shlwapi.dll';
 
-function CompareLogicalText(const S1, S2: string): Integer;
+function CompareLogicalText(const S1, S2: string; NaturalOrderNumericalSorting: Boolean): Integer;
 begin
-  Result := StrCmpLogicalW(PChar(S1), PChar(S2));
+  if NaturalOrderNumericalSorting then
+    Result := StrCmpLogicalW(PChar(S1), PChar(S2))
+  else
+    Result := lstrcmpi(PChar(S1), PChar(S2));
 end;
 
 function CompareFileType(I1, I2: TListItem; P1, P2: PFileRec): Integer;
@@ -1976,7 +1979,7 @@ begin
     Key1 := P1.TypeName + ' ' + P1.FileExt + ' ' + P1.DisplayName;
     Key2 := P2.TypeName + ' ' + P2.FileExt + ' ' + P2.DisplayName;
   end;
-  Result := CompareLogicalText(Key1, Key2);
+  Result := CompareLogicalText(Key1, Key2, TDirView(I1.ListView).NaturalOrderNumericalSorting);
 end;
 
 function CompareFileTime(P1, P2: PFileRec): Integer;
@@ -2062,7 +2065,8 @@ begin
           if not P1.isDirectory then
           begin
             Result := CompareLogicalText(
-              P1.FileExt + ' ' + P1.DisplayName, P2.FileExt + ' ' + P2.DisplayName);
+              P1.FileExt + ' ' + P1.DisplayName, P2.FileExt + ' ' + P2.DisplayName,
+              AOwner.NaturalOrderNumericalSorting);
           end
             else ; //fallback
 
@@ -2072,7 +2076,7 @@ begin
 
       if Result = fEqual then
       begin
-        Result := CompareLogicalText(P1.DisplayName, P2.DisplayName)
+        Result := CompareLogicalText(P1.DisplayName, P2.DisplayName, AOwner.NaturalOrderNumericalSorting)
       end;
     end;
   end;

+ 7 - 0
source/windows/WinConfiguration.cpp

@@ -543,6 +543,7 @@ void __fastcall TWinConfiguration::Default()
   FPanelFont.FontSize = 0;
   FPanelFont.FontStyle = 0;
   FPanelFont.FontCharset = DEFAULT_CHARSET;
+  FNaturalOrderNumericalSorting = true;
   FFullRowSelect = false;
   FOfferedEditorAutoConfig = false;
   FVersionHistory = L"";
@@ -941,6 +942,7 @@ THierarchicalStorage * TWinConfiguration::CreateScpStorage(bool & SessionList)
     KEYEX(Integer,PanelFont.FontSize, L"PanelFontSize"); \
     KEYEX(Integer,PanelFont.FontStyle, L"PanelFontStyle"); \
     KEYEX(Integer,PanelFont.FontCharset, L"PanelFontCharset"); \
+    KEY(Bool,     NaturalOrderNumericalSorting); \
     KEY(Bool,     FullRowSelect); \
     KEY(Bool,     OfferedEditorAutoConfig); \
     KEY(Integer,  LastMonitor); \
@@ -2080,6 +2082,11 @@ void __fastcall TWinConfiguration::SetPanelFont(const TFontConfiguration & value
   SET_CONFIG_PROPERTY_EX(PanelFont, UpdateIconFont());
 }
 //---------------------------------------------------------------------------
+void __fastcall TWinConfiguration::SetNaturalOrderNumericalSorting(bool value)
+{
+  SET_CONFIG_PROPERTY(NaturalOrderNumericalSorting);
+}
+//---------------------------------------------------------------------------
 void __fastcall TWinConfiguration::SetFullRowSelect(bool value)
 {
   SET_CONFIG_PROPERTY(FullRowSelect);

+ 3 - 0
source/windows/WinConfiguration.h

@@ -407,6 +407,7 @@ private:
   bool FRefreshRemotePanel;
   TDateTime FRefreshRemotePanelInterval;
   TFontConfiguration FPanelFont;
+  bool FNaturalOrderNumericalSorting;
   bool FFullRowSelect;
   bool FOfferedEditorAutoConfig;
   bool FUseMasterPassword;
@@ -506,6 +507,7 @@ private:
   void __fastcall SetRefreshRemotePanel(bool value);
   void __fastcall SetRefreshRemotePanelInterval(TDateTime value);
   void __fastcall SetPanelFont(const TFontConfiguration & value);
+  void __fastcall SetNaturalOrderNumericalSorting(bool value);
   void __fastcall SetFullRowSelect(bool value);
   void __fastcall SetOfferedEditorAutoConfig(bool value);
   void __fastcall SetLastMonitor(int value);
@@ -682,6 +684,7 @@ public:
   __property bool RefreshRemotePanel = { read = FRefreshRemotePanel, write = SetRefreshRemotePanel };
   __property TDateTime RefreshRemotePanelInterval = { read = FRefreshRemotePanelInterval, write = SetRefreshRemotePanelInterval };
   __property TFontConfiguration PanelFont = { read = FPanelFont, write = SetPanelFont };
+  __property bool NaturalOrderNumericalSorting = { read = FNaturalOrderNumericalSorting, write = SetNaturalOrderNumericalSorting };
   __property bool FullRowSelect = { read = FFullRowSelect, write = SetFullRowSelect };
   __property bool OfferedEditorAutoConfig = { read = FOfferedEditorAutoConfig, write = SetOfferedEditorAutoConfig };
   __property int LastMonitor = { read = GetLastMonitor, write = SetLastMonitor };