Pārlūkot izejas kodu

Merge branch 'showpreprocessedscript' into main

Fixed include tab insert order during merge + some cleanup.
Martijn Laan 5 gadi atpakaļ
vecāks
revīzija
24ae241f84

+ 12 - 12
Examples/ISPPExample1.iss

@@ -1,22 +1,22 @@
-; -- ISPPExample1.iss --
-;
-; This script shows various basic things you can achieve using Inno Setup Preprocessor (ISPP).
-; To enable commented #define's, either remove the ';' or use ISCC with the /D switch.
-
+// -- ISPPExample1.iss --
+//
+// This script shows various basic things you can achieve using Inno Setup Preprocessor (ISPP).
+// To enable commented #define's, either remove the '//' or use ISCC with the /D switch.
+//
 #pragma verboselevel 9
 #pragma verboselevel 9
-
-;#define Debug
-
-;#define AppEnterprise
-
+//
+//#define Debug
+//
+//#define AppEnterprise
+//
 #ifdef AppEnterprise
 #ifdef AppEnterprise
   #define AppName "My Program Enterprise Edition"
   #define AppName "My Program Enterprise Edition"
 #else
 #else
   #define AppName "My Program"
   #define AppName "My Program"
 #endif
 #endif
-
+//
 #define AppVersion GetVersionNumbersString(AddBackslash(SourcePath) + "MyProg.exe")
 #define AppVersion GetVersionNumbersString(AddBackslash(SourcePath) + "MyProg.exe")
-
+//
 [Setup]
 [Setup]
 AppName={#AppName}
 AppName={#AppName}
 AppVersion={#AppVersion}
 AppVersion={#AppVersion}

+ 253 - 156
Projects/CompForm.pas

@@ -52,7 +52,7 @@ type
     CompilerFileIndex: Integer;
     CompilerFileIndex: Integer;
     LastWriteTime: TFileTime;
     LastWriteTime: TFileTime;
     HasLastWriteTime: Boolean;
     HasLastWriteTime: Boolean;
-    Memo: TCompScintEdit;
+    Memo: TCompScintFileEdit;
   end;
   end;
 
 
   TIncludedFiles = TObjectList<TIncludedFile>;
   TIncludedFiles = TObjectList<TIncludedFile>;
@@ -183,7 +183,7 @@ type
     TInsertMsgBox: TMenuItem;
     TInsertMsgBox: TMenuItem;
     ToolBarPanel: TPanel;
     ToolBarPanel: TPanel;
     HMailingList: TMenuItem;
     HMailingList: TMenuItem;
-    MemosTabSet: TNewTabSet;
+    MemosTabSet: TNewTabSet; { First tab is the main memo, last tab is the preprocessor output memo }
     FSaveAll: TMenuItem;
     FSaveAll: TMenuItem;
     procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
     procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
     procedure FExitClick(Sender: TObject);
     procedure FExitClick(Sender: TObject);
@@ -274,9 +274,13 @@ type
     procedure FSaveAllClick(Sender: TObject);
     procedure FSaveAllClick(Sender: TObject);
   private
   private
     { Private declarations }
     { Private declarations }
-    FMemos: TList<TCompScintEdit>; { FMemos[0] is always the main memo }
-    FMainMemo, FActiveMemo, FErrorMemo, FStepMemo: TCompScintEdit;
-    FMemosStyler: TInnoSetupStyler;
+    FMemos: TList<TCompScintEdit>;                      { FMemos[0] is the main memo and FMemos[1] the preprocessor output memo - also see MemosTabSet comment above }
+    FMainMemo: TCompScintFileEdit;                      { Doesn't change }
+    FPreprocessorOutputMemo: TCompScintEdit;            { Doesn't change }
+    FFileMemos: TList<TCompScintFileEdit>;              { All memos except FPreprocessorOutputMemo }
+    FActiveMemo: TCompScintEdit;                        { Changes depending on user input }
+    FErrorMemo, FStepMemo: TCompScintFileEdit;          { These change depending on user input }
+    FMemosStyler: TInnoSetupStyler;                     { Single styler for all memos }
     FCompilerVersion: PCompilerVersionInfo;
     FCompilerVersion: PCompilerVersionInfo;
     FMRUMainFilesMenuItems: array[0..MRUListMaxCount-1] of TMenuItem;
     FMRUMainFilesMenuItems: array[0..MRUListMaxCount-1] of TMenuItem;
     FMRUMainFilesList: TStringList;
     FMRUMainFilesList: TStringList;
@@ -303,6 +307,7 @@ type
       LowPriorityDuringCompile: Boolean;
       LowPriorityDuringCompile: Boolean;
       GutterLineNumbers: Boolean;
       GutterLineNumbers: Boolean;
       ThemeType: TThemeType;
       ThemeType: TThemeType;
+      ShowPreprocessorOutput: Boolean;
       OpenIncludedFiles: Boolean;
       OpenIncludedFiles: Boolean;
     end;
     end;
     FOptionsLoaded: Boolean;
     FOptionsLoaded: Boolean;
@@ -322,6 +327,7 @@ type
     FProcessHandle, FDebugClientProcessHandle: THandle;
     FProcessHandle, FDebugClientProcessHandle: THandle;
     FDebugTarget: TDebugTarget;
     FDebugTarget: TDebugTarget;
     FCompiledExe, FUninstExe, FTempDir: String;
     FCompiledExe, FUninstExe, FTempDir: String;
+    FPreprocessorOutput: String;
     FIncludedFiles: TIncludedFiles;
     FIncludedFiles: TIncludedFiles;
     FLoadingIncludedFiles: Boolean;
     FLoadingIncludedFiles: Boolean;
     FDebugging: Boolean;
     FDebugging: Boolean;
@@ -367,8 +373,10 @@ type
     procedure Go(AStepMode: TStepMode);
     procedure Go(AStepMode: TStepMode);
     procedure HideError;
     procedure HideError;
     procedure InitializeFindText(Dlg: TFindDialog);
     procedure InitializeFindText(Dlg: TFindDialog);
-    function InitializeMainMemo(const Memo: TCompScintEdit; const PopupMenu: TPopupMenu): TCompScintEdit;
-    function InitializeMemo(const Memo: TCompScintEdit; const PopupMenu: TPopupMenu): TCompScintEdit;
+    function InitializeFileMemo(const Memo: TCompScintFileEdit; const PopupMenu: TPopupMenu): TCompScintFileEdit;
+    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;
     procedure InitiateAutoComplete(const Key: AnsiChar);
     procedure InitiateAutoComplete(const Key: AnsiChar);
     procedure InvalidateStatusPanel(const Index: Integer);
     procedure InvalidateStatusPanel(const Index: Integer);
     procedure LoadKnownIncludedFilesAndUpdateMemos(const AFilename: String);
     procedure LoadKnownIncludedFilesAndUpdateMemos(const AFilename: String);
@@ -378,8 +386,8 @@ type
     procedure MemoHintShow(Sender: TObject; var Info: TScintHintInfo);
     procedure MemoHintShow(Sender: TObject; var Info: TScintHintInfo);
     procedure MemoKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
     procedure MemoKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
     procedure MemoKeyPress(Sender: TObject; var Key: Char);
     procedure MemoKeyPress(Sender: TObject; var Key: Char);
-    procedure MemoLinesDeleted(Memo: TCompScintEdit; FirstLine, Count, FirstAffectedLine: Integer);
-    procedure MemoLinesInserted(Memo: TCompScintEdit; FirstLine, Count: integer);
+    procedure MemoLinesDeleted(Memo: TCompScintFileEdit; FirstLine, Count, FirstAffectedLine: Integer);
+    procedure MemoLinesInserted(Memo: TCompScintFileEdit; FirstLine, Count: integer);
     procedure MemoMarginClick(Sender: TObject; MarginNumber: Integer;
     procedure MemoMarginClick(Sender: TObject; MarginNumber: Integer;
       Line: Integer);
       Line: Integer);
     procedure MemoModifiedChange(Sender: TObject);
     procedure MemoModifiedChange(Sender: TObject);
@@ -389,18 +397,18 @@ type
     procedure MoveCaretAndActivateMemo(const AMemo: TCompScintEdit; const LineNumber: Integer; const AlwaysResetColumn: Boolean);
     procedure MoveCaretAndActivateMemo(const AMemo: TCompScintEdit; const LineNumber: Integer; const AlwaysResetColumn: Boolean);
     procedure NewMainFile;
     procedure NewMainFile;
     procedure NewMainFileUsingWizard;
     procedure NewMainFileUsingWizard;
-    procedure OpenFile(AMemo: TCompScintEdit; AFilename: String; const MainMemoAddToRecentDocs: Boolean);
+    procedure OpenFile(AMemo: TCompScintFileEdit; AFilename: String; const MainMemoAddToRecentDocs: Boolean);
     procedure OpenMRUMainFile(const AFilename: String);
     procedure OpenMRUMainFile(const AFilename: String);
     procedure ParseDebugInfo(DebugInfo: Pointer);
     procedure ParseDebugInfo(DebugInfo: Pointer);
     procedure ReadMRUMainFilesList;
     procedure ReadMRUMainFilesList;
     procedure ReadMRUParametersList;
     procedure ReadMRUParametersList;
     procedure ResetAllMemosLineState;
     procedure ResetAllMemosLineState;
     procedure StartProcess;
     procedure StartProcess;
-    function SaveFile(const AMemo: TCompScintEdit; const SaveAs: Boolean): Boolean;
+    function SaveFile(const AMemo: TCompScintFileEdit; const SaveAs: Boolean): Boolean;
     procedure SaveKnownIncludedFiles(const AFilename: String);
     procedure SaveKnownIncludedFiles(const AFilename: String);
-    procedure SetErrorLine(const AMemo: TCompScintEdit; const ALine: Integer);
+    procedure SetErrorLine(const AMemo: TCompScintFileEdit; const ALine: Integer);
     procedure SetStatusPanelVisible(const AVisible: Boolean);
     procedure SetStatusPanelVisible(const AVisible: Boolean);
-    procedure SetStepLine(const AMemo: TCompScintEdit; ALine: Integer);
+    procedure SetStepLine(const AMemo: TCompScintFileEdit; ALine: Integer);
     procedure ShowOpenMainFileDialog(const Examples: Boolean);
     procedure ShowOpenMainFileDialog(const Examples: Boolean);
     procedure StatusMessage(const Kind: TStatusMessageKind; const S: String);
     procedure StatusMessage(const Kind: TStatusMessageKind; const S: String);
     procedure SyncEditorOptions;
     procedure SyncEditorOptions;
@@ -408,14 +416,15 @@ type
     function ToCurrentPPI(const XY: Integer): Integer;
     function ToCurrentPPI(const XY: Integer): Integer;
     procedure ToggleBreakPoint(Line: Integer);
     procedure ToggleBreakPoint(Line: Integer);
     procedure UpdateAllMemosLineMarkers;
     procedure UpdateAllMemosLineMarkers;
-    procedure UpdateBevel1;
+    procedure UpdateBevel1Visibility;
     procedure UpdateCaption;
     procedure UpdateCaption;
     procedure UpdateCaretPosPanel;
     procedure UpdateCaretPosPanel;
     procedure UpdateCompileStatusPanels(const AProgress, AProgressMax: Cardinal;
     procedure UpdateCompileStatusPanels(const AProgress, AProgressMax: Cardinal;
       const ASecondsRemaining: Integer; const ABytesCompressedPerSecond: Cardinal);
       const ASecondsRemaining: Integer; const ABytesCompressedPerSecond: Cardinal);
     procedure UpdateEditModePanel;
     procedure UpdateEditModePanel;
-    procedure UpdateIncludedFilesMemos;
-    procedure UpdateLineMarkers(const AMemo: TCompScintEdit; const Line: Integer);
+    procedure UpdatePreprocMemos;
+    procedure UpdateLineMarkers(const AMemo: TCompScintFileEdit; const Line: Integer);
+    procedure UpdateMemosTabSetVisibility;
     procedure UpdateModifiedPanel;
     procedure UpdateModifiedPanel;
     procedure UpdateNewMainFileButtons;
     procedure UpdateNewMainFileButtons;
     procedure UpdateTabSetListsItemHeightAndDebugTimeWidth;
     procedure UpdateTabSetListsItemHeightAndDebugTimeWidth;
@@ -428,7 +437,7 @@ type
     procedure WMDebuggerHello(var Message: TMessage); message WM_Debugger_Hello;
     procedure WMDebuggerHello(var Message: TMessage); message WM_Debugger_Hello;
     procedure WMDebuggerGoodbye(var Message: TMessage); message WM_Debugger_Goodbye;
     procedure WMDebuggerGoodbye(var Message: TMessage); message WM_Debugger_Goodbye;
     procedure WMDebuggerQueryVersion(var Message: TMessage); message WM_Debugger_QueryVersion;
     procedure WMDebuggerQueryVersion(var Message: TMessage); message WM_Debugger_QueryVersion;
-    procedure GetMemoAndLineNumberFromEntry(Kind, Index: Integer; var Memo: TCompScintEdit; var LineNumber: Integer);
+    procedure GetMemoAndLineNumberFromEntry(Kind, Index: Integer; var Memo: TCompScintFileEdit; var LineNumber: Integer);
     procedure DebuggerStepped(var Message: TMessage; const Intermediate: Boolean);
     procedure DebuggerStepped(var Message: TMessage; const Intermediate: Boolean);
     procedure WMDebuggerStepped(var Message: TMessage); message WM_Debugger_Stepped;
     procedure WMDebuggerStepped(var Message: TMessage); message WM_Debugger_Stepped;
     procedure WMDebuggerSteppedIntermediate(var Message: TMessage); message WM_Debugger_SteppedIntermediate;
     procedure WMDebuggerSteppedIntermediate(var Message: TMessage); message WM_Debugger_SteppedIntermediate;
@@ -472,8 +481,8 @@ uses
 
 
 const
 const
   { Memos }
   { Memos }
-  MaxMemos = 11; { Includes the main memo }
-  FirstIncludedFilesMemoIndex = 1;
+  MaxMemos = 12; { Includes the main and preprocessor output memo's }
+  FirstIncludedFilesMemoIndex = 1; { This is an index into FFileMemos }
 
 
   { Status bar panel indexes }
   { Status bar panel indexes }
   spCaretPos = 0;
   spCaretPos = 0;
@@ -509,18 +518,15 @@ end;
 
 
 { TCompileForm }
 { TCompileForm }
 
 
-function TCompileForm.InitializeMemo(const Memo: TCompScintEdit; const PopupMenu: TPopupMenu): TCompScintEdit;
+function TCompileForm.InitializeMemoBase(const Memo: TCompScintEdit; const PopupMenu: TPopupMenu): TCompScintEdit;
 begin
 begin
   Memo.Align := alClient;
   Memo.Align := alClient;
   Memo.AutoCompleteFontName := Font.Name;
   Memo.AutoCompleteFontName := Font.Name;
   Memo.AutoCompleteFontSize := Font.Size;
   Memo.AutoCompleteFontSize := Font.Size;
   Memo.CodePage := CP_UTF8;
   Memo.CodePage := CP_UTF8;
-  Memo.CompilerFileIndex := UnknownCompilerFileIndex;
-  Memo.ErrorLine := -1;
   Memo.Font.Name := 'Courier New';
   Memo.Font.Name := 'Courier New';
   Memo.Font.Size := 10;
   Memo.Font.Size := 10;
   Memo.ShowHint := True;
   Memo.ShowHint := True;
-  Memo.StepLine := -1;
   Memo.Styler := FMemosStyler;
   Memo.Styler := FMemosStyler;
   Memo.PopupMenu := PopupMenu;
   Memo.PopupMenu := PopupMenu;
   Memo.OnChange := MemoChange;
   Memo.OnChange := MemoChange;
@@ -537,9 +543,18 @@ begin
   Result := Memo;
   Result := Memo;
 end;
 end;
 
 
-function TCompileForm.InitializeMainMemo(const Memo: TCompScintEdit; const PopupMenu: TPopupMenu): TCompScintEdit;
+function TCompileForm.InitializeFileMemo(const Memo: TCompScintFileEdit; const PopupMenu: TPopupMenu): TCompScintFileEdit;
+begin
+  InitializeMemoBase(Memo, PopupMenu);
+  Memo.CompilerFileIndex := UnknownCompilerFileIndex;
+  Memo.ErrorLine := -1;
+  Memo.StepLine := -1;
+  Result := Memo;
+end;
+
+function TCompileForm.InitializeMainMemo(const Memo: TCompScintFileEdit; const PopupMenu: TPopupMenu): TCompScintFileEdit;
 begin
 begin
-  InitializeMemo(Memo, PopupMenu);
+  InitializeFileMemo(Memo, PopupMenu);
   Memo.AcceptDroppedFiles := True;
   Memo.AcceptDroppedFiles := True;
   Memo.CompilerFileIndex := -1;
   Memo.CompilerFileIndex := -1;
   Memo.OnDropFiles := MainMemoDropFiles;
   Memo.OnDropFiles := MainMemoDropFiles;
@@ -547,6 +562,13 @@ begin
   Result := Memo;
   Result := Memo;
 end;
 end;
 
 
+function TCompileForm.InitializeNonFileMemo(const Memo: TCompScintEdit; const PopupMenu: TPopupMenu): TCompScintEdit;
+begin
+  InitializeMemoBase(Memo, PopupMenu);
+  Memo.ReadOnly := True;
+  Result := Memo;
+end;
+
 constructor TCompileForm.Create(AOwner: TComponent);
 constructor TCompileForm.Create(AOwner: TComponent);
 
 
   procedure ReadConfig;
   procedure ReadConfig;
@@ -583,6 +605,7 @@ constructor TCompileForm.Create(AOwner: TComponent);
       FOptions.AutoIndent := Ini.ReadBool('Options', 'AutoIndent', True);
       FOptions.AutoIndent := Ini.ReadBool('Options', 'AutoIndent', True);
       FOptions.IndentationGuides := Ini.ReadBool('Options', 'IndentationGuides', True);
       FOptions.IndentationGuides := Ini.ReadBool('Options', 'IndentationGuides', True);
       FOptions.GutterLineNumbers := Ini.ReadBool('Options', 'GutterLineNumbers', False);
       FOptions.GutterLineNumbers := Ini.ReadBool('Options', 'GutterLineNumbers', False);
+      FOptions.ShowPreprocessorOutput := Ini.ReadBool('Options', 'ShowPreprocessorOutput', True);
       FOptions.OpenIncludedFiles := Ini.ReadBool('Options', 'OpenIncludedFiles', True);
       FOptions.OpenIncludedFiles := Ini.ReadBool('Options', 'OpenIncludedFiles', True);
       I := Ini.ReadInteger('Options', 'ThemeType', Ord(GetDefaultThemeType));
       I := Ini.ReadInteger('Options', 'ThemeType', Ord(GetDefaultThemeType));
       if (I >= 0) and (I <= Ord(High(TThemeType))) then
       if (I >= 0) and (I <= Ord(High(TThemeType))) then
@@ -633,6 +656,7 @@ var
   I: Integer;
   I: Integer;
   NewItem: TMenuItem;
   NewItem: TMenuItem;
   PopupMenu: TPopupMenu;
   PopupMenu: TPopupMenu;
+  Memo: TCompScintEdit;
 begin
 begin
   inherited;
   inherited;
 
 
@@ -681,10 +705,16 @@ begin
   FMemosStyler.IsppInstalled := IsppInstalled;
   FMemosStyler.IsppInstalled := IsppInstalled;
   FTheme := TTheme.Create;
   FTheme := TTheme.Create;
   FMemos := TList<TCompScintEdit>.Create;
   FMemos := TList<TCompScintEdit>.Create;
-  FMainMemo := InitializeMainMemo(TCompScintEdit.Create(Self), PopupMenu);
+  FMainMemo := InitializeMainMemo(TCompScintFileEdit.Create(Self), PopupMenu);
   FMemos.Add(FMainMemo);
   FMemos.Add(FMainMemo);
-  for I := 1 to MaxMemos-1 do
-    FMemos.Add(InitializeMemo(TCompScintEdit.Create(Self), PopupMenu));
+  FPreprocessorOutputMemo := InitializeNonFileMemo(TCompScintEdit.Create(Self), PopupMenu);
+  FMemos.Add(FPreprocessorOutputMemo);
+  for I := FMemos.Count to MaxMemos-1 do
+    FMemos.Add(InitializeFileMemo(TCompScintFileEdit.Create(Self), PopupMenu));
+  FFileMemos := TList<TCompScintFileEdit>.Create;
+  for Memo in FMemos do
+    if Memo is TCompScintFileEdit then
+      FFileMemos.Add(TCompScintFileEdit(Memo));
   FActiveMemo := FMainMemo;
   FActiveMemo := FMainMemo;
   FActiveMemo.Visible := True;
   FActiveMemo.Visible := True;
   FErrorMemo := FMainMemo;
   FErrorMemo := FMainMemo;
@@ -710,7 +740,7 @@ begin
   FSignTools := TStringList.Create;
   FSignTools := TStringList.Create;
 
 
   FIncludedFiles := TIncludedFiles.Create;
   FIncludedFiles := TIncludedFiles.Create;
-  UpdateIncludedFilesMemos;
+  UpdatePreprocMemos;
 
 
   FDebugTarget := dtSetup;
   FDebugTarget := dtSetup;
   UpdateTargetMenu;
   UpdateTargetMenu;
@@ -783,6 +813,7 @@ begin
   FSignTools.Free;
   FSignTools.Free;
   FMRUParametersList.Free;
   FMRUParametersList.Free;
   FMRUMainFilesList.Free;
   FMRUMainFilesList.Free;
+  FFileMemos.Free;
   FMemos.Free;
   FMemos.Free;
 
 
   inherited;
   inherited;
@@ -916,7 +947,7 @@ end;
 
 
 procedure TCompileForm.NewMainFile;
 procedure TCompileForm.NewMainFile;
 var
 var
-  Memo: TCompScintEdit;
+  Memo: TCompScintFileEdit;
 begin
 begin
   HideError;
   HideError;
   FUninstExe := '';
   FUninstExe := '';
@@ -924,7 +955,7 @@ begin
     FDebugTarget := dtSetup;
     FDebugTarget := dtSetup;
     UpdateTargetMenu;
     UpdateTargetMenu;
   end;
   end;
-  for Memo in FMemos do
+  for Memo in FFileMemos do
     if Memo.Used then
     if Memo.Used then
       Memo.BreakPoints.Clear;
       Memo.BreakPoints.Clear;
   DestroyDebugInfo;
   DestroyDebugInfo;
@@ -934,8 +965,9 @@ begin
   FMainMemo.SaveInUTF8Encoding := False;
   FMainMemo.SaveInUTF8Encoding := False;
   FMainMemo.Lines.Clear;
   FMainMemo.Lines.Clear;
   FModifiedAnySinceLastCompile := True;
   FModifiedAnySinceLastCompile := True;
+  FPreprocessorOutput := '';
   FIncludedFiles.Clear;
   FIncludedFiles.Clear;
-  UpdateIncludedFilesMemos;
+  UpdatePreprocMemos;
   FMainMemo.ClearUndo;
   FMainMemo.ClearUndo;
 end;
 end;
 
 
@@ -964,7 +996,7 @@ begin
               FIncludedFiles.Add(IncludedFile);
               FIncludedFiles.Add(IncludedFile);
             end;
             end;
           finally
           finally
-            UpdateIncludedFilesMemos;
+            UpdatePreprocMemos;
           end;
           end;
         end;
         end;
       finally
       finally
@@ -1037,7 +1069,7 @@ begin
   end;
   end;
 end;
 end;
 
 
-procedure TCompileForm.OpenFile(AMemo: TCompScintEdit; AFilename: String;
+procedure TCompileForm.OpenFile(AMemo: TCompScintFileEdit; AFilename: String;
   const MainMemoAddToRecentDocs: Boolean);
   const MainMemoAddToRecentDocs: Boolean);
 
 
   function IsStreamUTF8Encoded(const Stream: TStream): Boolean;
   function IsStreamUTF8Encoded(const Stream: TStream): Boolean;
@@ -1093,7 +1125,7 @@ begin
   end;
   end;
 end;
 end;
 
 
-function TCompileForm.SaveFile(const AMemo: TCompScintEdit; const SaveAs: Boolean): Boolean;
+function TCompileForm.SaveFile(const AMemo: TCompScintFileEdit; const SaveAs: Boolean): Boolean;
 
 
   procedure SaveMemoTo(const FN: String);
   procedure SaveMemoTo(const FN: String);
   var
   var
@@ -1163,7 +1195,7 @@ end;
 
 
 function TCompileForm.ConfirmCloseFile(const PromptToSave: Boolean): Boolean;
 function TCompileForm.ConfirmCloseFile(const PromptToSave: Boolean): Boolean;
 
 
-  function PromptToSaveMemo(const AMemo: TCompScintEdit): Boolean;
+  function PromptToSaveMemo(const AMemo: TCompScintFileEdit): Boolean;
   var
   var
     FileTitle: String;
     FileTitle: String;
   begin
   begin
@@ -1182,7 +1214,7 @@ function TCompileForm.ConfirmCloseFile(const PromptToSave: Boolean): Boolean;
   end;
   end;
 
 
 var
 var
-  Memo: TCompScintEdit;
+  Memo: TCompScintFileEdit;
 begin
 begin
   if FCompiling then begin
   if FCompiling then begin
     MsgBox('Please stop the compile process before performing this command.',
     MsgBox('Please stop the compile process before performing this command.',
@@ -1196,7 +1228,7 @@ begin
   end;
   end;
   Result := True;
   Result := True;
   if PromptToSave then begin
   if PromptToSave then begin
-    for Memo in FMemos do begin
+    for Memo in FFileMemos do begin
       if Memo.Used then begin
       if Memo.Used then begin
         Result := PromptToSaveMemo(Memo);
         Result := PromptToSaveMemo(Memo);
         if not Result then
         if not Result then
@@ -1365,8 +1397,9 @@ begin
           if Form.FCompileWantAbort then
           if Form.FCompileWantAbort then
             Result := iscrRequestAbort;
             Result := iscrRequestAbort;
         end;
         end;
-      iscbNotifyIncludedFiles:
+      iscbNotifyPreproc:
         begin
         begin
+          Form.FPreprocessorOutput := Trim(Data.PreprocessedScript);
           DecodeIncludedFilenames(Data.IncludedFilenames, Form.FIncludedFiles); { Also stores last write time }
           DecodeIncludedFilenames(Data.IncludedFilenames, Form.FIncludedFiles); { Also stores last write time }
           Form.SaveKnownIncludedFiles(Filename);
           Form.SaveKnownIncludedFiles(Filename);
         end;
         end;
@@ -1393,15 +1426,15 @@ end;
 
 
 procedure TCompileForm.CompileFile(AFilename: String; const ReadFromFile: Boolean);
 procedure TCompileForm.CompileFile(AFilename: String; const ReadFromFile: Boolean);
 
 
-  function GetMemoFromErrorFilename(const ErrorFilename: String): TCompScintEdit;
+  function GetMemoFromErrorFilename(const ErrorFilename: String): TCompScintFileEdit;
   var
   var
-    Memo: TCompScintEdit;
+    Memo: TCompScintFileEdit;
   begin
   begin
     if ErrorFilename = '' then
     if ErrorFilename = '' then
       Result := FMainMemo
       Result := FMainMemo
     else begin
     else begin
       if FOptions.OpenIncludedFiles then begin
       if FOptions.OpenIncludedFiles then begin
-        for Memo in FMemos do begin
+        for Memo in FFileMemos do begin
           if Memo.Used and (PathCompare(Memo.Filename, ErrorFilename) = 0) then begin
           if Memo.Used and (PathCompare(Memo.Filename, ErrorFilename) = 0) then begin
             Result := Memo;
             Result := Memo;
             Exit;
             Exit;
@@ -1418,7 +1451,8 @@ var
   AppData: TAppData;
   AppData: TAppData;
   StartTime, ElapsedTime, ElapsedSeconds: DWORD;
   StartTime, ElapsedTime, ElapsedSeconds: DWORD;
   I: Integer;
   I: Integer;
-  Memo, OldActiveMemo: TCompScintEdit;
+  Memo: TCompScintFileEdit;
+  OldActiveMemo: TCompScintEdit;
 begin
 begin
   if FCompiling then begin
   if FCompiling then begin
     { Shouldn't get here, but just in case... }
     { Shouldn't get here, but just in case... }
@@ -1429,7 +1463,7 @@ begin
   if not ReadFromFile then begin
   if not ReadFromFile then begin
     if FOptions.OpenIncludedFiles then begin
     if FOptions.OpenIncludedFiles then begin
       { Included files must always be saved since they're not read from the editor by the compiler }
       { Included files must always be saved since they're not read from the editor by the compiler }
-      for Memo in FMemos do begin
+      for Memo in FFileMemos do begin
         if (Memo <> FMainMemo) and Memo.Used and Memo.Modified then begin
         if (Memo <> FMainMemo) and Memo.Used and Memo.Modified then begin
           if FOptions.Autosave then begin
           if FOptions.Autosave then begin
             if not SaveFile(Memo, False) then
             if not SaveFile(Memo, False) then
@@ -1480,7 +1514,7 @@ begin
     FActiveMemo.Cursor := crAppStart;
     FActiveMemo.Cursor := crAppStart;
     FActiveMemo.SetCursorID(999);  { hack to keep it from overriding Cursor }
     FActiveMemo.SetCursorID(999);  { hack to keep it from overriding Cursor }
     CompilerOutputList.Cursor := crAppStart;
     CompilerOutputList.Cursor := crAppStart;
-    for Memo in FMemos do
+    for Memo in FFileMemos do
       Memo.ReadOnly := True;
       Memo.ReadOnly := True;
     UpdateEditModePanel;
     UpdateEditModePanel;
     HideError;
     HideError;
@@ -1567,12 +1601,12 @@ begin
     OldActiveMemo.Cursor := crDefault;
     OldActiveMemo.Cursor := crDefault;
     OldActiveMemo.SetCursorID(SC_CURSORNORMAL);
     OldActiveMemo.SetCursorID(SC_CURSORNORMAL);
     CompilerOutputList.Cursor := crDefault;
     CompilerOutputList.Cursor := crDefault;
-    for Memo in FMemos do
+    for Memo in FFileMemos do
       Memo.ReadOnly := False;
       Memo.ReadOnly := False;
     UpdateEditModePanel;
     UpdateEditModePanel;
     UpdateRunMenu;
     UpdateRunMenu;
     UpdateCaption;
     UpdateCaption;
-    UpdateIncludedFilesMemos;
+    UpdatePreprocMemos;
     if AppData.DebugInfo <> nil then begin
     if AppData.DebugInfo <> nil then begin
       ParseDebugInfo(AppData.DebugInfo); { Must be called after UpdateIncludedFilesMemos }
       ParseDebugInfo(AppData.DebugInfo); { Must be called after UpdateIncludedFilesMemos }
       FreeMem(AppData.DebugInfo);
       FreeMem(AppData.DebugInfo);
@@ -1639,9 +1673,11 @@ procedure TCompileForm.FMenuClick(Sender: TObject);
 var
 var
   I: Integer;
   I: Integer;
 begin
 begin
+  FSave.Enabled := FActiveMemo is TCompScintFileEdit;
   FSaveMainFileAs.Enabled := FActiveMemo = FMainMemo;
   FSaveMainFileAs.Enabled := FActiveMemo = FMainMemo;
-  FSaveEncodingAuto.Checked := not FActiveMemo.SaveInUTF8Encoding;
-  FSaveEncodingUTF8.Checked := FActiveMemo.SaveInUTF8Encoding;
+  FSaveEncoding.Enabled := FSave.Enabled;
+  FSaveEncodingAuto.Checked := FSave.Enabled and not TCompScintFileEdit(FActiveMemo).SaveInUTF8Encoding;
+  FSaveEncodingUTF8.Checked := FSave.Enabled and TCompScintFileEdit(FActiveMemo).SaveInUTF8Encoding;
   FSaveAll.Visible := FOptions.OpenIncludedFiles;
   FSaveAll.Visible := FOptions.OpenIncludedFiles;
   ReadMRUMainFilesList;
   ReadMRUMainFilesList;
   FMRUMainFilesSep.Visible := FMRUMainFilesList.Count <> 0;
   FMRUMainFilesSep.Visible := FMRUMainFilesList.Count <> 0;
@@ -1692,19 +1728,19 @@ end;
 
 
 procedure TCompileForm.FSaveClick(Sender: TObject);
 procedure TCompileForm.FSaveClick(Sender: TObject);
 begin
 begin
-  SaveFile(FActiveMemo, Sender = FSaveMainFileAs);
+  SaveFile(TCompScintFileEdit(FActiveMemo), Sender = FSaveMainFileAs);
 end;
 end;
 
 
 procedure TCompileForm.FSaveEncodingItemClick(Sender: TObject);
 procedure TCompileForm.FSaveEncodingItemClick(Sender: TObject);
 begin
 begin
-  FActiveMemo.SaveInUTF8Encoding := (Sender = FSaveEncodingUTF8);
+  TCompScintFileEdit(FActiveMemo).SaveInUTF8Encoding := (Sender = FSaveEncodingUTF8);
 end;
 end;
 
 
 procedure TCompileForm.FSaveAllClick(Sender: TObject);
 procedure TCompileForm.FSaveAllClick(Sender: TObject);
 var
 var
-  Memo: TCompScintEdit;
+  Memo: TCompScintFileEdit;
 begin
 begin
-  for Memo in FMemos do
+  for Memo in FFileMemos do
     if Memo.Used and Memo.Modified then
     if Memo.Used and Memo.Modified then
       SaveFile(Memo, False);
       SaveFile(Memo, False);
 end;
 end;
@@ -1728,21 +1764,22 @@ end;
 
 
 procedure TCompileForm.EMenuClick(Sender: TObject);
 procedure TCompileForm.EMenuClick(Sender: TObject);
 var
 var
-  MemoHasFocus: Boolean;
+  MemoHasFocus, MemoIsReadOnly: Boolean;
 begin
 begin
   MemoHasFocus := FActiveMemo.Focused;
   MemoHasFocus := FActiveMemo.Focused;
+  MemoIsReadOnly := FActiveMemo.ReadOnly;
   EUndo.Enabled := MemoHasFocus and FActiveMemo.CanUndo;
   EUndo.Enabled := MemoHasFocus and FActiveMemo.CanUndo;
   ERedo.Enabled := MemoHasFocus and FActiveMemo.CanRedo;
   ERedo.Enabled := MemoHasFocus and FActiveMemo.CanRedo;
-  ECut.Enabled := MemoHasFocus and FActiveMemo.SelAvail;
+  ECut.Enabled := MemoHasFocus and not MemoIsReadOnly and FActiveMemo.SelAvail;
   ECopy.Enabled := MemoHasFocus and FActiveMemo.SelAvail;
   ECopy.Enabled := MemoHasFocus and FActiveMemo.SelAvail;
-  EPaste.Enabled := MemoHasFocus and Clipboard.HasFormat(CF_TEXT);
+  EPaste.Enabled := MemoHasFocus and not MemoIsReadOnly and Clipboard.HasFormat(CF_TEXT);
   EDelete.Enabled := MemoHasFocus and FActiveMemo.SelAvail;
   EDelete.Enabled := MemoHasFocus and FActiveMemo.SelAvail;
   ESelectAll.Enabled := MemoHasFocus;
   ESelectAll.Enabled := MemoHasFocus;
   EFind.Enabled := MemoHasFocus;
   EFind.Enabled := MemoHasFocus;
   EFindNext.Enabled := MemoHasFocus;
   EFindNext.Enabled := MemoHasFocus;
-  EReplace.Enabled := MemoHasFocus;
+  EReplace.Enabled := MemoHasFocus and not MemoIsReadOnly;
   EGoto.Enabled := MemoHasFocus;
   EGoto.Enabled := MemoHasFocus;
-  ECompleteWord.Enabled := MemoHasFocus;
+  ECompleteWord.Enabled := MemoHasFocus and not MemoIsReadOnly;
 end;
 end;
 
 
 procedure TCompileForm.EUndoClick(Sender: TObject);
 procedure TCompileForm.EUndoClick(Sender: TObject);
@@ -2137,14 +2174,26 @@ begin
 end;
 end;
 
 
 procedure TCompileForm.MemosTabSetClick(Sender: TObject);
 procedure TCompileForm.MemosTabSetClick(Sender: TObject);
+
+  function TabIndexToMemoIndex(const TabIndex, MaxTabIndex: Integer): Integer;
+  begin
+    if TabIndex = 0 then
+      Result := 0 { First tab displays the main memo which is FMemos[0] }
+    else if FPreprocessorOutputMemo.Used and (TabIndex = MaxTabIndex) then
+      Result := 1 { Last tab displays the preprocessor output memo which is FMemos[1] }
+    else
+      Result := TabIndex+1; { Other tabs display include files which start second tab but at FMemos[2] }
+  end;
 var
 var
   Memo: TCompScintEdit;
   Memo: TCompScintEdit;
-  I: Integer;
+  TabIndex, MaxTabIndex: Integer;
 begin
 begin
   FActiveMemo.CancelAutoComplete;
   FActiveMemo.CancelAutoComplete;
-  for I := 0 to MemosTabSet.Tabs.Count-1 do begin
-    Memo := FMemos[I];
-    Memo.Visible := (I = MemosTabSet.TabIndex);
+
+  MaxTabIndex := MemosTabSet.Tabs.Count-1;
+  for TabIndex := 0 to MaxTabIndex do begin
+    Memo := FMemos[TabIndexToMemoIndex(TabIndex, MaxTabIndex)];
+    Memo.Visible := (TabIndex = MemosTabSet.TabIndex);
     if Memo.Visible then begin
     if Memo.Visible then begin
       FActiveMemo := Memo;
       FActiveMemo := Memo;
       ActiveControl := Memo;
       ActiveControl := Memo;
@@ -2378,6 +2427,7 @@ begin
     OptionsForm.AutoIndentCheck.Checked := FOptions.AutoIndent;
     OptionsForm.AutoIndentCheck.Checked := FOptions.AutoIndent;
     OptionsForm.IndentationGuidesCheck.Checked := FOptions.IndentationGuides;
     OptionsForm.IndentationGuidesCheck.Checked := FOptions.IndentationGuides;
     OptionsForm.GutterLineNumbersCheck.Checked := FOptions.GutterLineNumbers;
     OptionsForm.GutterLineNumbersCheck.Checked := FOptions.GutterLineNumbers;
+    OptionsForm.ShowPreprocessorOutputCheck.Checked := FOptions.ShowPreprocessorOutput;
     OptionsForm.OpenIncludedFilesCheck.Checked := FOptions.OpenIncludedFiles;
     OptionsForm.OpenIncludedFilesCheck.Checked := FOptions.OpenIncludedFiles;
     OptionsForm.ThemeComboBox.ItemIndex := Ord(FOptions.ThemeType);
     OptionsForm.ThemeComboBox.ItemIndex := Ord(FOptions.ThemeType);
     OptionsForm.FontPanel.Font.Assign(FMainMemo.Font);
     OptionsForm.FontPanel.Font.Assign(FMainMemo.Font);
@@ -2406,11 +2456,12 @@ begin
     FOptions.AutoIndent := OptionsForm.AutoIndentCheck.Checked;
     FOptions.AutoIndent := OptionsForm.AutoIndentCheck.Checked;
     FOptions.IndentationGuides := OptionsForm.IndentationGuidesCheck.Checked;
     FOptions.IndentationGuides := OptionsForm.IndentationGuidesCheck.Checked;
     FOptions.GutterLineNumbers := OptionsForm.GutterLineNumbersCheck.Checked;
     FOptions.GutterLineNumbers := OptionsForm.GutterLineNumbersCheck.Checked;
+    FOptions.ShowPreprocessorOutput := OptionsForm.ShowPreprocessorOutputCheck.Checked;
     FOptions.OpenIncludedFiles := OptionsForm.OpenIncludedFilesCheck.Checked;
     FOptions.OpenIncludedFiles := OptionsForm.OpenIncludedFilesCheck.Checked;
     FOptions.ThemeType := TThemeType(OptionsForm.ThemeComboBox.ItemIndex);
     FOptions.ThemeType := TThemeType(OptionsForm.ThemeComboBox.ItemIndex);
     
     
     UpdateCaption;
     UpdateCaption;
-    UpdateIncludedFilesMemos;
+    UpdatePreprocMemos;
     for Memo in FMemos do begin
     for Memo in FMemos do begin
       { Move caret to start of line to ensure it doesn't end up in the middle
       { Move caret to start of line to ensure it doesn't end up in the middle
         of a double-byte character if the code page changes from SBCS to DBCS }
         of a double-byte character if the code page changes from SBCS to DBCS }
@@ -2443,6 +2494,7 @@ begin
       Ini.WriteBool('Options', 'AutoIndent', FOptions.AutoIndent);
       Ini.WriteBool('Options', 'AutoIndent', FOptions.AutoIndent);
       Ini.WriteBool('Options', 'IndentationGuides', FOptions.IndentationGuides);
       Ini.WriteBool('Options', 'IndentationGuides', FOptions.IndentationGuides);
       Ini.WriteBool('Options', 'GutterLineNumbers', FOptions.GutterLineNumbers);
       Ini.WriteBool('Options', 'GutterLineNumbers', FOptions.GutterLineNumbers);
+      Ini.WriteBool('Options', 'ShowPreprocessorOutput', FOptions.ShowPreprocessorOutput);
       Ini.WriteBool('Options', 'OpenIncludedFiles', FOptions.OpenIncludedFiles);
       Ini.WriteBool('Options', 'OpenIncludedFiles', FOptions.OpenIncludedFiles);
       Ini.WriteInteger('Options', 'ThemeType', Ord(FOptions.ThemeType)); { Also see Destroy }
       Ini.WriteInteger('Options', 'ThemeType', Ord(FOptions.ThemeType)); { Also see Destroy }
       Ini.WriteString('Options', 'EditorFontName', FMainMemo.Font.Name);
       Ini.WriteString('Options', 'EditorFontName', FMainMemo.Font.Name);
@@ -2478,7 +2530,7 @@ begin
   MemosTabSet.TabIndex := FMemos.IndexOf(AMemo);
   MemosTabSet.TabIndex := FMemos.IndexOf(AMemo);
 end;
 end;
 
 
-procedure TCompileForm.SetErrorLine(const AMemo: TCompScintEdit; const ALine: Integer);
+procedure TCompileForm.SetErrorLine(const AMemo: TCompScintFileEdit; const ALine: Integer);
 var
 var
   OldLine: Integer;
   OldLine: Integer;
 begin
 begin
@@ -2499,7 +2551,7 @@ begin
   end;
   end;
 end;
 end;
 
 
-procedure TCompileForm.SetStepLine(const AMemo: TCompScintEdit; ALine: Integer);
+procedure TCompileForm.SetStepLine(const AMemo: TCompScintFileEdit; ALine: Integer);
 var
 var
   OldLine: Integer;
   OldLine: Integer;
 begin
 begin
@@ -2541,6 +2593,13 @@ begin
     StatusBar.Panels[spEditMode].Text := InsertText[FActiveMemo.InsertMode];
     StatusBar.Panels[spEditMode].Text := InsertText[FActiveMemo.InsertMode];
 end;
 end;
 
 
+procedure TCompileForm.UpdateMemosTabSetVisibility;
+begin
+  MemosTabSet.Visible := FPreprocessorOutputMemo.Used or FFileMemos[FirstIncludedFilesMemoIndex].Used;
+  if not MemosTabSet.Visible then
+    MemosTabSet.TabIndex := 0; { For next time }
+end;
+
 procedure TCompileForm.UpdateModifiedPanel;
 procedure TCompileForm.UpdateModifiedPanel;
 begin
 begin
   if FActiveMemo.Modified then
   if FActiveMemo.Modified then
@@ -2549,26 +2608,39 @@ begin
     StatusBar.Panels[spModified].Text := '';
     StatusBar.Panels[spModified].Text := '';
 end;
 end;
 
 
-procedure TCompileForm.UpdateIncludedFilesMemos;
-var
-  NewTabs, NewHints: TStringList;
-  IncludedFile: TIncludedFile;
-  I, NextMemoIndex: Integer;
-  SaveTabName: String;
-begin
-  if FOptions.OpenIncludedFiles and (FIncludedFiles.Count > 0) then begin
-    NewTabs := nil;
-    NewHints := nil;
-    try
-      NewTabs := TStringList.Create;
-      NewTabs.Add(MemosTabSet.Tabs[0]); { 'Main Script' }
-      NewHints := TStringList.Create;
-      NewHints.Add(GetFileTitle(FMainMemo.Filename));
+procedure TCompileForm.UpdatePreprocMemos;
+
+  procedure UpdatePreprocessorOutputMemo(const NewTabs, NewHints: TStringList);
+  begin
+    if FOptions.ShowPreprocessorOutput and (FPreprocessorOutput <> '') and
+       not SameText(Trim(FMainMemo.Lines.Text), FPreprocessorOutput) then begin
+      NewTabs.Add('Preprocessor Output');
+      NewHints.Add('');
+      FPreprocessorOutputMemo.ReadOnly := False;
+      try
+        FPreprocessorOutputMemo.Lines.Text := FPreprocessorOutput;
+        FPreprocessorOutputMemo.ClearUndo;
+      finally
+        FPreprocessorOutputMemo.ReadOnly := True;
+      end;
+      FPreprocessorOutputMemo.Used := True;
+    end else begin
+      FPreprocessorOutputMemo.Used := False;
+      FPreprocessorOutputMemo.Visible := False;
+    end;
+  end;
+
+  procedure UpdateIncludedFilesMemos(const NewTabs, NewHints: TStringList);
+  var
+    IncludedFile: TIncludedFile;
+    I, NextMemoIndex, NewTabIndex: Integer;
+  begin
+    if FOptions.OpenIncludedFiles and (FIncludedFiles.Count > 0) then begin
       NextMemoIndex := FirstIncludedFilesMemoIndex;
       NextMemoIndex := FirstIncludedFilesMemoIndex;
       FLoadingIncludedFiles := True;
       FLoadingIncludedFiles := True;
       try
       try
         for IncludedFile in FIncludedFiles do begin
         for IncludedFile in FIncludedFiles do begin
-          IncludedFile.Memo := FMemos[NextMemoIndex];
+          IncludedFile.Memo := FFileMemos[NextMemoIndex];
           try
           try
             if not IncludedFile.Memo.Used or
             if not IncludedFile.Memo.Used or
               ((PathCompare(IncludedFile.Memo.Filename, IncludedFile.Filename) <> 0) or
               ((PathCompare(IncludedFile.Memo.Filename, IncludedFile.Filename) <> 0) or
@@ -2583,8 +2655,9 @@ begin
              { Previously the included file came from the history }
              { Previously the included file came from the history }
               IncludedFile.Memo.CompilerFileIndex := IncludedFile.CompilerFileIndex;
               IncludedFile.Memo.CompilerFileIndex := IncludedFile.CompilerFileIndex;
             end;
             end;
-            NewTabs.Add(PathExtractName(IncludedFile.Filename));
-            NewHints.Add(GetFileTitle(IncludedFile.Filename));
+            NewTabIndex := 1+NextMemoIndex-FirstIncludedFilesMemoIndex;
+            NewTabs.Insert(NewTabIndex, PathExtractName(IncludedFile.Filename));
+            NewHints.Insert(NewTabIndex, GetFileTitle(IncludedFile.Filename));
 
 
             Inc(NextMemoIndex);
             Inc(NextMemoIndex);
             if NextMemoIndex = FMemos.Count then
             if NextMemoIndex = FMemos.Count then
@@ -2600,38 +2673,58 @@ begin
         FLoadingIncludedFiles := False;
         FLoadingIncludedFiles := False;
       end;
       end;
       { Hide any remaining memos }
       { Hide any remaining memos }
-      for I := NextMemoIndex to FMemos.Count-1 do begin
-        FMemos[I].BreakPoints.Clear;
-        FMemos[I].Used := False;
-        FMemos[I].Visible := False;
+      for I := NextMemoIndex to FFileMemos.Count-1 do begin
+        FFileMemos[I].BreakPoints.Clear;
+        FFileMemos[I].Used := False;
+        FFileMemos[I].Visible := False;
       end;
       end;
-      { Set new tabs, try keep same file open }
-      SaveTabName := MemosTabSet.Tabs[MemosTabSet.TabIndex];
-      MemosTabSet.Tabs := NewTabs;
-      MemosTabSet.Hints := NewHints;
-      I := MemosTabSet.Tabs.IndexOf(SaveTabName);
-      if I <> -1 then
-         MemosTabSet.TabIndex := I;
-    finally
-      NewHints.Free;
-      NewTabs.Free;
-    end;
-    MemosTabSet.Visible := True;
-  end else begin
-    if MemosTabSet.Visible then begin
-      for I := FirstIncludedFilesMemoIndex to FMemos.Count-1 do begin
-        FMemos[I].BreakPoints.Clear;
-        FMemos[I].Used := False;
-        FMemos[I].Visible := False;
+    end else begin
+      for I := FirstIncludedFilesMemoIndex to FFileMemos.Count-1 do begin
+        FFileMemos[I].BreakPoints.Clear;
+        FFileMemos[I].Used := False;
+        FFileMemos[I].Visible := False;
       end;
       end;
       for IncludedFile in FIncludedFiles do
       for IncludedFile in FIncludedFiles do
         IncludedFile.Memo := nil;
         IncludedFile.Memo := nil;
-      MemosTabSet.Visible := False;
-      MemosTabSet.TabIndex := 0; { For next time }
     end;
     end;
   end;
   end;
-  
-  UpdateBevel1;
+
+var
+  NewTabs, NewHints: TStringList;
+  I, SaveTabIndex: Integer;
+  SaveTabName: String;
+begin
+  NewTabs := nil;
+  NewHints := nil;
+  try
+    NewTabs := TStringList.Create;
+    NewTabs.Add(MemosTabSet.Tabs[0]); { 'Main Script' }
+    NewHints := TStringList.Create;
+    NewHints.Add(GetFileTitle(FMainMemo.Filename));
+
+    UpdatePreprocessorOutputMemo(NewTabs, NewHints);
+    UpdateIncludedFilesMemos(NewTabs, NewHints);
+
+    { Set new tabs, try keep same file open }
+    SaveTabIndex := MemosTabSet.TabIndex;
+    SaveTabName := MemosTabSet.Tabs[MemosTabSet.TabIndex];
+    MemosTabSet.Tabs := NewTabs;
+    MemosTabSet.Hints := NewHints;
+    I := MemosTabSet.Tabs.IndexOf(SaveTabName);
+    if I <> -1 then
+       MemosTabSet.TabIndex := I;
+   if MemosTabSet.TabIndex = SaveTabIndex then begin
+      { If TabIndex stayed the same then the tabset won't perform a Click but we need this to make
+       sure the right memo is visible - so trigger it ourselves }
+      MemosTabSetClick(MemosTabSet);
+   end;
+  finally
+    NewHints.Free;
+    NewTabs.Free;
+  end;
+
+  UpdateMemosTabSetVisibility;
+  UpdateBevel1Visibility;
 end;
 end;
 
 
 procedure TCompileForm.MemoUpdateUI(Sender: TObject);
 procedure TCompileForm.MemoUpdateUI(Sender: TObject);
@@ -2713,7 +2806,7 @@ end;
 
 
 procedure TCompileForm.MemoChange(Sender: TObject; const Info: TScintEditChangeInfo);
 procedure TCompileForm.MemoChange(Sender: TObject; const Info: TScintEditChangeInfo);
 
 
-  procedure MemoLinesInsertedOrDeleted(Memo: TCompScintEdit);
+  procedure MemoLinesInsertedOrDeleted(Memo: TCompScintFileEdit);
   var
   var
     FirstAffectedLine, Line, LinePos: Integer;
     FirstAffectedLine, Line, LinePos: Integer;
   begin
   begin
@@ -2733,13 +2826,13 @@ procedure TCompileForm.MemoChange(Sender: TObject; const Info: TScintEditChangeI
   end;
   end;
 
 
 var
 var
-  Memo: TCompScintEdit;
+  Memo: TCompScintFileEdit;
 begin
 begin
-  Memo := Sender as TCompScintEdit;
-
-  if (Memo <> FMainMemo) and FLoadingIncludedFiles then
+  if not (Sender is TCompScintFileEdit) or ((Sender <> FMainMemo) and FLoadingIncludedFiles) then
     Exit;
     Exit;
 
 
+  Memo := TCompScintFileEdit(Sender);
+
   FModifiedAnySinceLastCompile := True;
   FModifiedAnySinceLastCompile := True;
   if FDebugging then
   if FDebugging then
     FModifiedAnySinceLastCompileAndGo := True
     FModifiedAnySinceLastCompileAndGo := True
@@ -2754,7 +2847,7 @@ begin
   if Memo = FErrorMemo then begin
   if Memo = FErrorMemo then begin
     { When the Delete key is pressed, the caret doesn't move, so reset
     { When the Delete key is pressed, the caret doesn't move, so reset
       FErrorCaretPosition to ensure that OnUpdateUI calls HideError }
       FErrorCaretPosition to ensure that OnUpdateUI calls HideError }
-    Memo.ErrorCaretPosition := -1;
+    FErrorMemo.ErrorCaretPosition := -1;
   end;
   end;
 
 
   { The change should trigger restyling. Allow the styler to see the current
   { The change should trigger restyling. Allow the styler to see the current
@@ -3002,14 +3095,15 @@ begin
   Line := FActiveMemo.GetLineFromPosition(Pos);
   Line := FActiveMemo.GetLineFromPosition(Pos);
 
 
   { Check if cursor is over a [Code] variable }
   { Check if cursor is over a [Code] variable }
-  if FMemosStyler.GetSectionFromLineState(FActiveMemo.Lines.State[Line]) = scCode then begin
+  if (FActiveMemo is TCompScintFileEdit) and
+     (FMemosStyler.GetSectionFromLineState(FActiveMemo.Lines.State[Line]) = scCode) then begin
     { Note: The '+ 1' is needed so that when the mouse is over a '.'
     { Note: The '+ 1' is needed so that when the mouse is over a '.'
       between two words, it won't match the word to the left of the '.' }
       between two words, it won't match the word to the left of the '.' }
     I := FActiveMemo.GetWordStartPosition(Pos + 1, True);
     I := FActiveMemo.GetWordStartPosition(Pos + 1, True);
     J := FActiveMemo.GetWordEndPosition(Pos, True);
     J := FActiveMemo.GetWordEndPosition(Pos, True);
     if J > I then begin
     if J > I then begin
-      DebugEntry := GetCodeVariableDebugEntryFromFileLineCol(FActiveMemo.CompilerFileIndex, Line,
-        GetCodeColumnFromPosition(I));
+      DebugEntry := GetCodeVariableDebugEntryFromFileLineCol(TCompScintFileEdit(FActiveMemo).CompilerFileIndex,
+        Line, GetCodeColumnFromPosition(I));
       if DebugEntry <> nil then begin
       if DebugEntry <> nil then begin
         case EvaluateVariableEntry(DebugEntry, Output) of
         case EvaluateVariableEntry(DebugEntry, Output) of
           1: Info.HintStr := Output;
           1: Info.HintStr := Output;
@@ -3095,15 +3189,15 @@ begin
   DebuggingStopped(True);
   DebuggingStopped(True);
 end;
 end;
 
 
-procedure TCompileForm.GetMemoAndLineNumberFromEntry(Kind, Index: Integer; var Memo: TCompScintEdit; var LineNumber: Integer);
+procedure TCompileForm.GetMemoAndLineNumberFromEntry(Kind, Index: Integer; var Memo: TCompScintFileEdit; var LineNumber: Integer);
 
 
-  function GetMemoFromDebugEntryFileIndex(const FileIndex: Integer): TCompScintEdit;
+  function GetMemoFromDebugEntryFileIndex(const FileIndex: Integer): TCompScintFileEdit;
   var
   var
-    Memo: TCompScintEdit;
+    Memo: TCompScintFileEdit;
   begin
   begin
     Result := nil;
     Result := nil;
     if FOptions.OpenIncludedFiles then begin
     if FOptions.OpenIncludedFiles then begin
-      for Memo in FMemos do begin
+      for Memo in FFileMemos do begin
         if Memo.Used and (Memo.CompilerFileIndex = FileIndex) then begin
         if Memo.Used and (Memo.CompilerFileIndex = FileIndex) then begin
           Result := Memo;
           Result := Memo;
           Exit;
           Exit;
@@ -3150,7 +3244,7 @@ end;
 
 
 procedure TCompileForm.DebuggerStepped(var Message: TMessage; const Intermediate: Boolean);
 procedure TCompileForm.DebuggerStepped(var Message: TMessage; const Intermediate: Boolean);
 var
 var
-  Memo: TCompScintEdit;
+  Memo: TCompScintFileEdit;
   LineNumber: Integer;
   LineNumber: Integer;
 begin
 begin
   GetMemoAndLineNumberFromEntry(Message.WParam, Message.LParam, Memo, LineNumber);
   GetMemoAndLineNumberFromEntry(Message.WParam, Message.LParam, Memo, LineNumber);
@@ -3193,7 +3287,7 @@ end;
 
 
 procedure TCompileForm.WMDebuggerException(var Message: TMessage);
 procedure TCompileForm.WMDebuggerException(var Message: TMessage);
 var
 var
-  Memo: TCompScintEdit;
+  Memo: TCompScintFileEdit;
   LineNumber: Integer;
   LineNumber: Integer;
   S: String;
   S: String;
 begin
 begin
@@ -3284,10 +3378,10 @@ end;
 procedure TCompileForm.DestroyDebugInfo;
 procedure TCompileForm.DestroyDebugInfo;
 var
 var
   HadDebugInfo: Boolean;
   HadDebugInfo: Boolean;
-  Memo: TCompScintEdit;
+  Memo: TCompScintFileEdit;
 begin
 begin
   HadDebugInfo := False;
   HadDebugInfo := False;
-  for Memo in FMemos do begin
+  for Memo in FFileMemos do begin
     if Assigned(Memo.LineState) then begin
     if Assigned(Memo.LineState) then begin
       Memo.LineStateCapacity := 0;
       Memo.LineStateCapacity := 0;
       Memo.LineStateCount := 0;
       Memo.LineStateCount := 0;
@@ -3315,17 +3409,17 @@ end;
 
 
 var
 var
   PrevCompilerFileIndex: Integer;
   PrevCompilerFileIndex: Integer;
-  PrevMemo: TCompScintEdit;
+  PrevMemo: TCompScintFileEdit;
 
 
 procedure TCompileForm.ParseDebugInfo(DebugInfo: Pointer);
 procedure TCompileForm.ParseDebugInfo(DebugInfo: Pointer);
 
 
-  function GetMemoFromCompilerFileIndex(const CompilerFileIndex: Integer): TCompScintEdit;
+  function GetMemoFromCompilerFileIndex(const CompilerFileIndex: Integer): TCompScintFileEdit;
   var
   var
-    Memo: TCompScintEdit;
+    Memo: TCompScintFileEdit;
   begin
   begin
     if (PrevCompilerFileIndex <> CompilerFileIndex) then begin
     if (PrevCompilerFileIndex <> CompilerFileIndex) then begin
       PrevMemo := nil;
       PrevMemo := nil;
-      for Memo in FMemos do begin
+      for Memo in FFileMemos do begin
         if Memo.Used and (Memo.CompilerFileIndex = CompilerFileIndex) then begin
         if Memo.Used and (Memo.CompilerFileIndex = CompilerFileIndex) then begin
           PrevMemo := Memo;
           PrevMemo := Memo;
           Break;
           Break;
@@ -3339,7 +3433,7 @@ procedure TCompileForm.ParseDebugInfo(DebugInfo: Pointer);
 { This creates and fills the DebugEntries and Memo LineState arrays }
 { This creates and fills the DebugEntries and Memo LineState arrays }
 var
 var
   Header: PDebugInfoHeader;
   Header: PDebugInfoHeader;
-  Memo: TCompScintEdit;
+  Memo: TCompScintFileEdit;
   Size: Cardinal;
   Size: Cardinal;
   I: Integer;
   I: Integer;
 begin
 begin
@@ -3351,7 +3445,7 @@ begin
     raise Exception.Create('Unrecognized debug info format');
     raise Exception.Create('Unrecognized debug info format');
 
 
   try
   try
-    for Memo in FMemos do begin
+    for Memo in FFileMemos do begin
       if Memo.Used then begin
       if Memo.Used then begin
         I := Memo.Lines.Count;
         I := Memo.Lines.Count;
         Memo.LineState := AllocMem(SizeOf(TLineState) * (I + LineStateGrowAmount));
         Memo.LineState := AllocMem(SizeOf(TLineState) * (I + LineStateGrowAmount));
@@ -3402,10 +3496,10 @@ end;
 procedure TCompileForm.ResetAllMemosLineState;
 procedure TCompileForm.ResetAllMemosLineState;
 { Changes green dots back to grey dots }
 { Changes green dots back to grey dots }
 var
 var
-  Memo: TCompScintEdit;
+  Memo: TCompScintFileEdit;
   I: Integer;
   I: Integer;
 begin
 begin
-  for Memo in FMemos do begin
+  for Memo in FFileMemos do begin
     if Memo.Used and Assigned(Memo.LineState) then begin
     if Memo.Used and Assigned(Memo.LineState) then begin
       for I := 0 to Memo.LineStateCount-1 do begin
       for I := 0 to Memo.LineStateCount-1 do begin
         if Memo.LineState[I] = lnEntryProcessed then begin
         if Memo.LineState[I] = lnEntryProcessed then begin
@@ -3525,9 +3619,10 @@ begin
   RunButton.Enabled := RRun.Enabled;
   RunButton.Enabled := RRun.Enabled;
   RPause.Enabled := FDebugging and not FPaused;
   RPause.Enabled := FDebugging and not FPaused;
   PauseButton.Enabled := RPause.Enabled;
   PauseButton.Enabled := RPause.Enabled;
-  RRunToCursor.Enabled := RRun.Enabled;
+  RRunToCursor.Enabled := RRun.Enabled and (FActiveMemo is TCompScintFileEdit);
   RStepInto.Enabled := RRun.Enabled;
   RStepInto.Enabled := RRun.Enabled;
   RStepOver.Enabled := RRun.Enabled;
   RStepOver.Enabled := RRun.Enabled;
+  RToggleBreakPoint.Enabled := FActiveMemo is TCompScintFileEdit;
   RTerminate.Enabled := FDebugging and (FDebugClientWnd <> 0);
   RTerminate.Enabled := FDebugging and (FDebugClientWnd <> 0);
   TerminateButton.Enabled := RTerminate.Enabled;
   TerminateButton.Enabled := RTerminate.Enabled;
   REvaluate.Enabled := FDebugging and (FDebugClientWnd <> 0);
   REvaluate.Enabled := FDebugging and (FDebugClientWnd <> 0);
@@ -3571,7 +3666,7 @@ begin
     ToolBarVirtualImageList.ImageCollection := DarkToolBarImageCollection
     ToolBarVirtualImageList.ImageCollection := DarkToolBarImageCollection
   else
   else
     ToolBarVirtualImageList.ImageCollection := LightToolBarImageCollection;
     ToolBarVirtualImageList.ImageCollection := LightToolBarImageCollection;
-  UpdateBevel1;
+  UpdateBevel1Visibility;
   SplitPanel.ParentBackground := False;
   SplitPanel.ParentBackground := False;
   SplitPanel.Color := FTheme.Colors[tcSplitterBack];
   SplitPanel.Color := FTheme.Colors[tcSplitterBack];
   if FTheme.Dark then begin
   if FTheme.Dark then begin
@@ -3813,7 +3908,7 @@ end;
 
 
 procedure TCompileForm.RRunToCursorClick(Sender: TObject);
 procedure TCompileForm.RRunToCursorClick(Sender: TObject);
 
 
-  function GetDebugEntryFromMemoAndLineNumber(Memo: TCompScintEdit; LineNumber: Integer;
+  function GetDebugEntryFromMemoAndLineNumber(Memo: TCompScintFileEdit; LineNumber: Integer;
     var DebugEntry: TDebugEntry): Boolean;
     var DebugEntry: TDebugEntry): Boolean;
   var
   var
     I: Integer;
     I: Integer;
@@ -3831,7 +3926,7 @@ procedure TCompileForm.RRunToCursorClick(Sender: TObject);
 
 
 begin
 begin
   CompileIfNecessary;
   CompileIfNecessary;
-  if not GetDebugEntryFromMemoAndLineNumber(FActiveMemo, FActiveMemo.CaretLine, FRunToCursorPoint) then begin
+  if not GetDebugEntryFromMemoAndLineNumber(TCompScintFileEdit(FActiveMemo), FActiveMemo.CaretLine, FRunToCursorPoint) then begin
     MsgBox('No code was generated for the current line.', SCompilerFormCaption,
     MsgBox('No code was generated for the current line.', SCompilerFormCaption,
       mbError, MB_OK);
       mbError, MB_OK);
     Exit;
     Exit;
@@ -4097,11 +4192,11 @@ const
       'also been made in the source editor.' + SNewLine2 + 'Do you want to ' +
       'also been made in the source editor.' + SNewLine2 + 'Do you want to ' +
       'reload the file and lose the changes made in the source editor?');
       'reload the file and lose the changes made in the source editor?');
 var
 var
-  Memo: TCompScintEdit;
+  Memo: TCompScintFileEdit;
   NewTime: TFileTime;
   NewTime: TFileTime;
   Changed: Boolean;
   Changed: Boolean;
 begin
 begin
-  for Memo in FMemos do begin
+  for Memo in FFileMemos do begin
     if (Memo.Filename = '') or not Memo.Used then
     if (Memo.Filename = '') or not Memo.Used then
       Continue;
       Continue;
 
 
@@ -4224,24 +4319,31 @@ end;
 
 
 procedure TCompileForm.ToggleBreakPoint(Line: Integer);
 procedure TCompileForm.ToggleBreakPoint(Line: Integer);
 var
 var
+  Memo: TCompScintFileEdit;
   I: Integer;
   I: Integer;
 begin
 begin
-  I := FActiveMemo.BreakPoints.IndexOf(Line);
+  Memo := TCompScintFileEdit(FActiveMemo);
+  I := Memo.BreakPoints.IndexOf(Line);
   if I = -1 then
   if I = -1 then
-    FActiveMemo.BreakPoints.Add(Line)
+    Memo.BreakPoints.Add(Line)
   else
   else
-    FActiveMemo.BreakPoints.Delete(I);
-  UpdateLineMarkers(FActiveMemo, Line);
+    Memo.BreakPoints.Delete(I);
+  UpdateLineMarkers(Memo, Line);
 end;
 end;
 
 
 procedure TCompileForm.MemoMarginClick(Sender: TObject; MarginNumber: Integer;
 procedure TCompileForm.MemoMarginClick(Sender: TObject; MarginNumber: Integer;
   Line: Integer);
   Line: Integer);
 begin
 begin
-  if MarginNumber = 1 then
+  if (MarginNumber = 1) and RToggleBreakPoint.Enabled then
     ToggleBreakPoint(Line);
     ToggleBreakPoint(Line);
 end;
 end;
 
 
-procedure TCompileForm.MemoLinesInserted(Memo: TCompScintEdit; FirstLine, Count: integer);
+procedure TCompileForm.RToggleBreakPointClick(Sender: TObject);
+begin
+  ToggleBreakPoint(FActiveMemo.CaretLine);
+end;
+
+procedure TCompileForm.MemoLinesInserted(Memo: TCompScintFileEdit; FirstLine, Count: integer);
 var
 var
   I, Line: Integer;
   I, Line: Integer;
 begin
 begin
@@ -4279,7 +4381,7 @@ begin
   end;
   end;
 end;
 end;
 
 
-procedure TCompileForm.MemoLinesDeleted(Memo: TCompScintEdit; FirstLine, Count,
+procedure TCompileForm.MemoLinesDeleted(Memo: TCompScintFileEdit; FirstLine, Count,
   FirstAffectedLine: Integer);
   FirstAffectedLine: Integer);
 var
 var
   I, Line: Integer;
   I, Line: Integer;
@@ -4345,7 +4447,7 @@ begin
   UpdateLineMarkers(Memo, FirstAffectedLine);
   UpdateLineMarkers(Memo, FirstAffectedLine);
 end;
 end;
 
 
-procedure TCompileForm.UpdateLineMarkers(const AMemo: TCompScintEdit; const Line: Integer);
+procedure TCompileForm.UpdateLineMarkers(const AMemo: TCompScintFileEdit; const Line: Integer);
 var
 var
   NewMarker: Integer;
   NewMarker: Integer;
 begin
 begin
@@ -4389,25 +4491,20 @@ end;
 
 
 procedure TCompileForm.UpdateAllMemosLineMarkers;
 procedure TCompileForm.UpdateAllMemosLineMarkers;
 var
 var
-  Memo: TCompScintEdit;
+  Memo: TCompScintFileEdit;
   Line: Integer;
   Line: Integer;
 begin
 begin
-  for Memo in FMemos do
+  for Memo in FFileMemos do
     if Memo.Used then
     if Memo.Used then
       for Line := 0 to Memo.Lines.Count-1 do
       for Line := 0 to Memo.Lines.Count-1 do
         UpdateLineMarkers(Memo, Line);
         UpdateLineMarkers(Memo, Line);
 end;
 end;
 
 
-procedure TCompileForm.UpdateBevel1;
+procedure TCompileForm.UpdateBevel1Visibility;
 begin
 begin
   Bevel1.Visible := (FTheme.Colors[tcMarginBack] = ToolBarPanel.Color) and not MemosTabSet.Visible;
   Bevel1.Visible := (FTheme.Colors[tcMarginBack] = ToolBarPanel.Color) and not MemosTabSet.Visible;
 end;
 end;
 
 
-procedure TCompileForm.RToggleBreakPointClick(Sender: TObject);
-begin
-  ToggleBreakPoint(FActiveMemo.CaretLine);
-end;
-
 function TCompileForm.ToCurrentPPI(const XY: Integer): Integer;
 function TCompileForm.ToCurrentPPI(const XY: Integer): Integer;
 begin
 begin
   Result := MulDiv(XY, CurrentPPI, 96);
   Result := MulDiv(XY, CurrentPPI, 96);

+ 3 - 2
Projects/CompInt.pas

@@ -22,7 +22,7 @@ const
   iscbNotifySuccess = 4;   { Sent when compilation succeeds }
   iscbNotifySuccess = 4;   { Sent when compilation succeeds }
   iscbNotifyError = 5;     { Sent when compilation fails or is aborted by the
   iscbNotifyError = 5;     { Sent when compilation fails or is aborted by the
                              application }
                              application }
-  iscbNotifyIncludedFiles = 6; { Sent to notify the application of included files }
+  iscbNotifyPreproc = 6;   { Sent to notify the application of preprocessor results }
 
 
   { Return values for callback function }
   { Return values for callback function }
   iscrSuccess = 0;         { Return this for compiler to continue }
   iscrSuccess = 0;         { Return this for compiler to continue }
@@ -74,7 +74,8 @@ type
         BytesCompressedPerSecond: Cardinal); { [in] Average bytes compressed
         BytesCompressedPerSecond: Cardinal); { [in] Average bytes compressed
                                                per second (new in 5.1.13) }
                                                per second (new in 5.1.13) }
 
 
-      iscbNotifyIncludedFiles: (
+      iscbNotifyPreproc: (
+        PreprocessedScript: PChar; { [in] Preprocessed script (new in 6.1.0) }
         IncludedFilenames: PChar); { [in] Names of #included files. Each name is
         IncludedFilenames: PChar); { [in] Names of #included files. Each name is
                                           a null-terminated string, and the final
                                           a null-terminated string, and the final
                                           name is followed by an additional null
                                           name is followed by an additional null

+ 30 - 22
Projects/CompOptions.dfm

@@ -4,7 +4,7 @@ object OptionsForm: TOptionsForm
   BorderIcons = [biSystemMenu]
   BorderIcons = [biSystemMenu]
   BorderStyle = bsDialog
   BorderStyle = bsDialog
   Caption = 'Options'
   Caption = 'Options'
-  ClientHeight = 349
+  ClientHeight = 355
   ClientWidth = 589
   ClientWidth = 589
   Color = clBtnFace
   Color = clBtnFace
   Font.Charset = DEFAULT_CHARSET
   Font.Charset = DEFAULT_CHARSET
@@ -17,14 +17,14 @@ object OptionsForm: TOptionsForm
   OnCreate = FormCreate
   OnCreate = FormCreate
   DesignSize = (
   DesignSize = (
     589
     589
-    349)
+    355)
   PixelsPerInch = 96
   PixelsPerInch = 96
   TextHeight = 13
   TextHeight = 13
   object GroupBox1: TGroupBox
   object GroupBox1: TGroupBox
     Left = 8
     Left = 8
     Top = 8
     Top = 8
     Width = 281
     Width = 281
-    Height = 233
+    Height = 245
     Anchors = [akLeft, akTop, akBottom]
     Anchors = [akLeft, akTop, akBottom]
     Caption = ' Miscellaneous '
     Caption = ' Miscellaneous '
     TabOrder = 0
     TabOrder = 0
@@ -46,72 +46,80 @@ object OptionsForm: TOptionsForm
     end
     end
     object AutosaveCheck: TCheckBox
     object AutosaveCheck: TCheckBox
       Left = 8
       Left = 8
-      Top = 76
+      Top = 96
       Width = 265
       Width = 265
       Height = 17
       Height = 17
       Caption = 'Automatically sa&ve before compiling'
       Caption = 'Automatically sa&ve before compiling'
-      TabOrder = 3
+      TabOrder = 4
     end
     end
     object BackupCheck: TCheckBox
     object BackupCheck: TCheckBox
       Left = 8
       Left = 8
-      Top = 96
+      Top = 116
       Width = 265
       Width = 265
       Height = 17
       Height = 17
       Caption = 'Create &backups when saving'
       Caption = 'Create &backups when saving'
-      TabOrder = 4
+      TabOrder = 5
     end
     end
     object UndoAfterSaveCheck: TCheckBox
     object UndoAfterSaveCheck: TCheckBox
       Left = 8
       Left = 8
-      Top = 116
+      Top = 136
       Width = 265
       Width = 265
       Height = 17
       Height = 17
       Caption = 'Allow &Undo after save'
       Caption = 'Allow &Undo after save'
-      TabOrder = 5
+      TabOrder = 6
     end
     end
     object FullPathCheck: TCheckBox
     object FullPathCheck: TCheckBox
       Left = 8
       Left = 8
-      Top = 136
+      Top = 156
       Width = 265
       Width = 265
       Height = 17
       Height = 17
       Caption = 'Display &full path in title bar'
       Caption = 'Display &full path in title bar'
-      TabOrder = 6
+      TabOrder = 7
     end
     end
     object PauseOnDebuggerExceptionsCheck: TCheckBox
     object PauseOnDebuggerExceptionsCheck: TCheckBox
       Left = 8
       Left = 8
-      Top = 156
+      Top = 176
       Width = 265
       Width = 265
       Height = 17
       Height = 17
       Caption = '&Pause on exceptions'
       Caption = '&Pause on exceptions'
-      TabOrder = 7
+      TabOrder = 8
     end
     end
     object RunAsDifferentUserCheck: TCheckBox
     object RunAsDifferentUserCheck: TCheckBox
       Left = 8
       Left = 8
-      Top = 176
+      Top = 196
       Width = 265
       Width = 265
       Height = 17
       Height = 17
       Caption = '*'
       Caption = '*'
-      TabOrder = 8
+      TabOrder = 9
     end
     end
     object ColorizeCompilerOutputCheck: TCheckBox
     object ColorizeCompilerOutputCheck: TCheckBox
       Left = 8
       Left = 8
-      Top = 196
+      Top = 216
       Width = 265
       Width = 265
       Height = 17
       Height = 17
       Caption = 'Colori&ze "Compiler Output" view'
       Caption = 'Colori&ze "Compiler Output" view'
-      TabOrder = 9
+      TabOrder = 10
     end
     end
     object OpenIncludedFilesCheck: TCheckBox
     object OpenIncludedFilesCheck: TCheckBox
       Left = 8
       Left = 8
-      Top = 56
+      Top = 76
       Width = 265
       Width = 265
       Height = 17
       Height = 17
       Caption = 'Automatically open #include files'
       Caption = 'Automatically open #include files'
+      TabOrder = 3
+    end
+    object ShowPreprocessorOutputCheck: TCheckBox
+      Left = 8
+      Top = 56
+      Width = 265
+      Height = 17
+      Caption = 'Automatically show preprocessor output'
       TabOrder = 2
       TabOrder = 2
     end
     end
   end
   end
   object GroupBox2: TGroupBox
   object GroupBox2: TGroupBox
     Left = 8
     Left = 8
-    Top = 248
+    Top = 254
     Width = 281
     Width = 281
     Height = 57
     Height = 57
     Anchors = [akLeft, akBottom]
     Anchors = [akLeft, akBottom]
@@ -135,7 +143,7 @@ object OptionsForm: TOptionsForm
     Left = 300
     Left = 300
     Top = 8
     Top = 8
     Width = 281
     Width = 281
-    Height = 297
+    Height = 303
     Anchors = [akLeft, akTop, akBottom]
     Anchors = [akLeft, akTop, akBottom]
     Caption = ' Editor '
     Caption = ' Editor '
     TabOrder = 2
     TabOrder = 2
@@ -275,7 +283,7 @@ object OptionsForm: TOptionsForm
   end
   end
   object OKButton: TButton
   object OKButton: TButton
     Left = 428
     Left = 428
-    Top = 317
+    Top = 323
     Width = 73
     Width = 73
     Height = 23
     Height = 23
     Anchors = [akLeft, akBottom]
     Anchors = [akLeft, akBottom]
@@ -286,7 +294,7 @@ object OptionsForm: TOptionsForm
   end
   end
   object CancelButton: TButton
   object CancelButton: TButton
     Left = 508
     Left = 508
-    Top = 317
+    Top = 323
     Width = 73
     Width = 73
     Height = 23
     Height = 23
     Anchors = [akLeft, akBottom]
     Anchors = [akLeft, akBottom]

+ 1 - 0
Projects/CompOptions.pas

@@ -50,6 +50,7 @@ type
     Label3: TNewStaticText;
     Label3: TNewStaticText;
     ThemeComboBox: TComboBox;
     ThemeComboBox: TComboBox;
     OpenIncludedFilesCheck: TCheckBox;
     OpenIncludedFilesCheck: TCheckBox;
+    ShowPreprocessorOutputCheck: TCheckBox;
     procedure AssocButtonClick(Sender: TObject);
     procedure AssocButtonClick(Sender: TObject);
     procedure ChangeFontButtonClick(Sender: TObject);
     procedure ChangeFontButtonClick(Sender: TObject);
     procedure FormCreate(Sender: TObject);
     procedure FormCreate(Sender: TObject);

+ 1 - 0
Projects/CompPreprocInt.pas

@@ -103,6 +103,7 @@ type
                                          ErrorProc with a description of the
                                          ErrorProc with a description of the
                                          error.}
                                          error.}
 
 
+    PreprocOutput: PChar;              { [out] Full preprocessor output. }
     PreprocCleanupProc: TPreprocCleanupProc;
     PreprocCleanupProc: TPreprocCleanupProc;
                                        { [out] Preprocessor-defined function
                                        { [out] Preprocessor-defined function
                                          that, if set, is called after
                                          that, if set, is called after

+ 28 - 19
Projects/CompScintEdit.pas

@@ -39,16 +39,24 @@ type
   TLineStateArray = array[0..0] of TLineState;
   TLineStateArray = array[0..0] of TLineState;
 
 
   TCompScintEdit = class(TScintEdit)
   TCompScintEdit = class(TScintEdit)
+  private
+    FTheme: TTheme;
+    FUsed: Boolean;
+  protected
+    procedure CreateWnd; override;
+  public
+    property Theme: TTheme read FTheme write FTheme;
+    property Used: Boolean read FUsed write FUsed;
+    procedure UpdateThemeColors;
+  end;
+
+  TCompScintFileEdit = class(TCompScintEdit)
   private
   private
     FBreakPoints: TList<Integer>;
     FBreakPoints: TList<Integer>;
     FCompilerFileIndex: Integer;
     FCompilerFileIndex: Integer;
     FFilename: String;
     FFilename: String;
     FFileLastWriteTime: TFileTime;
     FFileLastWriteTime: TFileTime;
     FSaveInUTF8Encoding: Boolean;
     FSaveInUTF8Encoding: Boolean;
-    FTheme: TTheme;
-    FUsed: Boolean;
-  protected
-    procedure CreateWnd; override;
   public
   public
     ErrorLine, ErrorCaretPosition: Integer;
     ErrorLine, ErrorCaretPosition: Integer;
     StepLine: Integer;
     StepLine: Integer;
@@ -61,27 +69,14 @@ type
     property CompilerFileIndex: Integer read FCompilerFileIndex write FCompilerFileIndex;
     property CompilerFileIndex: Integer read FCompilerFileIndex write FCompilerFileIndex;
     property FileLastWriteTime: TFileTime read FFileLastWriteTime write FFileLastWriteTime;
     property FileLastWriteTime: TFileTime read FFileLastWriteTime write FFileLastWriteTime;
     property SaveInUTF8Encoding: Boolean read FSaveInUTF8Encoding write FSaveInUTF8Encoding;
     property SaveInUTF8Encoding: Boolean read FSaveInUTF8Encoding write FSaveInUTF8Encoding;
-    property Theme: TTheme read FTheme write FTheme;
-    property Used: Boolean read FUsed write FUsed;
-    procedure UpdateThemeColors;
   end;
   end;
 
 
 implementation
 implementation
 
 
 uses
 uses
   ScintInt;
   ScintInt;
-
-constructor TCompScintEdit.Create;
-begin
-  inherited;
-  FBreakPoints := TList<Integer>.Create;
-end;
-
-destructor TCompScintEdit.Destroy;
-begin
-  FBreakPoints.Free;
-  inherited;
-end;
+  
+{ TCompScintEdit }
 
 
 procedure TCompScintEdit.CreateWnd;
 procedure TCompScintEdit.CreateWnd;
 const
 const
@@ -210,4 +205,18 @@ begin
   end;
   end;
 end;
 end;
 
 
+{ TCompScintFileEdit }
+
+constructor TCompScintFileEdit.Create;
+begin
+  inherited;
+  FBreakPoints := TList<Integer>.Create;
+end;
+
+destructor TCompScintFileEdit.Destroy;
+begin
+  FBreakPoints.Free;
+  inherited;
+end;
+
 end.
 end.

+ 97 - 62
Projects/Compile.pas

@@ -187,7 +187,10 @@ type
     WarningsList: THashStringList;
     WarningsList: THashStringList;
     ExpectedCustomMessageNames: TStringList;
     ExpectedCustomMessageNames: TStringList;
     MissingRunOnceIdsWarning, MissingRunOnceIds, UsedUserAreasWarning: Boolean;
     MissingRunOnceIdsWarning, MissingRunOnceIds, UsedUserAreasWarning: Boolean;
-    UsedUserAreas, PreprocIncludedFilenames: TStringList;
+    UsedUserAreas: TStringList;
+
+    PreprocIncludedFilenames: TStringList;
+    PreprocOutput: String;
 
 
     DefaultLangData: TLangData;
     DefaultLangData: TLangData;
     {$IFDEF UNICODE} PreLangDataList, {$ENDIF} LangDataList: TList;
     {$IFDEF UNICODE} PreLangDataList, {$ENDIF} LangDataList: TList;
@@ -1050,9 +1053,12 @@ end;
 type
 type
   EBuiltinPreprocessScriptError = class(Exception);
   EBuiltinPreprocessScriptError = class(Exception);
 
 
+var
+  LastBuiltinPreprocOutput: String;
+
 function BuiltinPreprocessScript(var Params: TPreprocessScriptParams): Integer; stdcall;
 function BuiltinPreprocessScript(var Params: TPreprocessScriptParams): Integer; stdcall;
 var
 var
-  IncludeStack: TStringList;
+  Output, IncludeStack: TStringList;
 
 
   procedure RaiseError(const LineFilename: String; const LineNumber: Integer;
   procedure RaiseError(const LineFilename: String; const LineNumber: Integer;
     const Msg: String);
     const Msg: String);
@@ -1134,9 +1140,11 @@ var
       SkipWhitespace(L);
       SkipWhitespace(L);
       if L^ = '#' then
       if L^ = '#' then
         ProcessDirective(Filename, I + 1, L + 1)
         ProcessDirective(Filename, I + 1, L + 1)
-      else
+      else begin
         Params.LineOutProc(Params.CompilerData, PChar(Filename), I + 1,
         Params.LineOutProc(Params.CompilerData, PChar(Filename), I + 1,
           LineText);
           LineText);
+        Output.Add(LineText);
+      end;
       Inc(I);
       Inc(I);
     end;
     end;
     IncludeStack.Delete(IncludeStack.Count-1);
     IncludeStack.Delete(IncludeStack.Count-1);
@@ -1150,11 +1158,16 @@ begin
   end;
   end;
 
 
   try
   try
-    IncludeStack := TStringList.Create;
+    Output := TStringList.Create;
+    IncludeStack := nil;
     try
     try
+      IncludeStack := TStringList.Create;
       ProcessLines(Params.Filename, 0);
       ProcessLines(Params.Filename, 0);
     finally
     finally
+      LastBuiltinPreprocOutput := Output.Text;
+      Params.PreprocOutput := PChar(LastBuiltinPreprocOutput);
       IncludeStack.Free;
       IncludeStack.Free;
+      Output.Free;
     end;
     end;
     Result := ispeSuccess;
     Result := ispeSuccess;
   except
   except
@@ -2074,6 +2087,7 @@ function TSetupCompiler.ReadScriptFile(const Filename: String;
           AddStatus(SCompilerStatusPreprocessing);
           AddStatus(SCompilerStatusPreprocessing);
         ResultCode := PreProc(Params);
         ResultCode := PreProc(Params);
         if Filename = '' then begin
         if Filename = '' then begin
+          PreprocOutput := Params.PreprocOutput;
           { Defer cleanup of main script until after compilation }
           { Defer cleanup of main script until after compilation }
           PreprocCleanupProcData := Params.PreprocCleanupProcData;
           PreprocCleanupProcData := Params.PreprocCleanupProcData;
           PreprocCleanupProc := Params.PreprocCleanupProc;
           PreprocCleanupProc := Params.PreprocCleanupProc;
@@ -9152,47 +9166,85 @@ begin
   end;
   end;
 end;
 end;
 
 
-{ Interface helper functions }
+{ Interface functions }
 
 
-function CheckParams(const Params: TCompileScriptParamsEx): Boolean;
-begin
-  Result := ((Params.Size = SizeOf(Params)) or
-             (Params.Size = SizeOf(TCompileScriptParams))) and
-            Assigned(Params.CallbackProc);
-end;
+function ISCompileScript(const Params: TCompileScriptParamsEx;
+  const PropagateExceptions: Boolean): Integer;
 
 
-procedure InitializeSetupCompiler(const SetupCompiler: TSetupCompiler;
-  const Params: TCompileScriptParamsEx);
-begin
-  SetupCompiler.AppData := Params.AppData;
-  SetupCompiler.CallbackProc := Params.CallbackProc;
-  if Assigned(Params.CompilerPath) then
-    SetupCompiler.CompilerDir := Params.CompilerPath
-  else
-    SetupCompiler.CompilerDir := PathExtractPath(GetSelfFilename);
-  SetupCompiler.SourceDir := Params.SourcePath;
-end;
+  function CheckParams(const Params: TCompileScriptParamsEx): Boolean;
+  begin
+    Result := ((Params.Size = SizeOf(Params)) or
+               (Params.Size = SizeOf(TCompileScriptParams))) and
+              Assigned(Params.CallbackProc);
+  end;
 
 
-function EncodeIncludedFilenames(const IncludedFilenames: TStringList): String;
-var
-  S: String;
-  I: Integer;
-begin
-  S := '';
-  for I := 0 to IncludedFilenames.Count-1 do
-   S := S + IncludedFilenames[I] + #0;
-  Result := S;
-end;
+  procedure InitializeSetupCompiler(const SetupCompiler: TSetupCompiler;
+    const Params: TCompileScriptParamsEx);
+  begin
+    SetupCompiler.AppData := Params.AppData;
+    SetupCompiler.CallbackProc := Params.CallbackProc;
+    if Assigned(Params.CompilerPath) then
+      SetupCompiler.CompilerDir := Params.CompilerPath
+    else
+      SetupCompiler.CompilerDir := PathExtractPath(GetSelfFilename);
+    SetupCompiler.SourceDir := Params.SourcePath;
+  end;
 
 
-{ Interface functions }
+  function EncodeIncludedFilenames(const IncludedFilenames: TStringList): String;
+  var
+    S: String;
+    I: Integer;
+  begin
+    S := '';
+    for I := 0 to IncludedFilenames.Count-1 do
+     S := S + IncludedFilenames[I] + #0;
+    Result := S;
+  end;
+
+  procedure NotifyPreproc(const SetupCompiler: TSetupCompiler);
+  var
+    Data: TCompilerCallbackData;
+    S: String;
+  begin
+    Data.PreprocessedScript := PChar(SetupCompiler.PreprocOutput);
+    S := EncodeIncludedFilenames(SetupCompiler.PreprocIncludedFilenames);
+    Data.IncludedFilenames := PChar(S);
+    Params.CallbackProc(iscbNotifyPreproc, Data, Params.AppData);
+  end;
+
+  procedure NotifySuccess(const SetupCompiler: TSetupCompiler);
+  var
+    Data: TCompilerCallbackData;
+  begin
+    Data.OutputExeFilename := PChar(SetupCompiler.ExeFilename);
+    Data.DebugInfo := SetupCompiler.DebugInfo.Memory;
+    Data.DebugInfoSize := SetupCompiler.DebugInfo.Size;
+    Data.PreprocessedScript := PChar(SetupCompiler.PreprocOutput);
+    Params.CallbackProc(iscbNotifySuccess, Data, Params.AppData);
+  end;
+
+  procedure NotifyError(const SetupCompiler: TSetupCompiler);
+  var
+    Data: TCompilerCallbackData;
+    S: String;
+  begin
+    Data.ErrorMsg := nil;
+    Data.ErrorFilename := nil;
+    Data.ErrorLine := 0;
+    if not(ExceptObject is EAbort) then begin
+      S := GetExceptMessage;
+      Data.ErrorMsg := PChar(S);
+      { use a Pointer cast instead of PChar so that we'll get a null
+        pointer if the string is empty }
+      Data.ErrorFilename := Pointer(SetupCompiler.LineFilename);
+      Data.ErrorLine := SetupCompiler.LineNumber;
+    end;
+    Params.CallbackProc(iscbNotifyError, Data, Params.AppData);
+  end;
 
 
-function ISCompileScript(const Params: TCompileScriptParamsEx;
-  const PropagateExceptions: Boolean): Integer;
 var
 var
   SetupCompiler: TSetupCompiler;
   SetupCompiler: TSetupCompiler;
   P: PChar;
   P: PChar;
-  Data: TCompilerCallbackData;
-  S: String;
   P2: Integer;
   P2: Integer;
 begin
 begin
   if not CheckParams(Params) then begin
   if not CheckParams(Params) then begin
@@ -9251,37 +9303,20 @@ begin
       end;
       end;
     end;
     end;
 
 
-    Result := isceNoError;
     try
     try
-      SetupCompiler.Compile;
+      try
+        SetupCompiler.Compile;
+      finally
+        NotifyPreproc(SetupCompiler);
+      end;
+      Result := isceNoError;
+      NotifySuccess(SetupCompiler);
     except
     except
       Result := isceCompileFailure;
       Result := isceCompileFailure;
-      S := EncodeIncludedFilenames(SetupCompiler.PreprocIncludedFilenames);
-      Data.IncludedFilenames := PChar(S);
-      Params.CallbackProc(iscbNotifyIncludedFiles, Data, Params.AppData);
-      Data.ErrorMsg := nil;
-      Data.ErrorFilename := nil;
-      Data.ErrorLine := 0;
-      if not(ExceptObject is EAbort) then begin
-        S := GetExceptMessage;
-        Data.ErrorMsg := PChar(S);
-        { use a Pointer cast instead of PChar so that we'll get a null
-          pointer if the string is empty }
-        Data.ErrorFilename := Pointer(SetupCompiler.LineFilename);
-        Data.ErrorLine := SetupCompiler.LineNumber;
-      end;
-      Params.CallbackProc(iscbNotifyError, Data, Params.AppData);
+      NotifyError(SetupCompiler);
       if PropagateExceptions then
       if PropagateExceptions then
         raise;
         raise;
-      Exit;
     end;
     end;
-    S := EncodeIncludedFilenames(SetupCompiler.PreprocIncludedFilenames);
-    Data.IncludedFilenames := PChar(S);
-    Params.CallbackProc(iscbNotifyIncludedFiles, Data, Params.AppData);
-    Data.OutputExeFilename := PChar(SetupCompiler.ExeFilename);
-    Data.DebugInfo := SetupCompiler.DebugInfo.Memory;
-    Data.DebugInfoSize := SetupCompiler.DebugInfo.Size;
-    Params.CallbackProc(iscbNotifySuccess, Data, Params.AppData);
   finally
   finally
     SetupCompiler.Free;
     SetupCompiler.Free;
   end;
   end;

+ 1 - 1
Projects/ISCmplr.dpr

@@ -51,7 +51,7 @@ type
     LastLineRead: String;
     LastLineRead: String;
   end;
   end;
 
 
-{ Does not support iscbNotifyIncludedFiles }
+{ Does not support iscbNotifyPreproc }
 function WrapperCallbackProc(Code: Integer; var Data: TCompilerCallbackData;
 function WrapperCallbackProc(Code: Integer; var Data: TCompilerCallbackData;
   AppData: Longint): Integer;
   AppData: Longint): Integer;
 stdcall;
 stdcall;

+ 5 - 0
Projects/ISPP/IsppPreprocess.pas

@@ -19,6 +19,9 @@ uses
   SysUtils, CmnFunc2, PathFunc,
   SysUtils, CmnFunc2, PathFunc,
   IsppBase, IsppTranslate, IsppSessions, IsppIntf, IsppIdentMan, IsppVarUtils, IsppConsts;
   IsppBase, IsppTranslate, IsppSessions, IsppIntf, IsppIdentMan, IsppVarUtils, IsppConsts;
 
 
+var
+  LastPreprocOutput: string;
+
 procedure ReadScript(const Params: TPreprocessScriptParams;
 procedure ReadScript(const Params: TPreprocessScriptParams;
   const Preprocessor: TPreprocessor);
   const Preprocessor: TPreprocessor);
 var
 var
@@ -275,6 +278,8 @@ begin
         Result := ispeSuccess;
         Result := ispeSuccess;
       end;
       end;
     finally
     finally
+      LastPreprocOutput := Preprocessor.GetAll;
+      Params.PreprocOutput := PChar(LastPreprocOutput);
       Preprocessor.Free;
       Preprocessor.Free;
     end;
     end;
   except
   except

+ 6 - 0
Projects/ISPP/IsppTranslate.pas

@@ -123,6 +123,7 @@ type
     procedure StatusMsg(const Msg: string; const Args: array of const);
     procedure StatusMsg(const Msg: string; const Args: array of const);
     procedure WarningMsg(const Msg: string; const Args: array of const);
     procedure WarningMsg(const Msg: string; const Args: array of const);
     procedure AddLine(const LineRead: string);
     procedure AddLine(const LineRead: string);
+    function GetAll: String;
     function GetFileName(Code: Integer): string;
     function GetFileName(Code: Integer): string;
     function GetLineNumber(Code: Integer): Word;
     function GetLineNumber(Code: Integer): Word;
     function GetNext(var LineFilename: string; var LineNumber: Integer;
     function GetNext(var LineFilename: string; var LineNumber: Integer;
@@ -298,6 +299,11 @@ begin
   Inc(FMainCounter, 1);
   Inc(FMainCounter, 1);
 end;
 end;
 
 
+function TPreprocessor.GetAll: String;
+begin
+  Result := FOutput.Text;
+end;
+
 function TPreprocessor.GetFileName(Code: Integer): string;
 function TPreprocessor.GetFileName(Code: Integer): string;
 begin
 begin
   if Code = -1 then
   if Code = -1 then

+ 1 - 0
whatsnew.htm

@@ -42,6 +42,7 @@ For conditions of distribution and use, see <a href="https://jrsoftware.org/file
 <p><span class="head2">Compiler IDE updates</span></p>
 <p><span class="head2">Compiler IDE updates</span></p>
 <p>Various improvements have been made to the Compiler IDE:</p>
 <p>Various improvements have been made to the Compiler IDE:</p>
 <ul>
 <ul>
+  <li>If the script uses Inno Setup Preprocessor (ISPP) functionality, the Compiler IDE now automatically <a href="https://i.imgur.com/IVI2nk3.png">shows the preprocessor output</a> in a tab so you can check it. This can be turned off in the options.</li>
   <li>The Compiler IDE now automatically opens (up to 10) <tt>#include</tt> files in tabs which allow you to <a href="https://i.imgur.com/iDrhOSs.png">edit and debug</a> these files from within the Compiler IDE. The list of <tt>#include</tt> files is updated after opening a new main file and after each compilation. This can be turned off in the options. If the option is not turned off, a new <i>Save All</i> menu item is added to the <i>File</i> menu.</li>
   <li>The Compiler IDE now automatically opens (up to 10) <tt>#include</tt> files in tabs which allow you to <a href="https://i.imgur.com/iDrhOSs.png">edit and debug</a> these files from within the Compiler IDE. The list of <tt>#include</tt> files is updated after opening a new main file and after each compilation. This can be turned off in the options. If the option is not turned off, a new <i>Save All</i> menu item is added to the <i>File</i> menu.</li>
   <li>If <tt>#include</tt> files are modified since last compile, the script is now automatically re-compiled before running it. This works even if the option to automatically open <tt>#include</tt> files is turned off.</li>
   <li>If <tt>#include</tt> files are modified since last compile, the script is now automatically re-compiled before running it. This works even if the option to automatically open <tt>#include</tt> files is turned off.</li>
   <li>Added new topic to the help file explaining the various <a href="https://jrsoftware.org/ishelp/index.php?topic=scriptdebug">integrated debugger menu items</a> in the <i>Run</i> menu which can be used to debug your [Code] section.</li>
   <li>Added new topic to the help file explaining the various <a href="https://jrsoftware.org/ishelp/index.php?topic=scriptdebug">integrated debugger menu items</a> in the <i>Run</i> menu which can be used to debug your [Code] section.</li>