mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-12 13:49:39 +02:00
* update spellcheck unit with new stuff
git-svn-id: trunk@10274 -
This commit is contained in:
parent
915b1bddb3
commit
acc4d25f75
@ -8,34 +8,84 @@ unit SpellCheck;
|
|||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
SysUtils, Aspell;
|
SysUtils, Classes, Aspell;
|
||||||
|
|
||||||
type
|
type
|
||||||
TSuggestionArray = array of string;
|
TSuggestionArray = array of string;
|
||||||
|
|
||||||
{ TSpellCheck }
|
TWordError = record
|
||||||
|
Word: string; // the word itself
|
||||||
|
Pos: LongWord; // word position in line
|
||||||
|
Length: LongWord; // word length
|
||||||
|
Suggestions: TSuggestionArray; // suggestions for the given word
|
||||||
|
end;
|
||||||
|
|
||||||
|
TLineErrors = array of TWordError;
|
||||||
|
TLineErrorsArray = array of TLineErrors;
|
||||||
|
|
||||||
TSpellCheck = class
|
{ TSpeller }
|
||||||
|
{ Abstract ancestor, don't use directly }
|
||||||
|
|
||||||
|
TSpeller = class // abstract class, basis for all checkers
|
||||||
protected
|
protected
|
||||||
FSpeller: PAspellSpeller;
|
|
||||||
FMode: string;
|
FMode: string;
|
||||||
FEncoding: string;
|
FEncoding: string;
|
||||||
FLanguage: string;
|
FLanguage: string;
|
||||||
procedure SetEncoding(const AValue: string);
|
procedure SetEncoding(const AValue: string);
|
||||||
procedure SetLanguage(const AValue: string);
|
procedure SetLanguage(const AValue: string);
|
||||||
procedure SetMode(const AValue: string);
|
procedure SetMode(const AValue: string);
|
||||||
procedure CreateSpeller;
|
procedure CreateSpeller; virtual; abstract;
|
||||||
procedure FreeSpeller;
|
procedure FreeSpeller; virtual; abstract;
|
||||||
public
|
public
|
||||||
constructor Create;
|
constructor Create;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
function SpellCheck(const Word: string): TSuggestionArray;
|
|
||||||
public
|
public
|
||||||
property Mode: string read FMode write SetMode;
|
property Mode: string read FMode write SetMode;
|
||||||
property Encoding: string read FEncoding write SetEncoding;
|
property Encoding: string read FEncoding write SetEncoding;
|
||||||
property Language: string read FLanguage write SetLanguage;
|
property Language: string read FLanguage write SetLanguage;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TWordSpeller }
|
||||||
|
{ Basic spelling class for spelling single words without context }
|
||||||
|
|
||||||
|
TWordSpeller = class(TSpeller) // class for simple per-word checking
|
||||||
|
private
|
||||||
|
FSpeller: PAspellSpeller;
|
||||||
|
protected
|
||||||
|
procedure CreateSpeller; override;
|
||||||
|
procedure FreeSpeller; override;
|
||||||
|
public
|
||||||
|
function SpellCheck(const Word: string): TSuggestionArray; // use to check single words, parsed out by you
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TDocumentSpeller }
|
||||||
|
{ This speller is used to spellcheck lines or even whole documents.
|
||||||
|
It is usefull when different mode (like "tex") is used so you can pass
|
||||||
|
everything to aspell and let it take care of the context }
|
||||||
|
|
||||||
|
TDocumentSpeller = class(TWordSpeller)
|
||||||
|
private
|
||||||
|
FChecker: PAspellDocumentChecker;
|
||||||
|
FLineErrors: TLineErrorsArray;
|
||||||
|
FNameSuggestions: Boolean;
|
||||||
|
function GetLineErrors(i: Integer): TLineErrors;
|
||||||
|
function GetLineErrorsCount: Integer;
|
||||||
|
protected
|
||||||
|
procedure CreateSpeller; override;
|
||||||
|
procedure FreeSpeller; override;
|
||||||
|
procedure DoNameSuggestions(const Word: string; var aWordError: TWordError);
|
||||||
|
public
|
||||||
|
constructor Create;
|
||||||
|
function CheckLine(const aLine: string): TLineErrors;
|
||||||
|
function CheckDocument(const FileName: string): Integer; // returns number of spelling errors found or -1 for error
|
||||||
|
function CheckDocument(aStringList: TStringList): Integer; // returns number of spelling errors found or -1 for error
|
||||||
|
procedure Reset;
|
||||||
|
public
|
||||||
|
property LineErrors[i: Integer]: TLineErrors read GetLineErrors;
|
||||||
|
property LineErrorsCount: Integer read GetLineErrorsCount;
|
||||||
|
property NameSuggestions: Boolean read FNameSuggestions write FNameSuggestions;
|
||||||
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
const
|
const
|
||||||
@ -50,27 +100,43 @@ begin
|
|||||||
Result := DEFAULT_LANGUAGE;
|
Result := DEFAULT_LANGUAGE;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TSpellCheck }
|
{ TSpeller }
|
||||||
|
|
||||||
procedure TSpellCheck.SetEncoding(const AValue: string);
|
procedure TSpeller.SetEncoding(const AValue: string);
|
||||||
begin
|
begin
|
||||||
FEncoding := aValue;
|
FEncoding := aValue;
|
||||||
CreateSpeller;
|
CreateSpeller;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TSpellCheck.SetLanguage(const AValue: string);
|
procedure TSpeller.SetLanguage(const AValue: string);
|
||||||
begin
|
begin
|
||||||
FLanguage := aValue;
|
FLanguage := aValue;
|
||||||
CreateSpeller;
|
CreateSpeller;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TSpellCheck.SetMode(const AValue: string);
|
procedure TSpeller.SetMode(const AValue: string);
|
||||||
begin
|
begin
|
||||||
FMode := aValue;
|
FMode := aValue;
|
||||||
CreateSpeller;
|
CreateSpeller;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TSpellCheck.CreateSpeller;
|
constructor TSpeller.Create;
|
||||||
|
begin
|
||||||
|
FEncoding := DEFAULT_ENCODING;
|
||||||
|
FLanguage := GetDefaultLanguage;
|
||||||
|
FMode := DEFAULT_MODE;
|
||||||
|
|
||||||
|
CreateSpeller;
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TSpeller.Destroy;
|
||||||
|
begin
|
||||||
|
FreeSpeller;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TWordSpeller }
|
||||||
|
|
||||||
|
procedure TWordSpeller.CreateSpeller;
|
||||||
var
|
var
|
||||||
Config: Paspellconfig;
|
Config: Paspellconfig;
|
||||||
Error: Paspellcanhaveerror;
|
Error: Paspellcanhaveerror;
|
||||||
@ -95,7 +161,7 @@ begin
|
|||||||
FSpeller := to_aspell_speller(Error);
|
FSpeller := to_aspell_speller(Error);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TSpellCheck.FreeSpeller;
|
procedure TWordSpeller.FreeSpeller;
|
||||||
begin
|
begin
|
||||||
if Assigned(FSpeller) then begin
|
if Assigned(FSpeller) then begin
|
||||||
delete_aspell_speller(FSpeller);
|
delete_aspell_speller(FSpeller);
|
||||||
@ -103,21 +169,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
constructor TSpellCheck.Create;
|
function TWordSpeller.SpellCheck(const Word: string): TSuggestionArray;
|
||||||
begin
|
|
||||||
FEncoding := DEFAULT_ENCODING;
|
|
||||||
FLanguage := GetDefaultLanguage;
|
|
||||||
FMode := DEFAULT_MODE;
|
|
||||||
|
|
||||||
CreateSpeller;
|
|
||||||
end;
|
|
||||||
|
|
||||||
destructor TSpellCheck.Destroy;
|
|
||||||
begin
|
|
||||||
FreeSpeller;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TSpellCheck.SpellCheck(const Word: string): TSuggestionArray;
|
|
||||||
var
|
var
|
||||||
sgs: Paspellwordlist;
|
sgs: Paspellwordlist;
|
||||||
elm: Paspellstringenumeration;
|
elm: Paspellstringenumeration;
|
||||||
@ -148,5 +200,121 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TDocumentSpeller }
|
||||||
|
|
||||||
|
function TDocumentSpeller.GetLineErrors(i: Integer): TLineErrors;
|
||||||
|
begin
|
||||||
|
Result := FLineErrors[i];
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TDocumentSpeller.GetLineErrorsCount: Integer;
|
||||||
|
begin
|
||||||
|
Result := Length(FLineErrors);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TDocumentSpeller.CreateSpeller;
|
||||||
|
var
|
||||||
|
Error: PAspellCanHaveError;
|
||||||
|
begin
|
||||||
|
inherited CreateSpeller;
|
||||||
|
|
||||||
|
Error := new_aspell_document_checker(FSpeller);
|
||||||
|
|
||||||
|
if aspell_error_number(Error) <> 0 then
|
||||||
|
raise Exception.Create('Error on checker creation: ' + aspell_error_message(Error))
|
||||||
|
else
|
||||||
|
FChecker := to_aspell_document_checker(Error);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TDocumentSpeller.FreeSpeller;
|
||||||
|
begin
|
||||||
|
if Assigned(FChecker) then begin
|
||||||
|
delete_aspell_document_checker(FChecker);
|
||||||
|
FChecker := nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
inherited FreeSpeller;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TDocumentSpeller.DoNameSuggestions(const Word: string;
|
||||||
|
var aWordError: TWordError);
|
||||||
|
begin
|
||||||
|
aWordError.Suggestions := SpellCheck(Word);
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TDocumentSpeller.Create;
|
||||||
|
begin
|
||||||
|
inherited Create;
|
||||||
|
|
||||||
|
FNameSuggestions := True;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TDocumentSpeller.CheckLine(const aLine: string): TLineErrors;
|
||||||
|
const
|
||||||
|
CHUNK_SIZE = 10;
|
||||||
|
var
|
||||||
|
i, Count: Integer;
|
||||||
|
Token: AspellToken;
|
||||||
|
begin
|
||||||
|
aspell_document_checker_process(FChecker, pChar(aLine), Length(aLine));
|
||||||
|
|
||||||
|
SetLength(Result, CHUNK_SIZE);
|
||||||
|
i := 0;
|
||||||
|
Count := 0;
|
||||||
|
repeat
|
||||||
|
Token := aspell_document_checker_next_misspelling(FChecker);
|
||||||
|
|
||||||
|
if Token.len > 0 then begin
|
||||||
|
if Length(Result) <= i then
|
||||||
|
SetLength(Result, Length(Result) + CHUNK_SIZE);
|
||||||
|
|
||||||
|
Result[i].Word := Copy(aLine, Token.offset + 1, Token.len);
|
||||||
|
Result[i].Pos := Token.offset + 1; // C goes from 0, we go from 1
|
||||||
|
Result[i].Length := Token.len;
|
||||||
|
|
||||||
|
if FNameSuggestions then
|
||||||
|
DoNameSuggestions(Copy(aLine, Token.offset + 1, Token.len), Result[i]);
|
||||||
|
|
||||||
|
Inc(Count);
|
||||||
|
end;
|
||||||
|
|
||||||
|
Inc(i);
|
||||||
|
until Token.len = 0;
|
||||||
|
|
||||||
|
SetLength(Result, Count);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TDocumentSpeller.CheckDocument(const FileName: string): Integer;
|
||||||
|
var
|
||||||
|
s: TStringList;
|
||||||
|
begin
|
||||||
|
Result := 0;
|
||||||
|
if FileExists(FileName) then try
|
||||||
|
s := TStringList.Create;
|
||||||
|
s.LoadFromFile(FileName);
|
||||||
|
Result := CheckDocument(s);
|
||||||
|
finally
|
||||||
|
s.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TDocumentSpeller.CheckDocument(aStringList: TStringList): Integer;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
Result := 0;
|
||||||
|
SetLength(FLineErrors, aStringList.Count);
|
||||||
|
|
||||||
|
for i := 0 to aStringList.Count - 1 do begin
|
||||||
|
FLineErrors[i] := CheckLine(aStringList[i]);
|
||||||
|
Inc(Result, Length(FLineErrors[i]));
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TDocumentSpeller.Reset;
|
||||||
|
begin
|
||||||
|
aspell_document_checker_reset(FChecker);
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user