Martin Prikryl 17 years ago
parent
commit
37daa48fa7

+ 4 - 4
Console.rc

@@ -1,6 +1,6 @@
 1 VERSIONINFO
-FILEVERSION 2,0,0,87
-PRODUCTVERSION 2,0,0,87
+FILEVERSION 2,0,0,88
+PRODUCTVERSION 2,0,0,88
 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.0.0.87\0"
+            VALUE "FileVersion", "2.0.0.88\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.1.0\0"
+            VALUE "ProductVersion", "4.1.2.0\0"
             VALUE "WWW", "http://winscp.net/\0"
         }
     }

+ 4 - 4
DragExt.rc

@@ -1,6 +1,6 @@
 1 VERSIONINFO
-FILEVERSION 1,1,7,84
-PRODUCTVERSION 1,1,7,84
+FILEVERSION 1,1,7,85
+PRODUCTVERSION 1,1,7,85
 FILEOS 0x4
 FILETYPE 0x2
 {
@@ -10,13 +10,13 @@ FILETYPE 0x2
         {
             VALUE "CompanyName", "Martin Prikryl\0"
             VALUE "FileDescription", "Drag&Drop shell extension for WinSCP\0"
-            VALUE "FileVersion", "1.1.7.84\0"
+            VALUE "FileVersion", "1.1.7.85\0"
             VALUE "InternalName", "dragext\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.1.0\0"
+            VALUE "ProductVersion", "4.1.2.0\0"
             VALUE "WWW", "http://winscp.net/\0"
         }
     }

+ 4 - 4
DragExt64.rc

@@ -1,6 +1,6 @@
 1 VERSIONINFO
-FILEVERSION 1,1,7,84
-PRODUCTVERSION 1,1,7,84
+FILEVERSION 1,1,7,85
+PRODUCTVERSION 1,1,7,85
 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.7.84\0"
+            VALUE "FileVersion", "1.1.7.85\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.1.0\0"
+            VALUE "ProductVersion", "4.1.2.0\0"
             VALUE "WWW", "http://winscp.net/\0"
         }
     }

+ 5 - 5
WinSCP.rc

@@ -1,6 +1,6 @@
 1 VERSIONINFO
-FILEVERSION 4,1,1,385
-PRODUCTVERSION 4,1,1,385
+FILEVERSION 4,1,2,388
+PRODUCTVERSION 4,1,2,388
 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.1.385\0"
+            VALUE "FileVersion", "4.1.2.388\0"
             VALUE "InternalName", "winscp\0"
             VALUE "LegalCopyright", "(c) 2000-2008 Martin Prikryl\0"
             VALUE "LegalTrademarks", "\0"
-            VALUE "OriginalFilename", "winscp411.exe\0"
+            VALUE "OriginalFilename", "winscp412.exe\0"
             VALUE "ProductName", "WinSCP\0"
-            VALUE "ProductVersion", "4.1.1.0\0"
+            VALUE "ProductVersion", "4.1.2.0\0"
             VALUE "WWW", "http://winscp.net/\0"
         }
     }

+ 0 - 9
core/PuttyIntf.cpp

@@ -53,15 +53,6 @@ void __fastcall DontSaveRandomSeed()
   SaveRandomSeed = false;
 }
 //---------------------------------------------------------------------------
-bool __fastcall IsListenerFree(unsigned int PortNumber)
-{
-  Socket socket =
-    sk_newlistener(NULL, PortNumber, NULL, true, ADDRTYPE_IPV4);
-  bool Result = (sk_socket_error(socket) == NULL);
-  sk_close(socket);
-  return Result;
-}
-//---------------------------------------------------------------------------
 int __fastcall ProtocolByName(const AnsiString & Name)
 {
   int Protocol = 0; // raw

+ 0 - 2
core/PuttyTools.h

@@ -11,8 +11,6 @@ AnsiString __fastcall EncodeUTF(const WideString Source);
 //---------------------------------------------------------------------------
 __int64 __fastcall ParseSize(AnsiString SizeStr);
 //---------------------------------------------------------------------------
-bool __fastcall IsListenerFree(unsigned int PortNumber);
-//---------------------------------------------------------------------------
 bool __fastcall HasGSSAPI();
 //---------------------------------------------------------------------------
 #endif

+ 23 - 13
core/Terminal.cpp

@@ -24,6 +24,10 @@
 #include "Security.h"
 #include "CoreMain.h"
 #include "Queue.h"
+
+#ifndef AUTO_WINSOCK
+#include <winsock2.h>
+#endif
 //---------------------------------------------------------------------------
 #pragma package(smart_init)
 //---------------------------------------------------------------------------
@@ -321,9 +325,6 @@ void __fastcall TTunnelUI::Closed()
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
-std::set<int> TTerminal::FTunnelLocalPorts;
-TCriticalSection TTerminal::FSection;
-//---------------------------------------------------------------------------
 __fastcall TTerminal::TTerminal(TSessionData * SessionData,
   TConfiguration * Configuration)
 {
@@ -645,6 +646,24 @@ void __fastcall TTerminal::Open()
   }
 }
 //---------------------------------------------------------------------------
+bool __fastcall TTerminal::IsListenerFree(unsigned int PortNumber)
+{
+  SOCKET Socket = socket(AF_INET, SOCK_STREAM, 0);
+  bool Result = (Socket != INVALID_SOCKET);
+  if (Result)
+  {
+    SOCKADDR_IN Address;
+
+    memset(&Address, 0, sizeof(Address));
+    Address.sin_family = AF_INET;
+    Address.sin_port = htons(static_cast<short>(PortNumber));
+    Address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+    Result = (bind(Socket, reinterpret_cast<sockaddr *>(&Address), sizeof(Address)) == 0);
+    closesocket(Socket);
+  }
+  return Result;
+}
+//---------------------------------------------------------------------------
 void __fastcall TTerminal::OpenTunnel()
 {
   assert(FTunnelData == NULL);
@@ -652,14 +671,8 @@ void __fastcall TTerminal::OpenTunnel()
   FTunnelLocalPortNumber = FSessionData->TunnelLocalPortNumber;
   if (FTunnelLocalPortNumber == 0)
   {
-    TGuard Guard(&FSection);
-
     FTunnelLocalPortNumber = Configuration->TunnelLocalPortNumberLow;
-    // override strange bug in STL
-    #pragma warn -8092
-    while ((FTunnelLocalPorts.find(FTunnelLocalPortNumber) != FTunnelLocalPorts.end()) ||
-           !IsListenerFree(FTunnelLocalPortNumber))
-    #pragma warn .8092
+    while (!IsListenerFree(FTunnelLocalPortNumber))
     {
       FTunnelLocalPortNumber++;
       if (FTunnelLocalPortNumber > Configuration->TunnelLocalPortNumberHigh)
@@ -669,7 +682,6 @@ void __fastcall TTerminal::OpenTunnel()
           (Configuration->TunnelLocalPortNumberLow, Configuration->TunnelLocalPortNumberHigh)));
       }
     }
-    FTunnelLocalPorts.insert(FTunnelLocalPortNumber);
     LogEvent(FORMAT("Autoselected tunnel local port number %d", (FTunnelLocalPortNumber)));
   }
 
@@ -730,8 +742,6 @@ void __fastcall TTerminal::CloseTunnel()
   SAFE_DESTROY_EX(TSessionLog, FTunnelLog);
   SAFE_DESTROY(FTunnelData);
 
-  TGuard Guard(&FSection);
-  FTunnelLocalPorts.erase(FTunnelLocalPortNumber);
   FTunnelLocalPortNumber = 0;
 }
 //---------------------------------------------------------------------------

+ 1 - 4
core/Terminal.h

@@ -3,7 +3,6 @@
 #define TerminalH
 
 #include <Classes.hpp>
-#include <set>
 
 #include "SessionInfo.h"
 #include "Interface.h"
@@ -143,9 +142,6 @@ friend class TFTPFileSystem;
 friend class TTunnelUI;
 
 private:
-  typedef std::set<int> Ports;
-  static Ports FTunnelLocalPorts;
-  static TCriticalSection FSection;
   TSessionData * FSessionData;
   TSessionLog * FLog;
   TConfiguration * FConfiguration;
@@ -313,6 +309,7 @@ protected:
     AnsiString Name, AnsiString Instructions, TStrings * Prompts, TStrings * Results);
   virtual void __fastcall DisplayBanner(const AnsiString & Banner);
   virtual void __fastcall Closed();
+  bool __fastcall IsListenerFree(unsigned int PortNumber);
 
   __property TFileOperationProgressType * OperationProgress = { read=FOperationProgress };
 

+ 15 - 12
forms/CustomScpExplorer.cpp

@@ -3216,21 +3216,24 @@ void __fastcall TCustomScpExplorerForm::DoSynchronize(
   const TSynchronizeParamType & Params, TSynchronizeChecklist ** Checklist,
   TSynchronizeOptions * Options, bool Full)
 {
-  try
+  if (Terminal->Status == ssOpened)
   {
-    int PParams = Params.Params;
-    if (!Full)
+    try
     {
-      PParams |= TTerminal::spNoRecurse | TTerminal::spUseCache |
-        TTerminal::spDelayProgress | TTerminal::spSubDirs;
+      int PParams = Params.Params;
+      if (!Full)
+      {
+        PParams |= TTerminal::spNoRecurse | TTerminal::spUseCache |
+          TTerminal::spDelayProgress | TTerminal::spSubDirs;
+      }
+      Synchronize(LocalDirectory, RemoteDirectory, smRemote, CopyParam,
+        PParams, Checklist, Options);
+    }
+    catch(Exception & E)
+    {
+      ShowExtendedExceptionEx(Terminal, &E);
+      throw;
     }
-    Synchronize(LocalDirectory, RemoteDirectory, smRemote, CopyParam,
-      PParams, Checklist, Options);
-  }
-  catch(Exception & E)
-  {
-    ShowExtendedExceptionEx(Terminal, &E);
-    throw;
   }
 }
 //---------------------------------------------------------------------------

+ 10 - 10
forms/Login.dfm

@@ -876,7 +876,7 @@ object LoginDialog: TLoginDialog
             Height = 21
             Style = csDropDownList
             Anchors = [akLeft, akTop, akRight]
-            ItemHeight = 0
+            ItemHeight = 13
             TabOrder = 0
           end
           object SFTPBugSignedTSCombo: TComboBox
@@ -886,7 +886,7 @@ object LoginDialog: TLoginDialog
             Height = 21
             Style = csDropDownList
             Anchors = [akLeft, akTop, akRight]
-            ItemHeight = 0
+            ItemHeight = 13
             TabOrder = 1
           end
         end
@@ -2285,7 +2285,7 @@ object LoginDialog: TLoginDialog
             Height = 21
             Style = csDropDownList
             Anchors = [akLeft, akTop, akRight]
-            ItemHeight = 0
+            ItemHeight = 13
             TabOrder = 0
             OnChange = DataChange
           end
@@ -2296,7 +2296,7 @@ object LoginDialog: TLoginDialog
             Height = 21
             Style = csDropDownList
             Anchors = [akLeft, akTop, akRight]
-            ItemHeight = 0
+            ItemHeight = 13
             TabOrder = 1
             OnChange = DataChange
           end
@@ -2307,7 +2307,7 @@ object LoginDialog: TLoginDialog
             Height = 21
             Style = csDropDownList
             Anchors = [akLeft, akTop, akRight]
-            ItemHeight = 0
+            ItemHeight = 13
             TabOrder = 2
             OnChange = DataChange
           end
@@ -2318,7 +2318,7 @@ object LoginDialog: TLoginDialog
             Height = 21
             Style = csDropDownList
             Anchors = [akLeft, akTop, akRight]
-            ItemHeight = 0
+            ItemHeight = 13
             TabOrder = 3
             OnChange = DataChange
           end
@@ -2329,7 +2329,7 @@ object LoginDialog: TLoginDialog
             Height = 21
             Style = csDropDownList
             Anchors = [akLeft, akTop, akRight]
-            ItemHeight = 0
+            ItemHeight = 13
             TabOrder = 4
             OnChange = DataChange
           end
@@ -2340,7 +2340,7 @@ object LoginDialog: TLoginDialog
             Height = 21
             Style = csDropDownList
             Anchors = [akLeft, akTop, akRight]
-            ItemHeight = 0
+            ItemHeight = 13
             TabOrder = 5
             OnChange = DataChange
           end
@@ -2351,7 +2351,7 @@ object LoginDialog: TLoginDialog
             Height = 21
             Style = csDropDownList
             Anchors = [akLeft, akTop, akRight]
-            ItemHeight = 0
+            ItemHeight = 13
             TabOrder = 6
             OnChange = DataChange
           end
@@ -2362,7 +2362,7 @@ object LoginDialog: TLoginDialog
             Height = 21
             Style = csDropDownList
             Anchors = [akLeft, akTop, akRight]
-            ItemHeight = 0
+            ItemHeight = 13
             TabOrder = 7
             OnChange = DataChange
           end

+ 43 - 11
packages/filemng/DirView.pas

@@ -1737,6 +1737,7 @@ var
   PSrec: ^SysUtils.TSearchRec;
   Dummy: Integer;
   ItemIndex: Integer;
+  AnyUpdate: Boolean;
   PUpdate: Boolean;
   PEFile: PEFileRec;
   SaveCursor: TCursor;
@@ -1748,6 +1749,8 @@ var
   AttrExcludeMask: Integer;
   FileSel: Boolean;
   FSize: Int64;
+  FocusedIsVisible: Boolean;
+  R: TRect;
 
   procedure AddToMasks(Attr: TSelAttr; Mask: Word);
   begin
@@ -1771,6 +1774,28 @@ begin
       end
         else
       begin
+        if Assigned(ItemFocused) then
+        begin
+          R := ItemFocused.DisplayRect(drBounds);
+          // btw, we use vsReport only, nothing else was tested
+          Assert(ViewStyle = vsReport);
+          case ViewStyle of
+            vsReport:
+              FocusedIsVisible := (TopItem.Index <= ItemFocused.Index) and
+                (ItemFocused.Index < TopItem.Index + VisibleRowCount);
+
+            vsList:
+              // do not know how to implement that
+              FocusedIsVisible := False;
+
+            else // vsIcon and vsSmallIcon
+              FocusedIsVisible :=
+                IntersectRect(R,
+                  Rect(ViewOrigin, Point(ViewOrigin.X + ClientWidth, ViewOrigin.Y + ClientHeight)),
+                  ItemFocused.DisplayRect(drBounds));
+          end;
+        end;
+
         SaveCursor := Screen.Cursor;
         Screen.Cursor := crHourGlass;
         FChangeTimer.Enabled  := False;
@@ -1781,6 +1806,7 @@ begin
         NewItems := TStringlist.Create;
 
         PUpdate := False;
+        AnyUpdate := False;
         TempMask := Mask;
 
         AttrIncludeMask := 0;
@@ -1873,11 +1899,10 @@ begin
                       if (iSize <> FSize) and Assigned(OnFileSizeChanged) then
                         OnFileSizeChanged(Self, Items[iIndex]);
                     end;
-                    if not PUpdate then
-                    begin
-                      PUpdate := True;
-                      Items.BeginUpdate;
-                    end;
+                    // alternative to TListItem.Update (which causes flicker)
+                    R := Items[iIndex].DisplayRect(drBounds);
+                    InvalidateRect(Handle, @R, True);
+                    AnyUpdate := True;
                   end;
                 end;
               end;
@@ -1933,6 +1958,7 @@ begin
                 PUpdate := True;
                 Items.BeginUpdate;
               end;
+              AnyUpdate := True;
               Items[Index].Delete;
             end;
           end;
@@ -1950,6 +1976,7 @@ begin
                 PUpdate := True;
                 Items.BeginUpdate;
               end;
+              AnyUpdate := True;
               PSrec := Pointer(NewItems.Objects[Index]);
               {$IFNDEF NO_THREADS}
               NewItem :=
@@ -1962,12 +1989,16 @@ begin
               Dispose(PSrec);
             end;
             NewItems.Free;
-            if PUpdate then
+            // if we are sorted by name and there were only updates to existing
+            // items, there is no need for sorting
+            if SortAfterUpdate and
+               (PUpdate or
+                (AnyUpdate and (DirColProperties.SortDirColumn <> dvName))) then
             begin
-              if SortAfterUpdate then
-                SortItems;
-              Items.EndUpdate;
+              SortItems;
             end;
+            if PUpdate then
+              Items.EndUpdate;
           finally
             FDirOK := True;
             FDirty := false;
@@ -1976,9 +2007,10 @@ begin
               StartIconUpdateThread;
             StartWatchThread;
 {$ENDIF}
-            if Assigned(ItemFocused) then
+            // make focused item visible, only if it was before
+            if FocusedIsVisible and Assigned(ItemFocused) then
               ItemFocused.MakeVisible(False);
-            if PUpdate and Assigned(OnDirUpdated) then
+            if AnyUpdate and Assigned(OnDirUpdated) then
               OnDirUpdated(Self);
 
             Screen.Cursor := SaveCursor;

+ 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.1">
+  <application uuid="48b341d1-d411-4b5a-a82c-f3b5d65602fc" version="4.1.2">
     <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>

+ 24 - 0
windows/ConsoleRunner.cpp

@@ -674,6 +674,7 @@ class TConsoleRunner
 {
 public:
   TConsoleRunner(TConsole * Console);
+  ~TConsoleRunner();
 
   int __fastcall Run(const AnsiString Session, TOptions * Options,
     TStrings * ScriptCommands);
@@ -697,6 +698,7 @@ private:
   bool FCommandError;
   bool FBatchScript;
   bool FAborted;
+  TTimer * Timer;
 
   void __fastcall ScriptPrint(TScript * Script, const AnsiString Str);
   void __fastcall ScriptPrintProgress(TScript * Script, bool First, const AnsiString Str);
@@ -725,6 +727,7 @@ private:
   void __fastcall SynchronizeControllerTooManyDirectories(TSynchronizeController * Sender,
     int & MaxDirectories);
   unsigned int InputTimeout();
+  void __fastcall TimerTimer(TObject * Sender);
 };
 //---------------------------------------------------------------------------
 TConsoleRunner::TConsoleRunner(TConsole * Console) :
@@ -737,6 +740,21 @@ TConsoleRunner::TConsoleRunner(TConsole * Console) :
   FScript = NULL;
   FAborted = false;
   FBatchScript = false;
+  Timer = new TTimer(Application);
+  Timer->OnTimer = TimerTimer;
+  Timer->Interval = 1000;
+  Timer->Enabled = true;
+}
+//---------------------------------------------------------------------------
+TConsoleRunner::~TConsoleRunner()
+{
+  delete Timer;
+}
+//---------------------------------------------------------------------------
+void __fastcall TConsoleRunner::TimerTimer(TObject * /*Sender*/)
+{
+  // sole presence of timer causes message to be dispatched,
+  // hence breaks the loops
 }
 //---------------------------------------------------------------------------
 unsigned int TConsoleRunner::InputTimeout()
@@ -1220,6 +1238,7 @@ void __fastcall TConsoleRunner::ScriptSynchronizeStartStop(TScript * /*Script*/,
     while (!FSynchronizeAborted && !Aborted(false))
     {
       Application->HandleMessage();
+      FScript->Terminal->Idle();
     }
   }
   __finally
@@ -1392,6 +1411,11 @@ int __fastcall TConsoleRunner::Run(const AnsiString Session, TOptions * Options,
               Result = false;
             }
           }
+
+          if (FScript->Terminal != NULL)
+          {
+            FScript->Terminal->Idle();
+          }
         }
       }
       while (Result && FScript->Continue && !Aborted());

+ 26 - 23
windows/SynchronizeController.cpp

@@ -134,41 +134,44 @@ void __fastcall TSynchronizeController::SynchronizeChange(
       TSynchronizeChecklist * Checklist = NULL;
       FOnSynchronize(this, LocalDirectory, RemoteDirectory, FCopyParam,
         FSynchronizeParams, &Checklist, Options, false);
-      try
+      if (Checklist != NULL)
       {
-        if (FLAGSET(FSynchronizeParams.Options, soRecurse))
+        try
         {
-          SubdirsChanged = false;
-          assert(Checklist != NULL);
-          for (int Index = 0; Index < Checklist->Count; Index++)
+          if (FLAGSET(FSynchronizeParams.Options, soRecurse))
           {
-            const TSynchronizeChecklist::TItem * Item = Checklist->Item[Index];
-            // note that there may be action saDeleteRemote even if nothing has changed
-            // so this is sub-optimal
-            if (Item->IsDirectory)
+            SubdirsChanged = false;
+            assert(Checklist != NULL);
+            for (int Index = 0; Index < Checklist->Count; Index++)
             {
-              if ((Item->Action == TSynchronizeChecklist::saUploadNew) ||
-                  (Item->Action == TSynchronizeChecklist::saDeleteRemote))
+              const TSynchronizeChecklist::TItem * Item = Checklist->Item[Index];
+              // note that there may be action saDeleteRemote even if nothing has changed
+              // so this is sub-optimal
+              if (Item->IsDirectory)
               {
-                SubdirsChanged = true;
-                break;
-              }
-              else
-              {
-                assert(false);
+                if ((Item->Action == TSynchronizeChecklist::saUploadNew) ||
+                    (Item->Action == TSynchronizeChecklist::saDeleteRemote))
+                {
+                  SubdirsChanged = true;
+                  break;
+                }
+                else
+                {
+                  assert(false);
+                }
               }
             }
           }
+          else
+          {
+            SubdirsChanged = false;
+          }
         }
-        else
+        __finally
         {
-          SubdirsChanged = false;
+          delete Checklist;
         }
       }
-      __finally
-      {
-        delete Checklist;
-      }
     }
   }
   catch(Exception & E)

+ 1 - 4
windows/VCLCommon.cpp

@@ -282,10 +282,7 @@ void __fastcall InitializeSystemSettings()
 //---------------------------------------------------------------------------
 void __fastcall FinalizeSystemSettings()
 {
-  if (ThemeManager != NULL)
-  {
-    SAFE_DESTROY(ThemeManager);
-  }
+  // deliberately do not destroy ThemeManager to avoid faults [[bug>226]]
 }
 //---------------------------------------------------------------------------
 // Settings that must be set as soon as possible.