{*******************************************************}
{                                                       }
{       Pascal Script Source File                       }
{       Run by RemObjects Pascal Script in CnWizards    }
{                                                       }
{       Generated by CnPack IDE Wizards                 }
{                                                       }
{*******************************************************}

program RegExprReplace;

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Buttons, StdCtrls, IniFiles, Registry, RegExpr, CnCommon, ToolsAPI;

const
  csDefExpression =
    // tblTest.FieldByName('Name').AsString => tblTestName.Value
    '(?i)(\w[\w\d]+).FieldByName\(\''(\w[\w\d]+)\''\)\.As[\w\d]+' + #13#10;
  csDefReplaceWith =
    '$1$2.Value' + #13#10;

var
  Form: TForm;
  btnOk, btnCancel, btnPreview: TButton;
  cbbRegExp, cbbRepTo: TComboBox;
  chkUseSub: TCheckBox;
  mmoInput, mmoPreview: TMemo;
  Ini: TCustomIniFile;

function CreateLabel(Parent: TForm; Left, Top: Integer; Caption: string): TLabel;
begin
  Result := TLabel.Create(Parent);
  Result.Parent := Parent;
  Result.Left := Left;
  Result.Top := Top;
  Result.Caption := Caption;
end;

function CreateButton(Parent: TForm; Left, Top: Integer; Caption: string): TButton;
begin
  Result := TButton.Create(Parent);
  Result.Parent := Parent;
  Result.Left := Left;
  Result.Top := Top;
  Result.Caption := Caption;
end;

function CreateComboBox(Parent: TForm; Left, Top, Width: Integer; Text: string): TComboBox;
begin
  Result := TComboBox.Create(Parent);
  Result.Parent := Parent;
  Result.Left := Left;
  Result.Top := Top;
  Result.Width := Width;
  Result.Text := Text;
end;

function CreateCheckBox(Parent: TForm; Left, Top, Width: Integer;
  Caption: string; Checked: Boolean): TCheckBox;
begin
  Result := TCheckBox.Create(Parent);
  Result.Parent := Parent;
  Result.Left := Left;
  Result.Top := Top;
  Result.Width := Width;
  Result.Caption := Caption;
  Result.Checked := Checked;
end;

function CreateMemo(Parent: TForm; Left, Top, Width, Height: Integer): TMemo;
begin
  Result := TMemo.Create(Parent);
  Result.Parent := Parent;
  Result.Left := Left;
  Result.Top := Top;
  Result.Width := Width;
  Result.Height := Height;
  Result.ScrollBars := ssBoth;
end;  

procedure cbbRegExpKeyPress(Sender: TObject; var Key: Char);
begin
  if Key = #13 then
  begin
    Key := #0;
    cbbRepTo.SetFocus;
  end;
end;

procedure cbbRepToKeyPress(Sender: TObject; var Key: Char);
begin
  if Key = #13 then
  begin
    Key := #0;
    btnPreview.SetFocus;
  end;
end;

procedure btnPreviewClick(Sender: TObject);
begin
  if cbbRegExp.Text = '' then
  begin
    ErrorDlg('Please input Expression string');
    Exit;
  end;  
  mmoPreview.Lines.Text := ReplaceRegExpr(cbbRegExp.Text, mmoInput.Lines.Text,
    cbbRepTo.Text, chkUseSub.Checked);
end;

procedure btnOkClick(Sender: TObject);
begin
  if cbbRegExp.Text = '' then
  begin
    ErrorDlg('Please input Expression string');
    Exit;
  end;  
  Form.ModalResult := mrOk;
end;

procedure btnCancelClick(Sender: TObject);
begin
  Form.ModalResult := mrCancel;
end;

const
  csRegPath = 'Software\CnPack\Scripts';
  csSection = 'RegExprReplace';

function ShowReplaceForm(InputText: string; var OutText: string): Boolean;
begin
  Form := nil;
  Ini := nil;
  try
    Form := TForm.Create(nil);
    Ini := TRegistryIniFile.Create(csRegPath);
    Form.BorderStyle := bsDialog;
    Form.SetBounds(100, 100, 600, 580);
    Form.Position := poScreenCenter;
    Form.Caption := 'Replace using RegExpr';
    CreateLabel(Form, 10, 10, 'Regular Expression:');
    cbbRegExp := CreateComboBox(Form, 110, 10, 470, '');
    cbbRegExp.OnKeyPress := @cbbRegExpKeyPress;
    cbbRegExp.Items.Text := csDefExpression;;
    cbbRegExp.Text := Ini.ReadString(csSection, 'RegExpText', '');
    cbbRegExp.Items.CommaText := Ini.ReadString(csSection, 'RegExpItems', cbbRegExp.Items.CommaText);
    CreateLabel(Form, 10, 40, 'Replace With:');
    cbbRepTo := CreateComboBox(Form, 110, 40, 470, '');
    cbbRepTo.OnKeyPress := @cbbRepToKeyPress;
    cbbRepTo.Items.Text := csDefReplaceWith;
    cbbRepTo.Text := Ini.ReadString(csSection, 'RepToText', '');
    cbbRepTo.Items.CommaText := Ini.ReadString(csSection, 'RepToItems', cbbRepTo.Items.CommaText);
    chkUseSub := CreateCheckBox(Form, 110, 68, 200, 'Use Substitution(supports $1, $2...)', True);
    chkUseSub.Checked := Ini.ReadBool(csSection, 'UseSub', True);
    CreateLabel(Form, 10, 90, 'Source Text:');
    mmoInput := CreateMemo(Form, 110, 90, 470, 200);
    mmoInput.Lines.Text := InputText;
    CreateLabel(Form, 10, 300, 'Preview Text:');
    mmoPreview := CreateMemo(Form, 110, 300, 470, 200);
    btnPreview := CreateButton(Form, 110, 510, '&Preview')
    btnPreview.OnClick := @btnPreviewClick;
    btnOk := CreateButton(Form, 190, 510, '&Ok')
    btnOk.OnClick := @btnOkClick;
    btnCancel := CreateButton(Form, 270, 510, '&Cancel')
    btnCancel.OnClick := @btnCancelClick;
    Result := Form.ShowModal = mrOk;
    if Result then
    begin
      AddComboBoxTextToItems(cbbRegExp, 10);
      AddComboBoxTextToItems(cbbRepTo, 10);
      Ini.WriteString(csSection, 'RegExpText', cbbRegExp.Text);
      Ini.WriteString(csSection, 'RegExpItems', cbbRegExp.Items.CommaText);
      Ini.WriteString(csSection, 'RepToText', cbbRepTo.Text);
      Ini.WriteString(csSection, 'RepToItems', cbbRepTo.Items.CommaText);
      Ini.WriteBool(csSection, 'UseSub', chkUseSub.Checked);

      OutText := ReplaceRegExpr(cbbRegExp.Text, mmoInput.Lines.Text,
        cbbRepTo.Text, chkUseSub.Checked);
    end;
  finally
    Form.Free;
    Ini.Free;
  end;
end;

var
  Lines: TStringList;
  OutText: string;
begin
  Lines := TStringList.Create;
  try
    if IdeGetEditorSelectedLines(Lines) and
      ShowReplaceForm(Lines.Text, OutText) then
    begin
      Lines.Text := OutText;
      IdeSetEditorSelectedLines(Lines);
    end;
  finally
    Lines.Free;
  end;
end.

