Martin Prikryl 19 years ago
parent
commit
d86a8d80da
55 changed files with 1040 additions and 344 deletions
  1. 5 5
      Console.bpr
  2. BIN
      Console.res
  3. 3 3
      DragExt.bpr
  4. BIN
      DragExt.res
  5. 5 5
      WinSCP3.bpr
  6. BIN
      WinSCP3.res
  7. 0 22
      components/DesignInterface.cpp
  8. 5 5
      components/UnixDirView.cpp
  9. 103 68
      console/Main.cpp
  10. 129 1
      core/Common.cpp
  11. 5 1
      core/Common.h
  12. 1 0
      core/FileSystems.h
  13. 5 0
      core/ScpFileSystem.cpp
  14. 1 0
      core/ScpFileSystem.h
  15. 3 3
      core/Script.cpp
  16. 2 2
      core/Script.h
  17. 29 20
      core/SecureShell.cpp
  18. 11 11
      core/SecureShell.h
  19. 7 1
      core/SessionData.cpp
  20. 1 1
      core/SessionData.h
  21. 7 2
      core/SftpFileSystem.cpp
  22. 1 0
      core/SftpFileSystem.h
  23. 11 6
      core/Terminal.cpp
  24. 3 2
      core/Terminal.h
  25. 6 31
      forms/CopyParams.cpp
  26. 0 1
      forms/CopyParams.h
  27. 2 1
      forms/CustomScpExplorer.cpp
  28. 1 1
      forms/CustomScpExplorer.h
  29. 1 1
      forms/FullSynchronize.dfm
  30. 1 1
      forms/Log.cpp
  31. 14 0
      forms/Login.cpp
  32. 15 15
      forms/Login.dfm
  33. 14 14
      forms/Login.h
  34. 1 0
      forms/NonVisual.cpp
  35. 40 0
      forms/NonVisual.dfm
  36. 12 0
      forms/NonVisual.h
  37. 3 0
      forms/Preferences.cpp
  38. 6 7
      forms/Preferences.dfm
  39. 2 2
      forms/Preferences.h
  40. 1 0
      forms/Progress.cpp
  41. 7 1
      forms/Properties.cpp
  42. 136 30
      forms/Rights.cpp
  43. 318 53
      forms/Rights.dfm
  44. 11 1
      forms/Rights.h
  45. 10 1
      forms/RightsExt.cpp
  46. 1 0
      forms/ScpExplorer.dfm
  47. 1 0
      forms/Synchronize.cpp
  48. 7 3
      forms/SynchronizeChecklist.cpp
  49. 0 1
      forms/SynchronizeChecklist.dfm
  50. 1 0
      forms/SynchronizeProgress.cpp
  51. 1 0
      packages/my/PathLabel.hpp
  52. 10 7
      packages/my/PathLabel.pas
  53. 12 3
      release/winscpsetup.iss
  54. 49 2
      windows/ConsoleRunner.cpp
  55. 20 10
      windows/WinMain.cpp

+ 5 - 5
Console.bpr

@@ -54,9 +54,9 @@
 IncludeVerInfo=1
 AutoIncBuild=1
 MajorVer=1
-MinorVer=3
-Release=1
-Build=64
+MinorVer=4
+Release=0
+Build=67
 Debug=0
 PreRelease=0
 Special=0
@@ -68,13 +68,13 @@ CodePage=1252
 [Version Info Keys]
 CompanyName=Martin Prikryl
 FileDescription=Console interface for WinSCP
-FileVersion=1.3.1.64
+FileVersion=1.4.0.67
 InternalName=console
 LegalCopyright=(c) 2004-2006 Martin Prikryl
 LegalTrademarks=
 OriginalFilename=winscp3.com
 ProductName=WinSCP
-ProductVersion=3.8.1.0
+ProductVersion=3.8.2.0
 Comments=
 WWW=http://winscp.net/
 

BIN
Console.res


+ 3 - 3
DragExt.bpr

@@ -57,7 +57,7 @@ AutoIncBuild=1
 MajorVer=1
 MinorVer=1
 Release=5
-Build=66
+Build=67
 Debug=0
 PreRelease=0
 Special=0
@@ -69,13 +69,13 @@ CodePage=1252
 [Version Info Keys]
 CompanyName=Martin Prikryl
 FileDescription=Drag&Drop shell extension for WinSCP
-FileVersion=1.1.5.66
+FileVersion=1.1.5.67
 InternalName=dragext
 LegalCopyright=(c) 2004-2006 Martin Prikryl
 LegalTrademarks=
 OriginalFilename=dragext.dll
 ProductName=WinSCP
-ProductVersion=3.8.1.0
+ProductVersion=3.8.2.0
 Comments=
 WWW=http://winscp.net/
 

BIN
DragExt.res


+ 5 - 5
WinSCP3.bpr

@@ -94,8 +94,8 @@ IncludeVerInfo=1
 AutoIncBuild=1
 MajorVer=3
 MinorVer=8
-Release=1
-Build=327
+Release=2
+Build=330
 Debug=0
 PreRelease=0
 Special=0
@@ -107,13 +107,13 @@ CodePage=1252
 [Version Info Keys]
 CompanyName=Martin Prikryl
 FileDescription=Windows SFTP/SCP client
-FileVersion=3.8.1.327
+FileVersion=3.8.2.330
 InternalName=winscp3
 LegalCopyright=(c) 2000-2006 Martin Prikryl
 LegalTrademarks=
-OriginalFilename=winscp381.exe
+OriginalFilename=winscp382.exe
 ProductName=WinSCP
-ProductVersion=3.8.1.0
+ProductVersion=3.8.2.0
 WWW=http://winscp.net/
 
 [Compiler]

BIN
WinSCP3.res


+ 0 - 22
components/DesignInterface.cpp

@@ -1,22 +0,0 @@
-//---------------------------------------------------------------------------
-#include <vcl.h>
-#pragma hdrstop
-
-#include <Interface.h>
-//---------------------------------------------------------------------------
-#pragma package(smart_init)
-//---------------------------------------------------------------------------
-void __fastcall ShowExtendedException(Exception* E, TObject* Sender)
-{
-  HandleExtendedException(E, Sender);
-}
-//---------------------------------------------------------------------------
-void __fastcall HandleExtendedException(Exception* E, TObject* Sender)
-{
-  Application->ShowException(E);
-}
-//---------------------------------------------------------------------------
-void ConfirmHostKey(int UnknownKey, char *host, int port, char *keytype,
-  char *keystr, char *fingerprint)
-{
-}

+ 5 - 5
components/UnixDirView.cpp

@@ -56,8 +56,8 @@ int __stdcall CompareDirectories(TListItem *Item1, TListItem *Item2, TUnixDirVie
   return 0;
 }
 //---------------------------------------------------------------------------
-#define DEFINE_COMPARE_FUNC_EX(PROPERTY, COMPAREFUNC, FALLBACK) \
-  int __stdcall Compare ## PROPERTY(TListItem *Item1, TListItem *Item2, TUnixDirView *DirView) \
+#define DEFINE_COMPARE_FUNC_EX(PROPERTY, NAME, COMPAREFUNC, FALLBACK) \
+  int __stdcall Compare ## NAME(TListItem *Item1, TListItem *Item2, TUnixDirView *DirView) \
   { \
     int Result = CompareDirectories(Item1, Item2, DirView); \
     if (!Result) \
@@ -72,11 +72,11 @@ int __stdcall CompareDirectories(TListItem *Item1, TListItem *Item2, TUnixDirVie
     return Result; \
   }
 #define DEFINE_COMPARE_FUNC(PROPERTY, COMPAREFUNC) \
-  DEFINE_COMPARE_FUNC_EX(PROPERTY, COMPAREFUNC, AnsiCompareText)
+  DEFINE_COMPARE_FUNC_EX(PROPERTY, PROPERTY, COMPAREFUNC, AnsiCompareText)
 #define COMPARE_NUMBER(Num1, Num2) ( Num1 < Num2 ? -1 : ( Num1 > Num2 ? 1 : 0) )
 #define COMPARE_DUMMY(X1, X2) 0
 //---------------------------------------------------------------------------
-DEFINE_COMPARE_FUNC_EX(FileName, AnsiCompareText, COMPARE_DUMMY);
+DEFINE_COMPARE_FUNC_EX(FileName, ItemFileName, AnsiCompareText, COMPARE_DUMMY);
 DEFINE_COMPARE_FUNC(Size, COMPARE_NUMBER);
 DEFINE_COMPARE_FUNC(Modification, COMPARE_NUMBER);
 DEFINE_COMPARE_FUNC(RightsStr, AnsiCompareText);
@@ -627,7 +627,7 @@ void __fastcall TUnixDirView::SortItems()
   {
     PFNLVCOMPARE SortProc;
     switch (SortColumn) {
-      case uvName: SortProc = (PFNLVCOMPARE)CompareFileName; break;
+      case uvName: SortProc = (PFNLVCOMPARE)CompareItemFileName; break;
       case uvSize: SortProc = (PFNLVCOMPARE)CompareSize; break;
       case uvChanged: SortProc = (PFNLVCOMPARE)CompareModification; break;
       case uvRights: SortProc = (PFNLVCOMPARE)CompareRightsStr; break;

+ 103 - 68
console/Main.cpp

@@ -12,6 +12,7 @@ HANDLE ConsoleInput = NULL;
 HANDLE Child = NULL;
 HANDLE CancelEvent = NULL;
 unsigned int OutputType = FILE_TYPE_UNKNOWN;
+unsigned int InputType = FILE_TYPE_UNKNOWN;
 enum { RESULT_GLOBAL_ERROR = 1, RESULT_INIT_ERROR = 2, RESULT_PROCESSING_ERROR = 3,
   RESULT_UNKNOWN_ERROR = 4 };
 const char * CONSOLE_CHILD_PARAM = "consolechild";
@@ -198,7 +199,7 @@ static char LastFromBeginning[sizeof(TConsoleCommStruct::TPrintEvent)] = "";
 //---------------------------------------------------------------------------
 inline void Print(bool FromBeginning, const char * Message)
 {
-  if (((OutputType == FILE_TYPE_DISK) || (OutputType == FILE_TYPE_PIPE)))
+  if ((OutputType == FILE_TYPE_DISK) || (OutputType == FILE_TYPE_PIPE))
   {
     if (FromBeginning && (Message[0] != '\n'))
     {
@@ -240,99 +241,132 @@ inline void ProcessPrintEvent(TConsoleCommStruct::TPrintEvent& Event)
 //---------------------------------------------------------------------------
 void ProcessInputEvent(TConsoleCommStruct::TInputEvent& Event)
 {
-  unsigned long PrevMode, NewMode;
-  GetConsoleMode(ConsoleInput, &PrevMode);
-  NewMode = PrevMode | ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT;
-  if (Event.Echo)
+  if ((InputType == FILE_TYPE_DISK) || (InputType == FILE_TYPE_PIPE))
   {
-    NewMode |= ENABLE_ECHO_INPUT;
+    unsigned long Len = 0;
+    unsigned long Read;
+    char Ch;
+    bool Result;
+    
+    while (((Result = (ReadFile(ConsoleInput, &Ch, 1, &Read, NULL) != 0)) != false) &&
+           (Read > 0) && (Len < sizeof(Event.Str) - 1) && (Ch != '\n'))
+    {
+      if (Ch != '\r')
+      {
+        Event.Str[Len] = Ch;
+        Len++;
+      }
+    }
+    Event.Str[Len] = '\0';
+
+    Print(false, Event.Str);
+    Print(false, "\n");
+
+    Event.Result = ((Result && (Read > 0)) || (Len > 0));
   }
   else
   {
-    NewMode &= ~ENABLE_ECHO_INPUT;
-  }
-  SetConsoleMode(ConsoleInput, NewMode);
-
-  try
-  {
-    unsigned long Read;
-    Event.Result = ReadConsole(ConsoleInput, Event.Str, sizeof(Event.Str) - 1, &Read, NULL);
-    Event.Str[Read] = '\0';
-
-    bool PendingCancel = (WaitForSingleObject(CancelEvent, 0) == WAIT_OBJECT_0);
-    if (PendingCancel || !Event.Echo)
+    unsigned long PrevMode, NewMode;
+    GetConsoleMode(ConsoleInput, &PrevMode);
+    NewMode = PrevMode | ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT;
+    if (Event.Echo)
     {
-      printf("\n");
+      NewMode |= ENABLE_ECHO_INPUT;
     }
-
-    if (PendingCancel || (Read == 0))
+    else
     {
-      Event.Result = false;
+      NewMode &= ~ENABLE_ECHO_INPUT;
     }
+    SetConsoleMode(ConsoleInput, NewMode);
 
-    SetConsoleMode(ConsoleInput, PrevMode);
-  }
-  catch(...)
-  {
-    SetConsoleMode(ConsoleInput, PrevMode);
-    throw;
+    try
+    {
+      unsigned long Read;
+      Event.Result = ReadConsole(ConsoleInput, Event.Str, sizeof(Event.Str) - 1, &Read, NULL);
+      Event.Str[Read] = '\0';
+
+      bool PendingCancel = (WaitForSingleObject(CancelEvent, 0) == WAIT_OBJECT_0);
+      if (PendingCancel || !Event.Echo)
+      {
+        printf("\n");
+      }
+
+      if (PendingCancel || (Read == 0))
+      {
+        Event.Result = false;
+      }
+
+      SetConsoleMode(ConsoleInput, PrevMode);
+    }
+    catch(...)
+    {
+      SetConsoleMode(ConsoleInput, PrevMode);
+      throw;
+    }
   }
 }
 //---------------------------------------------------------------------------
 void ProcessChoiceEvent(TConsoleCommStruct::TChoiceEvent& Event)
 {
-  Event.Result = 0;
+  if ((InputType == FILE_TYPE_DISK) || (InputType == FILE_TYPE_PIPE))
+  {
+    Event.Result = Event.Cancel;
+  }
+  else
+  {
+    Event.Result = 0;
 
-  unsigned long PrevMode, NewMode;
-  GetConsoleMode(ConsoleInput, &PrevMode);
-  NewMode = (PrevMode | ENABLE_PROCESSED_INPUT) & ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
-  SetConsoleMode(ConsoleInput, NewMode);
+    unsigned long PrevMode, NewMode;
+    GetConsoleMode(ConsoleInput, &PrevMode);
+    NewMode = (PrevMode | ENABLE_PROCESSED_INPUT) & ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
+    SetConsoleMode(ConsoleInput, NewMode);
 
-  try
-  {
-    do
+    try
     {
-      unsigned long Read;
-      INPUT_RECORD Record;
-      if ((ReadConsoleInput(ConsoleInput, &Record, 1, &Read) != 0) &&
-          (Read == 1))
+      do
       {
-        bool PendingCancel = (WaitForSingleObject(CancelEvent, 0) == WAIT_OBJECT_0);
-        if (PendingCancel)
-        {
-          Event.Result = Event.Break;
-        }
-        else if ((Record.EventType == KEY_EVENT) &&
-                 Record.Event.KeyEvent.bKeyDown)
+        unsigned long Read;
+        INPUT_RECORD Record;
+        if ((ReadConsoleInput(ConsoleInput, &Record, 1, &Read) != 0) &&
+            (Read == 1))
         {
-          char CStr[2];
-          CStr[0] = Record.Event.KeyEvent.uChar.AsciiChar;
-          CStr[1] = '\0';
-          CharUpperBuff(CStr, 1);
-          char C = CStr[0];
-          if (C == 27)
+          bool PendingCancel = (WaitForSingleObject(CancelEvent, 0) == WAIT_OBJECT_0);
+          if (PendingCancel)
           {
-            Event.Result = Event.Cancel;
+            Event.Result = Event.Break;
           }
-          else if ((strchr(Event.Options, C) != NULL) &&
-                   ((Record.Event.KeyEvent.dwControlKeyState &
-                     (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED | LEFT_ALT_PRESSED |
-                     RIGHT_CTRL_PRESSED)) == 0))
-
+          else if ((Record.EventType == KEY_EVENT) &&
+                   Record.Event.KeyEvent.bKeyDown)
           {
-            Event.Result = strchr(Event.Options, C) - Event.Options + 1;
+            char CStr[2];
+            CStr[0] = Record.Event.KeyEvent.uChar.AsciiChar;
+            CStr[1] = '\0';
+            CharUpperBuff(CStr, 1);
+            char C = CStr[0];
+            if (C == 27)
+            {
+              Event.Result = Event.Cancel;
+            }
+            else if ((strchr(Event.Options, C) != NULL) &&
+                     ((Record.Event.KeyEvent.dwControlKeyState &
+                       (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED | LEFT_ALT_PRESSED |
+                       RIGHT_CTRL_PRESSED)) == 0))
+
+            {
+              Event.Result = strchr(Event.Options, C) - Event.Options + 1;
+            }
           }
         }
       }
-    }
-    while (Event.Result == 0);
+      while (Event.Result == 0);
 
-    SetConsoleMode(ConsoleInput, PrevMode);
-  }
-  catch(...)
-  {
-    SetConsoleMode(ConsoleInput, PrevMode);
-    throw;
+      SetConsoleMode(ConsoleInput, PrevMode);
+    }
+    catch(...)
+    {
+      SetConsoleMode(ConsoleInput, PrevMode);
+      throw;
+    }
   }
 }
 //---------------------------------------------------------------------------
@@ -416,6 +450,7 @@ int main(int argc, char* argv[])
     randomize();
 
     ConsoleInput = GetStdHandle(STD_INPUT_HANDLE);
+    InputType = GetFileType(ConsoleInput);
     SetConsoleCtrlHandler(HandlerRoutine, true);
 
     HANDLE ConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);

+ 129 - 1
core/Common.cpp

@@ -21,7 +21,7 @@ void __fastcall Trace(const AnsiString SourceFile, const AnsiString Func,
   const char * FileName = getenv(TRACEENV);
   if (FileName == NULL)
   {
-    FileName = "C:\\winscptrace.log";
+    FileName = "c:\\winscptrace.log";
   }
   FILE * File = fopen(FileName, "a");
   if (File != NULL)
@@ -983,6 +983,33 @@ int __fastcall AbortAnswer(int Answers)
   return Result;
 }
 //---------------------------------------------------------------------------
+int __fastcall ContinueAnswer(int Answers)
+{
+  int Result;
+  if (FLAGSET(Answers, qaSkip))
+  {
+    Result = qaSkip;
+  }
+  else if (FLAGSET(Answers, qaIgnore))
+  {
+    Result = qaIgnore;
+  }
+  else if (FLAGSET(Answers, qaYes))
+  {
+    Result = qaYes;
+  }
+  else if (FLAGSET(Answers, qaOK))
+  {
+    Result = qaOK;
+  }
+  else
+  {
+    assert(false);
+    Result = CancelAnswer(Answers);
+  }
+  return Result;
+}
+//---------------------------------------------------------------------------
 TPasLibModule * __fastcall FindModule(void * Instance)
 {
   TPasLibModule * CurModule;
@@ -1088,3 +1115,104 @@ void __fastcall AnsiToOem(AnsiString & Str)
     CharToOem(Str.c_str(), Str.c_str());
   }
 }
+//---------------------------------------------------------------------------
+struct TUnicodeEmitParams
+{
+  WideString Buffer;
+  int Pos;
+  int Len;
+};
+//---------------------------------------------------------------------------
+extern "C" void UnicodeEmit(void * AParams, long int Output)
+{
+  if (Output == 0xFFFFL) // see Putty's charset\internal.h
+  {
+    throw Exception(LoadStr(DECODE_UTF_ERROR));
+  }
+  TUnicodeEmitParams * Params = (TUnicodeEmitParams *)AParams;
+  if (Params->Pos >= Params->Len)
+  {
+    Params->Len += 50;
+    Params->Buffer.SetLength(Params->Len);
+  }
+  Params->Pos++;
+  Params->Buffer[Params->Pos] = (wchar_t)Output;
+}
+//---------------------------------------------------------------------------
+AnsiString __fastcall DecodeUTF(const AnsiString UTF)
+{
+  charset_state State;
+  char * Str;
+  TUnicodeEmitParams Params;
+  AnsiString Result;
+
+  State.s0 = 0;
+  Str = UTF.c_str();
+  Params.Pos = 0;
+  Params.Len = UTF.Length();
+  Params.Buffer.SetLength(Params.Len);
+
+  while (*Str)
+  {
+    read_utf8(NULL, (unsigned char)*Str, &State, UnicodeEmit, &Params);
+    Str++;
+  }
+  Params.Buffer.SetLength(Params.Pos);
+
+  return Params.Buffer;
+}
+//---------------------------------------------------------------------------
+struct TUnicodeEmitParams2
+{
+  AnsiString Buffer;
+  int Pos;
+  int Len;
+};
+//---------------------------------------------------------------------------
+extern "C" void UnicodeEmit2(void * AParams, long int Output)
+{
+  if (Output == 0xFFFFL) // see Putty's charset\internal.h
+  {
+    throw Exception(LoadStr(DECODE_UTF_ERROR));
+  }
+  TUnicodeEmitParams2 * Params = (TUnicodeEmitParams2 *)AParams;
+  if (Params->Pos >= Params->Len)
+  {
+    Params->Len += 50;
+    Params->Buffer.SetLength(Params->Len);
+  }
+  Params->Pos++;
+  Params->Buffer[Params->Pos] = (unsigned char)Output;
+}
+//---------------------------------------------------------------------------
+AnsiString __fastcall EncodeUTF(const WideString Source)
+{
+  // WideString::c_bstr() returns NULL for empty strings
+  // (as opposite to AnsiString::c_str() which returns "")
+  if (Source.IsEmpty())
+  {
+    return "";
+  }
+  else
+  {
+    charset_state State;
+    wchar_t * Str;
+    TUnicodeEmitParams2 Params;
+    AnsiString Result;
+
+    State.s0 = 0;
+    Str = Source.c_bstr();
+    Params.Pos = 0;
+    Params.Len = Source.Length();
+    Params.Buffer.SetLength(Params.Len);
+
+    while (*Str)
+    {
+      write_utf8(NULL, (wchar_t)*Str, &State, UnicodeEmit2, &Params);
+      Str++;
+    }
+    Params.Buffer.SetLength(Params.Pos);
+
+    return Params.Buffer;
+  }
+}

+ 5 - 1
core/Common.h

@@ -9,7 +9,8 @@
 #define SCOPY(dest, source) \
   strncpy(dest, source, sizeof(dest)); \
   dest[sizeof(dest)-1] = '\0'
-#define SAFE_DESTROY(OBJ) { TObject * PObj = OBJ; OBJ = NULL; delete PObj; }
+#define SAFE_DESTROY_EX(CLASS, OBJ) { CLASS * PObj = OBJ; OBJ = NULL; delete PObj; }
+#define SAFE_DESTROY(OBJ) SAFE_DESTROY_EX(TObject, OBJ)
 #define ASCOPY(dest, source) SCOPY(dest, source.c_str())
 #define FORMAT(S, F) Format(S, ARRAYOFCONST(F))
 #define FMTLOAD(I, F) FmtLoadStr(I, ARRAYOFCONST(F))
@@ -36,6 +37,8 @@ AnsiString DelimitStr(AnsiString Str, AnsiString Chars);
 AnsiString ShellDelimitStr(AnsiString Str, char Quote);
 void __fastcall OemToAnsi(AnsiString & Str);
 void __fastcall AnsiToOem(AnsiString & Str);
+AnsiString __fastcall DecodeUTF(const AnsiString UTF);
+AnsiString __fastcall EncodeUTF(const WideString Source);
 AnsiString ExceptionLogString(Exception *E);
 bool IsDots(const AnsiString Str);
 AnsiString __fastcall SystemTemporaryDirectory();
@@ -59,6 +62,7 @@ AnsiString __fastcall EncodeUrlChars(AnsiString S, AnsiString Ignore = "");
 bool __fastcall RecursiveDeleteFile(const AnsiString FileName, bool ToRecycleBin);
 int __fastcall CancelAnswer(int Answers);
 int __fastcall AbortAnswer(int Answers);
+int __fastcall ContinueAnswer(int Answers);
 AnsiString __fastcall LoadStr(int Ident, unsigned int MaxLength);
 AnsiString __fastcall LoadStrPart(int Ident, int Part);
 struct TPasLibModule;

+ 1 - 0
core/FileSystems.h

@@ -71,6 +71,7 @@ public:
   virtual TStrings * __fastcall GetFixedPaths() = 0;
   virtual void __fastcall SpaceAvailable(const AnsiString Path,
     TSpaceAvailable & ASpaceAvailable) = 0;
+  virtual bool __fastcall TemporaryTransferFile(const AnsiString & FileName) = 0;
 
   __property AnsiString CurrentDirectory = { read = GetCurrentDirectory, write = SetCurrentDirectory };
   __property AnsiString ProtocolName = { read = GetProtocolName };

+ 5 - 0
core/ScpFileSystem.cpp

@@ -288,6 +288,11 @@ AnsiString __fastcall TSCPFileSystem::GetProtocolName() const
   return "SCP";
 }
 //---------------------------------------------------------------------------
+bool __fastcall TSCPFileSystem::TemporaryTransferFile(const AnsiString & /*FileName*/)
+{
+  return false;
+}
+//---------------------------------------------------------------------------
 AnsiString __fastcall TSCPFileSystem::AbsolutePath(AnsiString Path)
 {
   AnsiString Result;

+ 1 - 0
core/ScpFileSystem.h

@@ -55,6 +55,7 @@ public:
   virtual TStrings * __fastcall GetFixedPaths();
   virtual void __fastcall SpaceAvailable(const AnsiString Path,
     TSpaceAvailable & ASpaceAvailable);
+  virtual bool __fastcall TemporaryTransferFile(const AnsiString & FileName);
 
 protected:
   __property TStrings * Output = { read = FOutput };

+ 3 - 3
core/Script.cpp

@@ -991,8 +991,8 @@ void __fastcall TScript::OptionImpl(AnsiString OptionName, AnsiString ValueName)
   enum { Off, On };
   static const char * ToggleNames[] = { "off", "on" };
 
-  assert((BatchOff == 0) && (BatchOn == 1) && (BatchAbort == 2));
-  static const char * BatchModeNames[] = { "off", "on", "abort" };
+  assert((BatchOff == 0) && (BatchOn == 1) && (BatchAbort == 2) && (BatchContinue == 3));
+  static const char * BatchModeNames[] = { "off", "on", "abort", "continue" };
 
   assert((tmBinary == 0) && (tmAscii == 1) && (tmAutomatic == 2));
   static const char * TransferModeNames[] = { "binary", "ascii", "automatic" };
@@ -1531,7 +1531,7 @@ void __fastcall TManagementScript::TerminalOperationFinished(
 //---------------------------------------------------------------------------
 void __fastcall TManagementScript::TerminalSynchronizeDirectory(
   const AnsiString LocalDirectory, const AnsiString RemoteDirectory,
-  bool & Continue)
+  bool & Continue, bool /*Collect*/)
 {
   int SynchronizeMode = FSynchronizeMode;
   if (FKeepingUpToDate)

+ 2 - 2
core/Script.h

@@ -40,7 +40,7 @@ private:
 class TScript
 {
 public:
-  enum TBatchMode { BatchOff, BatchOn, BatchAbort };
+  enum TBatchMode { BatchOff, BatchOn, BatchAbort, BatchContinue };
 
   __fastcall TScript();
   __fastcall TScript(TTerminal * Terminal);
@@ -182,7 +182,7 @@ protected:
   void __fastcall PrintProgress(bool First, const AnsiString Str);
   bool __fastcall QueryCancel();
   void __fastcall TerminalSynchronizeDirectory(const AnsiString LocalDirectory,
-    const AnsiString RemoteDirectory, bool & Continue);
+    const AnsiString RemoteDirectory, bool & Continue, bool Collect);
   void __fastcall DoConnect(const AnsiString Session);
   void __fastcall DoClose(TTerminal * Terminal);
   virtual bool __fastcall HandleExtendedException(Exception * E,

+ 29 - 20
core/SecureShell.cpp

@@ -1358,7 +1358,8 @@ __fastcall TSessionLog::TSessionLog(TSecureShell * AOwner): TStringList()
   FFile = NULL;
   FLoggedLines = 0;
   FTopIndex = -1;
-  FFileName = "";
+  FCurrentLogFileName = "";
+  FCurrentFileName = "";
   FId = 0;
 }
 //---------------------------------------------------------------------------
@@ -1406,7 +1407,7 @@ TLogLineType __fastcall TSessionLog::GetType(Integer Index)
 void __fastcall TSessionLog::DoAdd(TLogLineType aType, AnsiString aLine)
 {
   assert(Configuration);
-  if (IsLogging())
+  if (Logging)
   {
     try
     {
@@ -1503,8 +1504,12 @@ void __fastcall TSessionLog::SetConfiguration(TConfiguration * value)
 //---------------------------------------------------------------------------
 void __fastcall TSessionLog::ReflectSettings()
 {
+  FLogging = (FConfiguration->Logging || (OnAddLine != NULL));
   // if logging to file was turned off or log file was change -> close current log file
-  if (FFile && (!LogToFile || (FFileName != LogFileName))) CloseLogFile();
+  if (FFile && (!LogToFile() || (FCurrentLogFileName != FConfiguration->LogFileName)))
+  {
+    CloseLogFile();
+  }
   // we used to open log file here, now it is posponed until first call to DoAdd()
   // this allows TSecureShell to change the Id sooner.
   DeleteUnnecessary();
@@ -1519,10 +1524,9 @@ void __fastcall TSessionLog::SetEnabled(bool value)
   }
 }
 //---------------------------------------------------------------------------
-Boolean __fastcall TSessionLog::GetLogToFile()
+bool __fastcall TSessionLog::LogToFile()
 {
-  return Enabled && (Configuration != NULL) && Configuration->Logging &&
-    Configuration->LogToFile;
+  return (FConfiguration != NULL) && FConfiguration->Logging && FConfiguration->LogToFile;
 }
 //---------------------------------------------------------------------------
 void __fastcall TSessionLog::CloseLogFile()
@@ -1532,18 +1536,20 @@ void __fastcall TSessionLog::CloseLogFile()
     fclose((FILE *)FFile);
     FFile = NULL;
   }
-  FFileName = "";
+  FCurrentLogFileName = "";
+  FCurrentFileName = "";
 }
 //---------------------------------------------------------------------------
 void TSessionLog::OpenLogFile()
 {
-  if (LogToFile)
+  if (LogToFile())
   {
     try
     {
       assert(!FFile);
       assert(Configuration);
-      AnsiString NewFileName = LogFileName;
+      FCurrentLogFileName = FConfiguration->LogFileName;
+      AnsiString NewFileName = StripPathQuotes(FCurrentLogFileName);
       TDateTime N = Now();
       for (int Index = 1; Index < NewFileName.Length(); Index++)
       {
@@ -1598,7 +1604,7 @@ void TSessionLog::OpenLogFile()
       if (FFile)
       {
         setvbuf((FILE *)FFile, NULL, _IONBF, BUFSIZ);
-        FFileName = NewFileName;
+        FCurrentFileName = NewFileName;
       }
       else
       {
@@ -1607,8 +1613,9 @@ void TSessionLog::OpenLogFile()
     }
     catch (Exception &E)
     {
-      // We failed logging to file, turn it of and notify user.
-      FFileName = "";
+      // We failed logging to file, turn it off and notify user.
+      FCurrentLogFileName = "";
+      FCurrentFileName = "";
       Configuration->LogToFile = false;
       try
       {
@@ -1755,7 +1762,7 @@ int __fastcall TSessionLog::GetIndexes(int Index)
 {
   assert((Index >= 0) && (Index < Count));
   int Result = TopIndex + Index;
-  assert((Result >= 0) && (Result < LoggedLines));
+  assert((Result >= 0) && (Result < FLoggedLines));
   return Result;
 }
 //---------------------------------------------------------------------------
@@ -1764,13 +1771,6 @@ int __fastcall TSessionLog::GetBottomIndex()
   return (Count ? Indexes[Count-1] : -1);
 }
 //---------------------------------------------------------------------------
-AnsiString __fastcall TSessionLog::GetLogFileName()
-{
-  assert(Configuration);
-  AnsiString Result = StripPathQuotes(Configuration->LogFileName);
-  return Result;
-}
-//---------------------------------------------------------------------------
 Boolean __fastcall TSessionLog::GetLoggingToFile()
 {
   return
@@ -1782,3 +1782,12 @@ void __fastcall TSessionLog::Clear()
   FTopIndex += Count;
   TStringList::Clear();
 }
+//---------------------------------------------------------------------------
+void __fastcall TSessionLog::SetOnAddLine(TLogAddLineEvent value)
+{
+  if (OnAddLine != value)
+  {
+    FOnAddLine = value;
+    ReflectSettings();
+  }
+}

+ 11 - 11
core/SecureShell.h

@@ -53,8 +53,10 @@ private:
   TSecureShell * FOwner;
   TConfiguration * FConfiguration;
   bool FEnabled;
+  bool FLogging;
   void * FFile;
-  AnsiString FFileName;
+  AnsiString FCurrentLogFileName;
+  AnsiString FCurrentFileName;
   Integer FLoggedLines;
   TLogAddLineEvent FOnAddLine;
   Integer FTopIndex;
@@ -71,11 +73,11 @@ private:
   Integer __fastcall GetIndexes(Integer Index);
   AnsiString __fastcall GetLogFileName();
   Boolean __fastcall GetLoggingToFile();
-  Boolean __fastcall GetLogToFile();
   void __fastcall SetEnabled(bool value);
   void __fastcall SetConfiguration(TConfiguration * value);
   AnsiString __fastcall GetSessionName();
   void __fastcall DoAdd(TLogLineType aType, AnsiString aLine);
+  void __fastcall SetOnAddLine(TLogAddLineEvent value);
 
 public:
   __fastcall TSessionLog(TSecureShell * AOwner);
@@ -88,11 +90,8 @@ public:
     const AnsiString AddedLine);
   virtual void __fastcall Clear();
   void __fastcall ReflectSettings();
-  bool __fastcall inline IsLogging()
-  {
-    return Enabled && (Configuration->Logging || (OnAddLine != NULL));
-  }
 
+  __property bool Logging = { read = FLogging };
   __property Integer BottomIndex = { read = GetBottomIndex };
   __property AnsiString Line[Integer Index]  = { read=GetLine, write=SetLine };
   __property TLogLineType Type[Integer Index]  = { read=GetType, write=SetType };
@@ -101,16 +100,17 @@ public:
   __property OnChange;
   __property bool Enabled = { read = FEnabled, write = SetEnabled };
   __property Integer Indexes[Integer Index] = { read = GetIndexes };
-  __property AnsiString LogFileName = { read = GetLogFileName };
-  __property Integer LoggedLines = { read = FLoggedLines };
+  __property AnsiString CurrentFileName = { read = FCurrentFileName };
   __property Boolean LoggingToFile = { read = GetLoggingToFile };
-  __property TLogAddLineEvent OnAddLine = { read = FOnAddLine, write = FOnAddLine };
+  __property TLogAddLineEvent OnAddLine = { read = FOnAddLine, write = SetOnAddLine };
   __property Integer TopIndex = { read = FTopIndex };
   __property AnsiString SessionName = { read = GetSessionName };
   __property unsigned int Id = { read = FId, write = FId };
+  __property Count;
+
 protected:
   void __fastcall CloseLogFile();
-  __property Boolean LogToFile = { read = GetLogToFile };
+  bool __fastcall LogToFile();
 };
 //---------------------------------------------------------------------------
 #ifndef PuttyIntfH
@@ -256,7 +256,7 @@ public:
 
   bool __fastcall inline IsLogging()
   {
-    return Log->IsLogging();
+    return Log->Logging;
   }
   void __fastcall PuttyLogEvent(const AnsiString & Str);
   void __fastcall inline LogEvent(const AnsiString & Str)

+ 7 - 1
core/SessionData.cpp

@@ -1811,7 +1811,8 @@ void __fastcall TStoredSessionList::ImportHostKeys(const AnsiString TargetKey,
 }
 //---------------------------------------------------------------------------
 TSessionData * __fastcall TStoredSessionList::ParseUrl(AnsiString Url,
-  bool & DefaultsOnly, int Params, AnsiString * FileName)
+  bool & DefaultsOnly, int Params, AnsiString * FileName,
+  bool * AProtocolDefined)
 {
   bool ProtocolDefined = false;
   TFSProtocol Protocol;
@@ -1828,6 +1829,11 @@ TSessionData * __fastcall TStoredSessionList::ParseUrl(AnsiString Url,
     ProtocolDefined = true;
   }
 
+  if (AProtocolDefined != NULL)
+  {
+    *AProtocolDefined = ProtocolDefined;
+  }
+
   DefaultsOnly = true;
   TSessionData * Data = new TSessionData("");
   try

+ 1 - 1
core/SessionData.h

@@ -330,7 +330,7 @@ public:
   int __fastcall IndexOf(TSessionData * Data);
   TSessionData * __fastcall NewSession(AnsiString SessionName, TSessionData * Session);
   TSessionData * __fastcall ParseUrl(AnsiString Url, bool & DefaultsOnly,
-    int Params, AnsiString * FileName = NULL);
+    int Params, AnsiString * FileName = NULL, bool * ProtocolDefined = NULL);
   virtual __fastcall ~TStoredSessionList();
   __property TSessionData * Sessions[int Index]  = { read=AtSession };
   __property TSessionData * DefaultSettings  = { read=FDefaultSettings, write=SetDefaultSettings };

+ 7 - 2
core/SftpFileSystem.cpp

@@ -311,7 +311,7 @@ public:
 
   inline void AddUtfString(const AnsiString Value)
   {
-    AddString(TSFTPFileSystem::EncodeUTF(Value));
+    AddString(EncodeUTF(Value));
   }
 
   inline void AddString(const AnsiString Value, bool Utf)
@@ -512,7 +512,7 @@ public:
 
   inline AnsiString GetUtfString()
   {
-    return TSFTPFileSystem::DecodeUTF(GetString());
+    return DecodeUTF(GetString());
   }
 
   inline AnsiString GetString(bool Utf)
@@ -1458,6 +1458,11 @@ __fastcall TSFTPFileSystem::~TSFTPFileSystem()
   delete FFixedPaths;
 }
 //---------------------------------------------------------------------------
+bool __fastcall TSFTPFileSystem::TemporaryTransferFile(const AnsiString & FileName)
+{
+  return AnsiSameText(UnixExtractFileExt(FileName), PARTIAL_EXT);
+}
+//---------------------------------------------------------------------------
 void __fastcall TSFTPFileSystem::ResetConnection()
 {
   // there must be no valid packet reservation at the end

+ 1 - 0
core/SftpFileSystem.h

@@ -65,6 +65,7 @@ public:
   virtual TStrings * __fastcall GetFixedPaths();
   virtual void __fastcall SpaceAvailable(const AnsiString Path,
     TSpaceAvailable & ASpaceAvailable);
+  virtual bool __fastcall TemporaryTransferFile(const AnsiString & FileName);
 
 protected:
   int FVersion;

+ 11 - 6
core/Terminal.cpp

@@ -2615,7 +2615,7 @@ void __fastcall TTerminal::DoSynchronizeCollectDirectory(const AnsiString LocalD
 
   if (FLAGCLEAR(Params, spDelayProgress))
   {
-    DoSynchronizeProgress(Data);
+    DoSynchronizeProgress(Data, true);
   }
 
   try
@@ -2650,6 +2650,7 @@ void __fastcall TTerminal::DoSynchronizeCollectDirectory(const AnsiString LocalD
           if ((FileName != ".") && (FileName != "..") &&
               CopyParam->AllowTransfer(Data.LocalDirectory + FileName, osLocal,
                 FLAGSET(SearchRec.Attr, faDirectory), MaskParams) &&
+              !FFileSystem->TemporaryTransferFile(FileName) &&
               (FLAGCLEAR(Flags, sfFirstLevel) ||
                (Options == NULL) || (Options->Filter == NULL) ||
                Options->Filter->Find(FileName, FoundIndex)))
@@ -2690,7 +2691,7 @@ void __fastcall TTerminal::DoSynchronizeCollectDirectory(const AnsiString LocalD
 
       if (!Cached && FLAGSET(Params, spDelayProgress))
       {
-        DoSynchronizeProgress(Data);
+        DoSynchronizeProgress(Data, true);
       }
 
       ProcessDirectory(RemoteDirectory, SynchronizeCollectFile, &Data,
@@ -2788,6 +2789,7 @@ void __fastcall TTerminal::SynchronizeCollectFile(const AnsiString FileName,
   if (Data->CopyParam->AllowTransfer(
         UnixExcludeTrailingBackslash(File->FullFileName), osRemote,
         File->IsDirectory, MaskParams) &&
+      !FFileSystem->TemporaryTransferFile(File->FileName) &&
       (FLAGCLEAR(Data->Flags, sfFirstLevel) ||
        (Data->Options == NULL) || (Data->Options->Filter == NULL) ||
         Data->Options->Filter->Find(File->FileName, FoundIndex)))
@@ -3054,7 +3056,7 @@ void __fastcall TTerminal::SynchronizeApply(TSynchronizeChecklist * Checklist,
       {
         Data.LocalDirectory = IncludeTrailingBackslash(CurrentLocalDirectory);
         Data.RemoteDirectory = UnixIncludeTrailingBackslash(CurrentRemoteDirectory);
-        DoSynchronizeProgress(Data);
+        DoSynchronizeProgress(Data, false);
 
         if (FLAGSET(Params, spTimestamp))
         {
@@ -3110,12 +3112,14 @@ void __fastcall TTerminal::SynchronizeApply(TSynchronizeChecklist * Checklist,
   }
 }
 //---------------------------------------------------------------------------
-void __fastcall TTerminal::DoSynchronizeProgress(const TSynchronizeData & Data)
+void __fastcall TTerminal::DoSynchronizeProgress(const TSynchronizeData & Data,
+  bool Collect)
 {
   if (Data.OnSynchronizeDirectory != NULL)
   {
     bool Continue = true;
-    Data.OnSynchronizeDirectory(Data.LocalDirectory, Data.RemoteDirectory, Continue);
+    Data.OnSynchronizeDirectory(Data.LocalDirectory, Data.RemoteDirectory,
+      Continue, Collect);
 
     if (!Continue)
     {
@@ -3408,7 +3412,8 @@ bool __fastcall TSecondaryTerminal::DoPromptUser(AnsiString Prompt,
 {
   bool Result = false;
 
-  if (!FMasterPasswordTried && (Kind != pkPrompt))
+  if (!FMasterPasswordTried &&
+      ((Kind == pkPassword) || (Kind == pkPassphrase) || (Kind == pkServerPrompt)))
   {
     // let's expect that the main session is already authenticated and its password
     // is not written after, so no locking is necessary

+ 3 - 2
core/Terminal.h

@@ -31,7 +31,8 @@ typedef void __fastcall (__closure *TProcessFileEventEx)
 typedef int __fastcall (__closure *TFileOperationEvent)
   (void * Param1, void * Param2);
 typedef void __fastcall (__closure *TSynchronizeDirectory)
-  (const AnsiString LocalDirectory, const AnsiString RemoteDirectory, bool & Continue);
+  (const AnsiString LocalDirectory, const AnsiString RemoteDirectory,
+   bool & Continue, bool Collect);
 typedef void __fastcall (__closure *TDeleteLocalFileEvent)(const AnsiString FileName);
 typedef int __fastcall (__closure *TDirectoryModifiedEvent)
   (TTerminal * Terminal, const AnsiString Directory, bool SubDirs);
@@ -236,7 +237,7 @@ protected:
     const TRemoteFile * File, void * Param);
   void __fastcall SynchronizeLocalTimestamp(const AnsiString FileName,
     const TRemoteFile * File, void * Param);
-  void __fastcall DoSynchronizeProgress(const TSynchronizeData & Data);
+  void __fastcall DoSynchronizeProgress(const TSynchronizeData & Data, bool Collect);
   void __fastcall DeleteLocalFile(AnsiString FileName,
     const TRemoteFile * File, void * Param);
   void __fastcall RecycleFile(AnsiString FileName, const TRemoteFile * File);

+ 6 - 31
forms/CopyParams.cpp

@@ -22,8 +22,6 @@
 __fastcall TCopyParamsFrame::TCopyParamsFrame(TComponent* Owner)
         : TFrame(Owner)
 {
-  FAddXToDirectoriesSuffix = "+x";
-
   FRightsFrame = new TRightsExtFrame(this);
   FRightsFrame->TabStop = false;
   FRightsFrame->Parent = this;
@@ -32,6 +30,7 @@ __fastcall TCopyParamsFrame::TCopyParamsFrame(TComponent* Owner)
   FRightsFrame->Popup = true;
   FRightsFrame->PopupParent = RightsEdit;
   FRightsFrame->OnChange = RightsFrameChange;
+  RightsEdit->PopupMenu = FRightsFrame->RightsPopup;
 
   // on start set different value than we want to allow property-setter to proceed
   FDirection = pdToLocal;
@@ -275,12 +274,7 @@ void __fastcall TCopyParamsFrame::RightsEditButtonClick(TObject * Sender)
 //---------------------------------------------------------------------------
 void __fastcall TCopyParamsFrame::RightsFrameChange(TObject * /*Sender*/)
 {
-  AnsiString RightsStr = FRightsFrame->Rights.Text;
-  if (FRightsFrame->AddXToDirectories)
-  {
-    RightsStr = FORMAT("%s (%s)", (RightsStr, FAddXToDirectoriesSuffix));
-  }
-  RightsEdit->Text = RightsStr;
+  RightsEdit->Text = FRightsFrame->Text;
   RightsEdit->Modified = false;
   RightsEdit->SelectAll();
 }
@@ -289,29 +283,10 @@ void __fastcall TCopyParamsFrame::UpdateRightsByStr()
 {
   if (!RightsEdit->Text.IsEmpty())
   {
-    AnsiString RightsStr = RightsEdit->Text;
-
-    int P = RightsStr.LowerCase().Pos(FAddXToDirectoriesSuffix);
-    bool AddXToDirectories = (P > 0);
-    if (AddXToDirectories)
-    {
-      RightsStr.Delete(P, FAddXToDirectoriesSuffix.Length());
-    }
-    RightsStr = DeleteChar(DeleteChar(RightsStr, '('), ')').Trim();
-    TRights R = FRightsFrame->Rights;
-    int Dummy;
-    if (((RightsStr.Length() == 3) || (RightsStr.Length() == 4)) &&
-        TryStrToInt(RightsStr, Dummy))
-    {
-      R.Octal = RightsStr;
-    }
-    else
-    {
-      R.Text = RightsStr;
-    }
-
-    FRightsFrame->Rights = R;
-    FRightsFrame->AddXToDirectories = AddXToDirectories;
+    FRightsFrame->Text = RightsEdit->Text;
+    // change handler may not be called if the rights were not actually changed,
+    // but we want to normalize the user-entered information anyway
+    RightsFrameChange(NULL);
   }
   UpdateControls();
   RightsEdit->Modified = false;

+ 0 - 1
forms/CopyParams.h

@@ -59,7 +59,6 @@ private:
   TCopyParamType * FParams;
   int FCopyParamAttrs;
   TRightsExtFrame * FRightsFrame;
-  AnsiString FAddXToDirectoriesSuffix;
   void __fastcall SetParams(TCopyParamType value);
   TCopyParamType __fastcall GetParams();
   void __fastcall SetDirection(TParamsForDirection value);

+ 2 - 1
forms/CustomScpExplorer.cpp

@@ -3151,7 +3151,8 @@ bool __fastcall TCustomScpExplorerForm::DoFullSynchronizeDirectories(
 }
 //---------------------------------------------------------------------------
 void __fastcall TCustomScpExplorerForm::TerminalSynchronizeDirectory(
-  const AnsiString LocalDirectory, const AnsiString RemoteDirectory, bool & Continue)
+  const AnsiString LocalDirectory, const AnsiString RemoteDirectory,
+  bool & Continue, bool /*Collect*/)
 {
   assert(FSynchronizeProgressForm != NULL);
   if (!FSynchronizeProgressForm->Started)

+ 1 - 1
forms/CustomScpExplorer.h

@@ -264,7 +264,7 @@ protected:
   TStrings * __fastcall CreateVisitedDirectories(TOperationSide Side);
   void __fastcall HandleErrorList(TStringList *& ErrorList);
   void __fastcall TerminalSynchronizeDirectory(const AnsiString LocalDirectory,
-    const AnsiString RemoteDirectory, bool & Continue);
+    const AnsiString RemoteDirectory, bool & Continue, bool Collect);
   void __fastcall DoSynchronize(TSynchronizeController * Sender,
     const AnsiString LocalDirectory, const AnsiString RemoteDirectory,
     const TCopyParamType & CopyParam, const TSynchronizeParamType & Params,

+ 1 - 1
forms/FullSynchronize.dfm

@@ -215,7 +215,7 @@ object FullSynchronizeDialog: TFullSynchronizeDialog
     Top = 184
     Width = 140
     Height = 97
-    Caption = 'Compare criterions'
+    Caption = 'Compare criteria'
     TabOrder = 3
     object SynchronizeByTimeCheck: TCheckBox
       Left = 11

+ 1 - 1
forms/Log.cpp

@@ -158,7 +158,7 @@ void __fastcall TLogForm::UpdateControls()
     if (SessionLog->LoggingToFile)
     {
       Panel->TextTruncation = twPathEllipsis;
-      Panel->Caption = SessionLog->LogFileName;
+      Panel->Caption = SessionLog->CurrentFileName;
     }
     else
     {

+ 14 - 0
forms/Login.cpp

@@ -591,6 +591,7 @@ void __fastcall TLoginDialog::UpdateControls()
       EnableControl(ShellIconsButton, SessionListView->Selected);
 
       EnableControl(PingIntervalSecEdit, !PingOffButton->Checked);
+      EnableControl(PingIntervalLabel, PingIntervalSecEdit->Enabled);
 
       EnableControl(SessionListView, SessionListView->Items->Count);
       AdjustListColumnsWidth(SessionListView);
@@ -612,25 +613,38 @@ void __fastcall TLoginDialog::UpdateControls()
         KexListBox->ItemIndex < KexListBox->Items->Count-1);
 
       EnableControl(BugIgnore1Combo, !SshProt2onlyButton->Checked);
+      EnableControl(BugIgnore1Label, BugIgnore1Combo->Enabled);
       EnableControl(BugPlainPW1Combo, !SshProt2onlyButton->Checked);
+      EnableControl(BugPlainPW1Label, BugPlainPW1Combo->Enabled);
       EnableControl(BugRSA1Combo, !SshProt2onlyButton->Checked);
+      EnableControl(BugRSA1Label, BugRSA1Combo->Enabled);
       EnableControl(BugHMAC2Combo, !SshProt1onlyButton->Checked);
+      EnableControl(BugHMAC2Label, BugHMAC2Combo->Enabled);
       EnableControl(BugDeriveKey2Combo, !SshProt1onlyButton->Checked);
+      EnableControl(BugDeriveKey2Label, BugDeriveKey2Combo->Enabled);
       EnableControl(BugRSAPad2Combo, !SshProt1onlyButton->Checked);
+      EnableControl(BugRSAPad2Label, BugRSAPad2Combo->Enabled);
       EnableControl(BugPKSessID2Combo, !SshProt1onlyButton->Checked);
+      EnableControl(BugPKSessID2Label, BugPKSessID2Combo->Enabled);
       EnableControl(BugRekey2Combo, !SshProt1onlyButton->Checked);
+      EnableControl(BugRekey2Label, BugRekey2Combo->Enabled);
 
       EnableControl(ScpSheet, !ExternalProtocol);
       EnableControl(ShellEdit, ShellEnterButton->Checked && ScpSheet->Enabled);
       EnableControl(ReturnVarEdit, ReturnVarEnterButton->Checked && ScpSheet->Enabled);
 
       EnableControl(ProxyHostEdit, !ProxyNoneButton->Checked);
+      EnableControl(ProxyHostLabel, ProxyHostEdit->Enabled);
       EnableControl(ProxyPortEdit, !ProxyNoneButton->Checked);
+      EnableControl(ProxyPortLabel, ProxyPortEdit->Enabled);
       EnableControl(ProxyUsernameEdit, !ProxyNoneButton->Checked);
+      EnableControl(ProxyUsernameLabel, ProxyUsernameEdit->Enabled);
       EnableControl(ProxyPasswordEdit, !ProxyNoneButton->Checked &&
         !ProxySocks4Button->Checked);
+      EnableControl(ProxyPasswordLabel, ProxyPasswordEdit->Enabled);
       EnableControl(ProxySettingsGroup, !ProxyNoneButton->Checked);
       EnableControl(ProxyTelnetCommandEdit, ProxyTelnetButton->Checked);
+      EnableControl(ProxyTelnetCommandLabel, ProxyTelnetCommandEdit->Enabled);
 
       EnableControl(DirectoriesSheet, !ExternalProtocol);
       DirectoryOptionsGroup->Visible = ShowAdvancedLoginOptionsCheck->Checked;

+ 15 - 15
forms/Login.dfm

@@ -378,7 +378,7 @@ object LoginDialog: TLoginDialog
         end
         object ColorButton: TButton
           Left = 271
-          Top = 238
+          Top = 237
           Width = 75
           Height = 25
           Caption = 'Select c&olor'
@@ -1265,7 +1265,7 @@ object LoginDialog: TLoginDialog
           DesignSize = (
             345
             111)
-          object Label6: TLabel
+          object PingIntervalLabel: TLabel
             Left = 12
             Top = 84
             Width = 140
@@ -1380,7 +1380,7 @@ object LoginDialog: TLoginDialog
           DesignSize = (
             345
             136)
-          object Label15: TLabel
+          object ProxyHostLabel: TLabel
             Left = 11
             Top = 41
             Width = 78
@@ -1388,7 +1388,7 @@ object LoginDialog: TLoginDialog
             Caption = 'Pro&xy host name'
             FocusControl = ProxyHostEdit
           end
-          object Label18: TLabel
+          object ProxyPortLabel: TLabel
             Left = 240
             Top = 41
             Width = 57
@@ -1397,7 +1397,7 @@ object LoginDialog: TLoginDialog
             Caption = 'Po&rt number'
             FocusControl = ProxyPortEdit
           end
-          object Label19: TLabel
+          object ProxyUsernameLabel: TLabel
             Left = 11
             Top = 85
             Width = 51
@@ -1405,7 +1405,7 @@ object LoginDialog: TLoginDialog
             Caption = '&User name'
             FocusControl = ProxyUsernameEdit
           end
-          object Label20: TLabel
+          object ProxyPasswordLabel: TLabel
             Left = 163
             Top = 85
             Width = 46
@@ -1513,7 +1513,7 @@ object LoginDialog: TLoginDialog
           DesignSize = (
             345
             108)
-          object Label21: TLabel
+          object ProxyTelnetCommandLabel: TLabel
             Left = 11
             Top = 19
             Width = 79
@@ -1595,7 +1595,7 @@ object LoginDialog: TLoginDialog
           DesignSize = (
             345
             217)
-          object Label22: TLabel
+          object BugIgnore1Label: TLabel
             Left = 12
             Top = 20
             Width = 167
@@ -1603,7 +1603,7 @@ object LoginDialog: TLoginDialog
             Caption = 'Chokes on SSH-1 &ignore messages'
             FocusControl = BugIgnore1Combo
           end
-          object Label23: TLabel
+          object BugPlainPW1Label: TLabel
             Left = 12
             Top = 44
             Width = 192
@@ -1611,7 +1611,7 @@ object LoginDialog: TLoginDialog
             Caption = 'Refuses all SSH-1 pass&word camouflage'
             FocusControl = BugPlainPW1Combo
           end
-          object Label24: TLabel
+          object BugRSA1Label: TLabel
             Left = 12
             Top = 68
             Width = 180
@@ -1619,7 +1619,7 @@ object LoginDialog: TLoginDialog
             Caption = 'Chokes on SSH-1 &RSA authentication'
             FocusControl = BugRSA1Combo
           end
-          object Label25: TLabel
+          object BugHMAC2Label: TLabel
             Left = 12
             Top = 92
             Width = 155
@@ -1627,7 +1627,7 @@ object LoginDialog: TLoginDialog
             Caption = 'Miscomputes SSH-2 H&MAC keys'
             FocusControl = BugHMAC2Combo
           end
-          object Label26: TLabel
+          object BugDeriveKey2Label: TLabel
             Left = 12
             Top = 116
             Width = 173
@@ -1635,7 +1635,7 @@ object LoginDialog: TLoginDialog
             Caption = 'Miscomputes SSH-2 &encryption keys'
             FocusControl = BugDeriveKey2Combo
           end
-          object Label27: TLabel
+          object BugRSAPad2Label: TLabel
             Left = 12
             Top = 140
             Width = 208
@@ -1643,7 +1643,7 @@ object LoginDialog: TLoginDialog
             Caption = 'Requires &padding on SSH-2 RSA signatures'
             FocusControl = BugRSAPad2Combo
           end
-          object Label14: TLabel
+          object BugPKSessID2Label: TLabel
             Left = 12
             Top = 164
             Width = 194
@@ -1651,7 +1651,7 @@ object LoginDialog: TLoginDialog
             Caption = 'Misuses the sessio&n ID in SSH-2 PK auth'
             FocusControl = BugPKSessID2Combo
           end
-          object Label33: TLabel
+          object BugRekey2Label: TLabel
             Left = 12
             Top = 188
             Width = 183

+ 14 - 14
forms/Login.h

@@ -104,30 +104,30 @@ __published:
   TRadioButton *ProxyHTTPButton;
   TRadioButton *ProxySocks4Button;
   TRadioButton *ProxyTelnetButton;
-  TLabel *Label15;
-  TLabel *Label18;
+  TLabel *ProxyHostLabel;
+  TLabel *ProxyPortLabel;
   TUpDownEdit *ProxyPortEdit;
   TEdit *ProxyHostEdit;
   TEdit *ProxyUsernameEdit;
-  TLabel *Label19;
-  TLabel *Label20;
+  TLabel *ProxyUsernameLabel;
+  TLabel *ProxyPasswordLabel;
   TPasswordEdit *ProxyPasswordEdit;
   TXPGroupBox *ProxySettingsGroup;
-  TLabel *Label21;
+  TLabel *ProxyTelnetCommandLabel;
   TEdit *ProxyTelnetCommandEdit;
   TTabSheet *BugsSheet;
   TXPGroupBox *BugsGroupBox;
-  TLabel *Label22;
+  TLabel *BugIgnore1Label;
   TComboBox *BugIgnore1Combo;
-  TLabel *Label23;
+  TLabel *BugPlainPW1Label;
   TComboBox *BugPlainPW1Combo;
-  TLabel *Label24;
+  TLabel *BugRSA1Label;
   TComboBox *BugRSA1Combo;
-  TLabel *Label25;
+  TLabel *BugHMAC2Label;
   TComboBox *BugHMAC2Combo;
-  TLabel *Label26;
+  TLabel *BugDeriveKey2Label;
   TComboBox *BugDeriveKey2Combo;
-  TLabel *Label27;
+  TLabel *BugRSAPad2Label;
   TComboBox *BugRSAPad2Combo;
   TRadioButton *SshProt1onlyButton;
   TRadioButton *SshProt2onlyButton;
@@ -161,7 +161,7 @@ __published:
   TMenuItem *Desktopicon1;
   TAction *SendToHookAction;
   TMenuItem *ExplorersSendtoshortcut1;
-  TLabel *Label14;
+  TLabel *BugPKSessID2Label;
   TComboBox *BugPKSessID2Combo;
   TRadioButton *ProxySocks5Button;
   TCheckBox *ProxyLocalhostCheck;
@@ -177,7 +177,7 @@ __published:
   TButton *SaveButton;
   TButton *LanguagesButton;
   TXPGroupBox *PingGroup;
-  TLabel *Label6;
+  TLabel *PingIntervalLabel;
   TUpDownEdit *PingIntervalSecEdit;
   TRadioButton *PingOffButton;
   TRadioButton *PingNullPacketButton;
@@ -230,7 +230,7 @@ __published:
   TRadioButton *IPAutoButton;
   TRadioButton *IPv4Button;
   TRadioButton *IPv6Button;
-  TLabel *Label33;
+  TLabel *BugRekey2Label;
   TComboBox *BugRekey2Combo;
   TXPGroupBox *SFTPProtocolGroup;
   TLabel *Label34;

+ 1 - 0
forms/NonVisual.cpp

@@ -716,6 +716,7 @@ void __fastcall TNonVisualDataModule::ExplorerShortcuts()
   RemoteOpenDirAction->ShortCut = ShortCut('O', CTRL);
   RemoteRefreshAction->ShortCut = ShortCut(VK_F5, NONE);
   RemoteHomeDirAction->ShortCut = ShortCut('H', CTRL);
+  RemotePathToClipboardAction->ShortCut = ShortCut('P', CTRLSHIFT);
   // selected operation
   CurrentCopyAction->ShortCut = CurrentCopyFocusedAction->ShortCut;
   CurrentMoveAction->ShortCut = CurrentMoveFocusedAction->ShortCut;

+ 40 - 0
forms/NonVisual.dfm

@@ -2292,4 +2292,44 @@ object NonVisualDataModule: TNonVisualDataModule
       Action = CurrentCreateDirAction
     end
   end
+  object RemoteAddressPopup: TTBXPopupMenu
+    Images = GlyphsModule.ExplorerImages
+    Left = 248
+    Top = 400
+    object TBXItem25: TTBXItem
+      Action = RemotePathToClipboardAction
+    end
+    object TBXItem24: TTBXItem
+      Action = RemoteAddBookmarkAction
+    end
+    object TBXSeparatorItem1: TTBXSeparatorItem
+      Hint = 'E'
+    end
+    object TBXItem17: TTBXItem
+      Action = RemoteOpenDirAction
+    end
+    object TBXSubmenuItem2: TTBXSubmenuItem
+      Caption = '&Go To'
+      HelpKeyword = 'task_navigate'
+      Hint = 'Go to directory'
+      object TBXItem18: TTBXItem
+        Action = RemoteParentDirAction
+      end
+      object TBXItem19: TTBXItem
+        Action = RemoteRootDirAction
+      end
+      object TBXItem20: TTBXItem
+        Action = RemoteHomeDirAction
+      end
+      object TBXSeparatorItem2: TTBXSeparatorItem
+        Hint = 'E'
+      end
+      object TBXItem21: TTBXItem
+        Action = RemoteBackAction
+      end
+      object TBXItem22: TTBXItem
+        Action = RemoteForwardAction
+      end
+    end
+  end
 end

+ 12 - 0
forms/NonVisual.h

@@ -462,6 +462,18 @@ __published:    // IDE-managed Components
   TAction *ColorDefaultAction;
   TAction *ColorMenuAction;
   TAction *AutoReadDirectoryAfterOpAction;
+  TTBXPopupMenu *RemoteAddressPopup;
+  TTBXSubmenuItem *TBXSubmenuItem2;
+  TTBXItem *TBXItem17;
+  TTBXSeparatorItem *TBXSeparatorItem1;
+  TTBXItem *TBXItem18;
+  TTBXItem *TBXItem19;
+  TTBXItem *TBXItem20;
+  TTBXSeparatorItem *TBXSeparatorItem2;
+  TTBXItem *TBXItem21;
+  TTBXItem *TBXItem22;
+  TTBXItem *TBXItem24;
+  TTBXItem *TBXItem25;
   void __fastcall LogActionsUpdate(TBasicAction *Action, bool &Handled);
   void __fastcall LogActionsExecute(TBasicAction *Action, bool &Handled);
   void __fastcall ExplorerActionsUpdate(TBasicAction *Action, bool &Handled);

+ 3 - 0
forms/Preferences.cpp

@@ -568,6 +568,7 @@ void __fastcall TPreferencesDialog::UpdateControls()
   EnableControl(BeepOnFinishAfterEdit, BeepOnFinishCheck->Checked);
   EnableControl(BeepOnFinishAfterText, BeepOnFinishCheck->Checked);
   EnableControl(ResumeThresholdEdit, ResumeSmartButton->Checked);
+  EnableControl(ResumeThresholdUnitLabel, ResumeThresholdEdit->Enabled);
   EnableControl(SessionReopenAutoEdit, SessionReopenAutoCheck->Checked);
   EnableControl(SessionReopenAutoLabel, SessionReopenAutoEdit->Enabled);
   EnableControl(SessionReopenAutoSecLabel, SessionReopenAutoEdit->Enabled);
@@ -619,7 +620,9 @@ void __fastcall TPreferencesDialog::UpdateControls()
     (EditorListView->ItemIndex < EditorListView->Items->Count - 1));
 
   EnableControl(UpdatesProxyHostEdit, UpdatesProxyCheck->Checked);
+  EnableControl(UpdatesProxyHostLabel, UpdatesProxyHostEdit->Enabled);
   EnableControl(UpdatesProxyPortEdit, UpdatesProxyCheck->Checked);
+  EnableControl(UpdatesProxyPortLabel, UpdatesProxyPortEdit->Enabled);
 
   EnableControl(PuttyPasswordCheck, !PuttyPathEdit->Text.IsEmpty());
   EnableControl(AutoOpenInPuttyCheck, PuttyPasswordCheck->Enabled);

+ 6 - 7
forms/Preferences.dfm

@@ -1276,17 +1276,17 @@ object PreferencesDialog: TPreferencesDialog
           object DDExtDisabledPanel: TPanel
             Left = 34
             Top = 195
-            Width = 325
+            Width = 315
             Height = 51
             BevelOuter = bvNone
             TabOrder = 3
             DesignSize = (
-              325
+              315
               51)
             object DDWarnLackOfTempSpaceCheck: TCheckBox
               Left = 0
               Top = 5
-              Width = 321
+              Width = 315
               Height = 17
               Anchors = [akLeft, akTop, akRight]
               Caption = '&Warn when there is not enough free space'
@@ -1296,7 +1296,7 @@ object PreferencesDialog: TPreferencesDialog
             object DDWarnOnMoveCheck: TCheckBox
               Left = 0
               Top = 28
-              Width = 321
+              Width = 315
               Height = 17
               Anchors = [akLeft, akTop, akRight]
               Caption = 'Warn when mo&ving via temporary directory'
@@ -1477,7 +1477,6 @@ object PreferencesDialog: TPreferencesDialog
             AutoSize = False
             Caption = 'Specify where to temporarily store edited and downloaded files.'
             WordWrap = True
-            OnClick = DDExtLabelClick
           end
           object DDSystemTemporaryDirectoryButton: TRadioButton
             Left = 16
@@ -1747,7 +1746,7 @@ object PreferencesDialog: TPreferencesDialog
           DesignSize = (
             357
             98)
-          object Label15: TLabel
+          object UpdatesProxyHostLabel: TLabel
             Left = 34
             Top = 46
             Width = 78
@@ -1755,7 +1754,7 @@ object PreferencesDialog: TPreferencesDialog
             Caption = 'Pro&xy host name'
             FocusControl = UpdatesProxyHostEdit
           end
-          object Label18: TLabel
+          object UpdatesProxyPortLabel: TLabel
             Left = 252
             Top = 46
             Width = 57

+ 2 - 2
forms/Preferences.h

@@ -163,8 +163,8 @@ __published:
   TRadioButton *UpdatesWeeklyButton;
   TRadioButton *UpdatesMonthlyButton;
   TXPGroupBox *UpdatesProxyGroup;
-  TLabel *Label15;
-  TLabel *Label18;
+  TLabel *UpdatesProxyHostLabel;
+  TLabel *UpdatesProxyPortLabel;
   TUpDownEdit *UpdatesProxyPortEdit;
   TEdit *UpdatesProxyHostEdit;
   TCheckBox *UpdatesProxyCheck;

+ 1 - 0
forms/Progress.cpp

@@ -50,6 +50,7 @@ __fastcall TProgressForm::~TProgressForm()
   if (IsIconic(Application->Handle) && FMinimizedByMe)
   {
     Application->Restore();
+    Application->BringToFront();
   }
 
   ReleaseAsModal(this, FShowAsModalStorage);

+ 7 - 1
forms/Properties.cpp

@@ -399,10 +399,16 @@ void __fastcall TPropertiesDialog::UpdateControls()
     // when setting properties for one file only, allow undef state
     // only when the input right explicitly requires it or
     // when "recursive" is on (possible for directory only).
-    RightsFrame->AllowUndef =
+    bool AllowUndef =
       (FOrigProperties.Valid.Contains(vpRights) &&
        FOrigProperties.Rights.AllowUndef) ||
       (RecursiveCheck->Checked);
+    if (!AllowUndef)
+    {
+      // when disallowing undef state, make sure, all undef are turned into unset
+      RightsFrame->Rights = TRights(RightsFrame->Rights.NumberSet);
+    }
+    RightsFrame->AllowUndef = AllowUndef;
   }
 }
 //---------------------------------------------------------------------------

+ 136 - 30
forms/Rights.cpp

@@ -7,6 +7,8 @@
 #include <Common.h>
 
 #include <VCLCommon.h>
+#include <Tools.h>
+#include <GUITools.h>
 //---------------------------------------------------------------------------
 #pragma package(smart_init)
 #pragma link "GrayedCheckBox"
@@ -15,6 +17,7 @@
 __fastcall TRightsFrame::TRightsFrame(TComponent* Owner)
         : TFrame(Owner)
 {
+  FAddXToDirectoriesSuffix = "+x";
   FOnChange = NULL;
   FAllowAddXToDirectories = true;
   FPopup = false;
@@ -23,6 +26,7 @@ __fastcall TRightsFrame::TRightsFrame(TComponent* Owner)
   FCancelButton = NULL;
   // to avoid duplication of reference in forms that uses the frame
   PopupMenu = RightsPopup;
+  FPopingContextMenu = false;
 
   #define COPY_HINT(R) \
     Checks[TRights::rrGroup ## R]->Hint = Checks[TRights::rrUser ## R]->Hint; \
@@ -71,14 +75,22 @@ TRights::TState __fastcall TRightsFrame::GetStates(TRights::TRight Right)
 //---------------------------------------------------------------------------
 void __fastcall TRightsFrame::SetRights(const TRights & value)
 {
+  bool Changed = (AllowUndef != value.AllowUndef);
   AllowUndef = true; // temporarily
   for (int Right = TRights::rrFirst; Right <= TRights::rrLast; Right++)
   {
-    States[static_cast<TRights::TRight>(Right)] =
-      value.RightUndef[static_cast<TRights::TRight>(Right)];
+    TRights::TRight R = static_cast<TRights::TRight>(Right);
+    if (States[R] != value.RightUndef[R])
+    {
+      States[R] = value.RightUndef[R];
+      Changed = true;
+    }
   }
   AllowUndef = value.AllowUndef;
-  UpdateControls();
+  if (Changed)
+  {
+    UpdateControls();
+  }
 }
 //---------------------------------------------------------------------------
 TRights __fastcall TRightsFrame::GetRights()
@@ -155,12 +167,17 @@ void __fastcall TRightsFrame::ControlChange(TObject * /*Sender*/)
   UpdateControls();
 }
 //---------------------------------------------------------------------------
+bool __fastcall TRightsFrame::DirectoriesXEffective()
+{
+  return !((Rights.NumberSet & TRights::rfExec) == TRights::rfExec);
+}
+//---------------------------------------------------------------------------
 void __fastcall TRightsFrame::UpdateControls()
 {
   Color = (FPopup ? clWindow : clBtnFace);
   DirectoriesXCheck->Visible = AllowAddXToDirectories;
   EnableControl(DirectoriesXCheck,
-    Enabled && !((Rights.NumberSet & TRights::rfExec) == TRights::rfExec));
+    Enabled && DirectoriesXEffective());
   DoChange();
 }
 //---------------------------------------------------------------------------
@@ -239,35 +256,53 @@ void __fastcall TRightsFrame::ForceUpdate()
 {
 }
 //---------------------------------------------------------------------------
+bool __fastcall TRightsFrame::HasFocus()
+{
+  return
+    (Focused() ||
+    ((Screen->ActiveControl != NULL) && (Screen->ActiveControl->Parent == this))) ||
+    ((PopupParent != NULL) && PopupParent->Focused());
+}
+//---------------------------------------------------------------------------
 void __fastcall TRightsFrame::RightsActionsExecute(TBasicAction * Action,
   bool & Handled)
 {
-  TRights R = Rights;
-  R.Number = TRights::rfNo;
-
-  Handled = true;
-  if (Action == NoRightsAction)
+  // prevent shortcuts to be avaluated when frame does not have a focus
+  if (HasFocus())
   {
-    R = TRights::rfNo;
-  }
-  else if (Action == DefaultRightsAction)
-  {
-    R = TRights::rfDefault;
-  }
-  else if (Action == AllRightsAction)
-  {
-    R = TRights::rfAll;
-  }
-  else if (Action == LeaveRightsAsIsAction)
-  {
-    R.AllUndef();
-  }
-  else
-  {
-    Handled = false;
+    bool Changed = true;
+    TRights R = Rights;
+    R.Number = TRights::rfNo;
+
+    Handled = true;
+    if (Action == NoRightsAction)
+    {
+      R = TRights::rfNo;
+    }
+    else if (Action == DefaultRightsAction)
+    {
+      R = TRights::rfDefault;
+    }
+    else if (Action == AllRightsAction)
+    {
+      R = TRights::rfAll;
+    }
+    else if (Action == LeaveRightsAsIsAction)
+    {
+      R.AllUndef();
+    }
+    else
+    {
+      Handled = false;
+    }
+
+    if (Changed)
+    {
+      Rights = R;
+      ForceUpdate();
+      DoChange();
+    }
   }
-  Rights = R;
-  ForceUpdate();
 }
 //---------------------------------------------------------------------------
 void __fastcall TRightsFrame::RightsActionsUpdate(TBasicAction *Action,
@@ -278,19 +313,25 @@ void __fastcall TRightsFrame::RightsActionsUpdate(TBasicAction *Action,
   Handled = true;
   if (Action == NoRightsAction)
   {
+    // explicitly enable as action gets disabled, if its shortcut is pressed,
+    // while the form does not have a focus and OnExecute handler denies the execution
+    NoRightsAction->Enabled = true;
     NoRightsAction->Checked = !R.IsUndef && (R.NumberSet == TRights::rfNo);
   }
   else if (Action == DefaultRightsAction)
   {
+    DefaultRightsAction->Enabled = true;
     DefaultRightsAction->Checked = !R.IsUndef && (R.NumberSet == TRights::rfDefault);
   }
   else if (Action == AllRightsAction)
   {
+    AllRightsAction->Enabled = true;
     AllRightsAction->Checked = !R.IsUndef && (R.NumberSet == TRights::rfAll);
   }
   else if (Action == LeaveRightsAsIsAction)
   {
-    LeaveRightsAsIsAction->Enabled = R.AllowUndef;
+    LeaveRightsAsIsAction->Enabled = true;
+    LeaveRightsAsIsAction->Visible = R.AllowUndef;
     LeaveRightsAsIsAction->Checked = (R.NumberSet == TRights::rfNo) &&
       (R.NumberUnset == TRights::rfNo);
   }
@@ -366,6 +407,19 @@ bool __fastcall TRightsFrame::IsAncestor(TControl * Control, TControl * Ancestor
   return (Control != NULL);
 }
 //---------------------------------------------------------------------------
+void __fastcall TRightsFrame::WMContextMenu(TWMContextMenu & Message)
+{
+  FPopingContextMenu = true;
+  try
+  {
+    TFrame::Dispatch(&Message);
+  }
+  __finally
+  {
+    FPopingContextMenu = false;
+  }  
+}
+//---------------------------------------------------------------------------
 void __fastcall TRightsFrame::CMDialogKey(TCMDialogKey & Message)
 {
   if (FPopup && Visible &&
@@ -384,7 +438,7 @@ void __fastcall TRightsFrame::CMDialogKey(TCMDialogKey & Message)
 //---------------------------------------------------------------------------
 void __fastcall TRightsFrame::CMCancelMode(TCMCancelMode & Message)
 {
-  if (FPopup && Visible &&
+  if (FPopup && Visible && !FPopingContextMenu &&
       ((Message.Sender == NULL) ||
        (!IsAncestor(Message.Sender, this) && 
         !IsAncestor(Message.Sender, FPopupParent) &&
@@ -409,6 +463,10 @@ void __fastcall TRightsFrame::Dispatch(void * Message)
       CMDialogKey(*(TCMDialogKey *)Message);
       break;
 
+    case WM_CONTEXTMENU:
+      WMContextMenu(*(TWMContextMenu *)Message);
+      break;
+
     default:
       TFrame::Dispatch(Message);
       break;
@@ -465,4 +523,52 @@ void __fastcall TRightsFrame::CloseUp()
   FPopupParent->SetFocus();
 }
 //---------------------------------------------------------------------------
+AnsiString __fastcall TRightsFrame::GetText()
+{
+  AnsiString Result = Rights.Text;
+  if (AllowAddXToDirectories && DirectoriesXEffective() && AddXToDirectories)
+  {
+    Result = FORMAT("%s (%s)", (Result, FAddXToDirectoriesSuffix));
+  }
+  return Result;
+}
+//---------------------------------------------------------------------------
+void __fastcall TRightsFrame::SetText(AnsiString value)
+{
+  if (Text != value)
+  {
+    AnsiString RightsStr = value;
+
+    int P = RightsStr.LowerCase().Pos(FAddXToDirectoriesSuffix);
+    bool AAddXToDirectories = (P > 0);
+    if (AAddXToDirectories)
+    {
+      RightsStr.Delete(P, FAddXToDirectoriesSuffix.Length());
+    }
+    RightsStr = DeleteChar(DeleteChar(RightsStr, '('), ')').Trim();
+    TRights R = Rights;
+    int Dummy;
+    if (((RightsStr.Length() == 3) || (RightsStr.Length() == 4)) &&
+        TryStrToInt(RightsStr, Dummy))
+    {
+      R.Octal = RightsStr;
+    }
+    else
+    {
+      R.Text = RightsStr;
+    }
+
+    Rights = R;
+    AddXToDirectories = AAddXToDirectories;
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TRightsFrame::RightsPopupPopup(TObject * /*Sender*/)
+{
+  if (!HasFocus())
+  {
+    SetFocus();
+  }
+}
+//---------------------------------------------------------------------------
 

+ 318 - 53
forms/Rights.dfm

@@ -177,6 +177,7 @@ object RightsFrame: TRightsFrame
   end
   object RightsPopup: TPopupMenu
     Images = RightsImages
+    OnPopup = RightsPopupPopup
     Left = 128
     Top = 59
     object Norights1: TMenuItem
@@ -221,8 +222,264 @@ object RightsFrame: TRightsFrame
   object RightsImages: TImageList
     Left = 128
     Bitmap = {
-      494C010103000400040010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600
-      0000000000003600000028000000400000001000000001002000000000000010
+      494C010106000900040010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600
+      0000000000003600000028000000400000003000000001002000000000000030
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000084000000840000008400000084000000840000008400
+      0000840000008400000084000000840000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000840000008400000084000000840000008400
+      0000840000008400000084000000840000000000000000000000000000000000
+      0000000000000000000084000000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+      FF00FFFFFF00FFFFFF00FFFFFF00840000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000084000000FFFFFF00FFFFFF00FFFFFF00FFFF
+      FF00FFFFFF00FFFFFF00FFFFFF00840000000000000084848400008484008484
+      8400008484008484840084000000FFFFFF000000000000000000000000000000
+      00000000000000000000FFFFFF00840000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000084000000FFFFFF00FFFFFF0000000000FFFF
+      FF00FFFFFF0000000000FFFFFF00840000000000000000848400848484000084
+      8400848484000084840084000000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+      FF00FFFFFF00FFFFFF00FFFFFF00840000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000084000000FFFFFF000000000000000000FFFF
+      FF00FFFFFF0000000000FFFFFF00840000000000000084848400008484008484
+      8400008484008484840084000000FFFFFF00000000000000000000000000FFFF
+      FF00840000008400000084000000840000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000FFFFFF00FFFF
+      FF00FFFFFF00FFFFFF00FFFFFF0084000000FFFFFF00FFFFFF0000000000FFFF
+      FF000000000000000000FFFFFF00840000000000000000848400848484000084
+      8400848484000084840084000000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+      FF0084000000FFFFFF0084000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000FFFFFF00FFFF
+      FF0000000000FFFFFF00FFFFFF0084000000FFFFFF000000000000000000FFFF
+      FF00FFFFFF0000000000FFFFFF00840000000000000084848400008484008484
+      8400008484008484840084000000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+      FF00840000008400000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000FFFFFF000000
+      000000000000FFFFFF00FFFFFF0084000000FFFFFF00FFFFFF00FFFFFF00FFFF
+      FF00840000008400000084000000840000000000000000848400848484000084
+      8400848484000084840084000000840000008400000084000000840000008400
+      0000840000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000FFFFFF00FFFF
+      FF0000000000FFFFFF00FFFFFF0084000000FFFFFF00FFFFFF00FFFFFF00FFFF
+      FF0084000000FFFFFF0084000000000000000000000084848400008484008484
+      8400008484008484840000848400848484000084840084848400008484008484
+      8400008484000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000FFFFFF000000
+      000000000000FFFFFF00FFFFFF0084000000FFFFFF00FFFFFF00FFFFFF00FFFF
+      FF00840000008400000000000000000000000000000000848400848484000000
+      0000000000000000000000000000000000000000000000000000000000008484
+      8400848484000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000FFFFFF00FFFF
+      FF00FFFFFF00FFFFFF0000000000840000008400000084000000840000008400
+      0000840000000000000000000000000000000000000084848400848484000000
+      0000000000000000000000000000000000000000000000000000000000008484
+      8400008484000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000FFFFFF00FFFF
+      FF00FFFFFF00FFFFFF0000000000FFFFFF000000000000000000000000000000
+      0000000000000000000000000000000000000000000000848400848484000084
+      84000000000000FFFF00000000000000000000FFFF0000000000848484000084
+      8400848484000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000FFFFFF00FFFF
+      FF00FFFFFF00FFFFFF0000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000FFFF0000FFFF000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000007B7B
       00007B7B00007B7B000039312100000000005A5A10007B7B0000000000003931
       2100000000000000000000000000000000000000000000000000000000007B7B
@@ -230,134 +487,142 @@ object RightsFrame: TRightsFrame
       4A00000000000000000000000000000000000000000073733900737339007373
       39004A4A3900000000004A4A39007373390000000000292929006B086B000000
       00006B086B00000000006B086B00000000000000000000000000000000000000
-      000000000000000000000000000000000000FFFFFF00FFFFFF00FFFFFF00FFFF
-      FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000000000000000BDBD0000F7F7
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000BDBD0000F7F7
       0000F7F700007B7B0000BDBD00007B7B0000BDBD00007B7B00007B7B0000217B
       9C000000000000008400FFFFFF00000000000000000000000000BDBD0000DEDE
       0000FFFF00007B7B0000BDBD00007B7B0000BDBD00007B7B00007B7B0000217B
       9C0000000000000000000000000000000000B5BD0000EFEF0000EFEF00007373
       3900B5BD000073733900B5BD0000737339007373390018737B0018737B001873
-      7B006B086B006B086B006B086B0000000000FFFFFF00FFFFFF00FFFFFF00FFFF
-      FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
-      FF00FFFFFF00FFFFFF00000000000000000000000000000000005A5A10000000
+      7B006B086B006B086B006B086B00000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000000000000000000000000000000000005A5A10000000
       8400FFFFFF009C9C0000F7F700005A5A100042424200393121007B7B00000000
       00000000000000000000000000000000000000000000000000005A5A1000BDBD
       00007B7B00009C9C0000FFFF00005A5A100042424200292910007B7B00000000
       0000000000000000000000000000000000004A4A3900B5BD000073733900B5BD
       0000EFEF0000737339004A4A39004A4A39007373390010ADAD0010ADAD0073AD
       AD004A4A39000000000000000000000000000000000000000000000000000000
-      0000000000000000000000000000000000000000000000000000000000000000
-      0000000000000000000000000000000000000000000000000000000084000000
+      0000000000000000000000000000840000008400000084000000840000008400
+      0000840000008400000084000000840000000000000000000000000084000000
       840000008400FFFFFF005A5A10008484840084848400424242005A5A5A000000
       000000008400FFFFFF0000000000000000000000000000000000000000000000
       00005A5A1000DEDE00005A5A1000848484008484840042424200635A63000000
       00000000000000000000000000000000000000000000000000004A4A3900EFEF
       000073733900737339008C8C8C004A4A39004A4A390010ADAD0073ADAD00EFF7
       EF004A4A39000000000000000000000000000000000000000000000000000000
-      0000000000000000000000000000000000000000000000000000000000000000
-      0000000000000000000000000000000000000000000000000000000084000000
+      000000000000000000000000000084000000FFFFFF00FFFFFF00FFFFFF00FFFF
+      FF00FFFFFF00FFFFFF00FFFFFF00840000000000000000000000000084000000
       840000008400FFFFFF00848484006B6B6B004242420000000000393121000000
       8400FFFFFF000000000000000000000000000000000000000000000000000000
       0000292910002929100084848400635A63004242420000000000292910000000
       0000000000000000000000000000000000000000000000000000292929002929
       290073733900737339004A4A3900000000002929290010ADAD00EFF7EF008C8C
-      8C008C8C8C00737339002929290000000000FFFFFF00FFFFFF00FFFFFF00FFFF
-      FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
-      FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000000000000000000000000000
+      8C008C8C8C007373390029292900000000000000000000000000000000000000
+      000000000000000000000000000084000000FFFFFF0000000000000000000000
+      00000000000000000000FFFFFF00840000000000000000000000000000000000
       84000000840000008400FFFFFF00848484008484840084848400000084000000
       8400FFFFFF000000000000000000000000000000000000000000000000000000
       00000000000029291000635A6300848484008484840084848400848484004242
       4200000000000000000000000000000000000000000000000000000000002929
       29004A4A39008C8C8C008C8C8C008C8C8C008C8C8C0029292900EFF7EF00EFF7
-      EF00EFF7EF00EFF7EF00737339000000000000008400FFFFFF00FFFFFF00FFFF
-      FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
-      FF00FFFFFF00FFFFFF0000000000000000000000000000000000000000000000
+      EF00EFF7EF00EFF7EF0073733900000000000000000000000000000000000000
+      000000000000000000000000000084000000FFFFFF00FFFFFF00FFFFFF00FFFF
+      FF00FFFFFF00FFFFFF00FFFFFF00840000000000000000000000000000000000
       0000000084000000840000008400FFFFFF00848484000000840000008400FFFF
       FF00000000000000000000000000000000000000000000000000000000000000
       0000000000000000000042424200848484008484840084848400635A63004242
       4200000000000000000000000000000000000000000000000000000000000000
       00004A4A39008C8C8C00737339008C8C8C004A4A39004A4A3900EFF7EF00EFF7
-      EF00EFF7EF008C8C8C002929290000000000FFFFFF00FFFFFF00FFFFFF00FFFF
-      FF00FFFFFF000000000000000000000000000000000000000000000000000000
-      0000000000002929290018737B0018737B000000000000000000000000000000
+      EF00EFF7EF008C8C8C0029292900000000000000000000000000FFFFFF00FFFF
+      FF00FFFFFF00FFFFFF00FFFFFF0084000000FFFFFF0000000000000000000000
+      00000000000000000000FFFFFF00840000000000000000000000000000000000
       0000000000000000840000008400000084000000840000008400FFFFFF004242
       4200000000000000000000000000000000000000000000000000000000000000
       00000000000000000000635A6300848484008484840084848400848484004242
       4200000000000000000000000000000000000000000000000000000000000000
       00004A4A39008C8C8C008C8C8C008C8C8C008C8C8C0029292900EFF7EF00EFF7
-      EF00EFF7EF0073ADAD008C8C8C0000000000FFFFFF00FFFFFF00FFFFFF00FFFF
-      FF00FFFFFF00FFFFFF00FFFFFF007B7B00007B7B00007B7B0000393121000000
-      00005A5A10007B7B000000000000393121000000000000000000000000000000
+      EF00EFF7EF0073ADAD008C8C8C00000000000000000000000000FFFFFF000000
+      000000000000000000000000000084000000FFFFFF00FFFFFF00FFFFFF00FFFF
+      FF00FFFFFF00FFFFFF00FFFFFF00840000000000000000000000000000000000
       00000000000042424200000084000000840000008400FFFFFF00848484004242
       42006B6B6B000000000000000000000000000000000000000000000000000000
       0000000000004242420084848400848484008484840084848400848484004242
       42006B6B6B000000000000000000000000000000000000000000000000004A4A
       39008C8C8C008C8C8C00737339008C8C8C008C8C8C002929290073733900EFF7
-      EF00FF7B7B00EFF7EF004A4A390000000000FFFFFF00FFFFFF00FFFFFF00FFFF
-      FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
-      FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000000000000000000000000000
+      EF00FF7B7B00EFF7EF004A4A3900000000000000000000000000FFFFFF00FFFF
+      FF00FFFFFF00FFFFFF00FFFFFF0084000000FFFFFF000000000000000000FFFF
+      FF00840000008400000084000000840000000000000000000000000000000000
       0000000000000000840000008400000084000000840000008400FFFFFF004242
       4200000000000000000000000000000000000000000000000000000000000000
       0000000000000000000042424200848484008484840029291000848484004242
       4200000000000000000000000000000000000000000000000000000000000000
       0000292929008C8C8C008C8C8C00000000008C8C8C0029292900EFF7EF00EFF7
-      EF008C8C8C008C8C8C000000000000000000FFFFFF00FFFFFF00FFFFFF00FFFF
-      FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
-      FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000000000000000000000000000
+      EF008C8C8C008C8C8C0000000000000000000000000000000000FFFFFF000000
+      000000000000000000000000000084000000FFFFFF00FFFFFF00FFFFFF00FFFF
+      FF0084000000FFFFFF0084000000000000000000000000000000000000000000
       0000000084000000840000008400FFFFFF008484840000008400FFFFFF000000
       0000000000000000000000000000000000000000000000000000000000000000
       00000000000000000000000000004242420084848400635A6300000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000004A4A39008C8C8C004A4A39000000000073ADAD0018737B00EFF7
-      EF0073ADAD00EFF7EF004A4A390000000000FFFFFF00FFFFFF00FFFFFF00FFFF
-      FF00FFFFFF00FFFFFF0000000000000000000000000042424200000084000000
-      840000008400FFFFFF0084848400424242000000000000000000000084000000
+      EF0073ADAD00EFF7EF004A4A3900000000000000000000000000FFFFFF00FFFF
+      FF00FFFFFF00FFFFFF00FFFFFF0084000000FFFFFF00FFFFFF00FFFFFF00FFFF
+      FF00840000008400000000000000000000000000000000000000000084000000
       84000000840000008400FFFFFF00424242008484840084848400000084000000
       8400FFFFFF000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000424242008484840084848400292910000000
       0000000000000000000000000000000000000000000000000000000000000000
       000000000000292929008C8C8C008C8C8C002929290073ADAD0010ADAD0010AD
-      AD0008F7F70010ADAD0008F7F70000000000FFFFFF00FFFFFF00FFFFFF00FFFF
-      FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
-      FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000000000008400000084000000
+      AD0008F7F70010ADAD0008F7F700000000000000000000000000FFFFFF000000
+      000000000000FFFFFF0000000000840000008400000084000000840000008400
+      0000840000000000000000000000000000000000000000008400000084000000
       840000008400FFFFFF0000000000000000000000000000000000000000000000
       840000008400FFFFFF0000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000073ADAD0063DEDE0008F7
-      F70008F7F70008F7F7002929290000000000FFFFFF00FFFFFF00FFFFFF00FFFF
-      FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
-      FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00000000000000840000008400FFFF
+      F70008F7F70008F7F70029292900000000000000000000000000FFFFFF00FFFF
+      FF00FFFFFF00FFFFFF0000000000FFFFFF000000000000000000000000000000
+      000000000000000000000000000000000000000000000000840000008400FFFF
       FF00000000000000000000000000000000000000000000000000000000000039
       39000000840000008400FFFFFF00000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000039
       3900000000000000000000000000000000000000000000000000000000000000
       000000000000000000000000000000000000000000002929290018737B001873
-      7B0018737B00000000000000000000000000FFFFFF00FFFFFF00FFFFFF00FFFF
-      FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
-      FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000000000000000000000000000
+      7B0018737B000000000000000000000000000000000000000000FFFFFF00FFFF
+      FF00FFFFFF00FFFFFF0000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
-      000000000000000000000000000000000000FFFFFF00FFFFFF00FFFFFF00FFFF
-      FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
-      FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000424D3E000000000000003E000000
+      2800000040000000300000000100010000000000800100000000000000000000
+      000000000000000000000000FFFFFF0000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
-      000000000000000000000000000000000000FFFFFF00FFFFFF00FFFFFF00FFFF
-      FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
-      FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00424D3E000000000000003E000000
-      2800000040000000100000000100010000000000800000000000000000000000
-      000000000000000000000000FFFFFF00E00FE00F8001FF00C009C00F00000500
-      C01FC01F00030500C013E01F80070500C007F01FC001FF00E007E00F8001FF00
-      E00FE00F8001FF00C00FC00F0000FF00C007C0070001FF00C00FC00F0001FF00
-      C01FC01F0000FF00C007C01F0000FF008003C01F0001FF008001E00F8003FF00
-      F01FF01FC07FFF00FFFFFFFFFFFF000000000000000000000000000000000000
+      00000000000000000000000000000000FFFFFFFF00000000FFFFFC0000000000
+      FE00800000000000FE00000000000000FE000000000000008000000000000000
+      8000000100000000800000030000000080000003000000008001000300000000
+      800300030000000080070FC300000000807F00030000000080FF800700000000
+      81FFF87F00000000FFFFFFFF00000000E00FE00F8001FFFFC009C00F0000FFFF
+      C01FC01F0003FE00C013E01F8007FE00C007F01FC001FE00E007E00F80018000
+      E00FE00F80018000C00FC00F00008000C007C00700018000C00FC00F00018001
+      C01FC01F00008003C007C01F000080078003C01F0001807F8001E00F800380FF
+      F01FF01FC07F81FFFFFFFFFFFFFFFFFF00000000000000000000000000000000
       000000000000}
   end
 end

+ 11 - 1
forms/Rights.h

@@ -49,6 +49,7 @@ __published:
   void __fastcall RightsActionsExecute(TBasicAction *Action,
           bool &Handled);
   void __fastcall RightsActionsUpdate(TBasicAction *Action, bool &Handled);
+  void __fastcall RightsPopupPopup(TObject *Sender);
 private:
   bool FAllowAddXToDirectories;
   TNotifyEvent FOnChange;
@@ -56,6 +57,8 @@ private:
   TWinControl * FPopupParent;
   TButton * FDefaultButton;
   TButton * FCancelButton;
+  bool FPopingContextMenu;
+  AnsiString FAddXToDirectoriesSuffix;
 
   void __fastcall CycleRights(int Group);
   bool __fastcall GetAddXToDirectories();
@@ -68,6 +71,8 @@ private:
   void __fastcall SetAllowUndef(bool value);
   void __fastcall SetRights(const TRights & value);
   void __fastcall SetStates(TRights::TRight Right, TRights::TState value);
+  AnsiString __fastcall GetText();
+  void __fastcall SetText(AnsiString value);
 
 public:
   virtual __fastcall ~TRightsFrame();
@@ -81,7 +86,7 @@ public:
   __property TCheckBox * Checks[TRights::TRight Right] = { read = GetChecks };
   __property TNotifyEvent OnChange = { read = FOnChange, write = FOnChange };
   __property TRights Rights = { read = GetRights, write = SetRights };
-  __property TRights::TState States[TRights::TRight Right] = { read = GetStates, write = SetStates };
+  __property AnsiString Text = { read = GetText, write = SetText };
   __property bool Popup = { read = FPopup, write = SetPopup };
   __property TWinControl * PopupParent = { read = FPopupParent, write = FPopupParent };
 
@@ -95,10 +100,15 @@ protected:
   virtual void __fastcall Dispatch(void * Message);
   void __fastcall CMCancelMode(TCMCancelMode & Message);
   void __fastcall CMDialogKey(TCMDialogKey & Message);
+  void __fastcall WMContextMenu(TWMContextMenu & Message);
   bool __fastcall IsAncestor(TControl * Control, TControl * Ancestor);
   DYNAMIC void __fastcall DoExit();
   virtual void __fastcall SetPopup(bool value);
   void __fastcall DoCloseUp();
+  bool __fastcall HasFocus();
+  bool __fastcall DirectoriesXEffective();
+
+  __property TRights::TState States[TRights::TRight Right] = { read = GetStates, write = SetStates };
 };
 //---------------------------------------------------------------------------
 #endif

+ 10 - 1
forms/RightsExt.cpp

@@ -3,6 +3,7 @@
 #pragma hdrstop
 
 #include "RightsExt.h"
+#include <Common.h>
 //---------------------------------------------------------------------------
 #pragma package(smart_init)
 #pragma link "Rights"
@@ -61,7 +62,15 @@ void __fastcall TRightsExtFrame::OctalEditChange(TObject * /*Sender*/)
 //---------------------------------------------------------------------------
 void __fastcall TRightsExtFrame::OctalEditExit(TObject * /*Sender*/)
 {
-  if (OctalEdit->Modified)
+  if (!Visible)
+  {
+    // should happen only if popup is closed by esc key
+    assert(Popup);
+
+    // cancel changes
+    ForceUpdate();
+  }
+  else if (OctalEdit->Modified)
   {
     // Now the text in OctalEdit is almost necessarily invalid, otherwise
     // OctalEditChange would have already cleared Modified flag

+ 1 - 0
forms/ScpExplorer.dfm

@@ -804,6 +804,7 @@ inherited ScpExplorerForm: TScpExplorerForm
         Height = 21
         Align = alClient
         Constraints.MinWidth = 50
+        PopupMenu = NonVisualDataModule.RemoteAddressPopup
         TabOrder = 0
       end
     end

+ 1 - 0
forms/Synchronize.cpp

@@ -365,6 +365,7 @@ void __fastcall TSynchronizeDialog::Stop()
   {
     FMinimizedByMe = false;
     Application->Restore();
+    Application->BringToFront();
   }
 }
 //---------------------------------------------------------------------------

+ 7 - 3
forms/SynchronizeChecklist.cpp

@@ -63,6 +63,10 @@ __fastcall TSynchronizeChecklistDialog::TSynchronizeChecklistDialog(
     SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
   FSystemImageList->ShareImages = true;
   ListView->SmallImages = FSystemImageList;
+
+  // header images mut be assigned after the small images, so it cannot
+  // be done via DFM
+  ListView->HeaderImages = ArrowImages;
 }
 //---------------------------------------------------------------------
 __fastcall TSynchronizeChecklistDialog::~TSynchronizeChecklistDialog()
@@ -180,12 +184,12 @@ void __fastcall TSynchronizeChecklistDialog::LoadItem(TListItem * Item)
       FLAGMASK(ChecklistItem->IsDirectory, FILE_ATTRIBUTE_DIRECTORY));
   }
 
-  AnsiString FileName = ChecklistItem->FileName;
+  S = ChecklistItem->FileName;
   if (ChecklistItem->IsDirectory)
   {
-    FileName = IncludeTrailingBackslash(FileName);
+    S = IncludeTrailingBackslash(S);
   }
-  Item->Caption = FileName;
+  Item->Caption = S;
 
   if (ChecklistItem->Action == TSynchronizeChecklist::saDeleteRemote)
   {

+ 0 - 1
forms/SynchronizeChecklist.dfm

@@ -172,7 +172,6 @@ object SynchronizeChecklistDialog: TSynchronizeChecklistDialog
         Caption = 'Changed'
         Width = 80
       end>
-    HeaderImages = ArrowImages
     OnAdvancedCustomDrawSubItem = ListViewAdvancedCustomDrawSubItem
     OnCompare = ListViewCompare
     OnSelectItem = ListViewSelectItem

+ 1 - 0
forms/SynchronizeProgress.cpp

@@ -38,6 +38,7 @@ __fastcall TSynchronizeProgressForm::~TSynchronizeProgressForm()
   if (IsIconic(Application->Handle) && FMinimizedByMe)
   {
     Application->Restore();
+    Application->BringToFront();
   }
 
   ReleaseAsModal(this, FShowAsModalStorage);

+ 1 - 0
packages/my/PathLabel.hpp

@@ -43,6 +43,7 @@ private:
 	TPathLabelGetStatusEvent FOnGetStatus;
 	TPathLabelPathClickEvent FOnPathClick;
 	AnsiString FDisplayPath;
+	AnsiString FDisplayHotTrack;
 	bool FHotTrack;
 	bool FMouseInView;
 	bool FIsActive;

+ 10 - 7
packages/my/PathLabel.pas

@@ -22,6 +22,7 @@ type
     FOnGetStatus: TPathLabelGetStatusEvent;
     FOnPathClick: TPathLabelPathClickEvent;
     FDisplayPath: string;
+    FDisplayHotTrack: string;
     FHotTrack: Boolean;
     FMouseInView: Boolean;
     FIsActive: Boolean;
@@ -243,7 +244,6 @@ procedure TCustomPathLabel.DoDrawText(var Rect: TRect; Flags: Longint);
 var
   i: Integer;
   Path: string;
-  HotPath: string;
   StandardColor: TColor;
 begin
   if (Flags and DT_CALCRECT <> 0) and ((Text = '') or ShowAccelChar and
@@ -278,15 +278,15 @@ begin
   end
     else
   begin
-    HotPath := HotTrackPath(FDisplayPath);
-    if HotPath <> '' then
+    FDisplayHotTrack := HotTrackPath(FDisplayPath);
+    if FDisplayHotTrack <> '' then
     begin
       StandardColor := Canvas.Font.Color;
       Canvas.Font.Color := FColors[4 + Integer(FIsActive)];
-      DrawText(Canvas.Handle, PChar(HotPath), Length(HotPath), Rect, Flags);
+      DrawText(Canvas.Handle, PChar(FDisplayHotTrack), Length(FDisplayHotTrack), Rect, Flags);
       Canvas.Font.Color := StandardColor;
-      Inc(Rect.Left, Canvas.TextWidth(HotPath));
-      Delete(Path, 1, Length(HotPath));
+      Inc(Rect.Left, Canvas.TextWidth(FDisplayHotTrack));
+      Delete(Path, 1, Length(FDisplayHotTrack));
     end;
     DrawText(Canvas.Handle, PChar(Path), Length(Path), Rect, Flags);
   end;
@@ -434,7 +434,10 @@ end; { Notification }
 procedure TCustomPathLabel.MouseMove(Shift: TShiftState; X: Integer; Y: Integer);
 begin
   inherited;
-  if FMouseInView then Invalidate;
+  if FMouseInView and HotTrack and (FDisplayHotTrack <> HotTrackPath(FDisplayPath)) then
+  begin
+    Invalidate;
+  end;
 end;
 
 procedure TCustomPathLabel.DoPathClick(Path: string);

+ 12 - 3
release/winscpsetup.iss

@@ -11,7 +11,7 @@
 #define WebForum WebRoot+"forum/"
 #define WebDocumentation WebRoot+"eng/docs/"
 #define WebPuTTY "http://www.chiark.greenend.org.uk/~sgtatham/putty/"
-#define Year 2005
+#define Year 2006
 
 #ifexist "winscpsetup.tmp"
   #include "winscpsetup.tmp"
@@ -110,7 +110,7 @@ Name: custom; Description: {cm:CustomInstallation}; Flags: iscustom
 
 [Components]
 Name: main; Description: {cm:ApplicationComponent}; \
-  Types: {#FullLangs} full custom compact; Flags: fixed
+  Types: {#FullLangs} full custom compact
 Name: shellext; Description: {cm:ShellExtComponent}; \
   Types: {#FullLangs} compact full
 Name: pageant; Description: {cm:PageantComponent}; \
@@ -355,6 +355,12 @@ begin
   WizardForm.ActiveControl := TLabel(Sender).FocusControl;
 end;
 
+procedure ComponentsListClickCheck(Sender: TObject);
+begin
+  if not WizardForm.ComponentsList.Checked[0] then
+    WizardForm.ComponentsList.Checked[0] := True;
+end;
+
 procedure InitializeWizard();
 var
   UserInterface: Cardinal;
@@ -374,10 +380,13 @@ begin
   WizardForm.LicenseNotAcceptedRadio.Visible := False;
   WizardForm.LicenseMemo.Top := WizardForm.LicenseLabel1.Top;
   WizardForm.LicenseMemo.Height :=
-    WizardForm.LicenseNotAcceptedRadio.Top + 
+    WizardForm.LicenseNotAcceptedRadio.Top +
     WizardForm.LicenseNotAcceptedRadio.Height -
     WizardForm.LicenseMemo.Top - 5;
 
+  // prevent the main component to be unchecked
+  WizardForm.ComponentsList.OnClickCheck := @ComponentsListClickCheck;
+
   HelpButton := TButton.Create(WizardForm);
   HelpButton.Parent := WizardForm;
   HelpButton.Left :=

+ 49 - 2
windows/ConsoleRunner.cpp

@@ -808,6 +808,8 @@ void __fastcall TConsoleRunner::ScriptTerminalQueryUser(TObject * /*Sender*/,
   int CancelIndex;
   int AbortA = AbortAnswer(Answers);
   int AbortIndex;
+  int ContinueA = ContinueAnswer(Answers);
+  int ContinueIndex;
 
   for (int Index = 0; Index < ButtonCount; Index++)
   {
@@ -857,6 +859,10 @@ void __fastcall TConsoleRunner::ScriptTerminalQueryUser(TObject * /*Sender*/,
     {
       AbortIndex = Index + 1;
     }
+    if (Buttons[Index] == ContinueA)
+    {
+      ContinueIndex = Index + 1;
+    }
   }
 
   assert(Accels.Pos(' ') == 0);
@@ -881,7 +887,11 @@ void __fastcall TConsoleRunner::ScriptTerminalQueryUser(TObject * /*Sender*/,
   Print(Output);
 
   int AnswerIndex;
-  if (FScript->Batch != TScript::BatchOff)
+  if (FScript->Batch == TScript::BatchContinue)
+  {
+    AnswerIndex = ContinueIndex;
+  }
+  else if (FScript->Batch != TScript::BatchOff)
   {
     AnswerIndex = AbortIndex;
   }
@@ -1140,6 +1150,22 @@ void __fastcall TConsoleRunner::UpdateTitle()
   FConsole->SetTitle(NewTitle);
 }
 //---------------------------------------------------------------------------
+void __fastcall LoadScriptFromFile(AnsiString FileName, TStrings * Lines)
+{
+  AnsiString UTFBOM = "\xEF\xBB\xBF";
+  Lines->LoadFromFile(FileName);
+  if ((Lines->Count > 0) &&
+      (Lines->Strings[0].SubString(1, UTFBOM.Length()) == UTFBOM))
+  {
+    Lines->Strings[0] = Lines->Strings[0].SubString(
+      UTFBOM.Length() + 1, Lines->Strings[0].Length() - UTFBOM.Length());
+    for (int Index = 0; Index < Lines->Count; Index++)
+    {
+      Lines->Strings[Index] = DecodeUTF(Lines->Strings[Index]);
+    }
+  }
+}
+//---------------------------------------------------------------------------
 int __fastcall Console(TProgramParams * Params, bool Help)
 {
   int Result = 0;
@@ -1183,15 +1209,36 @@ int __fastcall Console(TProgramParams * Params, bool Help)
         AnsiString Value;
         if (Params->FindSwitch("script", Value) && !Value.IsEmpty())
         {
-          ScriptCommands->LoadFromFile(Value);
+          LoadScriptFromFile(Value, ScriptCommands);
         }
         Params->FindSwitch("command", ScriptCommands);
 
+        bool Url = false;
         AnsiString Session;
         if (Params->ParamCount >= 1)
         {
           Session = Params->Param[1];
         }
+
+        bool DefaultsOnly;
+        delete StoredSessions->ParseUrl(Session, DefaultsOnly,
+          puDecodeUrlChars, NULL, &Url);
+
+        if (Url)
+        {
+          // prevent any automatic action when URL is provided on
+          // command-line
+          ScriptCommands->Clear();
+        }
+        else
+        {
+          AnsiString LogFile;
+          if (Params->FindSwitch("Log", LogFile))
+          {
+            Configuration->TemporaryLogging(LogFile);
+          }
+        }
+
         Result = Runner->Run(Session,
           (ScriptCommands->Count > 0 ? ScriptCommands : NULL));
       }

+ 20 - 10
windows/WinMain.cpp

@@ -20,13 +20,14 @@
 //---------------------------------------------------------------------------
 #pragma package(smart_init)
 //---------------------------------------------------------------------------
-TSessionData * GetLoginData(AnsiString SessionName, AnsiString & DownloadFile)
+TSessionData * GetLoginData(AnsiString SessionName, AnsiString & DownloadFile,
+  bool & Url)
 {
   bool DefaultsOnly;
   TSessionData * Data;
 
   Data = StoredSessions->ParseUrl(SessionName, DefaultsOnly,
-    puExtractFileName | puDecodeUrlChars, &DownloadFile);
+    puExtractFileName | puDecodeUrlChars, &DownloadFile, &Url);
   assert(Data != NULL);
 
   if (!Data->CanLogin || DefaultsOnly)
@@ -193,12 +194,6 @@ int __fastcall Execute(TProgramParams * Params)
     WinConfiguration->DefaultKeyFile = KeyFile;
   }
 
-  AnsiString LogFile;
-  if (Params->FindSwitch("Log", LogFile))
-  {
-    Configuration->TemporaryLogging(LogFile);
-  }
-
   bool Help = Params->FindSwitch("help") || Params->FindSwitch("h") || Params->FindSwitch("?");
   if (Help || Params->FindSwitch("Console") || Params->FindSwitch("script") ||
       Params->FindSwitch("command"))
@@ -337,9 +332,25 @@ int __fastcall Execute(TProgramParams * Params)
       do
       {
         Retry = false;
-        Data = GetLoginData(AutoStartSession, DownloadFile);
+        bool Url = false;
+        Data = GetLoginData(AutoStartSession, DownloadFile, Url);
         if (Data)
         {
+          if (Url)
+          {
+            // prevent any automatic action when URL is provided on
+            // command-line
+            UseDefaults = false;
+          }
+          else
+          {
+            AnsiString LogFile;
+            if (Params->FindSwitch("Log", LogFile))
+            {
+              Configuration->TemporaryLogging(LogFile);
+            }
+          }
+
           if ((Data->FSProtocol == fsExternalSSH) ||
               (Data->FSProtocol == fsExternalSFTP))
           {
@@ -428,4 +439,3 @@ int __fastcall Execute(TProgramParams * Params)
 
   return 0;
 }
-