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

Last change on this file since 1717 was 1715, checked in by healthsevak, 10 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.