OSDN Git Service

カチューシャスキンをオプション対応に変更
[gikonavigoeson/gikonavi.git] / HTMLCreate.pas
1 unit HTMLCreate;
2
3 interface
4
5 uses
6         Windows, Messages, SysUtils, Classes, {Graphics,} Controls, {Forms,}
7         ComCtrls, IniFiles, ShellAPI, Math, GikoSystem,
8 {$IF Defined(DELPRO) }
9         SHDocVw,
10         MSHTML,
11 {$ELSE}
12         SHDocVw_TLB,
13         MSHTML_TLB,
14 {$IFEND}
15         {HttpApp,} YofUtils, {URLMon,} BoardGroup, {gzip,} {Dolib,}
16         {bmRegExp,} AbonUnit,   MojuUtils, Setting,
17         ExternalBoardManager, ExternalBoardPlugInMain{,}
18         {Sort,} ,GikoBayesian;
19
20 type
21         THTMLCreate = class(TObject)
22         private
23                 { Private \90é\8c¾ }
24                 anchorLen                       : Integer;
25                 pURLCHARs,pURLCHARe : PChar;
26                 pANCHORs, pANCHORe  : PChar;
27                 pCTAGLs,  pCTAGLe   : PChar;
28                 pCTAGUs,  pCTAGUe   : PChar;
29                 pREF_MARKSs : array[0..9] of PChar;
30                 pREF_MARKSe : array[0..9] of PChar;
31                 constructor Create;
32
33                 function AddBeProfileLink(AID : string; ANum: Integer):string ;
34                 procedure CreateUsePluginHTML(doc: Variant; ThreadItem: TThreadItem; var sTitle: string);
35                 procedure CreateUseSKINHTML(doc: Variant; ThreadItem: TThreadItem; ReadList: TStringList);
36                 procedure CreateUseCSSHTML(doc: Variant; ThreadItem: TThreadItem; ReadList: TStringList; sTitle: string );
37                 procedure CreateDefaultHTML (doc: Variant; ThreadItem: TThreadItem; ReadList: TStringList; sTitle: string );
38                 function ConvertResAnchor(res: string): string;
39                 procedure separateNumber(var st: String; var et: String; const Text, Separator: String);
40         public
41                 { Public \90é\8c¾ }
42                 function AddAnchorTag(s: string): string;
43                 function LoadFromSkin(fileName: string; ThreadItem: TThreadItem; SizeByte: Integer): string;
44                 function SkinedRes(skin: string; Res: TResRec; No: string): string;
45                 function ConvRes(const Body, Bbs, Key,  ParamBBS, ParamKey, ParamStart, ParamTo, ParamNoFirst, ParamTrue : string; DatToHTML: boolean = false): string; overload;
46 //              function ConvRes(const Body, Bbs, Key,  ParamBBS, ParamKey, ParamStart, ParamTo, ParamNoFirst, ParamTrue, FullURL : string): string; overload;
47                 procedure CreateHTML2(doc: Variant; ThreadItem: TThreadItem; var sTitle: string);
48                 procedure CreateHTML3(var html: TStringList; ThreadItem: TThreadItem; var sTitle: string);
49         end;
50
51 var
52         HTMLCreater: THTMLCreate;
53
54 implementation
55
56 const
57         URL_CHAR: string = '0123456789'
58                                                                          + 'abcdefghijklmnopqrstuvwxyz'
59                                                                          + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
60                                                                          + '#$%&()*+,-./:;=?@[]^_`{|}~!''\';
61         ANCHOR_REF      = 'href=';
62         CLOSE_TAGAL = '</a>';
63         CLOSE_TAGAU = '</A>';
64         RES_REF                 = '&gt;&gt;';
65         REF_MARK: array[0..9] of string = ('http://', 'ttp://', 'tp://',
66                                                                          'ms-help://','p://', 'https://',
67                                                                          'www.', 'ftp://','news://','rtsp://');
68
69 constructor THTMLCreate.Create;
70 var
71         j : Integer;
72 begin
73         // + 3 \82Í 'href="' ('"'\82Â\82«)\82È\82Ç\82Ì\83o\83\8a\83G\81[\83V\83\87\83\93\82É\97]\97T\82ð\8e\9d\82½\82¹\82é\82½\82ß
74         anchorLen := Length( ANCHOR_REF ) + 3;
75         pANCHORs  := PChar(ANCHOR_REF);
76         pANCHORe  := pANCHORs + Length(ANCHOR_REF);
77         pURLCHARs := PChar(URL_CHAR);
78         pURLCHARe := pURLCHARs + Length(URL_CHAR);
79         pCTAGLs   := PChar(CLOSE_TAGAL);
80         pCTAGLe   := pCTAGLs + 4;
81         pCTAGUs   := PChar(CLOSE_TAGAU);
82         pCTAGUe   := pCTAGUs + 4;
83         for j := 0 to 9 do begin
84                 pREF_MARKSs[j] := PChar(REF_MARK[j]);
85                 pREF_MARKSe[j] := pREF_MARKSs[j] + Length(REF_MARK[j]);
86         end;
87 end;
88 // \83X\83L\83\93\82ð\93Ç\82Ý\8d\9e\82Ý\81A\92l\82ð\92u\8a·\82·\82é
89 function THTMLCreate.LoadFromSkin(
90         fileName: string;
91         ThreadItem: TThreadItem;
92         SizeByte: Integer
93 ): string;
94 var
95         Skin: TStringList;
96 begin
97
98         Skin := TStringList.Create;
99         try
100                 if FileExists( fileName ) then begin
101                         Skin.LoadFromFile( fileName );
102
103                         // \82â\82è\82©\82½\82ª\8bê\82µ\82¢\82¯\82Ç\81A\83I\83v\83V\83\87\83\93\83_\83C\83A\83\8d\83O\82Ì\83v\83\8c\83r\83\85\81[\97p try
104                         try
105                                 if ThreadItem.ParentBoard <> nil then
106                                         if ThreadItem.ParentBoard.ParentCategory <> nil then
107                                                 CustomStringReplace( Skin, '<BBSNAME/>', ThreadItem.ParentBoard.ParentCategory.ParenTBBS.Title);
108                                         CustomStringReplace( Skin, '<THREADURL/>', ThreadItem.URL);
109                         except end;
110                         CustomStringReplace( Skin, '<BOARDNAME/>', ThreadItem.ParentBoard.Title);
111                         CustomStringReplace( Skin, '<BOARDURL/>', ThreadItem.ParentBoard.URL);
112                         CustomStringReplace( Skin, '<THREADNAME/>', ThreadItem.Title);
113                         CustomStringReplace( Skin, '<SKINPATH/>', GikoSys.Setting.CSSFileName);
114                         CustomStringReplace( Skin, '<GETRESCOUNT/>', IntToStr( ThreadItem.Count - ThreadItem.NewResCount ));
115                         CustomStringReplace( Skin, '<NEWRESCOUNT/>', IntToStr( ThreadItem.NewResCount ));
116                         CustomStringReplace( Skin, '<ALLRESCOUNT/>', IntToStr( ThreadItem.Count ));
117
118                         CustomStringReplace( Skin, '<NEWDATE/>',FormatDateTime('yyyy/mm/dd(ddd) hh:mm', ThreadItem.RoundDate));
119                         CustomStringReplace( Skin, '<SIZEKB/>', IntToStr( Floor( SizeByte / 1024 ) ));
120                         CustomStringReplace( Skin, '<SIZE/>', IntToStr( SizeByte ));
121
122                         //----- \82Æ\82è\82 \82¦\82¸\82©\82¿\82ã\81`\82µ\82á\8cÝ\8a·\97p\81B\83R\83\81\83\93\83g\83A\83E\83g\82µ\82Ä\82à\82æ\82µ
123                         // \82â\82è\82©\82½\82ª\8bê\82µ\82¢\82¯\82Ç\81A\83I\83v\83V\83\87\83\93\83_\83C\83A\83\8d\83O\82Ì\83v\83\8c\83r\83\85\81[\97p try
124                         if GikoSys.Setting.UseKatjushaType then begin
125                                 try
126                                         if ThreadItem.ParentBoard <> nil then
127                                                 if ThreadItem.ParentBoard.ParentCategory <> nil then
128                                                         CustomStringReplace( Skin, '&BBSNAME', ThreadItem.ParentBoard.ParentCategory.ParenTBBS.Title);
129                                                 CustomStringReplace( Skin, '&THREADURL', ThreadItem.URL);
130                                 except end;
131                                 CustomStringReplace( Skin, '&BOARDNAME', ThreadItem.ParentBoard.Title);
132                                 CustomStringReplace( Skin, '&BOARDURL', ThreadItem.ParentBoard.URL);
133                                 CustomStringReplace( Skin, '&THREADNAME', ThreadItem.Title);
134                                 CustomStringReplace( Skin, '&SKINPATH', GikoSys.Setting.CSSFileName);
135                                 CustomStringReplace( Skin, '&GETRESCOUNT', IntToStr( ThreadItem.NewReceive - 1 ));
136                                 CustomStringReplace( Skin, '&NEWRESCOUNT', IntToStr( ThreadItem.NewResCount ));
137                                 CustomStringReplace( Skin, '&ALLRESCOUNT', IntToStr( ThreadItem.AllResCount ));
138
139                                 CustomStringReplace( Skin, '&NEWDATE', FormatDateTime('yyyy/mm/dd(ddd) hh:mm', ThreadItem.RoundDate));
140                                 CustomStringReplace( Skin, '&SIZEKB', IntToStr( Floor( SizeByte / 1024 ) ));
141                                 CustomStringReplace( Skin, '&SIZE', IntToStr( SizeByte ));
142                         end
143                         //----- \82±\82±\82Ü\82Å
144                 end;
145                 Result := Skin.Text;
146         finally
147                 Skin.Free;
148         end;
149 end;
150
151 // \83\8c\83X\82Ì\92l\82ð\92u\8a·\82·\82é
152 function THTMLCreate.SkinedRes(
153         skin: string;
154         Res: TResRec;
155         No: string
156 ): string;
157 var
158         spamminess      : Extended;
159         wordCount               : TWordCount;
160 begin
161
162         wordCount := TWordCount.Create;
163         try
164                 spamminess := Floor( GikoSys.SpamParse(
165                         Res.FName + '<>' + Res.FMailTo + '<>' + Res.FBody, wordCount ) * 100 );
166
167                 Skin := CustomStringReplace( Skin, '<NUMBER/>',
168                         '<a href="menu:' + No + '" name="' + No + '">' + No + '</a>');
169                 Skin := CustomStringReplace( Skin, '<PLAINNUMBER/>', No);
170                 Skin := CustomStringReplace( Skin, '<NAME/>', '<b>' + Res.FName + '</b>');
171                 Skin := CustomStringReplace( Skin, '<MAILNAME/>',
172                         '<a href="mailto:' + Res.FMailTo + '"><b>' + Res.FName + '</b></a>');
173                 Skin := CustomStringReplace( Skin, '<MAIL/>', Res.FMailTo);
174                 Skin := CustomStringReplace( Skin, '<DATE/>', Res.FDateTime);
175                 Skin := CustomStringReplace( Skin, '<MESSAGE/>', Res.FBody);
176                 Skin := CustomStringReplace( Skin, '<SPAMMINESS/>', FloatToStr( spamminess ) );
177                 Skin := CustomStringReplace( Skin, '<NONSPAMMINESS/>', FloatToStr( 100 - spamminess ) );
178
179                 //----- \82©\82¿\82ã\81`\82µ\82á\8cÝ\8a·\97p\81B\83R\83\81\83\93\83g\83A\83E\83g\82µ\82Ä\82à\82æ\82µ
180                 if GikoSys.Setting.UseKatjushaType then begin
181                         Skin := CustomStringReplace( Skin, '&NUMBER',
182                                 '<a href="menu:' + No + '" name="' + No + '">' + No + '</a>');
183                         Skin := CustomStringReplace( Skin, '&PLAINNUMBER', No);
184                         Skin := CustomStringReplace( Skin, '&NAME', '<b>' + Res.FName + '</b>');
185                         Skin := CustomStringReplace( Skin, '&MAILNAME',
186                                 '<a href="mailto:' + Res.FMailTo + '"><b>' + Res.FName + '</b></a>');
187                         Skin := CustomStringReplace( Skin, '&MAIL', Res.FMailTo);
188                         Skin := CustomStringReplace( Skin, '&DATE', Res.FDateTime);
189                         Skin := CustomStringReplace( Skin, '&MESSAGE', Res.FBody);
190                         Skin := CustomStringReplace( Skin, '&SPAMMINESS', FloatToStr( spamminess ) );
191                         Skin := CustomStringReplace( Skin, '&NONSPAMMINESS', FloatToStr( 100 - spamminess ) );
192                 end;
193                 //----- \82±\82±\82Ü\82Å
194
195                 Result := Skin;
196         finally
197                 wordCount.Free;
198         end;
199
200 end;
201 (*************************************************************************
202  *http://\82Ì\95\8e\9a\97ñ\82ðanchor\83^\83O\95t\82«\82É\82·\82é\81B
203  *************************************************************************)
204 function THTMLCreate.AddAnchorTag(s: string): string;
205 var
206         url: string;
207         href: string;
208         i, j, b: Integer;
209         tmp: Integer;
210         idx, idx2: Integer;
211         pos : PChar;
212         pp, pe : PChar;
213 begin
214         Result := '';
215
216         while True do begin
217                 idx  := MaxInt;
218                 idx2 := MaxInt;
219                 pp := PChar(s);
220                 pe := pp + Length(s);
221
222                 for j := 0 to 9 do begin
223                         pos := AnsiStrPosEx(pp, pe, pREF_MARKSs[j], pREF_MARKSe[j]);
224                         if pos <> nil then begin
225                                 tmp := pos - pp + 1;
226                                 idx := Min(tmp, idx);
227                                 if idx = tmp then idx2 := j;   //\82Ç\82Ì\83}\81[\83N\82Å\88ø\82Á\82©\82©\82Á\82½\82©\82ð\95Û\91
228                         end;
229                 end;
230
231                 if idx = MaxInt then begin
232                         //\83\8a\83\93\83N\82ª\96³\82¢\82æ\81B
233                         Result := Result + s;
234                         Break;
235                 end;
236
237                 if (idx > 1) and (idx > anchorLen) and
238                         (AnsiStrPosEx(pp + idx - 1 - anchorLen, pp + idx, pANCHORs, pANCHORe) <> nil) then begin
239                         //\8aù\82É\83\8a\83\93\83N\83^\83O\82ª\82Â\82¢\82Ä\82¢\82é\82Á\82Û\82¢\82Æ\82«\82Í\83\80\83V
240                         //</a></A>\82ð\92T\82·\81A\8f¬\95\8e\9a\82Å\8c©\82Â\82©\82ç\82È\82¯\82ê\82Î\91å\95\8e\9a\82Å\8c\9f\8dõ
241                         pos := AnsiStrPosEx(pp + idx, pe, pCTAGLs, pCTAGLe);
242                         if pos = nil then
243                                 pos := AnsiStrPosEx(pp + idx, pe, pCTAGUs, pCTAGUe);
244                         if pos = nil then
245                                 b := Length(REF_MARK[idx2])
246                         else
247                                 b := pos - pp + 1;
248
249                         Result := Result + Copy(s, 1, idx + b);
250                         Delete(s, 1, idx + b);
251                         Continue;
252                 end;
253
254                 Result := Result + Copy(s, 1, idx - 1);
255                 Delete(s, 1, idx - 1);
256                 b := Length( s ) + 1;
257                 pp      := PChar(s);
258                 for i := 1 to b do begin
259                         pe := AnsiStrPosEx(pURLCHARs, pURLCHARe, pp, pp + 1);
260
261                         if pe = nil then begin
262                                 //URL\82\82á\82È\82¢\95\8e\9a\94­\8c©\81I\82Æ\82©\81A\95\8e\9a\82ª\82È\82­\82È\82Á\82½\81B
263                                 url := Copy(s, 1, i - 1);
264                                 case idx2 of
265                                         1 : href := 'h' + url;
266                                         2 : href := 'ht' + url;
267                                         4 : href := 'htt' + url;
268                                         6 : href := 'http://' + url;
269                                 else
270                                         href := url;
271                                 end;
272
273                                 Result := Result + '<a href="' + href + '" target="_blank">' + url + '</a>';
274                                 Delete(s, 1, i - 1);
275                                 Break;
276                         end;
277                         //\88ê\95\8e\9a\90i\82ß\82é\81B
278                         Inc(pp);
279                 end;
280         end;
281 end;
282
283 //\88ø\90\94\81AAID\81F\91Î\8fÛ\82Æ\82È\82é\93ú\95tID\95\8e\9a\97ñ\81AANum:\83\8c\83X\94Ô AURL\81F\82»\82Ì\83X\83\8c\83b\83h\82ÌURL
284 function THTMLCreate.AddBeProfileLink(AID : string; ANum: Integer):string ;
285 var
286         p : integer;
287         BNum, BMark : string;
288 begin
289         p := AnsiPos('BE:', AnsiUpperCase(AID));
290         if p > 0 then begin
291                 BNum := Copy(AID, p, Length(AID));
292                 AID := Copy(AID, 1, p - 1);
293                 p := AnsiPos('-', BNum);
294                 if p > 0 then begin
295                         BMark := '?' + Trim(Copy(BNum, p + 1, Length(BNum)));
296                         BNum := Copy(BNum, 1, p - 1);
297                 end;
298                 BNum := Trim(BNum);
299                 Result := AID + ' <a href="'  + BNum + '/' + IntToStr(ANum)
300                         + '" target=_blank>' + BMark + '</a>';
301         end else
302                 Result := AID;
303 end;
304 procedure THTMLCreate.separateNumber(var st: String; var et: String; const Text, Separator: String);
305 var
306         p : Integer;
307 begin
308         p := Pos(Separator,Text);
309         if (p > 0 ) then begin
310                 st := Copy(Text, 1, p - 1);
311                 et := Copy(Text, p + Length(Separator), Length(Text));
312         end else begin
313                 st := Text;
314                 et := Text;
315         end;
316 end;
317 (*************************************************************************
318  *
319  * from HotZonu
320  *************************************************************************)
321 function THTMLCreate.ConvRes(const Body, Bbs, Key,
322         ParamBBS, ParamKey, ParamStart, ParamTo, ParamNoFirst, ParamTrue : string;
323         DatToHTML: boolean = false): string;
324 const
325         GT      = '&gt;';
326         SN      = '0123456789';
327         FORMAT_LINK = '<a href="../test/read.cgi?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s" target="_blank">';
328 var
329         i : integer;
330         s : string;
331         sw: boolean;
332         cm: boolean;
333         No: string;
334         oc      : string;
335         pos, pmin : integer;
336         j : integer;
337         token : array[0..5] of string;
338         ch : string;
339         db : boolean;
340         len : integer;
341         rink : string;
342         function addResAnchor(const Left :string) : string;
343         var
344                 st,et : string;
345         begin
346                 //\8fI\92[\82Ü\82Å\8ds\82Á\82Ä\82Ì\8fI\97¹\82©\83`\83F\83b\83N
347                 if j <= len then begin
348                         if db then j := j - 2
349                         else j := j - 1;
350                 end;
351                 //\89½\82à\90\94\8e\9a\82ª\8c©\82Â\82©\82ç\82È\82¢\82Æ\82«
352                 if No = '' then begin
353                         Result := Left + Copy(s, 1, j - 1);
354                 end else begin
355                         separateNumber(st, et, No, '-');
356
357                         if not DatToHTML then begin
358                                 Result := Left + Format(FORMAT_LINK,
359                                                         [ParamBBS, Bbs, ParamKey, Key, ParamStart, st, ParamTo, et, ParamNoFirst, ParamTrue]);
360                         end else begin
361                                 Result := Left + Format('<a href="#%s">', [st]);
362                         end;
363                         Result := Result + Copy(s, 1, j - 1) + '</a>';
364                 end;
365                 Delete(s, 1, j - 1);
366         end;
367
368         procedure getNumberString;
369         begin
370                 while (j <= len) do begin
371                         if (ByteType(s, j) = mbSingleByte) then begin
372                                 //1byte\95\8e\9a
373                                 ch := s[j];
374                                 Inc(j);
375                                 db := false;
376                         end else begin
377                                 //2byte\95\8e\9a
378                                 ch := ZenToHan(Copy(s, j, 2));
379                                 Inc(j, 2);
380                                 db := true;
381                         end;
382
383                         if System.Pos(ch, SN) > 0 then begin
384                                 No := No + ch;
385                         end else if (ch = '-') then begin
386                                 if sw then break;
387                                 if No = '' then break;
388                                 No := No + ch;
389                                 sw := true;
390                         end else begin
391                                 break;
392                         end;
393                 end;
394         end;
395
396         function checkComma : boolean;
397         begin
398                 j := 1;
399                 len := Length(s);
400                 if ((len > 0) and (s[j] = ',')) or ((len > 1) and (ZenToHan(Copy(s, j ,2)) = ','))  then begin
401                         Result := true;
402                         if (ByteType(s, j) = mbSingleByte) then
403                                 Inc(j)
404                         else
405                                 Inc(j, 2);
406                         No := '';
407                 end else begin
408                         Result := false;
409                 end;
410         end;
411 begin
412         //s \82É\96{\95\82ð\91S\95\94\93ü\82ê\82é
413         s        :=     Body;
414         //\8c\8b\89Ê\82ð\83N\83\8a\83A
415         Result   :=     '';
416         //\8c\9f\8dõ\91Î\8fÛ\82Ì\95\8e\9a\97ñ\8cS
417         token[0] := GT + GT;
418         token[1] := GT;
419         token[2] := '\81\84\81\84';
420         token[3] := '\81\84';
421         token[4] := '<a ';
422         token[5] := '<A ';
423
424         //
425         while Length(s) > 2 do begin
426                 pmin := Length(s) + 1;
427                 i       := Length(token);
428                 for j := 0 to 5 do begin
429                         pos := AnsiPos(token[j], s);
430                         if pos <> 0 then begin
431                                 if pos < pmin then begin
432                                         //\82Ç\82ê\82Å\83q\83b\83g\82µ\82½\82©\95Û\91
433                                         i := j;
434                                         //\8dÅ\8f¬\92l\82ð\8dX\90V
435                                         pmin := pos;
436                                 end;
437                         end;
438                 end;
439
440                 //\83q\83b\83g\82µ\82½\95\8e\9a\97ñ\82Ì\88ê\82Â\8eè\91O\82Ü\82Å\8c\8b\89Ê\82É\83R\83s\81[
441                 Result := Result + Copy(s, 1, pmin - 1);
442                 Delete(s, 1, pmin - 1);
443
444                 if i = 6 then begin
445                         //\83q\83b\83g\82È\82µ
446                 end else if (i = 4) or (i = 5) then begin
447                         //'<a ' or '<A' \82Å\83q\83b\83g '</a>' or '</A>' \82Ü\82Å\83R\83s\81[
448                         pmin := AnsiPos('</a>' , s);
449                         pos := AnsiPos('</A>' , s);
450                         if (pmin <> 0) and (pos <> 0) then begin
451                                 if (pmin > pos) then begin
452                                         pmin := pos;
453                                 end;
454                         end else if (pos <> 0) then begin
455                                 pmin := pos;
456                         end;
457                         rink := Copy(s, 1, pmin + 3);
458                         Result := Result + rink;
459                         Delete(s, 1, pmin + 3);
460
461                         pmin := Length(rink);
462                         i       := Length(token);
463                         for j := 0 to 3 do begin
464                                 pos := AnsiPos(token[j], rink);
465                                 if pos <> 0 then begin
466                                         if pos < pmin then begin
467                                                 //\82Ç\82ê\82Å\83q\83b\83g\82µ\82½\82©\95Û\91
468                                                 i := j;
469                                                 //\8dÅ\8f¬\92l\82ð\8dX\90V
470                                                 pmin := pos;
471                                         end;
472                                 end;
473                         end;
474                         // \83\8c\83X\83A\83\93\83J\81[\82ª\8aÜ\82Ü\82ê\82Ä\82¢\82½\82ç,\82ª\91±\82­\8cÀ\82è\83A\83\93\83J\81[\82Æ\82µ\82Ä\88µ\82¤
475                         if i <= 3 then begin
476                                 No := '';
477                                 cm := checkComma;
478                                 len := Length(s);
479                                 while cm do begin
480                                         oc := '';
481                                         No := '';
482                                         sw := false;
483                                         db := false;
484                                         getNumberString;
485                                         Result := addResAnchor(Result);
486                                         cm := checkComma;
487                                 end;
488                         end;
489                 end else begin
490                         //\89½\82©\82µ\82ç\8c©\82Â\82©\82Á\82½\83p\83^\81[\83\93
491                         j := Length(token[i]) + 1;
492                         oc := '';
493                         No := '';
494                         sw := false;
495                         db := false;
496                         len := Length(s);
497                         getNumberString;
498                         Result := addResAnchor(Result);
499                 end;
500         end;
501         Result := Result + s;
502 end;
503
504 function THTMLCreate.ConvertResAnchor(res: string): string;
505 const
506         _HEAD : string = '<a href="../';
507         _TAIL : string = ' target="_blank">';
508         _ST: string = '&st=';
509         _TO: string = '&to=';
510         _STA: string = '&START=';
511         _END: string = '&END=';
512 var
513         i, j, k: Integer;
514         tmp: string;
515 begin
516         Result := '';
517         i := AnsiPos(_HEAD, res);
518         while i <> 0 do begin
519                 Result := Result + Copy(res, 1, i -1);
520                 Delete(res, 1, i - 1);
521                 j := AnsiPos(_TAIL, res);
522                 if j = 0 then begin
523                         Result := Result + res;
524                         Exit;
525                 end;
526                 tmp := Copy(res, 1, j - 1);
527                 Delete(res, 1, j + 16);
528                 if (AnsiPos(_ST, tmp) <> 0) and (AnsiPos(_TO, tmp) <> 0) then begin
529                         Delete(tmp, 1, AnsiPos(_ST, tmp) + 3);
530                         Delete(tmp, AnsiPos(_TO, tmp), Length(tmp));
531                         Result := Result + '<a href="#' + tmp + '">';
532                 end else if (AnsiPos(_STA, tmp) <> 0) and (AnsiPos(_END, tmp) <> 0) then begin
533                         Delete(tmp, 1, AnsiPos(_STA, tmp) + 6);
534                         Delete(tmp, AnsiPos(_END, tmp), Length(tmp));
535                         Result := Result + '<a href="#' + tmp + '">';
536                 end else begin
537                         k := LastDelimiter('/', tmp);
538                         Delete(tmp, 1, k);
539                         if AnsiPos('-', tmp) < AnsiPos('"', tmp) then
540                                 Delete(tmp, AnsiPos('-', tmp), Length(tmp))
541                         else
542                                 Delete(tmp, AnsiPos('"', tmp), Length(tmp));
543
544                         Result := Result + '<a href="#' + tmp + '">';
545                 end;
546                 i := AnsiPos(_HEAD, res);
547         end;
548         Result := Result + res;
549
550 end;
551
552 //Plugin\82ð\97\98\97p\82·\82éBoard\82Ì\83X\83\8c\83b\83h\82ÌHTML\82ð\8dì\90¬\82µ\82Ädoc\82É\8f\91\82«\8d\9e\82Þ
553 procedure THTMLCreate.CreateUsePluginHTML(doc: Variant; ThreadItem: TThreadItem; var sTitle: string);
554 var
555         i: integer;
556         NewReceiveNo: Integer;
557         boardPlugIn : TBoardPlugIn;
558         UserOptionalStyle: string;
559 begin
560         //===== \83v\83\89\83O\83C\83\93\82É\82æ\82é\95\\8e¦
561         boardPlugIn             := ThreadItem.ParentBoard.BoardPlugIn;
562         NewReceiveNo    := ThreadItem.NewReceive;
563         // \83t\83H\83\93\83g\82â\83T\83C\83Y\82Ì\90Ý\92è
564         UserOptionalStyle := GikoSys.SetUserOptionalStyle;
565         try
566                 doc.open;
567                 // \83w\83b\83_
568                 doc.Write( boardPlugIn.GetHeader( DWORD( threadItem ),
569                         '<style type="text/css">body {' + UserOptionalStyle + '}</style>' ) + #13#10 );
570                 doc.Write('<p id="idSearch"></p>' + #13#10 );
571
572                 for i := 0 to threadItem.Count - 1 do begin
573                         // 1 \82Í\95K\82¸\95\\8e¦
574                         if i <> 0 then begin
575                                 // \95\\8e¦\94Í\88Í\82ð\8cÀ\92è
576                                 case GikoSys.ResRange of
577                                 Ord( grrKoko ):
578                                         if ThreadItem.Kokomade > (i + 1) then
579                                                 Continue;
580                                 Ord( grrNew ):
581                                         if NewReceiveNo > (i + 1) then
582                                                 Continue;
583                                 10..65535:
584                                         if (threadItem.Count - i) > GikoSys.ResRange then
585                                                 Continue;
586                                 end;
587                         end;
588
589                         // \90V\92\85\83}\81[\83N
590                         if (NewReceiveNo = (i + 1)) or ((NewReceiveNo = 0) and (i = 0)) then begin
591                                 try
592                                         if GikoSys.Setting.UseSkin then begin
593                                                 if FileExists( GikoSys.GetSkinNewmarkFileName ) then
594                                                         doc.Write( LoadFromSkin( GikoSys.GetSkinNewmarkFileName, ThreadItem, ThreadItem.Size ) + #13#10 )
595                                                 else
596                                                         doc.Write( '<a name="new"></a>' + #13#10 );
597                                         end else if GikoSys.Setting.UseCSS then begin
598                                                 doc.Write('<a name="new"></a><div class="new">\90V\92\85\83\8c\83X <span class="newdate">' + FormatDateTime('yyyy/mm/dd(ddd) hh:mm', ThreadItem.RoundDate) + '</span></div>' + #13#10);
599                                         end else begin
600                                                 doc.Write('</dl>');
601                                                 doc.Write('<a name="new"></a>');
602                                                 doc.Write('<table width="100%" bgcolor="#3333CC" cellpadding="0" cellspacing="1"><tr><td align="center" bgcolor="#6666FF" valign="middle"><font size="-1" color="#ffffff"><b>\90V\92\85\83\8c\83X ' + FormatDateTime('yyyy/mm/dd(ddd) hh:mm', ThreadItem.RoundDate) + '</b></font></td></tr></table>');
603                                                 doc.Write('<dl> + #13#10');
604                                         end;
605                                 except
606                                         doc.Write( '<a name="new"></a>' + #13#10);
607                                 end;
608                         end;
609
610                         // \83\8c\83X
611                         doc.Write( boardPlugIn.GetRes( DWORD( threadItem ), i + 1 ) + #13#10 );
612
613                         if ThreadItem.Kokomade = (i + 1) then begin
614                                 // \82±\82±\82Ü\82Å\93Ç\82ñ\82¾
615                                 try
616                                         if GikoSys.Setting.UseSkin then begin
617                                                 if FileExists( GikoSys.GetSkinBookmarkFileName ) then
618                                                         doc.Write( LoadFromSkin( GikoSys.GetSkinBookmarkFileName, ThreadItem, ThreadItem.Size ) + #13#10 )
619                                                 else
620                                                         doc.Write( '<a name="koko"></a>' + #13#10 );
621                                         end else if GikoSys.Setting.UseCSS then begin
622                                                 doc.Write('<a name="koko"></a><div class="koko">\83R\83R\82Ü\82Å\93Ç\82ñ\82¾</div>' + #13#10 );
623                                         end else begin
624                                                 doc.Write('</dl>');
625                                                 doc.Write('<a name="koko"></a><table width="100%" bgcolor="#55AA55" cellpadding="0" cellspacing="1"><tr><td align="center" bgcolor="#77CC77" valign="middle"><font size="-1" color="#ffffff"><b>\83R\83R\82Ü\82Å\93Ç\82ñ\82¾</b></font></td></tr></table>');
626                                                 doc.Write('<dl>' + #13#10 );
627                                         end;
628                                 except
629                                         doc.Write( '<a name="koko"></a>' + #13#10 );
630                                 end;
631                         end;
632                 end;
633
634
635                 // \83X\83L\83\93(\83t\83b\83^)
636                 doc.Write( boardPlugIn.GetFooter( DWORD( threadItem ), '<a name="bottom"></a>' ) + #13#10 );
637         finally
638                 doc.Close;
639         end;
640 end;
641
642
643 procedure THTMLCreate.CreateUseSKINHTML(doc: Variant; ThreadItem: TThreadItem; ReadList: TStringList);
644 var
645         i: integer;
646         No: string;
647         CSSFileName: string;
648         NewReceiveNo: Integer;
649         Res: TResRec;
650         UserOptionalStyle: string;
651         SkinHeader: string;
652         SkinNewRes: string;
653         SkinRes: string;
654         strTmp : string;
655         function ReplaceRes( skin: string ): string;
656         begin
657                 Result := SkinedRes( skin, Res, No );
658         end;
659 begin
660         NewReceiveNo := ThreadItem.NewReceive;
661         // \83t\83H\83\93\83g\82â\83T\83C\83Y\82Ì\90Ý\92è
662         UserOptionalStyle := GikoSys.SetUserOptionalStyle;
663         CSSFileName := GikoSys.GetStyleSheetDir + GikoSys.Setting.CSSFileName;
664         doc.open;
665         try
666                 doc.charset := 'Shift_JIS';
667
668                 // \83X\83L\83\93\82Ì\90Ý\92è
669                 try
670                         SkinHeader := LoadFromSkin( GikoSys.GetSkinHeaderFileName, ThreadItem, ThreadItem.Size);
671                         if Length( UserOptionalStyle ) > 0 then
672                                 SkinHeader := CustomStringReplace( SkinHeader, '</head>',
673                                         '<style type="text/css">body {' + UserOptionalStyle + '}</style></head>');
674                         doc.Write( SkinHeader + #13#10);
675                 except
676                 end;
677
678                 try
679                         SkinNewRes := LoadFromSkin( GikoSys.GetSkinNewResFileName, ThreadItem, ThreadItem.Size);
680                 except
681                 end;
682
683                 try
684                         SkinRes := LoadFromSkin( GikoSys.GetSkinResFileName, ThreadItem, ThreadItem.Size );
685                 except
686                 end;
687
688                 doc.Write('<p id="idSearch"></p>' + #13#10);
689                 doc.Write('<a name="top"></a>' + #13#10);
690
691                 for i := 0 to ReadList.Count - 1 do begin
692                         // 1 \82Í\95K\82¸\95\\8e¦
693                         if i <> 0 then begin
694                                 // \95\\8e¦\94Í\88Í\82ð\8cÀ\92è
695                                 case GikoSys.ResRange of
696                                 Ord( grrKoko ):
697                                         if ThreadItem.Kokomade > (i + 1) then
698                                                 Continue;
699                                 Ord( grrNew ):
700                                         if NewReceiveNo > (i + 1) then
701                                                 Continue;
702                                 10..65535:
703                                         if (threadItem.Count - i) > GikoSys.ResRange then
704                                                 Continue;
705                                 end;
706                         end;
707
708                         // \90V\92\85\83}\81[\83N
709                         if (NewReceiveNo = i + 1) or ((NewReceiveNo = 0) and (i = 0)) then begin
710                                 try
711                                         if FileExists( GikoSys.GetSkinNewmarkFileName ) then
712                                                 doc.Write( LoadFromSkin( GikoSys.GetSkinNewmarkFileName, ThreadItem, ThreadItem.Size )  + #13#10)
713                                         else
714                                                 doc.Write( '<a name="new"></a>' + #13#10 );
715                                 except
716                                         doc.Write( '<a name="new"></a>' + #13#10 );
717                                 end;
718                         end;
719
720                         if (Trim(ReadList[i]) <> '') then begin
721                                 No := IntToStr(i + 1);
722
723                                 Res := DivideStrLine(ReadList[i]);
724                                 Res.FBody := ConvRes(AddAnchorTag(Res.FBody), ThreadItem.ParentBoard.BBSID, ChangeFileExt(ThreadItem.FileName, ''), 'bbs', 'key', 'st', 'to', 'nofirst', 'true');
725                                 Res.FDateTime := AddBeProfileLink(Res.FDateTime, i + 1);
726
727                                 try
728                                         if NewReceiveNo <= (i + 1) then
729                                                 // \90V\92\85\83\8c\83X
730                                                 strTmp := ReplaceRes( SkinNewRes )
731                                         else
732                                                 // \92Ê\8fí\82Ì\83\8c\83X
733                                                 strTmp := ReplaceRes( SkinRes );
734
735                                         doc.Write( strTmp + #13#10 );
736                                 except
737                                 end;
738                         end;
739
740                         if ThreadItem.Kokomade = (i + 1) then begin
741                                 // \82±\82±\82Ü\82Å\93Ç\82ñ\82¾
742                                 try
743                                         if FileExists( GikoSys.GetSkinBookmarkFileName ) then
744                                                 doc.Write( LoadFromSkin( GikoSys.GetSkinBookmarkFileName, ThreadItem, ThreadItem.Size ) + #13#10 )
745                                         else
746                                                 doc.Write( '<a name="koko"></a>' + #13#10 );
747                                 except
748                                         doc.Write( '<a name="koko"></a>' + #13#10 );
749                                 end;
750                         end;
751                 end;
752
753                 doc.Write('<a name="bottom"></a>' + #13#10);
754                 // \83X\83L\83\93(\83t\83b\83^)
755                 try
756                         doc.Write( LoadFromSkin( GikoSys.GetSkinFooterFileName, ThreadItem, ThreadItem.Size ) + #13#10 );
757                 except
758                 end;
759         finally
760                 doc.close;
761         end;
762 end;
763
764 procedure THTMLCreate.CreateUseCSSHTML(doc: Variant; ThreadItem: TThreadItem; ReadList: TStringList; sTitle: string );
765 var
766         i: integer;
767         No: string;
768         CSSFileName: string;
769         NewReceiveNo: Integer;
770         Res: TResRec;
771         UserOptionalStyle: string;
772 begin
773         doc.open;
774         try
775                 doc.charset := 'Shift_JIS';
776                 NewReceiveNo := ThreadItem.NewReceive;
777                 // \83t\83H\83\93\83g\82â\83T\83C\83Y\82Ì\90Ý\92è
778                 UserOptionalStyle := GikoSys.SetUserOptionalStyle;
779                 CSSFileName := GikoSys.GetStyleSheetDir + GikoSys.Setting.CSSFileName;
780                 if GikoSys.Setting.UseCSS and FileExists(CSSFileName) then begin
781                         //CSS\8eg\97p
782                         doc.Write('<html><head>' + #13#10);
783                         doc.Write('<meta http-equiv="Content-type" content="text/html; charset=Shift_JIS">' + #13#10);
784                         doc.Write('<title>' + sTitle + '</title>' + #13#10);
785                         doc.Write('<link rel="stylesheet" href="'+CSSFileName+'" type="text/css">' + #13#10);
786                         if Length( UserOptionalStyle ) > 0 then
787                                 doc.Write('<style type="text/css">body {' + UserOptionalStyle + '}</style>' + #13#10);
788                         doc.Write('</head>' + #13#10);
789                         doc.Write('<body>' + #13#10);
790                         doc.Write('<a name="top"></a>' + #13#10);
791                         doc.Write('<p id="idSearch"></p>' + #13#10);
792                         doc.Write('<div class="title">' + sTitle + '</div>' + #13#10);
793                         for i := 0 to ReadList.Count - 1 do begin
794                                 // 1 \82Í\95K\82¸\95\\8e¦
795                                 if i <> 0 then begin
796                                         // \95\\8e¦\94Í\88Í\82ð\8cÀ\92è
797                                         case GikoSys.ResRange of
798                                         Ord( grrKoko ):
799                                                 if ThreadItem.Kokomade > (i + 1) then
800                                                         Continue;
801                                         Ord( grrNew ):
802                                                 if NewReceiveNo > (i + 1) then
803                                                         Continue;
804                                         10..65535:
805                                                 if (threadItem.Count - i) > GikoSys.ResRange then
806                                                         Continue;
807                                         end;
808                                 end;
809
810                                 if (NewReceiveNo = (i + 1)) or ((NewReceiveNo = 0) and (i = 0)) then begin
811                                         doc.Write('<a name="new"></a><div class="new">\90V\92\85\83\8c\83X <span class="newdate">' + FormatDateTime('yyyy/mm/dd(ddd) hh:mm', ThreadItem.RoundDate) + '</span></div>' + #13#10);
812                                 end;
813
814                                 if (Trim(ReadList[i]) <> '') then begin
815                                         No := IntToStr(i + 1);
816                                         Res := DivideStrLine(ReadList[i]);
817                                         Res.FBody := ConvRes(AddAnchorTag(Res.FBody), ThreadItem.ParentBoard.BBSID, ChangeFileExt(ThreadItem.FileName, ''), 'bbs', 'key', 'st', 'to', 'nofirst', 'true');
818                                         Res.FDateTime := AddBeProfileLink(Res.FDateTime, i + 1);
819                                         if Res.FMailTo = '' then
820                                                 doc.Write('<a name="' + No + '"></a>'
821                                                                         + '<div class="header"><span class="no"><a href="menu:' + No + '">' + No + '</a></span> '
822                                                                         + '<span class="name_label">\96¼\91O\81F</span> '
823                                                                         + '<span class="name"><b>' + Res.FName + '</b></span> '
824                                                                         + '<span class="date_label">\93\8a\8de\93ú\81F</span> '
825                                                                         + '<span class="date">' + Res.FDateTime+ '</span></div>'
826                                                                         + '<div class="mes">' + Res.FBody + ' </div>' + #13#10)
827                                         else if GikoSys.Setting.ShowMail then
828                                                 doc.Write('<a name="' + No + '"></a>'
829                                                                         + '<div class="header"><span class="no"><a href="menu:' + No + '">' + No + '</a></span>'
830                                                                         + '<span class="name_label"> \96¼\91O\81F </span>'
831                                                                         + '<a class="name_mail" href="mailto:' + Res.FMailTo + '">'
832                                                                         + '<b>' + Res.FName + '</b></a><span class="mail"> [' + Res.FMailTo + ']</span>'
833                                                                         + '<span class="date_label"> \93\8a\8de\93ú\81F</span>'
834                                                                         + '<span class="date"> ' + Res.FDateTime+ '</span></div>'
835                                                                         + '<div class="mes">' + Res.FBody + ' </div>' + #13#10)
836                                         else
837                                                 doc.Write('<a name="' + No + '"></a>'
838                                                                         + '<div class="header"><span class="no"><a href="menu:' + No + '">' + No + '</a></span>'
839                                                                         + '<span class="name_label"> \96¼\91O\81F </span>'
840                                                                         + '<a class="name_mail" href="mailto:' + Res.FMailTo + '">'
841                                                                         + '<b>' + Res.FName + '</b></a>'
842                                                                         + '<span class="date_label"> \93\8a\8de\93ú\81F</span>'
843                                                                         + '<span class="date"> ' + Res.FDateTime+ '</span></div>'
844                                                                         + '<div class="mes">' + Res.FBody + ' </div>' + #13#10);
845                                 end;
846
847                                 if ThreadItem.Kokomade = (i + 1) then begin
848                                         doc.Write('<a name="koko"></a><div class="koko">\83R\83R\82Ü\82Å\93Ç\82ñ\82¾</div>' + #13#10);
849                                 end;
850
851                         end;
852
853                         doc.Write('<a name="bottom"></a>' + #13#10);
854                         doc.Write('<a name="last"></a>' + #13#10);
855                         doc.Write('</body></html>' + #13#10);
856                 end;
857         finally
858                 doc.Close;
859         end;
860 end;
861
862 procedure THTMLCreate.CreateDefaultHTML (doc: Variant; ThreadItem: TThreadItem; ReadList: TStringList; sTitle: string );
863 var
864         i: integer;
865         No: string;
866         NewReceiveNo: Integer;
867         Res: TResRec;
868 begin
869         doc.open;
870         try
871                 doc.charset := 'Shift_JIS';
872                 NewReceiveNo := ThreadItem.NewReceive;
873                 doc.Write('<html><head>' + #13#10);
874                 doc.Write('<meta http-equiv="Content-type" content="text/html; charset=Shift_JIS">' + #13#10);
875                 doc.Write('<title>' + sTitle + '</title></head>' + #13#10);
876                 doc.Write('<body TEXT="#000000" BGCOLOR="#EFEFEF" link="#0000FF" alink="#FF0000" vlink="#660099">' + #13#10);
877                 doc.Write('<a name="top"></a>' + #13#10);
878                 doc.Write('<font size=+1 color="#FF0000">' + sTitle + '</font>' + #13#10);
879                 doc.Write('<dl>' + #13#10);
880                 doc.Write('<p id="idSearch"></p>' + #13#10);
881                 for i := 0 to ReadList.Count - 1 do begin
882                         // 1 \82Í\95K\82¸\95\\8e¦
883                         if i <> 0 then begin
884                                 // \95\\8e¦\94Í\88Í\82ð\8cÀ\92è
885                                 case GikoSys.ResRange of
886                                 Ord( grrKoko ):
887                                         if ThreadItem.Kokomade > (i + 1) then
888                                                 Continue;
889                                 Ord( grrNew ):
890                                         if NewReceiveNo > (i + 1) then
891                                                 Continue;
892                                 10..65535:
893                                         if (threadItem.Count - i) > GikoSys.ResRange then
894                                                 Continue;
895                                 end;
896                         end;
897
898                         if (NewReceiveNo = (i + 1)) or ((NewReceiveNo = 0) and (i = 0)) then begin
899                                 doc.Write('</dl>' + #13#10);
900                                 doc.Write('<a name="new"></a>' + #13#10);
901                                 doc.Write('<table width="100%" bgcolor="#3333CC" cellpadding="0" cellspacing="1"><tr><td align="center" bgcolor="#6666FF" valign="middle"><font size="-1" color="#ffffff"><b>\90V\92\85\83\8c\83X ' + FormatDateTime('yyyy/mm/dd(ddd) hh:mm', ThreadItem.RoundDate) + '</b></font></td></tr></table>' + #13#10);
902                                 doc.Write('<dl>' + #13#10);
903                         end;
904
905                         if (Trim(ReadList[i]) <> '') then begin
906                                 No := IntToStr(i + 1);
907                                 Res := DivideStrLine(ReadList[i]);
908                                 Res.FBody := ConvRes(AddAnchorTag(Res.FBody), ThreadItem.ParentBoard.BBSID, ChangeFileExt(ThreadItem.FileName, ''), 'bbs', 'key', 'st', 'to', 'nofirst', 'true');
909                                 Res.FDateTime := AddBeProfileLink(Res.FDateTime, i + 1);
910                                 if Res.FMailTo = '' then
911                                         doc.Write('<a name="' + No + '"></a><dt><a href="menu:' + No + '">' + No + '</a> \96¼\91O\81F<font color="forestgreen"><b> ' + Res.FName + ' </b></font> \93\8a\8de\93ú\81F <span class="date">' + Res.FDateTime+ '</span><br><dd>' + Res.Fbody + ' <br><br><br>' + #13#10)
912                                 else if GikoSys.Setting.ShowMail then
913                                         doc.Write('<a name="' + No + '"></a><dt><a href="menu:' + No + '">' + No + '</a> \96¼\91O\81F<a href="mailto:' + Res.FMailTo + '"><b> ' + Res.FName + ' </B></a> [' + Res.FMailTo + '] \93\8a\8de\93ú\81F <span class="date">' + Res.FDateTime+ '</span><br><dd>' + Res.Fbody + ' <br><br><br>' + #13#10)
914                                 else
915                                         doc.Write('<a name="' + No + '"></a><dt><a href="menu:' + No + '">' + No + '</a> \96¼\91O\81F<a href="mailto:' + Res.FMailTo + '"><b> ' + Res.FName + ' </B></a> \93\8a\8de\93ú\81F <span class="date">' + Res.FDateTime+ '</span><br><dd>' + Res.Fbody + ' <br><br><br>' + #13#10);
916                         end;
917                         if ThreadItem.Kokomade = (i + 1) then begin
918                                 doc.Write('</dl>' + #13#10);
919                                 doc.Write('<a name="koko"></a><table width="100%" bgcolor="#55AA55" cellpadding="0" cellspacing="1"><tr><td align="center" bgcolor="#77CC77" valign="middle"><font size="-1" color="#ffffff"><b>\83R\83R\82Ü\82Å\93Ç\82ñ\82¾</b></font></td></tr></table>' + #13#10);
920                                 doc.Write('<dl>' + #13#10);
921                         end;
922                 end;
923                 doc.Write('</dl>' + #13#10);
924                 doc.Write('<a name="bottom"></a>' + #13#10);
925                 doc.Write('</body></html>' + #13#10);
926         finally
927                 doc.Close;
928         end;
929 end;
930
931 procedure THTMLCreate.CreateHTML2(doc: Variant; ThreadItem: TThreadItem; var sTitle: string);
932 var
933         ReadList: TStringList;
934         CSSFileName: string;
935         FileName: string;
936         Res: TResRec;
937 {$IFDEF DEBUG}
938         st, rt: Cardinal;
939 {$ENDIF}
940 begin
941 {$IFDEF DEBUG}
942         Writeln('Create HTML');
943         st := GetTickCount;
944 {$ENDIF}
945         if ThreadItem <> nil then begin
946                 if ThreadItem.ParentBoard.IsBoardPlugInAvailable then begin
947                         CreateUsePluginHTML(doc, ThreadItem, sTitle);
948                 end else begin
949                         ShortDayNames[1] := '\93ú';               ShortDayNames[2] := '\8c\8e';
950                         ShortDayNames[3] := '\89Î';               ShortDayNames[4] := '\90\85';
951                         ShortDayNames[5] := '\96Ø';               ShortDayNames[6] := '\8bà';
952                         ShortDayNames[7] := '\93y';
953
954                         ReadList := TStringList.Create;
955                         try
956                                 if ThreadItem.IsLogFile then begin
957                                         FileName := ThreadItem.GetThreadFileName;
958                                         ReadList.LoadFromFile(FileName);
959                                         GikoSys.FAbon.IndividualAbon(ReadList, ChangeFileExt(FileName,'.NG'));
960                                         GikoSys.FAbon.Execute(ReadList);                //       \82 \82Ú\81`\82ñ\82µ\82Ä
961                                         GikoSys.FSelectResFilter.Execute(ReadList); //\83\8c\83X\82Ì\83t\83B\83\8b\83^\83\8a\83\93\83O\82ð\82·\82é
962                                         if ThreadItem.Title = '' then begin
963                                                 Res := DivideStrLine(ReadList[0]);
964                                                 sTitle := Res.FTitle;
965                                         end else
966                                                 sTitle := ThreadItem.Title
967                                 end else begin
968                                         sTitle := CustomStringReplace(ThreadItem.Title, '\81\97\81M', ',');
969                                 end;
970
971                                 // \83t\83H\83\93\83g\82â\83T\83C\83Y\82Ì\90Ý\92è
972                                 CSSFileName := GikoSys.GetStyleSheetDir + GikoSys.Setting.CSSFileName;
973                                 if GikoSys.Setting.UseSkin then begin
974                                         CreateUseSKINHTML(doc, ThreadItem, ReadList);
975                                 end else if GikoSys.Setting.UseCSS and FileExists(CSSFileName) then begin
976                                         CreateUseCSSHTML(doc, ThreadItem, ReadList, sTitle);
977                                 end else begin
978                                         CreateDefaultHTML(doc, ThreadItem, ReadList, sTitle);
979                                 end;
980                         finally
981                                 ReadList.Free;
982                         end;
983                 end;
984         end;
985 {$IFDEF DEBUG}
986         rt := GetTickCount - st;
987         Writeln('Done.');
988         Writeln(IntToStr(rt) + ' ms');
989 {$ENDIF}
990 end;
991
992 procedure THTMLCreate.CreateHTML3(var html: TStringList; ThreadItem: TThreadItem; var sTitle: string);
993 var
994         i: integer;
995         No: string;
996         //bufList : TStringList;
997         ReadList: TStringList;
998 //      SaveList: TStringList;
999         CSSFileName: string;
1000         BBSID: string;
1001         FileName: string;
1002         Res: TResRec;
1003         boardPlugIn : TBoardPlugIn;
1004
1005         UserOptionalStyle: string;
1006         SkinHeader: string;
1007         SkinRes: string;
1008         tmp, tmp1: string;
1009         function LoadSkin( fileName: string ): string;
1010         begin
1011                 Result := LoadFromSkin( fileName, ThreadItem, ThreadItem.Size );
1012         end;
1013         function ReplaceRes( skin: string ): string;
1014         begin
1015                 Result := SkinedRes( skin, Res, No );
1016         end;
1017
1018 begin
1019         if ThreadItem <> nil then begin
1020                 CSSFileName := GikoSys.GetStyleSheetDir + GikoSys.Setting.CSSFileName;
1021                 html.Clear;
1022                 html.BeginUpdate;
1023                 //if ThreadItem.IsBoardPlugInAvailable then begin
1024                 if ThreadItem.ParentBoard.IsBoardPlugInAvailable then begin
1025                         //===== \83v\83\89\83O\83C\83\93\82É\82æ\82é\95\\8e¦
1026                         //boardPlugIn           := ThreadItem.BoardPlugIn;
1027                         boardPlugIn             := ThreadItem.ParentBoard.BoardPlugIn;
1028                         // \83t\83H\83\93\83g\82â\83T\83C\83Y\82Ì\90Ý\92è
1029                         UserOptionalStyle := GikoSys.SetUserOptionalStyle;
1030                         try
1031                                 // \95\8e\9a\83R\81[\83h\82Í\83v\83\89\83O\83C\83\93\82É\94C\82¹\82é
1032                                 // \83w\83b\83_
1033                                 tmp := boardPlugIn.GetHeader( DWORD( threadItem ),
1034                                         '<style type="text/css">body {' + UserOptionalStyle + '}</style>' );
1035                                 //\90â\91Î\8eQ\8fÆ\82©\82ç\91\8a\91Î\8eQ\8fÆ\82Ö
1036                                 if GikoSys.Setting.UseSkin then begin
1037                                         tmp1 := './' + GikoSys.Setting.CSSFileName;
1038                                         tmp1 := CustomStringReplace(tmp1, GikoSys.GetConfigDir, '');
1039                                         tmp1 := CustomStringReplace(tmp1, '\', '/');
1040                                         tmp := CustomStringReplace(tmp, ExtractFilePath(GikoSys.Setting.CSSFileName),  tmp1);
1041                                 end else if GikoSys.Setting.UseCSS then begin
1042                                         tmp1 := './' + CSSFileName;
1043                                         tmp1 := CustomStringReplace(tmp1, GikoSys.GetConfigDir, '');
1044                                         tmp1 := CustomStringReplace(tmp1, '\', '/');
1045                                         tmp := CustomStringReplace(tmp, CSSFileName,  tmp1);
1046                                 end;
1047                                 html.Append( tmp );
1048
1049                                 for i := 0 to threadItem.Count - 1 do begin
1050
1051                                         // \83\8c\83X
1052                                         html.Append( ConvertResAnchor(boardPlugIn.GetRes( DWORD( threadItem ), i + 1 )) );
1053
1054                                 end;
1055                                 // \83X\83L\83\93(\83t\83b\83^)
1056                                 html.Append( boardPlugIn.GetFooter( DWORD( threadItem ), '<a name="bottom"></a>' ) );
1057                         finally
1058                         end;
1059                         html.EndUpdate;
1060                         //Exit;
1061                 end else begin
1062                         ShortDayNames[1] := '\93ú';               ShortDayNames[2] := '\8c\8e';
1063                         ShortDayNames[3] := '\89Î';               ShortDayNames[4] := '\90\85';
1064                         ShortDayNames[5] := '\96Ø';               ShortDayNames[6] := '\8bà';
1065                         ShortDayNames[7] := '\93y';
1066                         BBSID := ThreadItem.ParentBoard.BBSID;
1067                         ReadList := TStringList.Create;
1068                         try
1069                                 if ThreadItem.IsLogFile then begin
1070                                         FileName := ThreadItem.GetThreadFileName;
1071                                         ReadList.LoadFromFile(FileName);
1072                                         GikoSys.FAbon.IndividualAbon(ReadList, ChangeFileExt(FileName,'.NG'));
1073                                         GikoSys.FAbon.Execute(ReadList);                //       \82 \82Ú\81`\82ñ\82µ\82Ä
1074                                         GikoSys.FSelectResFilter.Execute(ReadList); //\83\8c\83X\82Ì\83t\83B\83\8b\83^\83\8a\83\93\83O\82ð\82·\82é
1075                                         Res := DivideStrLine(ReadList[0]);
1076                                         //Res.FTitle := CustomStringReplace(Res.FTitle, '\81\97\81M', ',');
1077                                         sTitle := Res.FTitle;
1078                                 end else begin
1079                                         sTitle := CustomStringReplace(ThreadItem.Title, '\81\97\81M', ',');
1080                                 end;
1081                                 try
1082                                         // \83t\83H\83\93\83g\82â\83T\83C\83Y\82Ì\90Ý\92è
1083                                         UserOptionalStyle := GikoSys.SetUserOptionalStyle;
1084
1085                                         if GikoSys.Setting.UseSkin then begin
1086                                                 // \83X\83L\83\93\8eg\97p
1087                                                 // \83X\83L\83\93\82Ì\90Ý\92è
1088                                                 try
1089                                                         SkinHeader := LoadSkin( GikoSys.GetSkinHeaderFileName );
1090                                                         if Length( UserOptionalStyle ) > 0 then
1091                                                                 SkinHeader := CustomStringReplace( SkinHeader, '</head>',
1092                                                                         '<style type="text/css">body {' + UserOptionalStyle + '}</style></head>');
1093                                                         //\90â\91Î\8eQ\8fÆ\82©\82ç\91\8a\91Î\8eQ\8fÆ\82Ö
1094                                                         tmp1 := './' + GikoSys.Setting.CSSFileName;
1095                                                         tmp1 := CustomStringReplace(tmp1, GikoSys.GetConfigDir, '');
1096                                                         tmp1 := CustomStringReplace(tmp1, '\', '/');
1097                                                         SkinHeader := CustomStringReplace(SkinHeader, ExtractFilePath(GikoSys.Setting.CSSFileName),  tmp1);
1098                                                         html.Append( SkinHeader );
1099                                                 except
1100                                                 end;
1101                                                 try
1102                                                         SkinRes := LoadSkin( GikoSys.GetSkinResFileName );
1103                                                 except
1104                                                 end;
1105                                                 html.Append('<a name="top"></a>');
1106                                                 for i := 0 to ReadList.Count - 1 do begin
1107                                                         if (Trim(ReadList[i]) <> '') then begin
1108                                                                 No := IntToStr(i + 1);
1109
1110                                                                 Res := DivideStrLine(ReadList[i]);
1111                                                                 Res.FBody := AddAnchorTag(Res.FBody);
1112                                                                 Res.FBody := ConvertResAnchor(ConvRes(Res.FBody, ThreadItem.ParentBoard.BBSID, ChangeFileExt(ThreadItem.FileName, ''), 'bbs', 'key', 'st', 'to', 'nofirst', 'true', true));
1113
1114                                                                 try
1115                                                                         html.Append( ReplaceRes( SkinRes ) );
1116                                                                 except
1117                                                                 end;
1118                                                         end;
1119
1120                                                 end;
1121                                                 html.Append('<a name="bottom"></a>');
1122                                                 // \83X\83L\83\93(\83t\83b\83^)
1123                                                 try
1124                                                         html.Append( LoadSkin( GikoSys.GetSkinFooterFileName ) );
1125                                                 except
1126                                                 end;
1127                                         end else if GikoSys.Setting.UseCSS and FileExists(CSSFileName) then begin
1128                                                 //CSS\8eg\97p
1129                                                 //CSSFileName := GetAppDir + CSS_FILE_NAME;
1130                                                 html.Append('<html><head>');
1131                                                 html.Append('<meta http-equiv="Content-type" content="text/html; charset=Shift_JIS">');
1132                                                 html.Append('<title>' + sTitle + '</title>');
1133                                                 //\90â\91Î\8eQ\8fÆ\82©\82ç\91\8a\91Î\8eQ\8fÆ\82Ö
1134                                                 tmp1 := './' + CSSFileName;
1135                                                 tmp1 := CustomStringReplace(tmp1, GikoSys.GetConfigDir, '');
1136                                                 tmp1 := CustomStringReplace(tmp1, '\', '/');
1137
1138                                                 html.Append('<link rel="stylesheet" href="'+tmp1+'" type="text/css">');
1139                                                 if Length( UserOptionalStyle ) > 0 then
1140                                                         html.Append('<style type="text/css">body {' + UserOptionalStyle + '}</style>');
1141                                                 html.Append('</head>');
1142                                                 html.Append('<body>');
1143                                                 html.Append('<a name="top"></a>');
1144                                                 html.Append('<div class="title">' + sTitle + '</div>');
1145                                                 for i := 0 to ReadList.Count - 1 do begin
1146                                                         if (Trim(ReadList[i]) <> '') then begin
1147                                                                 No := IntToStr(i + 1);
1148                                                                 Res := DivideStrLine(ReadList[i]);
1149                                                                 Res.FBody := AddAnchorTag(Res.FBody);
1150                                                                 Res.FBody := ConvertResAnchor(ConvRes(Res.FBody, ThreadItem.ParentBoard.BBSID, ChangeFileExt(ThreadItem.FileName, ''), 'bbs', 'key', 'st', 'to', 'nofirst', 'true', true));
1151                                                                 if Res.FMailTo = '' then
1152                                                                         html.Append('<a name="' + No + '"></a>'
1153                                                                                                         + '<div class="header"><span class="no"><a href="menu:' + No + '">' + No + '</a></span> '
1154                                                                                                         + '<span class="name_label">\96¼\91O\81F</span> '
1155                                                                                                         + '<span class="name"><b>' + Res.FName + '</b></span> '
1156                                                                                                         + '<span class="date_label">\93\8a\8de\93ú\81F</span> '
1157                                                                                                         + '<span class="date">' + Res.FDateTime+ '</span></div>'
1158                                                                                                                                                                                                 + '<div class="mes">' + Res.FBody + ' </div>')
1159                                                                 else if GikoSys.Setting.ShowMail then
1160                                                                         html.Append('<a name="' + No + '"></a>'
1161                                                                                                         + '<div class="header"><span class="no"><a href="menu:' + No + '">' + No + '</a></span>'
1162                                                                                                                                                                                                 + '<span class="name_label"> \96¼\91O\81F </span>'
1163                                                                                                         + '<a class="name_mail" href="mailto:' + Res.FMailTo + '">'
1164                                                                                                         + '<b>' + Res.FName + '</b></a><span class="mail"> [' + Res.FMailTo + ']</span>'
1165                                                                                                         + '<span class="date_label"> \93\8a\8de\93ú\81F</span>'
1166                                                                                                         + '<span class="date"> ' + Res.FDateTime+ '</span></div>'
1167                                                                                                         + '<div class="mes">' + Res.FBody + ' </div>')
1168                                                                 else
1169                                                                         html.Append('<a name="' + No + '"></a>'
1170                                                                                                         + '<div class="header"><span class="no"><a href="menu:' + No + '">' + No + '</a></span>'
1171                                                                                                         + '<span class="name_label"> \96¼\91O\81F </span>'
1172                                                                                                         + '<a class="name_mail" href="mailto:' + Res.FMailTo + '">'
1173                                                                                                         + '<b>' + Res.FName + '</b></a>'
1174                                                                                                         + '<span class="date_label"> \93\8a\8de\93ú\81F</span>'
1175                                                                                                         + '<span class="date"> ' + Res.FDateTime+ '</span></div>'
1176                                                                                                                                                                                                 + '<div class="mes">' + Res.FBody + ' </div>');
1177                                                         end;
1178                                                 end;
1179                                                 html.Append('<a name="bottom"></a>');
1180                                                 html.Append('<a name="last"></a>');
1181                                                 html.Append('</body></html>');
1182                                         end else begin
1183                                                 //CSS\94ñ\8eg\97p
1184                                                 html.Append('<html><head>');
1185                                                 html.Append('<meta http-equiv="Content-type" content="text/html; charset=Shift_JIS">');
1186                                                 html.Append('<title>' + sTitle + '</title></head>');
1187                                                 html.Append('<body TEXT="#000000" BGCOLOR="#EFEFEF" link="#0000FF" alink="#FF0000" vlink="#660099">');
1188                                                 html.Append('<a name="top"></a>');
1189                                                 html.Append('<font size=+1 color="#FF0000">' + sTitle + '</font>');
1190                                                 html.Append('<dl>');
1191                                                 for i := 0 to ReadList.Count - 1 do begin
1192                                                         if (Trim(ReadList[i]) <> '') then begin
1193                                                                 No := IntToStr(i + 1);
1194                                                                 Res := DivideStrLine(ReadList[i]);
1195                                                                 Res.FBody := AddAnchorTag(Res.FBody);
1196                                                                 Res.FBody := ConvertResAnchor(ConvRes(Res.FBody, ThreadItem.ParentBoard.BBSID, ChangeFileExt(ThreadItem.FileName, ''), 'bbs', 'key', 'st', 'to', 'nofirst', 'true', true));
1197                                                                 if Res.FMailTo = '' then
1198                                                                         html.Append('<a name="' + No + '"></a><dt><a href="menu:' + No + '">' + No + '</a> \96¼\91O\81F<font color="forestgreen"><b> ' + Res.FName + ' </b></font> \93\8a\8de\93ú\81F ' + Res.FDateTime+ '<br><dd>' + Res.Fbody + ' <br><br><br>')
1199                                                                 else if GikoSys.Setting.ShowMail then
1200                                                                         html.Append('<a name="' + No + '"></a><dt><a href="menu:' + No + '">' + No + '</a> \96¼\91O\81F<a href="mailto:' + Res.FMailTo + '"><b> ' + Res.FName + ' </B></a> [' + Res.FMailTo + '] \93\8a\8de\93ú\81F ' + Res.FDateTime+ '<br><dd>' + Res.Fbody + ' <br><br><br>')
1201                                                                 else
1202                                                                         html.Append('<a name="' + No + '"></a><dt><a href="menu:' + No + '">' + No + '</a> \96¼\91O\81F<a href="mailto:' + Res.FMailTo + '"><b> ' + Res.FName + ' </B></a> \93\8a\8de\93ú\81F ' + Res.FDateTime+ '<br><dd>' + Res.Fbody + ' <br><br><br>');
1203                                                         end;
1204                                                 end;
1205                                                 html.Append('</dl>');
1206                                                 html.Append('<a name="bottom"></a>');
1207                                                 html.Append('</body></html>');
1208                                         end;
1209                                 finally
1210                                         html.EndUpdate;
1211                                 end;
1212                         finally
1213                                 ReadList.Free;
1214                         end;
1215                 end;
1216         end;
1217 end;
1218
1219 initialization
1220          HTMLCreater := THTMLCreate.Create;
1221
1222 finalization
1223         if HTMLCreater <> nil then begin
1224                 HTMLCreater.Free;
1225                 HTMLCreater := nil;
1226         end;
1227
1228 end.