Kaynağa Gözat

Script commands and .NET assembly classes and methods in generated code link to online documentation

Source commit: 1a2ed974b8e5b0d6ca4291262ea68ebe8779de2d
Martin Prikryl 9 yıl önce
ebeveyn
işleme
799efb62bb

+ 37 - 3
source/core/Common.cpp

@@ -50,6 +50,17 @@ UnicodeString DeleteChar(UnicodeString Str, wchar_t C)
   return Str;
 }
 //---------------------------------------------------------------------------
+int PosFrom(const UnicodeString & SubStr, const UnicodeString & Str, int Index)
+{
+  UnicodeString S = Str.SubString(Index, Str.Length() - Index + 1);
+  int Result = S.Pos(SubStr);
+  if (Result > 0)
+  {
+    Result += Index - 1;
+  }
+  return Result;
+}
+//---------------------------------------------------------------------------
 template<typename T>
 void DoPackStr(T & Str)
 {
@@ -2582,6 +2593,20 @@ TStringList * __fastcall TextToStringList(const UnicodeString & Text)
   return List.release();
 }
 //---------------------------------------------------------------------------
+UnicodeString __fastcall StringsToText(TStrings * Strings)
+{
+  UnicodeString Result;
+  if (Strings->Count == 1)
+  {
+    Result = Strings->Strings[0];
+  }
+  else
+  {
+    Result = Strings->Text;
+  }
+  return Result;
+}
+//---------------------------------------------------------------------------
 TStrings * __fastcall CloneStrings(TStrings * Strings)
 {
   std::unique_ptr<TStringList> List(new TStringList());
@@ -2890,6 +2915,8 @@ bool __fastcall IsHttpUrl(const UnicodeString & S)
 }
 //---------------------------------------------------------------------------
 const UnicodeString RtfPara = L"\\par\n";
+const UnicodeString RtfHyperlinkField = L"HYPERLINK";
+const UnicodeString RtfHyperlinkFieldPrefix = RtfHyperlinkField + L" \"";
 //---------------------------------------------------------------------
 UnicodeString __fastcall RtfColor(int Index)
 {
@@ -2939,15 +2966,22 @@ UnicodeString __fastcall RtfColorItalicText(int Color, const UnicodeString & Tex
 //---------------------------------------------------------------------
 UnicodeString __fastcall RtfKeyword(const UnicodeString & Text)
 {
-  return RtfColorText(4, Text);
+  return RtfColorText(5, Text);
 }
 //---------------------------------------------------------------------
 UnicodeString __fastcall RtfParameter(const UnicodeString & Text)
 {
-  return RtfColorText(5, Text);
+  return RtfColorText(6, Text);
 }
 //---------------------------------------------------------------------
 UnicodeString __fastcall RtfString(const UnicodeString & Text)
 {
-  return RtfColorText(3, Text);
+  return RtfColorText(4, Text);
+}
+//---------------------------------------------------------------------
+UnicodeString __fastcall RtfLink(const UnicodeString & Link, const UnicodeString & RtfText)
+{
+  return
+    L"{\\field{\\*\\fldinst{HYPERLINK \"" + Link + L"\" }}{\\fldrslt{" +
+    RtfText + L"}}}";
 }

+ 5 - 0
source/core/Common.h

@@ -26,6 +26,7 @@ extern const UnicodeString PasswordMask;
 //---------------------------------------------------------------------------
 UnicodeString ReplaceChar(UnicodeString Str, wchar_t A, wchar_t B);
 UnicodeString DeleteChar(UnicodeString Str, wchar_t C);
+int PosFrom(const UnicodeString & SubStr, const UnicodeString & Str, int Index);
 void PackStr(UnicodeString & Str);
 void PackStr(RawByteString & Str);
 void PackStr(AnsiString & Str);
@@ -125,6 +126,7 @@ UnicodeString __fastcall FormatNumber(__int64 Size);
 UnicodeString __fastcall FormatSize(__int64 Size);
 UnicodeString __fastcall ExtractFileBaseName(const UnicodeString & Path);
 TStringList * __fastcall TextToStringList(const UnicodeString & Text);
+UnicodeString __fastcall StringsToText(TStrings * Strings);
 TStrings * __fastcall CloneStrings(TStrings * Strings);
 UnicodeString __fastcall TrimVersion(UnicodeString Version);
 UnicodeString __fastcall FormatVersion(int MajovVersion, int MinorVersion, int Release);
@@ -200,6 +202,8 @@ MethodT __fastcall MakeMethod(void * Data, void * Code)
 }
 //---------------------------------------------------------------------------
 extern const UnicodeString RtfPara;
+extern const UnicodeString RtfHyperlinkField;
+extern const UnicodeString RtfHyperlinkFieldPrefix;
 //---------------------------------------------------------------------
 UnicodeString __fastcall RtfText(const UnicodeString & Text);
 UnicodeString __fastcall RtfColor(int Index);
@@ -208,6 +212,7 @@ UnicodeString __fastcall RtfColorText(int Color, const UnicodeString & Text);
 UnicodeString __fastcall RtfKeyword(const UnicodeString & Text);
 UnicodeString __fastcall RtfParameter(const UnicodeString & Text);
 UnicodeString __fastcall RtfString(const UnicodeString & Text);
+UnicodeString __fastcall RtfLink(const UnicodeString & Link, const UnicodeString & RtfText);
 //---------------------------------------------------------------------------
 #include "Global.h"
 //---------------------------------------------------------------------------

+ 25 - 15
source/core/SessionData.cpp

@@ -2563,12 +2563,22 @@ void __fastcall TSessionData::LookupLastFingerprint()
 //---------------------------------------------------------------------
 static UnicodeString __fastcall RtfCodeComment(const UnicodeString & Text)
 {
-  return RtfColorItalicText(1, Text);
+  return RtfColorItalicText(2, Text);
 }
 //---------------------------------------------------------------------
 static UnicodeString __fastcall RtfClass(const UnicodeString & Text)
 {
-  return RtfColorText(2, Text);
+  return RtfColorText(3, Text);
+}
+//---------------------------------------------------------------------
+static UnicodeString __fastcall RtfLibraryClass(const UnicodeString & ClassName)
+{
+  return RtfLink(L"library_" + ClassName.LowerCase(), RtfClass(ClassName));
+}
+//---------------------------------------------------------------------
+static UnicodeString __fastcall RtfLibraryMethod(const UnicodeString & ClassName, const UnicodeString & MethodName)
+{
+  return RtfLink(L"library_" + ClassName.LowerCase() + L"_" + MethodName.LowerCase(), RtfColorText(1, MethodName));
 }
 //---------------------------------------------------------------------
 UnicodeString __fastcall TSessionData::GenerateOpenCommandArgs()
@@ -2780,14 +2790,14 @@ UnicodeString __fastcall TSessionData::GenerateAssemblyCode(
     case alCSharp:
       SessionOptionsPreamble =
         RtfCodeComment(L"// %s") + RtfPara +
-        RtfClass(L"SessionOptions") + RtfText(L" sessionOptions = ") + RtfKeyword(L"new") + RtfText(" ") + RtfClass(L"SessionOptions") + RtfPara +
+        RtfLibraryClass(L"SessionOptions") + RtfText(L" sessionOptions = ") + RtfKeyword(L"new") + RtfText(" ") + RtfLibraryClass(L"SessionOptions") + RtfPara +
         RtfText(L"{") + RtfPara;
       break;
 
     case alVBNET:
       SessionOptionsPreamble =
         RtfCodeComment(L"' %s") + RtfPara +
-        RtfKeyword(L"Dim") + RtfText(" mySessionOptions ") + RtfKeyword(L"As") + RtfText(L" ") + RtfKeyword(L"New") + RtfText(" ") + RtfClass(L"SessionOptions") + RtfPara +
+        RtfKeyword(L"Dim") + RtfText(" mySessionOptions ") + RtfKeyword(L"As") + RtfText(L" ") + RtfKeyword(L"New") + RtfText(" ") + RtfLibraryClass(L"SessionOptions") + RtfPara +
         RtfKeyword(L"With") + RtfText(" mySessionOptions") + RtfPara;
       break;
 
@@ -2797,7 +2807,7 @@ UnicodeString __fastcall TSessionData::GenerateAssemblyCode(
         RtfKeyword(L"Add-Type") + RtfText(" -Path ") + AssemblyString(Language, "WinSCPnet.dll") + RtfPara +
         RtfPara +
         RtfCodeComment(L"# %s") + RtfPara +
-        RtfText(L"$sessionOptions = ") + RtfKeyword(L"New-Object") + RtfText(" WinSCP.") + RtfClass(L"SessionOptions") + RtfPara;
+        RtfText(L"$sessionOptions = ") + RtfKeyword(L"New-Object") + RtfText(" WinSCP.") + RtfLibraryClass(L"SessionOptions") + RtfPara;
       break;
 
     default:
@@ -2964,15 +2974,15 @@ UnicodeString __fastcall TSessionData::GenerateAssemblyCode(
       switch (Language)
       {
         case alCSharp:
-          SettingsCode = RtfText(L"sessionOptions.AddRawSettings(%s, %s);") + RtfPara;
+          SettingsCode = RtfText(L"sessionOptions.") + RtfLibraryMethod(L"SessionOptions", L"AddRawSettings") + RtfText(L"(%s, %s);") + RtfPara;
           break;
 
         case alVBNET:
-          SettingsCode = RtfText(L"    .AddRawSettings(%s, %s)") + RtfPara;
+          SettingsCode = RtfText(L"    .") + RtfLibraryMethod(L"SessionOptions", L"AddRawSettings") + RtfText(L"(%s, %s)") + RtfPara;
           break;
 
         case alPowerShell:
-          SettingsCode = RtfText(L"$sessionOptions.AddRawSettings(%s, %s)") + RtfPara;
+          SettingsCode = RtfText(L"$sessionOptions.") + RtfLibraryMethod(L"SessionOptions", L"AddRawSettings") + RtfText(L"(%s, %s)") + RtfPara;
           break;
       }
       Result += FORMAT(SettingsCode, (AssemblyString(Language, Name), AssemblyString(Language, Value)));
@@ -2986,10 +2996,10 @@ UnicodeString __fastcall TSessionData::GenerateAssemblyCode(
     case alCSharp:
       SessionCode =
         RtfPara +
-        RtfKeyword(L"using") + RtfText(" (") + RtfClass(L"Session") + RtfText(L" session = ") + RtfKeyword(L"new") + RtfText(" ") + RtfClass(L"Session") + RtfText(L"())") + RtfPara +
+        RtfKeyword(L"using") + RtfText(" (") + RtfLibraryClass(L"Session") + RtfText(L" session = ") + RtfKeyword(L"new") + RtfText(" ") + RtfLibraryClass(L"Session") + RtfText(L"())") + RtfPara +
         RtfText(L"{") + RtfPara +
         RtfCodeComment(L"    // %s") + RtfPara +
-        RtfText(L"    session.Open(sessionOptions);") + RtfPara +
+        RtfText(L"    session.") + RtfLibraryMethod(L"Session", L"Open") + RtfText(L"(sessionOptions);") + RtfPara +
         RtfPara +
         RtfCodeComment(L"    // %s") + RtfPara +
         RtfText(L"}") + RtfPara;
@@ -2999,9 +3009,9 @@ UnicodeString __fastcall TSessionData::GenerateAssemblyCode(
       SessionCode =
         RtfKeyword(L"End With") + RtfPara +
         RtfPara +
-        RtfKeyword(L"Using") + RtfText(" mySession As ") + RtfClass(L"Session") + RtfText(L" = ") + RtfKeyword(L"New") + RtfText(" ") + RtfClass(L"Session") + RtfPara +
+        RtfKeyword(L"Using") + RtfText(" mySession As ") + RtfLibraryClass(L"Session") + RtfText(L" = ") + RtfKeyword(L"New") + RtfText(" ") + RtfLibraryClass(L"Session") + RtfPara +
         RtfCodeComment(L"    ' %s") + RtfPara +
-        RtfText(L"    mySession.Open(mySessionOptions)") + RtfPara +
+        RtfText(L"    mySession.") + RtfLibraryMethod(L"Session", L"Open") + RtfText(L"(mySessionOptions)") + RtfPara +
         RtfPara +
         RtfCodeComment(L"    ' %s") + RtfPara +
         RtfKeyword(L"End Using");
@@ -3010,18 +3020,18 @@ UnicodeString __fastcall TSessionData::GenerateAssemblyCode(
     case alPowerShell:
       SessionCode =
         RtfPara +
-        RtfText(L"$session = ") + RtfKeyword(L"New-Object") + RtfText(" WinSCP.") + RtfClass(L"Session") + RtfPara +
+        RtfText(L"$session = ") + RtfKeyword(L"New-Object") + RtfText(" WinSCP.") + RtfLibraryClass(L"Session") + RtfPara +
         RtfPara +
         RtfKeyword(L"try") + RtfPara +
         RtfText(L"{") + RtfPara +
         RtfCodeComment(L"    # %s") + RtfPara +
-        RtfText(L"    $session.Open($sessionOptions)") + RtfPara +
+        RtfText(L"    $session.") + RtfLibraryMethod(L"Session", L"Open") + RtfText(L"($sessionOptions)") + RtfPara +
         RtfPara +
         RtfCodeComment(L"    # %s") + RtfPara +
         RtfText(L"}") + RtfPara +
         RtfKeyword(L"finally") + RtfPara +
         RtfText(L"{") + RtfPara +
-        RtfText(L"    $session.Dispose()") + RtfPara +
+        RtfText(L"    $session.") + RtfLibraryMethod(L"Session", L"Dispose") + RtfText(L"()") + RtfPara +
         RtfText(L"}") + RtfPara;
       break;
   }

+ 167 - 28
source/forms/GenerateUrl.cpp

@@ -22,6 +22,104 @@ void __fastcall DoGenerateUrlDialog(TSessionData * Data, TStrings * Paths)
   Dialog->Execute();
 }
 //---------------------------------------------------------------------------
+// Rich edit 4.1 supports "Friendly name hyperlinks"
+class TRichEdit41 : public TRichEdit
+{
+public:
+  virtual __fastcall TRichEdit41(TComponent * AOwner);
+
+protected:
+  virtual void __fastcall CreateWnd();
+  virtual void __fastcall CreateParams(TCreateParams & Params);
+  virtual void __fastcall DestroyWnd();
+  void __fastcall Dispatch(void * Message);
+
+private:
+  HINSTANCE FLibrary;
+};
+//---------------------------------------------------------------------------
+__fastcall TRichEdit41::TRichEdit41(TComponent * AOwner) :
+  TRichEdit(AOwner),
+  FLibrary(0)
+{
+}
+//---------------------------------------------------------------------------
+void __fastcall TRichEdit41::CreateParams(TCreateParams & Params)
+{
+  UnicodeString RichEditModuleName(L"MSFTEDIT.DLL");
+  long int OldError;
+
+  OldError = SetErrorMode(SEM_NOOPENFILEERRORBOX);
+  FLibrary = LoadLibrary(RichEditModuleName.c_str());
+  SetErrorMode(OldError);
+
+  TCustomMemo::CreateParams(Params);
+  // Should not happen as
+  if (FLibrary != 0)
+  {
+    // MSDN says that we should use MSFTEDIT_CLASS to load Rich Edit 4.1:
+    // https://msdn.microsoft.com/en-us/library/windows/desktop/bb787873.aspx
+    // But MSFTEDIT_CLASS is defined as "RICHEDIT50W",
+    // so not sure what version we are loading.
+    // Seem to work on Windows XP SP3.
+    CreateSubClass(Params, MSFTEDIT_CLASS);
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TRichEdit41::CreateWnd()
+{
+  TRichEdit::CreateWnd();
+  int Mask = SendMessage(Handle, EM_GETEVENTMASK, 0, 0);
+  SendMessage(Handle, EM_SETEVENTMASK, 0, Mask | ENM_LINK);
+}
+//---------------------------------------------------------------------------
+void __fastcall TRichEdit41::Dispatch(void * AMessage)
+{
+  TMessage & Message = *reinterpret_cast<TMessage *>(AMessage);
+  if (Message.Msg == CN_NOTIFY)
+  {
+    TWMNotify & WMNotify = *reinterpret_cast<TWMNotify *>(AMessage);
+    if (WMNotify.NMHdr->code == EN_LINK)
+    {
+      TENLink & ENLink = *reinterpret_cast<TENLink *>(Message.LParam);
+      if (ENLink.msg == WM_LBUTTONDOWN)
+      {
+        TCharRange CharRange;
+        SendGetStructMessage(Handle, EM_EXGETSEL, 0, &CharRange);
+        SendGetStructMessage(Handle, EM_EXSETSEL, 0, &ENLink.chrg);
+        UnicodeString S = SelText;
+        if (DebugAlwaysTrue(StartsStr(RtfHyperlinkFieldPrefix, S)))
+        {
+          int P1 = RtfHyperlinkFieldPrefix.Length() + 1;
+          int P2 = PosFrom(L"\"", S, P1);
+          if (DebugAlwaysTrue(P2 > 0))
+          {
+            UnicodeString Url = S.SubString(P1, P2 - P1);
+            ShowHelp(Url);
+          }
+        }
+        SendGetStructMessage(Handle, EM_EXSETSEL, 0, &CharRange);
+      }
+    }
+    TRichEdit::Dispatch(AMessage);
+  }
+  else
+  {
+    TRichEdit::Dispatch(AMessage);
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TRichEdit41::DestroyWnd()
+{
+  TRichEdit::DestroyWnd();
+
+  if (FLibrary != 0)
+  {
+    FreeLibrary(FLibrary);
+  }
+}
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
 __fastcall TGenerateUrlDialog::TGenerateUrlDialog(
   TComponent * Owner, TSessionData * Data, TStrings * Paths)
   : TForm(Owner)
@@ -30,7 +128,20 @@ __fastcall TGenerateUrlDialog::TGenerateUrlDialog(
   FData = Data;
   FPaths = Paths;
   FChanging = false;
-  ReadOnlyControl(ResultMemo);
+
+  FResultMemo41 = new TRichEdit41(this);
+  FResultMemo41->Parent = ResultMemo->Parent;
+  FResultMemo41->SetBounds(ResultMemo->Left, ResultMemo->Top, ResultMemo->Width, ResultMemo->Height);
+  FResultMemo41->Anchors = ResultMemo->Anchors;
+  FResultMemo41->BevelInner = ResultMemo->BevelInner;
+  FResultMemo41->BevelOuter = ResultMemo->BevelOuter;
+  FResultMemo41->BorderStyle = ResultMemo->BorderStyle;
+  FResultMemo41->PopupMenu = ResultMemo->PopupMenu;
+  FResultMemo41->TabOrder = ResultMemo->TabOrder;
+  FResultMemo41->PlainText = false;
+  ResultMemo->Visible = false;
+
+  ReadOnlyControl(FResultMemo41);
 }
 //---------------------------------------------------------------------------
 bool __fastcall TGenerateUrlDialog::IsFileUrl()
@@ -73,7 +184,12 @@ static UnicodeString __fastcall RtfColorEntry(int Color)
 //---------------------------------------------------------------------
 static UnicodeString __fastcall RtfScriptComment(const UnicodeString & Text)
 {
-  return RtfColorItalicText(6, Text);
+  return RtfColorItalicText(7, Text);
+}
+//---------------------------------------------------------------------
+static UnicodeString __fastcall RtfScriptCommand(const UnicodeString & Command)
+{
+  return RtfLink(L"scriptcommand_" + Command, RtfKeyword(Command));
 }
 //---------------------------------------------------------------------------
 void __fastcall TGenerateUrlDialog::UpdateControls()
@@ -155,7 +271,7 @@ void __fastcall TGenerateUrlDialog::UpdateControls()
           Result += RtfText(Url) + RtfPara;
           FPlainResult +=
             Url +
-            // What CopyToClipboard would have done could we pass in ResultMemo->Lines
+            // What CopyToClipboard would have done could we pass in FResultMemo41->Lines
             ((FPaths->Count > 0) ? L"\n" : L"");
         }
       }
@@ -172,12 +288,12 @@ void __fastcall TGenerateUrlDialog::UpdateControls()
       {
         Result =
           FORMAT(
-            RtfKeyword(L"open") + L" %s" + RtfPara +
+            RtfScriptCommand(L"open") + L" %s" + RtfPara +
             RtfPara +
             RtfScriptComment("# %s") + RtfPara +
             RtfScriptComment("# %s") + RtfPara +
             RtfPara +
-            RtfKeyword(L"exit") + RtfPara,
+            RtfScriptCommand(L"exit") + RtfPara,
             (OpenCommand, CommandPlaceholder1, CommandPlaceholder2));
         WordWrap = false;
         FixedWidth = true;
@@ -190,10 +306,10 @@ void __fastcall TGenerateUrlDialog::UpdateControls()
           RtfScriptComment(L"@echo off") + RtfPara +
           RtfPara +
           RtfText(L"\"" + ComExeName + "\" ") + RtfParameter(L"/log") + RtfText(L"=" + BaseExeName + L".log ") + RtfParameter(L"/ini") + RtfText(L"=nul ") + RtfParameter(L"/command") + RtfText(L" ^") + RtfPara +
-          RtfText(L"  \"") + RtfKeyword(L"open") + RtfText(L" ") + EscapeParam(ReplaceStr(OpenCommand, L"%", L"%%")) + RtfText(L"\" ^") + RtfPara +
+          RtfText(L"  \"") + RtfScriptCommand(L"open") + RtfText(L" ") + EscapeParam(ReplaceStr(OpenCommand, L"%", L"%%")) + RtfText(L"\" ^") + RtfPara +
           RtfText(L"  \"") + RtfScriptComment(CommandPlaceholder1) + RtfText(L"\" ^") + RtfPara +
           RtfText(L"  \"") + RtfScriptComment(CommandPlaceholder2) + RtfText(L"\" ^") + RtfPara +
-          RtfText(L"  \"") + RtfKeyword(L"exit") + RtfText(L"\"") + RtfPara +
+          RtfText(L"  \"") + RtfScriptCommand(L"exit") + RtfText(L"\"") + RtfPara +
           RtfPara +
           RtfKeyword(L"set") + RtfText(L" WINSCP_RESULT=%ERRORLEVEL%") + RtfPara +
           RtfKeyword(L"if") + RtfText(L" %WINSCP_RESULT% ") + RtfKeyword(L"equ") + RtfText(L" 0 (") + RtfPara +
@@ -212,10 +328,10 @@ void __fastcall TGenerateUrlDialog::UpdateControls()
           RtfParameter(L"/log") + RtfText(L"=" + BaseExeName + L".log ") +
           RtfParameter(L"/ini") + RtfText(L"=nul ") +
           RtfParameter(L"/command") + RtfText(L" ") +
-            RtfText(L"\"") + RtfKeyword(L"open") + RtfText(L" ") + EscapeParam(OpenCommand) + RtfText(L"\" ") +
+            RtfText(L"\"") + RtfScriptCommand(L"open") + RtfText(L" ") + EscapeParam(OpenCommand) + RtfText(L"\" ") +
             RtfText(L"\"") + RtfScriptComment(CommandPlaceholder1) + RtfText(L"\" ") +
             RtfText(L"\"") + RtfScriptComment(CommandPlaceholder2) + RtfText(L"\" ") +
-            RtfText(L"\"") + RtfKeyword(L"exit") + RtfText(L"\"");
+            RtfText(L"\"") + RtfScriptCommand(L"exit") + RtfText(L"\"");
         WordWrap = true;
         FixedWidth = false;
       }
@@ -229,39 +345,39 @@ void __fastcall TGenerateUrlDialog::UpdateControls()
 
     if (FixedWidth)
     {
-      ResultMemo->Font->Name = CustomWinConfiguration->DefaultFixedWidthFontName;
-      ResultMemo->DefAttributes->Color = clWindowText;
+      FResultMemo41->Font->Name = CustomWinConfiguration->DefaultFixedWidthFontName;
     }
     else
     {
-      ResultMemo->ParentFont = true;
+      FResultMemo41->ParentFont = true;
     }
 
     Result =
       L"{\\rtf1\n"
        "{\\colortbl ;" +
        // The same RGB as on wiki
-       RtfColorEntry(0x008000) + // cde comment (green)
+       RtfColorEntry(0x010101) + // near-black fake color to be used with no-style link to ovreride the default blue underline
+       RtfColorEntry(0x008000) + // code comment (green)
        RtfColorEntry(0x008080) + // class (teal)
        RtfColorEntry(0x800000) + // string (maroon)
        RtfColorEntry(0x0000FF) + // keyword (blue)
        RtfColorEntry(0x993333) + // command-line argument (reddish)
        RtfColorEntry(0x808080) + // script command (gray)
       L"}\n"
-       "{\\fonttbl{\\f0\\fnil\\fcharset0 " + ResultMemo->Font->Name + L";}}\n"
-       "\\f0\\fs" + IntToStr(ResultMemo->Font->Size * 2) + L" " +
+       "{\\fonttbl{\\f0\\fnil\\fcharset0 " + FResultMemo41->Font->Name + L";}}\n"
+       "\\f0\\fs" + IntToStr(FResultMemo41->Font->Size * 2) + L" " +
        Result +
-      L"}";
+      "}";
 
-    ResultMemo->WordWrap = WordWrap;
-    ResultMemo->ScrollBars = WordWrap ? ssVertical : ssBoth;
+    FResultMemo41->WordWrap = WordWrap;
+    FResultMemo41->ScrollBars = WordWrap ? ssVertical : ssBoth;
 
     std::unique_ptr<TMemoryStream> Stream(new TMemoryStream());
     UTF8String ResultUtf = Result;
     Stream->Write(ResultUtf.c_str(), ResultUtf.Length());
     Stream->Position = 0;
 
-    ResultMemo->Lines->LoadFromStream(Stream.get(), TEncoding::UTF8);
+    FResultMemo41->Lines->LoadFromStream(Stream.get(), TEncoding::UTF8);
   }
 }
 //---------------------------------------------------------------------------
@@ -376,34 +492,52 @@ void __fastcall TGenerateUrlDialog::ControlChange(TObject * /*Sender*/)
 void __fastcall TGenerateUrlDialog::ClipboardButtonClick(TObject * /*Sender*/)
 {
   TInstantOperationVisualizer Visualizer;
-  if (ResultMemo->WordWrap)
+  UnicodeString Text;
+  if (FResultMemo41->WordWrap)
   {
-    // Cannot read the text from ResultMemo->Lines as TRichEdit (as opposite to TMemo)
+    // Cannot read the text from FResultMemo41->Lines as TRichEdit (as opposite to TMemo)
     // breaks wrapped lines
 
     if (!FPlainResult.IsEmpty())
     {
-      CopyToClipboard(FPlainResult);
+      Text = FPlainResult;
     }
     else
     {
       // We get here with command-line only,
       // where we know to have a single line only
       DebugAssert((OptionsPageControl->ActivePage == ScriptSheet) && (ScriptFormatCombo->ItemIndex == sfCommandLine));
-      UnicodeString Text;
-      for (int Index = 0; Index < ResultMemo->Lines->Count; Index++)
+      for (int Index = 0; Index < FResultMemo41->Lines->Count; Index++)
       {
-        Text += ResultMemo->Lines->Strings[Index];
+        Text += FResultMemo41->Lines->Strings[Index];
       }
-      CopyToClipboard(Text);
     }
   }
   else
   {
     // On the other hand, the FResult contains RTF markup
-    // in which case we want to use ResultMemo->Lines
-    CopyToClipboard(ResultMemo->Lines);
+    // in which case we want to use FResultMemo41->Lines
+    Text = StringsToText(FResultMemo41->Lines);
   }
+
+  int P;
+  int Index = 1;
+  while ((P = PosFrom(RtfHyperlinkFieldPrefix, Text, Index)) > 0)
+  {
+    int Index2 = P + RtfHyperlinkFieldPrefix.Length();
+    UnicodeString RtfHyperlinkFieldSuffix = L"\" ";
+    int P2 = PosFrom(RtfHyperlinkFieldSuffix, Text, Index2);
+    if (P2 > 0)
+    {
+      Text.Delete(P, P2 - P + RtfHyperlinkFieldSuffix.Length());
+    }
+    else
+    {
+      Index = Index2;
+    }
+  }
+
+  CopyToClipboard(Text);
 }
 //---------------------------------------------------------------------------
 void __fastcall TGenerateUrlDialog::HelpButtonClick(TObject * /*Sender*/)
@@ -448,3 +582,8 @@ void __fastcall TGenerateUrlDialog::ResultMemoContextPopup(TObject * Sender,
   MenuPopup(Sender, MousePos, Handled);
 }
 //---------------------------------------------------------------------------
+void __fastcall TGenerateUrlDialog::FormShow(TObject * /*Sender*/)
+{
+  UpdateControls();
+}
+//---------------------------------------------------------------------------

+ 2 - 3
source/forms/GenerateUrl.dfm

@@ -14,6 +14,7 @@ object GenerateUrlDialog: TGenerateUrlDialog
   ParentFont = True
   OldCreateOrder = True
   Position = poOwnerFormCenter
+  OnShow = FormShow
   DesignSize = (
     484
     338)
@@ -172,7 +173,7 @@ object GenerateUrlDialog: TGenerateUrlDialog
     DesignSize = (
       468
       176)
-    object ResultMemo: TRichEdit
+    object ResultMemo: TMemo
       Left = 7
       Top = 15
       Width = 454
@@ -183,9 +184,7 @@ object GenerateUrlDialog: TGenerateUrlDialog
       BevelOuter = bvNone
       BorderStyle = bsNone
       PopupMenu = ResultPopupMenu
-      ScrollBars = ssVertical
       TabOrder = 0
-      Zoom = 100
       OnContextPopup = ResultMemoContextPopup
     end
   end

+ 5 - 1
source/forms/GenerateUrl.h

@@ -14,11 +14,13 @@
 #include <Vcl.ActnList.hpp>
 #include <Vcl.StdActns.hpp>
 //---------------------------------------------------------------------------
+class TRichEdit41;
+//---------------------------------------------------------------------------
 class TGenerateUrlDialog : public TForm
 {
 __published:
   TGroupBox *ResultGroup;
-  TRichEdit *ResultMemo;
+  TMemo *ResultMemo;
   TButton *CancelBtn;
   TButton *HelpButton;
   TButton *ClipboardButton;
@@ -47,12 +49,14 @@ __published:
   void __fastcall HelpButtonClick(TObject *Sender);
   void __fastcall WMNCCreate(TWMNCCreate & Message);
   void __fastcall ResultMemoContextPopup(TObject *Sender, TPoint &MousePos, bool &Handled);
+  void __fastcall FormShow(TObject *Sender);
 
 private:
   TSessionData * FData;
   TStrings * FPaths;
   bool FChanging;
   UnicodeString FPlainResult;
+  TRichEdit41 * FResultMemo41;
 
 protected:
   void __fastcall UpdateControls();

+ 12 - 8
source/windows/Tools.cpp

@@ -538,6 +538,17 @@ void __fastcall OpenBrowser(UnicodeString URL)
   ShellExecute(Application->Handle, L"open", URL.c_str(), NULL, NULL, SW_SHOWNORMAL);
 }
 //---------------------------------------------------------------------------
+void __fastcall ShowHelp(const UnicodeString & AHelpKeyword)
+{
+  // see also AppendUrlParams
+  UnicodeString HelpKeyword = AHelpKeyword;
+  const wchar_t FragmentSeparator = L'#';
+  UnicodeString HelpPath = CutToChar(HelpKeyword, FragmentSeparator, false);
+  UnicodeString HelpUrl = FMTLOAD(DOCUMENTATION_KEYWORD_URL2, (HelpPath, Configuration->ProductVersion, GUIConfiguration->LocaleHex));
+  AddToList(HelpUrl, HelpKeyword, FragmentSeparator);
+  OpenBrowser(HelpUrl);
+}
+//---------------------------------------------------------------------------
 bool __fastcall IsFormatInClipboard(unsigned int Format)
 {
   bool Result = OpenClipboard(0);
@@ -870,14 +881,7 @@ void __fastcall CopyToClipboard(TStrings * Strings)
 {
   if (Strings->Count > 0)
   {
-    if (Strings->Count == 1)
-    {
-      CopyToClipboard(Strings->Strings[0]);
-    }
-    else
-    {
-      CopyToClipboard(Strings->Text);
-    }
+    CopyToClipboard(StringsToText(Strings));
   }
 }
 //---------------------------------------------------------------------------

+ 1 - 0
source/windows/Tools.h

@@ -38,6 +38,7 @@ void __fastcall ValidateMaskEdit(TComboBox * Edit);
 void __fastcall ValidateMaskEdit(TEdit * Edit);
 void __fastcall ValidateMaskEdit(TMemo * Edit, bool Directory);
 void __fastcall OpenBrowser(UnicodeString URL);
+void __fastcall ShowHelp(const UnicodeString & HelpKeyword);
 bool __fastcall IsFormatInClipboard(unsigned int Format);
 bool __fastcall TextFromClipboard(UnicodeString & Text, bool Trim);
 bool __fastcall NonEmptyTextFromClipboard(UnicodeString & Text);

+ 2 - 9
source/windows/WinHelp.cpp

@@ -99,19 +99,12 @@ void __fastcall TWebHelpSystem::ShowTableOfContents()
 //---------------------------------------------------------------------------
 void __fastcall TWebHelpSystem::ShowHelp(const UnicodeString AHelpString)
 {
-  UnicodeString HelpUrl;
   if (IsHttpUrl(AHelpString))
   {
-    HelpUrl = AHelpString;
+    OpenBrowser(AHelpString);
   }
   else
   {
-    // see also AppendUrlParams
-    UnicodeString HelpString = AHelpString;
-    const wchar_t FragmentSeparator = L'#';
-    UnicodeString HelpPath = CutToChar(HelpString, FragmentSeparator, false);
-    HelpUrl = FMTLOAD(DOCUMENTATION_KEYWORD_URL2, (HelpPath, FVersion, FLanguage));
-    AddToList(HelpUrl, HelpString, FragmentSeparator);
+    ShowHelp(AHelpString);
   }
-  OpenBrowser(HelpUrl);
 }