source: cprs/branches/HealthSevak-CPRS/CPRS-Lib/Hans SpellCheck/skaSpellCheck.pas@ 1715

Last change on this file since 1715 was 1715, checked in by healthsevak, 9 years ago

Modified the library to make it more generic from Delphi community point of view before sharing with original author/custodian of HunSpell library at sourceforge

File size: 24.0 KB
Line 
1unit skaSpellCheck;
2(* ***************************** BEGIN LICENSE BLOCK **********************
3 *
4 * Copyright (C) 2015
5 * Sunil Kumar Arora (digitiger@gmail.com sunil@healthsevak.com)
6 * All Rights Reserved.
7 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
8 *
9 * The contents of this file are subject to the Mozilla Public License Version
10 * 1.1 (the "License"); you may not use this file except in compliance with
11 * the License. You may obtain a copy of the License at
12 * http://www.mozilla.org/MPL/
13 *
14 * Software distributed under the License is distributed on an "AS IS" basis,
15 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
16 * for the specific language governing rights and limitations under the
17 * License.
18 *
19 *Special Note:
20 * This work has heavily relies upon rather build upon Copyrighted work by
21 * Miha Vrhovnik (http://simail.sf.net, http://xcollect.sf.net) which is
22 * available at http://sourceforge.net/projects/hunspell/
23 *
24 * Alternatively, the content of this file maybe used under the terms of either
25 * the GNU General Public License Version 2 or later (the "GPL"), or the GNU
26 * Lesser General Public License Version 2.1 or later (the "LGPL"), in which
27 * case the provisions of the GPL or the LGPL are applicable instead of those
28 * above. If you wish to allow use of your version of this file only under the
29 * terms of either the GPL or the LGPL, and not to allow others to use your
30 * version of this file under the terms of the MPL, indicate your division by
31 * deleting the provisions above and replace them with the notice and other
32 * provisions required by the GPL or LGPL. If you do not delete the provisions
33 * above, a recipient may use your version of this file under the terms of any
34 * one of the MPL, the GPL or the LGPL.
35 *
36 * *********************** END LICENSE BLOCK *********************************)
37
38interface
39
40uses
41 Windows, Classes, SysUtils, ComCtrls, StdCtrls, Graphics, Forms, Controls;
42
43 const
44 AboutThis = 'A wrapper component developed by Sunil K Arora '
45 + '(digitiger@gmail.com) of HealthSevak using OpenSource HanSpell engine';
46type
47 TSpellState = (ssNoengine, ssInActive, ssReady, ssChecking, ssCancelled,
48 ssCompleted);
49 TStateChangeEvent = procedure (const Sender : TObject;
50 const State : TSpellState) of object;
51
52 TskaHunSpellChecker = class(TComponent)
53 private
54 FActiveOrLoaded: Boolean;
55 FpointerHunLib: Pointer;
56 FSourceEdit: TRichEdit;
57 FSuggestionList: TListbox;
58
59 FAffixFileName: string;
60 FDictFileName: string;
61 CurrentWord: String;
62 CurrentText: String;
63 FoundAt: Integer;
64 PosOfFirstCharInCurrentLine: integer;
65 CurrentLine: Integer;
66 FIgnore: TStringList;
67 WaitForUser: Boolean;
68 WordLength:integer;
69 WordPos: Integer;
70 PREditorWndProc:pointer;
71 FHighlightColor: TColor;
72 FUndoList: TStringList;
73 FCustDict: TStringList;
74 FCustom: String;
75 FModified: Boolean;
76 FHighlightEdit: TEdit;
77 FTxtBeforeManualEdit: String;
78
79 FStatus: TSpellState;
80 FOnStart: TNotifyEvent;
81 FOnAbort : TNotifyEvent;
82 FOnStateChange : TStateChangeEvent;
83
84 function AddCustomWord(aWord: String; isInternal: Boolean = False): Boolean;
85 overload; virtual;
86 Function CurrentWordDetail(WithPosition: Boolean= True): String;
87 function GetActive: Boolean;
88 function GetStatus: TSpellState;
89 procedure Initialize;
90 procedure SetActive(const Value: Boolean);
91 procedure SetAffixFileName(const Value: string);
92 procedure SetCustomDict(const Value: String);
93 procedure SetDictFileName(const Value: string);
94 procedure SetHighLightEdit(const Value: TEdit);
95 procedure SetSourceEdit(const Value: TRichEdit);
96 Function ShowMisSpelledWord:boolean;
97 procedure Loaded; override;
98 procedure ReplaceCurrentWordWith(const aNewWord: String);
99 function GetAboutThis: String;
100 procedure SaveForUndo(const Ignoring: Boolean=False);
101 procedure InformStatusChange;
102 public
103 constructor Create(AOwner: TComponent); overload; override;
104 constructor Create(AOwner: TComponent; SourceTextRichEdit: TRichedit;
105 SuggestList: TListbox); ReIntroduce; overload;
106 destructor Destroy; override;
107
108 function AbortSpellCheck(Verbose: Boolean = True):Boolean;
109 function AddCustomWord: Boolean; overload; virtual;
110 procedure Change;
111 procedure ChangeAll;
112 procedure CheckSpelling;
113 procedure Close; virtual;
114 procedure CorrectWithMyWord;
115 procedure GetSuggestions(const aMisSpeltWord: string;
116 const SuggestionList: TStrings); dynamic;
117 procedure IgnoreAll;
118 procedure IgnoreOnce;
119 function IsMisspelled(const AWord: string): Boolean; dynamic;
120 procedure ManualChangeStart;
121 procedure ManualChangeDone;
122 function Open:Boolean; virtual;
123 procedure ReOpen;
124 function ReStart: Boolean; virtual;
125 function Undo: Boolean;
126 property SpellCheckState: TSpellState read GetStatus default ssInActive;
127 published
128 property About: String read GetAboutThis;
129 property Active: Boolean read GetActive write SetActive;
130 property AffixFileName: string read FAffixFileName write SetAffixFileName;
131 property CustDictionaryFile: String read FCustom write SetCustomDict;
132 property DictionaryFileName:string read FDictFileName write SetDictFileName;
133 property ColorForMisspelled: TColor read FHighlightColor
134 write FHighlightColor default clRed;
135 property MisSpeltWord: TEdit read FHighlightEdit write SetHighLightEdit;
136 property IsModified: Boolean read FModified;
137 property OnStart : TNotifyEvent read FOnStart write FOnStart;
138 property OnStateChange : TStateChangeEvent read FOnStateChange
139 write FOnStateChange;
140 property OnAbort : TNotifyEvent read FOnAbort write FOnAbort;
141 property SourceTextControl: TRichEdit read FSourceEdit write SetSourceEdit;
142 property SuggestionList:TListbox read FSuggestionList write FSuggestionList;
143
144 end;
145
146 procedure Register;
147
148 Const
149 CompletionMessage = 'Spell Check Complete.';
150 CaptionForNewWord = 'New Word Suggestion';
151 ConfirmAbort = 'Really abort?';
152 ConfirmComplete = 'If you accept last change than SpellCheck is complete.'
153 + #13 + ' To review last change click on "Cancel".';
154 PromptForNewWord = 'Specify the replacement for current mis-spelt word:';
155 DLLNotLoaded = 'Failed to load SpellCheck Engine DLL.';
156 MisSpeltReplacement = 'The new word specified by you "%s" looks mis-spelt!'
157 +' Would you want to still use it? Click NO button '
158 +'to specify better replacement word.';
159
160 var
161 OldRichEditWndProc: {integer}pointer;
162 CurrentMe: TskaHunSpellChecker;
163implementation
164 uses messages, Dialogs, RichEdit, SHFolder, uHunSpellLib;
165
166procedure Register;
167begin
168 RegisterComponentsProc('SkA Utility', [TskaHunSpellChecker]);
169end;
170
171{ TskaHunSpellChecker }
172
173function TskaHunSpellChecker.AbortSpellCheck(Verbose: Boolean = True): Boolean;
174begin
175 if FStatus <> ssChecking then
176 begin
177 FStatus := ssCancelled;
178 Close;
179 exit;
180 end;
181
182 Result := (not isModified) or
183 (not Verbose) or (MessageDlg(ConfirmAbort, mtConfirmation,
184 [mbYes, mbNo],0, mbNo) = 6);
185
186 if Result and (FUndoList.Count > 0) then
187 begin
188 SourceTextControl.Text := FUndoList[0];
189 FUndoList.Clear;
190 FUndoList.Add(SourceTextControl.Text);
191 end;
192 FIgnore.Clear;
193 FStatus := ssCancelled;
194 SourceTextControl.Invalidate;
195 if Assigned(OnAbort) then
196 OnAbort(Self);
197end;
198
199function TskaHunSpellChecker.AddCustomWord(aWord: String;
200 isInternal: Boolean = False): Boolean;
201begin
202 Result := False;
203 if (not active) or (trim(aWord) = '') or (SpellCheckState <> ssChecking)
204 or (not assigned(SourceTextControl)) or (not assigned(SuggestionList)) then
205 begin
206 Result := False;
207 exit;
208 end;
209 uHunSpellLib.hunspell_put_word(FpointerHunLib, PAnsiChar(AnsiString(aWord)));
210 Result := True;
211end;
212
213procedure TskaHunSpellChecker.ChangeAll;
214begin
215 if (SpellCheckState <> ssChecking) or (not assigned(SourceTextControl))
216 or (not assigned(SuggestionList)) then
217 exit;
218 SaveForUndo;
219 SourceTextControl.Text := StringReplace(SourceTextControl.Text,
220 CurrentWord, SuggestionList.Items[SuggestionList.ItemIndex],
221 [rfReplaceAll,rfIgnoreCase]);
222 WaitForUser := False;
223 FModified := True;
224 SourceTextControl.Invalidate;
225
226end;
227
228function TskaHunSpellChecker.AddCustomWord: Boolean;
229begin
230 Result := AddCustomWord(CurrentWord, False);
231 FCustdict.Add(CurrentWord);
232 WaitForUser := False;
233 AbortSpellCheck(False);
234 Initialize;
235 CheckSpelling;
236 ShowMisSpelledWord;
237end;
238
239procedure TskaHunSpellChecker.ReOpen;
240begin
241 Close;
242 Open;
243end;
244
245procedure TskaHunSpellChecker.ReplaceCurrentWordWith(const aNewWord: String);
246var
247 full: String;
248 prefix: string;
249 suffix: string;
250begin
251 full := SourceTextControl.Lines[CurrentLine];
252{remember there is one extra space at the start of the line prefixed while
253 populating this variable}
254 prefix := copy(CurrentText, 2, WordPos-2);
255 Suffix := copy(CurrentText, WordPos+WordLength,
256 length(CurrentText));
257 SaveForUndo;
258 FModified := True;
259 SourceTextControl.Lines[CurrentLine] :=prefix + aNewWord + suffix;
260 WaitForUser := False;
261 FStatus := ssChecking;
262 FModified := True;
263 SourceTextControl.Invalidate;
264end;
265
266function TskaHunSpellChecker.ReStart: Boolean;
267begin
268 Close;
269 Result := Open;
270 Initialize;
271 WaitForUser := False;
272 if FStatus <> ssChecking then
273 begin
274 FStatus := ssChecking;
275 InformStatusChange;
276 end;
277 SourceTextControl.Invalidate;
278 Result := not WaitForUser;
279end;
280
281procedure TskaHunSpellChecker.Change;
282
283begin
284 if (SpellCheckState <> ssChecking) or (not assigned(SourceTextControl))
285 or (not assigned(SuggestionList)) then
286 exit;
287 ReplaceCurrentWordWith(SuggestionList.Items[SuggestionList.ItemIndex]);
288end;
289
290procedure TskaHunSpellChecker.CheckSpelling;
291begin
292 if (SpellCheckState = ssChecking) or (not assigned(SourceTextControl))
293 or (trim(SourceTextControl.Text)= '') or (not assigned(SuggestionList)) then
294 exit;
295
296 Initialize;
297 FUndoList.Clear;
298 FUndoList.Add(SourceTextControl.Text);
299 FIgnore.Clear;
300 WaitForUser := False;
301 FStatus := ssChecking;
302 if Assigned(OnStart) then
303 OnStart(Self);
304 SourceTextControl.Invalidate;
305end;
306
307procedure TskaHunSpellChecker.Close;
308begin
309 if not Active then Exit;
310 uHunSpellLib.hunspell_uninitialize(FpointerHunLib);
311 FpointerHunLib := nil;
312 FStatus := ssInActive;
313 InformStatusChange;
314end;
315
316
317procedure TskaHunSpellChecker.CorrectWithMyWord;
318var
319 NewWord: String;
320 GotIt: Boolean;
321begin
322 if (SpellCheckState <> ssChecking) or (not assigned(SourceTextControl))
323 or (not assigned(SuggestionList)) then
324 exit;
325
326 if SuggestionList.Count > 0 then
327 NewWord := SuggestionList.Items[0]
328 else
329 NewWord := CurrentWord;
330
331 GotIt := False;
332 while not GotIt do
333 begin
334 if not InputQuery(CaptionForNewWord, PromptForNewWord, NewWord) then
335 exit;
336
337 GotIt := (not IsMisspelled(NewWord))
338 or (MessageDlg(Format(MisSpeltReplacement,[NewWord]),
339 mtWarning, [mbYes, mbNo],0, mbNo) =6) ;
340 end;
341
342 if IsMisspelled(NewWord) then
343 AddCustomWord(NewWord, True);
344
345 ReplaceCurrentWordWith(NewWord);
346end;
347
348constructor TskaHunSpellChecker.Create(AOwner: TComponent);
349begin
350 inherited;
351 ColorForMisspelled := clRed;
352
353 CurrentMe := Self;
354 FIgnore := TStringList.Create;
355 FCustDict := TStringList.Create;
356
357 if (trim(CustDictionaryFile)<>'') and (FileExists(CustDictionaryFile)) then
358 try
359 FCustDict.LoadFromFile(CustDictionaryFile);
360 except
361 end;
362
363 FUndoList := TStringList.Create;
364
365 FStatus := ssInActive;
366 WaitForUser := False;
367 WordPos := 0;
368end;
369
370constructor TskaHunSpellChecker.Create(AOwner: TComponent;
371 SourceTextRichEdit: TRichedit; SuggestList: TListbox);
372begin
373 create(AOwner);
374 SourceTextControl := SourceTextRichEdit;
375 SuggestionList := SuggestList;
376end;
377
378function TskaHunSpellChecker.CurrentWordDetail(WithPosition: Boolean): String;
379begin
380 Result := '$$' + CurrentWord + '$$';
381 if WithPosition then
382 Result := '$$' + IntToStr(FoundAt+1) + Result;
383end;
384
385destructor TskaHunSpellChecker.Destroy;
386begin
387 Close;
388 FIgnore.clear;
389 FreeAndNil(FIgnore);
390 FreeAndNil(FUndoList);
391 if not (csDesigning in ComponentState) then
392 try
393 if FCustDict.Count > 0 then
394 try
395 FCustDict.SaveToFile(CustDictionaryFile);
396 except
397 end;
398 finally
399 FCustDict.Free;
400 end;
401 inherited;
402end;
403
404function TskaHunSpellChecker.GetAboutThis: String;
405begin
406 Result := AboutThis;
407end;
408
409function TskaHunSpellChecker.GetActive: Boolean;
410begin
411 Result := (FpointerHunLib <> nil);
412end;
413
414function TskaHunSpellChecker.GetStatus: TSpellState;
415begin
416 Result := FStatus;
417end;
418
419procedure TskaHunSpellChecker.GetSuggestions(const aMisSpeltWord: string;
420 const SuggestionList: TStrings);
421var
422 i: Integer;
423 pMisSpelt: PAnsiChar;
424 suggestions: PPAnsiChar;
425 Results: PPAnsiChar;
426 Count: Integer;
427begin
428 if (not Active) or (not Assigned(SuggestionList)) then
429 exit;
430
431 pMisSpelt := PAnsiChar(AnsiString(aMisSpeltWord));
432
433 if not uHunSpellLib.hunspell_spell(FpointerHunLib, pMisSpelt) then
434 uHunSpellLib.hunspell_suggest_auto(FpointerHunLib, pMisSpelt, suggestions);
435 begin
436 Count :=uHunSpellLib.hunspell_suggest(FpointerHunLib,pMisSpelt,suggestions);
437 Results := suggestions;
438 for i := 1 to Count do
439 begin
440 SuggestionList.Add(Results^);
441 Inc(Integer(Results), SizeOf(Pointer));
442 end;
443 uHunSpellLib.hunspell_suggest_free(FpointerHunLib, suggestions, Count);
444 end;
445end;
446
447function TskaHunSpellChecker.ShowMisSpelledWord: boolean;
448var
449 I , l :integer;
450 CharPosion:integer;
451 FirstVisibleLine, LastVisibleLine:integer;
452
453 hndl: hwnd;
454 dcForHndl: THandle;
455 visrect:Trect;
456 vispoint:TPoint;
457 procedure ShowMisSpelletWord;
458 begin
459 if Assigned(FHighlightEdit) then
460 begin
461 FHighlightEdit.Font.Color := ColorForMisspelled;
462 FHighlightEdit.Text := CurrentWord;
463 FHighlightEdit.Show;
464 end ;
465
466 if ((PosOfFirstCharInCurrentLine + FoundAt) < 1) then
467 exit;
468
469 SendMessage (SourceTextControl.Handle, EM_POSFROMCHAR, integer(@VisPoint),
470 PosOfFirstCharInCurrentLine + FoundAt-1);
471 SetTextColor(dcForHndl, ColorForMisspelled);
472 TextOut(dcForHndl, VisPoint.x, VisPoint.y, pchar(CurrentWord), WordLength);
473 end;
474begin
475 Result := False;
476 if (SpellCheckState <> ssChecking) or (not assigned(SourceTextControl))
477 or (not assigned(SuggestionList)) then
478 exit;
479
480 hndl:=SourceTextControl.Handle;
481
482 result:= SendMessage (hndl, EM_GETRECT, 0, integer(@visrect))=0;
483
484 dcForHndl := getdc(hndl);
485
486 if result then
487 begin
488 // VisPoint := visrect.BottomRight;
489 vispoint.Y := visrect.Bottom;
490 vispoint.X := visrect.Right;
491 CharPosion := SendMessage (hndl, EM_CHARFROMPOS, 0, integer(@VisPoint));
492 LASTVISIBLELINE := SendMessage (hndl, EM_LINEFROMCHAR, CharPosion, 0);
493 FIRSTVISIBLELINE := SendMessage (hndl, EM_GETFIRSTVISIBLELINE, 0, 0);
494
495 SetBkMode (dcForHndl, TRANSPARENT);
496 SelectObject(dcForHndl, SourceTextControl.font.Handle);
497 i := 0;
498
499 if WaitForUser then
500 begin
501 ShowMisSpelletWord;
502 exit;
503 end;
504
505 For l := 0 to SourceTextControl.Lines.Count -1 do
506 begin
507 {$R-}
508 CurrentLine := l;
509 if trim(SourceTextControl.Lines[CurrentLine]) = '' then
510 continue;
511
512 CurrentText := ' ' + SourceTextControl.Lines[CurrentLine];
513 PosOfFirstCharInCurrentLine := SendMessage (SourceTextControl.Handle,
514 EM_LINEINDEX, CurrentLine, 0);
515 i := 0;
516
517 While i <= LENgth(CurrentText) do
518 begin
519 FoundAt := i -1;
520 if Assigned(FHighlightEdit) then
521 FHighlightEdit.Hide;
522
523
524 //SuggestionList.Clear;
525 {Any character except these will count as a word delimiter}
526 While CurrentText[i] in ['A'..'Z','a'..'z','0'..'9'] do inc(i);
527
528 WordLength := i- FoundAt -1;
529 WordPos := i-WordLength;
530 CurrentWord := copy(CurrentText, WordPos, WordLength);
531 If ((FIgnore.IndexOf(CurrentWordDetail(True))< 0) //SingelIgnore
532 and (FIgnore.IndexOf(CurrentWordDetail(False))< 0) //IgnoreAll
533 and (IsMisspelled(CurrentWord))) Then
534 begin
535 GetSuggestions(CurrentWord, SuggestionList.Items);
536 if SuggestionList.Count > 0 then
537 SuggestionList.ItemIndex := 0;
538 ShowMisSpelletWord;
539 if CurrentLine > LastVisibleLine then
540 SendMessage(SourceTextControl.Handle, EM_LINESCROLL, 0,
541 (CurrentLine - lastvisibleLine)+5);
542 WaitForUser := True;
543 exit;
544 End
545 else
546 SuggestionList.Clear;
547 inc(i);
548 end;
549 end;
550 if (CurrentLine >= SourceTextControl.Lines.Count-1)
551 and (i >= length(CurrentText) +1) then
552 begin
553 if (not FModified)
554 or (MessageDlg(ConfirmComplete,mtConfirmation,[mbOK, mbCancel],0)=mrOk)
555 then
556 begin
557 FStatus := ssCompleted;
558 InformStatusChange;
559 end
560 else
561 Undo;
562 end;
563 {$R+}
564 end;
565 ReleaseDC(SourceTextControl.Handle, dcForHndl);
566
567End;
568
569function TskaHunSpellChecker.Undo: Boolean;
570var
571 tmpStr: String;
572 tmpCount: Integer;
573 SrcText: String;
574begin
575 if FUndoList.Count > 1 then
576 try
577 tmpStr := FUndoList.Strings[FUndoList.Count-1];
578 if (AnsiPos('$$',tmpStr)=1) and (copy(tmpStr,length(tmpStr)-1,2) = '$$')then
579 //if last action was ignoring word then just remove it from ignore list
580 begin
581 tmpCount := strtoInt(StringReplace(tmpStr,'$$','',[rfReplaceAll]));
582 while FIgnore.Count > tmpCount do
583 FIgnore.Delete(FIgnore.Count -1);
584 end
585 else
586 SourceTextControl.Text := tmpStr;
587
588 Result := True;
589 FUndoList.Delete(FUndoList.Count-1);
590 ReStart;
591 except
592 Result := False;
593 end;
594end;
595
596procedure TskaHunSpellChecker.IgnoreAll;
597begin
598 if (SpellCheckState <> ssChecking) or (not assigned(SourceTextControl))
599 or (not assigned(SuggestionList)) then
600 exit;
601
602 SaveForUndo(True);
603 FIgnore.Add(CurrentWordDetail(False)) ;
604 WaitForUser := False;
605 SourceTextControl.Invalidate;
606end;
607
608procedure TskaHunSpellChecker.IgnoreOnce;
609begin
610 if (SpellCheckState <> ssChecking) or (not assigned(SourceTextControl))
611 or (not assigned(SuggestionList)) then
612 exit;
613
614 if trim(CurrentWord) <> '' then
615 begin
616 SaveForUndo(True);
617 FIgnore.Add(CurrentWordDetail(True)) ;
618 end;
619 WaitForUser := False;
620 SourceTextControl.Invalidate;
621end;
622
623procedure TskaHunSpellChecker.InformStatusChange;
624begin
625 if Assigned(OnStateChange) then
626 OnStateChange(Self, FStatus);
627end;
628
629procedure TskaHunSpellChecker.Initialize;
630begin
631 CurrentWord := '';
632 WordLength := 0;
633 FoundAt := -1;
634 CurrentLine := 0;
635 WordPos := 0;
636 SuggestionList.Clear;
637end;
638
639function TskaHunSpellChecker.IsMisspelled(const AWord: string): Boolean;
640begin
641 if (not Active) then
642 Result := True
643 else
644 Result := not uHunSpellLib.hunspell_spell(FpointerHunLib,
645 PAnsiChar(AnsiString(AWord)));
646end;
647
648procedure TskaHunSpellChecker.Loaded;
649begin
650 inherited;
651 SetActive(FActiveOrLoaded);
652end;
653
654procedure TskaHunSpellChecker.ManualChangeDone;
655begin
656 if trim(FTxtBeforeManualEdit) = '' then
657 exit;
658 FUndoList.Add(FTxtBeforeManualEdit);
659 ReStart;
660end;
661
662procedure TskaHunSpellChecker.ManualChangeStart;
663begin
664 FTxtBeforeManualEdit := FSourceEdit.Text;
665end;
666
667function TskaHunSpellChecker.Open: Boolean;
668var
669 CurrentLine: integer;
670 function GetSpecialFolderPath(folder : integer) : string;
671 var
672 path: array [0..MAX_PATH] of char;
673 begin
674 if SUCCEEDED(SHGetFolderPath(0,folder,0,0,@path[0])) then
675 Result := path
676 else
677 Result := '';
678 end;
679begin
680 Result := True;
681 if Active then Exit;
682 Result := False;
683 FpointerHunLib := Nil;
684 if not uHunSpellLib.LoadLibHunspell('') then
685 begin
686 MessageDlg(DLLNotLoaded, mtError, [mbOK],0);
687 Exit;
688 end;
689 FpointerHunLib := uHunSpellLib.hunspell_initialize(
690 PAnsiChar(AnsiString(FAffixFileName)),
691 PAnsiChar(AnsiString(FDictFileName)));
692 Result := Assigned(FpointerHunLib);
693
694 if Result then
695 begin
696 FStatus := ssReady;
697 InformStatusChange;
698 end;
699 if trim(CustDictionaryFile) = '' then
700 CustDictionaryFile := IncludeTrailingPathDelimiter(
701 GetSpecialFolderPath(CSIDL_PERSONAL)) + 'CustomDictionary.txt';
702 if (Result) and (assigned(FCustDict)) then
703 for CurrentLine := 0 to FCustDict.Count - 1 do
704 AddCustomWord(FCustDict[CurrentLine], True);
705end;
706
707procedure TskaHunSpellChecker.SaveForUndo(const Ignoring: Boolean = False);
708begin
709 if Ignoring then
710 FUndoList.Add('$$'+ IntToStr(FIgnore.Count)+'$$')
711 else
712 FUndoList.Add(SourceTextControl.Text);
713end;
714
715procedure TskaHunSpellChecker.SetActive(const Value: Boolean);
716begin
717 if (csDesigning in ComponentState) or (csLoading in ComponentState) then
718 FActiveOrLoaded := Value
719 else
720 if Value then
721 FActiveOrLoaded := Open
722 else
723 Close;
724end;
725
726procedure TskaHunSpellChecker.SetAffixFileName(const Value: string);
727begin
728 Close;
729 FAffixFileName := Value;
730 if (trim(DictionaryFileName) = '') and (trim(value)<>'') then
731 DictionaryFileName := ChangeFileExt(value, '.dic');
732end;
733
734procedure TskaHunSpellChecker.SetCustomDict(const Value: String);
735begin
736 FCustom := Value;
737 if (not (csDesigning in componentState))
738 and (FileExists(Value)) and assigned(FCustDict) then
739 begin
740 FCustDict.Clear;
741 FCustDict.LoadFromFile(Value);
742 end;
743end;
744
745procedure TskaHunSpellChecker.SetDictFileName(const Value: string);
746begin
747 Close;
748 FDictFileName := Value;
749 if (trim(AffixFileName) = '') and (trim(value)<>'') then
750 AffixFileName := ChangeFileExt(value, '.aff');
751end;
752
753procedure TskaHunSpellChecker.SetHighLightEdit(const Value: TEdit);
754begin
755 if FHighlightEdit = Value then
756 exit;
757
758 FHighlightEdit := Value;
759
760 if Active then
761 FHighlightEdit.Text := CurrentWord;
762
763
764end;
765
766Function RichEditWndProc(handle:HWnd;uMsg,wParam,lParam:longint):longint stdcall;
767begin
768 Result := CallWindowProc(OldRichEditWndProc, handle, uMsg, wParam, lParam);
769 if (uMsg=WM_PAINT) and assigned(CurrentMe) then
770 CurrentMe.ShowMisSpelledWord;
771End;
772
773procedure TskaHunSpellChecker.SetSourceEdit(const Value: TRichEdit);
774begin
775 if FSourceEdit = Value then
776 exit;
777
778 FSourceEdit := Value;
779
780 if csDesigning in ComponentState then
781 exit;
782
783 PREditorWndProc:=@RichEditWndProc;
784 //raise the limit of text which could be inserted into this Richedit
785 Value.perform(EM_EXLIMITTEXT, 0, 65535*32);
786 OldRichEditWndProc := pointer(SetWindowLong(Value.handle, GWL_WNDPROC,
787 longint(@RichEditWndProc)));
788end;
789
790end.
Note: See TracBrowser for help on using the repository browser.