Files
lazarus-ccr/components/jvcllaz/run/JvCmp/jvspellerform.pas

412 lines
9.8 KiB
ObjectPascal
Raw Permalink Normal View History

{-----------------------------------------------------------------------------
The contents of this file are subject to the Mozilla Public License
Version 1.1 (the "License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/MPL-1.1.html
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
the specific language governing rights and limitations under the License.
The Original Code is: JvSpellerForm.PAS, released on 2002-06-15.
The Initial Developer of the Original Code is Jan Verhoeven [jan1 dott verhoeven att wxs dott nl]
Portions created by Jan Verhoeven are Copyright (C) 2002 Jan Verhoeven.
All Rights Reserved.
Contributor(s): Robert Love [rlove att slcdug dott org].
You may retrieve the latest version of this file at the Project JEDI's JVCL home page,
located at http://jvcl.delphi-jedi.org
Known Issues:
-----------------------------------------------------------------------------}
// $Id$
unit JvSpellerForm;
{$mode objfpc}{$H+}
interface
uses
SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls;
type
TJvSpeller = class;
TJvSpellerForm = class(TForm) //TJvForm)
TextPanel: TPanel;
LblContext: TLabel;
TxtSpell: TEdit;
ButtonPanel: TPanel;
BtnSkip: TButton;
BtnChange: TButton;
BtnCancel: TButton;
BtnAdd: TButton;
BtnSkipAll: TButton;
private
FSpeller: TJvSpeller;
end;
TJvDicIndexArray = array [1..26] of Integer;
TJvSpeller = class(TComponent)
private
FSourceText: string;
FDict: string;
FUserDic: string;
FUserDicChanged: Boolean;
FDicIndex: TJvDicIndexArray;
FUserDicIndex: TJvDicIndexArray;
FSpellerDialog: TJvSpellerForm;
FWordBegin: Integer;
FWordEnd: Integer;
FDictionary: TFileName;
FUserDictionary: TFileName;
function WordBegin: Boolean;
function WordEnd: Boolean;
function ParseWord: string;
procedure SpellNext;
procedure Skip(Sender: TObject);
procedure Add(Sender: TObject);
procedure Change(Sender: TObject);
procedure IndexDictionary;
procedure IndexUserDictionary;
procedure SetDictionary(const Value: TFileName);
procedure SetUserDictionary(const Value: TFileName);
procedure CreateSpellerDialog(const SpellWord: string);
public
constructor Create(AOwner: TComponent); override;
procedure LoadDictionary(const AFile: string);
procedure LoadUserDictionary(const AFile: string);
procedure Spell(var SourceText: string);
published
property Dictionary: TFileName read FDictionary write SetDictionary;
property UserDictionary: TFileName read FUserDictionary write SetUserDictionary;
end;
implementation
uses
StrUtils,
JvConsts, JvResources, JvTypes;
{$R *.lfm}
procedure SaveAnsiFileFromString(const AFile, AText: string);
var
AnsiText: AnsiString;
begin
AnsiText := AnsiString(AText);
with TFileStream.Create(AFile, fmCreate) do
try
WriteBuffer(AnsiText[1], Length(AnsiText));
finally
Free;
end;
end;
function LoadAnsiFileToString(const AFile: string): string;
var
AnsiText: AnsiString = '';
begin
with TFileStream.Create(AFile, fmOpenRead) do
try
SetLength(AnsiText, Size);
if AnsiText <> '' then
ReadBuffer(AnsiText[1], Size);
finally
Free;
end;
Result := string(AnsiText);
end;
//=== { TJvSpeller } =========================================================
constructor TJvSpeller.Create(AOwner: TComponent);
var
I: Integer;
begin
inherited Create(AOwner);
for I := 1 to 26 do
begin
FDicIndex[I] := 1;
FUserDicIndex[I] := 1;
end;
end;
procedure TJvSpeller.Add(Sender: TObject);
var
S: string;
begin
S := FSpellerDialog.TxtSpell.Text;
if S = '' then
Exit;
FUserDic := FUserDic + LowerCase(S) + Cr;
FUserDicChanged := True;
with TStringList.Create do
try
Text := FUserDic;
Sort;
FUserDic := Text;
finally
Free;
end;
IndexUserDictionary;
Skip(Sender);
end;
procedure TJvSpeller.Change(Sender: TObject);
var
S: string;
begin
S := FSpellerDialog.TxtSpell.Text;
if S <> '' then
begin
FSourceText := Copy(FSourceText, 1, FWordBegin - 1) + S +
Copy(FSourceText, FWordEnd, Length(FSourceText));
FWordEnd := FWordEnd + (Length(S) - (FWordEnd - FWordBegin));
Skip(Sender);
end;
end;
procedure TJvSpeller.IndexDictionary;
var
I, P, StartPos: Integer;
begin
FDicIndex[1] := 1;
for I := 2 to 26 do
begin
if FDicIndex[I - 1] <> 1 then
StartPos := FDicIndex[I - 1]
else
StartPos := 1;
P := PosEx(Cr + Chr(96 + I), FDict, StartPos);
if P <> 0 then
FDicIndex[I] := P
else
FDicIndex[I] := FDicIndex[I - 1];
end;
end;
procedure TJvSpeller.IndexUserDictionary;
var
I, P, StartPos: Integer;
begin
FUserDicIndex[1] := 1;
for I := 2 to 26 do
begin
if FUserDicIndex[I - 1] <> 1 then
StartPos := FUserDicIndex[I - 1]
else
StartPos := 1;
P := PosEx(Cr + Chr(96 + I), FUserDic, StartPos);
if P <> 0 then
FUserDicIndex[I] := P
else
FUserDicIndex[I] := FUserDicIndex[I - 1];
end;
end;
procedure TJvSpeller.LoadDictionary(const AFile: string);
begin
if FileExists(AFile) then
FDict := LoadAnsiFileToString(AFile)
else
FDict := '';
IndexDictionary;
end;
procedure TJvSpeller.LoadUserDictionary(const AFile: string);
begin
UserDictionary := AFile;
FUserDicChanged := False;
if FileExists(AFile) then
FUserDic := LoadAnsiFileToString(AFile)
else
FUserDic := '';
IndexUserDictionary;
end;
function TJvSpeller.ParseWord: string;
begin
if WordBegin and WordEnd then
Result := Copy(FSourceText, FWordBegin, FWordEnd - FWordBegin)
else
Result := '';
end;
procedure TJvSpeller.SetDictionary(const Value: TFileName);
begin
if FDictionary <> Value then
begin
FDictionary := Value;
LoadDictionary(FDictionary);
end;
end;
procedure TJvSpeller.SetUserDictionary(const Value: TFileName);
begin
if FUserDictionary <> Value then
begin
FUserDictionary := Value;
LoadUserDictionary(FUserDictionary);
end;
end;
procedure TJvSpeller.Skip(Sender: TObject);
begin
FSpellerDialog.TxtSpell.Text := '';
SpellNext;
end;
procedure TJvSpeller.CreateSpellerDialog(const SpellWord: string);
begin
FSpellerDialog := TJvSpellerForm.Create(Application);
with FSpellerDialog do
begin
FSpeller := Self;
BtnSkip.OnClick := @Skip;
BtnChange.OnClick := @Change;
BtnAdd.OnClick := @Add;
BtnAdd.Enabled := UserDictionary <> '';
TxtSpell.Text := SpellWord;
LblContext.Caption := Copy(FSourceText, FWordBegin, 75);
end;
end;
procedure TJvSpeller.Spell(var SourceText: string);
var
Spw, S: string;
StartPos, Index: Integer;
begin
if FDict = '' then
raise EJVCLException.CreateRes(@RsENoDictionaryLoaded);
FSourceText := SourceText;
FWordEnd := 1;
Spw := ParseWord;
while Spw <> '' do
begin
S := AnsiLowerCase(Spw);
Index := Ord(S[1]) - 96;
if (Index > 0) and (Index < 27) then
StartPos := FDicIndex[Index]
else
StartPos := 1;
if PosEx(S + Cr, FDict, StartPos) = 0 then
begin
if FUserDic <> '' then
begin
if (Index > 0) and (Index < 27) then
StartPos := FUserDicIndex[Index]
else
StartPos := 1;
if PosEx(S + Cr, FUserDic, StartPos) = 0 then
begin
CreateSpellerDialog(Spw);
try
if FSpellerDialog.ShowModal = mrOk then
SourceText := FSourceText;
// (rom) the user dictionary has to be saved always!
if FUserDicChanged then
if FUserDic <> '' then
SaveAnsiFileFromString(UserDictionary, FUserDic);
finally
FSpellerDialog.Free;
end;
Exit;
end
end
else
begin
CreateSpellerDialog(Spw);
try
if FSpellerDialog.ShowModal = mrOk then
SourceText := FSourceText;
// (rom) the user dictionary has to be saved always!
if FUserDicChanged then
if FUserDic <> '' then
SaveAnsiFileFromString(UserDictionary, FUserDic);
finally
FSpellerDialog.Free;
end;
Exit;
end;
end;
Spw := ParseWord;
end;
end;
procedure TJvSpeller.SpellNext;
var
Spw, S: string;
Index, StartPos: Integer;
begin
Spw := ParseWord;
while Spw <> '' do
begin
S := AnsiLowerCase(Spw);
Index := Ord(S[1]) - 96;
if (Index > 0) and (Index < 27) then
StartPos := FDicIndex[Index]
else
StartPos := 1;
if PosEx(S + Cr, FDict, StartPos) = 0 then
begin
if FUserDic <> '' then
begin
if (Index > 0) and (Index < 27) then
StartPos := FUserDicIndex[Index]
else
StartPos := 1;
if PosEx(S + Cr, FUserDic, StartPos) = 0 then
begin
FSpellerDialog.TxtSpell.Text := Spw;
FSpellerDialog.LblContext.Caption := Copy(FSourceText, FWordBegin, 75);
Exit;
end;
end
else
begin
FSpellerDialog.TxtSpell.Text := Spw;
FSpellerDialog.LblContext.Caption := Copy(FSourceText, FWordBegin, 75);
Exit;
end;
end;
Spw := ParseWord;
end;
FSpellerDialog.ModalResult := mrOk;
end;
function TJvSpeller.WordBegin: Boolean;
var
L: Integer;
begin
L := Length(FSourceText);
FWordBegin := FWordEnd;
while (FWordBegin <= L) and (not CharInSet(FSourceText[FWordBegin], ['a'..'z', 'A'..'Z'])) do
Inc(FWordBegin);
Result := (FWordBegin <= L);
end;
function TJvSpeller.WordEnd: Boolean;
var
L: Integer;
begin
FWordEnd := FWordBegin;
L := Length(FSourceText);
while (FWordEnd <= L) and CharInSet(FSourceText[FWordEnd], ['a'..'z', 'A'..'Z']) do
Inc(FWordEnd);
Result := (FWordEnd <= L);
end;
end.