⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spellers.pas

📁 拼写检查
💻 PAS
📖 第 1 页 / 共 4 页
字号:
  FOptions:= Options;
  SpellChecker:= Owner;
end;

procedure CheckSR(SR: TSEC);
begin
  if (SR<>secNoErrors) then
    case FUserLanguage of
      ulEnglish: raise ESpellError.CreateFmt(SpellRes.spsError, [SR]);
      ulown: raise ESpellError.CreateFmt(SpellResDe.spsError, [SR]);
      ulother: raise ESpellError.CreateFmt(spOError, [SR]);
    end;
end;

{TCSAPISpeller}
type
  TCSAPISpeller = class(TAbstractSpeller)
  private
    SpellInstance: THandle;
    DLLName: String;
    LexName: String;
    UserDict: TFileName;
    UnkWord: String;
    FOptions: TSpellOptions;
    SpellVer: TSpellVerFunc;
    SpellInit: TSpellInitFunc;
    SpellOptions: TSpellOptionsFunc;
    SpellCheck: TSpellCheckFunc;
    SpellTerminate: TSpellTerminateFunc;
    SpellVerifyMdr: TSpellVerifyMdrFunc;
    SpellOpenMdr: TSpellOpenMdrFunc;
    SpellOpenUdr: TSpellOpenUdrFunc;
    SpellAddUdr: TSpellAddUdrFunc;
    SpellAddChangeUdr: TSpellAddChangeUdrFunc;
    SpellDelUdr: TSpellDelUdrFunc;
    SpellClearUdr: TSpellClearUdrFunc;
    SpellGetSizeUdr: TSpellGetSizeUdrFunc;
    SpellGetListUdr: TSpellGetListUdrFunc;
    SpellCloseMdr: TSpellCloseMdrFunc;
    SpellCloseUdr: TSpellCloseUdrFunc;
  protected
    Handle: TSPLID;
    SpecChars: TWSC;
    Mdrs: TMDRS;
    Udr: TUDR;
    InputBuffer: TSIB;
    ResultBuffer: TSRB;
    constructor Create(Language: TLanguage; Owner: TSpellChecker; Options: TSpellOptions); override;
    destructor Destroy; override;
    function FindMisspell(Buf: PChar; MaxLen: Integer; var Start, Len: Integer): TSpellReturnCode; override;
    function FindNextMisspell(Buf: PChar; MaxLen: Integer; var Start, Len: Integer): TSpellReturnCode; override;
    procedure ChangeOnce(Word, NewWord: String); override;
    procedure ChangeAlways(Word, NewWord: String); override;
    procedure Add(Word: String); override;
    procedure IgnoreAlways(Word: String); override;
    procedure GetVariants(Word: String; Variants: TStrings); override;
    function GetChangeText: String; override;
    function GetMisspellText: String; override;
  end;

{$O-}

constructor TCSAPISpeller.Create(Language: TLanguage; Owner: TSpellChecker; Options: TSpellOptions);
var
  UdrRO: Boolean;
  NotFound: Boolean;
  Registry: TRegistry;
begin
  inherited;
  FSpellerType := sptMSOffice;
  with SpecChars do
    begin
      bIgnore:= #0;
      bHyphenHard:= #45;
      bHyphenSoft:= #31;
      bHyphenNonBreaking:= #30;
      bEmDash:= #151;
      bEnDash:= #150;
      bEllipsis:= #133;
      rgLineBreak:= #11#10;
      rgParaBreak:= #13#10;
    end;
  Registry:= TRegistry.Create;
  Registry.RootKey:= HKEY_LOCAL_MACHINE;
  try
    NotFound:= True;
    if Registry.OpenKeyReadOnly(
        Format('\SOFTWARE\Microsoft\Shared Tools\Proofing Tools\Spelling\%d\Normal', [FLanguage])) or
       Registry.OpenKeyReadOnly(
        Format('\SOFTWARE\Microsoft\Shared Tools\Proofing Tools\Spelling\%d\Normal', [1024+(FLanguage mod 1024)]))
      then begin
      DLLName:= Registry.ReadString('Engine');
      LexName:= Registry.ReadString('Dictionary');
      NotFound := False;
      end;
    if not NotFound then begin
      if (SpellChecker.CustomDict='') and Registry.OpenKeyReadOnly(
         '\SOFTWARE\Microsoft\Shared Tools\Proofing Tools\Custom Dictionaries')
        then UserDict:= Registry.ReadString('1')
        else begin
          UserDict:= SpellChecker.CustomDict;
          if (SpellChecker.CustomDict='') then begin
            try
              Registry.Access := KEY_ALL_ACCESS;
              Registry.OpenKey(
                '\SOFTWARE\Microsoft\Shared Tools\Proofing Tools\Custom Dictionaries', True)
            except on E: Exception do
              Registry.Access := KEY_READ;
            end;
          end;
        end;
      if Assigned(SpellChecker.FOnGetDict)
        then SpellChecker.FOnGetDict(SpellChecker, FLanguage, UserDict);
      if UserDict='' then
        begin
          UserDict:= ExtractFilePath(LexName)+'CUSTOM.DIC';
          try
            Registry.WriteString('1', UserDict);
            Registry.CloseKey;
          except end;  
        end;
    end;
  finally
    Registry.Free;
  end;  
  if NotFound then
    begin
      FNotActive:= True;
      Exit;
    end;
  try
    SpellInstance:= LoadLibrary(PChar(DllName));
  except
    FNotActive:= True;
    case FUserLanguage of
      ulEnglish: raise ESpellError.CreateFmt(SpellRes.spsErrorLoad, [DllName]);
      ulown: raise ESpellError.CreateFmt(SpellResDe.spsErrorLoad, [DllName]);
      ulother: raise ESpellError.CreateFmt(spOErrorLoad, [DllName]);
    end;
  end;
  try
    @SpellVer:= GetProcAddress(SpellInstance, 'SpellVer');
    @SpellInit:= GetProcAddress(SpellInstance, 'SpellInit');
    @SpellOptions:= GetProcAddress(SpellInstance, 'SpellOptions');
    @SpellCheck:= GetProcAddress(SpellInstance, 'SpellCheck');
    @SpellTerminate:= GetProcAddress(SpellInstance, 'SpellTerminate');
    @SpellVerifyMdr:= GetProcAddress(SpellInstance, 'SpellVerifyMdr');
    @SpellOpenMdr:= GetProcAddress(SpellInstance, 'SpellOpenMdr');
    @SpellOpenUdr:= GetProcAddress(SpellInstance, 'SpellOpenUdr');
    @SpellAddUdr:= GetProcAddress(SpellInstance, 'SpellAddUdr');
    @SpellAddChangeUdr:= GetProcAddress(SpellInstance, 'SpellAddChangeUdr');
    @SpellDelUdr:= GetProcAddress(SpellInstance, 'SpellDelUdr');
    @SpellClearUdr:= GetProcAddress(SpellInstance, 'SpellClearUdr');
    @SpellGetSizeUdr:= GetProcAddress(SpellInstance, 'SpellGetSizeUdr');
    @SpellGetListUdr:= GetProcAddress(SpellInstance, 'SpellGetListUdr');
    @SpellCloseMdr:= GetProcAddress(SpellInstance, 'SpellCloseMdr');
    @SpellCloseUdr:= GetProcAddress(SpellInstance, 'SpellCloseUdr');
  except
    FreeLibrary(SpellInstance);
    FNotActive:= True;
    case FUserLanguage of
      ulEnglish: raise ESpellError.CreateFmt(SpellRes.spsErrorLoad, [DllName]);
      ulown: raise ESpellError.CreateFmt(SpellResDe.spsErrorLoad, [DllName]);
      ulother: raise ESpellError.CreateFmt(spOErrorLoad, [DllName]);
    end;
  end;
  FNotActive:= False;
  FOptions:= Options;
  CheckSR(SpellInit(Handle, SpecChars));
  CheckSR(SpellOptions(Handle, Word(FOptions)));
  CheckSR(SpellOpenMdr(Handle, PChar(LexName), nil, False, True, FLanguage, Mdrs));
  CheckSR(SpellOpenUdr(Handle, PChar(UserDict), True, IgnoreAlwaysProp, Udr, UdrRO));
  with InputBuffer do
    begin
      cMdr:= 1;
      cUdr:= 1;
      lrgMdr:= @Mdrs.MDR;
      lrgUdr:= @Udr;
    end;
  with ResultBuffer do
    begin
      cch:= 1024;
      lrgsz:= AllocMem(1024);
      lrgbRating:= AllocMem(255);
      cbRate:= 255;
    end;
end;

destructor TCSAPISpeller.Destroy;
var
 SR1: TSEC;
begin
  if not FNotActive then
    begin
      FreeMem(ResultBuffer.lrgsz);
      FreeMem(ResultBuffer.lrgbRating);
      CheckSR(SpellCloseMdr(Handle, Mdrs));
      SR1 := SpellCloseUdr(Handle, Udr, True);
      if (SR1 <> 33026) then CheckSR(SR1);
      CheckSR(SpellTerminate(Handle, True));
      try
        FreeLibrary(SpellInstance);
      except
        case FUserLanguage of
          ulEnglish: raise ESpellError.CreateFmt(SpellRes.spsErrorUnLoad, [DllName]);
          ulown: raise ESpellError.CreateFmt(SpellResDe.spsErrorUnLoad, [DllName]);
          ulother: raise ESpellError.CreateFmt(spOErrorUnLoad, [DllName]);
        end;
      end;
    end;
  inherited;
end;

function TCSAPISpeller.FindMisspell(Buf: PChar; MaxLen: Integer; var Start, Len: Integer): TSpellReturnCode;
begin
  if FNotActive then
    begin
      Result:= srNoErrors;
      Exit;
    end;
  InputBuffer.cch:= MaxLen;
  InputBuffer.lrgch:= Buf;
  InputBuffer.wSpellState:= fssStartsSentence;
  CheckSR(SpellCheck(handle, sccVerifyBuffer, InputBuffer, ResultBuffer));
  Result:= TSpellReturnCode(ResultBuffer.scrs);
  if Result<>srNoErrors then
    begin
      Start:= ResultBuffer.ichError;
      Len:= ResultBuffer.cchError;
      SetLength(UnkWord, ResultBuffer.cchError);
      StrLCopy(@UnkWord[1], InputBuffer.lrgch+ResultBuffer.ichError, ResultBuffer.cchError);
    end;
end;

function TCSAPISpeller.FindNextMisspell(Buf: PChar; MaxLen: Integer; var Start, Len: Integer): TSpellReturnCode;
begin
  if FNotActive then
    begin
      Result:= srNoErrors;
      Exit;
    end;
  InputBuffer.cch:= MaxLen;
  InputBuffer.lrgch:= Buf;
  InputBuffer.wSpellState:= fssIsContinued;
  CheckSR(SpellCheck(Handle, sccVerifyBuffer, InputBuffer, ResultBuffer));
  Result:= TSpellReturnCode(ResultBuffer.scrs);
  if Result<>srNoErrors then
    begin
      Start:= ResultBuffer.ichError;
      Len:= ResultBuffer.cchError;
      SetLength(UnkWord, ResultBuffer.cchError);
      StrLCopy(@UnkWord[1], InputBuffer.lrgch+ResultBuffer.ichError, ResultBuffer.cchError);
    end;
end;

procedure TCSAPISpeller.ChangeOnce(Word, NewWord: String);
begin
  if FNotActive then
    Exit;
  CheckSR(SpellAddChangeUdr(Handle, udrChangeOnce,
      PChar(Word), PChar(NewWord)));
end;

procedure TCSAPISpeller.ChangeAlways(Word, NewWord: String);
begin
  if FNotActive then
    Exit;
  CheckSR(SpellAddChangeUdr(Handle, udrChangeAlways,
      PChar(Word), PChar(NewWord)));
end;

procedure TCSAPISpeller.Add(Word: String);
begin
  if FNotActive then
    Exit;
  CheckSR(SpellAddUdr(Handle, Udr, PChar(Word)));
end;

procedure TCSAPISpeller.IgnoreAlways(Word: String);
begin
  if FNotActive then
    Exit;
  CheckSR(SpellAddUdr(Handle, udrIgnoreAlways, PChar(Word)));
end;

procedure TCSAPISpeller.GetVariants(Word: String; Variants: TStrings);
var
  SIB: TSIB;
  SRB: TSRB;
  Buf: array[0..2047]of Char;
  Ratings: array[0..255]of Byte;
  P: PChar;
begin
  Variants.Clear;
  if FNotActive then
    Exit;
  with SIB do
    begin
      cch:= Length(Word);
      cMdr:= 1;
      cUdr:= 1;
      wSpellState:= fssNoStateInfo;
      lrgch:= @Word[1];
      lrgMdr:= @Mdrs.MDR;
      lrgUdr:= @Udr;
    end;
  with SRB do
    begin
      cch:= 2047;
      lrgsz:= @Buf;
      lrgbRating:= @Ratings;
      cbRate:= 255;
    end;
  CheckSR(SpellCheck(Handle, sccSuggest, SIB, SRB));
  while SRB.scrs<>scrsNoMoreSuggestions do
    begin
      P:= SRB.lrgsz;
      while P^<>#0 do
        begin
          if Variants.IndexOf(P)=-1 then
            Variants.Add(P);
          while P^<>#0 do
            Inc(P);
          Inc(P);
        end;
      CheckSR(SpellCheck(Handle, sccSuggestMore, SIB, SRB));
    end;
end;

function TCSAPISpeller.GetChangeText: String;
begin
  if FNotActive then
    Result:= ''
  else
    Result:= ResultBuffer.lrgsz;
end;

function TCSAPISpeller.GetMisspellText: String;
begin
  if FNotActive then
    Result:= ''
  else
    Result:= UnkWord;
end;  {TCSAPISpeller}
{$O+}

{TISpeller}
type
  TISpeller = class(TAbstractSpeller)
  private
    FOptions: TSpellOptions;
    si_r, si_w, so_r, so_w, se_r, se_w: THandle;
    PI: TProcessInformation;
    M, Repl: String;
    UnkWord: WideString;
    ReplData: TStringList;
    function SpellCheck (word: String): String;
    function Check(Word: WideString): Boolean;
    procedure SpellCommand (Word: WideString);
  protected
    constructor Create(Language: TLanguage; Owner: TSpellChecker; Options: TSpellOptions); override;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -