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

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

Committing the files for first time to this new branch

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