unit ReplacePair; { [ReplacePair] [1.1] Delphi 2005 March 2008 LICENSE The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at "http://www.mozilla.org/MPL/" Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. The Original Code is "[ReplacePair.pas / ReplacePair.dfm]". The Initial Developer of the Original Code is Martin Holmes (Victoria, BC, Canada, "http://www.mholmes.com/"). Copyright (C) 2005-8 Martin Holmes and the University of Victoria Computing and Media Centre. The code was co-developed for university and personal projects, and rights are shared by Martin Holmes and the University of Victoria. All Rights Reserved. } { Written by Martin Holmes, October 2005 - March 2008. This unit and associated form constitutes a dialog box used to create and edit a "replace pair" (find text and replace text) used in the Transformer application. Each replace pair constitutes an item in a TransformItems list; when a replace pair is executed, it does a simple search-and-replace operation. There is rudimentary handling for regular expressions, but this should probably be avoided because the TURESearch object used for regexp replacement is a bit buggy, and in any case the script items which are also available can handle regexps much better, through the Mozilla SpiderMonkey JavaScript engine. Dependencies: FormState (to save and reload form state, and also to use its AppDirPath property). TntUnicode libraries (Troy Wolbrink). JEDI Code Library (Project JEDI) } interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, TntForms, TntStdCtrls, Buttons, TntButtons, ExtCtrls, TntExtCtrls, FormState, TntDialogs, jclUnicode, AppEvnts; type TufrmReplacePair = class(TTntForm) upnTop: TTntPanel; umFindThis: TTntMemo; ustFindThis: TTntStaticText; usplHorizontal: TTntSplitter; upnlBottom: TTntPanel; ustReplaceWithThis: TTntStaticText; umReplaceWithThis: TTntMemo; ubnOK: TTntBitBtn; ubnCancel: TTntBitBtn; ustPairName: TTntStaticText; uePairName: TTntEdit; ucbIgnoreCase: TTntCheckBox; ucbUseRegularExpressions: TTntCheckBox; ustmsgRegExpError: TTntStaticText; aeReplacePair: TApplicationEvents; ustmsgContainsControlChars: TTntStaticText; procedure aeReplacePairIdle(Sender: TObject; var Done: Boolean); procedure ubnOKClick(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure FormShow(Sender: TObject); private { Private declarations } FFormStateSaver: TFormStateSaver; function CheckRegularExpression: Boolean; function HasNoControlChars: Boolean; public { Public declarations } procedure Clear; end; var ufrmReplacePair: TufrmReplacePair; implementation {$R *.dfm} procedure TufrmReplacePair.FormShow(Sender: TObject); begin FFormStateSaver := TFormStateSaver.Create(Self, True); //To use XML uePairName.SetFocus; end; procedure TufrmReplacePair.FormClose(Sender: TObject; var Action: TCloseAction); begin FreeAndNil(FFormStateSaver); end; procedure TufrmReplacePair.Clear; begin uePairName.Text := ''; umFindThis.Text := ''; umReplaceWithThis.Text := ''; ucbIgnoreCase.Checked := False; ucbUseRegularExpressions.Checked := False; end; procedure TufrmReplacePair.ubnOKClick(Sender: TObject); begin if (CheckRegularExpression = False) {or (HasNoControlChars = False)} then ModalResult := mrNone else ModalResult := mrOK; end; //This function not called, because we're going to handle this problem //in the file i/o using escapes. function TufrmReplacePair.HasNoControlChars: Boolean; var wsFindThis, wsReplaceWithThis, wsName: WideString; function DoCheck(wsInput: WideString): Boolean; var i: integer; begin Result := True; if Length(wsInput) > 0 then for i := 1 to Length(wsInput) do if Ord(wsInput[i]) in [$01..$08, $0b..$0c, $0e..$1f, $7f..$84, $86..$9f] then begin Result := False; Break; end; end; begin Result := True; //default wsFindThis := umFindThis.Text; wsReplaceWithThis := umReplaceWithThis.Text; wsName := uePairName.Text; Result := DoCheck(wsFindThis) and DoCheck(wsReplaceWithThis) and DoCheck(wsName); if Result = False then WideMessageDlg(ustmsgContainsControlChars.Caption, mtWarning, [mbOK], 0); end; function TufrmReplacePair.CheckRegularExpression: Boolean; var URESearch: TURESearch; URESearchFlags: TSearchFlags; wsFindText: WideString; begin Result := False; //default -- be wary because of nasty bugs in TURESearch if ucbUseRegularExpressions.Checked = False then begin Result := True; Exit; end; wsFindText := umFindThis.Text; if wsFindText[1] in [WideChar('+'), WideChar('?'), WideChar('*')] then begin WideMessageDlg(ustmsgRegExpError.Caption, mtWarning, [mbOK], 0); Exit; end; URESearch := TURESearch.Create(nil); try try if ucbIgnoreCase.Checked then URESearchFlags := [] else URESearchFlags := [sfCaseSensitive]; URESearch.FindPrepare(wsFindText, URESearchFlags); except WideMessageDlg(ustmsgRegExpError.Caption, mtWarning, [mbOK], 0); Exit; end; finally FreeAndNil(URESearch); end; Result := True; end; procedure TufrmReplacePair.aeReplacePairIdle(Sender: TObject; var Done: Boolean); begin ubnOK.Enabled := (Length(umFindThis.Text) > 0); end; end.