unit Form_RegExpCalculator;

{$I _crw_sysdef}

{$IFDEF FPC}{$mode Delphi}{$ENDIF}{$H+}

interface

uses
 _crw_sharemem, // NB: THIS UNIT MUST BE FIRST !!!
 {$IFDEF UNIX} cthreads, dl, {$ENDIF}
 {$IFDEF WINDOWS} windows, {$ENDIF}
 sysutils, classes, math, graphics, controls, forms, dialogs, stdctrls, buttons,
 extctrls, comctrls, checklst, spin, imglist, clipbrd, lcltype, lclproc, lclintf,
   Form_TextEditDialog,
 _crw_alloc, _crw_rtc, _crw_str, _crw_fio, _crw_eldraw, _crw_ef, _crw_plut,
 _crw_utf8, _crw_regexp, _crw_appforms, _crw_apptools;

type
  TFormRegExpCalculator = class(TMasterForm)
    PanelRexMain: TPanel;
    PageControlRexMain: TPageControl;
    TabSheetRexPattern: TTabSheet;
    GroupBoxRexPattern: TGroupBox;
    GroupBoxRexInput: TGroupBox;
    GroupBoxRexResult: TGroupBox;
    GroupBoxRexLog: TGroupBox;
    TabSheetRexSettings: TTabSheet;
    GroupBoxRexEngine: TGroupBox;
    GroupBoxRexModifiers: TGroupBox;
    PanelRexSettingsButtons: TPanel;
    BitBtnRexSettingsApply: TBitBtn;
    TimerRexSettings: TTimer;
    TabSheetRexCheatSheet: TTabSheet;
    GroupBoxRexCheatSheet: TGroupBox;
    ScrollBoxRexCheatSheet: TScrollBox;
    ImageRexCheatSheet: TImage;
    BitBtnRexCheatSheetComments: TBitBtn;
    TimerRexMain: TTimer;
    PanelRexInputButtons: TPanel;
    BitBtnRexInputClear: TBitBtn;
    BitBtnRexInputCopy: TBitBtn;
    BitBtnRexInputCut: TBitBtn;
    BitBtnRexInputPaste: TBitBtn;
    BitBtnRexInputSelectAll: TBitBtn;
    BitBtnRexInputUnselect: TBitBtn;
    PanelRexResultButtons: TPanel;
    BitBtnRexResultClear: TBitBtn;
    BitBtnRexResultCopy: TBitBtn;
    BitBtnRexResultSelectAll: TBitBtn;
    BitBtnRexResultUnselect: TBitBtn;
    PanelRexLogButtons: TPanel;
    BitBtnRexLogClear: TBitBtn;
    BitBtnRexLogCopy: TBitBtn;
    BitBtnRexLogSelectAll: TBitBtn;
    BitBtnRexLogUnselect: TBitBtn;
    BitBtnRexInputUndo: TBitBtn;
    GroupBoxRexBenchmark: TGroupBox;
    GroupBoxRexDump: TGroupBox;
    PanelRexDumpButtons: TPanel;
    BitBtnRexDumpClear: TBitBtn;
    BitBtnRexDumpCopy: TBitBtn;
    BitBtnRexDumpSelectAll: TBitBtn;
    BitBtnRexDumpUnselect: TBitBtn;
    BitBtnRexDumpCode: TBitBtn;
    BitBtnRexDumpData: TBitBtn;
    ImageListRex32: TImageList;
    ImageListRex16: TImageList;
    PanelRexDumpContent: TPanel;
    MemoRexDump: TMemo;
    PanelRexModifiersContent: TPanel;
    CheckListBoxRexModifiers: TCheckListBox;
    PanelRexBenchmarkContent: TPanel;
    CheckBoxRexBenchmark: TCheckBox;
    SpinEditRexBenchmark: TSpinEdit;
    LabelRexBenchmarkMs: TLabel;
    PanelRexEngineContent: TPanel;
    LabelRexEngine: TLabel;
    ComboBoxRexEngine: TComboBox;
    LabelRexExecMax: TLabel;
    SpinEditRexExecMax: TSpinEdit;
    LabelRexExecMaxComment: TLabel;
    RadioGroupRexClose: TRadioGroup;
    LabelRexUseSubst: TLabel;
    CheckBoxRexUseSubst: TCheckBox;
    LabelRexUseSlash: TLabel;
    CheckBoxRexUseSlash: TCheckBox;
    LabelRexGreedy: TLabel;
    CheckBoxRexGreedy: TCheckBox;
    LabelSavePar: TLabel;
    CheckBoxRexSavePar: TCheckBox;
    PanelRexLogContent: TPanel;
    MemoRexLog: TMemo;
    PanelRexResultContent: TPanel;
    MemoRexResult: TMemo;
    PanelRexInputContent: TPanel;
    MemoRexInput: TMemo;
    PanelRexPatternContent: TPanel;
    LabelRexPattern: TLabel;
    ComboBoxRexPattern: TComboBox;
    LabelRexReplacer: TLabel;
    ComboBoxRexReplacer: TComboBox;
    LabelRexCommand: TLabel;
    BitBtnRexTest: TBitBtn;
    BitBtnRexExec: TBitBtn;
    BitBtnRexReplace: TBitBtn;
    BitBtnRexHelp: TBitBtn;
    BitBtnRexNotes: TBitBtn;
    BitBtnRexSettings: TBitBtn;
    BitBtnRexReset: TBitBtn;
    BitBtnRexOpenCalculator: TBitBtn;
    BitBtnRexBackToRegExp: TBitBtn;
    BitBtnRexMoreHelp: TBitBtn;
    BitBtnRexPatternEscapeSelText: TBitBtn;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormShow(Sender: TObject);
    procedure FormHide(Sender: TObject);
    procedure BitBtnRexSettingsApplyClick(Sender: TObject);
    procedure TabSheetRexSettingsEnter(Sender: TObject);
    procedure TimerRexSettingsTimer(Sender: TObject);
    procedure BitBtnRexTestClick(Sender: TObject);
    procedure BitBtnRexExecClick(Sender: TObject);
    procedure BitBtnRexReplaceClick(Sender: TObject);
    procedure BitBtnRexHelpClick(Sender: TObject);
    procedure BitBtnRexNotesClick(Sender: TObject);
    procedure BitBtnRexResetClick(Sender: TObject);
    procedure BitBtnRexCheatSheetCommentsClick(Sender: TObject);
    procedure TimerRexMainTimer(Sender: TObject);
    procedure MemoRexResultDblClick(Sender: TObject);
    procedure BitBtnRexInputSelectAllClick(Sender: TObject);
    procedure BitBtnRexResultSelectAllClick(Sender: TObject);
    procedure BitBtnRexLogSelectAllClick(Sender: TObject);
    procedure BitBtnRexInputUnselectClick(Sender: TObject);
    procedure BitBtnRexResultUnselectClick(Sender: TObject);
    procedure BitBtnRexLogUnselectClick(Sender: TObject);
    procedure BitBtnRexInputCopyClick(Sender: TObject);
    procedure BitBtnRexResultCopyClick(Sender: TObject);
    procedure BitBtnRexLogCopyClick(Sender: TObject);
    procedure BitBtnRexInputPasteClick(Sender: TObject);
    procedure BitBtnRexInputCutClick(Sender: TObject);
    procedure BitBtnRexInputClearClick(Sender: TObject);
    procedure BitBtnRexResultClearClick(Sender: TObject);
    procedure BitBtnRexLogClearClick(Sender: TObject);
    procedure BitBtnRexInputUndoClick(Sender: TObject);
    procedure FormResize(Sender: TObject);
    procedure BitBtnRexDumpSelectAllClick(Sender: TObject);
    procedure BitBtnRexDumpUnselectClick(Sender: TObject);
    procedure BitBtnRexDumpCopyClick(Sender: TObject);
    procedure BitBtnRexDumpClearClick(Sender: TObject);
    procedure BitBtnRexDumpCodeClick(Sender: TObject);
    procedure BitBtnRexDumpDataClick(Sender: TObject);
    function  GetRexBenchmark:Cardinal;
    procedure BitBtnRexSettingsClick(Sender: TObject);
    procedure BitBtnRexOpenCalculatorClick(Sender: TObject);
    procedure BitBtnRexBackToRegExpClick(Sender: TObject);
    procedure BitBtnRexPatternEscapeSelTextClick(Sender: TObject);
  private
    { Private declarations }
    rex : Integer;
    myResizeFlag : Boolean;
    function  GetRexInput:String;
    function  GetRexPattern:String;
    function  GetRexReplacer:String;
    function  GetRexResult:String;
    procedure SetRexResult(s:String);
    function  GetRexEngine:Integer;
    procedure SetRexEngine(n:Integer);
    function  GetRexUseSubst:Integer;
    function  GetRexUseSlash:Integer;
    function  GetRexExecMax:Integer;
    function  GetRexGreedy:Integer;
    function  GetRexSavePar:Integer;
    function  GetRexModifiers:String;
    procedure SetRexModifiers(s:String);
    function  GetRexEngines:String;
    procedure AdjustParameters;
    procedure UpdateMemoCaption(GroupBox:TGroupBox; Memo:TMemo; aCaption:String);
  public
    { Public declarations }
    procedure RexHelp;
    procedure RexInit;
    procedure RexFree;
    procedure RexTest;
    procedure RexExec;
    procedure RexReplace;
    procedure RexSetParams;
    procedure RexInitSettings;
    procedure RexApplySettings;
    procedure RexAddResult(Line:String);
    procedure RexLog(When:TDateTime; What:String);
    function  RexTimePrompt(When:TDateTime; cPad:Char=' '):String;
    function  RexPad(cPad:Char=' '):String;
    procedure RexPatternAddEscapedText;
    procedure RexCheatSheetComments;
    function  RexOptions:String;
    procedure RexLoadCheatSheet;
    procedure RexSelectMatch;
    procedure RexLoadSamples;
    procedure RexOpenCalculator;
    procedure RexNotes;
    procedure RexReset;
  public
    property RexInput     : String   read GetRexInput;
    property RexPattern   : String   read GetRexPattern;
    property RexReplacer  : String   read GetRexReplacer;
    property RexResult    : String   read GetRexResult    write SetRexResult;
    property RexEngine    : Integer  read GetRexEngine    write SetRexEngine;
    property RexUseSubst  : Integer  read GetRexUseSubst;
    property RexUseSlash  : Integer  read GetRexUseSlash;
    property RexExecMax   : Integer  read GetRexExecMax;
    property RexGreedy    : Integer  read GetRexGreedy;
    property RexSavePar   : Integer  read GetRexSavePar;
    property RexModifiers : String   read GetRexModifiers write SetRexModifiers;
    property RexEngines   : String   read GetRexEngines;
    property RexBenchmark : Cardinal read GetRexBenchmark;
  end;

var
 FormRegExpCalculator:TFormRegExpCalculator=nil;

const
 RegExpCalculatorFreeOnClose:Boolean=false;

function OpenRegExpCalculator:Boolean;
function ExecuteRegExpCalculator:Integer;

implementation

{$R *.lfm}

function OpenRegExpCalculator:Boolean;
begin
 Result:=false;
 try
  if not Assigned(FormRegExpCalculator) then begin
   Application.CreateForm(TFormRegExpCalculator, FormRegExpCalculator);
   FormRegExpCalculator.Master:=@FormRegExpCalculator;
  end;
  if Assigned(FormRegExpCalculator) then begin
   if not FormRegExpCalculator.Visible then FormRegExpCalculator.Show;
   FormRegExpCalculator.WindowState:=wsNormal;
   FormRegExpCalculator.BringToFront;
   Result:=true;
  end;
 except
  on E:Exception do BugReport(E,Application,'OpenRegExpCalculator');
 end;
end;

function ExecuteRegExpCalculator:Integer;
begin
 Result:=mrCancel;
 if CanShowModal(FormRegExpCalculator) then
 try
  if not Assigned(FormRegExpCalculator) then begin
   Application.CreateForm(TFormRegExpCalculator, FormRegExpCalculator);
   FormRegExpCalculator.Master:=@FormRegExpCalculator;
  end;
  if Assigned(FormRegExpCalculator) then begin
   Result:=mrVoice(FormRegExpCalculator.ShowModal);
  end;
 except
  on E:Exception do BugReport(E,Application,'ExecuteRegExpCalculator');
 end;
end;
 
procedure TFormRegExpCalculator.FormCreate(Sender: TObject);
begin
 inherited;
 SetStandardFont(Self);
 SetAllButtonsCursor(Self,crHandPoint);
 PageControlRexMain.ActivePageIndex:=0;
 ComboBoxRexEngine.Items.Text:=RexEngines;
 if (regexp_default_engine>0) and (regexp_default_engine<ComboBoxRexEngine.Items.Count)
 then ComboBoxRexEngine.ItemIndex:=regexp_default_engine
 else ComboBoxRexEngine.ItemIndex:=0;
 CheckListBoxRexModifiers.Items.Text:=
  'i - IgnoreCase - case insensitive mode                    '+EOL+
  'r - Russian    - expanded Russian support                 '+EOL+
  's - SingleLine - dot . operator includes line separators  '+EOL+
  'g - Global     - use global search to find all matches    '+EOL+
  'm - Multiline  - ^ and $ applies also to line begin/end   '+EOL+
  'x - Extended   - extended syntax of Pattern with #comments'+EOL;
 AdjustParameters;
 RexModifiers:=regexp_default_modifiers;
 SpinEditRexExecMax.Value:=regexp_default_execmax;
 CheckBoxRexUseSubst.Checked:=regexp_default_usesubst;
 CheckBoxRexUseSlash.Checked:=regexp_default_useslash;
 CheckBoxRexSavePar.Checked:=regexp_default_savepar;
 CheckBoxRexGreedy.Checked:=regexp_default_greedy;
 RexInit;
end;

procedure TFormRegExpCalculator.FormDestroy(Sender: TObject);
begin
 RegExpCalculatorFreeOnClose:=(RadioGroupRexClose.ItemIndex>0);
 RexFree;
 inherited;
end;

procedure TFormRegExpCalculator.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 if (RadioGroupRexClose.ItemIndex>0)
 then Action:=caFree
 else Action:=caHide;
end;

procedure TFormRegExpCalculator.FormShow(Sender: TObject);
begin
 inherited;
 TimerRexMain.Enabled:=true;
 TimerRexSettings.Enabled:=true;
end;

procedure TFormRegExpCalculator.FormHide(Sender: TObject);
begin
 inherited;
 TimerRexMain.Enabled:=false;
 TimerRexSettings.Enabled:=false;
end;

procedure TFormRegExpCalculator.FormResize(Sender: TObject);
begin
 inherited;
 myResizeFlag:=true;
end;

procedure TFormRegExpCalculator.AdjustParameters;
var Form:TForm;
begin
 try
  myResizeFlag:=true;
  RadioGroupRexClose.ItemIndex:=Ord(RegExpCalculatorFreeOnClose);
  with BitBtnRexCheatSheetComments.Font do begin Size:=14; Style:=[fsBold]; end;
  with BitBtnRexOpenCalculator.Font do begin Size:=14; Style:=[fsBold]; end;
  with BitBtnRexSettingsApply.Font do begin Size:=14; Style:=[fsBold]; end;
  with BitBtnRexBackToRegExp.Font do begin Size:=14; Style:=[fsBold]; end;
  with BitBtnRexSettings.Font do begin Size:=14; Style:=[fsBold]; end;
  with BitBtnRexDumpCode.Font do begin Size:=14; Style:=[fsBold]; end;
  with BitBtnRexDumpData.Font do begin Size:=14; Style:=[fsBold]; end;
  with BitBtnRexMoreHelp.Font do begin Size:=14; Style:=[fsBold]; end;
  with BitBtnRexReplace.Font do begin Size:=14; Style:=[fsBold]; end;
  with BitBtnRexNotes.Font do begin Size:=14; Style:=[fsBold]; end;
  with BitBtnRexReset.Font do begin Size:=14; Style:=[fsBold]; end;
  with BitBtnRexExec.Font do begin Size:=14; Style:=[fsBold]; end;
  with BitBtnRexTest.Font do begin Size:=14; Style:=[fsBold]; end;
  with BitBtnRexHelp.Font do begin Size:=14; Style:=[fsBold]; end;
  ImageListRex32.GetBitmap(0,BitBtnRexReset.Glyph);
  ImageListRex32.GetBitmap(1,BitBtnRexHelp.Glyph);
  ImageListRex32.GetBitmap(1,BitBtnRexMoreHelp.Glyph);
  ImageListRex32.GetBitmap(1,BitBtnRexNotes.Glyph);
  ImageListRex32.GetBitmap(1,BitBtnRexCheatSheetComments.Glyph);
  ImageListRex32.GetBitmap(2,BitBtnRexTest.Glyph);
  ImageListRex32.GetBitmap(3,BitBtnRexExec.Glyph);
  ImageListRex32.GetBitmap(4,BitBtnRexReplace.Glyph);
  ImageListRex32.GetBitmap(2,BitBtnRexSettingsApply.Glyph);
  ImageListRex32.GetBitmap(5,BitBtnRexDumpData.Glyph);
  ImageListRex32.GetBitmap(5,BitBtnRexDumpCode.Glyph);
  ImageListRex32.GetBitmap(6,BitBtnRexSettings.Glyph);
  ImageListRex32.GetBitmap(8,BitBtnRexOpenCalculator.Glyph);
  ImageListRex32.GetBitmap(9,BitBtnRexBackToRegExp.Glyph);
  ImageListRex16.GetBitmap(1,BitBtnRexInputSelectAll.Glyph);
  ImageListRex16.GetBitmap(1,BitBtnRexResultSelectAll.Glyph);
  ImageListRex16.GetBitmap(1,BitBtnRexLogSelectAll.Glyph);
  ImageListRex16.GetBitmap(1,BitBtnRexDumpSelectAll.Glyph);
  ImageListRex16.GetBitmap(0,BitBtnRexInputUnselect.Glyph);
  ImageListRex16.GetBitmap(0,BitBtnRexResultUnselect.Glyph);
  ImageListRex16.GetBitmap(0,BitBtnRexLogUnselect.Glyph);
  ImageListRex16.GetBitmap(0,BitBtnRexDumpUnselect.Glyph);
  ImageListRex16.GetBitmap(4,BitBtnRexInputCopy.Glyph);
  ImageListRex16.GetBitmap(4,BitBtnRexResultCopy.Glyph);
  ImageListRex16.GetBitmap(4,BitBtnRexLogCopy.Glyph);
  ImageListRex16.GetBitmap(4,BitBtnRexDumpCopy.Glyph);
  ImageListRex16.GetBitmap(2,BitBtnRexInputClear.Glyph);
  ImageListRex16.GetBitmap(2,BitBtnRexResultClear.Glyph);
  ImageListRex16.GetBitmap(2,BitBtnRexLogClear.Glyph);
  ImageListRex16.GetBitmap(2,BitBtnRexDumpClear.Glyph);
  ImageListRex16.GetBitmap(3,BitBtnRexInputCut.Glyph);
  ImageListRex16.GetBitmap(5,BitBtnRexInputPaste.Glyph);
  ImageListRex16.GetBitmap(6,BitBtnRexInputUndo.Glyph);
  PanelRexPatternContent.ParentFont:=false;
  GroupBoxRexPattern.Font.Style:=[fsBold];
  PanelRexInputContent.ParentFont:=false;
  PanelRexInputButtons.ParentFont:=false;
  GroupBoxRexInput.Font.Style:=[fsBold];
  PanelRexResultContent.ParentFont:=false;
  PanelRexResultButtons.ParentFont:=false;
  GroupBoxRexResult.Font.Style:=[fsBold];
  PanelRexLogContent.ParentFont:=false;
  PanelRexLogButtons.ParentFont:=false;
  GroupBoxRexLog.Font.Style:=[fsBold];
  PanelRexEngineContent.ParentFont:=false;
  GroupBoxRexEngine.Font.Style:=[fsBold];
  PanelRexModifiersContent.ParentFont:=false;
  GroupBoxRexModifiers.Font.Style:=[fsBold];
  PanelRexBenchmarkContent.ParentFont:=false;
  GroupBoxRexBenchmark.Font.Style:=[fsBold];
  PanelRexDumpContent.ParentFont:=false;
  PanelRexDumpButtons.ParentFont:=false;
  GroupBoxRexDump.Font.Style:=[fsBold];
  TabSheetRexPattern.ParentFont:=false;
  TabSheetRexSettings.ParentFont:=false;
  TabSheetRexCheatSheet.ParentFont:=false;
  PageControlRexMain.Font.Style:=[fsBold];
  PageControlRexMain.Font.Size:=14;
  if (Application=nil) then Form:=nil else
  if (Application.MainForm=nil) then Form:=nil else
  Form:=Application.MainForm;
  if (Form<>nil) then
  if (Form.Height>Height+(Form.Height div 16)) then begin
   Height:=Form.Height-(Form.Height div 8);
   Top:=Form.Top+(Form.Height div 16);
  end;
  RexLoadCheatSheet;
  RexLoadSamples;
 except
  on E:Exception do BugReport(E,Self,'AdjustParameters');
 end;
end;

procedure TFormRegExpCalculator.RexLoadSamples;
var sam:String;
begin
 try
  sam:=ExtractTextSection(SysIniFile,'[TFormRegExpCalculator.Pattern.Samples]',efAsIs);
  if (sam<>'') then begin
   ComboBoxRexPattern.Items.Text:=AdjustLineBreaks(sam);
   if ComboBoxRexPattern.Items.Count>0 then ComboBoxRexPattern.ItemIndex:=0;
  end;
  sam:=ExtractTextSection(SysIniFile,'[TFormRegExpCalculator.Replacer.Samples]',efAsIs);
  if (sam<>'') then begin
   ComboBoxRexReplacer.Items.Text:=AdjustLineBreaks(sam);
   if ComboBoxRexReplacer.Items.Count>0 then ComboBoxRexReplacer.ItemIndex:=0;
  end;
  sam:=ExtractTextSection(SysIniFile,'[TFormRegExpCalculator.Input.Samples]',efAsIs);
  if (sam<>'') then begin
   MemoRexInput.Text:=AdjustLineBreaks(sam);
  end;
 except
  on E:Exception do BugReport(E,Self,'RexLoadSamples');
 end;
end;

procedure TFormRegExpCalculator.RexLoadCheatSheet;
var img:ShortString;
begin
 try
  img:='';
  if not ReadIniFilePath(SysIniFile,'[System]','regexp_cheatsheet_picture',HomeDir,img)
  then img:=AddPathDelim(HomeDir)+'resource\manual\regexp\regexp.bmp';
  img:=FExpand(img); if not FileExists(img) then Exit;
  ImageRexCheatSheet.Picture.LoadFromFile(img);
 except
  on E:Exception do BugReport(E,Self,'RexLoadCheatSheet');
 end;
end;

procedure TFormRegExpCalculator.RexCheatSheetComments;
var pdf:ShortString;
begin
 try
  pdf:='';
  if not ReadIniFilePath(SysIniFile,'[System]','regexp_cheatsheet_comment',HomeDir,pdf)
  then pdf:=AddPathDelim(HomeDir)+'resource\manual\regexp\regexp-cheatsheet-1.pdf';
  pdf:=FExpand(pdf); if not FileExists(pdf) then Exit;
  SendToMainConsole('@run PdfViewer '+pdf+EOL);
 except
  on E:Exception do BugReport(E,Self,'RexCheatSheetComments');
 end;
end;

function TFormRegExpCalculator.GetRexInput:String;
begin
 Result:='';
 case MemoRexInput.Lines.Count of
  0:   Result:='';
  1:   Result:=MemoRexInput.Lines[0];
  else Result:=MemoRexInput.Lines.Text;
 end;
end;

function TFormRegExpCalculator.GetRexPattern:String;
begin
 Result:=ComboBoxRexPattern.Text;
end;

function TFormRegExpCalculator.GetRexReplacer:String;
begin
 Result:=ComboBoxRexReplacer.Text;
end;

function TFormRegExpCalculator.GetRexResult:String;
begin
 Result:=MemoRexResult.Lines.Text;
end;

procedure TFormRegExpCalculator.SetRexResult(s:String);
begin
 MemoRexResult.Lines.Text:=s;
end;

function TFormRegExpCalculator.GetRexEngine:Integer;
begin
 Result:=ComboBoxRexEngine.ItemIndex;
end;

procedure TFormRegExpCalculator.SetRexEngine(n:Integer);
begin
 try
  n:=Max(0,Min(n,ComboBoxRexEngine.Items.Count-1));
  ComboBoxRexEngine.ItemIndex:=n;
  RexFree;
  RexInit;
 except
  on E:Exception do BugReport(E,Self,'SetRexEngine');
 end;
end;

function TFormRegExpCalculator.GetRexUseSubst:Integer;
begin
 Result:=Ord(CheckBoxRexUseSubst.Checked);
end;

function TFormRegExpCalculator.GetRexUseSlash:Integer;
begin
 Result:=Ord(CheckBoxRexUseSlash.Checked);
end;

function TFormRegExpCalculator.GetRexExecMax:Integer;
begin
 Result:=SpinEditRexExecMax.Value;
end;

function TFormRegExpCalculator.GetRexGreedy:Integer;
begin
 Result:=Ord(CheckBoxRexGreedy.Checked);
end;

function TFormRegExpCalculator.GetRexSavePar:Integer;
begin
 Result:=Ord(CheckBoxRexSavePar.Checked);
end;

function TFormRegExpCalculator.GetRexModifiers:String;
var i:Integer;
begin
 Result:='';
 with CheckListBoxRexModifiers do for i:=0 to Items.Count-1 do
 if Checked[i] then Result:=Result+StrFetch(Trim(Items[i]),1);
 Result:=Result+'-';
 with CheckListBoxRexModifiers do for i:=0 to Items.Count-1 do
 if not Checked[i] then Result:=Result+StrFetch(Trim(Items[i]),1);
 if (Result<>'') and (Result[Length(Result)]='-') then Delete(Result,Length(Result),1);
end;

procedure TFormRegExpCalculator.SetRexModifiers(s:String);
var i,pm:Integer; sp,sm:String; c:Char;
begin
 pm:=pos('-',s); sp:=Copy(s,1,pm-1); sm:=Copy(s,pm+1,MaxInt);
 with CheckListBoxRexModifiers do for i:=0 to Items.Count-1 do begin
  c:=StrFetch(Trim(Items[i]),1);
  if Pos(c,sm)>0 then Checked[i]:=false else
  if Pos(c,sp)>0 then Checked[i]:=true;
 end;
end;

function TFormRegExpCalculator.GetRexEngines:String;
begin
 Result:='Default'+EOL+TRegExpMaster.Engines;
end;

function TFormRegExpCalculator.GetRexBenchmark:Cardinal;
begin
 Result:=0;
 if CheckBoxRexBenchmark.Checked
 then Result:=SpinEditRexBenchmark.Value;
end;

function TFormRegExpCalculator.RexOptions:String;
begin
 Result:='';
 if not regexp_ref(rex).Ok then Exit;
 Result:=regexp_ctrl(rex,'Options');
end;

procedure TFormRegExpCalculator.RexHelp;
var hlp:ShortString;
begin
 hlp:='';
 if not ReadIniFilePath(SysIniFile,'[System]','regexp_help_file',HomeDir,hlp)
 then hlp:=AddPathDelim(HomeDir)+'resource\manual\regexp\regexp.html';
 hlp:=FExpand(hlp);
 if FileExists(hlp)
 then SendToMainConsole('@run HtmlBrowser '+hlp+EOL)
 else RexLog(Now,'Help file not found.');
end;

procedure TFormRegExpCalculator.RexInit;
begin
 if regexp_ref(rex).Ok then Exit;
 try
  rex:=regexp_init(RexEngine,RexPattern);
  if regexp_ref(rex).Ok then begin
   RexSetParams;
   RexLog(Now,'RegExp Created '+regexp_ctrl(rex,'Version'));
   RexLog(0,RexPad+'with Options: '+regexp_ctrl(rex,'Options'));
   RexLog(0,RexPad+'with Pattern: '+regexp_ctrl(rex,'Pattern'));
  end else begin
   RexLog(Now,'Could not create '+TRegExpMaster.ClassName);
   RexFree;
  end;
 except
  on E:Exception do BugReport(E,Self,'RexInit');
 end;
end;

procedure TFormRegExpCalculator.RexFree;
begin
 if (rex<>0) then begin
  RexLog(Now,'Free '+regexp_ctrl(rex,'Version'));
  regexp_free(rex);
  rex:=0;
 end;
end;

procedure TFormRegExpCalculator.RexSetParams;
begin
 try
  if not regexp_ref(rex).Ok then Exit;
  regexp_ctrl(rex,'UseSubst='+IntToStr(RexUseSubst));
  regexp_ctrl(rex,'UseSlash='+IntToStr(RexUseSlash));
  regexp_ctrl(rex,'ExecMax='+IntToStr(RexExecMax));
  regexp_ctrl(rex,'SavePar='+IntToStr(RexSavePar));
  regexp_ctrl(rex,'Greedy='+IntToStr(RexGreedy));
  regexp_ctrl(rex,'Modifiers='+RexModifiers);
  regexp_ctrl(rex,'Pattern='+RexPattern);
  RexModifiers:=regexp_ctrl(rex,'Modifiers'); // Modifiers may change by /p/m instruction
 except
  on E:Exception do BugReport(E,Self,'RexSetParams');
 end;
end;

function TFormRegExpCalculator.RexTimePrompt(When:TDateTime; cPad:Char=' '):String;
begin
 Result:=FormatDateTime('yyyy.mm.dd-hh:nn:ss',When);
 if (When<=0) then Result:=StringOfChar(cPad,Length(Result));
 Result:=Result+' => ';
end;

function TFormRegExpCalculator.RexPad(cPad:Char=' '):String;
begin
 Result:=RexTimePrompt(0,cPad);
end;

procedure TFormRegExpCalculator.RexTest;
var test:Boolean; bm,t0,dt,cnt:Cardinal; inp:String; mks:Double;
begin
 try
  RexInit;
  RexResult:='';
  if not regexp_ref(rex).Ok then Exit;
  RexSetParams;
  inp:=RexInput;
  RexLog(Now,'RegExp Test started');
   RexLog(0,RexPad+'with Options: '+regexp_ctrl(rex,'Options'));
   RexLog(0,RexPad+'with Pattern: '+regexp_ctrl(rex,'Pattern'));
  test:=regexp_test(rex,inp);
  RexLog(Now,'RegExp Test Result = '+IntToStr(Ord(test)));
  if test
  then RexResult:='Test => TRUE'
  else RexResult:='Test => FALSE';
  bm:=RexBenchmark;
  if (bm>0) then begin
   cnt:=0;
   t0:=GetTickCount;
   repeat
    regexp_test(rex,inp);
    dt:=GetTickCount-t0;
    inc(cnt);
   until (dt>bm);
   mks:=1.0e3*dt/cnt;
   RexLog(0,RexPad+Format('RegExp Benchmark: Test takes %1.3f mksec per call.',[mks]));
  end;
 except
  on E:Exception do BugReport(E,Self,'RexTest');
 end;
end;

procedure TFormRegExpCalculator.RexExec;
var i,j,p,l,n,m,wn,wl,exec:Integer; s,inp:String; bm,t0,dt,cnt:Cardinal; mks:Double;
begin
 try
  RexInit;
  RexResult:='';
  if not regexp_ref(rex).Ok then Exit;
  RexSetParams;
  inp:=RexInput;
  RexLog(Now,'RegExp Exec started');
   RexLog(0,RexPad+'with Options: '+regexp_ctrl(rex,'Options'));
   RexLog(0,RexPad+'with Pattern: '+regexp_ctrl(rex,'Pattern'));
  exec:=regexp_exec(rex,inp);
  RexLog(Now,'RegExp Exec Result = '+IntToStr(exec));
  n:=regexp_matchnum(rex,0);
  wn:=Length(IntToStr(n));
  wl:=Length(IntToStr(Length(RexInput)));
  RexAddResult('Exec found matches  => '+IntToStr(n));
  if (n>0) then
  try
   MemoRexResult.Lines.BeginUpdate;
   for i:=1 to n do wn:=max(wn,Length(IntToStr(regexp_matchnum(rex,i))));
   for i:=1 to n do begin
    p:=regexp_matchpos(rex,i,0);
    l:=regexp_matchlen(rex,i,0);
    s:=regexp_matchstr(rex,i,0);
    RexAddResult(Format(RexPad+'Match[%*d] = %*d %*d %s',[wn,i,wl,p,wl,l,s]));
    m:=regexp_matchnum(rex,i);
    for j:=1 to m do begin
     p:=regexp_matchpos(rex,i,j);
     l:=regexp_matchlen(rex,i,j);
     s:=regexp_matchstr(rex,i,j);
     RexAddResult(Format(RexPad+'  Sub[%*d] = %*d %*d %s',[wn,j,wl,p,wl,l,s]));
    end;
   end;
  finally
   MemoRexResult.Lines.EndUpdate;
  end;
  bm:=RexBenchmark;
  if (bm>0) then begin
   cnt:=0;
   t0:=GetTickCount;
   repeat
    regexp_exec(rex,inp);
    dt:=GetTickCount-t0;
    inc(cnt);
   until (dt>bm);
   mks:=1.0e3*dt/cnt;
   RexLog(0,RexPad+Format('RegExp Benchmark: Exec takes %1.3f mksec per call.',[mks]));
  end;
 except
  on E:Exception do BugReport(E,Self,'RexExec');
 end;
end;

procedure TFormRegExpCalculator.RexReplace;
var bm,t0,dt,cnt:Cardinal; inp,rep:String; mks:Double;
begin
 try
  RexInit;
  RexResult:='';
  if not regexp_ref(rex).Ok then Exit;
  RexSetParams;
  inp:=RexInput;
  rep:=RexReplacer;
  RexLog(Now,'RegExp Replace started');
  RexLog(0,RexPad+'with Options: '+regexp_ctrl(rex,'Options'));
  RexLog(0,RexPad+'with Pattern: '+regexp_ctrl(rex,'Pattern'));
  RexLog(0,RexPad+'use Replacer: '+RexReplacer);
  RexResult:=regexp_replace(rex,inp,rep);
  RexLog(Now,'RegExp Replace Done');
  bm:=RexBenchmark;
  if (bm>0) then begin
   cnt:=0;
   t0:=GetTickCount;
   repeat
    regexp_replace(rex,inp,rep);
    dt:=GetTickCount-t0;
    inc(cnt);
   until (dt>bm);
   mks:=1.0e3*dt/cnt;
   RexLog(0,RexPad+Format('RegExp Benchmark: Replace takes %1.3f mksec per call.',[mks]));
  end;
 except
  on E:Exception do BugReport(E,Self,'RexReplace');
 end;
end;

procedure TFormRegExpCalculator.RexAddResult(Line:String);
begin
 MemoRexResult.Lines.Add(Line);
end;

procedure TFormRegExpCalculator.RexLog(When:TDateTime; What:String);
begin
 if (When>0) then What:=RexTimePrompt(When)+What;
 MemoRexLog.Lines.Add(What);
end;

procedure TFormRegExpCalculator.RexInitSettings;
var i:Integer;
begin
 try
  if regexp_ref(rex).Ok then begin
   SpinEditRexExecMax.Value:=StrToIntDef(regexp_ctrl(rex,'ExecMax'),0);
   CheckBoxRexUseSubst.Checked:=(StrToIntDef(regexp_ctrl(rex,'UseSubst'),0)<>0);
   CheckBoxRexUseSlash.Checked:=(StrToIntDef(regexp_ctrl(rex,'UseSlash'),0)<>0);
   i:=ComboBoxRexEngine.Items.IndexOf(ExtractFirstParam(regexp_ctrl(rex,'Version')));
   if (i>0) then ComboBoxRexEngine.ItemIndex:=i;
   RexModifiers:=regexp_ctrl(rex,'Modifiers');
   CheckBoxRexGreedy.Checked:=(StrToIntDef(regexp_ctrl(rex,'Greedy'),0)<>0);
   CheckBoxRexSavePar.Checked:=(StrToIntDef(regexp_ctrl(rex,'SavePar'),0)<>0);
  end;
 except
  on E:Exception do BugReport(E,Self,'RexInitSettings');
 end;
end;

procedure TFormRegExpCalculator.RexApplySettings;
begin
 try
  if not SameText(IntToStr(RexEngine),regexp_ctrl(rex,'Engine')) then begin
   RexFree;
   RexInit;
  end;
  RexSetParams;
  PageControlRexMain.ActivePageIndex:=0;
  RexLog(Now,'Options Applied: '+regexp_ctrl(rex,'Options'));
 except
  on E:Exception do BugReport(E,Self,'RexApplySettings');
 end;
end;

procedure TFormRegExpCalculator.RexNotes;
var sect,notes:String;
begin
 try
  sect:='[TFormRegExpCalculator.'+RusEng('Notes_Ru','Notes')+']';
  notes:=ExtractTextSection(SysIniFile,sect,efAsIs);
  if (notes<>'')
  then RexResult:=RusEng('Краткая справка:','Short notes:')+EOL+notes
  else RexResult:=RusEng('Справка не найдена.','Help notes is not found.');
 except
  on E:Exception do BugReport(E,Self,'RexNotes');
 end;
end;

procedure TFormRegExpCalculator.RexOpenCalculator;
var htm:ShortString;
begin
 try
  htm:='';
  if not ReadIniFilePath(SysIniFile,'[System]','regexp_html_calculator',HomeDir,htm)
  then htm:=AddPathDelim(HomeDir)+'resource\manual\regexp\regexpres\calculator.html';
  htm:=FExpand(htm); if not FileExists(htm) then Exit;
  SendToMainConsole('@run HtmlBrowser '+htm);
 except
  on E:Exception do BugReport(E,Self,'RexOpenCalculator');
 end;
end;

procedure TFormRegExpCalculator.RexReset;
begin
 try
  RexResult:='';
  MemoRexLog.Clear;
  RexLoadSamples;
  RexFree;
  RexInit;
 except
  on E:Exception do BugReport(E,Self,'RexReset');
 end;
end;

procedure TFormRegExpCalculator.RexSelectMatch;
var i,sel,spos,slen,mpos,mlen,rxm,rxs:Integer; lines,line:String;
begin
 try
  rxm:=0; rxs:=0;
  try
   lines:=MemoRexResult.Text;
   sel:=MemoRexResult.SelStart;
   i:=0; spos:=1; slen:=0;
   repeat
    i:=PosEx(EOL,lines,i+1);
    if (i>0) then begin
     if (i>=sel+1) then begin
      slen:=max(0,i-spos);
      break;
     end;
     spos:=i+Length(EOL);
    end else begin
     slen:=max(0,Length(lines)-spos+1);
     break;
    end;
   until (i<=0);
   if (slen<=0) then Exit;
   line:=Copy(lines,spos,slen); if (line='') then Exit;
   //MemoRexResult.SelStart:=spos-1; MemoRexResult.SelLength:=slen;
   rxm:=regexp_init(regexp_def,'Match\[\s*\d+\s*\]\s*=\s*(\d+)\s+(\d+)\s(.+)');
   rxs:=regexp_init(regexp_def,  'Sub\[\s*\d+\s*\]\s*=\s*(\d+)\s+(\d+)\s(.+)');
   regexp_ctrl(rxm,'Modifiers=img-srx'); regexp_ctrl(rxm,'ExecMax=1');
   regexp_ctrl(rxs,'Modifiers=img-srx'); regexp_ctrl(rxs,'ExecMax=1');
   if regexp_exec(rxm,line)>0 then begin
    if (regexp_matchnum(rxm,1)>2) then
    if Str2Int(regexp_matchstr(rxm,1,1),mpos) then
    if Str2Int(regexp_matchstr(rxm,1,2),mlen) then
    if (mpos>0) and (mlen>0) then begin
     MemoRexInput.SelStart:=mpos-1;
     MemoRexInput.SelLength:=mlen;
    end;
    mpos:=regexp_matchpos(rxm,1,3);
    mlen:=regexp_matchlen(rxm,1,3);
    if (mpos>0) and (mlen>0) then begin
     MemoRexResult.SelStart:=spos-1+mpos-1;
     MemoRexResult.SelLength:=mlen;
    end;
    Exit;
   end;
   if regexp_exec(rxs,line)>0 then begin
    if (regexp_matchnum(rxs,1)>2) then
    if Str2Int(regexp_matchstr(rxs,1,1),mpos) then
    if Str2Int(regexp_matchstr(rxs,1,2),mlen) then
    if (mpos>0) and (mlen>0) then begin
     MemoRexInput.SelStart:=mpos-1;
     MemoRexInput.SelLength:=mlen;
    end;
    mpos:=regexp_matchpos(rxs,1,3);
    mlen:=regexp_matchlen(rxs,1,3);
    if (mpos>0) and (mlen>0) then begin
     MemoRexResult.SelStart:=spos-1+mpos-1;
     MemoRexResult.SelLength:=mlen;
    end;
    Exit;
   end;
   MemoRexResult.SelStart:=sel;
   MemoRexResult.SelLength:=0;
  finally
   regexp_free(rxm);
   regexp_free(rxs);
  end;
 except
  on E:Exception do BugReport(E,Self,'RexSelectMatch');
 end;
end;

procedure TFormRegExpCalculator.BitBtnRexSettingsApplyClick(Sender: TObject);
begin
 RexApplySettings;
end;

procedure TFormRegExpCalculator.TabSheetRexSettingsEnter(Sender: TObject);
begin
 RexInitSettings;
end;

procedure TFormRegExpCalculator.TimerRexSettingsTimer(Sender: TObject);
const Loops:Cardinal=0;
begin
 try
  if (PageControlRexMain.ActivePage=TabSheetRexSettings) then begin
   inc(Loops);
   if Odd(Loops)
   then BitBtnRexSettingsApply.Font.Color:=clBtnText
   else BitBtnRexSettingsApply.Font.Color:=clGreen;
  end;
 except
  on E:Exception do BugReport(E,Self,'TimerRexSettingsTimer');
 end;
end;

procedure TFormRegExpCalculator.BitBtnRexTestClick(Sender: TObject);
begin
 RexTest;
end;

procedure TFormRegExpCalculator.BitBtnRexExecClick(Sender: TObject);
begin
 RexExec;
end;

procedure TFormRegExpCalculator.BitBtnRexReplaceClick(Sender: TObject);
begin
 RexReplace;
end;

procedure TFormRegExpCalculator.BitBtnRexHelpClick(Sender: TObject);
begin
 RexHelp;
end;

procedure TFormRegExpCalculator.BitBtnRexNotesClick(Sender: TObject);
begin
 RexNotes;
end;

procedure TFormRegExpCalculator.BitBtnRexResetClick(Sender: TObject);
begin
 RexReset;
end;

procedure TFormRegExpCalculator.BitBtnRexCheatSheetCommentsClick(Sender: TObject);
begin
 RexCheatSheetComments;
end;

procedure TFormRegExpCalculator.UpdateMemoCaption(GroupBox:TGroupBox; Memo:TMemo; aCaption:String);
var spos,slen,row,col,nerr:Integer; serr:String;
begin
 spos:=Memo.SelStart+1; slen:=Memo.SelLength;
 nerr:=StrToIntDef(regexp_ctrl(rex,'Errors'),-1);
 with Memo.CaretPos do begin col:=x+1; row:=y+1; end;
 if (GroupBox=GroupBoxRexResult) then serr:=Format(',  Errors:%d ', [nerr]) else serr:=' ';
 GroupBox.Caption:=aCaption+Format(' Selection (Pos:%d, Len:%d),  Caret (Line:%d, Column:%d)', [spos,slen,row,col])+serr;
end;

procedure TFormRegExpCalculator.TimerRexMainTimer(Sender: TObject);
var n,h:Integer;
begin
 try
  if (PageControlRexMain.ActivePageIndex=0) then begin
   UpdateMemoCaption(GroupBoxRexInput,MemoRexInput,' RegExp Input: ');
   UpdateMemoCaption(GroupBoxRexResult,MemoRexResult,' RegExp Result: ');
   n:=regexp_matchnum(rex,0);
   if (n<=0)
   then GroupBoxRexLog.Caption:=' RegExp - LogBook: '
   else GroupBoxRexLog.Caption:=' RegExp - LogBook: '+IntToStr(n)+' Match(es) found. Use DoubleClick on Result to select Sub/Match in Input.';
   n:=MemoRexInput.SelLength;
   BitBtnRexInputCut.Enabled:=(n>0);
   BitBtnRexInputCopy.Enabled:=(n>0);
   BitBtnRexInputUnselect.Enabled:=(n>0);
   BitBtnRexInputUndo.Enabled:=MemoRexInput.CanUndo;
   BitBtnRexInputPaste.Enabled:=Clipboard.HasFormat(CF_TEXT);
   n:=MemoRexResult.SelLength;
   BitBtnRexResultCopy.Enabled:=(n>0);
   BitBtnRexResultUnselect.Enabled:=(n>0);
   n:=MemoRexLog.SelLength;
   BitBtnRexLogCopy.Enabled:=(n>0);
   BitBtnRexLogUnselect.Enabled:=(n>0);
   n:=MemoRexDump.SelLength;
   BitBtnRexDumpCopy.Enabled:=(n>0);
   BitBtnRexDumpUnselect.Enabled:=(n>0);
   BitBtnRexHelp.Visible:=(BitBtnRexHelp.BoundsRect.Right<BitBtnRexSettings.Left);
   BitBtnRexNotes.Visible:=(BitBtnRexNotes.BoundsRect.Right<BitBtnRexSettings.Left);
   if myResizeFlag then begin
    h:=GroupBoxRexLog.Top-GroupBoxRexPattern.BoundsRect.Bottom;
    GroupBoxRexInput.Height:=h div 2;
    myResizeFlag:=false;
   end;
  end;
 except
  on E:Exception do BugReport(E,Self,'TimerRexMainTimer');
 end;
end;

procedure TFormRegExpCalculator.MemoRexResultDblClick(Sender: TObject);
begin
 RexSelectMatch;
end;

procedure MemoClear(Memo:TMemo);
begin
 if (Memo.SelLength>0) and not Memo.ReadOnly
 then Memo.ClearSelection
 else Memo.Clear;
end;

procedure TFormRegExpCalculator.BitBtnRexInputSelectAllClick(Sender: TObject);
begin
 MemoRexInput.SelectAll;
end;

procedure TFormRegExpCalculator.BitBtnRexResultSelectAllClick(Sender: TObject);
begin
 MemoRexResult.SelectAll;
end;

procedure TFormRegExpCalculator.BitBtnRexLogSelectAllClick(Sender: TObject);
begin
 MemoRexLog.SelectAll;
end;

procedure TFormRegExpCalculator.BitBtnRexInputUnselectClick(Sender: TObject);
begin
 MemoRexInput.SelLength:=0;
end;

procedure TFormRegExpCalculator.BitBtnRexResultUnselectClick(Sender: TObject);
begin
 MemoRexResult.SelLength:=0;
end;

procedure TFormRegExpCalculator.BitBtnRexLogUnselectClick(Sender: TObject);
begin
 MemoRexLog.SelLength:=0;
end;

procedure TFormRegExpCalculator.BitBtnRexInputCopyClick(Sender: TObject);
begin
 MemoRexInput.CopyToClipboard;
end;

procedure TFormRegExpCalculator.BitBtnRexResultCopyClick(Sender: TObject);
begin
 MemoRexResult.CopyToClipboard;
end;

procedure TFormRegExpCalculator.BitBtnRexLogCopyClick(Sender: TObject);
begin
 MemoRexLog.CopyToClipboard;
end;

procedure TFormRegExpCalculator.BitBtnRexInputPasteClick(Sender: TObject);
begin
 MemoRexInput.PasteFromClipboard;
end;

procedure TFormRegExpCalculator.BitBtnRexInputCutClick(Sender: TObject);
begin
 MemoRexInput.CutToClipboard;
end;

procedure TFormRegExpCalculator.BitBtnRexInputClearClick(Sender: TObject);
begin
 MemoClear(MemoRexInput);
end;

procedure TFormRegExpCalculator.BitBtnRexResultClearClick(Sender: TObject);
begin
 MemoClear(MemoRexResult);
end;

procedure TFormRegExpCalculator.BitBtnRexLogClearClick(Sender: TObject);
begin
 MemoClear(MemoRexLog);
end;

procedure TFormRegExpCalculator.BitBtnRexInputUndoClick(Sender: TObject);
begin
 MemoRexInput.Undo;
end;

procedure TFormRegExpCalculator.BitBtnRexDumpSelectAllClick(Sender: TObject);
begin
 MemoRexDump.SelectAll;
end;

procedure TFormRegExpCalculator.BitBtnRexDumpUnselectClick(Sender: TObject);
begin
 MemoRexDump.SelLength:=0;
end;

procedure TFormRegExpCalculator.BitBtnRexDumpCopyClick(Sender: TObject);
begin
 MemoRexDump.CopyToClipboard;
end;

procedure TFormRegExpCalculator.BitBtnRexDumpClearClick(Sender: TObject);
begin
 MemoRexDump.Clear;
end;

procedure TFormRegExpCalculator.BitBtnRexDumpCodeClick(Sender: TObject);
var dump:String;
begin
 dump:=regexp_ctrl(rex,'DumpCode');
 if (dump='') then dump:='<EMPTY>';
 MemoRexDump.Text:='Dump Code:'+EOL+dump;
end;

procedure TFormRegExpCalculator.BitBtnRexDumpDataClick(Sender: TObject);
var dump:String;
begin
 dump:=regexp_ctrl(rex,'DumpData');
 if (dump='') then dump:='<EMPTY>';
 MemoRexDump.Text:='Dump Data:'+EOL+dump;
end;

procedure TFormRegExpCalculator.BitBtnRexSettingsClick(Sender: TObject);
begin
 PageControlRexMain.ActivePage:=TabSheetRexSettings;
end;

procedure TFormRegExpCalculator.BitBtnRexOpenCalculatorClick(Sender: TObject);
begin
 RexOpenCalculator;
end;

procedure TFormRegExpCalculator.BitBtnRexBackToRegExpClick(Sender: TObject);
begin
 PageControlRexMain.ActivePage:=TabSheetRexPattern;
end;

procedure TFormRegExpCalculator.RexPatternAddEscapedText;
var s:String; List:TText;
begin
 try
  List:=NewText;
  try
   if TextEditDialog('Insert text with RegExp Escaping','Please enter Text to be Escaped',List)<>mrOk then Exit;
   if (List.Count=0) then s:='' else if (List.Count=1) then s:=List[0] else s:=List.Text;
   if (s<>'') then ComboBoxRexPattern.Text:=ComboBoxRexPattern.Text+regexp_escape(s);
  finally
   List.Free;
  end;
 except
  on E:Exception do BugReport(E,Self,'RexPatternAddEscapedText');
 end;
end;

procedure TFormRegExpCalculator.BitBtnRexPatternEscapeSelTextClick(Sender: TObject);
begin
 RexPatternAddEscapedText;
end;

end.
