Przeglądaj źródła

Merge branch 'calltips'

Martijn Laan 1 rok temu
rodzic
commit
2e5d656151

+ 7 - 4
Components/ModernColors.pas

@@ -16,7 +16,7 @@ uses
 
 type
   TThemeType = (ttModernLight, ttModernDark, ttClassic);
-  TThemeColor = (tcFore, tcBack, tcToolBack, tcSelBack,
+  TThemeColor = (tcFore, tcBack, tcToolBack, tcSelBack, tcIntelliBack,
                  tcWordAtCursorOccurrenceBack, tcSelTextOccurrenceBack,
                  tcMarginFore, tcMarginBack, tcSplitterBack, tcBraceBack, tcIndentGuideFore,
                  tcRed, tcGreen, tcBlue, tcOrange, tcReallyOrange, tcPurple,
@@ -46,6 +46,7 @@ const
   DToolBack = $413E40;       { Monokai Pro }
   DSelBack = $764F1D;        { VSCode Modern Dark }
   //DSelInactiveBack = $51504F;{ VSCode Modern Dark }
+  DIntelliBack = $202020;    { VSCode Modern Dark }
   DWACOBack = $4A4A4A;       { VSCode Modern Dark }
   DSTOBACK = $403A33;        { VSCode Modern Dark }
   DMarginFore = $716F71;     { Monokai Pro }
@@ -60,6 +61,7 @@ const
   LToolBack = clBtnFace;
   LSelBack = $FDD6A7;        { VSCode Modern Light }
   //LSelInactiveBack = $F1EBE4;{ VSCode Modern Light }
+  LIntelliBack = $F8F8F8;    { VSCode Modern Light }
   LWACOBack = $ECECEC;       { Inno Setup 5, 4 tints lightened using color-hex.com }
   LSTOBACK = $FEEAD3;        { VSCode Modern Light }
   LMarginFore = $716F71;     { Monokai Pro }
@@ -72,6 +74,7 @@ const
   CBack = clWhite;
   CToolBack = clBtnFace;
   CSelBack = LSelBack;
+  CIntelliBack = LIntelliBack;
   CWACOBack = LWACOBack;
   CSTOBACK = LSTOBack;
   CMarginFore = clWindowText;
@@ -103,9 +106,9 @@ const
   CGray = $707070;           { Inno Setup 5 }
 
   Colors: array [TThemeType, TThemeColor] of TColor = (
-    (LFore, LBack, LToolBack, LSelBack, LWACOBack, LSTOBack, LMarginFore, LMarginBack, LSplitterBack, LBraceBack, LIndentGuideFore, MRed, MGreen, MBlue, MOrange, MOrange, MPurple, MYellow, MTeal, MGray),
-    (DFore, DBack, DToolBack, DSelBack, DWACOBack, DSTOBack, DMarginFore, DMarginBack, DSplitterBack, DBraceBack, DIndentGuideFore, MRed, MGreen, MBlue, MOrange, MOrange, MPurple, MYellow, MTeal, MGray),
-    (CFore, CBack, CToolBack, CSelBack, CWACOBack, CSTOBack, CMarginFore, CMarginBack, CSplitterBack, CBraceBack, CIndentGuideFore, CRed, CGreen, CBlue, COrange, CReallyOrange, CPurple, CYellow, CTeal, CGray)
+    (LFore, LBack, LToolBack, LSelBack, LIntelliBack, LWACOBack, LSTOBack, LMarginFore, LMarginBack, LSplitterBack, LBraceBack, LIndentGuideFore, MRed, MGreen, MBlue, MOrange, MOrange, MPurple, MYellow, MTeal, MGray),
+    (DFore, DBack, DToolBack, DSelBack, DIntelliBack, DWACOBack, DSTOBack, DMarginFore, DMarginBack, DSplitterBack, DBraceBack, DIndentGuideFore, MRed, MGreen, MBlue, MOrange, MOrange, MPurple, MYellow, MTeal, MGray),
+    (CFore, CBack, CToolBack, CSelBack, CIntelliBack, CWACOBack, CSTOBack, CMarginFore, CMarginBack, CSplitterBack, CBraceBack, CIndentGuideFore, CRed, CGreen, CBlue, COrange, CReallyOrange, CPurple, CYellow, CTeal, CGray)
   );
   
 begin

+ 74 - 8
Components/ScintEdit.pas

@@ -130,14 +130,19 @@ type
     FUseStyleAttributes: Boolean;
     FUseTabCharacter: Boolean;
     FVirtualSpaceOptions: TScintVirtualSpaceOptions;
+    FWordChars: AnsiString;
+    FWordCharsAsSet: TSysCharSet;
     FWordWrap: Boolean;
     procedure ApplyOptions;
     procedure ForwardMessage(const Message: TMessage);
     function GetAutoCompleteActive: Boolean;
+    function GetCallTipActive: Boolean;
     function GetCaretColumn: Integer;
     function GetCaretColumnExpandedForTabs: Integer;
     function GetCaretLine: Integer;
+    function GetCaretLineText: String;
     function GetCaretPosition: Integer;
+    function GetCaretPositionInLine: Integer;
     function GetCaretVirtualSpace: Integer;
     function GetInsertMode: Boolean;
     function GetLineEndings: TScintLineEndings;
@@ -146,6 +151,7 @@ type
     function GetLinesInWindow: Integer;
     function GetMainSelText: String;
     function GetModified: Boolean;
+    function GetRawCaretLineText: TScintRawString;
     function GetRawMainSelText: TScintRawString;
     function GetRawSelText: TScintRawString;
     function GetRawText: TScintRawString;
@@ -240,6 +246,8 @@ type
     function CallStr(Msg: Cardinal; WParam: Longint;
       const LParamStr: TScintRawString): Longint;
     procedure CancelAutoComplete;
+    procedure CancelAutoCompleteAndCallTip;
+    procedure CancelCallTip;
     function CanRedo: Boolean;
     function CanUndo: Boolean;
     procedure ChooseCaretX;
@@ -322,11 +330,12 @@ type
     function SelEmpty: Boolean;
     function SelNotEmpty(out Sel: TScintRange): Boolean;
     procedure SetAutoCompleteFillupChars(const FillupChars: AnsiString);
-    procedure SetAutoCompleteSeparator(const C: AnsiChar);
+    procedure SetAutoCompleteSeparators(const Separator, TypeSeparator: AnsiChar);
     procedure SetAutoCompleteSelectedItem(const S: TScintRawString);
     procedure SetAutoCompleteStopChars(const StopChars: AnsiString);
     procedure SetBraceHighlighting(const Pos1, Pos2: Integer);
     procedure SetCursorID(const CursorID: Integer);
+    procedure SetCallTipHighlight(HighlightStart, HighlightEnd: Integer);
     procedure SetDefaultWordChars;
     procedure SetEmptySelection;
     procedure SetEmptySelections;
@@ -338,6 +347,7 @@ type
     procedure SettingChange(const Message: TMessage);
     procedure SetWordChars(const S: AnsiString);
     procedure ShowAutoComplete(const CharsEntered: Integer; const WordList: AnsiString);
+    procedure ShowCallTip(const Pos: Integer; const Definition: AnsiString);
     procedure StyleNeeded(const EndPos: Integer);
     procedure SysColorChange(const Message: TMessage);
     procedure Undo;
@@ -347,10 +357,13 @@ type
     procedure ZoomIn;
     procedure ZoomOut;
     property AutoCompleteActive: Boolean read GetAutoCompleteActive;
+    property CallTipActive: Boolean read GetCallTipActive;
     property CaretColumn: Integer read GetCaretColumn write SetCaretColumn;
     property CaretColumnExpandedForTabs: Integer read GetCaretColumnExpandedForTabs;
     property CaretLine: Integer read GetCaretLine write SetCaretLine;
+    property CaretLineText: String read GetCaretLineText;
     property CaretPosition: Integer read GetCaretPosition write SetCaretPosition;
+    property CaretPositionInLine: Integer read GetCaretPositionInLine;
     property CaretPositionWithSelectFromAnchor: Integer write SetCaretPositionWithSelectFromAnchor;
     property CaretVirtualSpace: Integer read GetCaretVirtualSpace write SetCaretVirtualSpace;
     property EffectiveCodePage: Integer read FEffectiveCodePage;
@@ -364,6 +377,7 @@ type
     property MainSelection: Integer read GetMainSelection write SetMainSelection;
     property MainSelText: String read GetMainSelText write SetMainSelText;
     property Modified: Boolean read GetModified;
+    property RawCaretLineText: TScintRawString read GetRawCaretLineText;
     property RawMainSelText: TScintRawString read GetRawMainSelText write SetRawMainSelText;
     property RawSelText: TScintRawString read GetRawSelText write SetRawSelText;
     property RawText: TScintRawString read GetRawText write SetRawText;
@@ -379,6 +393,8 @@ type
     property SelText: String read GetSelText write SetSelText;
     property Styler: TScintCustomStyler read FStyler write SetStyler;
     property TopLine: Integer read GetTopLine write SetTopLine;
+    property WordChars: AnsiString read FWordChars;
+    property WordCharsAsSet: TSysCharSet read FWordCharsAsSet;
   published
     property AcceptDroppedFiles: Boolean read FAcceptDroppedFiles write SetAcceptDroppedFiles
       default False;
@@ -645,6 +661,17 @@ begin
   Call(SCI_AUTOCCANCEL, 0, 0);
 end;
 
+procedure TScintEdit.CancelAutoCompleteAndCallTip;
+begin
+  CancelAutoComplete;
+  CancelCallTip;
+end;
+
+procedure TScintEdit.CancelCallTip;
+begin
+  Call(SCI_CALLTIPCANCEL, 0, 0);
+end;
+
 function TScintEdit.CanRedo: Boolean;
 begin
   Result := Call(SCI_CANREDO, 0, 0) <> 0;
@@ -904,11 +931,6 @@ begin
     CallWindowProc(DefWndProc, Handle, Message.Msg, Message.WParam, Message.LParam);
 end;
 
-function TScintEdit.GetMainSelText: String;
-begin
-  Result := ConvertRawStringToString(GetRawMainSelText);
-end;
-
 function TScintEdit.GetAutoCompleteActive: Boolean;
 begin
   Result := Call(SCI_AUTOCACTIVE, 0, 0) <> 0;
@@ -919,6 +941,11 @@ begin
   Result := AnsiChar(Call(SCI_GETCHARAT, Pos, 0));
 end;
 
+function TScintEdit.GetCallTipActive: Boolean;
+begin
+  Result := Call(SCI_CALLTIPACTIVE, 0, 0) <> 0;
+end;
+
 function TScintEdit.GetCaretColumn: Integer;
 begin
   Result := GetColumnFromPosition(GetCaretPosition);
@@ -935,11 +962,23 @@ begin
   Result := GetLineFromPosition(GetCaretPosition);
 end;
 
+function TScintEdit.GetCaretLineText: String;
+begin
+  Result := ConvertRawStringToString(GetRawCaretLineText);
+end;
+
 function TScintEdit.GetCaretPosition: Integer;
 begin
   Result := Call(SCI_GETCURRENTPOS, 0, 0);
 end;
 
+function TScintEdit.GetCaretPositionInLine: Integer;
+begin
+  var Caret := CaretPosition;
+  var LineStart := GetPositionFromLine(GetLineFromPosition(Caret));
+  Result := Caret - LineStart;
+end;
+
 function TScintEdit.GetCaretVirtualSpace: Integer;
 begin
   Result := GetSelectionCaretVirtualSpace(GetMainSelection);
@@ -1038,6 +1077,11 @@ begin
   Result := Call(SCI_GETMAINSELECTION, 0, 0);
 end;
 
+function TScintEdit.GetMainSelText: String;
+begin
+  Result := ConvertRawStringToString(GetRawMainSelText);
+end;
+
 function TScintEdit.GetMarkers(const Line: Integer): TScintMarkerNumbers;
 begin
   FLines.CheckIndexRange(Line);
@@ -1119,6 +1163,12 @@ begin
   Result := Call(SCI_POSITIONRELATIVE, Pos, CharacterCount);
 end;
 
+function TScintEdit.GetRawCaretLineText: TScintRawString;
+begin
+  var Line := CaretLine;
+  Result := GetRawTextRange(GetPositionFromLine(Line), GetPositionFromLine(Line+1));
+end;
+
 function TScintEdit.GetRawMainSelText: TScintRawString;
 begin
   var MainSel := MainSelection;
@@ -1580,9 +1630,10 @@ begin
   CallStr(SCI_AUTOCSELECT, 0, S);
 end;
 
-procedure TScintEdit.SetAutoCompleteSeparator(const C: AnsiChar);
+procedure TScintEdit.SetAutoCompleteSeparators(const Separator, TypeSeparator: AnsiChar);
 begin
-  Call(SCI_AUTOCSETSEPARATOR, WParam(C), 0);
+  Call(SCI_AUTOCSETSEPARATOR, WParam(Separator), 0);
+  Call(SCI_AUTOCSETTYPESEPARATOR, WParam(TypeSeparator), 0);
 end;
 
 procedure TScintEdit.SetAutoCompleteStopChars(const StopChars: AnsiString);
@@ -1595,6 +1646,11 @@ begin
   Call(SCI_BRACEHIGHLIGHT, Pos1, Pos2);
 end;
 
+procedure TScintEdit.SetCallTipHighlight(HighlightStart, HighlightEnd: Integer);
+begin
+  Call(SCI_CALLTIPSETHLT, HighlightStart, HighlightEnd);
+end;
+
 procedure TScintEdit.SetCaretColumn(const Value: Integer);
 begin
   SetCaretPosition(GetPositionFromLineColumn(GetCaretLine, Value));
@@ -1910,6 +1966,10 @@ end;
 
 procedure TScintEdit.SetWordChars(const S: AnsiString);
 begin
+  FWordChars := S;
+  FWordCharsAsSet := [];
+  for var C in S do
+    Include(FWordCharsAsSet, C);
   CallStr(SCI_SETWORDCHARS, 0, S);
 end;
 
@@ -1932,6 +1992,12 @@ begin
   Call(SCI_AUTOCSHOW, CharsEntered, LPARAM(PAnsiChar(WordList)));
 end;
 
+procedure TScintEdit.ShowCallTip(const Pos: Integer;
+  const Definition: AnsiString);
+begin
+  Call(SCI_CALLTIPSHOW, Pos, LPARAM(PAnsiChar(Definition)));
+end;
+
 procedure TScintEdit.StyleNeeded(const EndPos: Integer);
 
   function CalcCaretIndex(const FirstLine, LastLine: Integer): Integer;

Plik diff jest za duży
+ 476 - 441
Components/ScintStylerInnoSetup.pas


BIN
Files/isscint.dll


+ 10 - 4
ISHelp/isetup.xml

@@ -3120,7 +3120,7 @@ Filename: "{win}\MYPROG.INI"; Section: "InstallSettings"; Key: "InstallPath"; St
 
 <p>A single dash (-) means there's no shortcut available for this command in the key map.</p>
 
-<p>Note: a few of the shortcuts below use string representations for special virtual keys. More precisely: ; for VK_OEM_1, . for VK_OEM_PERIOD, / for VK_OEM_2, [ for VK_OEM_4, and ] for VK_OEM_6. Different keyboard layouts usually reposition these special virtual keys or change the characters produced when they are pressed. In the <i>Edit</i> menu these shortcuts are shown using the current system's keyboard layout. For example, when using a French AZERTY keyboard layout <i>Toggle Line Comment</i>'s shortcut is shown as Ctrl+: instead of Ctrl+/. If the keyboard layout doesn't support the virtual key then no shortcut will be shown.</p> 
+<p>Note: a few of the shortcuts below use string representations for special virtual keys. More precisely: ; for VK_OEM_1, . for VK_OEM_PERIOD, / for VK_OEM_2, [ for VK_OEM_4, and ] for VK_OEM_6. Different keyboard layouts usually reposition these special virtual keys or change the characters produced when they are pressed. In the <i>Edit</i> menu these shortcuts are shown using the current system's keyboard layout. For example, when using a French AZERTY keyboard layout the <i>Toggle Line Comment</i> shortcut is shown as Ctrl+: instead of Ctrl+/. If the keyboard layout doesn't support the virtual key then no shortcut will be shown.</p> 
 
 <table>
 <tr><td></td><td><u>Classic</u></td><td><u>Visual Studio Code</u></td></tr>
@@ -3320,13 +3320,19 @@ Filename: "{win}\MYPROG.INI"; Section: "InstallSettings"; Key: "InstallPath"; St
   <td>&nbsp;</td>
 </tr>
 <tr>
-  <td>Complete word.</td><td>Ctrl+Space or Ctrl+I</td>
+  <td>Invoke autocomplete.</td><td>Ctrl+Space or Ctrl+I</td>
 </tr>
 <tr>
-  <td>Fillup complete word.</td><td>Tab or Enter or<br />Space for ISPP directives or Flags and Type parameters or<br />\ for constants or<br />: for constants and section parameters or<br />] for sections or<br />= for section directives</td>
+  <td>Select autocompletion.</td><td>Tab or Enter</td>
 </tr>
 <tr>
-  <td>Cancel complete word.</td><td>Esc</td>
+  <td>Fillup autocompletion.</td><td>Space for ISPP directives and Flags and Type parameters<br />\ for constants<br />: for constants and section parameters<br />] for sections<br />= for section directives<br />( for script functions</td>
+</tr>
+<tr>
+  <td>Invoke parameter hint.</td><td>Ctrl+Shift+Space</td>
+</tr>
+<tr>
+  <td>Cancel autocomplete or parameter hint.</td><td>Esc</td>
 </tr>
 <tr>
   <td>&nbsp;</td>

+ 1 - 3
ISHelp/isxclasses.header

@@ -3,13 +3,11 @@
 
 <!--
   Inno Setup
-  Copyright (C) 1997-2006 Jordan Russell
+  Copyright (C) 1997-2024 Jordan Russell
   Portions by Martijn Laan
   For conditions of distribution and use, see LICENSE.TXT.
 
   This file is automatically generated. Do not edit.
-
-  $jrsoftware: ishelp/isxclasses.header,v 1.5 2006/09/23 00:33:22 jr Exp $
 -->
 
 <ishelp version="1">

+ 2 - 0
ISHelp/isxclasses.header2

@@ -10,6 +10,8 @@
 
 <p>One special constant is available: <tt>crHand</tt> of type <tt>TControl.Cursor</tt>.</p>
 
+<p>Parameter type <tt>AnyString</tt> means both <tt>String</tt> and <tt>AnsiString</tt> can be used.</p>
+
 <p>The <i>CodeClasses.iss</i> example script in the "Examples" subdirectory in your Inno Setup directory shows how to use these classes.</p>
 
 <p>Note: you may find it useful to also refer to the Delphi Visual Component Library (VCL) Help files by Embarcadero Technologies, since the classes below are mostly simple wrappers around the VCL classes Inno Setup uses internally. See <extlink href="http://docwiki.embarcadero.com/RADStudio/Alexandria/en/VCL">http://docwiki.embarcadero.com/RADStudio/Alexandria/en/VCL</extlink>.</p>

+ 82 - 66
ISHelp/isxfunc.xml

@@ -2,7 +2,7 @@
 <isxhelp version="1.0">
 <copyright>
   Inno Setup
-  Copyright (C) 1997-2020 Jordan Russell
+  Copyright (C) 1997-2024 Jordan Russell
   Portions by Martijn Laan
   For conditions of distribution and use, see LICENSE.TXT.
 </copyright>
@@ -640,37 +640,37 @@ end;</pre></example>
       </function>
       <function>
         <name>SendMessage</name>
-        <prototype>function SendMessage(const Wnd: HWND; const Msg, WParam, LParam: Longint): Longint;</prototype>
+        <prototype>function SendMessage(const Wnd: HWND; const Msg, WParam, LParam: LongInt): LongInt;</prototype>
         <description><p>Sends the specified message to the specified window. Does not return until the window procedure has processed the message.</p></description>
       </function>
       <function>
         <name>PostMessage</name>
-        <prototype>function PostMessage(const Wnd: HWND; const Msg, WParam, LParam: Longint): Boolean;</prototype>
+        <prototype>function PostMessage(const Wnd: HWND; const Msg, WParam, LParam: LongInt): Boolean;</prototype>
         <description><p>Posts the specified message to the specified window, returning immediately. Returns True if successful.</p></description>
       </function>
       <function>
         <name>SendNotifyMessage</name>
-        <prototype>function SendNotifyMessage(const Wnd: HWND; const Msg, WParam, LParam: Longint): Boolean;</prototype>
+        <prototype>function SendNotifyMessage(const Wnd: HWND; const Msg, WParam, LParam: LongInt): Boolean;</prototype>
         <description><p>Sends the specified message to the specified window without waiting for the message to be processed by the destination window procedure. Returns True if successful.</p></description>
       </function>
       <function>
         <name>RegisterWindowMessage</name>
-        <prototype>function RegisterWindowMessage(const Name: String): Longint;</prototype>
+        <prototype>function RegisterWindowMessage(const Name: String): LongInt;</prototype>
         <description><p>The RegisterWindowMessage function defines a new window message that is guaranteed to be unique throughout the system. The returned message value can be used when calling the SendBroadcastMessage or PostBroadcastMessage function.</p></description>
       </function>
       <function>
         <name>SendBroadcastMessage</name>
-        <prototype>function SendBroadcastMessage(const Msg, WParam, LParam: Longint): Longint;</prototype>
+        <prototype>function SendBroadcastMessage(const Msg, WParam, LParam: LongInt): LongInt;</prototype>
         <description><p>Sends the specified message to top-level windows in the system. Does not return until all window procedure have processed the message.<br />The specified message must be unique. Use RegisterWindowMessage to get such a message.</p></description>
       </function>
       <function>
         <name>PostBroadcastMessage</name>
-        <prototype>function PostBroadcastMessage(const Msg, WParam, LParam: Longint): Boolean;</prototype>
+        <prototype>function PostBroadcastMessage(const Msg, WParam, LParam: LongInt): Boolean;</prototype>
         <description><p>Posts the specified message to top-level windows in the system, returning immediately.<br />The specified message must be unique. Use RegisterWindowMessage to get such a message.</p></description>
       </function>
       <function>
         <name>SendBroadcastNotifyMessage</name>
-        <prototype>function SendBroadcastNotifyMessage(const Msg, WParam, LParam: Longint): Boolean;</prototype>
+        <prototype>function SendBroadcastNotifyMessage(const Msg, WParam, LParam: LongInt): Boolean;</prototype>
       </function>
     </subcategory>
     <subcategory>
@@ -748,7 +748,7 @@ end;</pre></example>
       </function>
       <function>
         <name>DLLGetLastError</name>
-        <prototype>function DLLGetLastError(): Longint;</prototype>
+        <prototype>function DLLGetLastError(): LongInt;</prototype>
         <description><p>Returns value the last error code had right after the most recent DLL function call you made. Useful after calling Windows API functions (if the function sets the last error code).</p></description>
         <remarks><p>It's recommended to use this function instead of directly calling the GetLastError Windows API function since Setup or Uninstall makes API calls of its own, so the last error code could be overwritten at any time.</p>
 <p>Refer to the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms681381.aspx">system error codes on MSDN</a>.</p></remarks>
@@ -777,47 +777,47 @@ begin
       </function>
       <function>
         <name>Copy</name>
-        <prototype>function Copy(S: String; Index, Count: Integer): String;</prototype>
+        <prototype>function Copy(S: AnyString; Index, Count: Integer): String;</prototype>
         <description><p>Returns a string containing Count characters starting at S[Index].<br />If Index is larger than the length of S, Copy returns an empty string.<br />If Count specifies more characters than are available, only the characters from S[Index] to the end of S are returned.</p></description>
       </function>
       <function>
         <name>Length</name>
-        <prototype>function Length(s: String): Longint;</prototype>
+        <prototype>function Length(S: AnyString): LongInt;</prototype>
         <description><p>Returns the length of the specified string.</p></description>
       </function>
       <function>
         <name>Lowercase</name>
-        <prototype>function Lowercase(S: String): String;</prototype>
+        <prototype>function Lowercase(S: AnyString): String;</prototype>
         <description><p>Returns a copy of the string S, but with all 7-bit ASCII characters between 'A' and 'Z' converted to lowercase. To convert 8-bit international characters, use AnsiLowercase instead.</p></description>
       </function>
       <function>
         <name>Uppercase</name>
-        <prototype>function Uppercase(S: String): String;</prototype>
+        <prototype>function Uppercase(S: AnyString): String;</prototype>
         <description><p>Returns a copy of the string S, but with all 7-bit ASCII characters between 'a' and 'z' converted to uppercase. To convert 8-bit international characters, use AnsiUppercase instead.</p></description>
       </function>
       <function>
         <name>AnsiLowercase</name>
-        <prototype>function AnsiLowercase(S: String): String;</prototype>
+        <prototype>function AnsiLowercase(S: AnyString): String;</prototype>
         <description><p>Returns a string that is a copy of the given string converted to lowercase. The conversion uses the current Windows locale. This function supports multi-byte character sets (MBCS).</p></description>
       </function>
       <function>
         <name>AnsiUppercase</name>
-        <prototype>function AnsiUppercase(S: String): String;</prototype>
+        <prototype>function AnsiUppercase(S: AnyString): String;</prototype>
         <description><p>Returns a string that is a copy of the given string converted to uppercase. The conversion uses the current Windows locale. This function supports multi-byte character sets (MBCS).</p></description>
       </function>
       <function>
         <name>StringOfChar</name>
-        <prototype>function StringOfChar(c: Char; I : Longint): String;</prototype>
+        <prototype>function StringOfChar(C: Char; I : LongInt): String;</prototype>
         <description><p>Returns a string of length I with all characters set to character C.</p></description>
       </function>
       <function>
         <name>Delete</name>
-        <prototype>procedure Delete(var S: String; Index, Count: Integer);</prototype>
+        <prototype>procedure Delete(var S: AnyString; Index, Count: Integer);</prototype>
         <description><p>Removes a substring of Count characters from string S starting at S[Index].<br />If Index is larger than the length of S, no characters are deleted. If Count specifies more characters than remain starting at the S[Index], Delete removes the rest of the string.</p></description>
       </function>
       <function>
         <name>Insert</name>
-        <prototype>procedure Insert(Source: String; var Dest: String; Index: Integer);</prototype>
+        <prototype>procedure Insert(Source: AnyString; var Dest: AnyString; Index: Integer);</prototype>
         <description><p>Merges Source into Dest at the position Dest[Index].</p></description>
       </function>
       <function>
@@ -842,7 +842,7 @@ end;</pre></example>
       </function>
       <function>
         <name>Pos</name>
-        <prototype>function Pos(SubStr, S: String): Integer;</prototype>
+        <prototype>function Pos(SubStr, S: AnyString): Integer;</prototype>
         <description><p>Searches for Substr within S and returns an integer value that is the index of the first character of Substr within S.<br />If Substr is not found, Pos returns zero. The Pos function is case-sensitive.</p></description>
       </function>
       <function>
@@ -864,22 +864,22 @@ end;</pre></example>
     <subcategory>
       <function>
         <name>CompareText</name>
-        <prototype>function CompareText(const S1, S2: string): Integer;</prototype>
+        <prototype>function CompareText(const S1, S2: String): Integer;</prototype>
         <description><p>Compares the strings S1 and S2 and returns 0 if they are equal. If S1 is greater than S2, CompareText returns an integer greater than 0. If S1 is less than S2, CompareText returns an integer less than 0. The CompareText function is not case-sensitive.</p></description>
       </function>
       <function>
         <name>CompareStr</name>
-        <prototype>function CompareStr(const S1, S2: string): Integer;</prototype>
+        <prototype>function CompareStr(const S1, S2: String): Integer;</prototype>
         <description><p>Compares S1 to S2, with case-sensitivity. The return value is less than 0 if S1 is less than S2, 0 if S1 equals S2, or greater than 0 if S1 is greater than S2.</p></description>
       </function>
       <function>
         <name>SameText</name>
-        <prototype>function SameText(const S1, S2: string): Boolean;</prototype>
+        <prototype>function SameText(const S1, S2: String): Boolean;</prototype>
         <description><p>Compares the strings S1 and S2 and returns True if they are equal. The SameText function is not case-sensitive.</p></description>
       </function>
       <function>
         <name>SameStr</name>
-        <prototype>function SameStr(const S1, S2: string): Boolean;</prototype>
+        <prototype>function SameStr(const S1, S2: String): Boolean;</prototype>
         <description><p>Compares S1 to S2, with case-sensitivity. The return value is True if they are equal.</p></description>
       </function>
       <function>
@@ -896,7 +896,7 @@ end;</pre></example>
     <subcategory>
       <function>
         <name>Format</name>
-        <prototype>function Format(const Format: string; const Args: array of const): string;</prototype>
+        <prototype>function Format(const Format: String; const Args: array of const): String;</prototype>
         <description><p>Formats the series of arguments in the open array Args. Formatting is controlled by the format string Format; the results are returned as a string.</p>
 <p>An exception will be raised if an invalid format string is specified, too few arguments are passed, or if any arguments are of the wrong type.</p></description>
         <example><pre>var
@@ -918,56 +918,56 @@ end;</pre></example>
     <subcategory>
       <function>
         <name>Trim</name>
-        <prototype>function Trim(const S: string): String;</prototype>
+        <prototype>function Trim(const S: AnyString): AnyString;</prototype>
         <description><p>Trims leading and trailing spaces and control characters from the given string S.</p></description>
       </function>
       <function>
         <name>TrimLeft</name>
-        <prototype>function TrimLeft(const S: string): String;</prototype>
+        <prototype>function TrimLeft(const S: String): String;</prototype>
         <description><p>Trims leading spaces and control characters from the given string S.</p></description>
       </function>
       <function>
         <name>TrimRight</name>
-        <prototype>function TrimRight(const S: string): String;</prototype>
+        <prototype>function TrimRight(const S: String): String;</prototype>
         <description><p>Trims trailing spaces and control characters from the given string S.</p></description>
       </function>
     </subcategory>
     <subcategory>
       <function>
         <name>StrToIntDef</name>
-        <prototype>function StrToIntDef(s: string; def: Longint): Longint;</prototype>
+        <prototype>function StrToIntDef(S: String; Def: LongInt): LongInt;</prototype>
         <description><p>The StrToInt function converts the string passed in S into a number. If S does not represent a valid number, StrToInt returns the number passed in Def.</p></description>
       </function>
       <function>
         <name>StrToInt</name>
-        <prototype>function StrToInt(s: string): Longint;</prototype>
+        <prototype>function StrToInt(S: String): LongInt;</prototype>
         <description><p>The StrToInt function converts the string passed in S into a number.</p></description>
         <remarks><p>Use of <link topic="isxfunc_StrToIntDef">StrToIntDef</link> instead of StrToInt is recommended.</p></remarks>
       </function>
       <function>
         <name>StrToInt64Def</name>
-        <prototype>function StrToInt64Def(s: string; def: Int64): Int64;</prototype>
+        <prototype>function StrToInt64Def(S: String; Def: Int64): Int64;</prototype>
         <description><p>The StrToInt64Def function converts the string passed in S into a 64-bit number. If S does not represent a valid 64-bit number, StrToInt returns the 64-bit number passed in Def.</p></description>
       </function>
       <function>
         <name>StrToInt64</name>
-        <prototype>function StrToInt64(s: string): Int64;</prototype>
+        <prototype>function StrToInt64(S: String): Int64;</prototype>
         <description><p>The StrToInt64 function converts the string passed in S into a 64-bit number.</p></description>
         <remarks><p>Use of <link topic="isxfunc_StrToInt64Def">StrToInt64Def</link> instead of StrToInt64 is recommended.</p></remarks>
       </function>
       <function>
         <name>StrToFloat</name>
-        <prototype>function StrToFloat(s: string): Extended;</prototype>
+        <prototype>function StrToFloat(S: String): Extended;</prototype>
         <description><p>The StrToFloat function converts the string passed in S into a floating point number. The character used for the decimal point should always be a dot.</p></description>
       </function>
       <function>
         <name>IntToStr</name>
-        <prototype>function IntToStr(i: Int64): String;</prototype>
+        <prototype>function IntToStr(I: Int64): String;</prototype>
         <description><p>The IntToStr function converts a 64-bit number into a string.</p></description>
       </function>
       <function>
         <name>FloatToStr</name>
-        <prototype>function FloatToStr(e: extended): String;</prototype>
+        <prototype>function FloatToStr(E: Extended): String;</prototype>
         <description><p>The FloatToStr function converts a floating point number into a string.</p><p>The character used for the decimal point will always be a dot.</p></description>
       </function>
     </subcategory>
@@ -1025,32 +1025,32 @@ end;</pre></example>
       </function>
       <function>
         <name>ChangeFileExt</name>
-        <prototype>function ChangeFileExt(const FileName, Extension: string): String;</prototype>
+        <prototype>function ChangeFileExt(const FileName, Extension: String): String;</prototype>
         <description><p>Takes the file name passed in FileName and changes the extension of the file name to the extension passed in Extension.</p></description>
       </function>
       <function>
         <name>ExtractFileExt</name>
-        <prototype>function ExtractFileExt(const FileName: string): String;</prototype>
+        <prototype>function ExtractFileExt(const FileName: String): String;</prototype>
         <description><p>Extracts the extension part of the given file name. The resulting string includes the period character that separates the name and extension parts. The resulting string is empty if the given filename has no extension.</p></description>
       </function>
       <function>
         <name>ExtractFileDir</name>
-        <prototype>function ExtractFileDir(const FileName: string): String;</prototype>
+        <prototype>function ExtractFileDir(const FileName: String): String;</prototype>
         <description><p>Extracts the drive and directory parts of the given file name. The resulting string is empty if FileName contains no drive and directory parts.</p></description>
       </function>
       <function>
         <name>ExtractFilePath</name>
-        <prototype>function ExtractFilePath(const FileName: string): String;</prototype>
+        <prototype>function ExtractFilePath(const FileName: String): String;</prototype>
         <description><p>Extracts the drive and directory parts of the given file name. The resulting string is the leftmost characters of FileName, up to and including the colon or backslash that separates the path information from the name and extension. The resulting string is empty if FileName contains no drive and directory parts.</p></description>
       </function>
       <function>
         <name>ExtractFileName</name>
-        <prototype>function ExtractFileName(const FileName: string): String;</prototype>
+        <prototype>function ExtractFileName(const FileName: String): String;</prototype>
         <description><p>Extracts the name and extension parts of the given file name. The resulting string is the rightmost characters of FileName, starting with the first character after the colon or backslash that separates the path information from the name and extension. The resulting string is equal to FileName if FileName contains no drive and directory parts.</p></description>
       </function>
       <function>
         <name>ExtractFileDrive</name>
-        <prototype>function ExtractFileDrive(const FileName: string): String;</prototype>
+        <prototype>function ExtractFileDrive(const FileName: String): String;</prototype>
         <description><p>Returns a string containing the 'drive' portion of a fully qualified path name for the file passed in the FileName. For file names with drive letters, the resulting string is in the form '&lt;drive&gt;:'. For file names with a UNC path the resulting string is in the form '\\&lt;servername&gt;\&lt;sharename&gt;'. If the given path contains neither style of path prefix, the result is an empty string.</p></description>
       </function>
       <function>
@@ -1067,12 +1067,12 @@ end;</pre></example>
       </function>
       <function>
         <name>ExpandFileName</name>
-        <prototype>function ExpandFileName(const FileName: string): String;</prototype>
+        <prototype>function ExpandFileName(const FileName: String): String;</prototype>
         <description><p>Returns a string containing a fully qualified path name for the file passed in the FileName. A fully qualified path name includes the drive letter and any directory and subdirectories in addition to the file name and extension.</p></description>
       </function>
       <function>
         <name>ExpandUNCFileName</name>
-        <prototype>function ExpandUNCFileName(const FileName: string): String;</prototype>
+        <prototype>function ExpandUNCFileName(const FileName: String): String;</prototype>
         <description><p>Returns a string containing a fully qualified path name for the file passed in the FileName. A fully qualified path name includes the drive portion of the filename in the UNC format '\\&lt;servername&gt;\&lt;sharename&gt;' if the drive letter is mapped to a network resource instead of a local drive and any directory and subdirectories in addition to the file name and extension.</p></description>
       </function>
     </subcategory>
@@ -1127,7 +1127,7 @@ GetDateTimeString('dd/mm/yyyy hh:nn:ss', '-', ':');
     <subcategory>
       <function>
         <name>SetLength</name>
-        <prototype>procedure SetLength(var S: String; L: Longint);</prototype>
+        <prototype>procedure SetLength(var S: AnyString; L: LongInt);</prototype>
         <description><p>Sets the length of a string.</p></description>
       </function>
       <function>
@@ -1248,12 +1248,12 @@ end;
     <subcategory>
       <function>
         <name>GetArrayLength</name>
-        <prototype>function GetArrayLength(var Arr: Array): Longint;</prototype>
+        <prototype>function GetArrayLength(var Arr: Array): LongInt;</prototype>
         <description><p>Gets the length of an array.</p></description>
       </function>
       <function>
         <name>SetArrayLength</name>
-        <prototype>procedure SetArrayLength(var Arr: Array; I: Longint);</prototype>
+        <prototype>procedure SetArrayLength(var Arr: Array; I: LongInt);</prototype>
         <description><p>Sets the length of an array. Always call SetArrayLength before accessing the elements in an array.</p></description>
       </function>
     </subcategory>
@@ -1300,7 +1300,7 @@ end;
 const
   varEmpty    = $0000;
   varNull     = $0001;
-  varSmallint = $0002;
+  varSmallInt = $0002;
   varInteger  = $0003;
   varSingle   = $0004;
   varDouble   = $0005;
@@ -1313,13 +1313,29 @@ const
   varVariant  = $000C;
   varUnknown  = $000D;
   varByte     = $0011;
+  varWord     = $0012;
+  varLongWord = $0013;
+  varInt64    = $0014;
+  varStrArg   = $0048;
   varString   = $0100;
+  varAny      = $0101;
+  varUString  = $0102;
   varTypeMask = $0FFF;
   varArray    = $2000;
   varByRef    = $4000;
 </pre>
 </description>
       </function>
+      <function>
+        <name>VarArrayGet</name>
+        <prototype>function VarArrayGet(var S: Variant; I: Integer): Variant;</prototype>
+        <description><p>Returns the specified element of the specified variant array.</p></description>
+      </function>
+      <function>
+        <name>VarArraySet</name>
+        <prototype>procedure VarArraySet(C: Variant; I: Integer; var S: Variant);</prototype>
+        <description><p>Sets the specified element of the specified variant array.</p></description>
+      </function>
     </subcategory>
   </category>
   <category>
@@ -1397,7 +1413,7 @@ end;</pre></example>
     <subcategory>
       <function>
         <name>FileSearch</name>
-        <prototype>function FileSearch(const Name, DirList: string): String;</prototype>
+        <prototype>function FileSearch(const Name, DirList: String): String;</prototype>
         <description><p>Searches through the directories passed in DirList for a file named Name. DirList should be directory names separated by semicolons. If FileSearch locates a file matching Name, it returns a string containing a fully-qualified path name for that file. If no matching file exists, FileSearch returns an empty string.</p></description>
       </function>
       <function>
@@ -1491,7 +1507,7 @@ end;</pre></example>
       </function>
       <function>
         <name>SetCurrentDir</name>
-        <prototype>function SetCurrentDir(const Dir: string): Boolean;</prototype>
+        <prototype>function SetCurrentDir(const Dir: String): Boolean;</prototype>
         <description><p>Sets the current directory. The return value is True if the current directory was successfully changed, or False if an error occurred.</p></description>
       </function>
       <function>
@@ -1765,7 +1781,7 @@ end;</pre></example>
 <p>For basic authentication use <link topic="isxfunc_SetDownloadCredentials">SetDownloadCredentials</link>.</p>
 <p>Set OnDownloadProgress to a function to be informed of progress, or <tt>nil</tt> otherwise.</p></description>
         <remarks><p>TOnDownloadProgress is defined as:</p>
-<p><tt>TOnDownloadProgress = function(const Url, FileName: string; const Progress, ProgressMax: Int64): Boolean;</tt></p>
+<p><tt>TOnDownloadProgress = function(const Url, FileName: String; const Progress, ProgressMax: Int64): Boolean;</tt></p>
 <p>ProgressMax will be 0 if the file size is still unknown. Return True to allow the download to continue, False otherwise.</p></remarks>
         <seealso><p><link topic="isxfunc_SetDownloadCredentials">SetDownloadCredentials</link><br />
 <link topic="isxfunc_DownloadTemporaryFileSize">DownloadTemporaryFileSize</link><br />
@@ -1774,7 +1790,7 @@ end;</pre></example>
 <link topic="isxfunc_ExtractTemporaryFile">ExtractTemporaryFile</link></p></seealso>
         <example><pre>
 [Code]
-function OnDownloadProgress(const Url, Filename: string; const Progress, ProgressMax: Int64): Boolean;
+function OnDownloadProgress(const Url, Filename: String; const Progress, ProgressMax: Int64): Boolean;
 begin
   if ProgressMax &lt;&gt; 0 then
     Log(Format('  %d of %d bytes done.', [Progress, ProgressMax]))
@@ -1820,7 +1836,7 @@ end;</pre>
     <subcategory>
       <function>
         <name>RenameFile</name>
-        <prototype>function RenameFile(const OldName, NewName: string): Boolean;</prototype>
+        <prototype>function RenameFile(const OldName, NewName: String): Boolean;</prototype>
         <description><p>Attempts to change the name of the file or directory specified by OldFile to NewFile. If the operation succeeds, RenameFile returns True. If it cannot rename the file (for example, if a file called NewName already exists), it returns False.</p></description>
       </function>
       <function>
@@ -1830,7 +1846,7 @@ end;</pre>
       </function>
       <function>
         <name>DeleteFile</name>
-        <prototype>function DeleteFile(const FileName: string): Boolean;</prototype>
+        <prototype>function DeleteFile(const FileName: String): Boolean;</prototype>
         <description><p>Erases the file named by FileName from the disk.<br />If the file cannot be deleted or does not exist, the function returns False.</p></description>
       </function>
       <function>
@@ -1904,17 +1920,17 @@ end;</pre>
     <subcategory>
       <function>
         <name>CreateDir</name>
-        <prototype>function CreateDir(const Dir: string): Boolean;</prototype>
+        <prototype>function CreateDir(const Dir: String): Boolean;</prototype>
         <description><p>Creates a new directory. The return value is True if a new directory was successfully created, or False if an error occurred.</p></description>
       </function>
       <function>
         <name>ForceDirectories</name>
-        <prototype>function ForceDirectories(Dir: string): Boolean;</prototype>
+        <prototype>function ForceDirectories(Dir: String): Boolean;</prototype>
         <description><p>Creates all the directories along the specified directory path all at once. If the first directories in the path do exist, but the latter ones don't, ForceDirectories creates just the ones that don't exist. Returns True if successful, False otherwise.</p></description>
       </function>
       <function>
         <name>RemoveDir</name>
-        <prototype>function RemoveDir(const Dir: string): Boolean;</prototype>
+        <prototype>function RemoveDir(const Dir: String): Boolean;</prototype>
         <description><p>Deletes an existing empty directory. The return value is True if the empty directory was successfully deleted, or False if an error occurred.</p></description>
       </function>
       <function>
@@ -2332,8 +2348,8 @@ end;</pre></example>
       </function>
       <function>
         <name>GetIniInt</name>
-        <prototype>function GetIniInt(const Section, Key: String; const Default, Min, Max: Longint; const Filename: String): Longint;</prototype>
-        <description><p>Reads a Longint from an INI file. If the Longint read is not between Min/Max then it returns Default. If Min=Max then Min/Max are ignored.</p></description>
+        <prototype>function GetIniInt(const Section, Key: String; const Default, Min, Max: LongInt; const Filename: String): LongInt;</prototype>
+        <description><p>Reads a LongInt from an INI file. If the LongInt read is not between Min/Max then it returns Default. If Min=Max then Min/Max are ignored.</p></description>
       </function>
       <function>
         <name>GetIniString</name>
@@ -2349,8 +2365,8 @@ end;</pre></example>
       </function>
       <function>
         <name>SetIniInt</name>
-        <prototype>function SetIniInt(const Section, Key: String; const Value: Longint; const Filename: String): Boolean;</prototype>
-        <description><p>Writes a Longint to an INI file.</p></description>
+        <prototype>function SetIniInt(const Section, Key: String; const Value: LongInt; const Filename: String): Boolean;</prototype>
+        <description><p>Writes a LongInt to an INI file.</p></description>
       </function>
       <function>
         <name>SetIniString</name>
@@ -2811,12 +2827,12 @@ end;</pre></example>
     <subcategory>
       <function>
         <name>CreateOleObject</name>
-        <prototype>function CreateOleObject(const ClassName: string): Variant;</prototype>
+        <prototype>function CreateOleObject(const ClassName: String): Variant;</prototype>
         <description><p>See the <link topic="scriptautomation" window="main">Using COM Automation objects</link> topic.</p></description>
       </function>
       <function>
         <name>GetActiveOleObject</name>
-        <prototype>function GetActiveOleObject(const ClassName: string): Variant;</prototype>
+        <prototype>function GetActiveOleObject(const ClassName: String): Variant;</prototype>
         <description><p>See the <link topic="scriptautomation" window="main">Using COM Automation objects</link> topic.</p></description>
       </function>
       <function>
@@ -2991,20 +3007,20 @@ end;</pre></example>
     <subcategory>
       <function>
         <name>LoadDLL</name>
-        <prototype>function LoadDLL(const DLLName: String; var ErrorCode: Integer): Longint;</prototype>
+        <prototype>function LoadDLL(const DLLName: String; var ErrorCode: Integer): LongInt;</prototype>
         <description><p>Loads the specified DLL. Returns the DLL handle if the DLL was loaded successfully, zero otherwise. If zero is returned then ErrorCode specifies the error that occurred. Use SysErrorMessage(ErrorCode) to get a description of the error.</p></description>
         <remarks><p>This function is deprecated. See the <link topic="scriptdll" window="main">Using DLLs</link> topic.</p>
 <p>Refer to the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms681381.aspx">system error codes on MSDN</a>.</p></remarks>
       </function>
       <function>
         <name>CallDLLProc</name>
-        <prototype>function CallDLLProc(const DLLHandle: Longint; const ProcName: String; const Param1, Param2: Longint; var Result: Longint): Boolean;</prototype>
+        <prototype>function CallDLLProc(const DLLHandle: LongInt; const ProcName: String; const Param1, Param2: LongInt; var Result: LongInt): Boolean;</prototype>
         <description><p>Calls the specified function in a DLL specified using the DLL handle returned by LoadDLL. Returns True is the procedure was called successfully, False otherwise.<br />The function must use the standard calling convention, accept two 4 byte integer parameters and return a 4 byte integer result.</p></description>
         <remarks><p>This function is deprecated. See the <link topic="scriptdll" window="main">Using DLLs</link> topic.</p></remarks>
       </function>
       <function>
         <name>FreeDLL</name>
-        <prototype>function FreeDLL(const DLLHandle: Longint): Boolean;</prototype>
+        <prototype>function FreeDLL(const DLLHandle: LongInt): Boolean;</prototype>
         <description><p>Unloads a DLL specified using the DLL handle returned by LoadDLL.</p></description>
         <remarks><p>This function is deprecated. See the <link topic="scriptdll" window="main">Using DLLs</link> topic.</p></remarks>
       </function>
@@ -3012,13 +3028,13 @@ end;</pre></example>
     <subcategory>
       <function>
         <name>CastStringToInteger</name>
-        <prototype>function CastStringToInteger(var S: String): Longint;</prototype>
+        <prototype>function CastStringToInteger(var S: String): LongInt;</prototype>
         <description><p>Casts a string to an integer so that a string can be passed to a DLL using CallDllProc.</p></description>
         <remarks><p>This function is deprecated. See the <link topic="scriptdll" window="main">Using DLLs</link> topic.</p></remarks>
       </function>
       <function>
         <name>CastIntegerToString</name>
-        <prototype>function CastIntegerToString(const L: Longint): String;</prototype>
+        <prototype>function CastIntegerToString(const L: LongInt): String;</prototype>
         <description><p>Casts an integer to a string so that a string can be received from a DLL using CallDllProc.</p></description>
         <remarks><p>This function is deprecated. See the <link topic="scriptdll" window="main">Using DLLs</link> topic.</p></remarks>
       </function>

+ 5 - 1
ISHelp/isxfunc.xsl

@@ -8,7 +8,7 @@
 <xsl:comment>
   Inno Setup
   Copyright (C) 1997-2020 Jordan Russell
-  Portions Copyright (C) 2000-2020 Martijn Laan
+  Portions Copyright (C) 2000-2024 Martijn Laan
   For conditions of distribution and use, see LICENSE.TXT.
 
   This file is automatically generated. Do not edit.
@@ -29,6 +29,10 @@
 
 <p>Here's the list of support functions that can be called from within the Pascal script.</p>
 
+<p>Parameter type <tt>AnyString</tt> means both <tt>String</tt> and <tt>AnsiString</tt> can be used.</p>
+
+<p>Parameter type <tt>Array</tt> means any array type can be used.</p>
+
 <xsl:for-each select="isxfunc//category">
 <xsl:call-template name="category"/>
 </xsl:for-each>

+ 2 - 1
Projects/Compil32.dpr

@@ -60,7 +60,8 @@ uses
   CompRegistryDesigner in 'Src\CompRegistryDesigner.pas' {RegistryDesignerForm},
   CompWizardRegistryHelper in 'Src\CompWizardRegistryHelper.pas',
   MD5 in 'Src\MD5.pas',
-  IsscintInt in 'Src\IsscintInt.pas';
+  IsscintInt in 'Src\IsscintInt.pas',
+  ScriptFunc in 'Src\ScriptFunc.pas';
 
 {$SetPEFlags IMAGE_FILE_RELOCS_STRIPPED}
 {$SETPEOSVERSION 6.1}

+ 2 - 1
Projects/Compil32.dproj

@@ -35,7 +35,7 @@
         <DCC_SymbolReferenceInfo>1</DCC_SymbolReferenceInfo>
         <DCC_UnitSearchPath>..\Components\UniPs\Source;ISPP;$(DCC_UnitSearchPath)</DCC_UnitSearchPath>
         <DCC_UsePackage>VCL30;vclx30;VclSmp30;vcldb30;vcldbx30;$(DCC_UsePackage)</DCC_UsePackage>
-        <DCC_Define>PS_MINIVCL;PS_NOGRAPHCONST;PS_PANSICHAR;PS_NOINTERFACEGUIDBRACKETS;$(DCC_Define)</DCC_Define>
+        <DCC_Define>COMPIL32PROJ;PS_MINIVCL;PS_NOGRAPHCONST;PS_PANSICHAR;PS_NOINTERFACEGUIDBRACKETS;$(DCC_Define)</DCC_Define>
         <SanitizedProjectName>Compil32</SanitizedProjectName>
         <VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
         <VerInfo_MajorVer>0</VerInfo_MajorVer>
@@ -142,6 +142,7 @@
         <DCCReference Include="Src\CompWizardRegistryHelper.pas"/>
         <DCCReference Include="Src\MD5.pas"/>
         <DCCReference Include="Src\IsscintInt.pas"/>
+        <DCCReference Include="Src\ScriptFunc.pas"/>
         <BuildConfiguration Include="Base">
             <Key>Base</Key>
         </BuildConfiguration>

Plik diff jest za duży
+ 2400 - 765
Projects/Src/CompForm.dfm


+ 327 - 92
Projects/Src/CompForm.pas

@@ -69,6 +69,12 @@ type
   TMenuBitmaps = TDictionary<TMenuItem, HBITMAP>;
   TKeyMappedMenus = TDictionary<TShortCut, TToolButton>;
 
+  TCallTipState = record
+    StartCallTipWord: Integer;
+    FunctionDefinition: AnsiString;
+    BraceCount: Integer;
+  end;
+
   TCompileForm = class(TUIStateForm)
     MainMenu1: TMainMenu;
     FMenu: TMenuItem;
@@ -228,9 +234,9 @@ type
     VReopenTabs2: TMenuItem;
     NavPopupMenu: TMenuItem;
     N23: TMenuItem;
-    LightMarkersImageCollection: TImageCollection;
-    DarkMarkersImageCollection: TImageCollection;
-    ThemedMarkersVirtualImageList: TVirtualImageList;
+    LightMarkersAndACImageCollection: TImageCollection;
+    DarkMarkersAndACImageCollection: TImageCollection;
+    ThemedMarkersAndACVirtualImageList: TVirtualImageList;
     ESelectNextOccurrence: TMenuItem;
     ESelectAllOccurrences: TMenuItem;
     BreakPointsPopupMenu: TMenuItem;
@@ -387,7 +393,8 @@ type
       UndoAfterSave: Boolean;
       PauseOnDebuggerExceptions: Boolean;
       RunAsDifferentUser: Boolean;
-      AutoComplete: Boolean;
+      AutoAutoComplete: Boolean;
+      AutoCallTips: Boolean;
       UseSyntaxHighlighting: Boolean;
       ColorizeCompilerOutput: Boolean;
       UnderlineErrors: Boolean;
@@ -467,6 +474,7 @@ type
     FBackNavButtonShortCut2, FForwardNavButtonShortCut2: TShortCut;
     FIgnoreTabSetClick: Boolean;
     FFirstTabSelectShortCut, FLastTabSelectShortCut: TShortCut;
+    FCallTipState: TCallTipState;
     function AnyMemoHasBreakPoint: Boolean;
     class procedure AppOnException(Sender: TObject; E: Exception);
     procedure AppOnActivate(Sender: TObject);
@@ -503,7 +511,11 @@ type
     function InitializeMainMemo(const Memo: TCompScintFileEdit; const PopupMenu: TPopupMenu): TCompScintFileEdit;
     function InitializeMemoBase(const Memo: TCompScintEdit; const PopupMenu: TPopupMenu): TCompScintEdit;
     function InitializeNonFileMemo(const Memo: TCompScintEdit; const PopupMenu: TPopupMenu): TCompScintEdit;
+    function InitiateAutoCompleteOrCallTipAllowedAtPos(const AMemo: TCompScintEdit;
+      const WordStartLinePos, PositionBeforeWordStartPos: Integer): Boolean;
     procedure InitiateAutoComplete(const Key: AnsiChar);
+    procedure InitiateCallTip;
+    procedure ContinueCallTip;
     procedure InvalidateStatusPanel(const Index: Integer);
     procedure LoadBreakPointLinesAndUpdateLineMarkers(const AMemo: TCompScintFileEdit);
     procedure LoadKnownIncludedAndHiddenFilesAndUpdateMemos(const AFilename: String);
@@ -564,7 +576,7 @@ type
     procedure UpdateEditModePanel;
     procedure UpdatePreprocMemos;
     procedure UpdateLineMarkers(const AMemo: TCompScintFileEdit; const Line: Integer);
-    procedure UpdateMarginsIcons;
+    procedure UpdateMarginsAndAutoCompleteIcons;
     procedure UpdateMarginsAndSquigglyAndCaretWidths;
     procedure UpdateMemosTabSetVisibility;
     procedure UpdateMenuBitmapsIfNeeded;
@@ -711,7 +723,7 @@ begin
   Memo.OnUpdateUI := MemoUpdateUI;
   Memo.OnZoom := MemoZoom;
   Memo.Parent := BodyPanel;
-  Memo.SetAutoCompleteSeparator(InnoSetupStylerWordListSeparator);
+  Memo.SetAutoCompleteSeparators(InnoSetupStylerWordListSeparator, InnoSetupStylerWordListTypeSeparator);
   Memo.SetWordChars(Memo.GetDefaultWordChars+'#{}[]');
   Memo.Theme := FTheme;
   Memo.Visible := False;
@@ -770,7 +782,8 @@ constructor TCompileForm.Create(AOwner: TComponent);
       FOptions.UndoAfterSave := Ini.ReadBool('Options', 'UndoAfterSave', True);
       FOptions.PauseOnDebuggerExceptions := Ini.ReadBool('Options', 'PauseOnDebuggerExceptions', True);
       FOptions.RunAsDifferentUser := Ini.ReadBool('Options', 'RunAsDifferentUser', False);
-      FOptions.AutoComplete := Ini.ReadBool('Options', 'AutoComplete', True);
+      FOptions.AutoAutoComplete := Ini.ReadBool('Options', 'AutoComplete', True);
+      FOptions.AutoCallTips := Ini.ReadBool('Options', 'AutoCallTips', True);
       FOptions.UseSyntaxHighlighting := Ini.ReadBool('Options', 'UseSynHigh', True);
       FOptions.ColorizeCompilerOutput := Ini.ReadBool('Options', 'ColorizeCompilerOutput', True);
       FOptions.UnderlineErrors := Ini.ReadBool('Options', 'UnderlineErrors', True);
@@ -966,7 +979,7 @@ begin
   FMenuDarkBackgroundBrush := TBrush.Create;
   FMenuDarkHotOrSelectedBrush := TBrush.Create;
 
-  ThemedMarkersVirtualImageList.AutoFill := True;
+  ThemedMarkersAndACVirtualImageList.AutoFill := True;
 
   UpdateThemeData(True);
 
@@ -1068,7 +1081,7 @@ procedure TCompileForm.FormAfterMonitorDpiChanged(Sender: TObject; OldDPI,
   NewDPI: Integer);
 begin
   UpdateMarginsAndSquigglyAndCaretWidths;
-  UpdateMarginsIcons;
+  UpdateMarginsAndAutoCompleteIcons;
   UpdateOutputTabSetListsItemHeightAndDebugTimeWidth;
   UpdateStatusPanelHeight(StatusPanel.Height);
 end;
@@ -1268,9 +1281,11 @@ begin
         Memo.SelectionMode := ssmStream;
       end;
     end;
+    { Key is not cleared to allow Scintilla to do the actual handling }
   end;
 
   if Key = VK_F1 then begin
+    Key := 0;
     var HelpFile := GetHelpFile;
     if Assigned(HtmlHelp) then begin
       HtmlHelp(GetDesktopWindow, PChar(HelpFile), HH_DISPLAY_TOPIC, 0);
@@ -1284,6 +1299,12 @@ begin
         HtmlHelp(GetDesktopWindow, PChar(HelpFile), HH_KEYWORD_LOOKUP, DWORD(@KLink));
       end;
     end;
+  end else if (Key = VK_SPACE) and (Shift * [ssShift, ssAlt, ssCtrl] = [ssShift, ssCtrl]) then begin
+    Key := 0;
+    if not FActiveMemo.CallTipActive then begin
+      FCallTipState.BraceCount := 1;
+      InitiateCallTip;
+    end;
   end else begin
     var AShortCut := ShortCut(Key, Shift);
     { Check if the memo keymap wants us to handle the shortcut but first check
@@ -2119,7 +2140,7 @@ begin
     FProgress := 0;
     FProgressMax := 0;
 
-    FActiveMemo.CancelAutoComplete;
+    FActiveMemo.CancelAutoCompleteAndCallTip;
     FActiveMemo.Cursor := crAppStart;
     FActiveMemo.SetCursorID(999);  { hack to keep it from overriding Cursor }
     CompilerOutputList.Cursor := crAppStart;
@@ -2989,7 +3010,7 @@ begin
       FIgnoreTabSetClick := False;
     end;
     VPreviousTabClick(Self);
-    Memo.CancelAutoComplete;
+    Memo.CancelAutoCompleteAndCallTip;
     Memo.Visible := False;
   end else if TabIndex < MemosTabset.TabIndex then
     MemosTabSet.TabIndex := MemosTabset.TabIndex-1; { Reselect old selected tab }
@@ -3381,7 +3402,7 @@ begin
     var OldActiveMemo := FActiveMemo;
     FActiveMemo := NewActiveMemo;
     ActiveControl := NewActiveMemo;
-    OldActiveMemo.CancelAutoComplete;
+    OldActiveMemo.CancelAutoCompleteAndCallTip;
     OldActiveMemo.Visible := False;
 
     UpdateSaveMenuItemAndButton;
@@ -3789,11 +3810,11 @@ begin
   inherited;
 end;
 
-procedure TCompileForm.UpdateMarginsIcons;
+procedure TCompileForm.UpdateMarginsAndAutoCompleteIcons;
 { Should be called at startup and after theme and DPI changes }
 
 type
-  TMarkerBitmaps = TObjectDictionary<Integer, TBitmapWithBits>;
+  TMarkerOrACBitmaps = TObjectDictionary<Integer, TBitmapWithBits>;
 
   procedure SwapRedBlue(const pvBits: PByte; Width, Height: Integer);
   begin
@@ -3807,8 +3828,8 @@ type
     end;
   end;
 
-  procedure AddMarkerBitmap(const MarkerBitmaps: TMarkerBitmaps; const DC: HDC; const BitmapInfo: TBitmapInfo;
-    const Marker: Integer; const BkBrush: TBrush; const ImageList: TVirtualImageList; const ImageName: String);
+  procedure AddMarkerOrACBitmap(const MarkerOrACBitmaps: TMarkerOrACBitmaps; const DC: HDC; const BitmapInfo: TBitmapInfo;
+    const MarkerNumberOrACType: Integer; const BkBrush: TBrush; const ImageList: TVirtualImageList; const ImageName: String);
   begin
     { Prepare a bitmap and select it }
     var pvBits: Pointer;
@@ -3829,7 +3850,7 @@ type
       var Bitmap2 := TBitmapWithBits.Create;
       Bitmap2.Handle := Bitmap;
       Bitmap2.pvBits := pvBits;
-      MarkerBitmaps.Add(Marker, Bitmap2);
+      MarkerOrACBitmaps.Add(MarkerNumberOrACType, Bitmap2);
     end else begin
       SelectObject(DC, OldBitmap);
       DeleteObject(Bitmap);
@@ -3837,48 +3858,80 @@ type
   end;
 
 type
-  TNamedMarker = TPair<Integer, String>;
+  TMarkerNumberOrACType = TPair<Integer, String>;
 
-  function NM(const Marker: Integer; const Name: String): TNamedMarker;
+  function NNT(const MarkerNumberOrACType: Integer; const Name: String): TMarkerNumberOrACType;
   begin
-    Result := TNamedMarker.Create(Marker, Name); { This is a record so no need to free }
+    Result := TMarkerNumberOrACType.Create(MarkerNumberOrACType, Name); { This is a record so no need to free }
   end;
 
 begin
-  var ImageList := ThemedMarkersVirtualImageList;
+  var ImageList := ThemedMarkersAndACVirtualImageList;
 
   var DC := CreateCompatibleDC(0);
   if DC <> 0 then begin
     try
-      var MarkerBitmaps := TMarkerBitmaps.Create([doOwnsValues]);
-      var BkBrush := TBrush.Create;
+      var MarkerBitmaps: TMarkerOrACBitmaps := nil;
+      var MarkerBkBrush: TBrush := nil;
+      var AutoCompleteBitmaps: TMarkerOrACBitmaps := nil;
+      var AutoCompleteBkBrush: TBrush := nil;
       try
-        BkBrush.Color := FTheme.Colors[tcMarginBack];
+        var BitmapInfo := CreateBitmapInfo(ImageList.Width, -ImageList.Height, 32); { This is a record so no need to free }
 
-        var BitmapInfo := CreateBitmapInfo(ImageList.Width, -ImageList.Height, 32);
+        MarkerBitmaps := TMarkerOrACBitmaps.Create([doOwnsValues]);
+        MarkerBkBrush := TBrush.Create;
+        MarkerBkBrush.Color := FTheme.Colors[tcMarginBack];
 
         var NamedMarkers := [
-            NM(mimHasEntry, 'debug-stop-filled'),
-            NM(mimEntryProcessed, 'debug-stop-filled_2'),
-            NM(mimBreakpoint, 'debug-breakpoint-filled'),
-            NM(mimBreakpointBad, 'debug-breakpoint-filled-cancel-2'),
-            NM(mimBreakpointGood, 'debug-breakpoint-filled-ok-2'),
-            NM(mimStep, 'symbol-arrow-right'),
-            NM(mimBreakpointStep, 'debug-breakpoint-filled-ok2-symbol-arrow-right'),
-            NM(SC_MARKNUM_FOLDER, 'symbol-add'),
-            NM(SC_MARKNUM_FOLDEROPEN, 'symbol-remove')];
+          NNT(mmiHasEntry, 'markers\debug-stop-filled'),
+          NNT(mmiEntryProcessed, 'markers\debug-stop-filled_2'),
+          NNT(mmiBreakpoint, 'markers\debug-breakpoint-filled'),
+          NNT(mmiBreakpointBad, 'markers\debug-breakpoint-filled-cancel-2'),
+          NNT(mmiBreakpointGood, 'markers\debug-breakpoint-filled-ok-2'),
+          NNT(mmiStep, 'markers\symbol-arrow-right'),
+          NNT(mmiBreakpointStep, 'markers\debug-breakpoint-filled-ok2-symbol-arrow-right'),
+          NNT(SC_MARKNUM_FOLDER, 'markers\symbol-add'),
+          NNT(SC_MARKNUM_FOLDEROPEN, 'markers\symbol-remove')];
 
         for var NamedMarker in NamedMarkers do
-          AddMarkerBitmap(MarkerBitmaps, DC, BitmapInfo, NamedMarker.Key, BkBrush, ImageList, NamedMarker.Value);
+          AddMarkerOrAcBitmap(MarkerBitmaps, DC, BitmapInfo, NamedMarker.Key, MarkerBkBrush, ImageList, NamedMarker.Value);
+
+        AutoCompleteBitmaps := TMarkerOrACBitmaps.Create([doOwnsValues]);
+        AutoCompleteBkBrush := TBrush.Create;
+        AutoCompleteBkBrush.Color := FTheme.Colors[tcIntelliBack];
+
+        var NamedTypes := [
+          NNT(awtScriptFunction, 'ac\method-filled'),
+          NNT(awtScriptType, 'ac\types'),
+          NNT(awtScriptVariable, 'ac\variables'),
+          NNT(awtScriptConstant, 'ac\constant-filled'),
+          NNT(awtScriptClass, 'ac\class-filled'),
+          NNT(awtScriptInterface, 'ac\interface-filled'),
+          NNT(awtScriptProperty, 'ac\properties-filled'),
+          NNT(awtScriptObject, 'ac\object-filled'),
+          NNT(awtScriptEvent, 'ac\event-filled'),
+          NNT(awtSection, 'ac\structure-filled'),
+          NNT(awtParameter, 'ac\xml-filled'),
+          NNT(awtDirective, 'ac\xml-filled'),
+          NNT(awtFlag, 'ac\values'),
+          NNT(awtPreprocessorDirective, 'ac\symbol-hashtag'),
+          NNT(awtConstant, 'ac\constant-filled_2')];
+
+        for var NamedType in NamedTypes do
+          AddMarkerOrAcBitmap(AutoCompleteBitmaps, DC, BitmapInfo, NamedType.Key, AutoCompleteBkBrush, ImageList, NamedType.Value);
 
         for var Memo in FMemos do begin
           Memo.Call(SCI_RGBAIMAGESETWIDTH, ImageList.Width, 0);
           Memo.Call(SCI_RGBAIMAGESETHEIGHT, ImageList.Height, 0);
           for var MarkerBitmap in MarkerBitmaps do
             Memo.Call(SCI_MARKERDEFINERGBAIMAGE, MarkerBitmap.Key, LPARAM(MarkerBitmap.Value.pvBits));
+          for var AutoCompleteBitmap in AutoCompleteBitmaps do
+            Memo.Call(SCI_REGISTERRGBAIMAGE, AutoCompleteBitmap.Key, LPARAM(AutoCompleteBitmap.Value.pvBits));
         end;
       finally
-        BkBrush.Free;
+        AutoCompleteBkBrush.Free;
+        AutoCompleteBitmaps.Free;
+        MarkerBkBrush.Free;
         MarkerBitmaps.Free;
       end;
     finally
@@ -4048,7 +4101,7 @@ begin
     OptionsForm.UndoAfterSaveCheck.Checked := FOptions.UndoAfterSave;
     OptionsForm.PauseOnDebuggerExceptionsCheck.Checked := FOptions.PauseOnDebuggerExceptions;
     OptionsForm.RunAsDifferentUserCheck.Checked := FOptions.RunAsDifferentUser;
-    OptionsForm.AutoCompleteCheck.Checked := FOptions.AutoComplete;
+    OptionsForm.AutoAutoCompleteCheck.Checked := FOptions.AutoAutoComplete;
     OptionsForm.UseSynHighCheck.Checked := FOptions.UseSyntaxHighlighting;
     OptionsForm.ColorizeCompilerOutputCheck.Checked := FOptions.ColorizeCompilerOutput;
     OptionsForm.UnderlineErrorsCheck.Checked := FOptions.UnderlineErrors;
@@ -4081,7 +4134,7 @@ begin
     FOptions.UndoAfterSave := OptionsForm.UndoAfterSaveCheck.Checked;
     FOptions.PauseOnDebuggerExceptions := OptionsForm.PauseOnDebuggerExceptionsCheck.Checked;
     FOptions.RunAsDifferentUser := OptionsForm.RunAsDifferentUserCheck.Checked;
-    FOptions.AutoComplete := OptionsForm.AutoCompleteCheck.Checked;
+    FOptions.AutoAutoComplete := OptionsForm.AutoAutoCompleteCheck.Checked;
     FOptions.UseSyntaxHighlighting := OptionsForm.UseSynHighCheck.Checked;
     FOptions.ColorizeCompilerOutput := OptionsForm.ColorizeCompilerOutputCheck.Checked;
     FOptions.UnderlineErrors := OptionsForm.UnderlineErrorsCheck.Checked;
@@ -4127,7 +4180,8 @@ begin
       Ini.WriteBool('Options', 'UndoAfterSave', FOptions.UndoAfterSave);
       Ini.WriteBool('Options', 'PauseOnDebuggerExceptions', FOptions.PauseOnDebuggerExceptions);
       Ini.WriteBool('Options', 'RunAsDifferentUser', FOptions.RunAsDifferentUser);
-      Ini.WriteBool('Options', 'AutoComplete', FOptions.AutoComplete);
+      Ini.WriteBool('Options', 'AutoComplete', FOptions.AutoAutoComplete);
+      Ini.WriteBool('Options', 'AutoCallTips', FOptions.AutoCallTips);
       Ini.WriteBool('Options', 'UseSynHigh', FOptions.UseSyntaxHighlighting);
       Ini.WriteBool('Options', 'ColorizeCompilerOutput', FOptions.ColorizeCompilerOutput);
       Ini.WriteBool('Options', 'UnderlineErrors', FOptions.UnderlineErrors);
@@ -4752,9 +4806,16 @@ begin
   Memo.ReportCaretPositionToStyler := True;
 end;
 
+function TCompileForm.InitiateAutoCompleteOrCallTipAllowedAtPos(const AMemo: TCompScintEdit;
+  const WordStartLinePos, PositionBeforeWordStartPos: Integer): Boolean;
+begin
+  Result := (PositionBeforeWordStartPos >= WordStartLinePos) and
+            not FMemosStyler.IsCommentOrPascalStringStyle(AMemo.GetStyleAtPosition(PositionBeforeWordStartPos));
+end;
+
 procedure TCompileForm.InitiateAutoComplete(const Key: AnsiChar);
 
-  function CheckWhiteSpace(const Memo: TCompScintEdit; const LinePos, WordStartPos: Integer): Boolean;
+  function OnlyWhiteSpaceBeforeWord(const Memo: TCompScintEdit; const LinePos, WordStartPos: Integer): Boolean;
   var
     I: Integer;
     C: AnsiChar;
@@ -4775,13 +4836,12 @@ procedure TCompileForm.InitiateAutoComplete(const Key: AnsiChar);
 
 var
   CaretPos, Line, LinePos, WordStartPos, WordEndPos, CharsBefore,
-    PrevWordStartPos, PrevWordEndPos, I, LangNamePos: Integer;
+    LangNamePos: Integer;
   Section: TInnoSetupStylerSection;
   IsParamSection: Boolean;
   WordList: AnsiString;
   FoundSemicolon, FoundFlagsOrType, FoundDot: Boolean;
   C: AnsiChar;
-  S: String;
 begin
   if FActiveMemo.AutoCompleteActive or FActiveMemo.ReadOnly then
     Exit;
@@ -4802,7 +4862,7 @@ begin
   WordEndPos := FActiveMemo.GetWordEndPosition(CaretPos, True);
   CharsBefore := CaretPos - WordStartPos;
 
-  { Don't start autocompletion after a character is typed if there are any
+  { Don't auto start autocompletion after a character is typed if there are any
     word characters adjacent to the character }
   if Key <> #0 then begin
     if CharsBefore > 1 then
@@ -4814,7 +4874,7 @@ begin
   case FActiveMemo.GetByteAtPosition(WordStartPos) of
     '#':
       begin
-        if not CheckWhiteSpace(FActiveMemo, LinePos, WordStartPos) then
+        if not OnlyWhiteSpaceBeforeWord(FActiveMemo, LinePos, WordStartPos) then
           Exit;
         WordList := FMemosStyler.ISPPDirectivesWordList;
         FActiveMemo.SetAutoCompleteFillupChars(' ');
@@ -4826,7 +4886,7 @@ begin
       end;
     '[':
       begin
-        if not CheckWhiteSpace(FActiveMemo, LinePos, WordStartPos) then
+        if not OnlyWhiteSpaceBeforeWord(FActiveMemo, LinePos, WordStartPos) then
           Exit;
         WordList := FMemosStyler.SectionsWordList;
         FActiveMemo.SetAutoCompleteFillupChars('');
@@ -4835,36 +4895,53 @@ begin
       begin
         Section := FMemosStyler.GetSectionFromLineState(FActiveMemo.Lines.State[Line]);
         if Section = scCode then begin
-          { Only allow autocompletion if the previous word on the line is 'function' or 'procedure',
-            exactly 1 space exists between it and the current word and no non-whitespace characters
-            exist before it on the line }
-          I := FActiveMemo.GetPositionBefore(WordStartPos);
-          if I < LinePos then
-            Exit;
-          if FActiveMemo.GetByteAtPosition(I) > ' ' then
-            Exit;
-          PrevWordEndPos := I;
-          PrevWordStartPos := FActiveMemo.GetWordStartPosition(PrevWordEndPos, True);
-          S := FActiveMemo.GetTextRange(PrevWordStartPos, PrevWordEndPos);
-          if SameText(S, 'procedure') then
-            WordList := FMemosStyler.EventFunctionsWordList[True]
-          else if SameText(S, 'function') then
-            WordList := FMemosStyler.EventFunctionsWordList[False]
-          else
+          var PositionBeforeWordStartPos := FActiveMemo.GetPositionBefore(WordStartPos);
+          if Key <> #0 then
+            FActiveMemo.StyleNeeded(PositionBeforeWordStartPos); { Make sure the typed character has been styled }
+          if not InitiateAutoCompleteOrCallTipAllowedAtPos(FActiveMemo, LinePos, PositionBeforeWordStartPos) then
             Exit;
-          if not CheckWhiteSpace(FActiveMemo, LinePos, PrevWordStartPos) then
+
+          WordList := '';
+
+          { Autocomplete event functions if the current word on the line has
+            exactly 1 space before it which has the word 'function' or
+            'procedure' before it which has only whitespace before it }
+          if (PositionBeforeWordStartPos >= LinePos) and (FActiveMemo.GetByteAtPosition(PositionBeforeWordStartPos) <= ' ') then begin
+            var FunctionWordEndPos := PositionBeforeWordStartPos;
+            var FunctionWordStartPos := FActiveMemo.GetWordStartPosition(FunctionWordEndPos, True);
+            if OnlyWhiteSpaceBeforeWord(FActiveMemo, LinePos, FunctionWordStartPos) then begin
+              var FunctionWord := FActiveMemo.GetTextRange(FunctionWordStartPos, FunctionWordEndPos);
+              if SameText(FunctionWord, 'procedure') then
+                WordList := FMemosStyler.EventFunctionsWordList[True]
+              else if SameText(FunctionWord, 'function') then
+                WordList := FMemosStyler.EventFunctionsWordList[False];
+              if WordList <> '' then
+                FActiveMemo.SetAutoCompleteFillupChars('');
+            end;
+          end;
+
+          { If no event function was found then autocomplete script functions if
+            the current word has no dot before it }
+          if WordList = '' then begin
+            var ClassFunction := (PositionBeforeWordStartPos >= LinePos) and (FActiveMemo.GetByteAtPosition(PositionBeforeWordStartPos) = '.');
+            if not ClassFunction then begin
+              WordList := FMemosStyler.ScriptWordList;
+              FActiveMemo.SetAutoCompleteFillupChars('(')
+            end;
+          end;
+
+          if WordList = '' then
             Exit;
-          FActiveMemo.SetAutoCompleteFillupChars('');
         end else begin
           IsParamSection := FMemosStyler.IsParamSection(Section);
 
-          { Only allow autocompletion if no non-whitespace characters exist before
-            the current word on the line, or after the last ';' or 'Flags:' or 'Type:' in parameterized
-            sections }
+          { Autocomplete if the current word on the line has only whitespace
+            before it, or else also: after the last ';' or after 'Flags:' or
+            'Type:' in parameterized sections }
           FoundSemicolon := False;
           FoundFlagsOrType := False;
           FoundDot := False;
-          I := WordStartPos;
+          var I := WordStartPos;
           while I > LinePos do begin
             I := FActiveMemo.GetPositionBefore(I);
             if I < LinePos then
@@ -4875,11 +4952,11 @@ begin
                FMemosStyler.IsSymbolStyle(FActiveMemo.GetStyleAtPosition(I)) then begin { Make sure it's an stSymbol ';' or ':' and not one inside a quoted string }
               FoundSemicolon := C = ';';
               if not FoundSemicolon then begin
-                PrevWordEndPos := I;
-                PrevWordStartPos := FActiveMemo.GetWordStartPosition(PrevWordEndPos, True);
-                S := FActiveMemo.GetTextRange(PrevWordStartPos, PrevWordEndPos);
-                FoundFlagsOrType := SameText(S, 'Flags') or
-                                    ((Section in [scInstallDelete, scUninstallDelete]) and SameText(S, 'Type'));
+                var ParameterWordEndPos := I;
+                var ParameterWordStartPos := FActiveMemo.GetWordStartPosition(ParameterWordEndPos, True);
+                var ParameterWord := FActiveMemo.GetTextRange(ParameterWordStartPos,ParameterWordEndPos);
+                FoundFlagsOrType := SameText(ParameterWord, 'Flags') or
+                                    ((Section in [scInstallDelete, scUninstallDelete]) and SameText(ParameterWord, 'Type'));
               end else
                 FoundFlagsOrType := False;
               Break;
@@ -4922,6 +4999,129 @@ begin
   FActiveMemo.ShowAutoComplete(CharsBefore, WordList);
 end;
 
+procedure TCompileForm.InitiateCallTip;
+begin
+  var Pos := FActiveMemo.CaretPosition;
+
+  if (FMemosStyler.GetSectionFromLineState(FActiveMemo.Lines.State[FActiveMemo.GetLineFromPosition(Pos)]) <> scCode) or
+     not InitiateAutoCompleteOrCallTipAllowedAtPos(FActiveMemo,
+       FActiveMemo.GetPositionFromLine(FActiveMemo.GetLineFromPosition(Pos)),
+       FActiveMemo.GetPositionBefore(Pos)) then
+    Exit;
+
+  { Based on SciTE 5.50's SciTEBase::StartAutoComplete and
+    SciTEBase::FillFunctionDefinition, without support for multiple calltips }
+
+  { StartAutoComplete }
+
+  var CurrentCallTipWord := '';
+  var Line := FActiveMemo.CaretLineText;
+  var Current := FActiveMemo.CaretPositionInLine;
+  var CalltipWordCharacters := FActiveMemo.WordCharsAsSet;
+
+  {$ZEROBASEDSTRINGS ON}
+  repeat
+    var Braces := 0;
+		while ((Current > 0) and ((Braces <> 0) or not (Line[Current-1] = '('))) do begin
+			if Line[Current-1] = '(' then
+			  Dec(Braces)
+			else if Line[Current-1] = ')' then
+				Inc(Braces);
+			Dec(Current);
+			Dec(Pos);
+    end;
+    if Current > 0 then begin
+      Dec(Current);
+      Dec(Pos);
+    end else
+      Break;
+    while (Current > 0) and (Line[Current-1] <= ' ') do begin
+      Dec(Current);
+      Dec(Pos);
+    end
+  until not ((Current > 0) and not CharInSet(Line[Current-1], CalltipWordCharacters));
+  {$ZEROBASEDSTRINGS OFF}
+  if Current <= 0 then
+    Exit;
+
+	FCallTipState.StartCalltipWord := Current - 1;
+  {$ZEROBASEDSTRINGS ON}
+	while (FCallTipState.StartCalltipWord > 0) and CharInSet(Line[FCallTipState.StartCalltipWord-1], CalltipWordCharacters) do
+    Dec(FCallTipState.StartCallTipWord);
+  var ClassFunction := (FCallTipState.StartCalltipWord > 0) and (Line[FCallTipState.StartCalltipWord-1] = '.');
+  {$ZEROBASEDSTRINGS OFF}
+
+  SetLength(Line, Current);
+  CurrentCallTipWord := Line.Substring(FCallTipState.StartCallTipWord); { Substring is zero-based }
+
+  FCallTipState.FunctionDefinition := '';
+
+  { FillFunctionDefinition - if this is separated for multiple calltips support like in SciTE then the following vars
+    need to be moved into FCallTipState: CurrentCallTipWord, ClassFunction, LastPosCallTip }
+
+  var LastPosCallTip := Pos;
+
+  // Should get current api definition
+  var Word: AnsiString;
+  if not ClassFunction then
+    Word := FMemosStyler.ScriptFunctionDefinition[CurrentCallTipWord]
+  else
+    Word := '';
+  if Word <> '' then begin
+    FCallTipState.FunctionDefinition := Word;
+    FActiveMemo.ShowCallTip(LastPosCallTip - Length(CurrentCallTipWord), FCallTipState.FunctionDefinition);
+    ContinueCallTip;
+  end;
+end;
+
+procedure TCompileForm.ContinueCallTip;
+begin
+  { Based on SciTE 5.50's SciTEBase::ContinueCallTip }
+
+	var Line := FActiveMemo.CaretLineText;
+	var Current := FActiveMemo.CaretPositionInLine;
+
+	var Braces := 0;
+	var Commas := 0;
+	for var I := FCallTipState.StartCalltipWord to Current-1 do begin
+    {$ZEROBASEDSTRINGS ON}
+		if Line[I] = '(' then
+      Inc(Braces)
+		else if (Line[I] = ')') and (Braces > 0) then
+			Dec(Braces)
+		else if (Braces = 1) and (Line[I] = ',') then
+			Inc(Commas);
+    {$ZEROBASEDSTRINGS OFF}
+	end;
+
+  {$ZEROBASEDSTRINGS ON}
+	var StartHighlight := 0;
+  var FunctionDefinition := FCallTipState.FunctionDefinition;
+  var FunctionDefinitionLength := Length(FunctionDefinition);
+	while (StartHighlight < FunctionDefinitionLength) and not (FunctionDefinition[StartHighlight] = '(') do
+		Inc(StartHighlight);
+	if (StartHighlight < FunctionDefinitionLength) and (FunctionDefinition[StartHighlight] = '(') then
+		Inc(StartHighlight);
+	while (StartHighlight < FunctionDefinitionLength) and (Commas > 0) do begin
+		if FunctionDefinition[StartHighlight] in [',', ';'] then
+			Dec(Commas);
+		// If it reached the end of the argument list it means that the user typed in more
+		// arguments than the ones listed in the calltip
+		if FunctionDefinition[StartHighlight] = ')' then
+			Commas := 0
+		else
+			Inc(StartHighlight);
+	end;
+	if (StartHighlight < FunctionDefinitionLength) and (FunctionDefinition[StartHighlight] in [',', ';']) then
+		Inc(StartHighlight);
+	var EndHighlight := StartHighlight;
+	while (EndHighlight < FunctionDefinitionLength) and not (FunctionDefinition[EndHighlight] in [',', ';']) and not (FunctionDefinition[EndHighlight] = ')') do
+		Inc(EndHighlight);
+  {$ZEROBASEDSTRINGS OFF}
+
+	FActiveMemo.SetCallTipHighlight(StartHighlight, EndHighlight);
+end;
+
 procedure TCompileForm.MemoCharAdded(Sender: TObject; Ch: AnsiChar);
 
   function LineIsBlank(const Line: Integer): Boolean;
@@ -4932,7 +5132,6 @@ procedure TCompileForm.MemoCharAdded(Sender: TObject; Ch: AnsiChar);
 
 var
   NewLine, PreviousLine, NewIndent, PreviousIndent: Integer;
-  RestartAutoComplete: Boolean;
 begin
   if FOptions.AutoIndent and (Ch = FActiveMemo.LineEndingString[Length(FActiveMemo.LineEndingString)]) then begin
     { Add to the new line any (remaining) indentation from the previous line }
@@ -4958,17 +5157,53 @@ begin
       end;
     end;
   end;
+  
+  { Based on SciTE 5.50's SciTEBase::CharAdded but with an altered interaction
+    between calltips and autocomplete }
+
+  var DoAutoComplete := False;
+
+  if FActiveMemo.CallTipActive then begin
+    if Ch = ')' then begin
+      Dec(FCallTipState.BraceCount);
+      if FCallTipState.BraceCount < 1 then
+        FActiveMemo.CancelCallTip
+      else if FOptions.AutoCallTips then
+        InitiateCallTip;
+    end else if Ch = '(' then begin
+      Inc(FCallTipState.BraceCount);
+      if FOptions.AutoCallTips then
+        InitiateCallTip;
+    end else
+      ContinueCallTip;
+  end else if FActiveMemo.AutoCompleteActive then begin
+    if Ch = '(' then begin
+      Inc(FCallTipState.BraceCount);
+      if FOptions.AutoCallTips then
+        InitiateCallTip;
+    end else if Ch = ')' then
+      Dec(FCallTipState.BraceCount)
+    else
+      DoAutoComplete := True;
+  end else if Ch = '(' then begin
+    FCallTipState.BraceCount := 1;
+    if FOptions.AutoCallTips then
+      InitiateCallTip;
+  end else
+    DoAutoComplete := True;
 
-  case Ch of
-    'A'..'Z', 'a'..'z', '_', '#', '{', '[':
-      if FOptions.AutoComplete then
+  if DoAutoComplete then begin
+    case Ch of
+      'A'..'Z', 'a'..'z', '_', '#', '{', '[':
+        if not FActiveMemo.AutoCompleteActive and FOptions.AutoAutoComplete then
+          InitiateAutoComplete(Ch);
+    else
+      var RestartAutoComplete := (Ch in [' ', '.']) and
+        (FOptions.AutoAutoComplete or FActiveMemo.AutoCompleteActive);
+      FActiveMemo.CancelAutoComplete;
+      if RestartAutoComplete then
         InitiateAutoComplete(Ch);
-  else
-    RestartAutoComplete := (Ch in [' ', '.']) and
-      (FOptions.AutoComplete or FActiveMemo.AutoCompleteActive);
-    FActiveMemo.CancelAutoComplete;
-    if RestartAutoComplete then
-      InitiateAutoComplete(Ch);
+    end;
   end;
 end;
 
@@ -5777,14 +6012,14 @@ begin
 
   if FTheme.Dark then begin
     ThemedToolbarVirtualImageList.ImageCollection := DarkToolBarImageCollection;
-    ThemedMarkersVirtualImageList.ImageCollection := DarkMarkersImageCollection;
+    ThemedMarkersAndACVirtualImageList.ImageCollection := DarkMarkersAndACImageCollection;
   end else begin
     ThemedToolbarVirtualImageList.ImageCollection := LightToolBarImageCollection;
-    ThemedMarkersVirtualImageList.ImageCollection := LightMarkersImageCollection;
+    ThemedMarkersAndACVirtualImageList.ImageCollection := LightMarkersAndACImageCollection;
   end;
 
   UpdateBevel1Visibility;
-  UpdateMarginsIcons;
+  UpdateMarginsAndAutoCompleteIcons;
 
   SplitPanel.ParentBackground := False;
   SplitPanel.Color := FTheme.Colors[tcSplitterBack];
@@ -7089,18 +7324,18 @@ begin
   NewMarker := -1;
   if AMemo.BreakPoints.IndexOf(Line) <> -1 then begin
     if AMemo.LineState = nil then
-      NewMarker := mimBreakpoint
+      NewMarker := mmiBreakpoint
     else if (Line < AMemo.LineStateCount) and (AMemo.LineState[Line] <> lnUnknown) then
-      NewMarker := IfThen(StepLine, mimBreakpointStep, mimBreakpointGood)
+      NewMarker := IfThen(StepLine, mmiBreakpointStep, mmiBreakpointGood)
     else
-      NewMarker := mimBreakpointBad;
+      NewMarker := mmiBreakpointBad;
   end else if StepLine then
-    NewMarker := mimStep
+    NewMarker := mmiStep
   else begin
     if Line < AMemo.LineStateCount then begin
       case AMemo.LineState[Line] of
-        lnHasEntry: NewMarker := mimHasEntry;
-        lnEntryProcessed: NewMarker := mimEntryProcessed;
+        lnHasEntry: NewMarker := mmiHasEntry;
+        lnEntryProcessed: NewMarker := mmiEntryProcessed;
       end;
     end;
   end;
@@ -7117,7 +7352,7 @@ begin
     AMemo.AddMarker(Line, mlmStep)
   else if AMemo.ErrorLine = Line then
     AMemo.AddMarker(Line, mlmError)
-  else if NewMarker = mimBreakpointBad then
+  else if NewMarker = mmiBreakpointBad then
     AMemo.AddMarker(Line, mlmBreakpointBad);
 end;
 

+ 1 - 1
Projects/Src/CompOptions.dfm

@@ -164,7 +164,7 @@ object OptionsForm: TOptionsForm
     Anchors = [akLeft, akTop, akBottom]
     Caption = ' Editor '
     TabOrder = 2
-    object AutoCompleteCheck: TCheckBox
+    object AutoAutoCompleteCheck: TCheckBox
       Left = 8
       Top = 16
       Width = 265

+ 1 - 1
Projects/Src/CompOptions.pas

@@ -43,7 +43,7 @@ type
     AutoIndentCheck: TCheckBox;
     IndentationGuidesCheck: TCheckBox;
     UseTabCharacterCheck: TCheckBox;
-    AutoCompleteCheck: TCheckBox;
+    AutoAutoCompleteCheck: TCheckBox;
     UnderlineErrorsCheck: TCheckBox;
     GutterLineNumbersCheck: TCheckBox;
     ColorizeCompilerOutputCheck: TCheckBox;

+ 21 - 11
Projects/Src/CompScintEdit.pas

@@ -22,15 +22,15 @@ const
   mmChangeHistory = 2;
   mmFolding = 3;
 
-  { Memo icon and line marker numbers }
-  mimHasEntry = 0;        { grey dot }
-  mimEntryProcessed = 1;  { green dot }
-  mimBreakpoint = 2;      { stop sign }
-  mimBreakpointGood = 3;  { stop sign + check }
-  mimBreakpointBad = 4;   { stop sign + X }
-  mimStep = 5;            { blue arrow }
-  mimBreakpointStep = 6;  { blue arrow on top of a stop sign + check }
-  mimMask = $7F;
+  { Memo marker icon and line marker numbers }
+  mmiHasEntry = 0;        { grey dot }
+  mmiEntryProcessed = 1;  { green dot }
+  mmiBreakpoint = 2;      { stop sign }
+  mmiBreakpointGood = 3;  { stop sign + check }
+  mmiBreakpointBad = 4;   { stop sign + X }
+  mmiStep = 5;            { blue arrow }
+  mmiBreakpointStep = 6;  { blue arrow on top of a stop sign + check }
+  mmiMask = $7F;
 
   mlmError = 10;          { maroon line highlight }
   mlmBreakpointBad = 11;  { ugly olive line highlight }
@@ -220,6 +220,12 @@ begin
   Call(SCI_AUTOCSETIGNORECASE, 1, 0);
   Call(SCI_AUTOCSETOPTIONS, SC_AUTOCOMPLETE_FIXED_SIZE, 0); { Removes the ugly WS_THICKFRAME header at the cost of resizability }
   Call(SCI_AUTOCSETMAXHEIGHT, 12, 0);
+  Call(SCI_AUTOCSETMINWIDTH, 50, 0);
+  Call(SCI_AUTOCSETMAXWIDTH, 50, 0);
+
+  { Same color as AutoComplete's border color, works well for both dark and light themes }
+  var BorderColor := ColorToRGB(clWindowFrame);
+  Call(SCI_CALLTIPSETFOREBORDER, BorderColor, BorderColor);
 
   Call(SCI_SETMULTIPLESELECTION, 1, 0);
   Call(SCI_SETADDITIONALSELECTIONTYPING, 1, 0);
@@ -253,7 +259,7 @@ begin
 
   { Set up the gutter column with breakpoint etc symbols }
   Call(SCI_SETMARGINTYPEN, mmIcons, SC_MARGIN_SYMBOL);
-  Call(SCI_SETMARGINMASKN, mmIcons, mimMask);
+  Call(SCI_SETMARGINMASKN, mmIcons, mmiMask);
   Call(SCI_SETMARGINSENSITIVEN, mmIcons, 1); { Makes it send SCN_MARGIN(RIGHT)CLICK instead of selecting lines }
   Call(SCI_SETMARGINCURSORN, mmIcons, SC_CURSORARROW);
 
@@ -466,7 +472,7 @@ begin
     Color := FTheme.Colors[tcBack];
 
     Call(SCI_SETELEMENTCOLOUR, SC_ELEMENT_LIST, FTheme.Colors[tcFore] or (SC_ALPHA_OPAQUE shl 24));
-    Call(SCI_SETELEMENTCOLOUR, SC_ELEMENT_LIST_BACK, FTheme.Colors[tcBack] or (SC_ALPHA_OPAQUE shl 24));
+    Call(SCI_SETELEMENTCOLOUR, SC_ELEMENT_LIST_BACK, FTheme.Colors[tcIntelliBack] or (SC_ALPHA_OPAQUE shl 24));
     var Options := Call(SCI_AUTOCGETOPTIONS, 0, 0);
     if FTheme.Dark then
       Options := Options or SC_AUTOCOMPLETE_DARK_MODE
@@ -474,6 +480,10 @@ begin
       Options := Options and not SC_AUTOCOMPLETE_DARK_MODE;
     Call(SCI_AUTOCSETOPTIONS, Options, 0);
 
+    Call(SCI_CALLTIPSETFORE, FTheme.Colors[tcFore], 0);
+    Call(SCI_CALLTIPSETBACK, FTheme.Colors[tcIntelliBack], 0);
+    Call(SCI_CALLTIPSETFOREHLT, FTheme.Colors[tcBlue], 0);
+
     var SelBackColor := FTheme.Colors[tcSelBack];
     Call(SCI_SETELEMENTCOLOUR, SC_ELEMENT_SELECTION_BACK, SelBackColor);
     Call(SCI_SETELEMENTCOLOUR, SC_ELEMENT_SELECTION_ADDITIONAL_BACK, SelBackColor);

+ 3 - 0
Projects/Src/IsscintInt.pas

@@ -27,6 +27,9 @@ const
   SC_CMDKEYS_VSCODE_WINDOWS = 1;
   SCI_RESETALLCMDKEYS = 2812;
   SC_AUTOCOMPLETE_DARK_MODE = 4;
+  SCI_CALLTIPSETFOREBORDER = 2813;
+  SCI_AUTOCSETMINWIDTH = 2814;
+  SCI_AUTOCGETMINWIDTH = 2815;
 
 implementation
 

+ 3 - 3
Projects/Src/ScriptClasses_C.pas

@@ -72,9 +72,9 @@ begin
   Cl.AddTypeS('TCheckItemOperation', '(coUncheck, coCheck, coCheckWithChildren)');
   with Cl.AddClassN(Cl.FindClass('TCustomListBox'), 'TNewCheckListBox') do
   begin
-    RegisterMethod('function AddCheckBox(const ACaption, ASubItem: string; ALevel: Byte; AChecked, AEnabled, AHasInternalChildren, ACheckWhenParentChecked: Boolean; AObject: TObject): Integer');
-    RegisterMethod('function AddGroup(const ACaption, ASubItem: string; ALevel: Byte; AObject: TObject): Integer');
-    RegisterMethod('function AddRadioButton(const ACaption, ASubItem: string; ALevel: Byte; AChecked, AEnabled: Boolean; AObject: TObject): Integer');
+    RegisterMethod('function AddCheckBox(const ACaption, ASubItem: String; ALevel: Byte; AChecked, AEnabled, AHasInternalChildren, ACheckWhenParentChecked: Boolean; AObject: TObject): Integer');
+    RegisterMethod('function AddGroup(const ACaption, ASubItem: String; ALevel: Byte; AObject: TObject): Integer');
+    RegisterMethod('function AddRadioButton(const ACaption, ASubItem: String; ALevel: Byte; AChecked, AEnabled: Boolean; AObject: TObject): Integer');
     RegisterMethod('function CheckItem(const Index: Integer; const AOperation: TCheckItemOperation): Boolean');
     RegisterProperty('Anchors', 'TAnchors', iptrw);
     RegisterProperty('Checked', 'Boolean Integer', iptrw);

+ 298 - 116
Projects/Src/ScriptFunc.pas

@@ -2,20 +2,208 @@ unit ScriptFunc;
 
 {
   Inno Setup
-  Copyright (C) 1997-2020 Jordan Russell
+  Copyright (C) 1997-2024 Jordan Russell
   Portions by Martijn Laan
   For conditions of distribution and use, see LICENSE.TXT.
 
-  Script support functions
+  Script support functions (listings - used by Compil32, ISCmplr, and Setup)
+
+  Script constants, types, etc (listings - used by Compil32)
 }
 
 interface
 
-const
+type
+  TScriptFuncTableID = (sftScriptDlg, sftNewDisk, sftBrowseFunc, sftCmnFunc,
+    sftCmnFunc2, sftInstall, sftInstFunc, sftInstFnc2, sftMain, sftMsgs,
+    sftSystem, sftSysUtils, sftVerInfo, sftWindows, sftOle2, sftLogging,
+    sftOther);
+  TScriptTable = array of AnsiString;
+
+var
+  ScriptFuncTables: array [TScriptFuncTableID] of TScriptTable; { Initialized below }
+
+  DelphiScriptFuncTable: TScriptTable =
+  [
+    'function FmtMessage(const S: String; const Args: array of String): String;',
+    'function FindFirst(const FileName: String; var FindRec: TFindRec): Boolean;',
+    'function FindNext(var FindRec: TFindRec): Boolean;',
+    'procedure FindClose(var FindRec: TFindRec);',
+    'function Format(const Format: String; const Args: array of const): String;',
+    'procedure GetWindowsVersionEx(var Version: TWindowsVersion);'
+  ];
+
+{$IFDEF COMPIL32PROJ}
+
+  { These are just for Compil32 and should not be used by ISCmplr or Setup because
+    they're already registered by TPSPascalCompiler.DefineStandardProcedures and
+    TPSExec.RegisterStandardProc }
+  ROPSScriptFuncTable: TScriptTable =
+  [
+    'function StrToIntDef(S: String; Def: LongInt): LongInt;',
+    'function StrToInt(S: String): LongInt;',
+    'function StrToInt64Def(S: String; Def: Int64): Int64;',
+    'function StrToInt64(S: String): Int64;',
+    'function StrToFloat(S: String): Extended;',
+    'function IntToStr(I: Int64): String;',
+    'function FloatToStr(E: Extended): String;',
+    'function Copy(S: AnyString; Index, Count: Integer): String;',
+    'function Length(S: AnyString): LongInt;',
+    'procedure SetLength(var S: AnyString; L: LongInt);',
+    'function Lowercase(S: AnyString): String;',
+    'function Uppercase(S: AnyString): String;',
+    'function AnsiLowercase(S: AnyString): String;',
+    'function AnsiUppercase(S: AnyString): String;',
+    'function StringOfChar(C: Char; I : LongInt): String;',
+    'procedure Delete(var S: AnyString; Index, Count: Integer);',
+    'procedure Insert(Source: AnyString; var Dest: AnyString; Index: Integer);',
+    'function Pos(SubStr, S: AnyString): Integer;',
+    'function GetArrayLength(var Arr: Array): LongInt;',
+    'procedure SetArrayLength(var Arr: Array; I: LongInt);',
+    'function Trim(const S: AnyString): AnyString;',
+    'function Null: Variant;',
+    'function Unassigned: Variant;',
+    'function VarIsEmpty(const V: Variant): Boolean;',
+    'function VarIsClear(const V: Variant): Boolean;',
+    'function VarIsNull(const V: Variant): Boolean;',
+    'function VarType(const V: Variant): TVarType;',
+    'function VarArrayGet(var S: Variant; I: Integer): Variant;',
+    'procedure VarArraySet(C: Variant; I: Integer; var S: Variant);',
+    'function IDispatchInvoke(Self: IDispatch; PropertySet: Boolean; const Name: String; Par: array of Variant): Variant;',
+    { Special functions: undocumented but listing anyway }
+    'function Low(var X): Int64;',
+    'function High(var X): Int64;',
+    'procedure Dec(var X: Ordinal);',
+    'procedure Inc(var X: Ordinal);',
+    'procedure Include(var S: Set; I: Ordinal);',
+    'procedure Exclude(var S: Set; I: Ordinal);',
+    'function SizeOf(var X): LongInt;'
+  ];
+
+  { ROPSUndocumentedScriptFuncTable: TScriptTable =
+  [
+    'function StrGet(var S: String; I: Integer): Char;',
+    'function StrGet2(S: String; I: Integer): Char;',
+    'procedure StrSet(C: Char; I: Integer; var S: String);',
+    'function WStrGet(var S: AnyString; I: Integer): WideChar;',
+    'procedure WStrSet(C: AnyString; I: Integer; var S: AnyString);',
+    'function Sin(E: Extended): Extended;',
+    'function Cos(E: Extended): Extended;',
+    'function Sqrt(E: Extended): Extended;',
+    'function Round(E: Extended): LongInt;',
+    'function Trunc(E: Extended): LongInt;',
+    'function Int(E: Extended): Extended;',
+    'function Pi: Extended;',
+    'function Abs(E: Extended): Extended;',
+    'function PadL(S: AnyString; I: LongInt): AnyString;',
+    'function PadR(S: AnyString; I: LongInt): AnyString;',
+    'function PadZ(S: AnyString; I: LongInt): AnyString;',
+    'function Replicate(C: Char; I: LongInt): String;',
+    'procedure RaiseLastException;',
+    'procedure RaiseException(Ex: TIFException; Param: String);',
+    'function ExceptionType: TIFException;',
+    'function ExceptionParam: String;',
+    'function ExceptionProc: Cardinal;',
+    'function ExceptionPos: Cardinal;',
+    'function ExceptionToString(er: TIFException; Param: String): String;',
+    'function Int64ToStr(I: Int64): String;'
+  ]; }
+
+{$ENDIF}
+
+function ScriptFuncHasParameters(const ScriptFunc: AnsiString): Boolean;
+function RemoveScriptFuncHeader(const ScriptFunc: AnsiString): AnsiString; overload;
+function RemoveScriptFuncHeader(const ScriptFunc: AnsiString; out WasFunction: Boolean): AnsiString; overload;
+function ExtractScriptFuncWithoutHeaderName(const ScriptFuncWithoutHeader: AnsiString): AnsiString;
+function ExtractScriptFuncName(const ScriptFunc: AnsiString): AnsiString;
+
+implementation
+
+uses
+  SysUtils, AnsiStrings;
+
+function ScriptFuncHasParameters(const ScriptFunc: AnsiString): Boolean;
+begin
+  const C: AnsiString = '(';
+
+  Result := Pos(C, ScriptFunc) <> 0;
+end;
+
+function RemoveScriptFuncHeader(const ScriptFunc: AnsiString): AnsiString;
+begin
+  var Dummy: Boolean;
+  Result := RemoveScriptFuncHeader(ScriptFunc, Dummy);
+end;
+
+function RemoveScriptFuncHeader(const ScriptFunc: AnsiString; out WasFunction: Boolean): AnsiString;
+begin
+  Result := ScriptFunc;
+
+  const H1: AnsiString = 'function ';
+  const H2: AnsiString = 'procedure ';
+
+  WasFunction := CompareText(Copy(Result, 1, Length(H1)), H1) = 0;
+
+  if WasFunction then
+    Delete(Result, 1, Length(H1))
+  else if CompareText(Copy(Result, 1, Length(H2)), H2) = 0 then
+    Delete(Result, 1, Length(H2))
+  else
+    raise Exception.CreateFmt('Invalid FunctionDefinition: %s', [Result]);
+end;
+
+function ExtractScriptFuncWithoutHeaderName(const ScriptFuncWithoutHeader: AnsiString): AnsiString;
+begin
+  Result := ScriptFuncWithoutHeader;
+
+  const C1: AnsiString = '(';
+  const C2: AnsiString = ':';
+  const C3: AnsiString = ';';
+
+  var P := Pos(C1, Result);
+  if P = 0 then
+    P := Pos(C2, Result);
+  if P = 0 then
+    P := Pos(C3, Result);
+  if P = 0 then
+    raise Exception.CreateFmt('Invalid FunctionDefinitionWithoutHeader: %s', [Result]);
+
+  Delete(Result, P, Maxint);
+end;
+
+function ExtractScriptFuncName(const ScriptFunc: AnsiString): AnsiString;
+begin
+  Result := ExtractScriptFuncWithoutHeaderName(RemoveScriptFuncHeader(ScriptFunc));
+end;
+
+{$IFDEF COMPIL32PROJ}
+{$IFDEF DEBUG}
+function IsCleanScriptFunc(const ScriptFunc: AnsiString): Boolean;
+begin
+  const GoodTerminator: AnsiString = ';';
+  const BadType1: AnsiString = 'string';
+  const BadType2: AnsiString = 'Longint';
+
+  Result := (Pos(GoodTerminator, ScriptFunc) <> 0) and
+            (Pos(BadType1, ScriptFunc) = 0) and (Pos(BadType2, ScriptFunc) = 0);
+end;
+
+procedure CheckIsCleanScriptFuncTable(const ScriptFuncTable: TScriptTable);
+begin
+  if Length(ScriptFuncTable) = 0 then
+    raise Exception.Create('Length(ScriptFuncTable) = 0');
+  for var AScriptFunc in ScriptFuncTable do
+    if not IsCleanScriptFunc(AScriptFunc) then
+      raise Exception.CreateFmt('not IsCleanScriptFunc: %s', [AScriptFunc]);
+end;
+{$ENDIF}
+{$ENDIF}
+
+initialization
 
   { ScriptDlg }
-  ScriptDlgTable: array [0..14] of AnsiString =
-  (
+  ScriptFuncTables[sftScriptDlg] :=
+  [
     'function PageFromID(const ID: Integer): TWizardPage;',
     'function PageIndexFromID(const ID: Integer): Integer;',
     'function CreateCustomPage(const AfterID: Integer; const ACaption, ADescription: String): TWizardPage;',
@@ -31,49 +219,49 @@ const
     'function ScaleX(X: Integer): Integer;',
     'function ScaleY(Y: Integer): Integer;',
     'function CreateCustomForm: TSetupForm;'
-  );
+  ];
 
   { NewDisk }
-  NewDiskTable: array [0..0] of AnsiString =
-  (
+  ScriptFuncTables[sftNewDisk] :=
+  [
     'function SelectDisk(const DiskNumber: Integer; const AFilename: String; var Path: String): Boolean;'
-  );
+  ];
 
   { BrowseFunc }
-  BrowseFuncTable: array [0..3] of AnsiString =
-  (
+  ScriptFuncTables[sftBrowseFunc] :=
+  [
     'function BrowseForFolder(const Prompt: String; var Directory: String; const NewFolderButton: Boolean): Boolean;',
     'function GetOpenFileName(const Prompt: String; var FileName: String; const InitialDirectory, Filter, DefaultExtension: String): Boolean;',
     'function GetOpenFileNameMulti(const Prompt: String; const FileNameList: TStrings; const InitialDirectory, Filter, DefaultExtension: String): Boolean;',
     'function GetSaveFileName(const Prompt: String; var FileName: String; const InitialDirectory, Filter, DefaultExtension: String): Boolean;'
-  );
+  ];
 
   { CmnFunc }
-  CmnFuncTable: array [0..0] of AnsiString =
-  (
+  ScriptFuncTables[sftCmnFunc] :=
+  [
     'function MinimizePathName(const Filename: String; const Font: TFont; MaxLen: Integer): String;'
-  );
+  ];
 
    { CmnFunc2 }
-  CmnFunc2Table: array [0..59] of AnsiString =
-  (
+  ScriptFuncTables[sftCmnFunc2] :=
+  [
     'function FileExists(const Name: String): Boolean;',
     'function DirExists(const Name: String): Boolean;',
     'function FileOrDirExists(const Name: String): Boolean;',
     'function GetIniString(const Section, Key, Default, Filename: String): String;',
-    'function GetIniInt(const Section, Key: String; const Default, Min, Max: Longint; const Filename: String): Longint;',
+    'function GetIniInt(const Section, Key: String; const Default, Min, Max: LongInt; const Filename: String): LongInt;',
     'function GetIniBool(const Section, Key: String; const Default: Boolean; const Filename: String): Boolean;',
     'function IniKeyExists(const Section, Key, Filename: String): Boolean;',
     'function IsIniSectionEmpty(const Section, Filename: String): Boolean;',
     'function SetIniString(const Section, Key, Value, Filename: String): Boolean;',
-    'function SetIniInt(const Section, Key: String; const Value: Longint; const Filename: String): Boolean;',
+    'function SetIniInt(const Section, Key: String; const Value: LongInt; const Filename: String): Boolean;',
     'function SetIniBool(const Section, Key: String; const Value: Boolean; const Filename: String): Boolean;',
     'procedure DeleteIniEntry(const Section, Key, Filename: String);',
     'procedure DeleteIniSection(const Section, Filename: String);',
     'function GetEnv(const EnvVar: String): String;',
     'function GetCmdTail: String;',
     'function ParamCount: Integer;',
-    'function ParamStr(Index: Integer): string;',
+    'function ParamStr(Index: Integer): String;',
     'function AddBackslash(const S: String): String;',
     'function RemoveBackslash(const S: String): String;',
     'function RemoveBackslashUnlessRoot(const S: String): String;',
@@ -119,29 +307,29 @@ const
     'function SetNTFSCompression(const FileOrDir: String; Compress: Boolean): Boolean;',
     'function IsWildcard(const Pattern: String): Boolean;',
     'function WildcardMatch(const Text, Pattern: String): Boolean;'
-  );
+  ];
 
   { Install }
-  InstallTable: array [0..5] of AnsiString =
-  (
+  ScriptFuncTables[sftInstall] :=
+  [
     'procedure ExtractTemporaryFile(const FileName: String);',
     'function ExtractTemporaryFiles(const Pattern: String): Integer;',
     'function DownloadTemporaryFile(const Url, FileName, RequiredSHA256OfFile: String; const OnDownloadProgress: TOnDownloadProgress): Int64;',
     'function DownloadTemporaryFileSize(const Url: String): Int64;',
     'function DownloadTemporaryFileDate(const Url: String): String;',
     'procedure SetDownloadCredentials(const User, Pass: String);'
-  );
+  ];
 
   { InstFunc }
-  InstFuncTable: array [0..32] of AnsiString =
-  (
+  ScriptFuncTables[sftInstFunc] :=
+  [
     'function CheckForMutexes(Mutexes: String): Boolean;',
     'function DecrementSharedCount(const Is64Bit: Boolean; const Filename: String): Boolean;',
     'procedure DelayDeleteFile(const Filename: String; const Tries: Integer);',
     'function DelTree(const Path: String; const IsDir, DeleteFiles, DeleteSubdirsAlso: Boolean): Boolean;',
     'function GenerateUniqueName(Path: String; const Extension: String): String;',
     'function GetComputerNameString: String;',
-    //function GetFileDateTime(const Filename: string; var DateTime: TFileTime): Boolean;
+    //function GetFileDateTime(const Filename: String; var DateTime: TFileTime): Boolean;
     'function GetMD5OfFile(const Filename: String): String;',
     'function GetMD5OfString(const S: AnsiString): String;',
     'function GetMD5OfUnicodeString(const S: String): String;',
@@ -172,21 +360,21 @@ const
     //procedure RestartComputer;
     'procedure RestartReplace(const TempFile, DestFile: String);',
     //procedure Win32ErrorMsg(const FunctionName: String);
-    'function ForceDirectories(Dir: string): Boolean;'
-  );
-  
+    'function ForceDirectories(Dir: String): Boolean;'
+  ];
+
   { InstFnc2 }
-  InstFnc2Table: array [0..3] of AnsiString =
-  (
+  ScriptFuncTables[sftInstFnc2] :=
+  [
     'function CreateShellLink(const Filename, Description, ShortcutTo, Parameters, WorkingDir, IconFilename: String; const IconIndex, ShowCmd: Integer): String;',
     'procedure RegisterTypeLibrary(const Is64Bit: Boolean; const Filename: String);',
     'function UnregisterTypeLibrary(const Is64Bit: Boolean; const Filename: String): Boolean;',
     'function UnpinShellLink(const Filename: String): Boolean;'
-  );
+  ];
 
   { Main }
-  MainTable: array [0..32] of AnsiString =
-  (
+  ScriptFuncTables[sftMain] :=
+  [
     'function GetWizardForm: TWizardForm;',
     'function GetMainForm: TMainForm;',
     'function ActiveLanguage: String;',
@@ -200,7 +388,6 @@ const
     'function GetShellFolderByCSIDL(const Folder: Integer; const Create: Boolean): String;',
     'function InstallOnThisVersion(const MinVersion, OnlyBelowVersion: String): Boolean;',
     'function GetWindowsVersion: Cardinal;',
-    'procedure GetWindowsVersionEx(var Version: TWindowsVersion);',
     'function GetWindowsVersionString: String;',
     'function MsgBox(const Text: String; const Typ: TMsgBoxType; const Buttons: Integer): Integer;',
     'function SuppressibleMsgBox(const Text: String; const Typ: TMsgBoxType; const Buttons, Default: Integer): Integer;',
@@ -209,32 +396,28 @@ const
     'function IsWin64: Boolean;',
     'function Is64BitInstallMode: Boolean;',
     'function ProcessorArchitecture: TSetupProcessorArchitecture;',
-    'function IsArm32Compatible: Boolean',
-    'function IsArm64: Boolean',
-    'function IsX64: Boolean',
-    'function IsX64OS: Boolean',
-    'function IsX64Compatible: Boolean',
-    'function IsX86: Boolean',
-    'function IsX86OS: Boolean',
-    'function IsX86Compatible: Boolean',
+    'function IsArm32Compatible: Boolean;',
+    'function IsArm64: Boolean;',
+    'function IsX64: Boolean;',
+    'function IsX64OS: Boolean;',
+    'function IsX64Compatible: Boolean;',
+    'function IsX86: Boolean;',
+    'function IsX86OS: Boolean;',
+    'function IsX86Compatible: Boolean;',
     'function CustomMessage(const MsgName: String): String;',
     'function RmSessionStarted: Boolean;',
     'function RegisterExtraCloseApplicationsResource(const DisableFsRedir: Boolean; const AFilename: String): Boolean;'
-  );
+  ];
 
   { Msgs }
-  MsgsTable: array[0..0] of AnsiString =
-  (
+  ScriptFuncTables[sftMsgs] :=
+  [
     'function SetupMessage(const ID: TSetupMessageID): String;'
-  );
-  MsgsDelphiTable: array[0..0] of AnsiString =
-  (
-    'function FmtMessage(const S: String; const Args: array of String): String;'
-  );
+  ];
 
   { System }
-  SystemTable: array [0..6] of AnsiString =
-  (
+  ScriptFuncTables[sftSystem] :=
+  [
     'function Random(const Range: Integer): Integer;',
     'function FileSize(const Name: String; var Size: Integer): Boolean;',
     'function FileSize64(const Name: String; var Size: Int64): Boolean;',
@@ -242,49 +425,41 @@ const
     'function Get8087CW: Word;',
     'function UTF8Encode(const S: String): AnsiString;',
     'function UTF8Decode(const S: AnsiString): String;'
-  );
+  ];
 
   { SysUtils }
-  SysUtilsTable: array [0..25] of AnsiString =
-  (
+  ScriptFuncTables[sftSysUtils] :=
+  [
     'procedure Beep;',
-    'function Trim(const S: string): string;',
-    'function TrimLeft(const S: string): string;',
-    'function TrimRight(const S: string): string;',
-    'function GetCurrentDir: string;',
-    'function SetCurrentDir(const Dir: string): Boolean;',
-    'function ExpandFileName(const FileName: string): string;',
-    'function ExpandUNCFileName(const FileName: string): string;',
-    'function ExtractRelativePath(const BaseName, DestName: string): string;',
-    'function ExtractFileDir(const FileName: string): string;',
-    'function ExtractFileDrive(const FileName: string): string;',
-    'function ExtractFileExt(const FileName: string): string;',
-    'function ExtractFileName(const FileName: string): string;',
-    'function ExtractFilePath(const FileName: string): string;',
-    'function ChangeFileExt(const FileName, Extension: string): string;',
-    'function FileSearch(const Name, DirList: string): string;',
-    'function RenameFile(const OldName, NewName: string): Boolean;',
-    'function DeleteFile(const FileName: string): Boolean;',
-    'function CreateDir(const Dir: string): Boolean;',
-    'function RemoveDir(const Dir: string): Boolean;',
-    'function CompareStr(const S1, S2: string): Integer;',
-    'function CompareText(const S1, S2: string): Integer;',
-    'function SameStr(const S1, S2: string): Boolean;',
-    'function SameText(const S1, S2: string): Boolean;',
+    'function TrimLeft(const S: String): String;',
+    'function TrimRight(const S: String): String;',
+    'function GetCurrentDir: String;',
+    'function SetCurrentDir(const Dir: String): Boolean;',
+    'function ExpandFileName(const FileName: String): String;',
+    'function ExpandUNCFileName(const FileName: String): String;',
+    'function ExtractRelativePath(const BaseName, DestName: String): String;',
+    'function ExtractFileDir(const FileName: String): String;',
+    'function ExtractFileDrive(const FileName: String): String;',
+    'function ExtractFileExt(const FileName: String): String;',
+    'function ExtractFileName(const FileName: String): String;',
+    'function ExtractFilePath(const FileName: String): String;',
+    'function ChangeFileExt(const FileName, Extension: String): String;',
+    'function FileSearch(const Name, DirList: String): String;',
+    'function RenameFile(const OldName, NewName: String): Boolean;',
+    'function DeleteFile(const FileName: String): Boolean;',
+    'function CreateDir(const Dir: String): Boolean;',
+    'function RemoveDir(const Dir: String): Boolean;',
+    'function CompareStr(const S1, S2: String): Integer;',
+    'function CompareText(const S1, S2: String): Integer;',
+    'function SameStr(const S1, S2: String): Boolean;',
+    'function SameText(const S1, S2: String): Boolean;',
     'function GetDateTimeString(const DateTimeFormat: String; const DateSeparator, TimeSeparator: Char): String;',
     'function SysErrorMessage(ErrorCode: Integer): String;'
-  );
-  SysUtilsDelphiTable: array [0..3] of AnsiString =
-  (
-    'function FindFirst(const FileName: String; var FindRec: TFindRec): Boolean;',
-    'function FindNext(var FindRec: TFindRec): Boolean;',
-    'procedure FindClose(var FindRec: TFindRec);',
-    'function Format(const Format: string; const Args: array of const): string;'
-  );
+  ];
 
   { VerInfo }
-  VerInfoTable: array [0..11] of AnsiString =
-  (
+  ScriptFuncTables[sftVerInfo] :=
+  [
     'function GetVersionNumbers(const Filename: String; var VersionMS, VersionLS: Cardinal): Boolean;',
     'function GetVersionComponents(const Filename: String; var Major, Minor, Revision, Build: Word): Boolean;',
     'function GetVersionNumbersString(const Filename: String; var Version: String): Boolean;',
@@ -297,44 +472,44 @@ const
     'procedure UnpackVersionComponents(const Version: Int64; var Major, Minor, Revision, Build: Word);',
     'function VersionToStr(const Version: Int64): String;',
     'function StrToVersion(const VersionString: String; var Version: Int64): Boolean;'
-  );
+  ];
 
   { Windows }
-  WindowsTable: array [0..15] of AnsiString =
-  (
+  ScriptFuncTables[sftWindows] :=
+  [
     'procedure Sleep(const Milliseconds: LongInt);',
     'function FindWindowByClassName(const ClassName: String): HWND;',
     'function FindWindowByWindowName(const WindowName: String): HWND;',
-    'function SendMessage(const Wnd: HWND; const Msg, WParam, LParam: Longint): Longint;',
-    'function PostMessage(const Wnd: HWND; const Msg, WParam, LParam: Longint): Boolean;',
-    'function SendNotifyMessage(const Wnd: HWND; const Msg, WParam, LParam: Longint): Boolean;',
-    'function RegisterWindowMessage(const Name: String): Longint;',
-    'function SendBroadcastMessage(const Msg, WParam, LParam: Longint): Longint;',
-    'function PostBroadcastMessage(const Msg, WParam, LParam: Longint): Boolean;',
-    'function SendBroadcastNotifyMessage(const Msg, WParam, LParam: Longint): Boolean;',
-    'function LoadDLL(const DLLName: String; var ErrorCode: Integer): Longint;',
-    'function CallDLLProc(const DLLHandle: Longint; const ProcName: String; const Param1, Param2: Longint; var Result: Longint): Boolean;',
-    'function FreeDLL(const DLLHandle: Longint): Boolean;',
+    'function SendMessage(const Wnd: HWND; const Msg, WParam, LParam: LongInt): LongInt;',
+    'function PostMessage(const Wnd: HWND; const Msg, WParam, LParam: LongInt): Boolean;',
+    'function SendNotifyMessage(const Wnd: HWND; const Msg, WParam, LParam: LongInt): Boolean;',
+    'function RegisterWindowMessage(const Name: String): LongInt;',
+    'function SendBroadcastMessage(const Msg, WParam, LParam: LongInt): LongInt;',
+    'function PostBroadcastMessage(const Msg, WParam, LParam: LongInt): Boolean;',
+    'function SendBroadcastNotifyMessage(const Msg, WParam, LParam: LongInt): Boolean;',
+    'function LoadDLL(const DLLName: String; var ErrorCode: Integer): LongInt;',
+    'function CallDLLProc(const DLLHandle: LongInt; const ProcName: String; const Param1, Param2: LongInt; var Result: LongInt): Boolean;',
+    'function FreeDLL(const DLLHandle: LongInt): Boolean;',
     'procedure CreateMutex(const Name: String);',
     'procedure OemToCharBuff(var S: AnsiString);',
     'procedure CharToOemBuff(var S: AnsiString);'
-  );
+  ];
 
   { Ole2 }
-  Ole2Table: array [0..0] of AnsiString =
-  (
+  ScriptFuncTables[sftOle2] :=
+  [
     'procedure CoFreeUnusedLibraries;'
-  );
+  ];
 
   { Logging }
-  LoggingTable: array [0..0] of AnsiString =
-  (
+  ScriptFuncTables[sftLogging] :=
+  [
     'procedure Log(const S: String);'
-  );
+  ];
 
   { Other }
-  OtherTable: array [0..36] of AnsiString =
-  (
+  ScriptFuncTables[sftOther] :=
+  [
     'procedure BringToFrontAndRestore;',
     'function WizardDirValue: String;',
     'function WizardGroupValue: String;',
@@ -349,8 +524,8 @@ const
     'function UninstallSilent: Boolean;',
     'function CurrentFilename: String;',
     'function CurrentSourceFilename: String;',
-    'function CastStringToInteger(var S: String): Longint;',
-    'function CastIntegerToString(const L: Longint): String;',
+    'function CastStringToInteger(var S: String): LongInt;',
+    'function CastIntegerToString(const L: LongInt): String;',
     'procedure Abort;',
     'function GetExceptionMessage: String;',
     'procedure RaiseException(const Msg: String);',
@@ -372,8 +547,15 @@ const
     'function IsDotNetInstalled(const MinVersion: TDotNetVersion; const MinServicePack: Cardinal): Boolean;',
     'function IsMsiProductInstalled(const UpgradeCode: String; const PackedMinVersion: Int64): Boolean;',
     'function InitializeBitmapImageFromIcon(const BitmapImage: TBitmapImage; const IconFilename: String; const BkColor: TColor; const AscendingTrySizes: TArrayOfInteger): Boolean;'
-  );
+  ];
 
-implementation
+  {$IFDEF COMPIL32PROJ}
+  {$IFDEF DEBUG}
+  for var ScriptFuncTable in ScriptFuncTables do
+    CheckIsCleanScriptFuncTable(ScriptFuncTable);
+  CheckIsCleanScriptFuncTable(DelphiScriptFuncTable);
+  CheckIsCleanScriptFuncTable(ROPSScriptFuncTable);
+  {$ENDIF}
+  {$ENDIF}
 
 end.

+ 7 - 25
Projects/Src/ScriptFunc_C.pas

@@ -2,11 +2,11 @@ unit ScriptFunc_C;
 
 {
   Inno Setup
-  Copyright (C) 1997-2020 Jordan Russell
+  Copyright (C) 1997-2024 Jordan Russell
   Portions by Martijn Laan
   For conditions of distribution and use, see LICENSE.TXT.
 
-  Script support functions (compile time)
+  Script support functions (compile time - used by ISCmplr)
 }
 
 interface
@@ -38,11 +38,9 @@ procedure ScriptFuncLibraryRegister_C(ScriptCompiler: TPSPascalCompiler;
   end;
 
   procedure RegisterFunctionTable(const FunctionTable: array of tbtstring);
-  var
-    I: Integer;
   begin
-    for I := Low(FunctionTable) to High(FunctionTable) do
-      ScriptCompiler.AddFunction(FunctionTable[I]);
+    for var Func in FunctionTable do
+      ScriptCompiler.AddFunction(Func);
   end;
 
   procedure RegisterDelphiFunctionTable(const FunctionTable: array of tbtstring);
@@ -151,29 +149,13 @@ begin
   RegisterType('TOnDownloadProgress', 'function(const Url, FileName: string; const Progress, ProgressMax: Int64): Boolean;');
   RegisterType('TOnLog', 'procedure(const S: String; const Error, FirstLine: Boolean);');
 
-  RegisterFunctionTable(ScriptDlgTable);
-  RegisterFunctionTable(NewDiskTable);
-  RegisterFunctionTable(BrowseFuncTable);
-  RegisterFunctionTable(CmnFuncTable);
-  RegisterFunctionTable(CmnFunc2Table);
+  for var ScriptFuncTable in ScriptFuncTables do
+    RegisterFunctionTable(ScriptFuncTable);
+  RegisterDelphiFunctionTable(DelphiScriptFuncTable);
   ObsoleteFunctionWarnings.Add('IsAdminLoggedOn', Format(SCompilerCodeFunctionRenamedWithAlternative, ['IsAdminLoggedOn', 'IsAdmin', 'IsAdminInstallMode']));
-  RegisterFunctionTable(InstallTable);
-  RegisterFunctionTable(InstFuncTable);
-  RegisterFunctionTable(InstFnc2Table);
-  RegisterFunctionTable(MainTable);
   ObsoleteFunctionWarnings.Add('IsComponentSelected', Format(SCompilerCodeFunctionRenamed, ['IsComponentSelected', 'WizardIsComponentSelected']));
   ObsoleteFunctionWarnings.Add('IsTaskSelected', Format(SCompilerCodeFunctionRenamed, ['IsTaskSelected', 'WizardIsTaskSelected']));
   ObsoleteFunctionWarnings.Add('IsX64', Format(SCompilerCodeFunctionDeprecatedWithAlternativeAndDocs, ['IsX64', 'IsX64OS', 'IsX64Compatible', 'Architecture Identifiers']));
-  RegisterFunctionTable(MsgsTable);
-  RegisterDelphiFunctionTable(MsgsDelphiTable);
-  RegisterFunctionTable(SystemTable);
-  RegisterFunctionTable(SysUtilsTable);
-  RegisterDelphiFunctionTable(SysUtilsDelphiTable);
-  RegisterFunctionTable(VerInfoTable);
-  RegisterFunctionTable(WindowsTable);
-  RegisterFunctionTable(Ole2Table);
-  RegisterFunctionTable(LoggingTable);
-  RegisterFunctionTable(OtherTable);
 
   RegisterConst('MaxInt', MaxInt);
 

+ 58 - 52
Projects/Src/ScriptFunc_R.pas

@@ -6,7 +6,7 @@ unit ScriptFunc_R;
   Portions by Martijn Laan
   For conditions of distribution and use, see LICENSE.TXT.
 
-  Script support functions (run time)
+  Script support functions (run time - used by Setup)
 }
 
 interface
@@ -1383,8 +1383,6 @@ begin
 
   if Proc.Name = 'BEEP' then begin
     Beep;
-  end else if Proc.Name = 'TRIM' then begin
-    Stack.SetString(PStart, Trim(Stack.GetString(PStart-1)));
   end else if Proc.Name = 'TRIMLEFT' then begin
     Stack.SetString(PStart, TrimLeft(Stack.GetString(PStart-1)));
   end else if Proc.Name = 'TRIMRIGHT' then begin
@@ -2051,63 +2049,71 @@ end;
 {---}
 
 procedure ScriptFuncLibraryRegister_R(ScriptInterpreter: TPSExec);
-
-  function ExtractName(const S: String): String;
-  var
-    P: Integer;
-  begin
-    Result := S;
-
-    if CompareText(Copy(Result, 1, Length('function')), 'function') = 0 then
-      Delete(Result, 1, Length('function'))
-    else if CompareText(Copy(Result, 1, Length('procedure')), 'procedure') = 0 then
-      Delete(Result, 1, Length('procedure'));
-
-    P := Pos('(', Result);
-    if P = 0 then
-      P := Pos(':', Result);
-    if P = 0 then
-      P := Pos(';', Result);
-    Delete(Result, P, Maxint);
-
-    Result := Trim(Result);
-  end;
+{$IFDEF DEBUG}
+var
+  Count: Integer;
+{$ENDIF}
 
   procedure RegisterFunctionTable(const FunctionTable: array of AnsiString;
     const ProcPtr: TPSProcPtr);
-  var
-    I: Integer;
   begin
-    for I := Low(FunctionTable) to High(FunctionTable) do
-      ScriptInterpreter.RegisterFunctionName(AnsiString(ExtractName(String(FunctionTable[I]))),
+    for var Func in FunctionTable do
+      ScriptInterpreter.RegisterFunctionName(ExtractScriptFuncName(Func),
         ProcPtr, nil, nil);
+    {$IFDEF DEBUG}
+    Inc(Count);
+    {$ENDIF}
+  end;
+
+  procedure RegisterDelphiFunction(ProcPtr: Pointer; const Name: AnsiString);
+  begin
+    ScriptInterpreter.RegisterDelphiFunction(ProcPtr, Name, cdRegister);
+    {$IFDEF DEBUG}
+    Inc(Count);
+    {$ENDIF}
   end;
 
 begin
-  RegisterFunctionTable(ScriptDlgTable, @ScriptDlgProc);
-  RegisterFunctionTable(NewDiskTable, @NewDiskProc);
-  RegisterFunctionTable(BrowseFuncTable, @BrowseFuncProc);
-  RegisterFunctionTable(CmnFuncTable, @CmnFuncProc);
-  RegisterFunctionTable(CmnFunc2Table, @CmnFunc2Proc);
-  RegisterFunctionTable(InstallTable, @InstallProc);
-  RegisterFunctionTable(InstFuncTable, @InstFuncProc);
-  RegisterFunctionTable(InstFnc2Table, @InstFnc2Proc);
-  RegisterFunctionTable(MainTable, @MainProc);
-  RegisterFunctionTable(MsgsTable, @MsgsProc);
-  RegisterFunctionTable(SystemTable, @SystemProc);
-  RegisterFunctionTable(SysUtilsTable, @SysUtilsProc);
-  RegisterFunctionTable(VerInfoTable, @VerInfoProc);
-  RegisterFunctionTable(WindowsTable, @WindowsProc);
-  RegisterFunctionTable(Ole2Table, @Ole2Proc);
-  RegisterFunctionTable(LoggingTable, @LoggingProc);
-  RegisterFunctionTable(OtherTable, @OtherProc);
-
-  ScriptInterpreter.RegisterDelphiFunction(@_FindFirst, 'FindFirst', cdRegister);
-  ScriptInterpreter.RegisterDelphiFunction(@_FindNext, 'FindNext', cdRegister);
-  ScriptInterpreter.RegisterDelphiFunction(@_FindClose, 'FindClose', cdRegister);
-  ScriptInterpreter.RegisterDelphiFunction(@_FmtMessage, 'FmtMessage', cdRegister);
-  ScriptInterpreter.RegisterDelphiFunction(@Format, 'Format', cdRegister);
-  ScriptInterpreter.RegisterDelphiFunction(@_GetWindowsVersionEx, 'GetWindowsVersionEx', cdRegister); 
+  { The following should register all tables in ScriptFuncTables }
+  {$IFDEF DEBUG}
+  Count := 0;
+  {$ENDIF}
+  RegisterFunctionTable(ScriptFuncTables[sftScriptDlg], @ScriptDlgProc);
+  RegisterFunctionTable(ScriptFuncTables[sftNewDisk], @NewDiskProc);
+  RegisterFunctionTable(ScriptFuncTables[sftBrowseFunc], @BrowseFuncProc);
+  RegisterFunctionTable(ScriptFuncTables[sftCmnFunc], @CmnFuncProc);
+  RegisterFunctionTable(ScriptFuncTables[sftCmnFunc2], @CmnFunc2Proc);
+  RegisterFunctionTable(ScriptFuncTables[sftInstall], @InstallProc);
+  RegisterFunctionTable(ScriptFuncTables[sftInstFunc], @InstFuncProc);
+  RegisterFunctionTable(ScriptFuncTables[sftInstFnc2], @InstFnc2Proc);
+  RegisterFunctionTable(ScriptFuncTables[sftMain], @MainProc);
+  RegisterFunctionTable(ScriptFuncTables[sftMsgs], @MsgsProc);
+  RegisterFunctionTable(ScriptFuncTables[sftSystem], @SystemProc);
+  RegisterFunctionTable(ScriptFuncTables[sftSysUtils], @SysUtilsProc);
+  RegisterFunctionTable(ScriptFuncTables[sftVerInfo], @VerInfoProc);
+  RegisterFunctionTable(ScriptFuncTables[sftWindows], @WindowsProc);
+  RegisterFunctionTable(ScriptFuncTables[sftOle2], @Ole2Proc);
+  RegisterFunctionTable(ScriptFuncTables[sftLogging], @LoggingProc);
+  RegisterFunctionTable(ScriptFuncTables[sftOther], @OtherProc);
+  {$IFDEF DEBUG}
+  if Count <> Length(ScriptFuncTables) then
+    raise Exception.Create('Count <> Length(ScriptFuncTables)');
+  {$ENDIF}
+
+  { The following should register all functions in ScriptDelphiFuncTable }
+  {$IFDEF DEBUG}
+  Count := 0;
+  {$ENDIF}
+  RegisterDelphiFunction(@_FindFirst, 'FindFirst');
+  RegisterDelphiFunction(@_FindNext, 'FindNext');
+  RegisterDelphiFunction(@_FindClose, 'FindClose');
+  RegisterDelphiFunction(@_FmtMessage, 'FmtMessage');
+  RegisterDelphiFunction(@Format, 'Format');
+  RegisterDelphiFunction(@_GetWindowsVersionEx, 'GetWindowsVersionEx');
+  {$IFDEF DEBUG}
+  if Count <> Length(DelphiScriptFuncTable) then
+    raise Exception.Create('Count <> Length(DelphiScriptFuncTable)');
+  {$ENDIF}
 end;
 
 procedure FreeASMInliners;

+ 1 - 1
compile.bat

@@ -44,7 +44,7 @@ cd ..
 
 echo - Compil32.dpr
 mkdir Dcu\Compil32.dpr 2>nul
-"%DELPHIXEROOT%\bin\dcc32.exe" --no-config -NSsystem;system.win;winapi;vcl;vcl.imaging -Q -B -H -W %DELPHIXEDISABLEDWARNINGS% %1 -U"%DELPHIXEROOT%\lib\win32\release;..\Components\UniPs\Source;ISPP" -E..\Files -NUDcu\Compil32.dpr -DPS_MINIVCL;PS_NOGRAPHCONST;PS_PANSICHAR;PS_NOINTERFACEGUIDBRACKETS Compil32.dpr
+"%DELPHIXEROOT%\bin\dcc32.exe" --no-config -NSsystem;system.win;winapi;vcl;vcl.imaging -Q -B -H -W %DELPHIXEDISABLEDWARNINGS% %1 -U"%DELPHIXEROOT%\lib\win32\release;..\Components\UniPs\Source;ISPP" -E..\Files -NUDcu\Compil32.dpr -DCOMPIL32PROJ;PS_MINIVCL;PS_NOGRAPHCONST;PS_PANSICHAR;PS_NOINTERFACEGUIDBRACKETS Compil32.dpr
 if errorlevel 1 goto failed
 
 echo - ISCC.dpr

+ 5 - 2
whatsnew.htm

@@ -50,6 +50,8 @@ For conditions of distribution and use, see <a href="files/is/license.txt">LICEN
 <p>Other editor changes:</p>
 <ul>
   <li>Added support for Visual Studio Code-style editor shortcuts, like Ctrl+D to Add Next Occurrence, Ctrl+Shift+K to delete a line and Alt+Click to add an additional cursor.<br />To activate this use the <i>Options</i> menu item in the <i>Tools</i> menu to set the new <i>Keys</i> option in the <i>Editor</i> group to <i>Visual Studio Code</i>.<br />The updated <a href="https://jrsoftware.org/ishelp/index.php?topic=compformshortcuts">Compiler IDE Keyboard And Mouse Commands</a> help topic lists all differences with the classic keyboard and mouse shortcuts.</li>
+  <li>Implemented parameter hints for all Pascal Scripting support functions for quick reference to the function's parameter names, types, and order. Parameter hints can be invoked manually by pressing Ctrl+Shift+Space or automatically by using the new <i>Invoke parameter hints automatically</i> option which is enabled by default.</li>
+  <li>Added autocompletion support for all Pascal Scripting support functions. Existing option <i>Invoke autocompletion automatically</i> controls whether the autocompletion suggestions appear automatically or only when invoked manually by pressing Ctrl+Space or Ctrl+I.</li>
   <li>Added new <i>Enable section folding</i> option which allows you to temporarily hide sections while editing by clicking the new minus or plus icons in the editor's gutter or by using the new keyboard shortcuts (Ctrl+Shift+[ to fold and Ctrl+Shift+] to unfold) or menu items. Enabled by default.</li>
   <li>The editor's gutter now shows change history to keep track of saved and unsaved modifications. Always enabled.</li>
   <li>The editor's font now defaults to Consolas if available, consistent with most other modern editors.</li>
@@ -58,7 +60,7 @@ For conditions of distribution and use, see <a href="files/is/license.txt">LICEN
   <li>Added shortcuts to move selected lines up or down (Alt+Up and Alt+Down).</li>
   <li>Added shortcut and menu item to toggle line comment (Ctrl+/).</li>
   <li>Added a right-click popup menu to the editor's gutter column for breakpoints.</li>
-  <li>Added dark mode support to autocompletion lists.</li>
+  <li>Added dark mode support to autocompletion lists and also added a minimum width.</li>
 </ul>
 <p>Other changes:</p>
 <ul>
@@ -70,10 +72,11 @@ For conditions of distribution and use, see <a href="files/is/license.txt">LICEN
   <li>Output logging now raises an exception if there was an error setting up output redirection (which should be very rare). The <i>PowerShell.iss</i> example script has been updated to catch the exception.</li>  
   <li>Pascal Scripting change: Added new <tt>ExecAndCaptureOutput</tt> support function to execute a program or batch file and capture its <i>stdout</i> and <i>stderr</i> output.</li>
   <li>Fixed an issue when the <i>Auto indent mode</i> and <i>Allow cursor to move beyond end of lines</i> options are both enabled.</li>  
+  <li>Pascal Scripting change: documented support functions <tt>VarArrayGet</tt> and <tt>VarArraySet</tt> which were already available but not documented.</li>
   <li>Various tweaks and documentation improvements.</li>
 </ul>
 
-<p>Contributions via <a href="https://github.com/jrsoftware/issrc" target="_blank">GitHub</a>: Thanks to Sergii Leonov and John Stevenson for their contributions.</p>
+<p>Contributions via <a href="https://github.com/jrsoftware/issrc" target="_blank">GitHub</a>: Thanks to Sergii Leonov, John Stevenson, and jogo- for their contributions!</p>
 
 <p><a name="6.3.2"></a><span class="ver">6.3.2 </span><span class="date">(2024-06-28)</span></p>
 <ul>

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików