git-svn-id: https://192.168.0.254/svn/Componentes.Terceros.DevExpressVCL@29 05c56307-c608-d34a-929d-697000501d7a
4102 lines
124 KiB
ObjectPascal
4102 lines
124 KiB
ObjectPascal
{********************************************************************}
|
|
{ }
|
|
{ Developer Express Visual Component Library }
|
|
{ ExpressSpellChecker }
|
|
{ }
|
|
{ Copyright (c) 1998-2008 Developer Express Inc. }
|
|
{ ALL RIGHTS RESERVED }
|
|
{ }
|
|
{ The entire contents of this file is protected by U.S. and }
|
|
{ International Copyright Laws. Unauthorized reproduction, }
|
|
{ reverse-engineering, and distribution of all or any portion of }
|
|
{ the code contained in this file is strictly prohibited and may }
|
|
{ result in severe civil and criminal penalties and will be }
|
|
{ prosecuted to the maximum extent possible under the law. }
|
|
{ }
|
|
{ RESTRICTIONS }
|
|
{ }
|
|
{ THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES }
|
|
{ (DCU, OBJ, DLL, ETC.) ARE CONFIDENTIAL AND PROPRIETARY TRADE }
|
|
{ SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS }
|
|
{ LICENSED TO DISTRIBUTE THE EXPRESSSPELLCHECKER AND ALL }
|
|
{ ACCOMPANYING VCL CONTROLS AS PART OF AN EXECUTABLE PROGRAM ONLY. }
|
|
{ }
|
|
{ THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED }
|
|
{ FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE }
|
|
{ COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE }
|
|
{ AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT }
|
|
{ AND PERMISSION FROM DEVELOPER EXPRESS INC. }
|
|
{ }
|
|
{ CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON }
|
|
{ ADDITIONAL RESTRICTIONS. }
|
|
{ }
|
|
{********************************************************************}
|
|
|
|
unit dxSpellChecker;
|
|
|
|
{$I cxVer.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
Types, Windows, SysUtils, Messages, Classes, Graphics, cxClasses, Controls,
|
|
Forms, StdCtrls, cxControls, dxSpellCheckerRules, dxSpellCheckerAlgorithms,
|
|
cxLookAndFeels, cxTextEdit, cxRichEdit, Menus;
|
|
|
|
type
|
|
TdxCustomSpellChecker = class;
|
|
TdxSpellCheckerWordList = class;
|
|
TdxSpellCheckerTextParser = class;
|
|
TdxCustomSpellCheckerDictionary = class;
|
|
TdxSpellCheckerSuggestionList = class;
|
|
TdxSpellCheckerSpellingOptions = class;
|
|
TdxSpellCheckerCheckAsYouTypeOptions = class;
|
|
|
|
EdxSpellCheckerException = class(Exception);
|
|
|
|
{ TdxSpellCheckerLanguages }
|
|
|
|
TdxSpellCheckerLanguages = class(TLanguages)
|
|
public
|
|
function GetDefaultLanguageLCID: DWORD;
|
|
function GetLCID(const AName: string): DWORD;
|
|
end;
|
|
|
|
{ TdxSpellCheckerSuggestion }
|
|
|
|
TdxSpellCheckerSuggestion = class
|
|
private
|
|
FDictionary: TdxCustomSpellCheckerDictionary;
|
|
FDistance: Integer;
|
|
FWord: WideString;
|
|
public
|
|
constructor Create(const AWord: WideString;
|
|
ADictionary: TdxCustomSpellCheckerDictionary; ADistance: Integer);
|
|
|
|
property Dictionary: TdxCustomSpellCheckerDictionary read FDictionary;
|
|
property Distance: Integer read FDistance;
|
|
property Word: WideString read FWord;
|
|
end;
|
|
|
|
{ TdxSpellCheckerSuggestionList }
|
|
|
|
TdxSpellCheckerSuggestionList = class(TcxObjectList)
|
|
private
|
|
function GetItem(Index: Integer): TdxSpellCheckerSuggestion;
|
|
public
|
|
procedure Add(const AWord: WideString;
|
|
ADictionary: TdxCustomSpellCheckerDictionary; ADistance: Integer);
|
|
procedure Delete(AIndex: Integer);
|
|
procedure FixCapitalization(const AMask: WideString);
|
|
procedure RemoveDuplicates;
|
|
procedure SortByWord;
|
|
procedure SortByDistance;
|
|
procedure SaveToStrings(AStrings: TStrings);
|
|
|
|
property Items[Index: Integer]: TdxSpellCheckerSuggestion read GetItem; default;
|
|
end;
|
|
|
|
{ TdxSpellCheckerReplacementItem }
|
|
|
|
TdxSpellCheckerReplacementItem = class
|
|
private
|
|
FReplacement: WideString;
|
|
FText: WideString;
|
|
public
|
|
constructor Create(const AText, AReplacement: WideString);
|
|
|
|
property Replacement: WideString read FReplacement;
|
|
property Text: WideString read FText;
|
|
end;
|
|
|
|
{ TdxSpellCheckerReplacementList }
|
|
|
|
TdxSpellCheckerReplacementList = class(TcxObjectList)
|
|
private
|
|
FAllowDuplicates: Boolean;
|
|
function GetItem(AIndex: Integer): TdxSpellCheckerReplacementItem;
|
|
public
|
|
constructor Create(AllowDuplicates: Boolean = False);
|
|
procedure Add(const AText, AReplacement: WideString);
|
|
function FindReplacement(const AText: WideString): TdxSpellCheckerReplacementItem;
|
|
procedure SortByText;
|
|
|
|
property Items[Index: Integer]: TdxSpellCheckerReplacementItem read GetItem; default;
|
|
end;
|
|
|
|
{ TdxSpellCheckerCustomEditAdapter }
|
|
|
|
TdxSpellCheckerCustomEditAdapter = class(TObject)
|
|
protected
|
|
FEdit: TWinControl;
|
|
FText: WideString;
|
|
FSelStart: Integer;
|
|
FSelLength: Integer;
|
|
function EditorHandleAllocated: Boolean;
|
|
function GetEditorHandle: THandle; virtual;
|
|
function GetHideSelection: Boolean; virtual; abstract;
|
|
function GetReadOnly: Boolean; virtual; abstract;
|
|
function GetSelLength: Integer; virtual; abstract;
|
|
function GetSelStart: Integer; virtual; abstract;
|
|
function GetSelText: string; virtual; abstract;
|
|
function GetText: WideString; virtual;
|
|
procedure Post(AUpdateValue: Boolean = True); virtual;
|
|
procedure SetHideSelection(AValue: Boolean); virtual; abstract;
|
|
procedure SetSelLength(AValue: Integer); virtual; abstract;
|
|
procedure SetSelStart(AValue: Integer); virtual; abstract;
|
|
procedure SetSelText(const AValue: string); virtual; abstract;
|
|
function IsInplace: Boolean;
|
|
public
|
|
constructor Create(AEdit: TWinControl); virtual;
|
|
procedure ClearSelection; virtual; abstract;
|
|
procedure GetSpellingBounds(out ASpellingStart, ASpellingEnd: Integer); virtual;
|
|
|
|
property EditorHandle: THandle read GetEditorHandle;
|
|
property HideSelection: Boolean read GetHideSelection write SetHideSelection;
|
|
property ReadOnly: Boolean read GetReadOnly;
|
|
property SelLength: Integer read GetSelLength write SetSelLength;
|
|
property SelStart: Integer read GetSelStart write SetSelStart;
|
|
property SelText: string read GetSelText write SetSelText;
|
|
property Text: WideString read GetText;
|
|
end;
|
|
|
|
{ TdxSpellCheckercxTextEditAdapter }
|
|
|
|
TdxSpellCheckercxTextEditAdapter = class(TdxSpellCheckerCustomEditAdapter)
|
|
private
|
|
function GetEdit: TcxCustomTextEdit;
|
|
protected
|
|
function GetHideSelection: Boolean; override;
|
|
function GetReadOnly: Boolean; override;
|
|
function GetSelLength: Integer; override;
|
|
function GetSelStart: Integer; override;
|
|
function GetSelText: string; override;
|
|
procedure SetHideSelection(AValue: Boolean); override;
|
|
procedure SetSelLength(AValue: Integer); override;
|
|
procedure SetSelStart(AValue: Integer); override;
|
|
procedure SetSelText(const AValue: string); override;
|
|
property Edit: TcxCustomTextEdit read GetEdit;
|
|
public
|
|
procedure ClearSelection; override;
|
|
end;
|
|
|
|
{ TdxSpellCheckercxRichEditAdapter }
|
|
|
|
TdxSpellCheckercxRichEditAdapter = class(TdxSpellCheckercxTextEditAdapter)
|
|
private
|
|
function GetEdit: TcxCustomRichEdit;
|
|
protected
|
|
function GetReadOnly: Boolean; override;
|
|
function GetText: WideString; override;
|
|
property Edit: TcxCustomRichEdit read GetEdit;
|
|
end;
|
|
|
|
{ TdxSpellCheckerEditAdapter }
|
|
|
|
TdxSpellCheckerEditAdapter = class(TdxSpellCheckerCustomEditAdapter)
|
|
private
|
|
function GetEdit: TCustomEdit;
|
|
protected
|
|
function GetHideSelection: Boolean; override;
|
|
function GetReadOnly: Boolean; override;
|
|
function GetSelLength: Integer; override;
|
|
function GetSelStart: Integer; override;
|
|
function GetSelText: string; override;
|
|
procedure SetHideSelection(AValue: Boolean); override;
|
|
procedure SetSelLength(AValue: Integer); override;
|
|
procedure SetSelStart(AValue: Integer); override;
|
|
procedure SetSelText(const AValue: string); override;
|
|
property Edit: TCustomEdit read GetEdit;
|
|
public
|
|
procedure ClearSelection; override;
|
|
end;
|
|
|
|
{ TdxSpellCheckerTextParser }
|
|
|
|
TdxSpellCheckerSentence = record
|
|
StartTextPosition: Integer;
|
|
StartWordPosition: Integer;
|
|
Text: WideString;
|
|
end;
|
|
|
|
TdxSpellCheckerTextParser = class(TdxCustomSpellCheckerTextHelper)
|
|
private
|
|
FSpellChecker: TdxCustomSpellChecker;
|
|
function LastWideCharIsSpace(const S: WideString): Boolean;
|
|
protected
|
|
FDelimiters: WideString;
|
|
FUrlDelimiters: WideString;
|
|
FPrevWord: WideString;
|
|
FSpellingEnd: Integer;
|
|
FSpellingStart: Integer;
|
|
FText: WideString;
|
|
function IsDelimiter(AChar: WideChar): Boolean;
|
|
function IsUrlDelimiter(AChar: WideChar): Boolean;
|
|
procedure UpdateTextInfo(AAdapter: TdxSpellCheckerCustomEditAdapter); virtual;
|
|
|
|
property SpellChecker: TdxCustomSpellChecker read FSpellChecker;
|
|
public
|
|
constructor Create(ASpellChecker: TdxCustomSpellChecker); virtual;
|
|
destructor Destroy; override;
|
|
|
|
function GetNextWord(var AStart, ALength: Integer; out ADelimiters: WideString): WideString; virtual;
|
|
function GetPrevWord: WideString; override;
|
|
function WordExists(const AWord: WideString): Boolean; override;
|
|
|
|
function GetNextDelimiterPosition(var AStart: Integer; ADirection: Integer): Boolean;
|
|
function GetSentence(APos: Integer): TdxSpellCheckerSentence; virtual;
|
|
function GetSuggestions(const AWord: WideString): TdxSpellCheckerSuggestionList; virtual;
|
|
|
|
property Delimiters: WideString read FDelimiters write FDelimiters;
|
|
property UrlDelimiters: WideString read FUrlDelimiters write FUrlDelimiters;
|
|
property Text: WideString read FText;
|
|
end;
|
|
|
|
TdxSpellCheckerTextParserClass = class of TdxSpellCheckerTextParser;
|
|
|
|
{ TdxSpellCheckerUndoItem }
|
|
|
|
TdxSpellCheckerUndoItem = class
|
|
private
|
|
FMisspelledWord: WideString;
|
|
FMisspelledWordPosition: Integer;
|
|
FPrevWord: WideString;
|
|
FReplacement: WideString;
|
|
public
|
|
constructor Create(const AMisspelledWord, AReplacement, APrevWord: WideString; AMisspelledWordPosition: Integer);
|
|
|
|
property MisspelledWord: WideString read FMisspelledWord;
|
|
property MisspelledWordPosition: Integer read FMisspelledWordPosition;
|
|
property PrevWord: WideString read FPrevWord;
|
|
property Replacement: WideString read FReplacement;
|
|
end;
|
|
|
|
{ TdxSpellCheckerUndoManager }
|
|
|
|
TdxSpellCheckerUndoManager = class(TPersistent)
|
|
private
|
|
FUndoList: TcxObjectList;
|
|
function GetCount: Integer;
|
|
function GetItem(AIndex: Integer): TdxSpellCheckerUndoItem;
|
|
function GetLast: TdxSpellCheckerUndoItem;
|
|
public
|
|
constructor Create;
|
|
destructor Destroy; override;
|
|
|
|
procedure Add(const AMisspelledWord, AReplacement, APrevWord: WideString; AMisspelledWordPosition: Integer);
|
|
procedure UndoLast;
|
|
|
|
property Count: Integer read GetCount;
|
|
property Last: TdxSpellCheckerUndoItem read GetLast;
|
|
property Items[AIndex: Integer]: TdxSpellCheckerUndoItem read GetItem; default;
|
|
end;
|
|
|
|
{ TdxSpellCheckerCustomCheckMode }
|
|
|
|
TdxSpellCheckerCustomCheckMode = class(TPersistent)
|
|
private
|
|
FAdapter: TdxSpellCheckerCustomEditAdapter;
|
|
FParser: TdxSpellCheckerTextParser;
|
|
FSpellChecker: TdxCustomSpellChecker;
|
|
FSpellingEnd: Integer;
|
|
FSpellingStart: Integer;
|
|
function GetPrevWord: WideString;
|
|
procedure SetPrevWord(const AValue: WideString);
|
|
procedure SetSpellingEnd(const AValue: Integer);
|
|
procedure SetSpellingStart(const AValue: Integer);
|
|
protected
|
|
FLastCode: TdxSpellCheckerSpellingCode;
|
|
FMisspelledLen: Integer;
|
|
FMisspelledStart: Integer;
|
|
FMisspelledWord: WideString;
|
|
function CheckWord(const AWord: WideString): TdxSpellCheckerSpellingCode; virtual;
|
|
procedure CreateParser; virtual;
|
|
function GetNextWord(out AWord: WideString): Boolean; virtual;
|
|
function GetOwner: TPersistent; override;
|
|
function GetParserClass: TdxSpellCheckerTextParserClass; virtual;
|
|
function InternalProcessWord(const AWord: WideString): Boolean; virtual;
|
|
function IsNeedChangeWord(const AWord: WideString;
|
|
out AReplacement: WideString): Boolean; virtual;
|
|
function IsNeedDeleteWord(const AWord: WideString): Boolean; virtual;
|
|
function IsNeedIgnoreWord(const AWord: WideString): Boolean; virtual;
|
|
function IsValidWord(const AWord: WideString): Boolean; virtual;
|
|
procedure SaveSelection; virtual;
|
|
procedure SelectMisspelledWord; virtual;
|
|
procedure SelectMisspelledWordAfterUndo; virtual;
|
|
procedure UpdateByDictionary(ADictionary: TdxCustomSpellCheckerDictionary); virtual;
|
|
procedure UpdateSpellingBounds(ADelta: Integer); virtual;
|
|
procedure UpdateTextInfo; virtual;
|
|
procedure ValidateSpellingBounds; virtual;
|
|
|
|
property PrevWord: WideString read GetPrevWord write SetPrevWord;
|
|
property SpellingEnd: Integer read FSpellingEnd write SetSpellingEnd;
|
|
property SpellingStart: Integer read FSpellingStart write SetSpellingStart;
|
|
public
|
|
constructor Create(AOwner: TdxCustomSpellChecker; AAdapter: TdxSpellCheckerCustomEditAdapter); virtual;
|
|
destructor Destroy; override;
|
|
|
|
procedure Add; virtual;
|
|
function CanUndo: Boolean; virtual;
|
|
procedure Change(const AWord: WideString); virtual;
|
|
procedure ChangeAll(const AWord: WideString); virtual;
|
|
procedure Delete; virtual;
|
|
procedure DeleteAll; virtual;
|
|
function GetSuggestions(const AWord: WideString): TdxSpellCheckerSuggestionList; virtual;
|
|
function GetNextMisspelledWord: Boolean; virtual;
|
|
procedure Ignore; virtual;
|
|
procedure IgnoreAll; virtual;
|
|
procedure UndoLast; virtual;
|
|
|
|
property Adapter: TdxSpellCheckerCustomEditAdapter read FAdapter;
|
|
property LastCode: TdxSpellCheckerSpellingCode read FLastCode;
|
|
property MisspelledWord: WideString read FMisspelledWord;
|
|
property Parser: TdxSpellCheckerTextParser read FParser;
|
|
property SpellChecker: TdxCustomSpellChecker read FSpellChecker;
|
|
end;
|
|
|
|
TdxSpellCheckerCustomCheckModeClass = class of TdxSpellCheckerCustomCheckMode;
|
|
|
|
{ TdxSpellCheckerDialogCheckMode }
|
|
|
|
TdxSpellCheckerDialogCheckMode = class(TdxSpellCheckerCustomCheckMode)
|
|
private
|
|
FCheckedSelection: Boolean;
|
|
FSaveHideSelection: Boolean;
|
|
FSaveSelLength: Integer;
|
|
FSaveSelStart: Integer;
|
|
FUndoManager: TdxSpellCheckerUndoManager;
|
|
function GetLanguages: TdxSpellCheckerLanguages;
|
|
protected
|
|
procedure CreateParser; override;
|
|
function IsCheckingSelectedText: Boolean; virtual;
|
|
procedure SaveSelection; override;
|
|
procedure ValidateSpellingBounds; override;
|
|
procedure ValidateSpellingBoundsAfterUndo;
|
|
|
|
property UndoManager: TdxSpellCheckerUndoManager read FUndoManager;
|
|
public
|
|
constructor Create(AOwner: TdxCustomSpellChecker; AAdapter: TdxSpellCheckerCustomEditAdapter); override;
|
|
destructor Destroy; override;
|
|
|
|
function CanUndo: Boolean; override;
|
|
procedure Change(const AWord: WideString); override;
|
|
procedure Delete; override;
|
|
procedure Ignore; override;
|
|
function ShowDialog: Integer; virtual;
|
|
procedure UndoLast; override;
|
|
|
|
property Languages: TdxSpellCheckerLanguages read GetLanguages;
|
|
end;
|
|
|
|
{ TdxSpellCheckerOutlookCheckMode }
|
|
|
|
TdxSpellCheckerOutlookCheckMode = class(TdxSpellCheckerDialogCheckMode)
|
|
protected
|
|
procedure SelectMisspelledWordAfterUndo; override;
|
|
public
|
|
function ShowDialog: Integer; override;
|
|
end;
|
|
|
|
{ TdxSpellCheckerWordCheckMode }
|
|
|
|
TdxSpellCheckerWordCheckMode = class(TdxSpellCheckerDialogCheckMode)
|
|
private
|
|
function GetMisspelledSentence: TdxSpellCheckerSentence;
|
|
protected
|
|
procedure SelectMisspelledWordAfterUndo; override;
|
|
public
|
|
procedure ChangeSentence(const ASentence: WideString); virtual;
|
|
function ShowDialog: Integer; override;
|
|
|
|
property MisspelledSentence: TdxSpellCheckerSentence read GetMisspelledSentence;
|
|
end;
|
|
|
|
{ TdxSpellCheckerWordList }
|
|
|
|
TdxSpellCheckerWordList = class
|
|
private
|
|
FCount: Integer;
|
|
FLangID: Cardinal;
|
|
FLock: TRTLCriticalSection;
|
|
FTable: PPointerList;
|
|
FTableSize: Integer;
|
|
function GetCodePage: Cardinal;
|
|
protected
|
|
function ElfHash(P: PWideChar): Integer;
|
|
function FindWord(const S: WideString): PWideChar;
|
|
function NewWord(S: PWideChar): PWideChar;
|
|
function AllocWord(ACharCount: Cardinal): PWideChar;
|
|
procedure DisposeWord(AWord: PWideChar);
|
|
function GetNextWord(AWord: PWideChar): Pointer;
|
|
procedure SetNextWord(AWord: PWideChar; AValue: Pointer);
|
|
function WordLength(AWord: PWideChar): Integer;
|
|
|
|
property CodePage: Cardinal read GetCodePage;
|
|
public
|
|
constructor Create(ALangID: Cardinal; ATableSize: Integer);
|
|
destructor Destroy; override;
|
|
procedure Add(const S: WideString);
|
|
procedure Clear;
|
|
function Find(const S: WideString): Boolean;
|
|
procedure LoadFromStrings(AStrings: TStrings);
|
|
procedure SaveToStrings(AStrings: TStrings);
|
|
|
|
property Count: Integer read FCount;
|
|
property LangID: Cardinal read FLangID write FLangID;
|
|
end;
|
|
|
|
{ TdxSpellCheckerSuggestionBuilder }
|
|
|
|
TdxSpellCheckerSuggestionBuilder = class
|
|
private
|
|
FAlphabet: WideString;
|
|
FDictionary: TdxCustomSpellCheckerDictionary;
|
|
FSuggestions: TdxSpellCheckerSuggestionList;
|
|
FWord: WideString;
|
|
procedure SetAlphabet(const AValue: WideString);
|
|
protected
|
|
function CanAddToSuggestions(const ATestWord: WideString): Boolean; virtual;
|
|
procedure DoAddSuggestions; virtual; abstract;
|
|
|
|
property Alphabet: WideString read FAlphabet write SetAlphabet;
|
|
property Dictionary: TdxCustomSpellCheckerDictionary read FDictionary;
|
|
property Suggestions: TdxSpellCheckerSuggestionList read FSuggestions;
|
|
property Word: WideString read FWord;
|
|
public
|
|
constructor Create(ADictionary: TdxCustomSpellCheckerDictionary); virtual;
|
|
procedure AddSuggestions(const AWord: WideString; ASuggestions: TdxSpellCheckerSuggestionList); virtual;
|
|
end;
|
|
|
|
{ TdxNearMissStrategy }
|
|
|
|
TdxNearMissStrategy = class(TdxSpellCheckerSuggestionBuilder)
|
|
protected
|
|
procedure CheckAddToSuggestions(const ATestWord: WideString; ADistance: Integer = 2);
|
|
procedure CheckChangeOneLetter;
|
|
procedure CheckInsertLetter;
|
|
procedure CheckInsertSpace;
|
|
procedure CheckDeleteLetter;
|
|
procedure DoAddSuggestions; override;
|
|
procedure InterchangeTwoLetters;
|
|
end;
|
|
|
|
{ TdxDictionaryLoadThread }
|
|
|
|
TdxDictionaryLoadThread = class(TcxThread)
|
|
private
|
|
FDictionary: TdxCustomSpellCheckerDictionary;
|
|
protected
|
|
procedure Execute; override;
|
|
|
|
property Dictionary: TdxCustomSpellCheckerDictionary read FDictionary;
|
|
public
|
|
constructor Create(ADictionary: TdxCustomSpellCheckerDictionary);
|
|
function IsLoadComplete: Boolean;
|
|
end;
|
|
|
|
{ TdxCustomSpellCheckerDictionary }
|
|
|
|
TdxSpellCheckerDictionaryLoadingEvent = procedure (Sender: TdxCustomSpellCheckerDictionary; var AHandled: Boolean) of object;
|
|
TdxSpellCheckerDictionaryLoadedEvent = procedure (Sender: TdxCustomSpellCheckerDictionary) of object;
|
|
TdxSpellCheckerDictionaryLoadMode = (dlmDefault, dlmDirectLoad, dlmThreadedLoad);
|
|
|
|
TdxCustomSpellCheckerDictionary = class(TPersistent)
|
|
private
|
|
FAlphabet: WideString;
|
|
FCodePage: Cardinal;
|
|
FEnabled: Boolean;
|
|
FLanguage: DWORD;
|
|
FLoaded: Boolean;
|
|
FLoadThread: TdxDictionaryLoadThread;
|
|
FSpellChecker: TdxCustomSpellChecker;
|
|
FWords: TdxSpellCheckerWordList;
|
|
FOnLoading: TdxSpellCheckerDictionaryLoadingEvent;
|
|
FOnLoaded: TdxSpellCheckerDictionaryLoadedEvent;
|
|
function GetActive: Boolean;
|
|
function GetWordCount: Integer;
|
|
procedure SetEnabled(AValue: Boolean);
|
|
procedure SetCodePage(AValue: Cardinal);
|
|
procedure SetLanguage(const AValue: DWORD);
|
|
protected
|
|
function CanLoad: Boolean; virtual;
|
|
procedure Cleanup; virtual;
|
|
function CreateSuggestionBuilder: TdxSpellCheckerSuggestionBuilder; virtual;
|
|
procedure DirectLoad; virtual;
|
|
procedure DoActivate; virtual;
|
|
function DoLoad: Boolean; virtual;
|
|
procedure DoLoadedEvent; virtual;
|
|
function DoLoadingEvent: Boolean; virtual;
|
|
function DoUnload: Boolean; virtual;
|
|
function GetActiveAlphabet: WideString; virtual;
|
|
function GetDisplayName: string; virtual;
|
|
procedure LoadingComplete; virtual;
|
|
function LoadingTerminated: Boolean; {$IFDEF DELPHI9} inline; {$ENDIF}
|
|
procedure LoadUsingThread; virtual;
|
|
procedure ThreadDone(Sender: TObject); virtual;
|
|
procedure Update; virtual;
|
|
procedure UpdateLoadedOnLoadEvent;
|
|
|
|
property LoadThread: TdxDictionaryLoadThread read FLoadThread;
|
|
property Words: TdxSpellCheckerWordList read FWords;
|
|
public
|
|
constructor Create(ASpellChecker: TdxCustomSpellChecker); virtual;
|
|
destructor Destroy; override;
|
|
procedure Assign(Source: TPersistent); override;
|
|
|
|
procedure Activate;
|
|
function HasWord(const AWord: WideString): Boolean; virtual;
|
|
|
|
procedure Clear;
|
|
procedure Load(AMode: TdxSpellCheckerDictionaryLoadMode = dlmDefault);
|
|
procedure Unload;
|
|
|
|
property Active: Boolean read GetActive;
|
|
property Alphabet: WideString read FAlphabet write FAlphabet;
|
|
property CodePage: Cardinal read FCodePage write SetCodePage default CP_ACP;
|
|
property Enabled: Boolean read FEnabled write SetEnabled default True;
|
|
property Language: DWORD read FLanguage write SetLanguage default 0;
|
|
property Loaded: Boolean read FLoaded;
|
|
property SpellChecker: TdxCustomSpellChecker read FSpellChecker;
|
|
property WordCount: Integer read GetWordCount;
|
|
property OnLoaded: TdxSpellCheckerDictionaryLoadedEvent read FOnLoaded write FOnLoaded;
|
|
property OnLoading: TdxSpellCheckerDictionaryLoadingEvent read FOnLoading write FOnLoading;
|
|
end;
|
|
|
|
TdxCustomSpellCheckerDictionaryClass = class of TdxCustomSpellCheckerDictionary;
|
|
|
|
{ TdxUserSpellCheckerDictionary }
|
|
|
|
TdxUserSpellCheckerDictionaryOption = (udFileMustExist, udSaveOnUnload);
|
|
TdxUserSpellCheckerDictionaryOptions = set of TdxUserSpellCheckerDictionaryOption;
|
|
|
|
TdxUserSpellCheckerDictionary = class(TdxCustomSpellCheckerDictionary)
|
|
private
|
|
FDictionaryPath: TFileName;
|
|
FOptions: TdxUserSpellCheckerDictionaryOptions;
|
|
protected
|
|
function DoLoad: Boolean; override;
|
|
function DoUnload: Boolean; override;
|
|
function GetDisplayName: string; override;
|
|
public
|
|
constructor Create(ASpellChecker: TdxCustomSpellChecker); override;
|
|
procedure Assign(Source: TPersistent); override;
|
|
procedure AddWord(const AWord: WideString);
|
|
procedure LoadFromStrings(AStrings: TStrings);
|
|
procedure SaveToStrings(AStrings: TStrings);
|
|
published
|
|
property Alphabet;
|
|
property CodePage;
|
|
property Enabled;
|
|
property DictionaryPath: TFileName read FDictionaryPath write FDictionaryPath;
|
|
property Options: TdxUserSpellCheckerDictionaryOptions read FOptions write FOptions default [udSaveOnUnload];
|
|
property OnLoaded;
|
|
property OnLoading;
|
|
end;
|
|
|
|
{ TdxSpellCheckerDictionaryItem }
|
|
|
|
TdxSpellCheckerDictionaries = class;
|
|
|
|
TdxSpellCheckerDictionaryItem = class(TCollectionItem)
|
|
private
|
|
FDictionaryType: TdxCustomSpellCheckerDictionary;
|
|
FDictionaryTypeClass: TdxCustomSpellCheckerDictionaryClass;
|
|
FDictionaryEvents: TNotifyEvent;
|
|
function GetCollection: TdxSpellCheckerDictionaries;
|
|
function GetDictionaryTypeClassName: string;
|
|
procedure SetDictionaryType(AValue: TdxCustomSpellCheckerDictionary);
|
|
procedure SetDictionaryTypeClassName(const AValue: string);
|
|
procedure SetDictionaryTypeClass(AValue: TdxCustomSpellCheckerDictionaryClass);
|
|
protected
|
|
function GetDisplayName: string; override;
|
|
procedure RecreateDictionaryType;
|
|
public
|
|
destructor Destroy; override;
|
|
procedure Assign(Source: TPersistent); override;
|
|
|
|
property Collection: TdxSpellCheckerDictionaries read GetCollection;
|
|
property DictionaryTypeClass: TdxCustomSpellCheckerDictionaryClass read FDictionaryTypeClass write SetDictionaryTypeClass;
|
|
published
|
|
property DictionaryTypeClassName: string read GetDictionaryTypeClassName write SetDictionaryTypeClassName;
|
|
property DictionaryType: TdxCustomSpellCheckerDictionary read FDictionaryType write SetDictionaryType;
|
|
property DictionaryEvents: TNotifyEvent read FDictionaryEvents write FDictionaryEvents;
|
|
end;
|
|
|
|
{ TdxSpellCheckerDictionaries }
|
|
|
|
TdxSpellCheckerDictionaries = class(TCollection)
|
|
private
|
|
FSpellChecker: TdxCustomSpellChecker;
|
|
function GetItem(Index: Integer): TdxSpellCheckerDictionaryItem;
|
|
procedure SetItem(Index: Integer; AValue: TdxSpellCheckerDictionaryItem);
|
|
protected
|
|
function GetOwner: TPersistent; override;
|
|
|
|
property SpellChecker: TdxCustomSpellChecker read FSpellChecker;
|
|
public
|
|
constructor Create(ASpellChecker: TdxCustomSpellChecker);
|
|
function Add: TdxSpellCheckerDictionaryItem;
|
|
function GetNamePath: string; override;
|
|
|
|
property Items[Index: Integer]: TdxSpellCheckerDictionaryItem read GetItem write SetItem; default;
|
|
end;
|
|
|
|
{ TdxSpellCheckerSpellingOptions }
|
|
|
|
TdxSpellCheckerSpellingOptionsChangedEvent = procedure (Sender: TdxSpellCheckerSpellingOptions) of object;
|
|
|
|
TdxSpellCheckerSpellingOptions = class(TPersistent)
|
|
private
|
|
FSpellChecker: TdxCustomSpellChecker;
|
|
FIgnoreMixedCaseWords: Boolean;
|
|
FIgnoreUpperCaseWords: Boolean;
|
|
FIgnoreMarkupTags: Boolean;
|
|
FIgnoreRepeatedWords: Boolean;
|
|
FCheckSelectedTextFirst: Boolean;
|
|
FIgnoreUrls: Boolean;
|
|
FCheckFromCursorPos: Boolean;
|
|
FIgnoreEmails: Boolean;
|
|
FIgnoreWordsWithNumbers: Boolean;
|
|
FOnChanged: TdxSpellCheckerSpellingOptionsChangedEvent;
|
|
procedure SetCheckFromCursorPos(AValue: Boolean);
|
|
procedure SetCheckSelectedTextFirst(AValue: Boolean);
|
|
procedure SetIgnoreEmails(AValue: Boolean);
|
|
procedure SetIgnoreMarkupTags(AValue: Boolean);
|
|
procedure SetIgnoreMixedCaseWords(AValue: Boolean);
|
|
procedure SetIgnoreRepeatedWords(AValue: Boolean);
|
|
procedure SetIgnoreUpperCaseWords(AValue: Boolean);
|
|
procedure SetIgnoreUrls(AValue: Boolean);
|
|
procedure SetIgnoreWordsWithNumbers(AValue: Boolean);
|
|
protected
|
|
procedure Changed; virtual;
|
|
procedure DoChanged; virtual;
|
|
procedure PopulateRules(ARules: TdxSpellCheckerRules;
|
|
AParser: TdxSpellCheckerTextParser); virtual;
|
|
|
|
property SpellChecker: TdxCustomSpellChecker read FSpellChecker;
|
|
|
|
property IgnoreMarkupTags: Boolean read FIgnoreMarkupTags write SetIgnoreMarkupTags default True;
|
|
public
|
|
constructor Create(ASpellChecker: TdxCustomSpellChecker); virtual;
|
|
procedure Assign(Source: TPersistent); override;
|
|
|
|
property OnChanged: TdxSpellCheckerSpellingOptionsChangedEvent read FOnChanged write FOnChanged;
|
|
published
|
|
property CheckFromCursorPos: Boolean read FCheckFromCursorPos write SetCheckFromCursorPos default False;
|
|
property CheckSelectedTextFirst: Boolean read FCheckSelectedTextFirst write SetCheckSelectedTextFirst default True;
|
|
property IgnoreEmails: Boolean read FIgnoreEmails write SetIgnoreEmails default True;
|
|
property IgnoreMixedCaseWords: Boolean read FIgnoreMixedCaseWords write SetIgnoreMixedCaseWords default True;
|
|
property IgnoreRepeatedWords: Boolean read FIgnoreRepeatedWords write SetIgnoreRepeatedWords default False;
|
|
property IgnoreUpperCaseWords: Boolean read FIgnoreUpperCaseWords write SetIgnoreUpperCaseWords default True;
|
|
property IgnoreUrls: Boolean read FIgnoreUrls write SetIgnoreUrls default True;
|
|
property IgnoreWordsWithNumbers: Boolean read FIgnoreWordsWithNumbers write SetIgnoreWordsWithNumbers default True;
|
|
end;
|
|
|
|
{ TdxSpellCheckerCheckAsYouTypeOptions }
|
|
|
|
TdxSpellCheckerUnderlineStyle = (usAuto, usWavyLine, usLine);
|
|
|
|
TdxSpellCheckerPopupMenuItem = (scmiAddToDictionary, scmiDelete, scmiIgnoreAll, scmiSpelling, scmiSuggestions);
|
|
TdxSpellCheckerPopupMenuItems = set of TdxSpellCheckerPopupMenuItem;
|
|
|
|
TdxSpellCheckerCheckAsYouTypeOptionsChangedEvent = procedure(
|
|
ASender: TdxSpellCheckerCheckAsYouTypeOptions) of object;
|
|
|
|
TdxSpellCheckerCheckAsYouTypeOptions = class(TPersistent)
|
|
private
|
|
FActive: Boolean;
|
|
FModifyControlPopupMenu: Boolean;
|
|
FPopupMenu: TComponent;
|
|
FPopupMenuItems: TdxSpellCheckerPopupMenuItems;
|
|
FSpellChecker: TdxCustomSpellChecker;
|
|
FSuggestionCount: Integer;
|
|
FUnderlineColor: TColor;
|
|
FUnderlineStyle: TdxSpellCheckerUnderlineStyle;
|
|
FOnChanged: TdxSpellCheckerCheckAsYouTypeOptionsChangedEvent;
|
|
procedure SetActive(AValue: Boolean);
|
|
procedure SetPopupMenu(AValue: TComponent);
|
|
procedure SetModifyControlPopupMenu(AValue: Boolean);
|
|
procedure SetPopupMenuItems(AValue: TdxSpellCheckerPopupMenuItems);
|
|
procedure SetSuggestionCount(AValue: Integer);
|
|
procedure SetUnderlineColor(AValue: TColor);
|
|
procedure SetUnderlineStyle(AValue: TdxSpellCheckerUnderlineStyle);
|
|
protected
|
|
procedure Changed; virtual;
|
|
procedure DoChanged; virtual;
|
|
procedure Notification(AComponent: TComponent; AOperation: TOperation); virtual;
|
|
|
|
property SpellChecker: TdxCustomSpellChecker read FSpellChecker;
|
|
public
|
|
constructor Create(ASpellChecker: TdxCustomSpellChecker); virtual;
|
|
procedure Assign(Source: TPersistent); override;
|
|
|
|
property OnChanged: TdxSpellCheckerCheckAsYouTypeOptionsChangedEvent
|
|
read FOnChanged write FOnChanged;
|
|
published
|
|
property Active: Boolean read FActive write SetActive default False;
|
|
property ModifyControlPopupMenu: Boolean read FModifyControlPopupMenu
|
|
write SetModifyControlPopupMenu default True;
|
|
property PopupMenu: TComponent read FPopupMenu write SetPopupMenu;
|
|
property PopupMenuItems: TdxSpellCheckerPopupMenuItems read FPopupMenuItems
|
|
write SetPopupMenuItems default [scmiAddToDictionary, scmiDelete, scmiIgnoreAll, scmiSpelling, scmiSuggestions];
|
|
property SuggestionCount: Integer read FSuggestionCount write SetSuggestionCount default 5;
|
|
property UnderlineColor: TColor read FUnderlineColor write SetUnderlineColor default clRed;
|
|
property UnderlineStyle: TdxSpellCheckerUnderlineStyle read FUnderlineStyle
|
|
write SetUnderlineStyle default usAuto;
|
|
end;
|
|
|
|
{ TdxSpellCheckerCustomCheckAsYouTypeManager }
|
|
|
|
TdxSpellCheckerCustomCheckAsYouTypeManager = class(TcxIUnknownObject, IdxSpellCheckerEditHelper)
|
|
private
|
|
FSpellChecker: TdxCustomSpellChecker;
|
|
function GetIsSpellCheckerReady: Boolean;
|
|
function GetOptions: TdxSpellCheckerCheckAsYouTypeOptions;
|
|
protected
|
|
function DoCheckAsYouTypeStart(AControl: TWinControl): Boolean; virtual;
|
|
function GetCheckMode: TdxSpellCheckerCustomCheckMode; virtual;
|
|
procedure DoCheckAsYouTypeFinish(AControl: TWinControl); virtual;
|
|
procedure DoOptionsChanged; virtual; abstract;
|
|
procedure InnerShowPopupMenu(APopup: TComponent; const P: TPoint);
|
|
procedure Reset; virtual;
|
|
procedure SpellingOptionsChanged; virtual;
|
|
procedure StartManualSpelling(AAdapter: TdxSpellCheckerCustomEditAdapter); virtual;
|
|
procedure ValidateRules(AParser: TdxSpellCheckerTextParser); virtual;
|
|
public
|
|
constructor Create(ASpellChecker: TdxCustomSpellChecker); virtual;
|
|
|
|
procedure BeginManualCheck; virtual;
|
|
procedure EndManualCheck; virtual;
|
|
procedure Refresh(AFullRefresh: Boolean = False); virtual; abstract;
|
|
|
|
// IdxSpellCheckerEditHelper
|
|
procedure CheckAsYouTypeFinish; virtual; abstract;
|
|
procedure CheckAsYouTypeStart(AControl: TWinControl); virtual; abstract;
|
|
procedure DoDrawMisspelleds(AControl: TWinControl); virtual; abstract;
|
|
function IsSpellCheckerDialogControl(AWnd: THandle): Boolean; virtual; abstract;
|
|
procedure LayoutChanged(AControl: TWinControl); virtual; abstract;
|
|
function QueryPopup(APopup: TComponent; const P: TPoint): Boolean; virtual; abstract;
|
|
procedure SelectionChanged(AControl: TWinControl); virtual; abstract;
|
|
procedure TextChanged(AControl: TWinControl); virtual; abstract;
|
|
|
|
property IsSpellCheckerReady: Boolean read GetIsSpellCheckerReady;
|
|
property Options: TdxSpellCheckerCheckAsYouTypeOptions read GetOptions;
|
|
property SpellChecker: TdxCustomSpellChecker read FSpellChecker;
|
|
end;
|
|
|
|
{ TdxCustomSpellChecker }
|
|
|
|
TdxSpellCheckerSpellingFormType = (sftOutlook, sftWord);
|
|
|
|
TdxSpellCheckerEvent = procedure (Sender: TdxCustomSpellChecker) of object;
|
|
TdxSpellCheckerCheckWordEvent = procedure (Sender: TdxCustomSpellChecker;
|
|
const AWord: WideString; out AValid: Boolean; var AHandled: Boolean) of object;
|
|
TdxSpellCheckerAddWordEvent = procedure (AUserDictionary: TdxUserSpellCheckerDictionary;
|
|
const AWord: WideString; var AHandled: Boolean) of object;
|
|
TdxSpellCheckerEnabledDictionariesLoadedEvent = procedure (Sender: TdxCustomSpellChecker;
|
|
const AWord: WideString; var AHandled: Boolean) of object;
|
|
TdxSpellCheckerSpellingComplete = procedure (Sender: TdxCustomSpellChecker;
|
|
var AHandled: Boolean) of object;
|
|
TdxSpellCheckerCheckAsYouTypeEvent = procedure (Sender: TdxCustomSpellChecker;
|
|
AControl: TWinControl) of object;
|
|
TdxSpellCheckerCheckAsYouTypePopupEvent = procedure(ASender: TdxCustomSpellChecker;
|
|
APopupMenu: TComponent; var AHandled: Boolean) of object;
|
|
TdxSpellCheckerCheckAsYouTypeStartEvent = procedure (Sender: TdxCustomSpellChecker;
|
|
AControl: TWinControl; var AAllow: Boolean) of object;
|
|
TdxSpellCheckerCheckControlInContainerEvent = procedure (Sender: TdxCustomSpellChecker;
|
|
AControl: TWinControl; var AAllow: Boolean; var AContinue: Boolean) of object;
|
|
TdxSpellCheckerGetSuggestionsEvent = procedure (Sender: TdxCustomSpellChecker;
|
|
ASuggestions: TdxSpellCheckerSuggestionList) of object;
|
|
|
|
TdxCustomSpellChecker = class(TComponent)
|
|
private
|
|
FAutoLoadDictionaries: Boolean;
|
|
FChangeList: TdxSpellCheckerReplacementList;
|
|
FCheckAsYouTypeManager: TdxSpellCheckerCustomCheckAsYouTypeManager;
|
|
FCheckAsYouTypeOptions: TdxSpellCheckerCheckAsYouTypeOptions;
|
|
FCheckGroupMode: Boolean;
|
|
FCheckingContainer: Boolean;
|
|
FCheckMode: TdxSpellCheckerCustomCheckMode;
|
|
FCreating: Boolean;
|
|
FDeleteList: TdxSpellCheckerWordList;
|
|
FDialogLookAndFeel: TcxLookAndFeel;
|
|
FDictionaryItems: TdxSpellCheckerDictionaries;
|
|
FIgnoreList: TdxSpellCheckerWordList;
|
|
FLanguages: TdxSpellCheckerLanguages;
|
|
FLastDialogResult: Integer;
|
|
FRules: TdxSpellCheckerRules;
|
|
FSimilarity: TdxStringSimilarityCalculator;
|
|
FSpellingFormType: TdxSpellCheckerSpellingFormType;
|
|
FSpellingOptions: TdxSpellCheckerSpellingOptions;
|
|
FUseThreadedLoad: Boolean;
|
|
FOnAddWord: TdxSpellCheckerAddWordEvent;
|
|
FOnAfterCheck: TdxSpellCheckerEvent;
|
|
FOnBeforeCheck: TdxSpellCheckerEvent;
|
|
FOnCheckAsYouTypeFinish: TdxSpellCheckerCheckAsYouTypeEvent;
|
|
FOnCheckAsYouTypeStart: TdxSpellCheckerCheckAsYouTypeStartEvent;
|
|
FOnCheckControlInContainer: TdxSpellCheckerCheckControlInContainerEvent;
|
|
FOnCheckWord: TdxSpellCheckerCheckWordEvent;
|
|
FOnEnabledDictionariesLoaded: TdxSpellCheckerEvent;
|
|
FOnGetSuggestions: TdxSpellCheckerGetSuggestionsEvent;
|
|
FOnCheckAsYouTypePopup: TdxSpellCheckerCheckAsYouTypePopupEvent;
|
|
FOnSpellingComplete: TdxSpellCheckerSpellingComplete;
|
|
function GetActiveDictionary(
|
|
Index: Integer): TdxCustomSpellCheckerDictionary;
|
|
function GetActiveDictionaryCount: Integer;
|
|
function GetCheckMode: TdxSpellCheckerCustomCheckMode;
|
|
function GetDictionary(Index: Integer): TdxCustomSpellCheckerDictionary;
|
|
function GetDictionaryCount: Integer;
|
|
function GetEnabledDictionary(
|
|
Index: Integer): TdxCustomSpellCheckerDictionary;
|
|
function GetEnabledDictionaryCount: Integer;
|
|
function GetUserDictionary(Index: Integer): TdxUserSpellCheckerDictionary;
|
|
function GetUserDictionaryCount: Integer;
|
|
procedure SetCheckAsYouTypeOptions(AValue: TdxSpellCheckerCheckAsYouTypeOptions);
|
|
procedure SetDialogLookAndFeel(AValue: TcxLookAndFeel);
|
|
procedure SetDictionaryItems(AValue: TdxSpellCheckerDictionaries);
|
|
procedure SetSpellingOptions(AValue: TdxSpellCheckerSpellingOptions);
|
|
protected
|
|
procedure AddToIgnoreList(const AWord: WideString); virtual;
|
|
procedure CheckCallEnabledDictionariesLoaded;
|
|
function CreateSimilarity: TdxStringSimilarityCalculator; virtual;
|
|
function CreateSpellingOptions: TdxSpellCheckerSpellingOptions; virtual;
|
|
function DoAddWord(AUserDictionary: TdxUserSpellCheckerDictionary;
|
|
const AWord: WideString): Boolean; virtual;
|
|
procedure DoAfterCheck; virtual;
|
|
procedure DoBeforeCheck; virtual;
|
|
procedure DoCheck(ADialogCheckMode: TdxSpellCheckerDialogCheckMode); virtual;
|
|
procedure DoCheckAsYouTypeFinish(AControl: TWinControl); virtual;
|
|
function DoCheckAsYouTypePopup(APopup: TComponent): Boolean; virtual;
|
|
function DoCheckAsYouTypeStart(AControl: TWinControl): Boolean; virtual;
|
|
procedure DoCheckContainer(AContainer: TWinControl; ARecursive: Boolean); virtual;
|
|
function DoCheckControlInContainer(AControl: TWinControl; var AContinue: Boolean): Boolean; virtual;
|
|
function DoCheckWord(const AWord: WideString; var AValid: Boolean): Boolean; virtual;
|
|
procedure DoEnabledDictionariesLoaded; virtual;
|
|
procedure DoGetSuggestions(ASuggestions: TdxSpellCheckerSuggestionList); virtual;
|
|
function DoSpellingComplete: Boolean; virtual;
|
|
procedure BeginManualCheck;
|
|
procedure EndManualCheck;
|
|
function GetDialogCheckModeClass: TdxSpellCheckerCustomCheckModeClass; virtual;
|
|
procedure InternalCheck(AAdapter: TdxSpellCheckerCustomEditAdapter); virtual;
|
|
procedure LoadDictionariesDirect(AIgnoreDisabled: Boolean = True); virtual;
|
|
procedure LoadDictionariesUsingThread(AIgnoreDisabled: Boolean = True); virtual;
|
|
procedure Loaded; override;
|
|
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
|
|
procedure SpellingComplete;
|
|
procedure SpellingOptionsChanged; virtual;
|
|
procedure ValidateRules(AParser: TdxSpellCheckerTextParser); virtual;
|
|
procedure UpdateByDictionary(ADictionary: TdxCustomSpellCheckerDictionary); virtual;
|
|
procedure UpdateCheckAsYouTypeManagerState; virtual;
|
|
|
|
property ChangeList: TdxSpellCheckerReplacementList read FChangeList;
|
|
property CheckAsYouTypeManager: TdxSpellCheckerCustomCheckAsYouTypeManager read FCheckAsYouTypeManager;
|
|
property CheckingContainer: Boolean read FCheckingContainer;
|
|
property DeleteList: TdxSpellCheckerWordList read FDeleteList;
|
|
property IgnoreList: TdxSpellCheckerWordList read FIgnoreList;
|
|
property Languages: TdxSpellCheckerLanguages read FLanguages;
|
|
property OnAddWord: TdxSpellCheckerAddWordEvent read FOnAddWord write FOnAddWord;
|
|
property OnAfterCheck: TdxSpellCheckerEvent read FOnAfterCheck write FOnAfterCheck;
|
|
property OnBeforeCheck: TdxSpellCheckerEvent read FOnBeforeCheck write FOnBeforeCheck;
|
|
property OnCheckAsYouTypeFinish: TdxSpellCheckerCheckAsYouTypeEvent
|
|
read FOnCheckAsYouTypeFinish write FOnCheckAsYouTypeFinish;
|
|
property OnCheckAsYouTypePopup: TdxSpellCheckerCheckAsYouTypePopupEvent
|
|
read FOnCheckAsYouTypePopup write FOnCheckAsYouTypePopup;
|
|
property OnCheckAsYouTypeStart: TdxSpellCheckerCheckAsYouTypeStartEvent
|
|
read FOnCheckAsYouTypeStart write FOnCheckAsYouTypeStart;
|
|
property OnCheckControlInContainer: TdxSpellCheckerCheckControlInContainerEvent
|
|
read FOnCheckControlInContainer write FOnCheckControlInContainer;
|
|
property OnCheckWord: TdxSpellCheckerCheckWordEvent read FOnCheckWord write FOnCheckWord;
|
|
property OnEnabledDictionariesLoaded: TdxSpellCheckerEvent
|
|
read FOnEnabledDictionariesLoaded write FOnEnabledDictionariesLoaded;
|
|
property OnGetSuggestions: TdxSpellCheckerGetSuggestionsEvent
|
|
read FOnGetSuggestions write FOnGetSuggestions;
|
|
property OnSpellingComplete: TdxSpellCheckerSpellingComplete
|
|
read FOnSpellingComplete write FOnSpellingComplete;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
|
|
procedure Check(AEdit: TCustomEdit); overload;
|
|
procedure Check(AEdit: TcxCustomTextEdit); overload;
|
|
procedure CheckContainer(AContainer: TWinControl; ARecursive: Boolean);
|
|
|
|
procedure AddWordToUserDictionary(const AWord: WideString);
|
|
function FindDictionaryByWord(const AWord: WideString): TdxCustomSpellCheckerDictionary;
|
|
function FindFirstEnabledUserDictionary: TdxUserSpellCheckerDictionary;
|
|
function GetSuggestions(const AWord: WideString): TdxSpellCheckerSuggestionList;
|
|
function HasWordInDictionaries(const AWord: WideString): Boolean;
|
|
function HasEnabledUserDictionary: Boolean;
|
|
function IsValidWord(const AWord: WideString): Boolean;
|
|
procedure PopulateLanguages(AList: TStrings);
|
|
procedure ShowSpellingCompleteMessage; virtual;
|
|
|
|
procedure LoadDictionaries(AIgnoreDisabled: Boolean = True);
|
|
procedure UnloadDictionaries;
|
|
|
|
function GetTwoWordsDistance(const AWord1, AWord2: WideString): Integer;
|
|
|
|
property ActiveDictionaries[Index: Integer]: TdxCustomSpellCheckerDictionary read GetActiveDictionary;
|
|
property ActiveDictionaryCount: Integer read GetActiveDictionaryCount;
|
|
property AutoLoadDictionaries: Boolean read FAutoLoadDictionaries write FAutoLoadDictionaries default False;
|
|
property CheckMode: TdxSpellCheckerCustomCheckMode read GetCheckMode;
|
|
property CheckAsYouTypeOptions: TdxSpellCheckerCheckAsYouTypeOptions read FCheckAsYouTypeOptions write SetCheckAsYouTypeOptions;
|
|
property DialogLookAndFeel: TcxLookAndFeel read FDialogLookAndFeel write SetDialogLookAndFeel;
|
|
property Dictionaries[Index: Integer]: TdxCustomSpellCheckerDictionary read GetDictionary;
|
|
property DictionaryCount: Integer read GetDictionaryCount;
|
|
property DictionaryItems: TdxSpellCheckerDictionaries read FDictionaryItems write SetDictionaryItems;
|
|
property EnabledDictionaries[Index: Integer]: TdxCustomSpellCheckerDictionary read GetEnabledDictionary;
|
|
property EnabledDictionaryCount: Integer read GetEnabledDictionaryCount;
|
|
property Rules: TdxSpellCheckerRules read FRules;
|
|
property SpellingFormType: TdxSpellCheckerSpellingFormType read FSpellingFormType write FSpellingFormType default sftOutlook;
|
|
property SpellingOptions: TdxSpellCheckerSpellingOptions read FSpellingOptions write SetSpellingOptions;
|
|
property UserDictionaries[Index: Integer]: TdxUserSpellCheckerDictionary read GetUserDictionary;
|
|
property UserDictionaryCount: Integer read GetUserDictionaryCount;
|
|
property UseThreadedLoad: Boolean read FUseThreadedLoad write FUseThreadedLoad default False;
|
|
end;
|
|
|
|
{ TdxSpellChecker }
|
|
|
|
TdxSpellChecker = class(TdxCustomSpellChecker)
|
|
published
|
|
property AutoLoadDictionaries;
|
|
property CheckAsYouTypeOptions;
|
|
property DialogLookAndFeel;
|
|
property DictionaryItems;
|
|
property SpellingFormType;
|
|
property SpellingOptions;
|
|
property UseThreadedLoad;
|
|
property OnAddWord;
|
|
property OnAfterCheck;
|
|
property OnBeforeCheck;
|
|
property OnCheckAsYouTypeFinish;
|
|
property OnCheckAsYouTypePopup;
|
|
property OnCheckAsYouTypeStart;
|
|
property OnCheckControlInContainer;
|
|
property OnCheckWord;
|
|
property OnEnabledDictionariesLoaded;
|
|
property OnGetSuggestions;
|
|
property OnSpellingComplete;
|
|
end;
|
|
|
|
function GetRegisteredDictionaryTypes: TcxRegisteredClasses;
|
|
|
|
implementation
|
|
|
|
uses
|
|
Dialogs, cxGeometry, dxOffice11, dxSpellCheckerStrs, dxSpellCheckerUtils,
|
|
dxSpellCheckerDialogs, dxISpellDecompressor, dxSpellCheckerCheckAsYouType,
|
|
cxContainer, cxEdit;
|
|
|
|
var
|
|
FRegisteredDictionaryTypes: TcxRegisteredClasses;
|
|
|
|
function GetRegisteredDictionaryTypes: TcxRegisteredClasses;
|
|
begin
|
|
if FRegisteredDictionaryTypes = nil then
|
|
begin
|
|
FRegisteredDictionaryTypes := TcxRegisteredClasses.Create;
|
|
FRegisteredDictionaryTypes.Sorted := True;
|
|
end;
|
|
Result := FRegisteredDictionaryTypes;
|
|
end;
|
|
|
|
procedure FreeRegisteredDictionaryTypes;
|
|
begin
|
|
FreeAndNil(FRegisteredDictionaryTypes);
|
|
end;
|
|
|
|
{ TdxSpellCheckerLanguages }
|
|
|
|
function TdxSpellCheckerLanguages.GetDefaultLanguageLCID: DWORD;
|
|
begin
|
|
Result := GetSystemDefaultLCID;
|
|
end;
|
|
|
|
function TdxSpellCheckerLanguages.GetLCID(const AName: string): DWORD;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := 0;
|
|
for I := 0 to Count - 1 do
|
|
begin
|
|
if AnsiCompareText(AName, Name[I]) = 0 then
|
|
begin
|
|
Result := LocaleID[I];
|
|
Break;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{ TdxSpellCheckerSuggestion }
|
|
|
|
constructor TdxSpellCheckerSuggestion.Create(const AWord: WideString;
|
|
ADictionary: TdxCustomSpellCheckerDictionary; ADistance: Integer);
|
|
begin
|
|
inherited Create;
|
|
FDictionary := ADictionary;
|
|
FWord := AWord;
|
|
FDistance := ADistance;
|
|
end;
|
|
|
|
{ TdxSpellCheckerSuggestionList }
|
|
|
|
procedure TdxSpellCheckerSuggestionList.Add(const AWord: WideString;
|
|
ADictionary: TdxCustomSpellCheckerDictionary; ADistance: Integer);
|
|
begin
|
|
inherited Add(TdxSpellCheckerSuggestion.Create(AWord, ADictionary, ADistance));
|
|
end;
|
|
|
|
procedure TdxSpellCheckerSuggestionList.Delete(AIndex: Integer);
|
|
begin
|
|
Items[AIndex].Free;
|
|
inherited Delete(AIndex);
|
|
end;
|
|
|
|
procedure TdxSpellCheckerSuggestionList.FixCapitalization(const AMask: WideString);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if Length(AMask) = 0 then Exit;
|
|
case GetWordCapitalizationType(AMask) of
|
|
ctUpper:
|
|
for I := 0 to Count - 1 do
|
|
with Items[I] do
|
|
FWord := WideUpperCase(FWord);
|
|
ctCapitalized:
|
|
for I := 0 to Count - 1 do
|
|
with Items[I] do
|
|
if Length(FWord) > 0 then
|
|
FWord[1] := WideUpperCase(FWord[1])[1];
|
|
end;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerSuggestionList.RemoveDuplicates;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
SortByWord;
|
|
I := 1;
|
|
while I < Count do
|
|
begin
|
|
while (I < Count) and WideSameText(Items[I].Word, Items[I - 1].Word) do
|
|
begin
|
|
Items[I].Free;
|
|
Delete(I);
|
|
end;
|
|
Inc(I);
|
|
end;
|
|
SortByDistance;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerSuggestionList.SaveToStrings(AStrings: TStrings);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
AStrings.BeginUpdate;
|
|
try
|
|
AStrings.Clear;
|
|
for I := 0 to Count - 1 do
|
|
AStrings.AddObject(Items[I].Word, Pointer(Items[I].Distance));
|
|
finally
|
|
AStrings.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
function CompareSuggestionsByDistance(Item1, Item2: Pointer): Integer;
|
|
begin
|
|
Result := TdxSpellCheckerSuggestion(Item1).Distance - TdxSpellCheckerSuggestion(Item2).Distance;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerSuggestionList.SortByDistance;
|
|
begin
|
|
Sort(CompareSuggestionsByDistance);
|
|
end;
|
|
|
|
function CompareSuggestionsByWord(Item1, Item2: Pointer): Integer;
|
|
begin
|
|
Result := WideCompareText(TdxSpellCheckerSuggestion(Item1).Word, TdxSpellCheckerSuggestion(Item2).Word);
|
|
end;
|
|
|
|
procedure TdxSpellCheckerSuggestionList.SortByWord;
|
|
begin
|
|
Sort(CompareSuggestionsByWord);
|
|
end;
|
|
|
|
function TdxSpellCheckerSuggestionList.GetItem(
|
|
Index: Integer): TdxSpellCheckerSuggestion;
|
|
begin
|
|
Result := TdxSpellCheckerSuggestion(inherited Items[Index]);
|
|
end;
|
|
|
|
{ TdxSpellCheckerReplacementItem }
|
|
|
|
constructor TdxSpellCheckerReplacementItem.Create(
|
|
const AText, AReplacement: WideString);
|
|
begin
|
|
inherited Create;
|
|
FText := AText;
|
|
FReplacement := AReplacement;
|
|
end;
|
|
|
|
{ TdxSpellCheckerReplacementList }
|
|
|
|
constructor TdxSpellCheckerReplacementList.Create(AllowDuplicates: Boolean = False);
|
|
begin
|
|
inherited Create;
|
|
Capacity := 256;
|
|
FAllowDuplicates := AllowDuplicates;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerReplacementList.Add(
|
|
const AText, AReplacement: WideString);
|
|
var
|
|
AItem: TdxSpellCheckerReplacementItem;
|
|
begin
|
|
if FAllowDuplicates then
|
|
inherited Add(TdxSpellCheckerReplacementItem.Create(AText, AReplacement))
|
|
else
|
|
begin
|
|
AItem := FindReplacement(AText);
|
|
if AItem = nil then
|
|
begin
|
|
inherited Add(TdxSpellCheckerReplacementItem.Create(AText, AReplacement));
|
|
SortByText;
|
|
end
|
|
else
|
|
AItem.FReplacement := AReplacement;
|
|
end;
|
|
end;
|
|
|
|
function TdxSpellCheckerReplacementList.FindReplacement(
|
|
const AText: WideString): TdxSpellCheckerReplacementItem;
|
|
var
|
|
L, H, I, C: Integer;
|
|
begin
|
|
Result := nil;
|
|
L := 0;
|
|
H := Count - 1;
|
|
while L <= H do
|
|
begin
|
|
I := (L + H) shr 1;
|
|
C := WideCompareText(TdxSpellCheckerReplacementItem(List^[I]).Text, AText);
|
|
if C < 0 then
|
|
L := I + 1
|
|
else
|
|
begin
|
|
H := I - 1;
|
|
if C = 0 then
|
|
begin
|
|
Result := TdxSpellCheckerReplacementItem(List^[I]);
|
|
Break;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TdxSpellCheckerReplacementList.GetItem(
|
|
AIndex: Integer): TdxSpellCheckerReplacementItem;
|
|
begin
|
|
Result := TdxSpellCheckerReplacementItem(inherited Items[AIndex]);
|
|
end;
|
|
|
|
function CompareReplacementByText(Item1, Item2: Pointer): Integer;
|
|
begin
|
|
Result := WideCompareText(TdxSpellCheckerReplacementItem(Item1).Text,
|
|
TdxSpellCheckerReplacementItem(Item2).Text);
|
|
end;
|
|
|
|
procedure TdxSpellCheckerReplacementList.SortByText;
|
|
begin
|
|
Sort(CompareReplacementByText);
|
|
end;
|
|
|
|
{ TdxSpellCheckerCustomEditAdapter }
|
|
|
|
constructor TdxSpellCheckerCustomEditAdapter.Create(AEdit: TWinControl);
|
|
begin
|
|
FEdit := AEdit;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCustomEditAdapter.GetSpellingBounds(
|
|
out ASpellingStart, ASpellingEnd: Integer);
|
|
begin
|
|
ASpellingStart := 1;
|
|
if EditorHandleAllocated then
|
|
ASpellingEnd := SendMessageW(EditorHandle, WM_GETTEXTLENGTH, 0, 0) + 1
|
|
else
|
|
ASpellingEnd := Length(FText);
|
|
end;
|
|
|
|
function TdxSpellCheckerCustomEditAdapter.EditorHandleAllocated: Boolean;
|
|
begin
|
|
Result := (FEdit <> nil) and FEdit.HandleAllocated
|
|
end;
|
|
|
|
function TdxSpellCheckerCustomEditAdapter.GetEditorHandle: THandle;
|
|
begin
|
|
if EditorHandleAllocated then
|
|
Result := FEdit.Handle
|
|
else
|
|
Result := 0;
|
|
end;
|
|
|
|
function TdxSpellCheckerCustomEditAdapter.GetText: WideString;
|
|
var
|
|
ALen: Integer;
|
|
begin
|
|
if EditorHandleAllocated then
|
|
begin
|
|
ALen := SendMessageW(EditorHandle, WM_GETTEXTLENGTH, 0, 0) + 1;
|
|
SetLength(Result, ALen);
|
|
GetWindowTextW(EditorHandle, Pointer(Result), ALen);
|
|
FText := Result;
|
|
end
|
|
else
|
|
Result := FText;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCustomEditAdapter.Post(AUpdateValue: Boolean = True);
|
|
var
|
|
AEdit: IdxSpellCheckerSupport;
|
|
begin
|
|
if Supports(GetInnerControlContainer(FEdit), IdxSpellCheckerSupport, AEdit) and
|
|
AUpdateValue and not EditorHandleAllocated then
|
|
begin
|
|
FText := PWideChar(FText);
|
|
AEdit.SetValue(FText);
|
|
end;
|
|
end;
|
|
|
|
function TdxSpellCheckerCustomEditAdapter.IsInplace: Boolean;
|
|
var
|
|
AContainer: TcxCustomEdit;
|
|
begin
|
|
AContainer := TcxCustomEdit(GetInnerControlContainer(FEdit));
|
|
Result := (AContainer <> nil) and AContainer.IsInplace;
|
|
end;
|
|
|
|
{ TdxSpellCheckercxTextEditAdapter }
|
|
|
|
procedure TdxSpellCheckercxTextEditAdapter.ClearSelection;
|
|
begin
|
|
if EditorHandleAllocated then
|
|
Edit.ClearSelection
|
|
else
|
|
SelText := '';
|
|
end;
|
|
|
|
function TdxSpellCheckercxTextEditAdapter.GetHideSelection: Boolean;
|
|
begin
|
|
Result := Edit.Properties.HideSelection;
|
|
end;
|
|
|
|
function TdxSpellCheckercxTextEditAdapter.GetReadOnly: Boolean;
|
|
begin
|
|
Result := Edit.Properties.ReadOnly;
|
|
end;
|
|
|
|
function TdxSpellCheckercxTextEditAdapter.GetSelLength: Integer;
|
|
begin
|
|
Result := Edit.SelLength;
|
|
end;
|
|
|
|
function TdxSpellCheckercxTextEditAdapter.GetSelStart: Integer;
|
|
begin
|
|
Result := Edit.SelStart
|
|
end;
|
|
|
|
function TdxSpellCheckercxTextEditAdapter.GetSelText: string;
|
|
begin
|
|
Result := Edit.SelText
|
|
end;
|
|
|
|
procedure TdxSpellCheckercxTextEditAdapter.SetHideSelection(AValue: Boolean);
|
|
begin
|
|
Edit.Properties.HideSelection := AValue
|
|
end;
|
|
|
|
procedure TdxSpellCheckercxTextEditAdapter.SetSelLength(AValue: Integer);
|
|
begin
|
|
Edit.SelLength := AValue;
|
|
end;
|
|
|
|
procedure TdxSpellCheckercxTextEditAdapter.SetSelStart(AValue: Integer);
|
|
begin
|
|
Edit.SelStart := AValue;
|
|
end;
|
|
|
|
procedure TdxSpellCheckercxTextEditAdapter.SetSelText(const AValue: string);
|
|
begin
|
|
Edit.SelText := AValue;
|
|
end;
|
|
|
|
function TdxSpellCheckercxTextEditAdapter.GetEdit: TcxCustomTextEdit;
|
|
begin
|
|
Result := TcxCustomTextEdit(FEdit);
|
|
end;
|
|
|
|
{ TdxSpellCheckercxRichEditAdapter }
|
|
|
|
function TdxSpellCheckercxRichEditAdapter.GetReadOnly: Boolean;
|
|
begin
|
|
Result := Edit.ActiveProperties.ReadOnly;
|
|
end;
|
|
|
|
function TdxSpellCheckercxRichEditAdapter.GetText: WideString;
|
|
var
|
|
ASource, ADest: WideString;
|
|
ALen: Integer;
|
|
begin
|
|
ASource := inherited GetText;
|
|
ALen := Length(ASource);
|
|
SetLength(ADest, ALen);
|
|
ALen := AdjustRichLineBreaksW(PWideChar(ADest), PWideChar(ASource),
|
|
Edit.RichVersion >= 200);
|
|
SetLength(ADest, ALen);
|
|
Result := ADest;
|
|
end;
|
|
|
|
function TdxSpellCheckercxRichEditAdapter.GetEdit: TcxCustomRichEdit;
|
|
begin
|
|
Result := TcxCustomRichEdit(inherited Edit);
|
|
end;
|
|
|
|
{ TdxSpellCheckerEditAdapter }
|
|
|
|
procedure TdxSpellCheckerEditAdapter.ClearSelection;
|
|
begin
|
|
SelText := '';
|
|
end;
|
|
|
|
function TdxSpellCheckerEditAdapter.GetHideSelection: Boolean;
|
|
begin
|
|
if FEdit is TMemo then
|
|
Result := TMemo(FEdit).HideSelection
|
|
else
|
|
if FEdit is TEdit then
|
|
Result := TEdit(FEdit).HideSelection
|
|
else
|
|
Result := False;
|
|
end;
|
|
|
|
function TdxSpellCheckerEditAdapter.GetReadOnly: Boolean;
|
|
begin
|
|
Result := TEdit(FEdit).ReadOnly;
|
|
end;
|
|
|
|
function TdxSpellCheckerEditAdapter.GetSelLength: Integer;
|
|
begin
|
|
if EditorHandleAllocated then
|
|
Result := Edit.SelLength
|
|
else
|
|
Result := FSelLength;
|
|
end;
|
|
|
|
function TdxSpellCheckerEditAdapter.GetSelStart: Integer;
|
|
begin
|
|
if EditorHandleAllocated then
|
|
Result := Edit.SelStart
|
|
else
|
|
Result := FSelStart;
|
|
end;
|
|
|
|
function TdxSpellCheckerEditAdapter.GetSelText: string;
|
|
begin
|
|
if EditorHandleAllocated then
|
|
Result := Edit.SelText
|
|
else
|
|
Result := Copy(FText, FSelStart, FSelLength);
|
|
end;
|
|
|
|
procedure TdxSpellCheckerEditAdapter.SetHideSelection(AValue: Boolean);
|
|
begin
|
|
if FEdit is TMemo then
|
|
TMemo(FEdit).HideSelection := AValue
|
|
else
|
|
if FEdit is TEdit then
|
|
TEdit(FEdit).HideSelection := AValue;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerEditAdapter.SetSelLength(AValue: Integer);
|
|
begin
|
|
if EditorHandleAllocated then
|
|
Edit.SelLength := AValue;
|
|
FSelLength := AValue;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerEditAdapter.SetSelStart(AValue: Integer);
|
|
begin
|
|
if EditorHandleAllocated then
|
|
Edit.SelStart := AValue;
|
|
FSelStart := AValue;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerEditAdapter.SetSelText(const AValue: string);
|
|
var
|
|
AContainer: TWinControl;
|
|
AIntf: IdxSpellCheckerSupport;
|
|
begin
|
|
FText := Copy(FText, 1, FSelStart) + AValue + Copy(FText, FSelStart + FSelLength + 1, Length(FText) - FSelStart - FSelLength);
|
|
if EditorHandleAllocated then
|
|
begin
|
|
AContainer := GetInnerControlContainer(Edit);
|
|
if Supports(TObject(AContainer), IdxSpellCheckerSupport, AIntf) then
|
|
AIntf.SetSelText(AValue)
|
|
else
|
|
Edit.SelText := AValue;
|
|
end;
|
|
end;
|
|
|
|
function TdxSpellCheckerEditAdapter.GetEdit: TCustomEdit;
|
|
begin
|
|
Result := TCustomEdit(FEdit);
|
|
end;
|
|
|
|
{ TdxSpellCheckerTextParser }
|
|
|
|
constructor TdxSpellCheckerTextParser.Create(ASpellChecker: TdxCustomSpellChecker);
|
|
begin
|
|
inherited Create;
|
|
FSpellChecker := ASpellChecker;
|
|
FDelimiters := #0#9#10#11#13#32'.,<>=!?:;"()[]{}+|-/\';
|
|
FUrlDelimiters := #0#9#10#11#13#32',<>!;()[]{}|';
|
|
FText := #0;
|
|
end;
|
|
|
|
destructor TdxSpellCheckerTextParser.Destroy;
|
|
begin
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TdxSpellCheckerTextParser.GetNextWord(var AStart, ALength: Integer; out ADelimiters: WideString): WideString;
|
|
|
|
procedure SkipFirstDelimiters;
|
|
begin
|
|
if (AStart <= FSpellingEnd) and WideIsSpace(FText[AStart]) then
|
|
while (AStart < FSpellingEnd) and WideIsSpace(FText[AStart]) do
|
|
begin
|
|
ADelimiters := ADelimiters + FText[AStart];
|
|
Inc(AStart);
|
|
end
|
|
else
|
|
while (AStart < FSpellingEnd) and not WideIsAlphaNumeric(FText[AStart]) do
|
|
begin
|
|
ADelimiters := ADelimiters + FText[AStart];
|
|
Inc(AStart);
|
|
end;
|
|
end;
|
|
|
|
var
|
|
APos: Integer;
|
|
APreDelimiters: WideString;
|
|
begin
|
|
ADelimiters := '';
|
|
SkipFirstDelimiters;
|
|
ALength := 0;
|
|
APos := AStart;
|
|
while (APos < FSpellingEnd) and not WideIsSpace(FText[APos]) do
|
|
Inc(APos);
|
|
ALength := APos - AStart;
|
|
if ALength = 0 then
|
|
Result := ''
|
|
else
|
|
begin
|
|
Result := Copy(FText, AStart, ALength);
|
|
if LastWideCharIsSpace(ADelimiters) and IsUrl(Result) then
|
|
begin
|
|
while (APos > AStart) and IsUrlDelimiter(FText[APos]) do
|
|
Dec(APos);
|
|
ALength := APos - AStart + 1;
|
|
Result := Copy(FText, AStart, ALength);
|
|
end
|
|
else
|
|
begin
|
|
while (AStart < FSpellingEnd) and IsDelimiter(FText[AStart]) do
|
|
begin
|
|
ADelimiters := ADelimiters + FText[AStart];
|
|
Inc(AStart);
|
|
end;
|
|
ALength := 0;
|
|
APos := AStart;
|
|
while (APos < FSpellingEnd) and not IsDelimiter(FText[APos]) do
|
|
Inc(APos);
|
|
ALength := APos - AStart;
|
|
Result := Copy(FText, AStart, ALength);
|
|
if not WideStringContainsAlpha(Result) then
|
|
begin
|
|
APreDelimiters := ADelimiters + Result;
|
|
Inc(AStart, ALength);
|
|
Result := GetNextWord(AStart, ALength, ADelimiters);
|
|
ADelimiters := APreDelimiters + ADelimiters;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TdxSpellCheckerTextParser.GetPrevWord: WideString;
|
|
begin
|
|
Result := FPrevWord;
|
|
end;
|
|
|
|
function TdxSpellCheckerTextParser.IsDelimiter(AChar: WideChar): Boolean;
|
|
begin
|
|
Result := WideCharPos(AChar, FDelimiters) > 0;
|
|
end;
|
|
|
|
function TdxSpellCheckerTextParser.IsUrlDelimiter(AChar: WideChar): Boolean;
|
|
begin
|
|
Result := WideCharPos(AChar, FUrlDelimiters) > 0;
|
|
end;
|
|
|
|
function TdxSpellCheckerTextParser.WordExists(const AWord: WideString): Boolean;
|
|
begin
|
|
Result := SpellChecker.HasWordInDictionaries(AWord);
|
|
end;
|
|
|
|
function TdxSpellCheckerTextParser.GetSentence(APos: Integer): TdxSpellCheckerSentence;
|
|
|
|
function IsSentenceDelimiters(ACh: WideChar): Boolean;
|
|
begin
|
|
Result := (ACh = '.') or (WideIsSpace(ACh) and (ACh <> ' '));
|
|
end;
|
|
|
|
function GetSentenceText(var AStartPos: Integer): WideString;
|
|
var
|
|
AEndPos: Integer;
|
|
ALength: Integer;
|
|
begin
|
|
AEndPos := AStartPos;
|
|
while (AStartPos > 0) and not IsSentenceDelimiters(Text[AStartPos]) do
|
|
Dec(AStartPos);
|
|
while (AStartPos > 0) and (IsSentenceDelimiters(Text[AStartPos]) or (Text[AStartPos] = ' ')) do
|
|
Inc(AStartPos);
|
|
ALength := Length(FText);
|
|
while (AEndPos <= ALength) and (not IsSentenceDelimiters(Text[AEndPos]) or (Text[AEndPos] = '.')) do
|
|
Inc(AEndPos);
|
|
Result := Copy(Text, AStartPos, AEndPos - AStartPos);
|
|
end;
|
|
|
|
begin
|
|
with Result do
|
|
begin
|
|
StartTextPosition := APos;
|
|
Text := GetSentenceText(StartTextPosition);
|
|
if StartTextPosition = 0 then
|
|
Inc(StartTextPosition);
|
|
StartWordPosition := APos - StartTextPosition;
|
|
end;
|
|
end;
|
|
|
|
function TdxSpellCheckerTextParser.GetNextDelimiterPosition(var AStart: Integer; ADirection: Integer): Boolean;
|
|
begin
|
|
while (AStart <= FSpellingEnd) and (AStart >= FSpellingStart) and not WideIsSpace(FText[AStart]) do
|
|
Inc(AStart, ADirection);
|
|
Result := WideIsSpace(FText[AStart]);
|
|
if Result and (ADirection < 0) then
|
|
Inc(AStart, ADirection);
|
|
end;
|
|
|
|
function TdxSpellCheckerTextParser.GetSuggestions(
|
|
const AWord: WideString): TdxSpellCheckerSuggestionList;
|
|
begin
|
|
Result := SpellChecker.GetSuggestions(AWord);
|
|
end;
|
|
|
|
procedure TdxSpellCheckerTextParser.UpdateTextInfo(AAdapter: TdxSpellCheckerCustomEditAdapter);
|
|
begin
|
|
AAdapter.GetSpellingBounds(FSpellingStart, FSpellingEnd);
|
|
FText := AAdapter.Text;
|
|
end;
|
|
|
|
function TdxSpellCheckerTextParser.LastWideCharIsSpace(const S: WideString): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
I := Length(S);
|
|
Result := (I > 0) and WideIsSpace(S[I]);
|
|
end;
|
|
|
|
{ TdxSpellCheckerUndoItem }
|
|
|
|
constructor TdxSpellCheckerUndoItem.Create(const AMisspelledWord, AReplacement, APrevWord: WideString; AMisspelledWordPosition: Integer);
|
|
begin
|
|
FMisspelledWord := AMisspelledWord;
|
|
FReplacement := AReplacement;
|
|
FPrevWord := APrevWord;
|
|
FMisspelledWordPosition := AMisspelledWordPosition;
|
|
end;
|
|
|
|
{ TdxSpellCheckerUndoManager }
|
|
|
|
constructor TdxSpellCheckerUndoManager.Create;
|
|
begin
|
|
FUndoList := TcxObjectList.Create;
|
|
end;
|
|
|
|
destructor TdxSpellCheckerUndoManager.Destroy;
|
|
begin
|
|
FreeAndNil(FUndoList);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerUndoManager.Add(const AMisspelledWord, AReplacement, APrevWord: WideString; AMisspelledWordPosition: Integer);
|
|
begin
|
|
FUndoList.Add(TdxSpellCheckerUndoItem.Create(AMisspelledWord, AReplacement, APrevWord, AMisspelledWordPosition));
|
|
end;
|
|
|
|
procedure TdxSpellCheckerUndoManager.UndoLast;
|
|
begin
|
|
if Count > 0 then
|
|
begin
|
|
Last.Free;
|
|
FUndoList.Delete(Count - 1);
|
|
end;
|
|
end;
|
|
|
|
function TdxSpellCheckerUndoManager.GetCount: Integer;
|
|
begin
|
|
Result := FUndoList.Count;
|
|
end;
|
|
|
|
function TdxSpellCheckerUndoManager.GetItem(AIndex: Integer): TdxSpellCheckerUndoItem;
|
|
begin
|
|
Result := TdxSpellCheckerUndoItem(FUndoList[AIndex]);
|
|
end;
|
|
|
|
function TdxSpellCheckerUndoManager.GetLast: TdxSpellCheckerUndoItem;
|
|
begin
|
|
if Count > 0 then
|
|
Result := Items[Count - 1]
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
{ TdxSpellCheckerCustomCheckAsYouTypeManager }
|
|
|
|
constructor TdxSpellCheckerCustomCheckAsYouTypeManager.Create(
|
|
ASpellChecker: TdxCustomSpellChecker);
|
|
begin
|
|
FSpellChecker := ASpellChecker;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCustomCheckAsYouTypeManager.BeginManualCheck;
|
|
begin
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCustomCheckAsYouTypeManager.EndManualCheck;
|
|
begin
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCustomCheckAsYouTypeManager.DoCheckAsYouTypeFinish(
|
|
AControl: TWinControl);
|
|
begin
|
|
SpellChecker.DoCheckAsYouTypeFinish(AControl);
|
|
end;
|
|
|
|
function TdxSpellCheckerCustomCheckAsYouTypeManager.DoCheckAsYouTypeStart(
|
|
AControl: TWinControl): Boolean;
|
|
begin
|
|
Result := SpellChecker.DoCheckAsYouTypeStart(AControl);
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCustomCheckAsYouTypeManager.InnerShowPopupMenu(APopup: TComponent; const P: TPoint);
|
|
begin
|
|
if not SpellChecker.DoCheckAsYouTypePopup(APopup) then
|
|
ShowPopupMenu(nil, APopup, P.X, P.Y);
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCustomCheckAsYouTypeManager.Reset;
|
|
begin
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCustomCheckAsYouTypeManager.SpellingOptionsChanged;
|
|
begin
|
|
if GetCheckMode <> nil then
|
|
SpellChecker.ValidateRules(GetCheckMode.Parser);
|
|
end;
|
|
|
|
function TdxSpellCheckerCustomCheckAsYouTypeManager.GetIsSpellCheckerReady: Boolean;
|
|
begin
|
|
Result := SpellChecker.ActiveDictionaryCount > 0;
|
|
end;
|
|
|
|
function TdxSpellCheckerCustomCheckAsYouTypeManager.GetOptions: TdxSpellCheckerCheckAsYouTypeOptions;
|
|
begin
|
|
Result := SpellChecker.CheckAsYouTypeOptions;
|
|
end;
|
|
|
|
function TdxSpellCheckerCustomCheckAsYouTypeManager.GetCheckMode: TdxSpellCheckerCustomCheckMode;
|
|
begin
|
|
Result := nil;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCustomCheckAsYouTypeManager.StartManualSpelling(
|
|
AAdapter: TdxSpellCheckerCustomEditAdapter);
|
|
begin
|
|
SpellChecker.InternalCheck(AAdapter);
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCustomCheckAsYouTypeManager.ValidateRules(
|
|
AParser: TdxSpellCheckerTextParser);
|
|
begin
|
|
SpellChecker.ValidateRules(AParser);
|
|
end;
|
|
|
|
{ TdxSpellCheckerCustomCheckMode }
|
|
|
|
constructor TdxSpellCheckerCustomCheckMode.Create(AOwner: TdxCustomSpellChecker;
|
|
AAdapter: TdxSpellCheckerCustomEditAdapter);
|
|
begin
|
|
FSpellChecker := AOwner;
|
|
FAdapter := AAdapter;
|
|
SaveSelection;
|
|
CreateParser;
|
|
FMisspelledStart := SpellingStart;
|
|
end;
|
|
|
|
destructor TdxSpellCheckerCustomCheckMode.Destroy;
|
|
begin
|
|
FreeAndNil(FParser);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCustomCheckMode.Add;
|
|
begin
|
|
if SpellChecker.HasEnabledUserDictionary then
|
|
SpellChecker.AddWordToUserDictionary(FMisspelledWord);
|
|
end;
|
|
|
|
function TdxSpellCheckerCustomCheckMode.CanUndo: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCustomCheckMode.Change(const AWord: WideString);
|
|
var
|
|
ADelta: Integer;
|
|
begin
|
|
SelectMisspelledWord;
|
|
ADelta := Length(AWord) - Length(Adapter.SelText);
|
|
Adapter.SelText := AWord;
|
|
PrevWord := AWord;
|
|
UpdateSpellingBounds(ADelta);
|
|
UpdateTextInfo;
|
|
Inc(FMisspelledStart, Length(AWord));
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCustomCheckMode.ChangeAll(const AWord: WideString);
|
|
begin
|
|
SpellChecker.ChangeList.Add(MisspelledWord, AWord);
|
|
Change(AWord);
|
|
end;
|
|
|
|
function TdxSpellCheckerCustomCheckMode.CheckWord(
|
|
const AWord: WideString): TdxSpellCheckerSpellingCode;
|
|
begin
|
|
if not IsValidWord(AWord) then
|
|
begin
|
|
FLastCode := SpellChecker.Rules.ErrorCode;
|
|
FMisspelledWord := AWord;
|
|
end
|
|
else
|
|
FLastCode := scNoError;
|
|
Result := FLastCode;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCustomCheckMode.Delete;
|
|
begin
|
|
Inc(FMisspelledLen);
|
|
Dec(FMisspelledStart);
|
|
SelectMisspelledWord;
|
|
Adapter.ClearSelection;
|
|
UpdateSpellingBounds(-FMisspelledLen);
|
|
UpdateTextInfo;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCustomCheckMode.DeleteAll;
|
|
begin
|
|
SpellChecker.DeleteList.Add(MisspelledWord);
|
|
Delete;
|
|
end;
|
|
|
|
function TdxSpellCheckerCustomCheckMode.GetNextWord(out AWord: WideString): Boolean;
|
|
var
|
|
ADelimetrs: WideString;
|
|
begin
|
|
AWord := Parser.GetNextWord(FMisspelledStart, FMisspelledLen, ADelimetrs);
|
|
if AWord = '' then
|
|
begin
|
|
ValidateSpellingBounds;
|
|
AWord := Parser.GetNextWord(FMisspelledStart, FMisspelledLen, ADelimetrs);
|
|
end;
|
|
if (Length(ADelimetrs) <> GetWideCharCount(' ', ADelimetrs)) then // todo:
|
|
PrevWord := '';
|
|
Result := FMisspelledLen > 0;
|
|
end;
|
|
|
|
function TdxSpellCheckerCustomCheckMode.GetNextMisspelledWord: Boolean;
|
|
var
|
|
AWord: WideString;
|
|
begin
|
|
FMisspelledWord := '';
|
|
while GetNextWord(AWord) do
|
|
begin
|
|
if InternalProcessWord(AWord) then
|
|
Continue;
|
|
if CheckWord(AWord) <> scNoError then
|
|
Break;
|
|
PrevWord := AWord;
|
|
Inc(FMisspelledStart, FMisspelledLen);
|
|
end;
|
|
if FMisspelledLen = 0 then
|
|
FLastCode := scNoError
|
|
else
|
|
SelectMisspelledWord;
|
|
Result := FLastCode <> scNoError;
|
|
end;
|
|
|
|
function TdxSpellCheckerCustomCheckMode.GetSuggestions(
|
|
const AWord: WideString): TdxSpellCheckerSuggestionList;
|
|
begin
|
|
Result := Parser.GetSuggestions(AWord);
|
|
end;
|
|
|
|
function TdxSpellCheckerCustomCheckMode.InternalProcessWord(
|
|
const AWord: WideString): Boolean;
|
|
var
|
|
AReplacement: WideString;
|
|
begin
|
|
Result := True;
|
|
if IsNeedIgnoreWord(AWord) then
|
|
begin
|
|
FMisspelledWord := AWord;
|
|
Ignore;
|
|
end
|
|
else
|
|
if IsNeedChangeWord(AWord, AReplacement) then
|
|
begin
|
|
Change(AReplacement);
|
|
PrevWord := AReplacement;
|
|
end
|
|
else
|
|
begin
|
|
if IsNeedDeleteWord(AWord) then
|
|
Delete
|
|
else
|
|
Result := False;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCustomCheckMode.Ignore;
|
|
begin
|
|
Inc(FMisspelledStart, FMisspelledLen);
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCustomCheckMode.IgnoreAll;
|
|
begin
|
|
SpellChecker.AddToIgnoreList(MisspelledWord);
|
|
Ignore;
|
|
end;
|
|
|
|
function TdxSpellCheckerCustomCheckMode.IsValidWord(
|
|
const AWord: WideString): Boolean;
|
|
begin
|
|
Result := SpellChecker.IsValidWord(AWord);
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCustomCheckMode.UndoLast;
|
|
begin
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCustomCheckMode.CreateParser;
|
|
begin
|
|
if FParser = nil then
|
|
FParser := GetParserClass.Create(SpellChecker);
|
|
Adapter.GetSpellingBounds(FSpellingStart, FSpellingEnd);
|
|
Dec(FSpellingStart);
|
|
Dec(FSpellingEnd);
|
|
Parser.UpdateTextInfo(Adapter);
|
|
end;
|
|
|
|
function TdxSpellCheckerCustomCheckMode.GetOwner: TPersistent;
|
|
begin
|
|
Result := FSpellChecker;
|
|
end;
|
|
|
|
function TdxSpellCheckerCustomCheckMode.GetParserClass: TdxSpellCheckerTextParserClass;
|
|
begin
|
|
Result := TdxSpellCheckerTextParser;
|
|
end;
|
|
|
|
function TdxSpellCheckerCustomCheckMode.IsNeedChangeWord(const AWord: WideString;
|
|
out AReplacement: WideString): Boolean;
|
|
var
|
|
AItem: TdxSpellCheckerReplacementItem;
|
|
begin
|
|
AItem := SpellChecker.ChangeList.FindReplacement(AWord);
|
|
Result := Assigned(AItem);
|
|
if Result then
|
|
AReplacement := AItem.Replacement;
|
|
end;
|
|
|
|
function TdxSpellCheckerCustomCheckMode.IsNeedDeleteWord(const AWord: WideString): Boolean;
|
|
begin
|
|
Result := SpellChecker.DeleteList.Find(AWord);
|
|
end;
|
|
|
|
function TdxSpellCheckerCustomCheckMode.IsNeedIgnoreWord(const AWord: WideString): Boolean;
|
|
begin
|
|
Result := SpellChecker.IgnoreList.Find(AWord);
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCustomCheckMode.SaveSelection;
|
|
begin
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCustomCheckMode.SelectMisspelledWord;
|
|
begin
|
|
if FMisspelledLen > 0 then
|
|
Adapter.SelStart := FMisspelledStart - 1;
|
|
Adapter.SelLength := FMisspelledLen;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCustomCheckMode.SelectMisspelledWordAfterUndo;
|
|
begin
|
|
SelectMisspelledWord;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCustomCheckMode.UpdateByDictionary(
|
|
ADictionary: TdxCustomSpellCheckerDictionary);
|
|
begin
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCustomCheckMode.UpdateSpellingBounds(ADelta: Integer);
|
|
begin
|
|
if FMisspelledStart < FSpellingStart then
|
|
Inc(FSpellingStart, ADelta);
|
|
if FMisspelledStart < FSpellingEnd then
|
|
Inc(FSpellingEnd, ADelta);
|
|
ValidateSpellingBounds;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCustomCheckMode.UpdateTextInfo;
|
|
begin
|
|
Parser.UpdateTextInfo(Adapter);
|
|
FParser.FSpellingStart := SpellingStart;
|
|
FParser.FSpellingEnd := SpellingEnd;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCustomCheckMode.ValidateSpellingBounds;
|
|
begin
|
|
end;
|
|
|
|
function TdxSpellCheckerCustomCheckMode.GetPrevWord: WideString;
|
|
begin
|
|
Result := Parser.FPrevWord;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCustomCheckMode.SetPrevWord(const AValue: WideString);
|
|
begin
|
|
Parser.FPrevWord := AValue;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCustomCheckMode.SetSpellingEnd(
|
|
const AValue: Integer);
|
|
begin
|
|
FSpellingEnd := AValue;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCustomCheckMode.SetSpellingStart(
|
|
const AValue: Integer);
|
|
begin
|
|
FSpellingStart := AValue;
|
|
end;
|
|
|
|
{ TdxSpellCheckerDialogCheckMode }
|
|
|
|
constructor TdxSpellCheckerDialogCheckMode.Create(AOwner: TdxCustomSpellChecker; AAdapter: TdxSpellCheckerCustomEditAdapter);
|
|
begin
|
|
inherited Create(AOwner, AAdapter);
|
|
FUndoManager := TdxSpellCheckerUndoManager.Create;
|
|
FCheckedSelection := False;
|
|
end;
|
|
|
|
destructor TdxSpellCheckerDialogCheckMode.Destroy;
|
|
begin
|
|
FreeAndNil(FUndoManager);
|
|
Adapter.HideSelection := FSaveHideSelection;
|
|
Adapter.SelStart := FSaveSelStart;
|
|
Adapter.SelLength := FSaveSelLength;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TdxSpellCheckerDialogCheckMode.CanUndo: Boolean;
|
|
begin
|
|
Result := FUndoManager.Count > 0;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerDialogCheckMode.Change(const AWord: WideString);
|
|
begin
|
|
FUndoManager.Add(MisspelledWord, AWord, '', FMisspelledStart - 1);
|
|
inherited Change(AWord);
|
|
end;
|
|
|
|
procedure TdxSpellCheckerDialogCheckMode.CreateParser;
|
|
begin
|
|
inherited CreateParser;
|
|
if not SpellChecker.CheckingContainer then
|
|
begin
|
|
if SpellChecker.SpellingOptions.CheckFromCursorPos or IsCheckingSelectedText then
|
|
begin
|
|
SpellingStart := FSaveSelStart;
|
|
Parser.GetNextDelimiterPosition(FSpellingStart, -1);
|
|
end;
|
|
if IsCheckingSelectedText then
|
|
begin
|
|
SpellingEnd := FSaveSelStart + FSaveSelLength;
|
|
Parser.GetNextDelimiterPosition(FSpellingEnd, 1);
|
|
end;
|
|
end;
|
|
Inc(FSpellingStart);
|
|
Inc(FSpellingEnd);
|
|
UpdateTextInfo;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerDialogCheckMode.Delete;
|
|
begin
|
|
FUndoManager.Add(' ' + MisspelledWord, '', PrevWord, FMisspelledStart - 2);
|
|
inherited Delete;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerDialogCheckMode.Ignore;
|
|
begin
|
|
FUndoManager.Add(MisspelledWord, MisspelledWord, PrevWord, FMisspelledStart - 1);
|
|
inherited Ignore;
|
|
end;
|
|
|
|
function TdxSpellCheckerDialogCheckMode.ShowDialog: Integer;
|
|
begin
|
|
if not Adapter.EditorHandleAllocated then
|
|
Adapter.Post;
|
|
Result := 0;
|
|
end;
|
|
|
|
function TdxSpellCheckerDialogCheckMode.IsCheckingSelectedText: Boolean;
|
|
begin
|
|
Result := SpellChecker.SpellingOptions.CheckSelectedTextFirst and
|
|
(FSaveSelLength > 0) and not FCheckedSelection;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerDialogCheckMode.UndoLast;
|
|
var
|
|
AItem: TdxSpellCheckerUndoItem;
|
|
begin
|
|
AItem := FUndoManager.Last;
|
|
if CanUndo and (AItem <> nil) then
|
|
begin
|
|
Adapter.SelStart := AItem.MisspelledWordPosition;
|
|
Adapter.SelLength := Length(AItem.Replacement);
|
|
UpdateSpellingBounds(Length(AItem.MisspelledWord) - Adapter.SelLength);
|
|
Adapter.SelText := AItem.MisspelledWord;
|
|
UpdateTextInfo;
|
|
SelectMisspelledWordAfterUndo;
|
|
ValidateSpellingBoundsAfterUndo;
|
|
PrevWord := AItem.PrevWord;
|
|
FUndoManager.UndoLast;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerDialogCheckMode.SaveSelection;
|
|
begin
|
|
FSaveHideSelection := Adapter.HideSelection;
|
|
FSaveSelLength := Adapter.SelLength;
|
|
FSaveSelStart := Adapter.SelStart;
|
|
Adapter.HideSelection := False;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerDialogCheckMode.ValidateSpellingBounds;
|
|
|
|
procedure SetBeforeSelectionBounds;
|
|
begin
|
|
SpellingEnd := SpellingStart;
|
|
SpellingStart := 1;
|
|
FMisspelledStart := 1;
|
|
end;
|
|
|
|
var
|
|
ASpellingStart, ASpellingEnd: Integer;
|
|
begin
|
|
if (SpellChecker.SpellingOptions.CheckFromCursorPos or IsCheckingSelectedText) and not SpellChecker.CheckingContainer then
|
|
begin
|
|
Adapter.GetSpellingBounds(ASpellingStart, ASpellingEnd);
|
|
if ((FMisspelledStart >= ASpellingEnd) or (FMisspelledStart < SpellingStart)) and (SpellingStart > 1) and
|
|
not IsCheckingSelectedText then
|
|
begin
|
|
SetBeforeSelectionBounds;
|
|
UpdateTextInfo;
|
|
end
|
|
else
|
|
if (FMisspelledStart >= SpellingEnd) and IsCheckingSelectedText and
|
|
(ASpellingStart = SpellingStart) and (ASpellingEnd = SpellingEnd) and
|
|
(MessageDlg(cxGetResourceString(@sdxSpellCheckerSelectionCheckIsFinished), mtInformation, [mbYes, mbNo], 0) = mrYes) then
|
|
begin
|
|
if SpellingEnd = ASpellingEnd then
|
|
SetBeforeSelectionBounds
|
|
else
|
|
SpellingEnd := ASpellingEnd;
|
|
FCheckedSelection := True;
|
|
UpdateTextInfo;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerDialogCheckMode.ValidateSpellingBoundsAfterUndo;
|
|
var
|
|
ASpellingStart, ASpellingEnd: Integer;
|
|
begin
|
|
Adapter.GetSpellingBounds(ASpellingStart, ASpellingEnd);
|
|
if (FMisspelledStart >= SpellingEnd) and (SpellingEnd < ASpellingEnd) then
|
|
begin
|
|
SpellingStart := SpellingEnd;
|
|
SpellingEnd := ASpellingEnd;
|
|
UpdateTextInfo;
|
|
end;
|
|
end;
|
|
|
|
function TdxSpellCheckerDialogCheckMode.GetLanguages: TdxSpellCheckerLanguages;
|
|
begin
|
|
Result := SpellChecker.Languages;
|
|
end;
|
|
|
|
{ TdxSpellCheckerOutlookCheckMode }
|
|
|
|
function TdxSpellCheckerOutlookCheckMode.ShowDialog: Integer;
|
|
begin
|
|
Result := dxShowOutlookSpellingDialog(SpellChecker);
|
|
inherited ShowDialog;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerOutlookCheckMode.SelectMisspelledWordAfterUndo;
|
|
var
|
|
AItem: TdxSpellCheckerUndoItem;
|
|
begin
|
|
AItem := FUndoManager.Last;
|
|
if AItem <> nil then
|
|
FMisspelledStart := FMisspelledStart - Length(AItem.Replacement) + Length(AItem.MisspelledWord);
|
|
inherited;
|
|
end;
|
|
|
|
{ TdxSpellCheckerWordCheckMode }
|
|
|
|
procedure TdxSpellCheckerWordCheckMode.ChangeSentence(const ASentence: WideString);
|
|
var
|
|
AMisspelledSentence: TdxSpellCheckerSentence;
|
|
ADelta: Integer;
|
|
begin
|
|
AMisspelledSentence := MisspelledSentence;
|
|
FUndoManager.Add(AMisspelledSentence.Text, ASentence, '', AMisspelledSentence.StartTextPosition - 1);
|
|
Adapter.SelStart := AMisspelledSentence.StartTextPosition - 1;
|
|
Adapter.SelLength := Length(AMisspelledSentence.Text);
|
|
PrevWord := '';
|
|
ADelta := Length(ASentence) - Adapter.SelLength;
|
|
Adapter.SelText := ASentence;
|
|
UpdateSpellingBounds(ADelta);
|
|
UpdateTextInfo;
|
|
FMisspelledStart := AMisspelledSentence.StartTextPosition - 1;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerWordCheckMode.SelectMisspelledWordAfterUndo;
|
|
var
|
|
AItem: TdxSpellCheckerUndoItem;
|
|
begin
|
|
AItem := FUndoManager.Last;
|
|
if AItem <> nil then
|
|
begin
|
|
FMisspelledStart := AItem.MisspelledWordPosition + 1;
|
|
FMisspelledLen := Length(AItem.MisspelledWord);
|
|
end;
|
|
inherited SelectMisspelledWordAfterUndo;
|
|
end;
|
|
|
|
function TdxSpellCheckerWordCheckMode.ShowDialog: Integer;
|
|
begin
|
|
Result := dxShowWordSpellingDialog(SpellChecker);
|
|
inherited ShowDialog;
|
|
end;
|
|
|
|
function TdxSpellCheckerWordCheckMode.GetMisspelledSentence: TdxSpellCheckerSentence;
|
|
begin
|
|
Result := Parser.GetSentence(FMisspelledStart);
|
|
end;
|
|
|
|
{ TdxSpellCheckerSuggestionBuilder }
|
|
|
|
constructor TdxSpellCheckerSuggestionBuilder.Create(
|
|
ADictionary: TdxCustomSpellCheckerDictionary);
|
|
begin
|
|
inherited Create;
|
|
FDictionary := ADictionary;
|
|
Alphabet := ADictionary.GetActiveAlphabet;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerSuggestionBuilder.AddSuggestions(
|
|
const AWord: WideString; ASuggestions: TdxSpellCheckerSuggestionList);
|
|
begin
|
|
if (ASuggestions = nil) or (Length(AWord) = 0) then Exit;
|
|
FSuggestions := ASuggestions;
|
|
FWord := WideLowerCase(AWord);
|
|
DoAddSuggestions;
|
|
end;
|
|
|
|
function TdxSpellCheckerSuggestionBuilder.CanAddToSuggestions(
|
|
const ATestWord: WideString): Boolean;
|
|
begin
|
|
Result := Dictionary.HasWord(ATestWord);
|
|
end;
|
|
|
|
procedure TdxSpellCheckerSuggestionBuilder.SetAlphabet(const AValue: WideString);
|
|
var
|
|
I: Integer;
|
|
ALower: WideString;
|
|
begin
|
|
FAlphabet := '';
|
|
if Length(AValue) > 0 then
|
|
begin
|
|
ALower := WideLowerCase(AValue);
|
|
for I := 1 to Length(ALower) do
|
|
if WideCharPos(ALower[I], FAlphabet) = 0 then
|
|
FAlphabet := FAlphabet + ALower[I];
|
|
end;
|
|
end;
|
|
|
|
{ TdxNearMissStrategy }
|
|
|
|
procedure TdxNearMissStrategy.CheckAddToSuggestions(const ATestWord: WideString;
|
|
ADistance: Integer = 2);
|
|
begin
|
|
if CanAddToSuggestions(ATestWord) then
|
|
FSuggestions.Add(ATestWord, Dictionary, ADistance);
|
|
end;
|
|
|
|
procedure TdxNearMissStrategy.CheckDeleteLetter;
|
|
var
|
|
ATestWord: WideString;
|
|
ASymbol: WideChar;
|
|
ADeletePos, ALen: Integer;
|
|
begin
|
|
ALen := Length(FWord);
|
|
if ALen < 2 then Exit;
|
|
ADeletePos := 1;
|
|
repeat
|
|
ATestWord := FWord;
|
|
ASymbol := ATestWord[ADeletePos];
|
|
Delete(ATestWord, ADeletePos, 1);
|
|
CheckAddToSuggestions(ATestWord);
|
|
Inc(ADeletePos);
|
|
while (ADeletePos <= ALen) and (ASymbol = FWord[ADeletePos]) do
|
|
Inc(ADeletePos);
|
|
until ADeletePos > ALen;
|
|
end;
|
|
|
|
procedure TdxNearMissStrategy.InterchangeTwoLetters;
|
|
var
|
|
ATestWord: WideString;
|
|
I, ALen: Integer;
|
|
begin
|
|
ALen := Length(Word);
|
|
if ALen < 2 then Exit;
|
|
for I := 1 to ALen - 1 do
|
|
begin
|
|
if FWord[I] = Word[I + 1] then Continue;
|
|
ATestWord := Word;
|
|
ATestWord[I] := ATestWord[I + 1];
|
|
ATestWord[I + 1] := Word[I];
|
|
CheckAddToSuggestions(ATestWord);
|
|
end;
|
|
end;
|
|
|
|
procedure TdxNearMissStrategy.CheckChangeOneLetter;
|
|
var
|
|
ATestWord: WideString;
|
|
ASymbol: WideChar;
|
|
I, J: Integer;
|
|
begin
|
|
if Length(Alphabet) = 0 then Exit;
|
|
for I := 1 to Length(Word) do
|
|
for J := 1 to Length(Alphabet) do
|
|
begin
|
|
ASymbol := Alphabet[J];
|
|
if Word[I] <> ASymbol then
|
|
begin
|
|
ATestWord := Word;
|
|
ATestWord[I] := ASymbol;
|
|
CheckAddToSuggestions(ATestWord);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxNearMissStrategy.CheckInsertLetter;
|
|
var
|
|
ATestWord: WideString;
|
|
ASymbol: WideChar;
|
|
I, AInsertPos, ALen: Integer;
|
|
begin
|
|
if Length(Alphabet) = 0 then Exit;
|
|
ALen := Length(Word);
|
|
for I := 1 to Length(Alphabet) do
|
|
begin
|
|
ASymbol := Alphabet[I];
|
|
AInsertPos := 1;
|
|
repeat
|
|
ATestWord := Word;
|
|
while (AInsertPos <= ALen) and (ASymbol = ATestWord[AInsertPos]) do
|
|
Inc(AInsertPos);
|
|
Insert(ASymbol, ATestWord, AInsertPos);
|
|
CheckAddToSuggestions(ATestWord);
|
|
if AInsertPos > ALen then
|
|
Break
|
|
else
|
|
Inc(AInsertPos);
|
|
until False;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxNearMissStrategy.CheckInsertSpace;
|
|
var
|
|
ATestWord1, ATestWord2: WideString;
|
|
I, ALen: Integer;
|
|
begin
|
|
ALen := Length(Word);
|
|
if ALen < 2 then Exit;
|
|
for I := 1 to ALen - 1 do
|
|
begin
|
|
ATestWord1 := Copy(Word, 1, I);
|
|
ATestWord2 := Copy(Word, I + 1, ALen);
|
|
if CanAddToSuggestions(ATestWord1) and CanAddToSuggestions(ATestWord2) then
|
|
FSuggestions.Add(ATestWord1 + ' ' + ATestWord2, Dictionary, 3);
|
|
end;
|
|
end;
|
|
|
|
procedure TdxNearMissStrategy.DoAddSuggestions;
|
|
begin
|
|
CheckInsertLetter;
|
|
CheckInsertSpace;
|
|
CheckDeleteLetter;
|
|
InterchangeTwoLetters;
|
|
CheckChangeOneLetter;
|
|
end;
|
|
|
|
{ TdxSpellCheckerWordList }
|
|
|
|
constructor TdxSpellCheckerWordList.Create(ALangID: Cardinal; ATableSize: Integer);
|
|
begin
|
|
inherited Create;
|
|
InitializeCriticalSection(FLock);
|
|
FLangID := ALangID;
|
|
FCount := 0;
|
|
FTableSize := ATableSize;
|
|
FTable := AllocMem(FTableSize * SizeOf(Integer));
|
|
end;
|
|
|
|
destructor TdxSpellCheckerWordList.Destroy;
|
|
begin
|
|
Clear;
|
|
FreeMem(FTable);
|
|
DeleteCriticalSection(FLock);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerWordList.Add(const S: WideString);
|
|
var
|
|
AIndex, ASrcLen, AWordLen: Integer;
|
|
AWord, ATemp, P: PWideChar;
|
|
begin
|
|
ASrcLen := Length(S);
|
|
if ASrcLen = 0 then Exit;
|
|
EnterCriticalSection(FLock);
|
|
try
|
|
P := Pointer(S);
|
|
AIndex := ElfHash(P) mod FTableSize;
|
|
AWord := FTable^[AIndex];
|
|
if AWord = nil then
|
|
FTable^[AIndex] := NewWord(P)
|
|
else
|
|
begin
|
|
repeat
|
|
AWordLen := WordLength(AWord);
|
|
if (AWordLen = ASrcLen) and
|
|
(CompareStringW(LangID, NORM_IGNORECASE, AWord, AWordLen, P, ASrcLen) = CSTR_EQUAL) then Exit;
|
|
ATemp := GetNextWord(AWord);
|
|
if ATemp = nil then
|
|
begin
|
|
SetNextWord(AWord, NewWord(P));
|
|
Break;
|
|
end;
|
|
AWord := ATemp;
|
|
until False;
|
|
end;
|
|
Inc(FCount);
|
|
finally
|
|
LeaveCriticalSection(FLock);
|
|
end;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerWordList.Clear;
|
|
var
|
|
I: Integer;
|
|
AWord, ATemp: PWideChar;
|
|
begin
|
|
if Count = 0 then Exit;
|
|
EnterCriticalSection(FLock);
|
|
try
|
|
for I := 0 to FTableSize - 1 do
|
|
begin
|
|
AWord := FTable^[I];
|
|
while AWord <> nil do
|
|
begin
|
|
ATemp := AWord;
|
|
AWord := GetNextWord(AWord);
|
|
DisposeWord(ATemp);
|
|
end;
|
|
FTable^[I] := nil;
|
|
end;
|
|
FCount := 0;
|
|
finally
|
|
LeaveCriticalSection(FLock);
|
|
end;
|
|
end;
|
|
|
|
function TdxSpellCheckerWordList.Find(const S: WideString): Boolean;
|
|
begin
|
|
Result := FindWord(S) <> nil;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerWordList.LoadFromStrings(AStrings: TStrings);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if AStrings = nil then Exit;
|
|
Clear;
|
|
for I := 0 to AStrings.Count - 1 do
|
|
Add(AStrings[I]);
|
|
end;
|
|
|
|
procedure TdxSpellCheckerWordList.SaveToStrings(AStrings: TStrings);
|
|
var
|
|
I: Integer;
|
|
AWord: PWideChar;
|
|
begin
|
|
if AStrings = nil then Exit;
|
|
AStrings.BeginUpdate;
|
|
try
|
|
AStrings.Clear;
|
|
for I := 0 to FTableSize - 1 do
|
|
begin
|
|
AWord := FTable^[I];
|
|
while AWord <> nil do
|
|
begin
|
|
AStrings.Add(AWord);
|
|
AWord := GetNextWord(AWord);
|
|
end;
|
|
end;
|
|
finally
|
|
AStrings.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
function TdxSpellCheckerWordList.ElfHash(P: PWideChar): Integer;
|
|
var
|
|
I: Integer;
|
|
ABuffer: array[0..256] of WideChar;
|
|
begin
|
|
LCMapStringW(LangID, LCMAP_LOWERCASE, P, -1, @ABuffer, SizeOf(ABuffer) div SizeOf(WideChar));
|
|
Result := 0;
|
|
Pointer(P) := @ABuffer;
|
|
while P^ <> #$00 do
|
|
begin
|
|
Result := (Result shl 4) + Ord(P^);
|
|
I := Result and $F0000000;
|
|
if (I <> 0) then
|
|
Result := Result xor (I shr 24);
|
|
Result := Result and (not I);
|
|
Inc(P);
|
|
end;
|
|
end;
|
|
|
|
function TdxSpellCheckerWordList.FindWord(const S: WideString): PWideChar;
|
|
var
|
|
AIndex, ASrcLen, AResultLen: Integer;
|
|
P: PWideChar;
|
|
begin
|
|
Result := nil;
|
|
ASrcLen := Length(S);
|
|
if ASrcLen = 0 then Exit;
|
|
P := Pointer(S);
|
|
AIndex := ElfHash(P) mod FTableSize;
|
|
Result := FTable^[AIndex];
|
|
while Result <> nil do
|
|
begin
|
|
AResultLen := WordLength(Result);
|
|
if (AResultLen = ASrcLen) and
|
|
(CompareStringW(LangID, NORM_IGNORECASE, Result, AResultLen, P, ASrcLen) = CSTR_EQUAL) then Exit;
|
|
Result := GetNextWord(Result);
|
|
end;
|
|
end;
|
|
|
|
function TdxSpellCheckerWordList.NewWord(S: PWideChar): PWideChar;
|
|
var
|
|
P : PWideChar;
|
|
ALength: Integer;
|
|
begin
|
|
Result := nil;
|
|
if S = nil then Exit;
|
|
P := S;
|
|
while (P^ <> #0) do Inc(P);
|
|
ALength := P - S;
|
|
if ALength > 0 then
|
|
begin
|
|
Result := AllocWord(ALength);
|
|
Inc(ALength); //include terminated null
|
|
Move(S^, Result^, ALength * SizeOf(WideChar));
|
|
end;
|
|
end;
|
|
|
|
function TdxSpellCheckerWordList.AllocWord(ACharCount: Cardinal): PWideChar;
|
|
var
|
|
ASize: Integer;
|
|
begin
|
|
ASize := (ACharCount + 1) * Sizeof(WideChar); //add terminated null
|
|
Inc(ASize, SizeOf(Cardinal) * 3); //Size, Next, Length
|
|
GetMem(Result, ASize);
|
|
Cardinal(Pointer(Result)^) := ASize; //Size
|
|
Inc(PChar(Result), SizeOf(Cardinal));
|
|
Pointer(Pointer(Result)^) := nil; //Next
|
|
Inc(PChar(Result), SizeOf(Cardinal));
|
|
Cardinal(Pointer(Result)^) := ACharCount; //Length
|
|
Inc(PChar(Result), SizeOf(Cardinal));
|
|
end;
|
|
|
|
procedure TdxSpellCheckerWordList.DisposeWord(AWord: PWideChar);
|
|
begin
|
|
if AWord <> nil then
|
|
begin
|
|
Dec(PChar(AWord), SizeOf(Cardinal) * 3);
|
|
FreeMem(AWord, Cardinal(Pointer(AWord)^));
|
|
end;
|
|
end;
|
|
|
|
function TdxSpellCheckerWordList.GetNextWord(AWord: PWideChar): Pointer;
|
|
begin
|
|
if AWord = nil then
|
|
Result := nil
|
|
else
|
|
begin
|
|
Dec(PChar(AWord), SizeOf(Cardinal) * 2);
|
|
Result := Pointer(Pointer(AWord)^);
|
|
end;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerWordList.SetNextWord(AWord: PWideChar; AValue: Pointer);
|
|
begin
|
|
if AWord <> nil then
|
|
begin
|
|
Dec(PChar(AWord), SizeOf(Cardinal) * 2);
|
|
Pointer(Pointer(AWord)^) := AValue;
|
|
end;
|
|
end;
|
|
|
|
function TdxSpellCheckerWordList.WordLength(AWord: PWideChar): Integer;
|
|
begin
|
|
if AWord = nil then
|
|
Result := 0
|
|
else
|
|
begin
|
|
Dec(PChar(AWord), SizeOf(Cardinal));
|
|
Result := Cardinal(Pointer(AWord)^);
|
|
end;
|
|
end;
|
|
|
|
function TdxSpellCheckerWordList.GetCodePage: Cardinal;
|
|
begin
|
|
Result := LanguageToCodePage(FLangID);
|
|
end;
|
|
|
|
{ TdxDictionaryLoadThread }
|
|
|
|
constructor TdxDictionaryLoadThread.Create(
|
|
ADictionary: TdxCustomSpellCheckerDictionary);
|
|
begin
|
|
inherited Create(False);
|
|
FDictionary := ADictionary;
|
|
OnTerminate := Dictionary.ThreadDone;
|
|
end;
|
|
|
|
function TdxDictionaryLoadThread.IsLoadComplete: Boolean;
|
|
begin
|
|
Result := not Terminated and Dictionary.Loaded;
|
|
end;
|
|
|
|
procedure TdxDictionaryLoadThread.Execute;
|
|
begin
|
|
ResetException;
|
|
try
|
|
with Dictionary do
|
|
begin
|
|
try
|
|
Synchronize(UpdateLoadedOnLoadEvent);
|
|
if not Loaded then
|
|
FLoaded := DoLoad and not Terminated;
|
|
except
|
|
FLoaded := False;
|
|
raise;
|
|
end;
|
|
if Loaded then
|
|
Synchronize(LoadingComplete);
|
|
end;
|
|
except
|
|
HandleException;
|
|
end;
|
|
end;
|
|
|
|
{ TdxCustomSpellCheckerDictionary }
|
|
|
|
constructor TdxCustomSpellCheckerDictionary.Create(ASpellChecker: TdxCustomSpellChecker);
|
|
begin
|
|
inherited Create;
|
|
FSpellChecker := ASpellChecker;
|
|
FEnabled := True;
|
|
FCodePage := CP_ACP;
|
|
FWords := TdxSpellCheckerWordList.Create(CodePage, 269683);
|
|
Language := GetSystemDefaultLangID;
|
|
end;
|
|
|
|
destructor TdxCustomSpellCheckerDictionary.Destroy;
|
|
begin
|
|
FLoadThread.Free; //don't use FreeAndNil
|
|
FLoadThread := nil;
|
|
Unload;
|
|
FWords.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TdxCustomSpellCheckerDictionary.Assign(Source: TPersistent);
|
|
begin
|
|
if Source is TdxCustomSpellCheckerDictionary then
|
|
begin
|
|
FAlphabet := TdxCustomSpellCheckerDictionary(Source).Alphabet;
|
|
FCodePage := TdxCustomSpellCheckerDictionary(Source).CodePage;
|
|
FEnabled := TdxCustomSpellCheckerDictionary(Source).Enabled;
|
|
FLanguage := TdxCustomSpellCheckerDictionary(Source).Language;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxCustomSpellCheckerDictionary.Activate;
|
|
begin
|
|
DoActivate;
|
|
end;
|
|
|
|
procedure TdxCustomSpellCheckerDictionary.Load(
|
|
AMode: TdxSpellCheckerDictionaryLoadMode = dlmDefault);
|
|
begin
|
|
case AMode of
|
|
dlmDefault:
|
|
begin
|
|
if SpellChecker.UseThreadedLoad then
|
|
LoadUsingThread
|
|
else
|
|
DirectLoad;
|
|
end;
|
|
dlmDirectLoad:
|
|
DirectLoad;
|
|
dlmThreadedLoad:
|
|
LoadUsingThread;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxCustomSpellCheckerDictionary.Unload;
|
|
begin
|
|
if LoadThread <> nil then
|
|
LoadThread.Terminate;
|
|
if Loaded then
|
|
FLoaded := not DoUnload;
|
|
if not Loaded then
|
|
Cleanup;
|
|
Update;
|
|
end;
|
|
|
|
procedure TdxCustomSpellCheckerDictionary.Clear;
|
|
begin
|
|
Enabled := False;
|
|
Unload;
|
|
end;
|
|
|
|
function TdxCustomSpellCheckerDictionary.CanLoad: Boolean;
|
|
begin
|
|
Result := not Loaded and (FLoadThread = nil);
|
|
end;
|
|
|
|
procedure TdxCustomSpellCheckerDictionary.Cleanup;
|
|
begin
|
|
Words.Clear;
|
|
end;
|
|
|
|
function TdxCustomSpellCheckerDictionary.CreateSuggestionBuilder: TdxSpellCheckerSuggestionBuilder;
|
|
begin
|
|
Result := TdxNearMissStrategy.Create(Self);
|
|
end;
|
|
|
|
procedure TdxCustomSpellCheckerDictionary.DirectLoad;
|
|
begin
|
|
if not CanLoad then Exit;
|
|
ShowHourglassCursor;
|
|
try
|
|
try
|
|
FLoaded := DoLoadingEvent or DoLoad;
|
|
except
|
|
FLoaded := False;
|
|
raise;
|
|
end;
|
|
if Loaded then
|
|
LoadingComplete;
|
|
finally
|
|
HideHourglassCursor;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxCustomSpellCheckerDictionary.DoActivate;
|
|
begin
|
|
Load;
|
|
Enabled := True;
|
|
end;
|
|
|
|
function TdxCustomSpellCheckerDictionary.DoLoad: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
procedure TdxCustomSpellCheckerDictionary.DoLoadedEvent;
|
|
begin
|
|
if Assigned(FOnLoaded) then
|
|
FOnLoaded(Self);
|
|
end;
|
|
|
|
function TdxCustomSpellCheckerDictionary.DoLoadingEvent: Boolean;
|
|
begin
|
|
Result := False;
|
|
if Assigned(FOnLoading) then
|
|
FOnLoading(Self, Result);
|
|
end;
|
|
|
|
function TdxCustomSpellCheckerDictionary.DoUnload: Boolean;
|
|
begin
|
|
Words.Clear;
|
|
Result := True;
|
|
end;
|
|
|
|
function TdxCustomSpellCheckerDictionary.GetActiveAlphabet: WideString;
|
|
begin
|
|
if Alphabet = '' then
|
|
Result := CreateDefaultAlphabet(CodePage)
|
|
else
|
|
Result := Alphabet;
|
|
end;
|
|
|
|
function TdxCustomSpellCheckerDictionary.GetDisplayName: string;
|
|
begin
|
|
Result := GetRegisteredDictionaryTypes.GetDescriptionByClass(ClassType);
|
|
if Result = '' then
|
|
Result := ClassName;
|
|
end;
|
|
|
|
procedure TdxCustomSpellCheckerDictionary.LoadingComplete;
|
|
begin
|
|
DoLoadedEvent;
|
|
Update;
|
|
end;
|
|
|
|
function TdxCustomSpellCheckerDictionary.LoadingTerminated: Boolean;
|
|
begin
|
|
Result := (FLoadThread <> nil) and FLoadThread.Terminated;
|
|
end;
|
|
|
|
procedure TdxCustomSpellCheckerDictionary.LoadUsingThread;
|
|
begin
|
|
if not CanLoad then Exit;
|
|
FreeAndNil(FLoadThread);
|
|
FLoadThread := TdxDictionaryLoadThread.Create(Self);
|
|
end;
|
|
|
|
procedure TdxCustomSpellCheckerDictionary.ThreadDone(Sender: TObject);
|
|
begin
|
|
if not LoadThread.IsLoadComplete then
|
|
Cleanup
|
|
else
|
|
SpellChecker.CheckCallEnabledDictionariesLoaded;
|
|
end;
|
|
|
|
procedure TdxCustomSpellCheckerDictionary.Update;
|
|
begin
|
|
SpellChecker.UpdateByDictionary(Self);
|
|
end;
|
|
|
|
procedure TdxCustomSpellCheckerDictionary.UpdateLoadedOnLoadEvent;
|
|
begin
|
|
FLoaded := DoLoadingEvent;
|
|
end;
|
|
|
|
function TdxCustomSpellCheckerDictionary.GetActive: Boolean;
|
|
begin
|
|
Result := Loaded and Enabled;
|
|
end;
|
|
|
|
function TdxCustomSpellCheckerDictionary.GetWordCount: Integer;
|
|
begin
|
|
Result := FWords.Count;
|
|
end;
|
|
|
|
function TdxCustomSpellCheckerDictionary.HasWord(
|
|
const AWord: WideString): Boolean;
|
|
begin
|
|
Result := FWords.Find(AWord);
|
|
end;
|
|
|
|
procedure TdxCustomSpellCheckerDictionary.SetEnabled(AValue: Boolean);
|
|
begin
|
|
if FEnabled <> AValue then
|
|
begin
|
|
FEnabled := AValue;
|
|
if Loaded then
|
|
Update;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxCustomSpellCheckerDictionary.SetCodePage(AValue: Cardinal);
|
|
begin
|
|
if FCodePage <> AValue then
|
|
begin
|
|
FCodePage := AValue;
|
|
if Loaded then
|
|
begin
|
|
Unload;
|
|
Load;
|
|
Update;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxCustomSpellCheckerDictionary.SetLanguage(const AValue: DWORD);
|
|
begin
|
|
if FLanguage <> AValue then
|
|
begin
|
|
FLanguage := AValue;
|
|
FWords.LangID := FLanguage;
|
|
end;
|
|
end;
|
|
|
|
{ TdxUserSpellCheckerDictionary }
|
|
|
|
constructor TdxUserSpellCheckerDictionary.Create(
|
|
ASpellChecker: TdxCustomSpellChecker);
|
|
begin
|
|
inherited Create(ASpellChecker);
|
|
FOptions := [udSaveOnUnload];
|
|
end;
|
|
|
|
procedure TdxUserSpellCheckerDictionary.Assign(Source: TPersistent);
|
|
begin
|
|
inherited Assign(Source);
|
|
if Source is TdxUserSpellCheckerDictionary then
|
|
begin
|
|
DictionaryPath := TdxUserSpellCheckerDictionary(Source).DictionaryPath;
|
|
Options := TdxUserSpellCheckerDictionary(Source).Options;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxUserSpellCheckerDictionary.AddWord(const AWord: WideString);
|
|
begin
|
|
Words.Add(AWord);
|
|
Update;
|
|
end;
|
|
|
|
procedure TdxUserSpellCheckerDictionary.LoadFromStrings(AStrings: TStrings);
|
|
begin
|
|
Words.LoadFromStrings(AStrings);
|
|
Update;
|
|
end;
|
|
|
|
procedure TdxUserSpellCheckerDictionary.SaveToStrings(AStrings: TStrings);
|
|
begin
|
|
if AStrings = nil then Exit;
|
|
Words.SaveToStrings(AStrings);
|
|
if AStrings is TStringList then
|
|
TStringList(AStrings).Sort;
|
|
end;
|
|
|
|
function TdxUserSpellCheckerDictionary.DoLoad: Boolean;
|
|
var
|
|
AStrings: TStrings;
|
|
begin
|
|
Result := True;
|
|
if not FileExists(DictionaryPath) then
|
|
if not (udFileMustExist in Options) then Exit;
|
|
AStrings := TStringList.Create;
|
|
try
|
|
AStrings.LoadFromFile(DictionaryPath);
|
|
Words.LoadFromStrings(AStrings);
|
|
finally
|
|
AStrings.Free;
|
|
end;
|
|
end;
|
|
|
|
function TdxUserSpellCheckerDictionary.DoUnload: Boolean;
|
|
var
|
|
AStrings: TStrings;
|
|
begin
|
|
Result := True;
|
|
if udSaveOnUnload in Options then
|
|
begin
|
|
AStrings := TStringList.Create;
|
|
try
|
|
Words.SaveToStrings(AStrings);
|
|
try
|
|
AStrings.SaveToFile(DictionaryPath);
|
|
except
|
|
if not (csDestroying in SpellChecker.ComponentState) then
|
|
raise;
|
|
end;
|
|
finally
|
|
AStrings.Free;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TdxUserSpellCheckerDictionary.GetDisplayName: string;
|
|
var
|
|
AFileName: TFileName;
|
|
begin
|
|
Result := inherited GetDisplayName;
|
|
AFileName := ExtractFileName(DictionaryPath);
|
|
if AFileName <> '' then
|
|
Result := Format('%s (%s)', [Result, AFileName]);
|
|
end;
|
|
|
|
{ TdxSpellCheckerDictionaryItem }
|
|
|
|
destructor TdxSpellCheckerDictionaryItem.Destroy;
|
|
begin
|
|
FreeAndNil(FDictionaryType);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerDictionaryItem.Assign(Source: TPersistent);
|
|
begin
|
|
if Source is TdxSpellCheckerDictionaryItem then
|
|
begin
|
|
DictionaryTypeClassName := TdxSpellCheckerDictionaryItem(Source).DictionaryTypeClassName;
|
|
DictionaryType := TdxSpellCheckerDictionaryItem(Source).DictionaryType;
|
|
end;
|
|
end;
|
|
|
|
function TdxSpellCheckerDictionaryItem.GetDisplayName: string;
|
|
begin
|
|
if FDictionaryType <> nil then
|
|
Result := FDictionaryType.GetDisplayName
|
|
else
|
|
Result := inherited GetDisplayName;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerDictionaryItem.RecreateDictionaryType;
|
|
begin
|
|
FreeAndNil(FDictionaryType);
|
|
if FDictionaryTypeClass <> nil then
|
|
FDictionaryType := FDictionaryTypeClass.Create(Collection.SpellChecker);
|
|
end;
|
|
|
|
function TdxSpellCheckerDictionaryItem.GetCollection: TdxSpellCheckerDictionaries;
|
|
begin
|
|
Result := TdxSpellCheckerDictionaries(inherited Collection);
|
|
end;
|
|
|
|
function TdxSpellCheckerDictionaryItem.GetDictionaryTypeClassName: string;
|
|
begin
|
|
if FDictionaryType = nil then
|
|
Result := ''
|
|
else
|
|
Result := FDictionaryType.ClassName;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerDictionaryItem.SetDictionaryType(
|
|
AValue: TdxCustomSpellCheckerDictionary);
|
|
begin
|
|
if (FDictionaryType <> nil) and (AValue <> nil) then
|
|
FDictionaryType.Assign(AValue);
|
|
end;
|
|
|
|
procedure TdxSpellCheckerDictionaryItem.SetDictionaryTypeClass(
|
|
AValue: TdxCustomSpellCheckerDictionaryClass);
|
|
begin
|
|
if FDictionaryTypeClass <> AValue then
|
|
begin
|
|
FDictionaryTypeClass := AValue;
|
|
RecreateDictionaryType;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerDictionaryItem.SetDictionaryTypeClassName(
|
|
const AValue: string);
|
|
begin
|
|
if not SameText(DictionaryTypeClassName, AValue) then
|
|
begin
|
|
with GetRegisteredDictionaryTypes do
|
|
DictionaryTypeClass := TdxCustomSpellCheckerDictionaryClass(FindByClassName(AValue));
|
|
end;
|
|
end;
|
|
|
|
{ TdxSpellCheckerDictionaries }
|
|
|
|
constructor TdxSpellCheckerDictionaries.Create(ASpellChecker: TdxCustomSpellChecker);
|
|
begin
|
|
inherited Create(TdxSpellCheckerDictionaryItem);
|
|
FSpellChecker := ASpellChecker;
|
|
end;
|
|
|
|
function TdxSpellCheckerDictionaries.Add: TdxSpellCheckerDictionaryItem;
|
|
begin
|
|
Result := TdxSpellCheckerDictionaryItem(inherited Add);
|
|
end;
|
|
|
|
function TdxSpellCheckerDictionaries.GetNamePath: string;
|
|
var
|
|
S: string;
|
|
begin
|
|
S := SpellChecker.Name;
|
|
if S = '' then
|
|
S := SpellChecker.GetNamePath;
|
|
Result := S + '.' + 'Items';
|
|
end;
|
|
|
|
function TdxSpellCheckerDictionaries.GetOwner: TPersistent;
|
|
begin
|
|
Result := SpellChecker;
|
|
end;
|
|
|
|
function TdxSpellCheckerDictionaries.GetItem(
|
|
Index: Integer): TdxSpellCheckerDictionaryItem;
|
|
begin
|
|
Result := TdxSpellCheckerDictionaryItem(inherited Items[Index]);
|
|
end;
|
|
|
|
procedure TdxSpellCheckerDictionaries.SetItem(Index: Integer;
|
|
AValue: TdxSpellCheckerDictionaryItem);
|
|
begin
|
|
inherited Items[Index] := AValue;
|
|
end;
|
|
|
|
{ TdxSpellCheckerSpellingOptions }
|
|
|
|
constructor TdxSpellCheckerSpellingOptions.Create(
|
|
ASpellChecker: TdxCustomSpellChecker);
|
|
begin
|
|
inherited Create;
|
|
FSpellChecker := ASpellChecker;
|
|
FIgnoreMixedCaseWords := True;
|
|
FIgnoreUpperCaseWords := True;
|
|
FIgnoreMarkupTags := True;
|
|
FIgnoreRepeatedWords := False;
|
|
FCheckSelectedTextFirst := True;
|
|
FIgnoreUrls := True;
|
|
FCheckFromCursorPos := False;
|
|
FIgnoreEmails := True;
|
|
FIgnoreWordsWithNumbers := True;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerSpellingOptions.Assign(Source: TPersistent);
|
|
begin
|
|
if Source is TdxSpellCheckerSpellingOptions then
|
|
begin
|
|
FIgnoreMixedCaseWords := TdxSpellCheckerSpellingOptions(Source).IgnoreMixedCaseWords;
|
|
FIgnoreUpperCaseWords := TdxSpellCheckerSpellingOptions(Source).IgnoreUpperCaseWords;
|
|
FIgnoreMarkupTags := TdxSpellCheckerSpellingOptions(Source).IgnoreMarkupTags;
|
|
FIgnoreRepeatedWords := TdxSpellCheckerSpellingOptions(Source).IgnoreRepeatedWords;
|
|
FCheckSelectedTextFirst := TdxSpellCheckerSpellingOptions(Source).CheckSelectedTextFirst;
|
|
FIgnoreUrls := TdxSpellCheckerSpellingOptions(Source).IgnoreUrls;
|
|
FCheckFromCursorPos := TdxSpellCheckerSpellingOptions(Source).CheckFromCursorPos;
|
|
FIgnoreEmails := TdxSpellCheckerSpellingOptions(Source).IgnoreEmails;
|
|
FIgnoreWordsWithNumbers := TdxSpellCheckerSpellingOptions(Source).IgnoreWordsWithNumbers;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerSpellingOptions.Changed;
|
|
begin
|
|
SpellChecker.SpellingOptionsChanged;
|
|
DoChanged;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerSpellingOptions.DoChanged;
|
|
begin
|
|
if Assigned(FOnChanged) then
|
|
FOnChanged(Self);
|
|
end;
|
|
|
|
procedure TdxSpellCheckerSpellingOptions.PopulateRules(
|
|
ARules: TdxSpellCheckerRules; AParser: TdxSpellCheckerTextParser);
|
|
begin
|
|
if AParser = nil then
|
|
Exit;
|
|
if not IgnoreRepeatedWords then
|
|
ARules.Add(TdxSpellCheckerRepeatedWordsRule.Create(AParser));
|
|
if IgnoreEmails then
|
|
ARules.Add(TdxSpellCheckerIgnoreEmailRule.Create(AParser));
|
|
if IgnoreMixedCaseWords then
|
|
ARules.Add(TdxSpellCheckerIgnoreMixedCaseWordsRule.Create(AParser));
|
|
if IgnoreUpperCaseWords then
|
|
ARules.Add(TdxSpellCheckerIgnoreUpperCaseWordsRule.Create(AParser));
|
|
if IgnoreUrls then
|
|
ARules.Add(TdxSpellCheckerIgnoreUrlRule.Create(AParser));
|
|
if IgnoreWordsWithNumbers then
|
|
ARules.Add(TdxSpellCheckerIgnoreWordsWithNumbersRule.Create(AParser));
|
|
end;
|
|
|
|
procedure TdxSpellCheckerSpellingOptions.SetCheckFromCursorPos(
|
|
AValue: Boolean);
|
|
begin
|
|
if FCheckFromCursorPos <> AValue then
|
|
begin
|
|
FCheckFromCursorPos := AValue;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerSpellingOptions.SetCheckSelectedTextFirst(
|
|
AValue: Boolean);
|
|
begin
|
|
if FCheckSelectedTextFirst <> AValue then
|
|
begin
|
|
FCheckSelectedTextFirst := AValue;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerSpellingOptions.SetIgnoreEmails(
|
|
AValue: Boolean);
|
|
begin
|
|
if FIgnoreEmails <> AValue then
|
|
begin
|
|
FIgnoreEmails := AValue;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerSpellingOptions.SetIgnoreMarkupTags(
|
|
AValue: Boolean);
|
|
begin
|
|
if FIgnoreMarkupTags <> AValue then
|
|
begin
|
|
FIgnoreMarkupTags := AValue;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerSpellingOptions.SetIgnoreMixedCaseWords(
|
|
AValue: Boolean);
|
|
begin
|
|
if FIgnoreMixedCaseWords <> AValue then
|
|
begin
|
|
FIgnoreMixedCaseWords := AValue;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerSpellingOptions.SetIgnoreRepeatedWords(
|
|
AValue: Boolean);
|
|
begin
|
|
if FIgnoreRepeatedWords <> AValue then
|
|
begin
|
|
FIgnoreRepeatedWords := AValue;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerSpellingOptions.SetIgnoreUpperCaseWords(
|
|
AValue: Boolean);
|
|
begin
|
|
if FIgnoreUpperCaseWords <> AValue then
|
|
begin
|
|
FIgnoreUpperCaseWords := AValue;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerSpellingOptions.SetIgnoreUrls(
|
|
AValue: Boolean);
|
|
begin
|
|
if FIgnoreUrls <> AValue then
|
|
begin
|
|
FIgnoreUrls := AValue;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerSpellingOptions.SetIgnoreWordsWithNumbers(
|
|
AValue: Boolean);
|
|
begin
|
|
if FIgnoreWordsWithNumbers <> AValue then
|
|
begin
|
|
FIgnoreWordsWithNumbers := AValue;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
{ TdxSpellCheckerCheckAsYouTypeOptions }
|
|
|
|
constructor TdxSpellCheckerCheckAsYouTypeOptions.Create(
|
|
ASpellChecker: TdxCustomSpellChecker);
|
|
begin
|
|
FSpellChecker := ASpellChecker;
|
|
FSuggestionCount := 5;
|
|
FUnderlineColor := clRed;
|
|
FUnderlineStyle := usAuto;
|
|
FModifyControlPopupMenu := True;
|
|
FPopupMenuItems := [scmiAddToDictionary, scmiDelete, scmiIgnoreAll, scmiSpelling, scmiSuggestions];
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCheckAsYouTypeOptions.Assign(Source: TPersistent);
|
|
begin
|
|
if Source is TdxSpellCheckerCheckAsYouTypeOptions then
|
|
begin
|
|
FSuggestionCount := TdxSpellCheckerCheckAsYouTypeOptions(Source).FSuggestionCount;
|
|
FUnderlineColor := TdxSpellCheckerCheckAsYouTypeOptions(Source).FUnderlineColor;
|
|
FUnderlineStyle := TdxSpellCheckerCheckAsYouTypeOptions(Source).FUnderlineStyle;
|
|
FModifyControlPopupMenu := TdxSpellCheckerCheckAsYouTypeOptions(Source).ModifyControlPopupMenu;
|
|
FPopupMenu := TdxSpellCheckerCheckAsYouTypeOptions(Source).PopupMenu;
|
|
FPopupMenuItems := TdxSpellCheckerCheckAsYouTypeOptions(Source).PopupMenuItems;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCheckAsYouTypeOptions.Changed;
|
|
begin
|
|
if SpellChecker.CheckAsYouTypeManager <> nil then
|
|
SpellChecker.CheckAsYouTypeManager.DoOptionsChanged;
|
|
DoChanged;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCheckAsYouTypeOptions.DoChanged;
|
|
begin
|
|
if Assigned(FOnChanged) then
|
|
FOnChanged(Self);
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCheckAsYouTypeOptions.Notification(AComponent: TComponent; AOperation: TOperation);
|
|
begin
|
|
if (AComponent = FPopupMenu) and (AOperation = opRemove) then
|
|
PopupMenu := nil;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCheckAsYouTypeOptions.SetActive(AValue: Boolean);
|
|
begin
|
|
if FActive <> AValue then
|
|
begin
|
|
FActive := AValue;
|
|
SpellChecker.UpdateCheckAsYouTypeManagerState;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCheckAsYouTypeOptions.SetPopupMenu(AValue: TComponent);
|
|
begin
|
|
if FPopupMenu <> AValue then
|
|
begin
|
|
if (FPopupMenu <> nil) and not (csDestroying in FPopupMenu.ComponentState) then
|
|
FPopupMenu.RemoveFreeNotification(SpellChecker);
|
|
FPopupMenu := AValue;
|
|
if FPopupMenu <> nil then
|
|
FPopupMenu.FreeNotification(SpellChecker);
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCheckAsYouTypeOptions.SetModifyControlPopupMenu(AValue: Boolean);
|
|
begin
|
|
if AValue <> FModifyControlPopupMenu then
|
|
begin
|
|
FModifyControlPopupMenu := AValue;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCheckAsYouTypeOptions.SetPopupMenuItems(AValue: TdxSpellCheckerPopupMenuItems);
|
|
begin
|
|
if AValue <> FPopupMenuItems then
|
|
begin
|
|
FPopupMenuItems := AValue;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCheckAsYouTypeOptions.SetSuggestionCount(AValue: Integer);
|
|
begin
|
|
if AValue <> FSuggestionCount then
|
|
begin
|
|
FSuggestionCount := AValue;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCheckAsYouTypeOptions.SetUnderlineColor(AValue: TColor);
|
|
begin
|
|
if FUnderlineColor <> AValue then
|
|
begin
|
|
FUnderlineColor := AValue;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxSpellCheckerCheckAsYouTypeOptions.SetUnderlineStyle(
|
|
AValue: TdxSpellCheckerUnderlineStyle);
|
|
begin
|
|
if FUnderlineStyle <> AValue then
|
|
begin
|
|
FUnderlineStyle := AValue;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
{ TdxCustomSpellChecker }
|
|
|
|
function IsContainer(AComponent: TComponent): Boolean;
|
|
begin
|
|
Result := (AComponent is TCustomForm) or (AComponent is TCustomFrame) or
|
|
(AComponent is TDataModule);
|
|
end;
|
|
|
|
function IsSpellCheckerAlreadyExists(AOwner: TComponent;
|
|
AInstance: TdxCustomSpellChecker): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := False;
|
|
for I := 0 to AOwner.ComponentCount - 1 do
|
|
if (AOwner.Components[I] <> AInstance) and (AOwner.Components[I] is TdxCustomSpellChecker) then
|
|
begin
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
end;
|
|
|
|
procedure SpellCheckerCreatingError;
|
|
begin
|
|
raise Exception.Create(cxGetResourceString(@sdxSpellCheckerMoreThanOne));
|
|
end;
|
|
|
|
constructor TdxCustomSpellChecker.Create(AOwner: TComponent);
|
|
var
|
|
I: Integer;
|
|
AComponent: TComponent;
|
|
begin
|
|
FCreating := True;
|
|
if IsContainer(AOwner) and IsSpellCheckerAlreadyExists(AOwner, Self) then
|
|
SpellCheckerCreatingError;
|
|
for I := 0 to Application.ComponentCount - 1 do
|
|
begin
|
|
AComponent := Application.Components[I];
|
|
if IsContainer(AComponent) and IsSpellCheckerAlreadyExists(AComponent, Self) then
|
|
SpellCheckerCreatingError;
|
|
end;
|
|
FCreating := False;
|
|
inherited Create(AOwner);
|
|
FAutoLoadDictionaries := False;
|
|
FSpellingFormType := sftOutlook;
|
|
FDictionaryItems := TdxSpellCheckerDictionaries.Create(Self);
|
|
FSimilarity := CreateSimilarity;
|
|
FRules := TdxSpellCheckerRules.Create;
|
|
FDialogLookAndFeel := TcxLookAndFeel.Create(nil);
|
|
FSpellingOptions := CreateSpellingOptions;
|
|
FCheckAsYouTypeOptions := TdxSpellCheckerCheckAsYouTypeOptions.Create(Self);
|
|
SpellingOptionsChanged;
|
|
FLanguages := TdxSpellCheckerLanguages.Create;
|
|
FChangeList := TdxSpellCheckerReplacementList.Create;
|
|
FDeleteList := TdxSpellCheckerWordList.Create(LANG_SYSTEM_DEFAULT, 257);
|
|
FIgnoreList := TdxSpellCheckerWordList.Create(LANG_SYSTEM_DEFAULT, 257);
|
|
end;
|
|
|
|
destructor TdxCustomSpellChecker.Destroy;
|
|
begin
|
|
if not FCreating then
|
|
begin
|
|
FreeAndNil(FChangeList);
|
|
FreeAndNil(FDeleteList);
|
|
FreeAndNil(FIgnoreList);
|
|
FCheckAsYouTypeOptions.Active := False;
|
|
UnloadDictionaries;
|
|
FreeAndNil(FLanguages);
|
|
FreeAndNil(FSpellingOptions);
|
|
FreeAndNil(FRules);
|
|
FreeAndNil(FSimilarity);
|
|
FreeAndNil(FCheckAsYouTypeOptions);
|
|
FreeAndNil(FDialogLookAndFeel);
|
|
FreeAndNil(FDictionaryItems);
|
|
end;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TdxCustomSpellChecker.Check(AEdit: TCustomEdit);
|
|
var
|
|
AEditAdapter: TdxSpellCheckerEditAdapter;
|
|
begin
|
|
AEditAdapter := TdxSpellCheckerEditAdapter.Create(AEdit);
|
|
try
|
|
InternalCheck(AEditAdapter);
|
|
finally
|
|
FreeAndNil(AEditAdapter);
|
|
end;
|
|
end;
|
|
|
|
procedure TdxCustomSpellChecker.Check(AEdit: TcxCustomTextEdit);
|
|
var
|
|
AEditAdapter: TdxSpellCheckercxTextEditAdapter;
|
|
begin
|
|
if AEdit is TcxCustomRichEdit then
|
|
AEditAdapter := TdxSpellCheckercxRichEditAdapter.Create(AEdit)
|
|
else
|
|
AEditAdapter := TdxSpellCheckercxTextEditAdapter.Create(AEdit);
|
|
try
|
|
InternalCheck(AEditAdapter);
|
|
finally
|
|
FreeAndNil(AEditAdapter);
|
|
end;
|
|
end;
|
|
|
|
procedure TdxCustomSpellChecker.CheckContainer(AContainer: TWinControl; ARecursive: Boolean);
|
|
begin
|
|
if AContainer = nil then Exit;
|
|
FCheckingContainer := True;
|
|
try
|
|
FCheckGroupMode := True;
|
|
FLastDialogResult := mrOk;
|
|
try
|
|
DoCheckContainer(AContainer, ARecursive);
|
|
finally
|
|
FCheckGroupMode := False;
|
|
end;
|
|
if FLastDialogResult <> mrCancel then
|
|
SpellingComplete;
|
|
finally
|
|
FCheckingContainer := False;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxCustomSpellChecker.AddToIgnoreList(const AWord: WideString);
|
|
begin
|
|
IgnoreList.Add(AWord);
|
|
if Assigned(CheckAsYouTypeManager) then
|
|
CheckAsYouTypeManager.Refresh;
|
|
end;
|
|
|
|
procedure TdxCustomSpellChecker.AddWordToUserDictionary(
|
|
const AWord: WideString);
|
|
var
|
|
AUserDictionary: TdxUserSpellCheckerDictionary;
|
|
begin
|
|
AUserDictionary := FindFirstEnabledUserDictionary;
|
|
if AUserDictionary <> nil then
|
|
begin
|
|
if not DoAddWord(AUserDictionary, AWord) then
|
|
AUserDictionary.AddWord(AWord);
|
|
end;
|
|
end;
|
|
|
|
function TdxCustomSpellChecker.FindDictionaryByWord(const AWord: WideString): TdxCustomSpellCheckerDictionary;
|
|
var
|
|
I: Integer;
|
|
ADictionary: TdxCustomSpellCheckerDictionary;
|
|
begin
|
|
Result := nil;
|
|
for I := 0 to ActiveDictionaryCount - 1 do
|
|
begin
|
|
ADictionary := ActiveDictionaries[I];
|
|
if ADictionary.HasWord(AWord) then
|
|
begin
|
|
Result := ADictionary;
|
|
Break;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TdxCustomSpellChecker.FindFirstEnabledUserDictionary: TdxUserSpellCheckerDictionary;
|
|
var
|
|
I: Integer;
|
|
ADictionary: TdxUserSpellCheckerDictionary;
|
|
begin
|
|
Result := nil;
|
|
for I := 0 to UserDictionaryCount - 1 do
|
|
begin
|
|
ADictionary := UserDictionaries[I];
|
|
if ADictionary.Enabled then
|
|
begin
|
|
Result := ADictionary;
|
|
Break;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TdxCustomSpellChecker.GetSuggestions(const AWord: WideString): TdxSpellCheckerSuggestionList;
|
|
var
|
|
I: Integer;
|
|
ADictionary: TdxCustomSpellCheckerDictionary;
|
|
begin
|
|
Result := TdxSpellCheckerSuggestionList.Create;
|
|
if not HasWordInDictionaries(AWord) then
|
|
begin
|
|
for I := 0 to ActiveDictionaryCount - 1 do
|
|
begin
|
|
ADictionary := ActiveDictionaries[I];
|
|
with ADictionary.CreateSuggestionBuilder do
|
|
try
|
|
AddSuggestions(AWord, Result);
|
|
finally
|
|
Free;
|
|
end;
|
|
end;
|
|
Result.RemoveDuplicates;
|
|
Result.FixCapitalization(AWord);
|
|
DoGetSuggestions(Result);
|
|
end;
|
|
end;
|
|
|
|
function TdxCustomSpellChecker.HasWordInDictionaries(const AWord: WideString): Boolean;
|
|
begin
|
|
Result := FindDictionaryByWord(AWord) <> nil;
|
|
end;
|
|
|
|
function TdxCustomSpellChecker.HasEnabledUserDictionary: Boolean;
|
|
begin
|
|
Result := FindFirstEnabledUserDictionary <> nil;
|
|
end;
|
|
|
|
function TdxCustomSpellChecker.IsValidWord(const AWord: WideString): Boolean;
|
|
begin
|
|
Result := False;
|
|
if not DoCheckWord(AWord, Result) then
|
|
Result := Rules.IsValid(AWord);
|
|
end;
|
|
|
|
procedure TdxCustomSpellChecker.PopulateLanguages(AList: TStrings);
|
|
var
|
|
I: Integer;
|
|
ADictionary: TdxCustomSpellCheckerDictionary;
|
|
ALanguageName: string;
|
|
ALangID: Cardinal;
|
|
begin
|
|
for I := 0 to DictionaryItems.Count - 1 do
|
|
begin
|
|
ADictionary := Dictionaries[I];
|
|
if ADictionary is TdxUserSpellCheckerDictionary then
|
|
Continue;
|
|
if ADictionary.Language <> 0 then
|
|
ALangID := ADictionary.Language
|
|
else
|
|
ALangID := Languages.GetDefaultLanguageLCID;
|
|
ALanguageName := Languages.NameFromLocaleID[ALangID];
|
|
if AList.IndexOf(ALanguageName) < 0 then
|
|
AList.AddObject(ALanguageName, Pointer(ALangID));
|
|
end;
|
|
end;
|
|
|
|
procedure TdxCustomSpellChecker.ShowSpellingCompleteMessage;
|
|
begin
|
|
ShowMessage(cxGetResourceString(@sdxSpellCheckerSpellingComplete));
|
|
end;
|
|
|
|
procedure TdxCustomSpellChecker.LoadDictionaries(AIgnoreDisabled: Boolean = True);
|
|
begin
|
|
if UseThreadedLoad then
|
|
LoadDictionariesUsingThread(AIgnoreDisabled)
|
|
else
|
|
LoadDictionariesDirect(AIgnoreDisabled);
|
|
end;
|
|
|
|
procedure TdxCustomSpellChecker.UnloadDictionaries;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
ShowHourglassCursor;
|
|
try
|
|
for I := 0 to DictionaryCount - 1 do
|
|
Dictionaries[I].Unload;
|
|
finally
|
|
HideHourglassCursor;
|
|
end;
|
|
end;
|
|
|
|
function TdxCustomSpellChecker.GetTwoWordsDistance(
|
|
const AWord1, AWord2: WideString): Integer;
|
|
begin
|
|
Result := FSimilarity.GetDistance(AWord1, AWord2);
|
|
end;
|
|
|
|
procedure TdxCustomSpellChecker.CheckCallEnabledDictionariesLoaded;
|
|
begin
|
|
if Assigned(CheckAsYouTypeManager) then
|
|
CheckAsYouTypeManager.Refresh(True);
|
|
if ActiveDictionaryCount = EnabledDictionaryCount then
|
|
DoEnabledDictionariesLoaded;
|
|
end;
|
|
|
|
function TdxCustomSpellChecker.CreateSimilarity: TdxStringSimilarityCalculator;
|
|
begin
|
|
Result := TdxStringSimilarityCalculator.Create;
|
|
end;
|
|
|
|
function TdxCustomSpellChecker.CreateSpellingOptions: TdxSpellCheckerSpellingOptions;
|
|
begin
|
|
Result := TdxSpellCheckerSpellingOptions.Create(Self);
|
|
end;
|
|
|
|
procedure TdxCustomSpellChecker.BeginManualCheck;
|
|
begin
|
|
if Assigned(CheckAsYouTypeManager) then
|
|
CheckAsYouTypeManager.BeginManualCheck;
|
|
end;
|
|
|
|
procedure TdxCustomSpellChecker.EndManualCheck;
|
|
begin
|
|
if Assigned(CheckAsYouTypeManager) then
|
|
CheckAsYouTypeManager.EndManualCheck;
|
|
end;
|
|
|
|
function TdxCustomSpellChecker.DoAddWord(AUserDictionary: TdxUserSpellCheckerDictionary;
|
|
const AWord: WideString): Boolean;
|
|
begin
|
|
Result := False;
|
|
if Assigned(FOnAddWord) then
|
|
FOnAddWord(AUserDictionary, AWord, Result);
|
|
end;
|
|
|
|
procedure TdxCustomSpellChecker.DoAfterCheck;
|
|
begin
|
|
if Assigned(FOnAfterCheck) then
|
|
FOnAfterCheck(Self);
|
|
end;
|
|
|
|
procedure TdxCustomSpellChecker.DoBeforeCheck;
|
|
begin
|
|
if Assigned(FOnBeforeCheck) then
|
|
FOnBeforeCheck(Self);
|
|
end;
|
|
|
|
procedure TdxCustomSpellChecker.DoCheck(ADialogCheckMode: TdxSpellCheckerDialogCheckMode);
|
|
begin
|
|
if ActiveDictionaryCount = 0 then
|
|
raise EdxSpellCheckerException.Create(cxGetResourceString(@sdxSpellCheckerNoActiveDictionaries));
|
|
DoBeforeCheck;
|
|
try
|
|
ValidateRules(ADialogCheckMode.Parser);
|
|
if not ADialogCheckMode.GetNextMisspelledWord then
|
|
begin
|
|
SpellingComplete;
|
|
FLastDialogResult := mrOk;
|
|
end
|
|
else
|
|
begin
|
|
FLastDialogResult := ADialogCheckMode.ShowDialog;
|
|
if FLastDialogResult = mrOk then
|
|
SpellingComplete;
|
|
end;
|
|
finally
|
|
DoAfterCheck;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxCustomSpellChecker.DoCheckAsYouTypeFinish(AControl: TWinControl);
|
|
begin
|
|
if Assigned(OnCheckAsYouTypeFinish) then
|
|
OnCheckAsYouTypeFinish(Self, AControl);
|
|
end;
|
|
|
|
function TdxCustomSpellChecker.DoCheckAsYouTypePopup(APopup: TComponent): Boolean;
|
|
begin
|
|
Result := False;
|
|
if Assigned(FOnCheckAsYouTypePopup) then
|
|
FOnCheckAsYouTypePopup(Self, APopup, Result);
|
|
end;
|
|
|
|
function TdxCustomSpellChecker.DoCheckAsYouTypeStart(AControl: TWinControl): Boolean;
|
|
begin
|
|
Result := Assigned(AControl);
|
|
if Result and Assigned(OnCheckAsYouTypeStart) then
|
|
OnCheckAsYouTypeStart(Self, AControl, Result);
|
|
end;
|
|
|
|
procedure TdxCustomSpellChecker.DoCheckContainer(AContainer: TWinControl;
|
|
ARecursive: Boolean);
|
|
|
|
function StopCheck(AContinue: Boolean): Boolean;
|
|
begin
|
|
Result := not AContinue or (FLastDialogResult <> mrOk);
|
|
if Result then
|
|
FLastDialogResult := mrCancel;
|
|
end;
|
|
|
|
var
|
|
I: Integer;
|
|
AControl: TWinControl;
|
|
AContinue: Boolean;
|
|
L: TList;
|
|
begin
|
|
L := TList.Create;
|
|
try
|
|
AContainer.GetTabOrderList(L);
|
|
for I := 0 to L.Count - 1 do
|
|
begin
|
|
AControl := TWinControl(L[I]);
|
|
if not AControl.CanFocus or (not ARecursive and (AControl.Parent <> AContainer)) then
|
|
Continue;
|
|
AContinue := True;
|
|
if (AControl is TcxCustomTextEdit) then
|
|
begin
|
|
if DoCheckControlInContainer(AControl, AContinue) then
|
|
Check(TcxCustomTextEdit(AControl));
|
|
if StopCheck(AContinue) then
|
|
Break;
|
|
end
|
|
else
|
|
if (AControl is TCustomEdit) then
|
|
begin
|
|
if DoCheckControlInContainer(GetInnerControlContainer(AControl), AContinue) then
|
|
Check(TCustomEdit(AControl));
|
|
if StopCheck(AContinue) then
|
|
Break;
|
|
end;
|
|
end;
|
|
finally
|
|
L.Free;
|
|
end;
|
|
end;
|
|
|
|
function TdxCustomSpellChecker.DoCheckControlInContainer(AControl: TWinControl;
|
|
var AContinue: Boolean): Boolean;
|
|
begin
|
|
Result := True;
|
|
if Assigned(FOnCheckControlInContainer) then
|
|
FOnCheckControlInContainer(Self, AControl, Result, AContinue);
|
|
end;
|
|
|
|
function TdxCustomSpellChecker.DoCheckWord(const AWord: WideString; var AValid: Boolean): Boolean;
|
|
begin
|
|
Result := False;
|
|
if Assigned(FOnCheckWord) then
|
|
FOnCheckWord(Self, AWord, AValid, Result);
|
|
end;
|
|
|
|
procedure TdxCustomSpellChecker.DoEnabledDictionariesLoaded;
|
|
begin
|
|
if Assigned(FOnEnabledDictionariesLoaded) then
|
|
FOnEnabledDictionariesLoaded(Self);
|
|
end;
|
|
|
|
procedure TdxCustomSpellChecker.DoGetSuggestions(ASuggestions: TdxSpellCheckerSuggestionList);
|
|
begin
|
|
if Assigned(FOnGetSuggestions) then
|
|
FOnGetSuggestions(Self, ASuggestions);
|
|
end;
|
|
|
|
function TdxCustomSpellChecker.DoSpellingComplete: Boolean;
|
|
begin
|
|
Result := False;
|
|
if Assigned(FOnSpellingComplete) then
|
|
FOnSpellingComplete(Self, Result);
|
|
end;
|
|
|
|
function TdxCustomSpellChecker.GetDialogCheckModeClass: TdxSpellCheckerCustomCheckModeClass;
|
|
begin
|
|
if sftWord = SpellingFormType then
|
|
Result := TdxSpellCheckerWordCheckMode
|
|
else
|
|
Result := TdxSpellCheckerOutlookCheckMode;
|
|
end;
|
|
|
|
procedure TdxCustomSpellChecker.InternalCheck(AAdapter: TdxSpellCheckerCustomEditAdapter);
|
|
begin
|
|
if ActiveDictionaryCount = 0 then
|
|
Exit;
|
|
BeginManualCheck;
|
|
try
|
|
FCheckMode := GetDialogCheckModeClass.Create(Self, AAdapter);
|
|
try
|
|
DoCheck(FCheckMode as TdxSpellCheckerDialogCheckMode);
|
|
finally
|
|
FreeAndNil(FCheckMode);
|
|
end;
|
|
finally
|
|
EndManualCheck;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxCustomSpellChecker.LoadDictionariesDirect(
|
|
AIgnoreDisabled: Boolean = True);
|
|
var
|
|
I: Integer;
|
|
ADictionary: TdxCustomSpellCheckerDictionary;
|
|
begin
|
|
ShowHourglassCursor;
|
|
try
|
|
for I := 0 to DictionaryCount - 1 do
|
|
begin
|
|
ADictionary := Dictionaries[I];
|
|
if ADictionary.Enabled or not AIgnoreDisabled then
|
|
ADictionary.Load;
|
|
end;
|
|
finally
|
|
HideHourglassCursor;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxCustomSpellChecker.LoadDictionariesUsingThread(
|
|
AIgnoreDisabled: Boolean = True);
|
|
var
|
|
I: Integer;
|
|
ADictionary: TdxCustomSpellCheckerDictionary;
|
|
begin
|
|
for I := 0 to DictionaryCount - 1 do
|
|
begin
|
|
ADictionary := Dictionaries[I];
|
|
if ADictionary.Enabled or not AIgnoreDisabled then
|
|
ADictionary.LoadUsingThread;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxCustomSpellChecker.Loaded;
|
|
begin
|
|
inherited Loaded;
|
|
if AutoLoadDictionaries and not (csDesigning in ComponentState) then
|
|
LoadDictionaries;
|
|
end;
|
|
|
|
procedure TdxCustomSpellChecker.Notification(AComponent: TComponent; Operation: TOperation);
|
|
begin
|
|
inherited Notification(AComponent, Operation);
|
|
if CheckAsYouTypeOptions <> nil then
|
|
CheckAsYouTypeOptions.Notification(AComponent, Operation);
|
|
end;
|
|
|
|
procedure TdxCustomSpellChecker.SpellingOptionsChanged;
|
|
begin
|
|
if Assigned(CheckMode) then
|
|
ValidateRules(CheckMode.Parser);
|
|
if Assigned(CheckAsYouTypeManager) then
|
|
CheckAsYouTypeManager.SpellingOptionsChanged;
|
|
end;
|
|
|
|
procedure TdxCustomSpellChecker.ValidateRules(AParser: TdxSpellCheckerTextParser);
|
|
begin
|
|
Rules.Clear;
|
|
if Assigned(AParser) then
|
|
begin
|
|
SpellingOptions.PopulateRules(Rules, AParser);
|
|
Rules.Add(TdxSpellCheckerWordExistsRule.Create(AParser));
|
|
end;
|
|
end;
|
|
|
|
procedure TdxCustomSpellChecker.UpdateByDictionary(
|
|
ADictionary: TdxCustomSpellCheckerDictionary);
|
|
begin
|
|
if Assigned(CheckMode) then
|
|
CheckMode.UpdateByDictionary(ADictionary);
|
|
if Assigned(CheckAsYouTypeManager) then
|
|
CheckAsYouTypeManager.Reset;
|
|
end;
|
|
|
|
procedure TdxCustomSpellChecker.UpdateCheckAsYouTypeManagerState;
|
|
begin
|
|
FreeAndNil(FCheckAsYouTypeManager);
|
|
if CheckAsYouTypeOptions.Active then
|
|
begin
|
|
FCheckAsYouTypeManager := TdxSpellCheckerCheckAsYouTypeManager.Create(Self);
|
|
FCheckAsYouTypeManager.DoOptionsChanged;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxCustomSpellChecker.SpellingComplete;
|
|
begin
|
|
if not FCheckGroupMode and not DoSpellingComplete then
|
|
ShowSpellingCompleteMessage;
|
|
end;
|
|
|
|
function TdxCustomSpellChecker.GetActiveDictionary(
|
|
Index: Integer): TdxCustomSpellCheckerDictionary;
|
|
var
|
|
I, J: Integer;
|
|
ADictionary: TdxCustomSpellCheckerDictionary;
|
|
begin
|
|
Result := nil;
|
|
J := 0;
|
|
for I := 0 to DictionaryItems.Count - 1 do
|
|
begin
|
|
ADictionary := DictionaryItems[I].DictionaryType;
|
|
if (ADictionary <> nil) and (ADictionary.Active) then
|
|
begin
|
|
if J = Index then
|
|
begin
|
|
Result := ADictionary;
|
|
Exit;
|
|
end;
|
|
Inc(J);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TdxCustomSpellChecker.GetActiveDictionaryCount: Integer;
|
|
var
|
|
I: Integer;
|
|
ADictionary: TdxCustomSpellCheckerDictionary;
|
|
begin
|
|
Result := 0;
|
|
for I := 0 to DictionaryItems.Count - 1 do
|
|
begin
|
|
ADictionary := DictionaryItems[I].DictionaryType;
|
|
if (ADictionary <> nil) and (ADictionary.Active) then
|
|
Inc(Result);
|
|
end;
|
|
end;
|
|
|
|
function TdxCustomSpellChecker.GetCheckMode: TdxSpellCheckerCustomCheckMode;
|
|
begin
|
|
Result := FCheckMode;
|
|
if (Result = nil) and Assigned(CheckAsYouTypeManager) then
|
|
Result := CheckAsYouTypeManager.GetCheckMode;
|
|
end;
|
|
|
|
function TdxCustomSpellChecker.GetDictionary(
|
|
Index: Integer): TdxCustomSpellCheckerDictionary;
|
|
var
|
|
I, J: Integer;
|
|
ADictionary: TdxCustomSpellCheckerDictionary;
|
|
begin
|
|
Result := nil;
|
|
J := 0;
|
|
for I := 0 to DictionaryItems.Count - 1 do
|
|
begin
|
|
ADictionary := DictionaryItems[I].DictionaryType;
|
|
if ADictionary <> nil then
|
|
begin
|
|
if J = Index then
|
|
begin
|
|
Result := ADictionary;
|
|
Exit;
|
|
end;
|
|
Inc(J);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TdxCustomSpellChecker.GetDictionaryCount: Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := 0;
|
|
for I := 0 to DictionaryItems.Count - 1 do
|
|
if DictionaryItems[I].DictionaryType <> nil then
|
|
Inc(Result);
|
|
end;
|
|
|
|
function TdxCustomSpellChecker.GetEnabledDictionary(
|
|
Index: Integer): TdxCustomSpellCheckerDictionary;
|
|
var
|
|
I, J: Integer;
|
|
ADictionary: TdxCustomSpellCheckerDictionary;
|
|
begin
|
|
Result := nil;
|
|
J := 0;
|
|
for I := 0 to DictionaryItems.Count - 1 do
|
|
begin
|
|
ADictionary := DictionaryItems[I].DictionaryType;
|
|
if (ADictionary <> nil) and (ADictionary.Enabled) then
|
|
begin
|
|
if J = Index then
|
|
begin
|
|
Result := DictionaryItems[I].DictionaryType;
|
|
Exit;
|
|
end;
|
|
Inc(J);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TdxCustomSpellChecker.GetEnabledDictionaryCount: Integer;
|
|
var
|
|
I: Integer;
|
|
ADictionary: TdxCustomSpellCheckerDictionary;
|
|
begin
|
|
Result := 0;
|
|
for I := 0 to DictionaryItems.Count - 1 do
|
|
begin
|
|
ADictionary := DictionaryItems[I].DictionaryType;
|
|
if (ADictionary <> nil) and (ADictionary.Enabled) then
|
|
Inc(Result);
|
|
end;
|
|
end;
|
|
|
|
function TdxCustomSpellChecker.GetUserDictionary(
|
|
Index: Integer): TdxUserSpellCheckerDictionary;
|
|
var
|
|
I, J: Integer;
|
|
begin
|
|
Result := nil;
|
|
J := 0;
|
|
for I := 0 to DictionaryItems.Count - 1 do
|
|
begin
|
|
if DictionaryItems[I].DictionaryType is TdxUserSpellCheckerDictionary then
|
|
begin
|
|
if J = Index then
|
|
begin
|
|
Result := TdxUserSpellCheckerDictionary(DictionaryItems[I].DictionaryType);
|
|
Exit;
|
|
end;
|
|
Inc(J);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TdxCustomSpellChecker.GetUserDictionaryCount: Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := 0;
|
|
for I := 0 to DictionaryItems.Count - 1 do
|
|
if DictionaryItems[I].DictionaryType is TdxUserSpellCheckerDictionary then
|
|
Inc(Result);
|
|
end;
|
|
|
|
procedure TdxCustomSpellChecker.SetCheckAsYouTypeOptions(
|
|
AValue: TdxSpellCheckerCheckAsYouTypeOptions);
|
|
begin
|
|
FCheckAsYouTypeOptions.Assign(AValue);
|
|
end;
|
|
|
|
procedure TdxCustomSpellChecker.SetDialogLookAndFeel(AValue: TcxLookAndFeel);
|
|
begin
|
|
FDialogLookAndFeel.Assign(AValue);
|
|
end;
|
|
|
|
procedure TdxCustomSpellChecker.SetDictionaryItems(
|
|
AValue: TdxSpellCheckerDictionaries);
|
|
begin
|
|
FDictionaryItems.Assign(AValue);
|
|
end;
|
|
|
|
procedure TdxCustomSpellChecker.SetSpellingOptions(
|
|
AValue: TdxSpellCheckerSpellingOptions);
|
|
begin
|
|
FSpellingOptions.Assign(AValue);
|
|
end;
|
|
|
|
initialization
|
|
GetRegisteredDictionaryTypes.Register(
|
|
TdxUserSpellCheckerDictionary, cxGetResourceString(@sdxSpellCheckerUserDictionary));
|
|
|
|
finalization
|
|
FreeRegisteredDictionaryTypes;
|
|
|
|
end.
|