📄 synautocorrect.pas
字号:
{-------------------------------------------------------------------------------
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: SynAutoCorrect.pas, released 2001-10-05.
Author of this file is Aaron Chan. All Rights Reserved.
Contributors to the SynEdit and mwEdit projects are listed in the
Contributors.txt file.
Alternatively, the contents of this file may be used under the terms of the
GNU General Public License Version 2 or later (the "GPL"), in which case
the provisions of the GPL are applicable instead of those above.
If you wish to allow use of your version of this file only under the terms
of the GPL and not to allow others to use your version of this file
under the MPL, indicate your decision by deleting the provisions above and
replace them with the notice and other provisions required by the GPL.
If you do not delete the provisions above, a recipient may use your version
of this file under either the MPL or the GPL.
$Id: SynAutoCorrect.pas,v 1.13 2004/05/06 19:16:42 markonjezic Exp $
You may retrieve the latest version of this file at the SynEdit home page,
located at http://SynEdit.SourceForge.net
-------------------------------------------------------------------------------}
{*******************************************************}
{ }
{ Aerodynamica Components }
{ SynAutoCorrect 2.x }
{ }
{ Copyright (c) 1996-2003, Aerodynamica Software }
{ }
{ Author: Aaron Chan }
{ Portions by Greg Nixon and Jan Fiala }
{ }
{*******************************************************}
{
@author: Aaron Chan
@url: http://aerodynamica.idz.net
@comp-url: http://aerodynamica.idz.net/products.asp?id=SynAC_2
@email: aerodynamica@idz.net
@last-updated: 12/04/03
@history:
! comment * changed + added
- removed @ bug-fixed # todo
12/04/2003
- removed integrated sound support.
* changed keyboard and mouse handling to use SynEdit plugin system.
11/04/04 - Release 2.21:
@ Fixed support for correction after delimiters.
* SOUND_SUPPORT undefined by default.
24/03/03 - Release 2.2:
@ Fixed "Stack Overflow" bug and memory leak (fixed by Danail Traichev).
30/09/02 - Release 2.1:
@ Fixed bug when user KeyDown and MouseDown events weren't fired.
+ Added INI_FILES and REGISTRY compiler defines (to minimize code size
if you don't need these features).
* Further tidy-up of code.
* Quite a few minor bug-fixes and tweaks.
* Items editor enhanced.
* Improved demo.
* Registry and INI file entries are saved in a new and improved way, which
overcomes some limitations set by the old method. If you still want to
use the old method, define OLD_SAVE_METHOD.
31/07/02 - Revision 2.01:
@ Fixed bug which occured when undefining SOUND_SUPPORT (reported by
Stefan Ascher).
30/07/02 - First public release of version 2.0:
@ MANY bugs fixed and small tweaks everywhere in the code (some
courtesy of Jan Fiala).
+ Ability to play an optional WAVE file (or beep) on correction.
+ Options set.
* New demo.
}
{$IFNDEF QSYNAUTOCORRECT}
unit SynAutoCorrect;
{$ENDIF}
{$I SynEdit.inc}
interface
uses
{$IFDEF SYN_WIN32} //Borland translation of Qt doesn't include Char handling
Windows,
{$ELSE}
Libc,
{$ENDIF}
{$IFDEF SYN_CLX}
QGraphics,
QControls,
QForms,
QDialogs,
Types,
QSynEditMiscProcs,
QSynEditTypes,
QSynEditKeyCmds,
QSynEdit,
{$ELSE}
Registry,
Messages,
Graphics,
Controls,
Forms,
Dialogs,
SynEditMiscProcs,
SynEditTypes,
SynEditKeyCmds,
SynEdit,
SynEditMiscClasses, //TBetterRegistry
{$ENDIF}
Classes,
SysUtils,
IniFiles;
type
TAsSynAutoCorrectOption = (ascoCorrectOnMouseDown, ascoIgnoreCase,
ascoMaintainCase);
TAsSynAutoCorrectOptions = set of TAsSynAutoCorrectOption;
TAutoCorrectAction = (aaCorrect, aaAbort);
TAutoCorrectEvent = procedure(Sender: TObject;
const AOriginal, ACorrection: string; Line, Column: Integer;
var Action: TAutoCorrectAction) of object;
TCustomSynAutoCorrect = class(TComponent)
private
{ Private declarations }
{ Published properties and events. }
FEditor: TCustomSynEdit;
FEnabled: Boolean;
FItems: TStrings;
FItemSepChar: Char;
FOptions: TAsSynAutoCorrectOptions;
fEditors: TList;
FOnAutoCorrect: TAutoCorrectEvent;
FOnCorrected: TNotifyEvent;
{ Private variables and methods. }
// FPrevLine: Integer;
function CorrectItemStart(EditLine, SearchString: string; StartPos: LongInt;
MatchCase, WholeWord: Boolean): LongInt;
function FindAndCorrect(Editor: TCustomSynEdit; var EditLine: string;
Original, Correction: string; var CurrentX: Integer): Boolean;
function PreviousToken(Editor: TCustomSynEdit): string;
{ Accessor methods. }
function GetItems: TStrings;
procedure SetItems(const Value: TStrings);
protected
{ Protected declarations }
procedure KeyboardHandler(Sender: TObject; AfterProcessing: boolean;
var Handled: boolean; var Command: TSynEditorCommand; var AChar: char;
Data: pointer; HandlerData: pointer); virtual;
procedure MouseDownHandler(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer); virtual;
procedure Notification(AComponent: TComponent;
Operation: TOperation); override;
procedure SetEditor(Value: TCustomSynEdit);
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
//mod Add
procedure AddEditor(AEditor: TCustomSynEdit);
//mod Add
function RemoveEditor(AEditor: TCustomSynEdit): boolean;
procedure Add(AOriginal, ACorrection: string);
function AutoCorrectAll(Editor: TCustomSynEdit): Boolean;
procedure Delete(AIndex: Integer);
procedure Edit(AIndex: Integer; ANewOriginal, ANewCorrection: string);
// mod 把选项也保存进去
procedure LoadFromINI(Reg : TCustomIniFile; ASection: string);
procedure SaveToINI(Reg : TCustomIniFile; ASection: string);
{$IFNDEF SYN_CLX}
// mod 把选项也保存进去
procedure LoadFromRegistry(ARoot: DWORD; AKey: string);
procedure SaveToRegistry(ARoot: DWORD; AKey: string);
{$ENDIF}
function LoadFromList(AFileName: string): Boolean;
procedure SaveToList(AFileName: string);
{ Utility functions. }
function HalfString(Str: string; GetFirstHalf: Boolean): string;
public
{ Published declarations }
property Enabled: Boolean read FEnabled write FEnabled default True;
property Editor: TCustomSynEdit read FEditor write SetEditor;
property Items: TStrings read GetItems write SetItems;
property ItemSepChar: Char read FItemSepChar write FItemSepChar default #9;
property Options: TAsSynAutoCorrectOptions read FOptions write FOptions
default [ascoIgnoreCase, ascoMaintainCase];
property OnAutoCorrect: TAutoCorrectEvent read FOnAutoCorrect
write FOnAutoCorrect;
property OnCorrected: TNotifyEvent read FOnCorrected write FOnCorrected;
end;
TSynAutoCorrect = class(TCustomSynAutoCorrect)
published
{ Published declarations }
property Enabled;
property Editor;
property Items;
property ItemSepChar;
property Options;
property OnAutoCorrect;
property OnCorrected;
end;
var
AC_IdentChars: set of char;
implementation
const
FStrSepChar = '|';
{ TCustomSynAutoCorrect }
constructor TCustomSynAutoCorrect.Create(AOwner: TComponent);
var
i: char;
begin
inherited Create(AOwner);
{$IFDEF SYN_WIN32}
for i := #33 to #255 do if IsCharAlphaNumeric(i) then Include(AC_IdentChars, i);
{$ELSE}
for i := #33 to #255 do if isalpha(Ord(i)) <> 0 then Include(AC_IdentChars, i);
{$ENDIF}
FEnabled := True;
FItems := TStringList.Create;
FItemSepChar := #9;
FOptions := [ascoIgnoreCase, ascoMaintainCase];
// FPrevLine := -1;
// FEditor := nil; initialized by Delphi
FEditors := TList.Create;
end;
destructor TCustomSynAutoCorrect.Destroy;
begin
Editor := nil;
inherited;
FItems.Free;
FEditors.Free;
end;
{ Utilities. }
function TCustomSynAutoCorrect.HalfString(Str: string;
GetFirstHalf: Boolean): string;
var
i: Integer;
begin
i := LastDelimiter(FItemSepChar, Str);
if i = 0 then i := Pred(MaxInt);
if GetFirstHalf then
Result := Copy(Str, 1, Pred(i))
else
Result := Copy(Str, Succ(i), MaxInt);
end;
procedure TCustomSynAutoCorrect.LoadFromIni(Reg: TCustomIniFile;
ASection: string);
var
i: Integer;
Original, Correction: string;
// Reg: TIniFile;
Option :TAsSynAutoCorrectOption;
OptionStr : string;
Link : string;
FileItem : TStrings;
begin
// Reg := TIniFile.Create(AFileName);
// try
FItems.Clear;
with Reg do
begin
Link := ReadString(ASection, 'Link', '');
if Link <> '' then Link := ExpandFile(Link);
if FileExists(Link) then
begin
FileItem := TStringList.Create;
try
FileItem.LoadFromFile(Link);
FItems.AddStrings(FileItem);
finally
FileItem.Free;
end;
end
else if ReadInteger(ASection, 'Count', 0) > 0 then
begin
for i := 0 to Pred(ReadInteger(ASection, 'Count', 0)) do
begin
Original := ReadString(ASection, 'Original' + IntToStr(i), '');
Correction := ReadString(ASection, 'Correction' + IntToStr(i), '');
if not ((Original = '') and (Correction = '')) then
FItems.Add(Original + FItemSepChar + Correction);
end;
end;
Enabled := ReadBool(ASection, 'Enabled', Enabled);
ItemSepChar := Char(ReadInteger(ASection, 'ItemSepChar', Ord(ItemSepChar)));
for Option := ascoCorrectOnMouseDown to ascoMaintainCase do
OptionStr := OptionStr + IntToStr(Integer(Option in Options));
OptionStr := ReadString(ASection, 'Options', OptionStr);
for I := 1 to Length(OptionStr) do
if (OptionStr[i] = '1') then
FOptions := FOptions + [TAsSynAutoCorrectOption(I-1)];
end;
// finally
// Reg.Free;
// end;
end;
procedure TCustomSynAutoCorrect.SaveToIni(Reg : TCustomIniFile; ASection: string);
var
i: Integer;
// Reg: TIniFile;
Option :TAsSynAutoCorrectOption;
OptionStr : string;
Link : string;
begin
// Reg := TIniFile.Create(AFileName);
// try
with Reg do
begin
Link := ReadString(ASection, 'Link', '');
if Link <> '' then Link := ExpandFile(Link);
if FileExists(Link) then
begin
FItems.SaveToFile(Link);
end
else begin
WriteInteger(ASection, 'Count', FItems.Count);
for i := 0 to Pred(FItems.Count) do
begin
WriteString(ASection, 'Original' + IntToStr(i),
HalfString(FItems[i], True));
WriteString(ASection, 'Correction' + IntToStr(i),
HalfString(FItems[i], False));
end;
WriteBool(ASection, 'Enabled', Enabled);
WriteInteger(ASection, 'ItemSepChar', Ord(ItemSepChar));
for Option := ascoCorrectOnMouseDown to ascoMaintainCase do
OptionStr := OptionStr + IntToStr(Integer(Option in Options));
WriteString(ASection, 'Options', OptionStr);
end;
end;
// finally
// Reg.Free;
// end;
end;
function TCustomSynAutoCorrect.LoadFromList(AFileName: string): Boolean;
begin
Result := False;
if FileExists(AFileName) then
begin
FItems.LoadFromFile(AFileName);
Result := True;
end;
end;
procedure TCustomSynAutoCorrect.SaveToList(AFileName: string);
begin
FItems.SaveToFile(AFileName);
end;
{$IFNDEF SYN_CLX}
procedure TCustomSynAutoCorrect.LoadFromRegistry(ARoot: DWORD; AKey: string);
var
i: Integer;
Original, Correction: string;
Reg: TRegIniFile;
Option :TAsSynAutoCorrectOption;
OptionStr : string;
Link : string;
FileItem : TStrings;
begin
Reg := TRegIniFile.Create('');
try
with Reg do
begin
RootKey := ARoot;
TBetterRegistry(Reg).OpenKeyReadOnly(AKey);
FItems.Clear;
for i := 0 to Pred(ReadInteger('', 'Count', 0)) do
begin
Original := ReadString('', 'Original' + IntToStr(i), '');
Correction := ReadString('', 'Correction' + IntToStr(i), '');
if not ((Original = '') and (Correction = '')) then
FItems.Add(Original + FItemSepChar + Correction);
end;
Link := ReadString('', 'Link', '');
if Link <> '' then
begin
Link := ExpandFile(Link);
if FileExists(Link) then
begin
FileItem := TStringList.Create;
try
FileItem.LoadFromFile(Link);
FItems.AddStrings(FileItem);
finally
FileItem.Free;
end;
end;
end;
Enabled := ReadBool('', 'Enabled', Enabled);
ItemSepChar := Char(ReadInteger('', 'ItemSepChar', Ord(ItemSepChar)));
for Option := ascoCorrectOnMouseDown to ascoMaintainCase do
OptionStr := OptionStr + IntToStr(Integer(Option in Options));
OptionStr := ReadString('', 'Options', OptionStr);
for I := 1 to Length(OptionStr) do
if (OptionStr[i] = '1') then
FOptions := FOptions + [TAsSynAutoCorrectOption(I-1)];
end;
finally
Reg.Free;
end;
end;
procedure TCustomSynAutoCorrect.SaveToRegistry(ARoot: DWORD; AKey: string);
var
i: Integer;
Reg: TRegIniFile;
Option :TAsSynAutoCorrectOption;
OptionStr : string;
begin
Reg := TRegIniFile.Create('');
try
with Reg do
begin
RootKey := ARoot;
OpenKey(AKey, True);
WriteInteger('', 'Count', FItems.Count);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -