Martin Prikryl 17 年之前
父节点
当前提交
ec98f56331

+ 4 - 4
Console.rc

@@ -1,6 +1,6 @@
 1 VERSIONINFO
-FILEVERSION 2,2,0,98
-PRODUCTVERSION 2,2,0,98
+FILEVERSION 2,2,0,99
+PRODUCTVERSION 2,2,0,99
 FILEOS 0x4
 FILETYPE 0x1
 {
@@ -10,13 +10,13 @@ FILETYPE 0x1
         {
             VALUE "CompanyName", "Martin Prikryl\0"
             VALUE "FileDescription", "Console interface for WinSCP\0"
-            VALUE "FileVersion", "2.2.0.98\0"
+            VALUE "FileVersion", "2.2.0.99\0"
             VALUE "InternalName", "console\0"
             VALUE "LegalCopyright", "(c) 2000-2008 Martin Prikryl\0"
             VALUE "LegalTrademarks", "\0"
             VALUE "OriginalFilename", "winscp.com\0"
             VALUE "ProductName", "WinSCP\0"
-            VALUE "ProductVersion", "4.1.7.0\0"
+            VALUE "ProductVersion", "4.1.8.0\0"
             VALUE "WWW", "http://winscp.net/\0"
         }
     }

+ 4 - 4
DragExt.rc

@@ -1,6 +1,6 @@
 1 VERSIONINFO
-FILEVERSION 1,1,8,92
-PRODUCTVERSION 1,1,8,92
+FILEVERSION 1,1,8,93
+PRODUCTVERSION 1,1,8,93
 FILEOS 0x4
 FILETYPE 0x2
 {
@@ -10,13 +10,13 @@ FILETYPE 0x2
         {
             VALUE "CompanyName", "Martin Prikryl\0"
             VALUE "FileDescription", "Drag&Drop shell extension for WinSCP (32-bit)\0"
-            VALUE "FileVersion", "1.1.8.92\0"
+            VALUE "FileVersion", "1.1.8.93\0"
             VALUE "InternalName", "dragext32\0"
             VALUE "LegalCopyright", "(c) 2000-2008 Martin Prikryl\0"
             VALUE "LegalTrademarks", "\0"
             VALUE "OriginalFilename", "dragext.dll\0"
             VALUE "ProductName", "WinSCP\0"
-            VALUE "ProductVersion", "4.1.7.0\0"
+            VALUE "ProductVersion", "4.1.8.0\0"
             VALUE "WWW", "http://winscp.net/\0"
         }
     }

+ 4 - 4
DragExt64.rc

@@ -1,6 +1,6 @@
 1 VERSIONINFO
-FILEVERSION 1,1,8,92
-PRODUCTVERSION 1,1,8,92
+FILEVERSION 1,1,8,93
+PRODUCTVERSION 1,1,8,93
 FILEOS 0x4
 FILETYPE 0x2
 {
@@ -10,13 +10,13 @@ FILETYPE 0x2
         {
             VALUE "CompanyName", "Martin Prikryl\0"
             VALUE "FileDescription", "Drag&Drop shell extension for WinSCP (64-bit)\0"
-            VALUE "FileVersion", "1.1.8.92\0"
+            VALUE "FileVersion", "1.1.8.93\0"
             VALUE "InternalName", "dragext64\0"
             VALUE "LegalCopyright", "(c) 2000-2008 Martin Prikryl\0"
             VALUE "LegalTrademarks", "\0"
             VALUE "OriginalFilename", "dragext64.dll\0"
             VALUE "ProductName", "WinSCP\0"
-            VALUE "ProductVersion", "4.1.7.0\0"
+            VALUE "ProductVersion", "4.1.8.0\0"
             VALUE "WWW", "http://winscp.net/\0"
         }
     }

+ 5 - 5
WinSCP.rc

@@ -1,6 +1,6 @@
 1 VERSIONINFO
-FILEVERSION 4,1,7,413
-PRODUCTVERSION 4,1,7,413
+FILEVERSION 4,1,8,415
+PRODUCTVERSION 4,1,8,415
 FILEOS 0x4
 FILETYPE 0x1
 {
@@ -10,13 +10,13 @@ FILETYPE 0x1
         {
             VALUE "CompanyName", "Martin Prikryl\0"
             VALUE "FileDescription", "SFTP, FTP and SCP client\0"
-            VALUE "FileVersion", "4.1.7.413\0"
+            VALUE "FileVersion", "4.1.8.415\0"
             VALUE "InternalName", "winscp\0"
             VALUE "LegalCopyright", "(c) 2000-2008 Martin Prikryl\0"
             VALUE "LegalTrademarks", "\0"
-            VALUE "OriginalFilename", "winscp417.exe\0"
+            VALUE "OriginalFilename", "winscp418.exe\0"
             VALUE "ProductName", "WinSCP\0"
-            VALUE "ProductVersion", "4.1.7.0\0"
+            VALUE "ProductVersion", "4.1.8.0\0"
             VALUE "WWW", "http://winscp.net/\0"
         }
     }

+ 81 - 39
components/UnixDriveView.cpp

@@ -49,6 +49,7 @@ __fastcall TCustomUnixDriveView::TCustomUnixDriveView(TComponent* Owner) :
   DDAllowMove = false;
   FShowInaccesibleDirectories = true;
   FDummyDragFile = NULL;
+  FPendingDelete = new TList();
 }
 //---------------------------------------------------------------------------
 __fastcall TCustomUnixDriveView::~TCustomUnixDriveView()
@@ -60,6 +61,7 @@ __fastcall TCustomUnixDriveView::~TCustomUnixDriveView()
     SAFE_DESTROY(FDummyDragFile);
     #endif
   }
+  SAFE_DESTROY(FPendingDelete);
 }
 //---------------------------------------------------------------------------
 void __fastcall TCustomUnixDriveView::CreateWnd()
@@ -137,10 +139,16 @@ bool __fastcall TCustomUnixDriveView::NodeIsHidden(const TTreeNode * Node)
   #endif
 }
 //---------------------------------------------------------------------------
-bool __fastcall TCustomUnixDriveView::NodeCanDelete(TTreeNode * Node)
+bool __fastcall TCustomUnixDriveView::NodeCanDelete(TTreeNode * Node, bool RememberIfNot)
 {
-  return (Selected == NULL) ||
+  bool Result =
+    (Selected == NULL) ||
     ((Selected != Node) && !Selected->HasAsParent(Node));
+  if (!Result && RememberIfNot)
+  {
+    FPendingDelete->Add(Node);
+  }
+  return Result;
 }
 //---------------------------------------------------------------------------
 void __fastcall TCustomUnixDriveView::UpdatePath(TTreeNode * Node, bool Force,
@@ -203,7 +211,7 @@ void __fastcall TCustomUnixDriveView::UpdatePath(TTreeNode * Node, bool Force,
       {
         TTreeNode * ChildNode = dynamic_cast<TTreeNode *>(ChildrenDirs->Objects[i]);
         TNodeData * ChildData = NodeData(ChildNode);
-        if ((ChildData->File == NULL) && NodeCanDelete(ChildNode))
+        if ((ChildData->File == NULL) && NodeCanDelete(ChildNode, true))
         {
           ChildNode->Delete();
         }
@@ -223,7 +231,7 @@ void __fastcall TCustomUnixDriveView::UpdatePath(TTreeNode * Node, bool Force,
     {
       TTreeNode * PrevChildNode = Node->GetPrevChild(ChildNode);
       TRemoteFile * File = NodeFile(ChildNode);
-      if (!NodeCanDelete(ChildNode) ||
+      if (!NodeCanDelete(ChildNode, true) ||
           ((ShowHiddenDirs || !NodeIsHidden(ChildNode)) &&
            (ShowInaccesibleDirectories || (File == NULL) || !File->IsInaccesibleDirectory)))
       {
@@ -391,6 +399,15 @@ void __fastcall TCustomUnixDriveView::Delete(TTreeNode * Node)
   {
     FPrevSelected = NULL;
   }
+  // optimization check
+  if (FPendingDelete->Count > 0)
+  {
+    int I = FPendingDelete->IndexOf(Node);
+    if (I >= 0)
+    {
+      FPendingDelete->Delete(I);
+    }
+  }
   TNodeData * Data = NULL;
   if (Node != NULL)
   {
@@ -410,60 +427,85 @@ void __fastcall TCustomUnixDriveView::Delete(TTreeNode * Node)
 void __fastcall TCustomUnixDriveView::Change(TTreeNode * Node)
 {
   #ifndef DESIGN_ONLY
-  // During D&D Selected is set to NULL and then back to previous selection,
-  // prevent actually changing directory in such case
-  if (FIgnoreChange || (Node == NULL) || (Node == FPrevSelected))
-  {
-    TCustomDriveView::Change(Node);
-  }
-  else
+  try
   {
-    if (FDirView != NULL)
-    {
-      // remember current directory, so it gets selected if we move to parent
-      // directory
-      FDirView->ContinueSession(true);
-    }
-
-    // if previous node is child to newly selected one, do not expand it.
-    // it is either already expanded and it is even being collapsed.
-    bool Expand = (FPrevSelected == NULL) || !FPrevSelected->HasAsParent(Node);
-    FDirectoryLoaded = false;
-    try
+    // During D&D Selected is set to NULL and then back to previous selection,
+    // prevent actually changing directory in such case
+    if (FIgnoreChange || (Node == NULL) || (Node == FPrevSelected))
     {
-      Terminal->ChangeDirectory(NodePathName(Node));
       TCustomDriveView::Change(Node);
     }
-    __finally
+    else
     {
-      if (FDirectoryLoaded)
+      if (FDirView != NULL)
       {
-        FPrevSelected = Selected;
-        if (Expand)
-        {
-          Selected->Expand(false);
-        }
+        // remember current directory, so it gets selected if we move to parent
+        // directory
+        FDirView->ContinueSession(true);
       }
-      else
+
+      // if previous node is child to newly selected one, do not expand it.
+      // it is either already expanded and it is even being collapsed.
+      bool Expand = (FPrevSelected == NULL) || !FPrevSelected->HasAsParent(Node);
+      FDirectoryLoaded = false;
+      try
       {
-        assert(!FIgnoreChange);
-        FIgnoreChange = true;
-        try
+        Terminal->ChangeDirectory(NodePathName(Node));
+        TCustomDriveView::Change(Node);
+      }
+      __finally
+      {
+        if (FDirectoryLoaded)
         {
-          Selected = FPrevSelected;
+          FPrevSelected = Selected;
+          if (Expand)
+          {
+            Selected->Expand(false);
+          }
         }
-        __finally
+        else
         {
-          FIgnoreChange = false;
+          assert(!FIgnoreChange);
+          FIgnoreChange = true;
+          try
+          {
+            Selected = FPrevSelected;
+          }
+          __finally
+          {
+            FIgnoreChange = false;
+          }
         }
       }
     }
   }
+  __finally
+  {
+    CheckPendingDeletes();
+  }
   #else
   TCustomDriveView::Change(Node);
   #endif
 }
 //---------------------------------------------------------------------------
+void __fastcall TCustomUnixDriveView::CheckPendingDeletes()
+{
+  int Index = 0;
+  while (Index < FPendingDelete->Count)
+  {
+    TTreeNode * Node = static_cast<TTreeNode *>(FPendingDelete->Items[Index]);
+    if (NodeCanDelete(Node, false))
+    {
+      // this as well deletes node from FPendingDelete
+      Node->Delete();
+    }
+    else
+    {
+      Index++;
+    }
+  }
+}
+//---------------------------------------------------------------------------
 void __fastcall TCustomUnixDriveView::PerformDragDropFileOperation(
   TTreeNode * Node, int Effect)
 {
@@ -704,7 +746,7 @@ TTreeNode * __fastcall TCustomUnixDriveView::FindNodeToPath(AnsiString Path)
     }
   }
   #else
-  Result = NULL
+  Result = NULL;
   #endif
   return Result;
 }

+ 3 - 1
components/UnixDriveView.h

@@ -38,6 +38,7 @@ protected:
   TTreeNode * __fastcall LoadPathEasy(TTreeNode * Parent,
     AnsiString Path, TRemoteFile * File);
   void __fastcall UpdatePath(TTreeNode * Node, bool Force, bool CanLoad = false);
+  void __fastcall CheckPendingDeletes();
 
   void __fastcall SetTerminal(TTerminal * value);
 
@@ -46,7 +47,7 @@ protected:
   inline TRemoteFile * __fastcall NodeFile(const TTreeNode * Node);
   inline TRemoteFile * __fastcall NodeFileForce(TTreeNode * Node);
   inline bool __fastcall NodeIsHidden(const TTreeNode * Node);
-  inline bool __fastcall NodeCanDelete(TTreeNode * Node);
+  inline bool __fastcall NodeCanDelete(TTreeNode * Node, bool RememberIfNot);
 
   virtual TCustomDirView * __fastcall GetCustomDirView();
   virtual void __fastcall SetCustomDirView(TCustomDirView * Value);
@@ -94,6 +95,7 @@ private:
   TDDDragFileName FOnDDDragFileName;
   bool FShowInaccesibleDirectories;
   TRemoteFile * FDummyDragFile;
+  TList * FPendingDelete;
 
   bool __fastcall IsRootNameStored();
   void __fastcall SetShowInaccesibleDirectories(bool value);

+ 13 - 13
core/SessionData.cpp

@@ -864,13 +864,13 @@ bool __fastcall TSessionData::ParseUrl(AnsiString Url, TOptions * Options,
     // (this allows setting for example default username for host
     // by creating stored session named by host)
     TSessionData * Data = NULL;
-    for (Integer Index = 0; Index < StoredSessions->Count; Index++)
+    for (Integer Index = 0; Index < StoredSessions->Count + StoredSessions->HiddenCount; Index++)
     {
-      AnsiString Name = StoredSessions->Sessions[Index]->Name;
-      if (AnsiSameText(Name, DecodedUrl) ||
-          AnsiSameText(Name + "/", DecodedUrl.SubString(1, Name.Length() + 1)))
+      TSessionData * AData = (TSessionData *)StoredSessions->Items[Index];
+      if (AnsiSameText(AData->Name, DecodedUrl) ||
+          AnsiSameText(AData->Name + "/", DecodedUrl.SubString(1, AData->Name.Length() + 1)))
       {
-        Data = StoredSessions->Sessions[Index];
+        Data = AData;
         break;
       }
     }
@@ -881,14 +881,6 @@ bool __fastcall TSessionData::ParseUrl(AnsiString Url, TOptions * Options,
     {
       DefaultsOnly = false;
       Assign(Data);
-      if (StoredSessions->IsHidden(Data))
-      {
-        Data->Remove();
-        StoredSessions->Remove(Data);
-        // only modified, implicit
-        StoredSessions->Save(false, false);
-      }
-
       int P = 1;
       while (!AnsiSameText(DecodeUrlChars(Url.SubString(1, P)), Data->Name))
       {
@@ -896,6 +888,14 @@ bool __fastcall TSessionData::ParseUrl(AnsiString Url, TOptions * Options,
         assert(P <= Url.Length());
       }
       ARemoteDirectory = Url.SubString(P + 1, Url.Length() - P);
+
+      if (StoredSessions->IsHidden(Data))
+      {
+        Data->Remove();
+        StoredSessions->Remove(Data);
+        // only modified, implicit
+        StoredSessions->Save(false, false);
+      }
     }
     else
     {

+ 79 - 1
core/Terminal.cpp

@@ -2157,6 +2157,38 @@ void __fastcall TTerminal::ReadFile(const AnsiString FileName,
   }
 }
 //---------------------------------------------------------------------------
+bool __fastcall TTerminal::FileExists(const AnsiString FileName)
+{
+  bool Result;
+  TRemoteFile * File = NULL;
+  try
+  {
+    ExceptionOnFail = true;
+    try
+    {
+      ReadFile(FileName, File);
+    }
+    __finally
+    {
+      ExceptionOnFail = false;
+    }
+    delete File;
+    Result = true;
+  }
+  catch(...)
+  {
+    if (Active)
+    {
+      Result = false;
+    }
+    else
+    {
+      throw;
+    }
+  }
+  return Result;
+}
+//---------------------------------------------------------------------------
 void __fastcall TTerminal::AnnounceFileListOperation()
 {
   FFileSystem->AnnounceFileListOperation();
@@ -2773,7 +2805,53 @@ bool __fastcall TTerminal::MoveFiles(TStrings * FileList, const AnsiString Targe
   Params.Target = Target;
   Params.FileMask = FileMask;
   DirectoryModified(Target, true);
-  return ProcessFiles(FileList, foRemoteMove, MoveFile, &Params);
+  bool Result;
+  BeginTransaction();
+  try
+  {
+    Result = ProcessFiles(FileList, foRemoteMove, MoveFile, &Params);
+  }
+  __finally
+  {
+    if (Active)
+    {
+      AnsiString WithTrailing = UnixIncludeTrailingBackslash(CurrentDirectory);
+      bool PossiblyMoved = false;
+      // check if we was moving current directory.
+      // this is just optimization to avoid checking existence of current
+      // directory after each move operation.
+      for (int Index = 0; !PossiblyMoved && (Index < FileList->Count); Index++)
+      {
+        const TRemoteFile * File =
+          dynamic_cast<const TRemoteFile *>(FileList->Objects[Index]);
+        // File can be NULL, and filename may not be full path,
+        // but currently this is the only way we can move (at least in GUI)
+        // current directory
+        if ((File != NULL) &&
+            File->IsDirectory &&
+            ((CurrentDirectory.SubString(1, FileList->Strings[Index].Length()) == FileList->Strings[Index]) &&
+             ((FileList->Strings[Index].Length() == CurrentDirectory.Length()) ||
+              (CurrentDirectory[FileList->Strings[Index].Length() + 1] == '/'))))
+        {
+          PossiblyMoved = true;
+        }
+      }
+
+      if (PossiblyMoved && !FileExists(CurrentDirectory))
+      {
+        AnsiString NearestExisting = CurrentDirectory;
+        do
+        {
+          NearestExisting = UnixExtractFileDir(NearestExisting);
+        }
+        while (!IsUnixRootPath(NearestExisting) && !FileExists(NearestExisting));
+
+        ChangeDirectory(NearestExisting);
+      }
+    }
+    EndTransaction();
+  }
+  return Result;
 }
 //---------------------------------------------------------------------------
 void __fastcall TTerminal::DoCopyFile(const AnsiString FileName,

+ 1 - 0
core/Terminal.h

@@ -339,6 +339,7 @@ public:
   void __fastcall ReadDirectory(bool ReloadOnly, bool ForceCache = false);
   TRemoteFileList * ReadDirectoryListing(AnsiString Directory, bool UseCache);
   void __fastcall ReadFile(const AnsiString FileName, TRemoteFile *& File);
+  bool __fastcall FileExists(const AnsiString FileName);
   void __fastcall ReadSymlink(TRemoteFile * SymlinkFile, TRemoteFile *& File);
   bool __fastcall CopyToLocal(TStrings * FilesToCopy,
     const AnsiString TargetDir, const TCopyParamType * CopyParam, int Params);

+ 2 - 15
forms/MessageDlg.cpp

@@ -3,7 +3,6 @@
 #pragma hdrstop
 
 #include <Consts.hpp>
-#include <MoreButton.hpp>
 #include <GUITools.h>
 
 #include <Common.h>
@@ -70,8 +69,7 @@ AnsiString __fastcall TMessageForm::GetFormText()
   DividerLine = AnsiString::StringOfChar('-', 27) + sLineBreak;
   for (int i = 0; i < ComponentCount - 1; i++)
   {
-    if ((dynamic_cast<TButton*>(Components[i]) != NULL) &&
-        (dynamic_cast<TMoreButton*>(Components[i]) == NULL))
+    if (dynamic_cast<TButton*>(Components[i]) != NULL)
     {
       ButtonCaptions += dynamic_cast<TButton*>(Components[i])->Caption +
         AnsiString::StringOfChar(' ', 3);
@@ -301,17 +299,6 @@ TForm * __fastcall TMessageForm::Create(const AnsiString & Msg,
     MessageMemo->Lines->Text = MoreMessages->Text;
 
     Result->MessageMemo = MessageMemo;
-
-    TMoreButton * MoreButton = new TMoreButton(Result);
-    MoreButton->Parent = Result;
-    MoreButton->Panel = MessageMemo;
-    MoreButton->RepositionForm = true;
-    MoreButton->Name = "MoreButton";
-
-    MessageMemo->TabOrder = static_cast<short>(MoreButton->TabOrder + 1);
-
-    ButtonControls[ButtonControlsCount] = MoreButton;
-    ButtonControlsCount++;
   }
 
   int ButtonGroupWidth = 0;
@@ -324,7 +311,7 @@ TForm * __fastcall TMessageForm::Create(const AnsiString & Msg,
   int MoreMessageWidth = (MoreMessages != NULL ?
     MulDiv(mcMoreMessageWidth, DialogUnits.x, 4) : 0);
   int MoreMessageHeight = (MoreMessages != NULL ?
-    MulDiv(mcMoreMessageHeight, DialogUnits.y, 8) : 0);
+    MulDiv(mcMoreMessageHeight, DialogUnits.y, 12) : 0);
 
   int AClientWidth =
     (IconTextWidth > ButtonGroupWidth ? IconTextWidth : ButtonGroupWidth) +

+ 1 - 0
forms/Preferences.dfm

@@ -898,6 +898,7 @@ object PreferencesDialog: TPreferencesDialog
             ViewStyle = vsReport
             OnData = EditorListViewData
             OnDblClick = EditorListViewDblClick
+            OnEndDrag = ListViewEndDrag
             OnDragDrop = EditorListViewDragDrop
             OnDragOver = ListViewDragOver
             OnKeyDown = EditorListViewKeyDown

+ 20 - 1
forms/Properties.cpp

@@ -135,7 +135,26 @@ void __fastcall TPropertiesDialog::LoadInfo()
     {
       TRemoteFile * File = (TRemoteFile *)(FFileList->Objects[0]);
       assert(File && FShellImageList);
-      FShellImageList->GetIcon(File->IconIndex, FileIconImage->Picture->Icon);
+
+      // shell image list does not have fixed large icon size
+      // (it is probably 32x32 min, but can be larged, on xp it is 48x48 if
+      // large icons are enabled, on vista, can be even larger).
+      // so we stretch (shrink) the icon to 32x32 here to be sure.
+      Graphics::TBitmap * Bitmap = new Graphics::TBitmap;
+      try
+      {
+        FShellImageList->GetBitmap(File->IconIndex, Bitmap);
+        FileIconImage->Picture->Bitmap->Width = FileIconImage->Width;
+        FileIconImage->Picture->Bitmap->Height = FileIconImage->Height;
+        FileIconImage->Picture->Bitmap->Canvas->StretchDraw(
+          TRect(0, 0, FileIconImage->Width, FileIconImage->Height),
+          Bitmap);
+      }
+      __finally
+      {
+        delete Bitmap;
+      }
+
       if (!FUsersSet)
       {
         OwnerComboBox->Items->Text = File->Owner;

+ 11 - 0
packages/filemng/CustomDirView.pas

@@ -210,6 +210,7 @@ type
     procedure WMRButtonDown(var Message: TWMRButtonDown); message WM_RBUTTONDOWN;
     procedure WMXButtonUp(var Message: TWMXMouse); message _WM_XBUTTONUP;
     procedure WMAppCommand(var Message: TMessage); message _WM_APPCOMMAND;
+    procedure CMColorChanged(var Message: TMessage); message CM_COLORCHANGED;
 
     procedure DumbCustomDrawItem(Sender: TCustomListView; Item: TListItem;
       State: TCustomDrawState; var DefaultDraw: Boolean);
@@ -2631,6 +2632,16 @@ begin
     else inherited;
 end;
 
+procedure TCustomDirView.CMColorChanged(var Message: TMessage);
+begin
+  inherited;
+  // particularly when changing color back to default (clWindow),
+  // non-client area (border line) is not redrawn,
+  // keeping previous color. force redraw here
+  if HandleAllocated then
+    RedrawWindow(Handle, nil, 0, RDW_INVALIDATE or RDW_FRAME);
+end;
+
 procedure TCustomDirView.WndProc(var Message: TMessage);
 begin
   case Message.Msg of

+ 11 - 1
packages/filemng/DirView.pas

@@ -1056,7 +1056,7 @@ begin
 
   Expanded := ExpandFileName(FPath);
   Assert(Pos(':', Expanded) = 2);
-  FLastPath[Expanded[1]] := Expanded;
+  FLastPath[UpCase(Expanded[1])] := Expanded;
 end;
 
 procedure TDirView.SetPath(Value: string);
@@ -1960,6 +1960,14 @@ begin
                 Items.BeginUpdate;
               end;
               AnyUpdate := True;
+
+              with PFileRec(Items[Index].Data)^ do
+              begin
+                Dec(FFilesSize, Size);
+                if Items[Index].Selected then
+                  Dec(FFilesSelSize, Size);
+              end;
+
               Items[Index].Delete;
             end;
           end;
@@ -2014,6 +2022,8 @@ begin
             if AnyUpdate and Assigned(OnDirUpdated) then
               OnDirUpdated(Self);
 
+            UpdateStatusBar;
+
             Screen.Cursor := SaveCursor;
           end;
         end; {Finally}

+ 12 - 1
packages/theme/ThemeMgr.pas

@@ -624,6 +624,7 @@ var
   L, H,
   I, C: Integer;
   Dummy: TWindowProcEntry;
+  NeedSort: Boolean;
 
 begin
   // First try the cached data to speed up retrieval.
@@ -634,7 +635,8 @@ begin
   end
   else
   begin
-    if FDirty and (Count > 1) then
+    NeedSort := FDirty and (Count > 1);
+    if NeedSort then
     begin
       Sort(Compare);
       FDirty := False;
@@ -665,6 +667,15 @@ begin
     begin
       FLastControl := Control;
       FLastIndex := L;
+    end
+      else
+    begin
+      // even if lookup failed, we need to clear cache as we were forced to resort
+      if NeedSort then
+      begin
+        FLastControl := nil;
+        FLastIndex := -1;
+      end;
     end;
   end;
 end;

+ 1 - 1
release/winscp.u3i

@@ -1,6 +1,6 @@
 <?xml version="1.0"?>
 <u3manifest version="1.0">
-  <application uuid="48b341d1-d411-4b5a-a82c-f3b5d65602fc" version="4.1.7">
+  <application uuid="48b341d1-d411-4b5a-a82c-f3b5d65602fc" version="4.1.8">
     <icon>winscp.ico</icon>
     <name>WinSCP</name>
     <description>Freeware SFTP (SSH File Transfer Protocol), FTP (File Transfer Protocol) and SCP (Secure CoPy) client for Windows using SSH (Secure SHell). Its main function is safe copying of files between a local and a remote computer.</description>

+ 0 - 2
windows/GUIConfiguration.cpp

@@ -542,7 +542,6 @@ void __fastcall TGUIConfiguration::Default()
 
   FIgnoreCancelBeforeFinish = TDateTime(0, 0, 3, 0);
   FCopyParamDialogExpanded = false;
-  FErrorDialogExpanded = false;
   FContinueOnError = false;
   FConfirmCommandSession = true;
   FSynchronizeParams = TTerminal::spNoConfirmation | TTerminal::spPreviewChanges;
@@ -617,7 +616,6 @@ AnsiString __fastcall TGUIConfiguration::PropertyToKey(const AnsiString Property
 #define REGCONFIG(CANCREATE) \
   BLOCK("Interface", CANCREATE, \
     KEY(Bool,     CopyParamDialogExpanded); \
-    KEY(Bool,     ErrorDialogExpanded); \
     KEY(Bool,     ContinueOnError); \
     KEY(Bool,     ConfirmCommandSession); \
     KEY(Integer,  SynchronizeParams); \

+ 0 - 2
windows/GUIConfiguration.h

@@ -145,7 +145,6 @@ class TGUIConfiguration : public TConfiguration
 {
 private:
   bool FCopyParamDialogExpanded;
-  bool FErrorDialogExpanded;
   TStrings * FLocales;
   AnsiString FLastLocalesExts;
   bool FContinueOnError;
@@ -214,7 +213,6 @@ public:
   HANDLE __fastcall ChangeResourceModule(HANDLE Instance);
 
   __property bool CopyParamDialogExpanded = { read = FCopyParamDialogExpanded, write = FCopyParamDialogExpanded };
-  __property bool ErrorDialogExpanded = { read = FErrorDialogExpanded, write = FErrorDialogExpanded };
   __property bool ContinueOnError = { read = FContinueOnError, write = FContinueOnError };
   __property bool ConfirmCommandSession = { read = FConfirmCommandSession, write = FConfirmCommandSession };
   __property int SynchronizeParams = { read = FSynchronizeParams, write = FSynchronizeParams };

+ 0 - 16
windows/WinInterface.cpp

@@ -3,7 +3,6 @@
 #pragma hdrstop
 
 #include <shlwapi.h>
-#include <MoreButton.hpp>
 
 #include <Common.h>
 #include <Exceptions.h>
@@ -338,15 +337,6 @@ TForm * __fastcall CreateMessageDialogEx(const AnsiString Msg,
 //---------------------------------------------------------------------------
 int __fastcall ExecuteMessageDialog(TForm * Dialog, int Answers, const TMessageParams * Params)
 {
-  TMoreButton * MoreButton = dynamic_cast<TMoreButton *>(Dialog->FindComponent("MoreButton"));
-  if (MoreButton != NULL)
-  {
-    // WinConfiguration may be destroyed already, if called from
-    // try ... catch statement of main()
-    MoreButton->Expanded = (GUIConfiguration != NULL) &&
-      GUIConfiguration->ErrorDialogExpanded;
-  }
-
   FlashOnBackground();
   int Answer = MapResult(Dialog->ShowModal(), Answers);
 
@@ -369,12 +359,6 @@ int __fastcall ExecuteMessageDialog(TForm * Dialog, int Answers, const TMessageP
     }
   }
 
-  if ((MoreButton != NULL) && (GUIConfiguration != NULL))
-  {
-    // store state even when user selects 'Cancel'?
-    GUIConfiguration->ErrorDialogExpanded = MoreButton->Expanded;
-  }
-
   return Answer;
 }
 //---------------------------------------------------------------------------