unit MDIForm;

{To compile without RX Library uncomment next UNDEF}
{$UNDEF USE_RX_LIB}
{$IFNDEF WIN32}
 {$UNDEF USE_RX_LIB}
{$ENDIF}
{$IFNDEF VER140}
 {$UNDEF USE_RX_LIB}
{$ENDIF}

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls, ToolWin, ecSyntAnal, ecPopupCtrl, ecPrint,
  ecSyntDlg, ecKeyMap, Menus, ImgList, ecActns, StdActns, ActnList,
  {$IFDEF USE_RX_LIB} MRUList, Placemnt, {$ENDIF}
  {$IFNDEF WIN32} Variants, System.ComponentModel, {$ENDIF}
  ExtCtrls, ecSyntTree, ecSyntMemo, ecStylesCombo, ecPropManager,
  ecAutoReplace;

type
  TMDIMain = class(TForm)
    SyntaxTreeView1: TSyntaxTreeView;
    Splitter1: TSplitter;
    ActionList1: TActionList;
    actOpen: TAction;
    actSave: TAction;
    actNewFile: TAction;
    actSaveAs: TAction;
    ecFullExpand1: TecFullExpand;
    EditPaste1: TEditPaste;
    EditSelectAll1: TEditSelectAll;
    EditUndo1: TEditUndo;
    EditDelete1: TEditDelete;
    EditCopy1: TEditCopy;
    EditCut1: TEditCut;
    ecCommandRedo: TecCommandAction;
    ecCommandAction1: TecCommandAction;
    ecCommandAction2: TecCommandAction;
    ecFullCollapse1: TecFullCollapse;
    ecCopyAsRTF1: TecCopyAsRTF;
    ecCommandAction3: TecCommandAction;
    HelpContents1: THelpContents;
    ecSearch1: TecSearch;
    ecSearchAgain1: TecSearchAgain;
    ecReplace1: TecReplace;
    ecUserRangeDelete1: TecUserRangeDelete;
    ecUserRangeCollapsable1: TecUserRangeCollapsable;
    ecUserRangeTopLine1: TecUserRangeTopLine;
    ecUserRangeBottomLine1: TecUserRangeBottomLine;
    ecUserRangeLineHighlight1: TecUserRangeLineHighlight;
    ecPrintAction1: TecPrintAction;
    ecPreviewAction1: TecPreviewAction;
    ecExportRTFAction1: TecExportRTFAction;
    ecExportHTMLAction1: TecExportHTMLAction;
    ecCustomizeEditorOptionsAction1: TecCustomizeEditorOptionsAction;
    ecCustomizeSyntaxHighlightingAction1: TecCustomizeSyntaxHighlightingAction;
    ecCustomizeLexerPropertiesAction1: TecCustomizeLexerPropertiesAction;
    ecCustomizeKeyMappingAction1: TecCustomizeKeyMappingAction;
    ecCustomizeUserStylesAction1: TecCustomizeUserStylesAction;
    ImageList1: TImageList;
    MainMenu1: TMainMenu;
    File1: TMenuItem;
    New1: TMenuItem;
    Open1: TMenuItem;
    Save1: TMenuItem;
    Saveas1: TMenuItem;
    Reopen1: TMenuItem;
    N9: TMenuItem;
    ExportRTF1: TMenuItem;
    ExportHTML1: TMenuItem;
    N11: TMenuItem;
    PageSetup1: TMenuItem;
    PrintSetup1: TMenuItem;
    actPrintPreview1: TMenuItem;
    Print1: TMenuItem;
    N1: TMenuItem;
    Exit1: TMenuItem;
    View1: TMenuItem;
    actShowNonPrinted1: TMenuItem;
    Wordwrap1: TMenuItem;
    N10: TMenuItem;
    FullExpand1: TMenuItem;
    FullCollapse1: TMenuItem;
    CollapseSelection1: TMenuItem;
    N12: TMenuItem;
    SynchronizeTree1: TMenuItem;
    Edit1: TMenuItem;
    Undo1: TMenuItem;
    Redo1: TMenuItem;
    N3: TMenuItem;
    Copy1: TMenuItem;
    Cut1: TMenuItem;
    Paste1: TMenuItem;
    Delete1: TMenuItem;
    CopyasRTF1: TMenuItem;
    N2: TMenuItem;
    Action11: TMenuItem;
    Findnext1: TMenuItem;
    Replace1: TMenuItem;
    N4: TMenuItem;
    SelectAll1: TMenuItem;
    SelLexMenu: TMenuItem;
    Options1: TMenuItem;
    EditorProperties1: TMenuItem;
    actCustomize1: TMenuItem;
    SyntaxHighlignting2: TMenuItem;
    LexerLibrary1: TMenuItem;
    KeyMapping1: TMenuItem;
    Userstyles1: TMenuItem;
    N8: TMenuItem;
    Contents1: TMenuItem;
    N5: TMenuItem;
    About1: TMenuItem;
    SyntKeyMapping1: TSyntKeyMapping;
    SyntaxManager1: TSyntaxManager;
    SyntReplaceDialog1: TSyntReplaceDialog;
    SyntFindDialog1: TSyntFindDialog;
    OD: TOpenDialog;
    SD: TSaveDialog;
    ecSyntPrinter1: TecSyntPrinter;
    SyntStyles1: TSyntStyles;
    PrinterSetupDialog1: TPrinterSetupDialog;
    ToolBar1: TToolBar;
    ToolButton1: TToolButton;
    ToolButton2: TToolButton;
    ToolButton33: TToolButton;
    ToolButton18: TToolButton;
    ToolButton5: TToolButton;
    ToolButton7: TToolButton;
    ToolButton8: TToolButton;
    ToolButton9: TToolButton;
    ToolButton3: TToolButton;
    ToolButton4: TToolButton;
    ToolButton6: TToolButton;
    ToolButton10: TToolButton;
    ToolButton12: TToolButton;
    ToolButton19: TToolButton;
    ToolButton20: TToolButton;
    ToolButton21: TToolButton;
    ToolButton11: TToolButton;
    ToolButton16: TToolButton;
    ToolButton14: TToolButton;
    ToolButton13: TToolButton;
    ToolButton15: TToolButton;
    ToolButton32: TToolButton;
    ToolButton17: TToolButton;
    ToolButton23: TToolButton;
    ToolButton26: TToolButton;
    ToolButton28: TToolButton;
    ToolButton24: TToolButton;
    ToolButton25: TToolButton;
    ToolButton27: TToolButton;
    ToolButton31: TToolButton;
    ToolButton30: TToolButton;
    WindowCascade1: TWindowCascade;
    WindowTileHorizontal1: TWindowTileHorizontal;
    WindowTileVertical1: TWindowTileVertical;
    WindowMinimizeAll1: TWindowMinimizeAll;
    WindowArrange1: TWindowArrange;
    Window1: TMenuItem;
    Cascade1: TMenuItem;
    ileHorizontally1: TMenuItem;
    ileVertically1: TMenuItem;
    N6: TMenuItem;
    MinimizeAll1: TMenuItem;
    Arrange1: TMenuItem;
    UserStylesCombo1: TUserStylesCombo;
    SB: TStatusBar;
    SyntaxMemo1: TSyntaxMemo;
    PropsManager1: TPropsManager;
    ecToggleNonPrinted1: TecToggleNonPrinted;
    ecToggleWordWrap1: TecToggleWordWrap;
    ecToggleSyntTreeSync1: TecToggleSyntTreeSync;
    ecCustomizeLexerLib1: TecCustomizeLexerLib;
    FileExit1: TFileExit;
    PropsManager2: TPropsManager;
    SyntAutoReplace1: TSyntAutoReplace;
    ecIncrementalSearch1: TecIncrementalSearch;
    IncrementalSearch1: TMenuItem;
    ToolButton22: TToolButton;
    FilePrintSetup1: TFilePrintSetup;
    ecPageSetupAction1: TecPageSetupAction;
    ecCustomizeAutoReplace1: TecCustomizeAutoReplace;
    CustomizeAutoReplace1: TMenuItem;
    procedure FormShow(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure actOpenExecute(Sender: TObject);
    procedure actSaveExecute(Sender: TObject);
    procedure About1Click(Sender: TObject);
    procedure FormResize(Sender: TObject);
    procedure actNewFileExecute(Sender: TObject);
    procedure actSaveUpdate(Sender: TObject);
    procedure actSaveAsExecute(Sender: TObject);
    procedure UpdateStatus(Sender: TObject);
    procedure ecCustomizeEditorOptionsAction1ExecuteOK(Sender: TObject);
    procedure SyntaxManager1LexerChanged(Sender: TObject);
    procedure SyntaxMemo1IncSearchChange(Sender: TObject;
      State: TIncSearchState);
    procedure SyntFindDialog1AfterExecute(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  private
    procedure OpenFile(AFileName: string);
    function IsActive: Boolean;
    {$IFDEF USE_RX_LIB}
  private
    FormPlacement: TFormPlacement;
    MRU: TMRUManager;
    procedure MRUClick(Sender: TObject; const RecentName, Caption: String;
      UserData: Integer);
  public
    constructor Create(AOwner: TComponent); override;
    {$ENDIF}
  public
    procedure ChildChanged;
  end;

var
  MDIMain: TMDIMain;

implementation

uses ChildForm, ecEditorAbout, ecCustEditDlg;

{$R *.dfm}

{ TMDIMain }

{$IFDEF USE_RX_LIB}
constructor TMDIMain.Create(AOwner: TComponent);
begin
  inherited;
  FormPlacement := TFormPlacement.Create(Self);
  FormPlacement.Name := 'FormPlacement';
  FormPlacement.IniFileName := ChangeFileExt(Application.ExeName, '.ini');
  FormPlacement.IniSection := 'MainForm';
  MRU := TMRUManager.Create(Self);
  MRU.Name := 'MRU';
  MRU.AccelDelimiter := adSpace;
  MRU.Capacity := 9;
  MRU.RecentMenu := Reopen1;
  MRU.OnClick := MRUClick;
  MRU.IniStorage := FormPlacement;
  Reopen1.Visible := True;
  FormPlacement.RestoreFormPlacement;
end;

procedure TMDIMain.MRUClick(Sender: TObject; const RecentName,
  Caption: String; UserData: Integer);
begin
  OpenFile(RecentName);
end;
{$ENDIF}

procedure TMDIMain.FormShow(Sender: TObject);
var s: string;
begin
  PropsManager1.LoadProps;
  PropsManager2.LoadProps;
  s := ExtractFilePath(Application.ExeName) + 'LexLib.LXL';
  if FileExists(s) then
   SyntaxManager1.LoadFromFile(s);
  s := ChangeFileExt(Application.ExeName, '.ecs');
  if FileExists(s) then
   SyntStyles1.LoadFromFile(s);
  s := ChangeFileExt(Application.ExeName, '.ari');
  if FileExists(s) then
   SyntAutoReplace1.Items.LoadFromFile(s);
  if ParamCount > 0 then
   OpenFile(ParamStr(1));
end;

procedure TMDIMain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
{$IFDEF USE_RX_LIB}
  FormPlacement.SaveFormPlacement;
{$ENDIF}
  SyntStyles1.SaveToFile(ChangeFileExt(Application.ExeName, '.ecs'));
  SyntAutoReplace1.Items.SaveToFile(ChangeFileExt(Application.ExeName, '.ari'));
  PropsManager1.SaveProps;
  PropsManager2.SaveProps;
end;

function TMDIMain.IsActive: Boolean;
begin
  Result := (ActiveMDIChild <> nil) and (ActiveMDIChild is TEditorForm);
end;

procedure TMDIMain.OpenFile(AFileName: string);
var child: TEditorForm;
begin
  child := TEditorForm.Create(Self);
  child.Editor.OnChange := UpdateStatus;
  child.Editor.OnCaretPosChanged := UpdateStatus;
  child.Editor.OnIncSearchChange := SyntaxMemo1IncSearchChange;
  if FileExists(AFileName) then
   begin
    child.Editor.LoadFromFile(AFileName);
    child.Editor.SyntaxAnalyzer := SyntaxManager1.AnalyzerForFile(AFileName);
   end;
  SyntaxManager1.CurrentLexer := child.Editor.SyntaxAnalyzer;
  child.Caption := AFileName;
{$IFDEF USE_RX_LIB}
  if AFileName <> '' then
    MRU.Add(AFileName, 0);
{$ENDIF}
end;

procedure TMDIMain.actOpenExecute(Sender: TObject);
begin
  OD.Filter := SyntaxManager1.GetFilesFilter;
  if OD.Execute then
   OpenFile(OD.FileName);
end;

procedure TMDIMain.actSaveUpdate(Sender: TObject);
begin
  actSave.Enabled := IsActive and
                     (ActiveMDIChild as TEditorForm).Editor.Modified;
end;

procedure TMDIMain.actSaveExecute(Sender: TObject);
begin
  if IsActive then
   with (ActiveMDIChild as TEditorForm) do
    begin
      if Caption <> '' then
        Editor.SaveToFile(Caption)
      else actSaveAsExecute(nil);
    end;
end;

procedure TMDIMain.actSaveAsExecute(Sender: TObject);
begin
  if IsActive then
   with (ActiveMDIChild as TEditorForm) do
    begin
      SD.Filter := SyntaxManager1.GetFilesFilter;
      SD.FileName := Caption;
      if SD.Execute then
       begin
        Editor.SaveToFile(SD.FileName);
        Caption := SD.FileName;
      {$IFDEF USE_RX_LIB}
        MRU.Add(SD.FileName, 0);
      {$ENDIF}
       end;
    end;
end;

procedure TMDIMain.actNewFileExecute(Sender: TObject);
begin
  OpenFile('Untitled');
end;

procedure TMDIMain.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
var i: integer;
begin
  for i := 0 to MDIChildCount - 1 do
   if MDIChildren[i] is TEditorForm then
    with MDIChildren[i] as TEditorForm do
     if Editor.Modified then
       case MessageDlg('Save changes to ' + Caption + '?', mtConfirmation, [mbYes, mbNo, mbCancel], 0) of
        IDYES:  Editor.SaveToFile(Caption);
        IDCANCEL: begin
                   CanClose := False;
                   Exit;
                  end;
       end;
end;

procedure TMDIMain.About1Click(Sender: TObject);
begin
  TAboutForm.Create(Self).ShowModal;
end;

procedure TMDIMain.FormResize(Sender: TObject);
begin
  if SyntaxTreeView1.Width = 0 then
   SyntaxTreeView1.Left := -1;
end;

procedure TMDIMain.ChildChanged;
var memo: TCustomSyntaxMemo;
begin
  SelLexMenu.Enabled := IsActive;
  if SelLexMenu.Enabled then
    begin
      memo := (ActiveMDIChild as TEditorForm).Editor;
      if memo = SyntaxTreeView1.SyntaxMemo then Exit;
      SyntaxManager1.CurrentLexer := memo.SyntaxAnalyzer;
      SyntaxTreeView1.SyntaxMemo := memo;
      ecSyntPrinter1.SyntMemo := memo;
      UserStylesCombo1.Editor := memo;
      UpdateStatus(nil);
      PropsManager1.Add(memo);
    end;
end;

procedure TMDIMain.UpdateStatus(Sender: TObject);
begin
  if IsActive then
  with (ActiveMDIChild as TEditorForm).Editor do
   begin
     SB.Panels[0].Text := Format('  %d: %d', [CaretPos.X, CaretPos.Y]);
     if Modified then  SB.Panels[1].Text := 'Modified'
                 else  SB.Panels[1].Text := '';
     if ReplaceMode then SB.Panels[2].Text := 'Overwrite'
                    else SB.Panels[2].Text := 'Insert';
   end;
end;

procedure TMDIMain.SyntaxMemo1IncSearchChange(Sender: TObject;
  State: TIncSearchState);
begin
  if State <> isStop then
   SB.SimpleText := 'Search for: ' + SyntaxMemo1.IncSearchStr
  else
   SB.SimpleText := '';
  SB.SimplePanel := State <> isStop;
end;

procedure TMDIMain.ecCustomizeEditorOptionsAction1ExecuteOK(
  Sender: TObject);
begin
  PropsManager1.UpdateAll;
end;

procedure TMDIMain.SyntaxManager1LexerChanged(Sender: TObject);
begin
  if IsActive then
   (ActiveMDIChild as TEditorForm).Editor.SyntaxAnalyzer := SyntaxManager1.CurrentLexer;
end;

procedure TMDIMain.SyntFindDialog1AfterExecute(Sender: TObject);
begin
  // Synchronize incremental search with Find Dialog
  SyntaxMemo1.IncSearchBack := ftBackward in SyntFindDialog1.Flags;
  SyntaxMemo1.IncSearchIgnoreCase := not (ftCaseSensitive in SyntFindDialog1.Flags);
  PropsManager1.UpdateAll;
end;

end.
