OSDN Git Service

まちBBSで削除レスがあるレス番号とスレの件数がずれる不具合を修正
[gikonavigoeson/gikonavi.git] / AbonUnit.pas
1 {
2 NO_ABON                                                 \82 \82Ú\81[\82ñ\8dÏ\82Ý\82Ì\83\8c\83X\82à\95\\8e¦\82·\82é(\8b­\92²\82³\82ê\82é)
3 SPAM_FILTER_ENABLED     \83X\83p\83\80\83t\83B\83\8b\83^\82ð\8b@\94\\82³\82¹\82é
4 }
5
6 unit AbonUnit;
7
8 interface
9 uses
10     Windows,Messages, ShellAPI, SysUtils, Classes,StdCtrls,StrUtils,
11     Forms, Controls, AbonInfo;
12
13 type
14         TIndiviAbon = class( TObject )
15         private
16                 FRes: Integer;
17                 FOption: Integer; // 0:\93§\96¾ 1:\92Ê\8fí\82 \82Ú\81[\82ñ
18         public
19                 property Res            : Integer read FRes                     write FRes;
20                 property Option : Integer       read FOption    write FOption;
21         end;
22
23         TIndiviAbonList = class( TList )
24         private
25                 FFilePath       : string;               //!< \83t\83@\83C\83\8b\83p\83X
26                 FLearned        : Integer;      //!< \83X\83p\83\80\8aw\8fK\8dÏ\82Ý\83\8c\83X No
27
28                 function GetItem( index : Integer ) : TIndiviAbon;
29                 procedure SetItem( index : Integer; value : TIndiviAbon );
30
31         public
32                 destructor Destroy; override;
33
34                 property Items[ index : Integer ] : TIndiviAbon
35                         read GetItem write SetItem; default;
36                 procedure Sort; overload;
37                 procedure LoadFromFile( const filePath : string );
38                 procedure Save;
39         end;
40
41   TAbon = class(TObject)
42   private
43         { Private \90é\8c¾ }
44         Froot : String;
45         Flistpath : String;
46         FNGwordpath : String;
47         Ftokens : array of array of string;
48         FAbonRes : TIndiviAbonList;
49         FAbonString : String;
50         FpAbons : PChar;
51         FpAbone : PChar;
52         FDeleterlo : Boolean; //&rlo;\82ð\8dí\82é\82© //\92Ç\89Á&lro;\82à\8dí\82é
53         FReplaceul :Boolean ; //<ul>\83^\83O\82ð<br>\83^\83O\82É\92u\8a·\82·\82é\82©
54         FReverse : Boolean ;  //NG\83\8f\81[\83h\82Å\82Ì\82 \82Ú\81`\82ñ\82Ì\8c\8b\89Ê\82ð\94½\93]\82³\82¹\82é\82©
55         FAbonPopupRes : Boolean; //\83\8c\83X\83|\83b\83v\83A\83b\83v\82Ì\8e\9e\82É\82 \82Ú\81[\82ñ\82·\82é\82©
56         FNGwordFileIndex : Integer; //\8c»\8dÝ\93Ç\82Ý\8d\9e\82ñ\82Å\82éNG\83\8f\81[\83h\82ªlist\82Ì\89½\8ds\96Ú\82©
57         FNGwordname : String; //\8c»\8dÝ\93Ç\82Ý\8d\9e\82ñ\82Å\82éNG\83\8f\81[\83h\82Ì\95\\8e¦\96¼
58         FIndividualFileName : String;   //\8cÂ\95Ê\82 \82Ú\81`\82ñ\82Ì\83t\83@\83C\83\8b\96¼
59         FReturnNGwordLineNum : Boolean; //NG\83\8f\81[\83h\82Ì\8ds\90\94\82ð\95Ô\82·\81B
60         FSetNGResAnchor : Boolean; //NG\82É\8aY\93\96\82µ\82½\82Æ\82«\82É\96{\95\82É\82»\82Ì\83\8c\83X\82Ö\82Ì\83\8c\83X\83A\83\93\83J\81[\82ð\82Â\82¯\82é\82©\82Ç\82¤\82©
61         FDeleteSyria: Boolean;  //\83V\83\8a\83A\8cê\83u\83\89\83N\83\89\91Î\8dô\81i&#1792~&#1871\81j
62         FIgnoreKana: Boolean;   //\91S\8ap\94¼\8ap\82Ð\82ç\82ª\82È\83J\83^\83J\83i\82Ì\88á\82¢\82ð\96³\8e\8b\82·\82é\82©
63         procedure SetTokens(index: integer ; argline:String);
64         function Getlistpath() : String;
65         procedure Setlistpath(const Value : String);
66         function LoadListFile(path :String;listStringList : TStringList) : Boolean;
67         function ReadNGwordslist(line : Integer) : Boolean;
68         function LoadFromSetResNumFile(SetResNumFile : String) : Boolean;
69   public
70         { Public \90é\8c¾ }
71         constructor Create; // \83R\83\93\83X\83g\83\89\83N\83^
72         destructor Destroy; override; // \83f\83X\83g\83\89\83N\83^
73         property Deleterlo: Boolean read FDeleterlo write FDeleterlo  default false;
74         property Replaceul: Boolean read FReplaceul write FReplaceul  default false;
75         property Reverse: Boolean read FReverse write FReverse  default false;
76         property AbonString : String read FAbonString write FAbonString;
77         property  AbonPopupRes : Boolean read FAbonPopupRes write FAbonPopupRes default false;
78         property listpath : String read Getlistpath write Setlistpath;
79         property NGwordFileIndex : Integer read FNGwordFileIndex write FNGwordFileIndex default 0;
80         property NGwordname : String read FNGwordname write FNGwordname;
81         property ReturnNGwordLineNum : Boolean read FReturnNGwordLineNum write FReturnNGwordLineNum default false;
82         property SetNGResAnchor : Boolean read FSetNGResAnchor write FSetNGResAnchor default false;
83         property DeleteSyria : Boolean read FDeleteSyria write FDeleteSyria default false;
84         property IgnoreKana: Boolean read FIgnoreKana write FIgnoreKana default false;
85         procedure Setroot(root :String);
86         function Getroot() : String;
87
88         function Getfullpath(argpath : String) : String;
89         procedure SetNGwordpath(path :String);
90         function GetNGwordpath() : String;
91         function LoadFromNGwordFile(path :String) : Boolean;
92         function ReLoadFromNGwordFile() : Boolean;
93         procedure LoadFromStringList( bufstl : TStringList );
94         function CheckAbonPopupRes(line : String; ThreadInfo: TAbonThread) :Boolean;
95         function FindNGwords(const line : String; var NGwordsLineNum : Integer; var Invisible : Boolean; ThreadInfo: TAbonThread) : Boolean;//1\83\89\83C\83\93\82¸\82Â\97p\81B
96         //\82 \82Ú\81`\82ñ\8f\88\97\9d(NG\83\8f\81[\83h\82Å\82Ì\83t\83B\83\8b\83^\83\8a\83\93\83O)
97         procedure Execute(var ThreadStrings : TStringList; ThreadInfo: TAbonThread); overload;
98         procedure Execute(var ResString : String; ResNumber : Integer; ThreadInfo: TAbonThread); overload;      //\8eå\82Éplugin\82©\82ç\82ÌDat To HTML \97p
99
100 {$IFDEF SPAM_FILTER_ENABLED}
101         //! \83X\83p\83\80\83t\83B\83\8b\83^\82Ì\8aw\8fK
102         procedure Learn( resList : TStringList );
103 {$ENDIF}
104         //\8cÂ\95Ê\82 \82Ú\81`\82ñ\82µ\82å\82è
105         procedure IndividualAbon(var ThreadStrings : TStringList; SetResNumFile : String); overload;
106         procedure IndividualAbon(var ResString : String; SetResNumFile : String; ResNumber : Integer); overload;
107         procedure AddIndividualAbon( ResNum : Integer ; option : Integer; SetResNumFile : String);
108         function CheckIndividualAbonList(ResNum : Integer) : Boolean;
109
110         function EditNGwords(Owner: TForm): Boolean;  //NGword.txt\82ð\8aJ\82­\81B
111         function ShowAllTokens() : String;  //\83f\83o\83b\83O\97p
112         //--
113         procedure GoHome();//List\82Ì\82P\8ds\96Ú\82ð\93Ç\82Þ
114         function GoForward() : Boolean; //List\82Ì\88ê\82Â\8e\9f\82ÌNG\83\8f\81[\83h\83t\83@\83C\83\8b\82ð\93Ç\82Ý\8d\9e\82Þ
115         function GoBack() : Boolean; //List\82Ì\88ê\82Â\91O\82ÌNG\83\8f\81[\83h\83t\83@\83C\83\8b\82ð\93Ç\82Ý\8d\9e\82Þ
116         //--
117         function TreatSyria(AString: string): string;
118     //--
119     function AddToken(AString: string; Invisible: Boolean): Boolean;
120   end;
121 var
122         Abon1 :TAbon;
123 const
124         NGwordListFileName : String = 'NGwords.list';
125
126 implementation
127
128 uses MojuUtils, GikoSystem, GikoBayesian, Setting,
129   NgEditor,
130   bmRegExp;
131
132 function InvidiAbonListSort( item1, item2 : Pointer ) : Integer;
133 begin
134
135         Result := TIndiviAbon( item1 ).Res - TIndiviAbon( item2 ).Res;
136
137 end;
138
139 destructor TIndiviAbonList.Destroy;
140 var
141         i : Integer;
142 begin
143
144         for i := 0 to Count - 1 do
145                 if inherited Items[ i ] <> nil then
146                         TObject( inherited Items[ i ] ).Free;
147
148         inherited;
149
150 end;
151
152 function TIndiviAbonList.GetItem( index : Integer ) : TIndiviAbon;
153 begin
154
155         Result := TIndiviAbon( inherited Items[ index ] );
156
157 end;
158
159 procedure TIndiviAbonList.SetItem( index : Integer; value : TIndiviAbon );
160 begin
161
162         inherited Items[ index ] := Pointer( value );
163
164 end;
165
166 procedure TIndiviAbonList.Sort;
167 begin
168
169         inherited Sort( InvidiAbonListSort );
170
171 end;
172
173 procedure TIndiviAbonList.LoadFromFile( const filePath : string );
174 var
175         bufStringList   : TStringList;
176         bufLine                         : string;
177         i                                                       : Integer;
178         item                                    : TIndiviAbon;
179 begin
180
181         if not FileExists( filePath ) then begin
182                 FLearned := 0;
183                 Exit;
184         end;
185
186         FFilePath := filePath;
187         bufStringList := TStringList.Create;
188         try
189                 bufStringList.LoadFromFile( filePath );
190                 if bufStringList.Values[ 'Learned' ] <> '' then begin
191                         FLearned := StrToInt( bufStringList.Values[ 'Learned' ] );
192                         bufStringList.Delete( bufStringList.IndexOfName( 'Learned' ) );
193                 end else begin
194                         FLearned := 0;
195                 end;
196
197                 //\8bó\8ds\8dí\8f\9c
198                 for i := bufStringList.Count-1 downto 0 do begin
199                         if bufStringList.Strings[i] = '' then begin
200                                 bufStringList.Delete(i);
201                         end;
202                 end;
203
204                 //\91ã\93ü
205                 for i := 0 to bufStringList.Count - 1 do begin
206                         bufLine                 := Trim(bufStringList.Strings[i]);
207                         item                            := TIndiviAbon.Create;
208                         item.Res                := StrToInt(Copy(bufLine,1,AnsiPos('-',bufLine)-1));
209                         item.option     := StrToInt(Copy(bufLine,AnsiPos('-',bufLine)+1,1));
210                         Add( item );
211                 end;
212         finally
213                 bufStringList.Free;
214         end;
215
216 end;
217
218 procedure TIndiviAbonList.Save;
219 var
220         bufStringList   : TStringList;
221         i                                                       : Integer;
222 begin
223
224         bufStringList := TStringList.Create;
225         try
226                 bufStringList.Values[ 'Learned' ] := IntToStr( FLearned );
227
228                 for i := 0 to Count - 1 do begin
229                         bufStringList.Add(
230                                 IntToStr( Items[ i ].Res ) + '-' + IntToStr( Items[ i ].Option ) );
231                 end;
232
233                 bufStringList.SaveToFile( FFilePath );
234         finally
235                 bufStringList.Free;
236         end;
237
238 end;
239
240 constructor TAbon.Create;
241 begin
242         // \8f\89\8aú\89»
243         FAbonString := '&nbsp;<>&nbsp;<>&nbsp;<>&nbsp;&nbsp;<><>';
244         FAbonRes := TIndiviAbonList.Create;
245         FpAbons := PChar(FAbonString);
246         FpAbone := FpAbons + Length(FAbonString);
247
248 end;
249
250 destructor TAbon.Destroy;
251 begin
252         FAbonRes.Free;
253         inherited;
254 end;
255 //root\82ÍExe\config\NGwords\83t\83H\83\8b\83_
256 procedure TAbon.Setroot(root :String);
257 var
258         bufStringList : TStringList;
259 begin
260         bufStringList := TStringList.Create;
261         try
262                 if not DirectoryExists(root) then begin
263                         CreateDir(root);
264                 end;
265                 if root[Length(root)] <> '\' then begin
266                         root := root + '\';
267                 end;
268                 Flistpath := root + NGwordListFileName;
269                 LoadListFile(Flistpath, bufStringList);
270         finally
271                 bufStringList.Free;
272         end;
273         Froot := root;
274 end;
275 function TAbon.Getroot() : String;
276 begin
277         Result := Froot;
278 end;
279 //NGwordpath\82ÍNGword.txt\82Ì\83t\83\8b\83p\83X
280 procedure TAbon.SetNGwordpath(path :String);
281 begin
282         FNGwordpath := Getfullpath(path);
283         LoadFromNGwordFile(FNGwordpath);
284 end;
285 function TAbon.GetNGwordpath() : String;
286 begin
287         Result :=  FNGwordpath;
288 end;
289 //\83t\83\8b\83p\83X\82Å\82È\82¯\82ê\82Î\83t\83\8b\83p\83X\82É\82µ\82Ä\95Ô\82·\81B
290 function TAbon.Getfullpath(argpath : String) : String;
291 begin
292         if AnsiPos(':\',argpath) <> 2 then begin  //\83h\83\89\83C\83u\82©\82ç\82Ì\83t\83\8b\83p\83X\82ª\96³\82¯\82ê\82Î
293                 if Getroot() = '' then begin
294                         Result := '';    //root\83p\83X\82ª\90Ý\92è\82³\82ê\82Ä\82È\82¢\82©\8bó\82É\82·\82é
295                 end else begin
296                         if (Froot[Length(Froot)] = '\') and (argpath[1] = '\') then begin  //\90æ\93ª\82Ì\\82ð\8dí\8f\9c
297                                 Delete(argpath,1,1);
298                         end;
299                         Insert( Getroot(), argpath , 1);//root\83p\83X\82ð\91}\93ü
300                         Result := argpath;
301                 end;
302         end else begin
303                 Result := argpath;
304         end;
305
306 end;
307 //NGword\83t\83@\83C\83\8b\82Ì\93Ç\82Ý\8d\9e\82Ý
308 function TAbon.LoadFromNGwordFile(path :String) : boolean;
309 var
310         bufstl : TStringList;
311 begin
312         path := Getfullpath(path);
313         if path = '' then begin
314                 Result := false;
315         end else begin
316
317                 bufstl := TStringList.Create;
318                 try
319                         if not FileExists(path) then begin
320                                 Result := false;
321                                 try
322                                         bufstl.SaveToFile(path);
323                                 except
324                                 end;
325                         end else begin
326                                 bufstl.LoadFromFile(path);
327                                 LoadFromStringList( bufstl );
328                                 Result := true;
329                         end;
330                 finally
331                         bufstl.Free;
332                 end;
333         end;
334
335 end;
336 //NGword\83\8a\83X\83g\93Ç\82Ý\8d\9e\82Ý
337 procedure TAbon.LoadFromStringList( bufstl : TStringList );
338 var
339         i : integer;
340 begin
341         try
342                 for i := bufstl.Count -1  downto 0 do begin
343                         if bufstl.Strings[i] = '' then begin
344                                 bufstl.Delete(i);
345                         end;
346                 end;
347                 SetLength(Ftokens,bufstl.Count);
348                 for i := 0  to bufstl.Count -1 do begin
349                         SetTokens(i , bufstl.Strings[i]);
350                 end;
351
352         except
353                 Exit;
354         end;
355 end;
356 //NGwordpath\82ª\8aù\82É\90Ý\92è\82³\82ê\82Ä\82¢\82é\82Æ\82«\82Ì\83\8a\83\8d\81[\83h\97p\8aÖ\90\94
357 function TAbon.ReLoadFromNGwordFile() : boolean;
358 begin
359         if GetNGwordpath() ='' then begin
360                 Result := false;
361         end else begin
362                 Result := LoadFromNGwordFile( GetNGwordpath() );
363         end;
364 end;
365 function TAbon.Getlistpath() : String;
366 begin
367         Result := Flistpath;
368 end;
369 procedure TAbon.Setlistpath(const Value : String);
370 begin
371         Flistpath := Getfullpath(Value);
372 end;
373 //\88ê\8ds\82Ì\92\86\82Ì\83g\81[\83N\83\93\82ð\90Ø\82è\95ª\82¯\82Ä\83Z\83b\83g
374 procedure TAbon.SetTokens(index: integer ; argline : String);
375 var
376         ret : Integer;
377         bufstl : TStringList;
378         i : Integer;
379         pos : Integer;
380         buftoken : String;
381     RegExp: Boolean;
382     Target: String;
383 begin
384         bufstl := TStringList.Create;
385     RegExp := False;
386         try
387                 if Length(argline) > 0 then begin
388                         pos := AnsiPos(#9,argline);
389                         while pos <> 0 DO begin
390                                 buftoken := Copy(argline,1,pos-1);
391                                 Delete(argline,1,pos);
392                                 if Length(buftoken) > 0 then begin
393                     // \90³\8bK\95\\8c»
394                     if (buftoken = DEF_REGEXP) then begin
395                         RegExp := True;
396                     // \94Â\81E\83X\83\8c\8ew\92è
397                     end else if ((AnsiPos(DEF_THREAD, buftoken) = 1) or
398                                  (AnsiPos(DEF_BOARD,  buftoken) = 1)) and
399                                  (AnsiPos(DEF_END, buftoken) > 1) then begin
400                         Target := buftoken;
401                     // >> \82Å\8en\82Ü\82é\83g\81[\83N\83\93\82Í\83R\83\81\83\93\83g\88µ\82¢\82Å\96³\8e\8b\82·\82é
402                     end else if AnsiPos('>>', buftoken) <> 1 then begin
403                                     bufstl.Append(buftoken);
404                     end;
405                                 end else if ( bufstl.Count = 0 ) then begin
406                                         bufstl.Append('');
407                                 end;
408                                 pos := AnsiPos(#9,argline);
409                         end;
410                         if Length(argline) > 0 then begin
411                 // >> \82Å\8en\82Ü\82é\83g\81[\83N\83\93\82Í\83R\83\81\83\93\83g\88µ\82¢\82Å\96³\8e\8b\82·\82é
412                 if AnsiPos('>>', argline) <> 1 then begin
413                                 bufstl.Append(argline);
414                 end;
415                         end;
416             // \8ae\8eí\8ew\92è\82Ì\8f\87\88Ê\81F\93§\96¾\81¨\94Â\81E\83X\83\8c\81¨\90³\8bK\95\\8c»
417             if (RegExp = True) then begin
418                 if (bufstl.Count > 0) and (bufstl.Strings[0] = '') then
419                     bufstl.Insert(1, DEF_REGEXP)    // \93§\96¾\8ew\92è\82Ì\8cã\82É\90³\8bK\95\\8c»\8ew\92è\82ð\92u\82­
420                 else
421                     bufstl.Insert(0, DEF_REGEXP);   // \90³\8bK\95\\8c»\8ew\92è\82Í\90æ\93ª\82É\92u\82­
422             end;
423             if (Target <> '') then begin
424                 if (bufstl.Count > 0) and (bufstl.Strings[0] = '') then
425                     bufstl.Insert(1, Target)    // \93§\96¾\8ew\92è\82Ì\8cã\82É\94Â\81E\83X\83\8c\8ew\92è\82ð\92u\82­
426                 else
427                     bufstl.Insert(0, Target);   // \94Â\81E\83X\83\8c\8ew\92è\82Í\90æ\93ª\82É\92u\82­
428             end;
429                         ret := bufstl.Count;
430                         SetLength(Ftokens[index],ret);
431                         for i := 0 to ret - 1  do begin
432                 if IgnoreKana then
433                     Ftokens[index][i] := ZenToHan(bufstl.Strings[i])
434                 else
435                     Ftokens[index][i] := bufstl.Strings[i];
436                         end;
437                 end;
438         finally
439                 bufstl.Free;
440         end;
441
442 end;
443 //Debug\97p\82¿\82á\82ñ\82ÆNG\83\8f\81[\83h\82ð\8fE\82¦\82Ä\82¢\82é\82©
444 function TAbon.ShowAllTokens() : String;
445 var
446         i : Integer;
447         j : Integer;
448         ret : String;
449 begin
450         for i := 0 to High(Ftokens) do begin
451                 for j := 0 to High(Ftokens[i]) do begin
452                         ret := ret + Ftokens[i][j];
453                 end;
454         end;
455         Result := ret;
456
457
458
459 end;
460 //NG\83\8f\81[\83h\82ª\8aÜ\82Ü\82ê\82Ä\82¢\82½\82çtrue\82ð\95Ô\82µ\81A\82»\82ÌNG\83\8f\81[\83h\82Ì\8ds\90\94\82ðNGwordsLineNum\82É\93ü\82ê\82Ä\95Ô\82·\81B
461 //\82à\82µ\82à\93§\96¾\82 \82Ú\81`\82ñ\82É\82·\82é\82È\82çInbisible\82ðtrue\82É\82µ\82Ä\95Ô\82·
462 function TAbon.FindNGwords(const line : String; var NGwordsLineNum : Integer; var Invisible : Boolean; ThreadInfo: TAbonThread) : Boolean; //1\83\89\83C\83\93\82¸\82Â\97p\81B
463 var
464         lines : Integer;
465         cells : Integer;
466         hit : Boolean;
467         bufline : String;
468         start : Integer;
469         target : String;
470         pos : PChar;
471         pts, pte : PChar;
472         trgLen : Integer;
473     RegExp: Boolean;
474     AWKStr: TAWKStr;
475         RStart: Integer;
476         RLength: Integer;
477     TokenCnt: Integer;
478     Chk: Integer;
479     CheckTarget: Boolean;
480 begin
481         hit := false;
482         if AnsiStrPosEx(PChar(line), PChar(line)+Length(line), FpAbons, FpAbone) = nil then begin
483                 //\91S\94¼\8ap\82Ð\82ç\83J\83i\96³\8e\8b\82·\82é\82©
484                 if IgnoreKana then
485                         target := ZenToHan(line)
486                 else
487                         target := line;
488
489                 trgLen := Length(target);
490         AWKStr := nil;
491
492                 for lines := 0 to High(Ftokens) do begin
493             if Length(Ftokens[lines]) = 0 then begin
494                 Continue;
495             end;
496                         hit := False;
497                         bufline := target;
498                         pts := PChar(bufline);
499                         pte := pts + trgLen;
500             RegExp := False;
501             Invisible := False;
502             start := 0;
503             CheckTarget := True;
504
505             TokenCnt := Length(Ftokens[lines]);
506             for Chk := 0 to 2 do begin
507                 if (Chk >= TokenCnt) then
508                     Break;
509                 if (Chk = 0) and (Ftokens[lines][0] = '') then begin
510                                 Invisible := True;
511                     start := 1;
512                 end else if ((AnsiPos(DEF_THREAD, Ftokens[lines][Chk]) = 1) or
513                              (AnsiPos(DEF_BOARD,  Ftokens[lines][Chk]) = 1))
514                          and (AnsiPos(DEF_END,    Ftokens[lines][Chk]) > 1) then begin
515                     CheckTarget := ThreadInfo.IsTarget(Ftokens[lines][Chk]);
516                     if (CheckTarget = False) then
517                         Break;
518                     Inc(start);     // \91Î\8fÛ\82Ì\94Â\81E\83X\83\8c
519                 end else if (Ftokens[lines][Chk] = DEF_REGEXP) then begin
520                     RegExp := True; // \90³\8bK\95\\8c»
521                     Inc(start);
522                 end else begin
523                     Break;
524                 end;
525             end;
526             if (CheckTarget = False) then begin     // \91Î\8fÛ\82Ì\94Â\81E\83X\83\8c\82Å\82Í\82È\82¢
527                 Continue;
528             end;
529
530                         hit := True;
531             if (RegExp = True) and (AWKStr = nil) then begin
532                 AWKStr := TAWKStr.Create(nil);
533             end;
534
535                         for cells := start to High(Ftokens[lines]) do begin
536                 if (RegExp = False) then begin
537                     pos := AnsiStrPosEx(pts, pte,
538                             PChar(Ftokens[lines][cells]), PChar(Ftokens[lines][cells]) + Length(Ftokens[lines][cells]));
539                     if pos = nil then begin
540                         hit := false;
541                         break;
542                     end else begin
543                         Delete(bufline, pos - pte + 1, Length(Ftokens[lines][cells]));
544                         pts := PChar(bufline);
545                         pte := pts + Length(bufline);
546                     end;
547                 end else begin
548                     try
549                         AWKStr.RegExp := Ftokens[lines][cells];
550                         if (AWKStr.Match(AWKStr.ProcessEscSeq(target), RStart, RLength) < 1) then
551                             hit := False;   // \83}\83b\83`\82µ\82È\82¢
552                         except
553                         hit := False;
554                     end;
555                     if (hit = False) then
556                         Break;      // 1\82Â\82Å\82à\83}\83b\83`\82µ\82È\82¢\8fê\8d\87\82Í\82 \82Ú\81[\82ñ\82µ\82È\82¢
557                 end;
558                         end;
559                         if hit = true then begin
560                                 NGwordsLineNum := lines + 1;
561                                 break;
562                         end;
563                 end;
564
565         if (AWKStr <> nil) then
566             FreeAndNil(AWKStr);
567         end;
568         Result := hit;
569 end;
570 //\96\96\94ö\82Ì\83u\81[\83\8b\92l\82Ítrue\82¾\82Æ\81ANG\83\8f\81[\83h\82ð\8aÜ\82Þ\82à\82Ì\82¾\82¯\82ð\95Ô\82·\81B
571 procedure TAbon.Execute(var ThreadStrings : TStringList; ThreadInfo: TAbonThread);
572 var
573         i : Integer;
574         NGwordsLine : Integer;
575         bufline : String;
576         invisi : Boolean;
577 begin
578         for i:=0 to ThreadStrings.Count - 1 do begin
579                 NGwordsLine := 0;
580                 if FindNGwords(ThreadStrings.Strings[i], NGwordsLine, invisi, ThreadInfo) <> Reverse  then begin
581                         if invisi = true then begin
582                                 ThreadStrings.Strings[i] := '';
583                         end else begin
584                                 if not ReturnNGwordLineNum and not SetNGResAnchor then begin
585                                         ThreadStrings.Strings[i] := FAbonString;
586                                 end else if not ReturnNGwordLineNum then begin
587                                         ThreadStrings.Strings[i] := Format('&nbsp;<>&nbsp;<>&nbsp;<>&gt;%d<><>',[(i+1)]);
588                                 end else if not SetNGResAnchor then begin
589                                         ThreadStrings.Strings[i] := Format('&nbsp;<>&nbsp;<>&nbsp;<><B> %d \8ds\96Ú\82ÌNG\83\8f\81[\83h\82ª\8aÜ\82Ü\82ê\82Ä\82¢\82Ü\82·\81B</B><><>',[NGwordsLine]);
590                                 end else begin
591                                         ThreadStrings.Strings[i] := Format('&nbsp;<>&nbsp;<>&nbsp;<><B> %d \8ds\96Ú\82ÌNG\83\8f\81[\83h\82ª\8aÜ\82Ü\82ê\82Ä\82¢\82Ü\82·\81B</B>&gt;%d <><>',[NGwordsLine,(i+1)]);
592                                 end;
593                         end;
594                 end else begin
595                         bufline := ThreadStrings.Strings[i];
596                         if Deleterlo = true then begin
597                                 bufline := CustomStringReplace(bufline,'&rlo;','');
598                                 bufline := CustomStringReplace(bufline,'&lro;','');
599                         end;
600                         if Replaceul = true then begin
601                                 bufline := CustomStringReplace( bufline,'<ul>','<br>' );
602                                 bufline := CustomStringReplace( bufline,'</ul>','<br>' );
603                         end;
604                         if DeleteSyria = true then
605                                 bufline := TreatSyria(bufline);
606                         ThreadStrings.Strings[i] := bufline;
607                 end;
608         end;
609 end;
610 procedure TAbon.Execute(var ResString : String; ResNumber : Integer; ThreadInfo: TAbonThread);
611 var
612         NGwordsLine : Integer;
613         bufline : String;
614         invisi : Boolean;
615 begin
616         NGwordsLine := 0;
617         if FindNGwords(ResString, NGwordsLine, invisi, ThreadInfo) <> Reverse  then begin
618                 if invisi = true then begin
619                         ResString := '';
620                 end else begin
621                         if not ReturnNGwordLineNum and not SetNGResAnchor then begin
622                                 ResString := FAbonString;
623                         end else if not ReturnNGwordLineNum then begin
624                                 ResString := Format('&nbsp;<>&nbsp;<>&nbsp;<>&gt;%d<><>',[(ResNumber)]);
625                         end else if not SetNGResAnchor then begin
626                                 ResString := Format('&nbsp;<>&nbsp;<>&nbsp;<><B> %d \8ds\96Ú\82ÌNG\83\8f\81[\83h\82ª\8aÜ\82Ü\82ê\82Ä\82¢\82Ü\82·\81B</B><><>',[NGwordsLine]);
627                         end else begin
628                                 ResString := Format('&nbsp;<>&nbsp;<>&nbsp;<><B> %d \8ds\96Ú\82ÌNG\83\8f\81[\83h\82ª\8aÜ\82Ü\82ê\82Ä\82¢\82Ü\82·\81B</B>&gt;%d <><>',[NGwordsLine,(ResNumber)]);
629                         end;
630                 end;
631         end else begin
632                 bufline := ResString;
633                 if Deleterlo = true then begin
634                         bufline := CustomStringReplace( bufline,'&rlo;','' );
635                         bufline := CustomStringReplace( bufline,'&lro;','' );
636                 end;
637                 if Replaceul = true then begin
638                         bufline := CustomStringReplace( bufline,'<ul>','<br>' );
639                         bufline := CustomStringReplace( bufline,'</ul>','<br>' );
640                 end;
641                 if DeleteSyria = true then
642                         bufline := TreatSyria(bufline);
643                 ResString := bufline;
644         end;
645 end;
646
647
648
649 //****************************************************************************//
650 //\8c»\8dÝ\83Z\83b\83g\82³\82ê\82Ä\82¢\82éNGword.txt\82ð\8aJ\82­
651 function TAbon.EditNGwords(Owner: TForm): Boolean;
652 var
653     Dlg: TNgEdit;
654     ReLoad: Boolean;
655 begin
656     ReLoad := False;
657
658     if (GikoSys.Setting.NGTextEditor = False) then begin
659         Dlg := TNgEdit.Create(Owner);
660
661         Dlg.SetFilePath(FNGwordpath);
662         if (Dlg.ShowModal = mrOk) then begin
663             if (Dlg.GetReload = True) then
664                 ReLoad := True;
665         end;
666
667         Dlg.Free;
668     end else begin
669             ShellExecute(0 ,nil,PChar(FNGwordpath),nil,nil,SW_SHOW);
670     end;
671
672     Result := ReLoad;
673 end;
674 //\83|\83b\83v\83A\83b\83v\97p\94»\92è\8aÖ\90\94
675 function TAbon.CheckAbonPopupRes(line : String; ThreadInfo: TAbonThread) :Boolean;
676 var
677         i: Integer;
678         v: boolean;
679 begin
680         if AbonPopupRes = true then begin
681                 Result := FindNGwords(line, i, v, ThreadInfo);
682         end else begin
683                 Result := false;
684         end;
685 end;
686 //\95¡\90\94\82ÌNG\83\8f\81[\83h\83e\83L\83X\83g\82ð\93Ç\82Ý\8d\9e\82Þ==============================================
687 //List\83t\83@\83C\83\8b\82ð\93Ç\82Ý\8d\9e\82Þ
688 function TAbon.LoadListFile(path :String; listStringList : TStringList) : Boolean;
689 begin
690     try
691         listStringList.LoadFromFile(path);
692         Result := true;
693     except
694         listStringList.Append('\88ê\94Ê=NGword.txt');
695         listStringList.SaveToFile(path);
696         Result := false;
697     end;
698 end;
699 //List\82Ì\88ê\82Â\8e\9f\82ÌNG\83\8f\81[\83h\83t\83@\83C\83\8b\82ð\93Ç\82Ý\8d\9e\82Þ
700 function TAbon.GoForward() : Boolean;
701 begin
702     FNGwordFileIndex := FNGwordFileIndex + 1;
703     Result := ReadNGwordslist(FNGwordFileIndex);
704 end;
705 //List\82Ì\88ê\82Â\91O\82ÌNG\83\8f\81[\83h\83t\83@\83C\83\8b\82ð\93Ç\82Ý\8d\9e\82Þ
706 function TAbon.GoBack() : Boolean;
707 begin
708     FNGwordFileIndex := FNGwordFileIndex -1;
709     Result := ReadNGwordslist(FNGwordFileIndex);
710 end;
711 //List\82Ì\82P\8ds\96Ú\82ð\93Ç\82Þ
712 procedure TAbon.GoHome();
713 begin
714     FNGwordFileIndex := 0;
715     ReadNGwordslist(FNGwordFileIndex);
716 end;
717 //List\82Ìline\8ds\96Ú\82ð\93Ç\82Þ
718 function TAbon.ReadNGwordslist(line : Integer) : Boolean;
719 var
720     liststl : TStringList;
721     linebuf : String;
722 begin
723     liststl := TStringList.Create;
724     try
725         if LoadListFile(Flistpath,liststl) = true then begin
726             if line < 0 then begin
727                 line := liststl.Count - 1;
728                 FNGwordFileIndex := liststl.Count - 1;
729             end else if line > liststl.Count - 1 then begin
730                 line := 0;
731                 FNGwordFileIndex := 0;
732             end;
733             linebuf := liststl.Strings[line];
734             FNGwordname := Copy(linebuf,1,AnsiPos('=',linebuf)-1);
735             Delete(linebuf,1,AnsiPos('=',linebuf));
736             SetNGwordpath(linebuf);
737             Result := true;
738         end else begin
739             Result := false;
740         end
741     finally
742         liststl.Free;
743     end;
744
745 end;
746
747 {$IFDEF SPAM_FILTER_ENABLED}
748 procedure TAbon.Learn( resList : TStringList );
749 var
750         i, j                            : Integer;
751         wordCount       : TWordCount;
752         spamminess      : Extended;
753         indiviAbon      : TIndiviAbon;
754 const
755         SPAM_THRESHOLD = 0.9;
756 begin
757
758         if GikoSys.Setting.SpamFilterAlgorithm = gsfaNone then Exit;
759         j := 0;
760         wordCount := TWordCount.Create;
761         try
762                 if (FAbonRes.FLearned = 0) and (FAbonRes.Count = 0) then begin
763                         // \8f\89\82ß\82Ä\82Ì\8aw\8fK\82©\82Â\8cÂ\95Ê\82 \82Ú\81`\82ñ\82 \82è\82È\82Ì\82Å\81A\8b\8cver\82©\82ç\82Ì\88Ú\8ds\82É\82Â\82«
764                         // \8cÂ\95Ê\82 \82Ú\81`\82ñ\82ð\8eg\82Á\82½\8aw\8fK
765                         FAbonRes.Sort;
766                         for i := 0 to FAbonRes.Count - 1 do begin
767                                 while (j < resList.Count) and (j + 1 < FAbonRes[ j ].Res) do begin
768                                         wordCount.Clear;
769                                         GikoSys.Bayesian.CountWord( resList[ j ], wordCount );
770                                         GikoSys.Bayesian.Learn( wordCount, False );
771                                         Inc( j );
772                                 end;
773                                 if j < resList.Count then begin
774                                         wordCount.Clear;
775                                         GikoSys.Bayesian.CountWord( resList[ j ], wordCount );
776                                         GikoSys.Bayesian.Learn( wordCount, True );
777                                         Inc( j );
778                                 end;
779                         end;
780
781                         while j < resList.Count do begin
782                                 wordCount.Clear;
783                                 GikoSys.Bayesian.CountWord( resList[ j ], wordCount );
784                                 GikoSys.Bayesian.Learn( wordCount, False );
785                                 Inc( j );
786                         end;
787                 end else begin
788                         // \8b\8cver\82©\82ç\82Ì\88Ú\8ds\82Å\82Í\82È\82¢\82Ì\82Å\83\8c\83X\82ð\91S\82Ä\90\84\98_\82Å\8aw\8fK
789                         // \81¦\90\84\98_\82ª\8aÔ\88á\82Á\82Ä\82¢\82é\8fê\8d\87\82Í\83\86\81[\83U\82ª\82 \82Ú\81`\82ñ\82ð\8fC\90³\82·\82é\8e\96\82Å\8aw\8fK\82³\82ê\82é
790                         for j := FAbonRes.FLearned to resList.Count - 1 do begin
791                                 wordCount.Clear;
792                                 spamminess := GikoSys.SpamParse( resList[ j ], wordCount );
793                                 if spamminess >= SPAM_THRESHOLD then begin
794                                         // \83X\83p\83\80
795                                         GikoSys.Bayesian.Learn( wordCount, True );
796                                         indiviAbon := TIndiviAbon.Create;
797                                         indiviAbon.Res := j + 1;
798                                         indiviAbon.Option := 1;
799                                         FAbonRes.Add( indiviAbon );
800                                 end else begin
801                                         // \83n\83\80
802                                         GikoSys.Bayesian.Learn( wordCount, False );
803                                 end;
804                         end;
805                 end;
806
807                 FAbonRes.FLearned := resList.Count;
808                 FAbonRes.Save;
809         finally
810                 wordCount.Free;
811         end;
812
813         FAbonRes.Save;
814         GikoSys.Bayesian.Save;
815
816 end;
817 {$ENDIF}
818
819 //\95¡\90\94\82ÌNG\83\8f\81[\83h\83e\83L\83X\83g\82ð\93Ç\82Ý\8d\9e\82Þ=====\82±\82±\82Ü\82Å=================================
820 //\8cÂ\95Ê\82 \82Ú\81`\82ñ\8eÀ\8ds\8aÖ\90\94
821 procedure TAbon.IndividualAbon(var ThreadStrings : TStringList; SetResNumFile : String);
822 var
823         i : Integer;
824         f : Boolean;
825 begin
826         f := LoadFromSetResNumFile( SetResNumFile );
827         FAbonRes.FFilePath := SetResNumFile;    // Learn \82Í\82Å\95Û\91\82·\82é\82Ì\82Å
828 {$IFDEF SPAM_FILTER_ENABLED}
829         Learn( ThreadStrings );
830 {$ENDIF}
831
832         if f then begin
833                 for i := 0 to FAbonRes.Count - 1 do begin
834                         if (FAbonRes[i].Res <= ThreadStrings.Count) and (FAbonRes[i].Res > 0) then begin
835 {$IFDEF NO_ABON}
836                                 ThreadStrings.Strings[FAbonRes[i].Res-1] :=
837                                         '<font color="red">\82 \82Ú\81`\82ñ\8dÏ\82Ý</font>' +
838                                         ThreadStrings.Strings[FAbonRes[i].Res-1];
839 {$ELSE}
840                                 if FAbonRes[i].option = 0 then begin
841                                         ThreadStrings.Strings[FAbonRes[i].Res-1] := '';
842                                 end else begin
843                                         ThreadStrings.Strings[FAbonRes[i].Res-1] := '\82 \82Ú\81`\82ñ<>\82 \82Ú\81`\82ñ<>\82 \82Ú\81`\82ñ<>\82 \82Ú\81`\82ñ<>';
844                                 end;
845 {$ENDIF}
846                         end;
847                 end;
848         end;
849 end;
850 procedure TAbon.IndividualAbon(var ResString : String; SetResNumFile : String; ResNumber : Integer);
851 var
852         i : Integer;
853 begin
854         if FileExists(SetResNumFile) = true then begin
855         if LoadFromSetResNumFile(SetResNumFile) = true then begin
856                                         for i := 0 to FAbonRes.Count - 1 do begin
857                  if FAbonRes[i].Res = ResNumber then begin
858                         if FAbonRes[i].option = 0 then begin
859                         ResString := '';
860                     end else begin
861                         ResString := '\82 \82Ú\81`\82ñ<>\82 \82Ú\81`\82ñ<>\82 \82Ú\81`\82ñ<>\82 \82Ú\81`\82ñ<>';
862                     end;
863                     Exit;
864                  end;
865             end;
866         end;
867     end else begin
868                                 FIndividualFileName := SetResNumFile;
869                                 FAbonRes.Free;
870                                 FAbonRes := TIndiviAbonList.Create;
871                 end;
872 end;
873
874 //\8cÂ\95Ê\82 \82Ú\81`\82ñ\83t\83@\83C\83\8b\93Ç\82Ý\8d\9e\82Ý\8aÖ\90\94
875 function TAbon.LoadFromSetResNumFile(SetResNumFile : String) : Boolean;
876 begin
877
878         FIndividualFileName := SetResNumFile;
879         FAbonRes.Free;
880         FAbonRes := TIndiviAbonList.Create;
881         if FileExists( SetResNumFile ) then begin
882                 FAbonRes.LoadFromFile( SetResNumFile );
883                 Result := true;
884         end else begin
885                 Result := False;
886         end;
887
888 end;
889 //\8cÂ\95Ê\82 \82Ú\81`\82ñ\83t\83@\83C\83\8b\82É\92Ç\89Á
890 procedure TAbon.AddIndividualAbon( ResNum : Integer ; option : Integer; SetResNumFile : String);
891 var
892         IndividualFile : TStringList;
893         i, j : Integer;
894 begin
895         IndividualFile := TStringList.Create;
896         try
897                 if FileExists(SetResNumFile) then begin
898                         IndividualFile.LoadFromFile(SetResNumFile);
899                         i := -1;
900                         for j := 0 to IndividualFile.Count -1 do begin
901                                 if AnsiPos(IntToStr(ResNum) + '-', IndividualFile[j]) = 1 then begin
902                                         i := j;
903                                         break;
904                                 end;
905                         end;
906                         if i = -1 then
907                                 IndividualFile.Add(IntToStr(ResNum) + '-' + IntToStr(option))
908                         else
909                                 IndividualFile[j] := IntToStr(ResNum) + '-' + IntToStr(option);
910
911                 end else begin
912                         IndividualFile.Add(IntToStr(ResNum) + '-' + IntToStr(option));
913                 end;
914                 IndividualFile.SaveToFile(SetResNumFile);
915         finally
916                 IndividualFile.Free;
917         end;
918 end;
919
920 //\83|\83b\83v\83A\83b\83v\82Ì\94»\92è\97p
921 function TAbon.CheckIndividualAbonList(ResNum : Integer) : Boolean;
922 var
923         i : Integer;
924 begin
925         if (FAbonRes.Count > 0) and (FAbonRes[0].Res <> 0) then begin
926                 for i := 0 to FAbonRes.Count - 1 do begin
927                         if FAbonRes[i].Res = ResNum then begin
928                                 Result := true;
929                                 Exit;
930                         end;
931                 end;
932         end;
933         Result := false;
934
935 end;
936 //\83V\83\8a\83A\8cê\83u\83\89\83N\83\89\91Î\8dô
937 function TAbon.TreatSyria(AString: string): string;
938 const
939         UNI_TAG = '&#';
940 var
941         //count: Integer; //(&#1792~&#1871)
942         ps : PChar;
943         p, pe, s, se : PChar;
944         scode: String;
945         icode: Integer;
946 begin
947
948         Result := '';
949
950         p := PChar(AString);
951         pe := p + Length(AString);
952         s := PChar(UNI_TAG);
953         se := s + Length(UNI_TAG);
954
955         p := AnsiStrPosEx(p, pe, s, se);
956
957         while p <> nil do begin
958                 //&#\82Ì\8eè\91O\82Ü\82Å\83R\83s\81[\82·\82é
959                 Result := Result + Copy(AString, 1, p - PChar(AString));
960                 //&#\82Ì\8eè\91O\82Ü\82Å\8dí\8f\9c\82·\82é
961                 Delete(AString, 1, p - PChar(AString));
962
963                 //AString\82É3\95\8e\9a\88È\8fã\82 \82ê\82Î\8e\9f\82Ì3\95\8e\9a\96Ú\82ð\83`\83F\83b\83N
964                 if Length(AString) > 2 then begin
965                         ps := PChar(AString) + 2;
966                         if (ps^ = 'x') or (ps^ = 'X') then begin
967                                 //16\90i\95\\8bL
968                                 Inc(ps);
969                                 scode := '0x';
970                                 while ((ps^ >= '0') and (ps^ <= '9')) or
971                                         ((ps^ >= 'a') and (ps^ <= 'f')) or
972                                         ((ps^ >= 'A') and (ps^ <= 'F')) do begin
973                                         
974                                         scode := scode + String(ps^);
975                                         Inc(ps);
976                                 end;
977                         end else begin
978                                 //10\90i\95\\8bL
979                                 scode := '';
980                                 while ((ps^ >= '0') and (ps^ <= '9')) do begin
981                                         scode := scode + String(ps^);
982                                         Inc(ps);
983                                 end;
984                         end;
985                         icode := StrToIntDef(scode, 0);
986
987                         //\8dÅ\8cã\82ª;\82Å\95Â\82\82Ä\82¢\82È\82¯\82ê\82Î\81A\88ê\95\8e\9a\91O\82Ü\82Å\82É\82·\82é
988                         if not (ps^ = ';') then
989                                 Dec(ps);
990
991                         //\83V\83\8a\83A\8cê\83u\83\89\83N\83\89\82Ì\82Å\82È\82¢
992             if ( icode < 1758) or
993                 ((icode > 1871) and (icode < 1958)) or
994                 (icode > 1968) then begin
995                 Result := Result + Copy(AString, 1, ps - PChar(AString) + 1);
996             end;
997
998                         Delete(AString, 1, ps - PChar(AString) + 1);
999                 end else begin
1000             //\8cã\82ë\82É\95\8e\9a\82ª\96³\82¢\82Ì\82Å\81A\82»\82Ì\82Ü\82ÜResult\82É\93Ë\82Á\8d\9e\82Þ
1001                         Result := Result + AString;
1002                         AString := '';
1003                 end;
1004                 p := PChar(AString);
1005                 pe := p + Length(AString);
1006                 p := AnsiStrPosEx(p, pe, s, se);
1007         end;
1008
1009     //\8ec\82Á\82½\95\8e\9a\97ñ\82ð\91«\82µ\82Ä\8c\8b\89Ê\82É\82·\82é
1010         Result := Result + AString;
1011 end;
1012
1013 // NG\83\8f\81[\83h\83t\83@\83C\83\8b\82É\92Ç\89Á \92Ç\89Á\82³\82ê\82½\8fê\8d\87\81ATrue\82ª\82©\82¦\82é
1014 function TAbon.AddToken(AString: string; Invisible: Boolean): Boolean;
1015 var
1016         bufStringList : TStringList;
1017     ngword: String;
1018 begin
1019     Result := False;
1020     if FileExists(GetNGwordpath) then begin
1021         bufStringList := TStringList.Create;
1022         try
1023             bufStringList.LoadFromFile(GetNGwordpath);
1024             if (Invisible) then begin
1025                 ngword := #9 + AString;
1026             end else begin
1027                 ngword := AString;
1028             end;
1029             if (bufStringList.IndexOf(ngword) = -1) then begin
1030                 bufStringList.Add(ngword);
1031                 bufStringList.SaveToFile(GetNGwordpath);
1032                 Result := True;
1033             end;
1034         finally
1035             bufStringList.Free;
1036         end;
1037     end;
1038 end;
1039
1040
1041 end.
1042