OSDN Git Service

Setting.txt,head.txt, 板トップ画像をローカルに保存するようにした。
[gikonavigoeson/gikonavi.git] / GikoSystem.pas
1 unit GikoSystem;
2
3 interface
4
5 uses
6         Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
7         ComCtrls, IniFiles, ShellAPI, ActnList, Math,
8 {$IF Defined(DELPRO) }
9         SHDocVw,
10         MSHTML,
11 {$ELSE}
12         SHDocVw_TLB,
13         MSHTML_TLB,
14 {$IFEND}
15         {HttpApp,} YofUtils, URLMon, IdGlobal, IdURI, {Masks,}
16         Setting, BoardGroup, gzip, Dolib, bmRegExp, AbonUnit,
17         MojuUtils, ExternalBoardManager, ExternalBoardPlugInMain;
18
19 type
20         //BBS\83^\83C\83v
21         TGikoBBSType = (gbt2ch);
22         //\83\8d\83O\83^\83C\83v
23         TGikoLogType = (glt2chNew, glt2chOld);
24         //\83\81\83b\83Z\81[\83W\83A\83C\83R\83\93
25         TGikoMessageIcon = (gmiOK, gmiSAD, gmiNG, gmiWhat, gmiNone);
26         //URL\83I\81[\83v\83\93\83u\83\89\83E\83U\83^\83C\83v
27         TGikoBrowserType = (gbtIE, gbtUserApp, gbtAuto);
28
29
30         TStrTokSeparator = set of Char;
31         TStrTokRec = record
32                 Str: string;
33                 Pos: Integer;
34         end;
35
36         //\83C\83\93\83f\83b\83N\83X\83t\83@\83C\83\8b\83\8c\83R\81[\83h
37         TIndexRec = record
38                 FNo: Integer;
39                 FFileName: string;
40                 FTitle: string;
41                 FCount: Integer;
42                 FSize: Integer;
43 //              FRoundNo: Integer;
44                 FRoundDate: TDateTime;
45                 FLastModified: TDateTime;
46                 FKokomade: Integer;
47                 FNewReceive: Integer;
48                 FMishiyou: Boolean;     //\96¢\8eg\97p
49                 FUnRead: Boolean;
50                 FScrollTop: Integer;
51                 //Index Ver 1.01
52                 FAllResCount: Integer;
53                 FNewResCount: Integer;
54                 FAgeSage: TGikoAgeSage;
55         end;
56
57         //\83T\83u\83W\83F\83N\83g\83\8c\83R\81[\83h
58         TSubjectRec = record
59                 FFileName: string;
60                 FTitle: string;
61                 FCount: Integer;
62         end;
63
64         //\83\8c\83X\83\8c\83R\81[\83h
65         TResRec = record
66                 FTitle: string;
67                 FMailTo: string;
68                 FName: string;
69                 FDateTime: string;
70                 FBody: string;
71                 FType: TGikoLogType;
72         end;
73
74         //URLPath\83\8c\83R\81[\83h
75         TPathRec = record
76                 FBBS: string;                           //BBSID
77                 FKey: string;                           //ThreadID
78                 FSt: Int64;                             //\8aJ\8en\83\8c\83X\94Ô
79                 FTo: Int64;                             //\8fI\97¹\83\8c\83X\94Ô
80                 FFirst: Boolean;                //>>1\82Ì\95\\8e¦
81                 FStBegin: Boolean;      //1\81`\95\\8e¦
82                 FToEnd: Boolean;                //\81`\8dÅ\8cã\82Ü\82Å\95\\8e¦
83                 FDone: Boolean;                 //\90¬\8c÷
84         end;
85
86         TGikoSys = class(TObject)
87         private
88                 { Private \90é\8c¾ }
89                 FSetting: TSetting;
90                 FDolib: TDolib;
91                 FAWKStr: TAWKStr;
92                 FOnlyAHundredRes : Boolean;
93
94 //              FExitWrite: TStringList;
95 //              function StrToFloatDef(s: string; Default: Double): Double;
96         public
97                 { Public \90é\8c¾ }
98                 FAbon : TAbon;
99                 FSelectResFilter : TAbon;
100                 constructor Create;
101
102                 destructor Destroy; override;
103                 property OnlyAHundredRes : Boolean read FOnlyAHundredRes write FOnlyAHundredRes;
104 //              function MsgBox(Msg: string; Title: string; Flags: Longint): integer; overload;
105 //              function MsgBox(Handle: THandle; Msg: string; Title: string; Flags: Longint): integer; overload;
106                 function IsNumeric(s: string): boolean;
107                 function IsFloat(s: string): boolean;
108                 function DirectoryExistsEx(const Name: string): Boolean;
109                 function ForceDirectoriesEx(Dir: string): Boolean;
110 //              function GetVersion: string;
111
112                 function GetBoardFileName: string;
113                 function GetCustomBoardFileName: string;
114                 function GetHtmlTempFileName: string;
115                 function GetAppDir: string;
116                 function GetTempFolder: string;
117                 function GetSentFileName: string;
118                 function GetConfigDir: string;
119                 function GetSkinDir: string;
120                 function GetSkinHeaderFileName: string;
121                 function GetSkinFooterFileName: string;
122                 function GetSkinResFileName: string;
123                 function GetSkinNewResFileName: string;
124                 function GetSkinBookmarkFileName: string;
125                 function GetSkinNewmarkFileName: string;
126                 function GetStyleSheetDir: string;
127                 function GetOutBoxFileName: string;
128                 function GetUserAgent: string;
129                                 function GetSambaFileName : string;
130
131                 procedure ReadSubjectFile(Board: TBoard);
132                 procedure CreateThreadDat(Board: TBoard);
133                 procedure WriteThreadDat(Board: TBoard);
134                 function ParseIndexLine(Line: string): TIndexRec;
135                 procedure GetFileList(Path: string; Mask: string; var List: TStringList; SubDir: Boolean; IsPathAdd: Boolean); overload;
136                 procedure GetFileList(Path: string; Mask: string; var List: TStringList; IsPathAdd: Boolean); overload;//\83T\83u\83t\83H\83\8b\83_\82Í\8c\9f\8dõ\82µ\82È\82¢
137                 procedure GetDirectoryList(Path: string; Mask: string; List: TStringList; SubDir: Boolean);
138
139                 procedure CreateHTML2(doc: Variant; ThreadItem: TThreadItem; var sTitle: string);
140                 procedure CreateHTML3(var html: TStringList; ThreadItem: TThreadItem; var sTitle: string);
141                 function AddAnchorTag(s: string): string;
142
143                 function DivideSubject(Line: string): TSubjectRec;
144                 function DivideStrLine(Line: string): TResRec;
145
146                 property Setting: TSetting read FSetting write FSetting;
147                 property Dolib: TDolib read FDolib write FDolib;
148
149                 function UrlToID(url: string): string;
150                 function UrlToServer(url: string): string;
151
152                 function StrTokFirst(const s:string; const sep:TStrTokSeparator; var Rec:TStrTokRec):string;
153                 function StrTokNext(const sep:TStrTokSeparator; var Rec:TStrTokRec): string;
154
155                 function GetFileSize(FileName : string) : longint;
156                 function GetFileLineCount(FileName : string): longint;
157                 function Get2chDate(aDate: TDateTime): string;
158                 function IntToDateTime(val: Int64): TDateTime;
159                 function DateTimeToInt(ADate: TDateTime): Int64;
160
161                 function ReadThreadFile(FileName: string; Line: Integer): string;
162
163                 procedure MenuFont(Font: TFont);
164
165                 function RemoveToken(var s:string; const delimiter:string):string;
166                 function GetTokenIndex(s: string; delimiter: string; index: Integer): string;
167                 function DeleteLink(const s: string): string;
168
169                 function GetShortName(const LongName: string; ALength: integer): string;
170                 function ConvRes(const Body, Bbs, Key,  ParamBBS, ParamKey, ParamStart, ParamTo, ParamNoFirst, ParamTrue : string; DatToHTML: boolean = false): string; overload;
171                 function ConvRes(const Body, Bbs, Key,  ParamBBS, ParamKey, ParamStart, ParamTo, ParamNoFirst, ParamTrue, FullURL : string): string; overload;
172                 function ConvertResAnchor(res: string): string;
173                 function BoolToInt(b: Boolean): Integer;
174                 function IntToBool(i: Integer): Boolean;
175                 function GzipDecompress(ResStream: TStream; ContentEncoding: string): string;
176                 procedure LoadKeySetting(ActionList: TActionList);
177                 procedure SaveKeySetting(ActionList: TActionList);
178                 procedure LoadEditorKeySetting(ActionList: TActionList);
179                 procedure SaveEditorKeySetting(ActionList: TActionList);
180
181                 procedure CreateProcess(const AppPath: string; const Param: string);
182                 procedure OpenBrowser(URL: string; BrowserType: TGikoBrowserType);
183                 function HTMLDecode(const AStr: String): String;
184                 function GetHRefText(s: string): string;
185                 function Is2chHost(Host: string): Boolean;
186                 function Parse2chURL(const url: string; const path: string; const document: string; var BBSID: string; var BBSKey: string): Boolean;
187                 function Parse2chURL2(URL: string): TPathRec;
188                 procedure ParseURI(var URL, Protocol, Host, Path, Document, Port, Bookmark: string);
189                 function GetVersionBuild: Integer;
190                 function        GetBrowsableThreadURL( inURL : string ) : string;
191                 function        GetThreadURL2BoardURL( inURL : string ) : string;
192                 function        Get2chThreadURL2BoardURL( inURL : string ) : string;
193                 function        Get2chBrowsableThreadURL( inURL : string ) : string;
194                 function        Get2chBoard2ThreadURL( inBoard : TBoard; inKey : string ) : string;
195                 procedure ListBoardFile;
196                 procedure ReadBoardFile( bbs : TBBS );
197
198                 function        GetUnknownCategory : TCategory;
199                 function        GetUnknownBoard( inPlugIn : TBoardPlugIn; inURL : string ) : TBoard;
200
201         procedure GetPopupResNumber(URL : string; var stRes, endRes : Int64);
202
203                 // \83X\83L\83\93\82ð\93Ç\82Ý\8d\9e\82Ý\81A\92l\82ð\92u\8a·\82·\82é
204                 function LoadFromSkin( fileName: string; ThreadItem: TThreadItem; SizeByte: Integer ): string;
205         // \83\8c\83X\82Ì\92l\82ð\92u\8a·\82·\82é
206                 function SkinedRes( skin: string; Res: TResRec; No: string ): string;
207
208         //Samba24\82Ì\83t\83@\83C\83\8b\82ª\91\8dÝ\82·\82é\82©\81B\91\8dÝ\82µ\82È\82¢\8fê\8d\87\81Adefault\83t\83@\83C\83\8b\82ðrename\82·\82é
209         procedure SambaFileExists();
210         end;
211
212 var
213         GikoSys: TGikoSys;
214 const
215         //LENGTH_RESTITLE                       = 40;
216         ZERO_DATE: Integer      = 25569;
217         BETA_VERSION_NAME_E = 'beta';
218         BETA_VERSION_NAME_J = 'ÊÞÀ';
219         BETA_VERSION                            = 48;
220         BETA_VERSION_BUILD      = '';                           //debug\94Å\82È\82Ç
221         APP_NAME                                                = 'gikoNavi';
222
223 implementation
224
225 uses
226         Giko, RoundData;
227
228 const
229         FOLDER_INDEX_VERSION                                    = '1.01';
230         USER_AGENT                                                                              = 'Monazilla';
231         DEFAULT_NGWORD_FILE_NAME : String = 'NGword.txt';
232         NGWORDs_DIR_NAME : String               = 'NGwords';
233
234         READ_PATH: string =                     '/test/read.cgi/';
235         OLD_READ_PATH: string =         '/test/read.cgi?';
236         KAKO_PATH: string =                     '/kako/';
237
238 (*************************************************************************
239  *GikoSys\83R\83\93\83X\83g\83\89\83N\83^
240  *************************************************************************)
241 constructor TGikoSys.Create;
242 begin
243         FSetting := TSetting.Create;
244         FDolib := TDolib.Create;
245         FAWKStr := TAWKStr.Create(nil);
246         if DirectoryExists(GetConfigDir) = false then begin
247                 CreateDir(GetConfigDir);
248         end;
249         FAbon := TAbon.Create;
250         FAbon.Setroot(GetConfigDir+NGWORDs_DIR_NAME);
251         FAbon.GoHome;
252         FAbon.ReturnNGwordLineNum := FSetting.ShowNGLinesNum;
253         FAbon.SetNGResAnchor := FSetting.AddResAnchor;
254     FAbon.DeleteSyria := FSetting.DeleteSyria;
255         FAbon.Deleterlo := FSetting.AbonDeleterlo;
256         FAbon.Replaceul := FSetting.AbonReplaceul;
257         FAbon.AbonPopupRes := FSetting.PopUpAbon;
258
259         FSelectResFilter := TAbon.Create;
260         // \8di\82è\8d\9e\82Þ\82Æ\82«\82Í\8bÉ\97Í\88ê\97\97\82ª\8c©\82ç\82ê\82é\82Ù\82¤\82ª\82¢\82¢\82Ì\82Å\91¼\82Í\8a®\91S\82É\8dí\8f\9c
261         FSelectResFilter.AbonString := '';
262         //
263         OnlyAHundredRes := FSetting.OnlyAHundredRes;
264 end;
265
266 (*************************************************************************
267  *GikoSys\83f\83X\83g\83\89\83N\83^
268  *************************************************************************)
269 destructor TGikoSys.Destroy;
270 var
271         i: Integer;
272         FileList: TStringList;
273 begin
274         //\83X\83\8c\83b\83h\83f\81[\83^\83t\83@\83C\83\8b\82ð\8dX\90V
275 //      FlashExitWrite;
276
277 //      FExitWrite.Free;
278         FAWKStr.Free;
279         FSetting.Free;
280         FDolib.Free;
281         FAbon.Free;
282         FSelectResFilter.Free;
283         //\83e\83\93\83|\83\89\83\8aHTML\82ð\8dí\8f\9c
284         FileList := TStringList.Create;
285         try
286                 GetFileList(GetTempFolder, '*.html', FileList, False, True);
287                 for i := 0 to FileList.Count - 1 do begin
288                         DeleteFile(FileList[i]);
289                 end;
290         finally
291                 FileList.Free;
292         end;
293         inherited;
294 end;
295
296 (*************************************************************************
297  *\95\8e\9a\97ñ\90\94\8e\9a\83`\83F\83b\83N
298  *************************************************************************)
299 {$HINTS OFF}
300 function TGikoSys.IsNumeric(s: string): boolean;
301 var
302         e: integer;
303         v: integer;
304 begin
305         Val(s, v, e);
306         Result := e = 0;
307 end;
308 {$HINTS ON}
309
310 (*************************************************************************
311  *\95\8e\9a\97ñ\95\82\93®\8f¬\90\94\93_\90\94\8e\9a\83`\83F\83b\83N
312  *************************************************************************)
313 function TGikoSys.IsFloat(s: string): boolean;
314 var
315         v: Extended;
316 begin
317         Result := TextToFloat(PChar(s), v, fvExtended);
318 end;
319
320 (*************************************************************************
321  *\83{\81[\83h\83t\83@\83C\83\8b\96¼\8eæ\93¾\81i\83p\83X\81{\83t\83@\83C\83\8b\96¼\81j
322  *************************************************************************)
323 function TGikoSys.GetBoardFileName: string;
324 begin
325         Result := Setting.GetBoardFileName;
326 end;
327
328 (*************************************************************************
329  *\83{\81[\83h\83t\83@\83C\83\8b\96¼\8eæ\93¾\81i\83p\83X\81{\83t\83@\83C\83\8b\96¼\81j
330  *************************************************************************)
331 function TGikoSys.GetCustomBoardFileName: string;
332 begin
333         Result := Setting.GetCustomBoardFileName;
334 end;
335
336 (*************************************************************************
337  *\83e\83\93\83|\83\89\83\8a\83t\83H\83\8b\83_\81[\96¼\8eæ\93¾
338  *************************************************************************)
339 function TGikoSys.GetHtmlTempFileName: string;
340 begin
341         Result := Setting.GetHtmlTempFileName;
342 end;
343
344
345 (*************************************************************************
346  *\8eÀ\8ds\83t\83@\83C\83\8b\83t\83H\83\8b\83_\8eæ\93¾
347  *************************************************************************)
348 function TGikoSys.GetAppDir: string;
349 begin
350         Result := Setting.GetAppDir;
351 end;
352
353 (*************************************************************************
354  *TempHtml\83t\83@\83C\83\8b\96¼\8eæ\93¾\81i\83p\83X\81{\83t\83@\83C\83\8b\96¼\81j
355  *************************************************************************)
356 function TGikoSys.GetTempFolder: string;
357 begin
358         Result := Setting.GetTempFolder;
359 end;
360
361 (*************************************************************************
362  *sent.ini\83t\83@\83C\83\8b\96¼\8eæ\93¾\81i\83p\83X\81{\83t\83@\83C\83\8b\96¼\81j
363  *************************************************************************)
364 function TGikoSys.GetSentFileName: string;
365 begin
366         Result := Setting.GetSentFileName;
367 end;
368
369 (*************************************************************************
370  *outbox.ini\83t\83@\83C\83\8b\96¼\8eæ\93¾\81i\83p\83X\81{\83t\83@\83C\83\8b\96¼\81j
371  *************************************************************************)
372 function TGikoSys.GetOutBoxFileName: string;
373 begin
374         Result := Setting.GetOutBoxFileName;
375 end;
376
377 (*************************************************************************
378  *Config\83t\83H\83\8b\83_\8eæ\93¾
379  *************************************************************************)
380 function TGikoSys.GetConfigDir: string;
381 begin
382         Result := Setting.GetConfigDir;
383 end;
384
385 function TGikoSys.GetStyleSheetDir: string;
386 begin
387         Result := Setting.GetStyleSheetDir;
388 end;
389
390 function TGikoSys.GetSkinDir: string;
391 begin
392         Result := Setting.GetSkinDir;
393 end;
394
395 function TGikoSys.GetSkinHeaderFileName: string;
396 begin
397         Result := Setting.GetSkinHeaderFileName;
398 end;
399
400 function TGikoSys.GetSkinFooterFileName: string;
401 begin
402         Result := Setting.GetSkinFooterFileName;
403 end;
404
405 function TGikoSys.GetSkinNewResFileName: string;
406 begin
407         Result := Setting.GetSkinNewResFileName;
408 end;
409
410 function TGikoSys.GetSkinResFileName: string;
411 begin
412         Result := Setting.GetSkinResFileName;
413 end;
414
415 function TGikoSys.GetSkinBookmarkFileName: string;
416 begin
417         Result := Setting.GetSkinBookmarkFileName;
418 end;
419
420 function TGikoSys.GetSkinNewmarkFileName: string;
421 begin
422         Result := Setting.GetSkinNewmarkFileName;
423 end;
424
425 // UserAgent\8eæ\93¾
426 function TGikoSys.GetUserAgent: string;
427 begin
428         if Dolib.Connected then begin
429                 Result := Format('%s %s/%s%d%s', [
430                                                                 Dolib.UserAgent,
431                                                                 APP_NAME,
432                                                                 //MAJOR_VERSION,
433                                                                 //MINOR_VERSION,
434                                                                 BETA_VERSION_NAME_E,
435                                                                 BETA_VERSION,
436                                                                 BETA_VERSION_BUILD]);
437         end else begin
438                 Result := Format('%s/%s %s/%s%d%s', [
439                                                                 USER_AGENT,
440                                                                 Dolib.Version,
441                                                                 APP_NAME,
442                                                                 //MAJOR_VERSION,
443                                                                 //MINOR_VERSION,
444                                                                 BETA_VERSION_NAME_E,
445                                                                 BETA_VERSION,
446                                                                 BETA_VERSION_BUILD]);
447         end;
448 end;
449
450 (*************************************************************************
451  *\82Q\82¿\82á\82ñ\82Ë\82é\95û\8e®\8e\9e\8d\8f\8eæ\93¾
452  *************************************************************************)
453 function TGikoSys.Get2chDate(aDate: TDateTime): string;
454 var
455         d1: TDateTime;
456         d2: TDateTime;
457 begin
458         d1 := EncodeDate(1970, 1, 1);
459         d2 := aDate - EncodeTime(9, 0, 0, 0);
460         //Result := FloatToStr(Trunc((d2 - d1) * 24 * 60 * 60));
461         Result := FloatToStr(Trunc((d2 - d1) * 86400));
462 end;
463
464
465 function TGikoSys.IntToDateTime(val: Int64): TDateTime;
466 var
467         d1: tdatetime;
468         d2: tdatetime;
469 begin
470         d1 := EncodeDate(1970, 1, 1);
471         d2 := val / 86400.0;//(val * 1000) / (24 * 60 * 60 * 1000);
472         Result := d1 + d2;
473 end;
474
475 function TGikoSys.DateTimeToInt(ADate: TDateTime): Int64;
476 var
477         d: TDateTime;
478         c: Currency;
479 begin
480         d := EncodeDate(1970, 1, 1);
481         c := (ADate - d) * 86400; //(ADate - d) * 24 * 60 * 60;
482         Result := Trunc(c);
483 end;
484
485
486 (*************************************************************************
487  *Subject\83t\83@\83C\83\8bRead
488  *************************************************************************)
489 procedure TGikoSys.ReadSubjectFile(Board: TBoard);
490 var
491         ThreadItem: TThreadItem;
492         FileName: string;
493         FileList: TStringList;
494         TmpFileList: TStringList;
495         Index: Integer;
496         sl: TStringList;
497         i: Integer;
498         Rec: TIndexRec;
499         UnRead: Integer;
500         ini: TMemIniFile;
501         ResRec: TResRec;
502         RoundItem: TRoundItem;
503         idx: Integer;
504         usePlugIn : Boolean;
505         tmpStr: string;
506 begin
507         if Board.IsThreadDatRead then
508                 Exit;
509         Board.Clear;
510         UnRead := 0;
511
512         usePlugIn := Board.IsBoardPlugInAvailable;
513
514         FileName := Board.GetFolderIndexFileName;
515
516         FileList := TStringList.Create;
517         FileList.Sorted := True;
518         TmpFileList := TStringList.Create;
519         TmpFileList.Sorted := True;
520
521         //IsLogFile\97pDAT\83t\83@\83C\83\8b\83\8a\83X\83g
522         GetFileList(ExtractFileDir(Board.GetFolderIndexFileName), '*.dat', FileList, False);
523         //\91O\89ñ\88Ù\8fí\8fI\97¹\8e\9e\97pTmp\83t\83@\83C\83\8b\83\8a\83X\83g
524         GetFileList(ExtractFileDir(Board.GetFolderIndexFileName), '*.tmp', TmpFileList, False);
525
526         // \8fd\95¡\82ð\96h\82®
527         Board.BeginUpdate;
528         Board.Sorted := True;
529
530         sl := TStringList.Create;
531         try
532                 if FileExists(FileName) then begin
533                         sl.LoadFromFile(FileName);
534
535                         //\82Q\8ds\96Ú\82©\82ç\81i\82P\8ds\96Ú\82Í\83o\81[\83W\83\87\83\93\81j
536                         for i := sl.Count - 1 downto 1 do begin
537                                 Rec := ParseIndexLine(sl[i]);
538                                 if usePlugIn then
539                                         ThreadItem := TThreadItem.Create(
540                                                         Board.BoardPlugIn,
541                                                         Board.BoardPlugIn.FileName2ThreadURL( DWORD( Board ), Rec.FFileName ) )
542                                 else
543                                         ThreadItem := TThreadItem.Create(
544                                                 nil,
545                                                 Get2chBoard2ThreadURL( Board, ChangeFileExt( Rec.FFileName, '' ) ) );
546
547                                 if FileList.Count <> 0 then
548                                         if FileList.Find( ThreadItem.FileName, Index ) then
549                                                 FileList.Delete( Index );
550
551                                 ThreadItem.BeginUpdate;
552                                 ThreadItem.No := Rec.FNo;
553                                 ThreadItem.FileName := Rec.FFileName;
554                                 ThreadItem.Title := Rec.FTitle;
555                                 ThreadItem.Count := Rec.FCount;
556                                 ThreadItem.Size := Rec.FSize;
557 //                      ThreadItem.RoundNo := Rec.FRoundNo;
558                                 ThreadItem.RoundDate := Rec.FRoundDate;
559                                 ThreadItem.LastModified := Rec.FLastModified;
560                                 ThreadItem.Kokomade := Rec.FKokomade;
561                                 ThreadItem.NewReceive := Rec.FNewReceive;
562 //                      ThreadItem.Round := Rec.FRound;
563                                 ThreadItem.UnRead := Rec.FUnRead;
564                                 ThreadItem.ScrollTop := Rec.FScrollTop;
565                                 ThreadItem.AllResCount := Rec.FAllResCount;
566                                 ThreadItem.NewResCount := Rec.FNewResCount;
567                                 ThreadItem.AgeSage := Rec.FAgeSage;
568                                 ThreadItem.ParentBoard := Board;
569
570                                 //\8f\84\89ñ\83\8a\83X\83g\82É\91\8dÝ\82µ\82½\82ç\8f\84\89ñ\83t\83\89\83O\83Z\83b\83g
571                                 if ThreadItem.IsLogFile then begin
572                                         idx := RoundList.Find(ThreadItem);
573                                         if idx <> -1 then begin
574                                                 RoundItem := RoundList.Items[idx, grtItem];
575                                                 ThreadItem.RoundName := RoundItem.RoundName;
576                                                 ThreadItem.Round := True;
577                                         end;
578                                 end;
579
580                                 //\91O\89ñ\88Ù\8fí\8fI\97¹\8e\9e\83`\83F\83b\83N
581                                 if TmpFileList.Count <> 0 then begin
582                                         if TmpFileList.Find(ChangeFileExt(ThreadItem.FileName, '.tmp'), Index) then begin
583                                                 ini := TMemIniFile.Create(ExtractFilePath(Board.GetFolderIndexFileName) + TmpFileList[Index]);
584                                                 try
585                                                         tmpStr := ini.ReadString('Setting', 'RoundDate', DateTimeToStr(ZERO_DATE));
586                                                         ThreadItem.RoundDate := ConvertDateTimeString(tmpStr);
587
588                                                         tmpStr := ini.ReadString('Setting', 'LastModified', DateTimeToStr(ZERO_DATE));
589                                                         ThreadItem.LastModified := ConvertDateTimeString(tmpStr);
590                                                         ThreadItem.Count := ini.ReadInteger('Setting', 'Count', 0);
591                                                         ThreadItem.NewReceive := ini.ReadInteger('Setting', 'NewReceive', 0);
592
593                                                         ThreadItem.Size := ini.ReadInteger('Setting', 'Size', 0);
594                                                         if(ThreadItem.Size = 0) and (FileExists(ThreadItem.GetThreadFileName)) then begin
595                                                                 try
596                                                                         ThreadItem.Size := GetFileSize(ThreadItem.GetThreadFileName) - ThreadItem.Count;
597                                                                 except
598                                                                 end;
599                                                         end;
600
601
602                                                         ThreadItem.Round := ini.ReadBool('Setting', 'Round', False);
603                                                         ThreadItem.UnRead := False;//ini.ReadBool('Setting', 'UnRead', False);
604                                                         ThreadItem.ScrollTop := ini.ReadInteger('Setting', 'ScrollTop', 0);
605                                                         ThreadItem.AllResCount := ini.ReadInteger('Setting', 'AllResCount', ThreadItem.Count);
606                                                         ThreadItem.NewResCount := ini.ReadInteger('Setting', 'NewResCount', 0);
607                                                         ThreadItem.AgeSage := TGikoAgeSage(ini.ReadInteger('Setting', 'AgeSage', Ord(gasNone)));
608                                                 finally
609                                                         ini.Free;
610                                                 end;
611                                                 DeleteFile(ExtractFilePath(Board.GetFolderIndexFileName) + TmpFileList[Index]);
612                                                 TmpFileList.Delete(Index);
613                                         end;
614                                 end;
615
616                                 ThreadItem.EndUpdate;
617                                 Board.Add(ThreadItem);
618
619                                 if (ThreadItem.IsLogFile) and (ThreadItem.UnRead) then
620                                         Inc(UnRead);
621                         end;
622                 end;
623
624                 if UnRead <> Board.UnRead then
625                         Board.UnRead := UnRead;
626
627                 //\83C\83\93\83f\83b\83N\83X\82É\96³\82©\82Á\82½\83\8d\83O\82ð\92Ç\89Á\81i\95\85\82ê\83C\83\93\83f\83b\83N\83X\91Î\89\9e\81j
628                 for i := 0 to FileList.Count - 1 do begin
629                         FileName := ExtractFileDir(Board.GetFolderIndexFileName) + '\' + FileList[i];
630
631                         //ResRec := DivideStrLine(ReadThreadFile(FileName, 1));
632                         if usePlugIn then begin
633                                 ThreadItem := TThreadItem.Create(
634                                         Board.BoardPlugIn,
635                                         Board.BoardPlugIn.FileName2ThreadURL( DWORD( Board ), FileList[i] ) );
636                                 ResRec := DivideStrLine(Board.BoardPlugIn.GetDat( DWORD( ThreadItem ), 1 ));
637                         end else begin
638                                 ThreadItem := TThreadItem.Create(
639                                         nil, Get2chBoard2ThreadURL( Board, ChangeFileExt( FileList[i], '' ) ) );
640                                 ResRec := DivideStrLine(ReadThreadFile(FileName, 1));
641                         end;
642
643                         ThreadItem.BeginUpdate;
644                         ThreadItem.FilePath := FileName;
645                         ThreadItem.No := Board.Count + 1;
646                         ThreadItem.FileName := FileList[i];
647                         ThreadItem.Title := ResRec.FTitle;
648                         ThreadItem.Count := GetFileLineCount(FileName);
649                         ThreadItem.AllResCount := ThreadItem.Count;
650                         ThreadItem.NewResCount := ThreadItem.Count;
651                         ThreadItem.Size := GetFileSize(FileName) - ThreadItem.Count;//1byte\82¸\82ê\82é\82Æ\82«\82ª\82 \82é\82¯\82Ç\82»\82ê\82Í\82 \82«\82ç\82ß\82é
652                         ThreadItem.RoundDate := ZERO_DATE;
653                         ThreadItem.LastModified := ZERO_DATE;
654                         ThreadItem.Kokomade := -1;
655                         ThreadItem.NewReceive := ThreadItem.Count;
656                         ThreadItem.ParentBoard := Board;
657                         ThreadItem.IsLogFile := True;
658                         ThreadItem.Round := False;
659                         ThreadItem.UnRead := False;
660                         ThreadItem.ScrollTop := 0;
661                         ThreadItem.AgeSage := gasNone;
662                         ThreadItem.EndUpdate;
663                         Board.Add(ThreadItem);
664                 end;
665                 Board.EndUpdate;
666         finally
667                 sl.Free;
668                 FileList.Free;
669                 TmpFileList.Free;
670                 Board.Sorted := False;
671         end;
672         Board.IsThreadDatRead := True;
673 end;
674
675 (*************************************************************************
676  *\83X\83\8c\83b\83h\83C\83\93\83f\83b\83N\83X\83t\83@\83C\83\8b(Folder.idx)\8dì\90¬
677  *************************************************************************)
678 procedure TGikoSys.CreateThreadDat(Board: TBoard);
679 var
680         i: integer;
681         s: string;
682         SubjectList: TStringList;
683         sl: TStringList;
684         Rec: TSubjectRec;
685         FileName: string;
686         cnt: Integer;
687 begin
688         if not FileExists(Board.GetSubjectFileName) then Exit;
689         FileName := Board.GetFolderIndexFileName;
690
691         SubjectList := TStringList.Create;
692         try
693                 SubjectList.LoadFromFile(Board.GetSubjectFileName);
694                 sl := TStringList.Create;
695                 try
696                         cnt := 1;
697                         sl.Add(FOLDER_INDEX_VERSION);
698                         for i := 0 to SubjectList.Count - 1 do begin
699                                 Rec := DivideSubject(SubjectList[i]);
700
701                                 if (Trim(Rec.FFileName) = '') or (Trim(Rec.FTitle) = '') then
702                                         Continue;
703
704                                 s := Format('%x', [cnt]) + #1                                   //\94Ô\8d\86
705                                          + Rec.FFileName + #1                                                           //\83t\83@\83C\83\8b\96¼
706                                          + Rec.FTitle + #1                                                                      //\83^\83C\83g\83\8b
707                                          + Format('%x', [Rec.FCount]) + #1      //\83J\83E\83\93\83g
708                                          + Format('%x', [0]) + #1                                               //size
709                                          + Format('%x', [0]) + #1                                               //RoundDate
710                                          + Format('%x', [0]) + #1                                               //LastModified
711                                          + Format('%x', [0]) + #1                                               //Kokomade
712                                          + Format('%x', [0]) + #1                                               //NewReceive
713                                          + '0' + #1                                                                                             //\96¢\8eg\97p
714                                          + Format('%x', [0]) + #1                                               //UnRead
715                                          + Format('%x', [0]) + #1                                               //ScrollTop
716                                          + Format('%x', [Rec.FCount]) + #1      //AllResCount
717                                          + Format('%x', [0]) + #1                                               //NewResCount
718                                          + Format('%x', [0]);                                                           //AgeSage
719
720                                 sl.Add(s);
721                                 inc(cnt);
722                         end;
723                         sl.SaveToFile(FileName);
724                 finally
725                         sl.Free;
726                 end;
727         finally
728                 SubjectList.Free;
729         end;
730 end;
731
732 (*************************************************************************
733  *\83X\83\8c\83b\83h\83C\83\93\83f\83b\83N\83X(Thread.dat)\8f\91\82«\8d\9e\82Ý
734  *Public
735  *************************************************************************)
736 procedure TGikoSys.WriteThreadDat(Board: TBoard);
737 //const
738 //      Values: array[Boolean] of string = ('0', '1');
739 var
740         i: integer;
741         FileName: string;
742         sl: TStringList;
743         s: string;
744         TmpFileList: TStringList;
745 begin
746         if not Board.IsThreadDatRead then
747                 Exit;
748         FileName := Board.GetFolderIndexFileName;
749         ForceDirectoriesEx( ExtractFilePath( FileName ) );
750
751         sl := TStringList.Create;
752         TmpFileList := TStringList.Create;
753         TmpFileList.Sorted := true;
754         try
755                 GetFileList(ExtractFileDir(Board.GetFolderIndexFileName), '*.tmp', TmpFileList, false);
756                 sl.BeginUpdate;
757                 sl.Add(FOLDER_INDEX_VERSION);
758                 for i := 0 to Board.Count - 1 do begin
759                         Board.Items[i].No := i + 1;
760                         s := Format('%x', [Board.Items[i].No]) + #1
761                                  + Board.Items[i].FileName + #1
762                                  + Board.Items[i].Title + #1
763                                  + Format('%x', [Board.Items[i].Count]) + #1
764                                  + Format('%x', [Board.Items[i].Size]) + #1
765                                  + Format('%x', [DateTimeToInt(Board.Items[i].RoundDate)]) + #1
766                                  + Format('%x', [DateTimeToInt(Board.Items[i].LastModified)]) + #1
767                                  + Format('%x', [Board.Items[i].Kokomade]) + #1
768                                  + Format('%x', [Board.Items[i].NewReceive]) + #1
769                                  + '0' + #1     //\96¢\8eg\97p
770                                  + Format('%x', [BoolToInt(Board.Items[i].UnRead)]) + #1
771                                  + Format('%x', [Board.Items[i].ScrollTop]) + #1
772                                  + Format('%x', [Board.Items[i].AllResCount]) + #1
773                                  + Format('%x', [Board.Items[i].NewResCount]) + #1
774                                  + Format('%x', [Ord(Board.Items[i].AgeSage)]);
775
776                         sl.Add(s);
777                 end;
778                 sl.EndUpdate;
779                 sl.SaveToFile(FileName);
780
781                 for i := 0 to TmpFileList.Count - 1 do begin
782                         DeleteFile(ExtractFilePath(Board.GetFolderIndexFileName) + TmpFileList[i]);
783                 end;
784
785         finally
786                 TmpFileList.Free;
787                 sl.Free;
788         end;
789 end;
790
791 function TGikoSys.ParseIndexLine(Line: string): TIndexRec;
792 begin
793         Result.FNo := StrToIntDef('$' + RemoveToken(Line, #1), 0);
794         Result.FFileName := RemoveToken(Line, #1);
795         Result.FTitle := RemoveToken(Line, #1);
796         Result.FCount := StrToIntDef('$' + RemoveToken(Line, #1), 0);
797         Result.FSize := StrToIntDef('$' + RemoveToken(Line, #1), 0);
798         Result.FRoundDate := IntToDateTime(StrToIntDef('$' + RemoveToken(Line, #1), ZERO_DATE));
799         Result.FLastModified := IntToDateTime(StrToIntDef('$' + RemoveToken(Line, #1), ZERO_DATE));
800         Result.FKokomade := StrToIntDef('$' + RemoveToken(Line, #1), -1);
801         Result.FNewReceive := StrToIntDef('$' + RemoveToken(Line, #1), 0);
802         RemoveToken(Line, #1);//9: ;    //\96¢\8eg\97p
803         Result.FUnRead := IntToBool(StrToIntDef('$' + RemoveToken(Line, #1), 0));
804         Result.FScrollTop := StrToIntDef('$' + RemoveToken(Line, #1), 0);
805         Result.FAllResCount := StrToIntDef('$' + RemoveToken(Line, #1), 0);
806         Result.FNewResCount := StrToIntDef('$' + RemoveToken(Line, #1), 0);
807         Result.FAgeSage := TGikoAgeSage(StrToIntDef('$' + RemoveToken(Line, #1), 0));
808
809 end;
810
811 //\8ew\92è\83t\83H\83\8b\83_\93à\82Ì\8ew\92è\83t\83@\83C\83\8b\88ê\97\97\82ð\8eæ\93¾\82·\82é
812 // ListFiles('c:\', '*.txt', list, True);
813 procedure TGikoSys.GetFileList(Path: string; Mask: string; var List: TStringList; SubDir: Boolean; IsPathAdd: Boolean);
814 var
815         rc: Integer;
816         SearchRec : TSearchRec;
817         s: string;
818         maskExt: string;
819 begin
820         maskExt := Copy(Mask, 1, Length(Mask) - 1);
821
822         Path := IncludeTrailingPathDelimiter(Path);
823         rc := FindFirst(Path + '*.*', faAnyfile, SearchRec);
824         try
825                 while rc = 0 do begin
826                         if (SearchRec.Name <> '..') and (SearchRec.Name <> '.') then begin
827                                 s := Path + SearchRec.Name;
828                                 //if (SearchRec.Attr and faDirectory > 0) then
829                                 //      s := IncludeTrailingPathDelimiter(s)
830
831                                 if (SearchRec.Attr and faDirectory = 0) and (MatchesMask(s, Mask)) then
832                                                 if IsPathAdd then
833                                                         List.Add(s)
834                                                 else
835                                                         List.Add(SearchRec.Name);
836                                 if SubDir and (SearchRec.Attr and faDirectory > 0) then
837                                         GetFileList(s, Mask, List, True, IsPathAdd);
838                         end;
839                         rc := FindNext(SearchRec);
840                 end;
841         finally
842                 SysUtils.FindClose(SearchRec);
843         end;
844         List.Sort;
845 end;
846 //\8ew\92è\83t\83H\83\8b\83_\93à\82Ì\8ew\92è\83t\83@\83C\83\8b\88ê\97\97\82ð\8eæ\93¾\82·\82é
847 //\83T\83u\83t\83H\83\8b\83_\82Í\8c\9f\8dõ\82µ\82È\82¢
848 // ListFiles('c:\', '*.txt', list, True);
849 procedure TGikoSys.GetFileList(Path: string; Mask: string; var List: TStringList; IsPathAdd: Boolean);
850 var
851         rc: Integer;
852         SearchRec : TSearchRec;
853         s: string;
854 begin
855         Path := IncludeTrailingPathDelimiter(Path);
856         rc := FindFirst(Path + Mask, faAnyfile, SearchRec);
857         try
858                 while rc = 0 do begin
859                         if (SearchRec.Name <> '..') and (SearchRec.Name <> '.') then begin
860                                 s := Path + SearchRec.Name;
861
862                                 if (SearchRec.Attr and faDirectory = 0) then
863                                                 if IsPathAdd then
864                                                         List.Add(s)
865                                                 else
866                                                         List.Add(SearchRec.Name);
867                         end;
868                         rc := FindNext(SearchRec);
869                 end;
870         finally
871                 SysUtils.FindClose(SearchRec);
872         end;
873         List.Sort;
874 end;
875 //\8ew\92è\83t\83H\83\8b\83_\93à\82Ì\83f\83B\83\8c\83N\83g\83\8a\88ê\97\97\82ð\8eæ\93¾\82·\82é
876 procedure TGikoSys.GetDirectoryList(Path: string; Mask: string; List: TStringList; SubDir: Boolean);
877 var
878         rc: Integer;
879         SearchRec : TSearchRec;
880         s: string;
881 begin
882         Path := IncludeTrailingPathDelimiter(Path);
883         rc := FindFirst(Path + '*.*', faDirectory, SearchRec);
884         try
885                 while rc = 0 do begin
886                         if (SearchRec.Name <> '..') and (SearchRec.Name <> '.') then begin
887                                 s := Path + SearchRec.Name;
888                                 //if (SearchRec.Attr and faDirectory > 0) then
889                                 //      s := IncludeTrailingPathDelimiter(s)
890
891                                 if (SearchRec.Attr and faDirectory > 0) and (MatchesMask(s, Mask)) then
892                                         List.Add( IncludeTrailingPathDelimiter( s ) );
893                                 if SubDir and (SearchRec.Attr and faDirectory > 0) then
894                                         GetDirectoryList(s, Mask, List, True);
895                         end;
896                         rc := FindNext(SearchRec);
897                 end;
898         finally
899                 SysUtils.FindClose(SearchRec);
900         end;
901 end;
902
903 // \83X\83L\83\93\82ð\93Ç\82Ý\8d\9e\82Ý\81A\92l\82ð\92u\8a·\82·\82é
904 function TGikoSys.LoadFromSkin(
905         fileName: string;
906         ThreadItem: TThreadItem;
907         SizeByte: Integer
908 ): string;
909 var
910         Skin: TStringList;
911 begin
912
913         Skin := TStringList.Create;
914         try
915                 if FileExists( fileName ) then begin
916                         Skin.LoadFromFile( fileName );
917
918                         // \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
919                         try
920                                 if ThreadItem.ParentBoard <> nil then
921                                         if ThreadItem.ParentBoard.ParentCategory <> nil then
922                                                 CustomStringReplace( Skin, '<BBSNAME/>', ThreadItem.ParentBoard.ParentCategory.ParenTBBS.Title);
923                                         CustomStringReplace( Skin, '<THREADURL/>', ThreadItem.URL);
924                         except end;
925                         CustomStringReplace( Skin, '<BOARDNAME/>', ThreadItem.ParentBoard.Title);
926                         CustomStringReplace( Skin, '<BOARDURL/>', ThreadItem.ParentBoard.URL);
927                         CustomStringReplace( Skin, '<THREADNAME/>', ThreadItem.Title);
928                         CustomStringReplace( Skin, '<SKINPATH/>', Setting.CSSFileName);
929                         CustomStringReplace( Skin, '<GETRESCOUNT/>', IntToStr( ThreadItem.Count - ThreadItem.NewResCount ));
930                                                 CustomStringReplace( Skin, '<NEWRESCOUNT/>', IntToStr( ThreadItem.NewResCount ));
931                                                 CustomStringReplace( Skin, '<ALLRESCOUNT/>', IntToStr( ThreadItem.Count ));
932
933                         CustomStringReplace( Skin, '<NEWDATE/>',FormatDateTime('yyyy/mm/dd(ddd) hh:mm', ThreadItem.RoundDate));
934                                                 CustomStringReplace( Skin, '<SIZEKB/>', IntToStr( Floor( SizeByte / 1024 ) ));
935                                                 CustomStringReplace( Skin, '<SIZE/>', IntToStr( SizeByte ));
936
937                         //----- \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µ
938                         // \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
939                         try
940                                 if ThreadItem.ParentBoard <> nil then
941                                         if ThreadItem.ParentBoard.ParentCategory <> nil then
942                                                 CustomStringReplace( Skin, '&BBSNAME', ThreadItem.ParentBoard.ParentCategory.ParenTBBS.Title);
943                                         CustomStringReplace( Skin, '&THREADURL', ThreadItem.URL);
944                         except end;
945                         CustomStringReplace( Skin, '&BOARDNAME', ThreadItem.ParentBoard.Title);
946                         CustomStringReplace( Skin, '&BOARDURL', ThreadItem.ParentBoard.URL);
947                         CustomStringReplace( Skin, '&THREADNAME', ThreadItem.Title);
948                         CustomStringReplace( Skin, '&SKINPATH', Setting.CSSFileName);
949                         CustomStringReplace( Skin, '&GETRESCOUNT', IntToStr( ThreadItem.NewReceive - 1 ));
950                         CustomStringReplace( Skin, '&NEWRESCOUNT', IntToStr( ThreadItem.NewResCount ));
951                         CustomStringReplace( Skin, '&ALLRESCOUNT', IntToStr( ThreadItem.AllResCount ));
952
953                         CustomStringReplace( Skin, '&NEWDATE', FormatDateTime('yyyy/mm/dd(ddd) hh:mm', ThreadItem.RoundDate));
954                         CustomStringReplace( Skin, '&SIZEKB', IntToStr( Floor( SizeByte / 1024 ) ));
955                         CustomStringReplace( Skin, '&SIZE', IntToStr( SizeByte ));
956                         //----- \82±\82±\82Ü\82Å
957                 end;
958                 Result := Skin.Text;
959         finally
960                 Skin.Free;
961         end;
962 end;
963
964 // \83\8c\83X\82Ì\92l\82ð\92u\8a·\82·\82é
965 function TGikoSys.SkinedRes(
966         skin: string;
967         Res: TResRec;
968         No: string
969 ): string;
970 begin
971
972         try
973                 Skin := CustomStringReplace( Skin, '<NUMBER/>',
974                         '<a href="menu:' + No + '" name="' + No + '">' + No + '</a>');
975                 Skin := CustomStringReplace( Skin, '<PLAINNUMBER/>', No);
976                 Skin := CustomStringReplace( Skin, '<NAME/>', '<b>' + Res.FName + '</b>');
977                 Skin := CustomStringReplace( Skin, '<MAILNAME/>',
978                         '<a href="mailto:' + Res.FMailTo + '"><b>' + Res.FName + '</b></a>');
979                 Skin := CustomStringReplace( Skin, '<MAIL/>', Res.FMailTo);
980                 Skin := CustomStringReplace( Skin, '<DATE/>', Res.FDateTime);
981                 Skin := CustomStringReplace( Skin, '<MESSAGE/>', Res.FBody);
982
983                 //----- \82©\82¿\82ã\81`\82µ\82á\8cÝ\8a·\97p\81B\83R\83\81\83\93\83g\83A\83E\83g\82µ\82Ä\82à\82æ\82µ
984                 Skin := CustomStringReplace( Skin, '&NUMBER',
985                         '<a href="menu:' + No + '" name="' + No + '">' + No + '</a>');
986                 Skin := CustomStringReplace( Skin, '&PLAINNUMBER', No);
987                 Skin := CustomStringReplace( Skin, '&NAME', '<b>' + Res.FName + '</b>');
988                 Skin := CustomStringReplace( Skin, '&MAILNAME',
989                         '<a href="mailto:' + Res.FMailTo + '"><b>' + Res.FName + '</b></a>');
990                 Skin := CustomStringReplace( Skin, '&MAIL', Res.FMailTo);
991                 Skin := CustomStringReplace( Skin, '&DATE', Res.FDateTime);
992                 Skin := CustomStringReplace( Skin, '&MESSAGE', Res.FBody);
993                 //----- \82±\82±\82Ü\82Å
994
995                 Result := Skin;
996         finally
997         end;
998
999 end;
1000
1001 procedure TGikoSys.CreateHTML2(doc: Variant; ThreadItem: TThreadItem; var sTitle: string);
1002 var
1003         i: integer;
1004         No: string;
1005         //bufList : TStringList;
1006         ReadList: TStringList;
1007         SaveList: TStringList;
1008         CSSFileName: string;
1009         BBSID: string;
1010         FileName: string;
1011         NewReceiveNo: Integer;
1012         Res: TResRec;
1013         boardPlugIn : TBoardPlugIn;
1014
1015         UserOptionalStyle: string;
1016         SkinHeader: string;
1017         SkinNewRes: string;
1018         SkinRes: string;
1019
1020         function LoadSkin( fileName: string ): string;
1021         begin
1022                 Result := LoadFromSkin( fileName, ThreadItem, ThreadItem.Size );
1023         end;
1024         function ReplaceRes( skin: string ): string;
1025         begin
1026                 Result := SkinedRes( skin, Res, No );
1027         end;
1028 begin
1029         if ThreadItem <> nil then begin
1030                 if ThreadItem.IsBoardPlugInAvailable then begin
1031                         //===== \83v\83\89\83O\83C\83\93\82É\82æ\82é\95\\8e¦
1032                         boardPlugIn             := ThreadItem.BoardPlugIn;
1033                         NewReceiveNo    := ThreadItem.NewReceive;
1034                         // \83t\83H\83\93\83g\82â\83T\83C\83Y\82Ì\90Ý\92è
1035                         if Length( GikoSys.Setting.BrowserFontName ) > 0 then
1036                                 UserOptionalStyle := UserOptionalStyle +
1037                                                                 'font-family:"' + GikoSys.Setting.BrowserFontName + '";';
1038                         if GikoSys.Setting.BrowserFontSize <> 0 then
1039                                 UserOptionalStyle := UserOptionalStyle +
1040                                                                 'font-size:' + IntToStr( GikoSys.Setting.BrowserFontSize ) + 'pt;';
1041                         if GikoSys.Setting.BrowserFontColor <> -1 then
1042                                 UserOptionalStyle := UserOptionalStyle +
1043                                                                 'color:#' + IntToHex( GikoSys.Setting.BrowserFontColor, 6 ) + ';';
1044                         if GikoSys.Setting.BrowserBackColor <> -1 then
1045                                 UserOptionalStyle := UserOptionalStyle +
1046                                                                 'background-color:#' + IntToHex( GikoSys.Setting.BrowserBackColor, 6 ) + ';';
1047                         case GikoSys.Setting.BrowserFontBold of
1048                                 -1: UserOptionalStyle := UserOptionalStyle + 'font-weight:normal;';
1049                                 1: UserOptionalStyle := UserOptionalStyle + 'font-weight:bold;';
1050                         end;
1051                         case GikoSys.Setting.BrowserFontItalic of
1052                                 -1: UserOptionalStyle := UserOptionalStyle + 'font-style:normal;';
1053                                 1: UserOptionalStyle := UserOptionalStyle + 'font-style:italic;';
1054                         end;
1055
1056                         SaveList := TStringList.Create;
1057                         try
1058                                 doc.open;
1059                                 // \95\8e\9a\83R\81[\83h\82Í\83v\83\89\83O\83C\83\93\82É\94C\82¹\82é
1060                                 // doc.charset := 'Shift_JIS';
1061
1062                                 // \83w\83b\83_
1063                                 SaveList.Add( boardPlugIn.GetHeader( DWORD( threadItem ),
1064                                         '<style type="text/css">body {' + UserOptionalStyle + '}</style>' ) );
1065
1066                                 for i := 0 to threadItem.Count - 1 do begin
1067                                         if (OnlyAHundredRes = true) and ( i <> 0 ) and ( (threadItem.Count-i) > 101 ) then begin
1068                                                 Continue;
1069                                         end;
1070
1071                                         // \90V\92\85\83}\81[\83N
1072                                         if (NewReceiveNo = (i + 1)) or ((NewReceiveNo = 0) and (i = 0)) then begin
1073                                                 try
1074                                                         if GikoSys.Setting.UseSkin then begin
1075                                                                 if FileExists( GetSkinNewmarkFileName ) then
1076                                                                         SaveList.Add( LoadSkin( GetSkinNewmarkFileName ) )
1077                                                                 else
1078                                                                         SaveList.Add( '<a name="new"></a>' );
1079                                                         end else if GikoSys.Setting.UseCSS then begin
1080                                                                 SaveList.Add('<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>');
1081                                                         end else begin
1082                                                                 SaveList.Add('</dl>');
1083                                                                 SaveList.Add('<a name="new"></a>');
1084                                                                 SaveList.Add('<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>');
1085                                                                 SaveList.Add('<dl>');
1086                                                         end;
1087                                                 except
1088                                                         SaveList.Add( '<a name="new"></a>' );
1089                                                 end;
1090                                         end;
1091
1092                                         // \83\8c\83X
1093                                         SaveList.Add( boardPlugIn.GetRes( DWORD( threadItem ), i + 1 ) );
1094
1095                                         if ThreadItem.Kokomade = (i + 1) then begin
1096                                                 // \82±\82±\82Ü\82Å\93Ç\82ñ\82¾
1097                                                 try
1098                                                         if GikoSys.Setting.UseSkin then begin
1099                                                                 if FileExists( GetSkinBookmarkFileName ) then
1100                                                                         SaveList.Add( LoadSkin( GetSkinBookmarkFileName ) )
1101                                                                 else
1102                                                                         SaveList.Add( '<a name="koko"></a>' );
1103                                                         end else if GikoSys.Setting.UseCSS then begin
1104                                                                 SaveList.Add('<a name="koko"></a><div class="koko">\83R\83R\82Ü\82Å\93Ç\82ñ\82¾</div>');
1105                                                         end else begin
1106                                                                 SaveList.Add('</dl>');
1107                                                                 SaveList.Add('<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>');
1108                                                                 SaveList.Add('<dl>');
1109                                                         end;
1110                                                 except
1111                                                         SaveList.Add( '<a name="koko"></a>' );
1112                                                 end;
1113                                         end;
1114
1115                                         doc.Write(SaveList.Text);
1116                                         SaveList.Clear;
1117                                 end;
1118
1119
1120                                 // \83X\83L\83\93(\83t\83b\83^)
1121                                 SaveList.Add( boardPlugIn.GetFooter( DWORD( threadItem ), '<a name="bottom"></a>' ) );
1122
1123                                 doc.Write(SaveList.Text);
1124                         finally
1125                                 SaveList.Free;
1126                                 doc.Close;
1127                         end;
1128
1129                         Exit;
1130                 end;
1131         end;
1132         ShortDayNames[1] := '\93ú';               ShortDayNames[2] := '\8c\8e';
1133         ShortDayNames[3] := '\89Î';               ShortDayNames[4] := '\90\85';
1134         ShortDayNames[5] := '\96Ø';               ShortDayNames[6] := '\8bà';
1135         ShortDayNames[7] := '\93y';
1136         BBSID := ThreadItem.ParentBoard.BBSID;
1137         NewReceiveNo := ThreadItem.NewReceive;
1138         ReadList := TStringList.Create;
1139         try
1140                 if ThreadItem.IsLogFile then begin
1141                         FileName := ThreadItem.GetThreadFileName;
1142                         ReadList.LoadFromFile(FileName);
1143                         FAbon.IndividualAbon(ReadList, ChangeFileExt(FileName,'.NG'));
1144                         FAbon.Execute(ReadList);                //       \82 \82Ú\81`\82ñ\82µ\82Ä
1145                         FSelectResFilter.ExecuteEx(ReadList); //\83\8c\83X\82Ì\83t\83B\83\8b\83^\83\8a\83\93\83O\82ð\82·\82é
1146                         Res := DivideStrLine(ReadList[0]);
1147                         Res.FTitle := CustomStringReplace(Res.FTitle, '\81\97\81M', ',');
1148                         sTitle := Res.FTitle;
1149                 end else begin
1150                         sTitle := CustomStringReplace(ThreadItem.Title, '\81\97\81M', ',');
1151                 end;
1152                 SaveList := TStringList.Create;
1153                 try
1154                         doc.open;
1155                         doc.charset := 'Shift_JIS';
1156
1157                         // \83t\83H\83\93\83g\82â\83T\83C\83Y\82Ì\90Ý\92è
1158                         if Length( GikoSys.Setting.BrowserFontName ) > 0 then
1159                                 UserOptionalStyle := UserOptionalStyle +
1160                                                                 'font-family:"' + GikoSys.Setting.BrowserFontName + '";';
1161                         if GikoSys.Setting.BrowserFontSize <> 0 then
1162                                 UserOptionalStyle := UserOptionalStyle +
1163                                                                 'font-size:' + IntToStr( GikoSys.Setting.BrowserFontSize ) + 'pt;';
1164                         if GikoSys.Setting.BrowserFontColor <> -1 then
1165                                 UserOptionalStyle := UserOptionalStyle +
1166                                                                 'color:#' + IntToHex( GikoSys.Setting.BrowserFontColor, 6 ) + ';';
1167                         if GikoSys.Setting.BrowserBackColor <> -1 then
1168                                 UserOptionalStyle := UserOptionalStyle +
1169                                                                 'background-color:#' + IntToHex( GikoSys.Setting.BrowserBackColor, 6 ) + ';';
1170                         case GikoSys.Setting.BrowserFontBold of
1171                                 -1: UserOptionalStyle := UserOptionalStyle + 'font-weight:normal;';
1172                                 1: UserOptionalStyle := UserOptionalStyle + 'font-weight:bold;';
1173                         end;
1174                         case GikoSys.Setting.BrowserFontItalic of
1175                                 -1: UserOptionalStyle := UserOptionalStyle + 'font-style:normal;';
1176                                 1: UserOptionalStyle := UserOptionalStyle + 'font-style:italic;';
1177                         end;
1178
1179                         CSSFileName := GetStyleSheetDir + Setting.CSSFileName;
1180                         if GikoSys.Setting.UseSkin then begin
1181                                 // \83X\83L\83\93\8eg\97p
1182                                 // \83X\83L\83\93\82Ì\90Ý\92è
1183                                 try
1184                                         SkinHeader := LoadSkin( GetSkinHeaderFileName );
1185                                         if Length( UserOptionalStyle ) > 0 then
1186                                                 SkinHeader := CustomStringReplace( SkinHeader, '</head>',
1187                                                         '<style type="text/css">body {' + UserOptionalStyle + '}</style></head>');
1188                                         SaveList.Add( SkinHeader );
1189                                 except
1190                                 end;
1191                                 try
1192                                         SkinNewRes := LoadSkin( GetSkinNewResFileName );
1193                                 except
1194                                                                 end;
1195                                 try
1196                                         SkinRes := LoadSkin( GetSkinResFileName );
1197                                 except
1198                                 end;
1199
1200                                 SaveList.Add('<a name="top"></a>');
1201
1202                                 for i := 0 to ReadList.Count - 1 do begin
1203                                         if (OnlyAHundredRes = true) and ( i <> 0 ) and ( (ReadList.Count-i) > 101 ) then begin
1204                                                 Continue;
1205                                         end;
1206                                         // \90V\92\85\83}\81[\83N
1207                                         if (NewReceiveNo = i + 1) or ((NewReceiveNo = 0) and (i = 0)) then begin
1208                                                 try
1209                                                         if FileExists( GetSkinNewmarkFileName ) then
1210                                                                 SaveList.Add( LoadSkin( GetSkinNewmarkFileName ) )
1211                                                         else
1212                                                                 SaveList.Add( '<a name="new"></a>' );
1213                                                 except
1214                                                         SaveList.Add( '<a name="new"></a>' );
1215                                                 end;
1216                                         end;
1217                                         if (Trim(ReadList[i]) <> '') then begin
1218                                                 No := IntToStr(i + 1);
1219
1220                                                 Res := DivideStrLine(ReadList[i]);
1221                                                 if Res.FType = glt2chOld then begin
1222                                                         Res.FMailTo := CustomStringReplace(Res.FMailTo, '\81\97\81M', ',');
1223                                                         Res.FName := CustomStringReplace(Res.FName, '\81\97\81M', ',');
1224                                                         Res.FBody := CustomStringReplace(Res.FBody, '\81\97\81M', ',');
1225                                                 end;
1226
1227                                                 Res.FBody := AddAnchorTag(Res.FBody);
1228                                                 Res.FBody := ConvRes(Res.FBody, ThreadItem.ParentBoard.BBSID, ChangeFileExt(ThreadItem.FileName, ''), 'bbs', 'key', 'st', 'to', 'nofirst', 'true');
1229
1230                                                 try
1231                                                         if NewReceiveNo <= (i + 1) then
1232                                                                 // \90V\92\85\83\8c\83X
1233                                                                 SaveList.Add( ReplaceRes( SkinNewRes ) )
1234                                                         else
1235                                                                 // \92Ê\8fí\82Ì\83\8c\83X
1236                                                                 SaveList.Add( ReplaceRes( SkinRes ) );
1237                                                 except
1238                                                 end;
1239                                         end;
1240
1241                                         if ThreadItem.Kokomade = (i + 1) then begin
1242                                                 // \82±\82±\82Ü\82Å\93Ç\82ñ\82¾
1243                                                 try
1244                                                         if FileExists( GetSkinBookmarkFileName ) then
1245                                                                 SaveList.Add( LoadSkin( GetSkinBookmarkFileName ) )
1246                                                         else
1247                                                                 SaveList.Add( '<a name="koko"></a>' );
1248                                                 except
1249                                                         SaveList.Add( '<a name="koko"></a>' );
1250                                                 end;
1251                                         end;
1252                                         doc.Write(SaveList.Text);
1253                                         SaveList.Clear;
1254                                 end;
1255                                 SaveList.Add('<a name="bottom"></a>');
1256                                 // \83X\83L\83\93(\83t\83b\83^)
1257                                 try
1258                                         SaveList.Add( LoadSkin( GetSkinFooterFileName ) );
1259                                 except
1260                                 end;
1261                                 doc.Write(SaveList.Text);
1262
1263                         end else if GikoSys.Setting.UseCSS and FileExists(CSSFileName) then begin
1264                                 //CSS\8eg\97p
1265                                 //CSSFileName := GetAppDir + CSS_FILE_NAME;
1266 //                              SaveList.Add('<html lang="ja"><head>');
1267                                 SaveList.Add('<html><head>');
1268                                 SaveList.Add('<meta http-equiv="Content-type" content="text/html; charset=Shift_JIS">');
1269                                 SaveList.Add('<title>' + sTitle + '</title>');
1270                                 SaveList.Add('<link rel="stylesheet" href="'+CSSFileName+'" type="text/css">');
1271                                 if Length( UserOptionalStyle ) > 0 then
1272                                         SaveList.Add('<style type="text/css">body {' + UserOptionalStyle + '}</style>');
1273                                 SaveList.Add('</head>');
1274                                 SaveList.Add('<body>');
1275                                 SaveList.Add('<a name="top"></a>');
1276                                 SaveList.Add('<div class="title">' + sTitle + '</div>');
1277                                 doc.Write(SaveList.Text);
1278                                 SaveList.Clear;
1279                                 //Application.ProcessMessages;
1280                                 for i := 0 to ReadList.Count - 1 do begin
1281                                         if (OnlyAHundredRes = true) and ( i <> 0 ) and ( (ReadList.Count-i) > 101 ) then begin
1282                                                 Continue;
1283                                         end;
1284                                         if (NewReceiveNo = (i + 1)) or ((NewReceiveNo = 0) and (i = 0)) then begin
1285                                                 SaveList.Add('<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>');
1286                                         end;
1287                                         if (Trim(ReadList[i]) <> '') then begin
1288                                                 No := IntToStr(i + 1);
1289                                                 Res := DivideStrLine(ReadList[i]);
1290                                                 Res.FBody := AddAnchorTag(Res.FBody);
1291                                                 Res.FBody := ConvRes(Res.FBody, ThreadItem.ParentBoard.BBSID, ChangeFileExt(ThreadItem.FileName, ''), 'bbs', 'key', 'st', 'to', 'nofirst', 'true');
1292                                                 if Res.FMailTo = '' then
1293                                                         SaveList.Add('<a name="' + No + '"></a>'
1294                                                                                         + '<div class="header"><span class="no"><a href="menu:' + No + '">' + No + '</a></span> '
1295                                                                                         + '<span class="name_label">\96¼\91O\81F</span> '
1296                                                                                         + '<span class="name"><b>' + Res.FName + '</b></span> '
1297                                                                                         + '<span class="date_label">\93\8a\8de\93ú\81F</span> '
1298                                                                                         + '<span class="date">' + Res.FDateTime+ '</span></div>'
1299                                                                                                                                                                                 + '<div class="mes">' + Res.FBody + ' </div>')
1300                                                 else if GikoSys.Setting.ShowMail then
1301                                                         SaveList.Add('<a name="' + No + '"></a>'
1302                                                                                         + '<div class="header"><span class="no"><a href="menu:' + No + '">' + No + '</a></span>'
1303                                                                                                                                                                                 + '<span class="name_label"> \96¼\91O\81F </span>'
1304                                                                                         + '<a class="name_mail" href="mailto:' + Res.FMailTo + '">'
1305                                                                                         + '<b>' + Res.FName + '</b></a><span class="mail"> [' + Res.FMailTo + ']</span>'
1306                                                                                         + '<span class="date_label"> \93\8a\8de\93ú\81F</span>'
1307                                                                                         + '<span class="date"> ' + Res.FDateTime+ '</span></div>'
1308                                                                                         + '<div class="mes">' + Res.FBody + ' </div>')
1309                                                 else
1310                                                         SaveList.Add('<a name="' + No + '"></a>'
1311                                                                                         + '<div class="header"><span class="no"><a href="menu:' + No + '">' + No + '</a></span>'
1312                                                                                         + '<span class="name_label"> \96¼\91O\81F </span>'
1313                                                                                         + '<a class="name_mail" href="mailto:' + Res.FMailTo + '">'
1314                                                                                         + '<b>' + Res.FName + '</b></a>'
1315                                                                                         + '<span class="date_label"> \93\8a\8de\93ú\81F</span>'
1316                                                                                         + '<span class="date"> ' + Res.FDateTime+ '</span></div>'
1317                                                                                                                                                                                 + '<div class="mes">' + Res.FBody + ' </div>');
1318                                         end;
1319                                         if ThreadItem.Kokomade = (i + 1) then begin
1320                                                 SaveList.Add('<a name="koko"></a><div class="koko">\83R\83R\82Ü\82Å\93Ç\82ñ\82¾</div>');
1321                                         end;
1322
1323                                         doc.Write(SaveList.Text);
1324                                         SaveList.Clear;
1325                                 end;
1326                                 SaveList.Add('<a name="bottom"></a>');
1327                                 SaveList.Add('</body></html>');
1328                                 SaveList.Add('<a name="last"></a>');
1329                                 SaveList.Add('</body></html>');
1330
1331                                 doc.Write(SaveList.Text);
1332                         end else begin
1333                                 //CSS\94ñ\8eg\97p
1334 //                              SaveList.Add('<html lang="ja"><head>');
1335                                 SaveList.Add('<html><head>');
1336                                 SaveList.Add('<meta http-equiv="Content-type" content="text/html; charset=Shift_JIS">');
1337                                 SaveList.Add('<title>' + sTitle + '</title></head>');
1338                                 SaveList.Add('<body TEXT="#000000" BGCOLOR="#EFEFEF" link="#0000FF" alink="#FF0000" vlink="#660099">');
1339                                 SaveList.Add('<a name="top"></a>');
1340                                 SaveList.Add('<font size=+1 color="#FF0000">' + sTitle + '</font>');
1341                                 SaveList.Add('<dl>');
1342                                 doc.Write(SaveList.Text);
1343                                 SaveList.Clear;
1344                                 //Application.ProcessMessages;
1345                                 for i := 0 to ReadList.Count - 1 do begin
1346                                         if (OnlyAHundredRes = true) and ( i <> 0 ) and ( (ReadList.Count-i) > 101 ) then begin
1347                                                 Continue;
1348                                         end;
1349                                         if (NewReceiveNo = (i + 1)) or ((NewReceiveNo = 0) and (i = 0)) then begin
1350                                                 SaveList.Add('</dl>');
1351                                                 SaveList.Add('<a name="new"></a>');
1352                                                 SaveList.Add('<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>');
1353                                                 SaveList.Add('<dl>');
1354                                         end;
1355                                         if (Trim(ReadList[i]) <> '') then begin
1356                                                 No := IntToStr(i + 1);
1357                                                 Res := DivideStrLine(ReadList[i]);
1358                                                 if Res.FType = glt2chOld then begin
1359                                                         Res.FMailTo := CustomStringReplace(Res.FMailTo, '\81\97\81M', ',');
1360                                                         Res.FName := CustomStringReplace(Res.FName, '\81\97\81M', ',');
1361                                                         Res.FBody := CustomStringReplace(Res.FBody, '\81\97\81M', ',');
1362                                                 end;
1363                                                 Res.FBody := AddAnchorTag(Res.FBody);
1364                                                 Res.FBody := ConvRes(Res.FBody, ThreadItem.ParentBoard.BBSID, ChangeFileExt(ThreadItem.FileName, ''), 'bbs', 'key', 'st', 'to', 'nofirst', 'true');
1365                                                 if Res.FMailTo = '' then
1366                                                         SaveList.Add('<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>')
1367                                                 else if GikoSys.Setting.ShowMail then
1368                                                         SaveList.Add('<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>')
1369                                                 else
1370                                                         SaveList.Add('<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>');
1371                                         end;
1372                                         if ThreadItem.Kokomade = (i + 1) then begin
1373                                                 SaveList.Add('</dl>');
1374                                                 SaveList.Add('<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>');
1375                                                 SaveList.Add('<dl>');
1376                                         end;
1377                                         doc.Write(SaveList.Text);
1378                                         SaveList.Clear;
1379                                 end;
1380                                 SaveList.Add('</dl>');
1381                                 SaveList.Add('<a name="bottom"></a>');
1382                                 SaveList.Add('</body></html>');
1383                                 doc.Write(SaveList.Text);
1384                         end;
1385                 finally
1386                         SaveList.Free;
1387                         doc.Close;
1388                 end;
1389         finally
1390                 ReadList.Free;
1391         end;
1392 end;
1393 procedure TGikoSys.CreateHTML3(var html: TStringList; ThreadItem: TThreadItem; var sTitle: string);
1394 var
1395         i: integer;
1396         No: string;
1397         //bufList : TStringList;
1398         ReadList: TStringList;
1399 //      SaveList: TStringList;
1400         CSSFileName: string;
1401         BBSID: string;
1402         FileName: string;
1403         Res: TResRec;
1404         boardPlugIn : TBoardPlugIn;
1405
1406         UserOptionalStyle: string;
1407         SkinHeader: string;
1408         SkinRes: string;
1409         tmp, tmp1: string;
1410         function LoadSkin( fileName: string ): string;
1411         begin
1412                 Result := LoadFromSkin( fileName, ThreadItem, ThreadItem.Size );
1413         end;
1414         function ReplaceRes( skin: string ): string;
1415         begin
1416                 Result := SkinedRes( skin, Res, No );
1417         end;
1418
1419 begin
1420         if ThreadItem <> nil then begin
1421                 CSSFileName := GetStyleSheetDir + Setting.CSSFileName;
1422                 html.Clear;
1423                 html.BeginUpdate;
1424                 if ThreadItem.IsBoardPlugInAvailable then begin
1425                         //===== \83v\83\89\83O\83C\83\93\82É\82æ\82é\95\\8e¦
1426                         boardPlugIn             := ThreadItem.BoardPlugIn;
1427                         // \83t\83H\83\93\83g\82â\83T\83C\83Y\82Ì\90Ý\92è
1428                         if Length( GikoSys.Setting.BrowserFontName ) > 0 then
1429                                 UserOptionalStyle := UserOptionalStyle +
1430                                                                 'font-family:"' + GikoSys.Setting.BrowserFontName + '";';
1431                         if GikoSys.Setting.BrowserFontSize <> 0 then
1432                                 UserOptionalStyle := UserOptionalStyle +
1433                                                                 'font-size:' + IntToStr( GikoSys.Setting.BrowserFontSize ) + 'pt;';
1434                         if GikoSys.Setting.BrowserFontColor <> -1 then
1435                                 UserOptionalStyle := UserOptionalStyle +
1436                                                                 'color:#' + IntToHex( GikoSys.Setting.BrowserFontColor, 6 ) + ';';
1437                         if GikoSys.Setting.BrowserBackColor <> -1 then
1438                                 UserOptionalStyle := UserOptionalStyle +
1439                                                                 'background-color:#' + IntToHex( GikoSys.Setting.BrowserBackColor, 6 ) + ';';
1440                         case GikoSys.Setting.BrowserFontBold of
1441                                 -1: UserOptionalStyle := UserOptionalStyle + 'font-weight:normal;';
1442                                 1: UserOptionalStyle := UserOptionalStyle + 'font-weight:bold;';
1443                         end;
1444                         case GikoSys.Setting.BrowserFontItalic of
1445                                 -1: UserOptionalStyle := UserOptionalStyle + 'font-style:normal;';
1446                                 1: UserOptionalStyle := UserOptionalStyle + 'font-style:italic;';
1447                         end;
1448
1449                         try
1450                                 // \95\8e\9a\83R\81[\83h\82Í\83v\83\89\83O\83C\83\93\82É\94C\82¹\82é
1451                                 // \83w\83b\83_
1452                                 tmp := boardPlugIn.GetHeader( DWORD( threadItem ),
1453                                         '<style type="text/css">body {' + UserOptionalStyle + '}</style>' );
1454                                 //\90â\91Î\8eQ\8fÆ\82©\82ç\91\8a\91Î\8eQ\8fÆ\82Ö
1455                                 if Setting.UseSkin then begin
1456                                         tmp1 := './' +Setting.CSSFileName;
1457                                         tmp1 := CustomStringReplace(tmp1, GetConfigDir, '');
1458                                         tmp1 := CustomStringReplace(tmp1, '\', '/');
1459                                         tmp := CustomStringReplace(tmp, ExtractFilePath(Setting.CSSFileName),  tmp1);
1460                                 end else if Setting.UseCSS then begin
1461                                         tmp1 := './' + CSSFileName;
1462                                         tmp1 := CustomStringReplace(tmp1, GetConfigDir, '');
1463                                         tmp1 := CustomStringReplace(tmp1, '\', '/');
1464                                         tmp := CustomStringReplace(tmp, CSSFileName,  tmp1);
1465                                 end;
1466                                 html.Append( tmp );
1467
1468                                 for i := 0 to threadItem.Count - 1 do begin
1469
1470                                         // \83\8c\83X
1471                                         html.Append( ConvertResAnchor(boardPlugIn.GetRes( DWORD( threadItem ), i + 1 )) );
1472
1473                                 end;
1474                                 // \83X\83L\83\93(\83t\83b\83^)
1475                                 html.Append( boardPlugIn.GetFooter( DWORD( threadItem ), '<a name="bottom"></a>' ) );
1476                         finally
1477                         end;
1478                         html.EndUpdate;
1479                         Exit;
1480                 end;
1481         end;
1482         ShortDayNames[1] := '\93ú';               ShortDayNames[2] := '\8c\8e';
1483         ShortDayNames[3] := '\89Î';               ShortDayNames[4] := '\90\85';
1484         ShortDayNames[5] := '\96Ø';               ShortDayNames[6] := '\8bà';
1485         ShortDayNames[7] := '\93y';
1486         BBSID := ThreadItem.ParentBoard.BBSID;
1487         ReadList := TStringList.Create;
1488         try
1489                 if ThreadItem.IsLogFile then begin
1490                         FileName := ThreadItem.GetThreadFileName;
1491                         ReadList.LoadFromFile(FileName);
1492                         FAbon.IndividualAbon(ReadList, ChangeFileExt(FileName,'.NG'));
1493                         FAbon.Execute(ReadList);                //       \82 \82Ú\81`\82ñ\82µ\82Ä
1494                         FSelectResFilter.ExecuteEx(ReadList); //\83\8c\83X\82Ì\83t\83B\83\8b\83^\83\8a\83\93\83O\82ð\82·\82é
1495                         Res := DivideStrLine(ReadList[0]);
1496                         Res.FTitle := CustomStringReplace(Res.FTitle, '\81\97\81M', ',');
1497                         sTitle := Res.FTitle;
1498                 end else begin
1499                         sTitle := CustomStringReplace(ThreadItem.Title, '\81\97\81M', ',');
1500                 end;
1501                 try
1502                         // \83t\83H\83\93\83g\82â\83T\83C\83Y\82Ì\90Ý\92è
1503                         if Length( GikoSys.Setting.BrowserFontName ) > 0 then
1504                                 UserOptionalStyle := UserOptionalStyle +
1505                                                                 'font-family:"' + GikoSys.Setting.BrowserFontName + '";';
1506                         if GikoSys.Setting.BrowserFontSize <> 0 then
1507                                 UserOptionalStyle := UserOptionalStyle +
1508                                                                 'font-size:' + IntToStr( GikoSys.Setting.BrowserFontSize ) + 'pt;';
1509                         if GikoSys.Setting.BrowserFontColor <> -1 then
1510                                 UserOptionalStyle := UserOptionalStyle +
1511                                                                 'color:#' + IntToHex( GikoSys.Setting.BrowserFontColor, 6 ) + ';';
1512                         if GikoSys.Setting.BrowserBackColor <> -1 then
1513                                 UserOptionalStyle := UserOptionalStyle +
1514                                                                 'background-color:#' + IntToHex( GikoSys.Setting.BrowserBackColor, 6 ) + ';';
1515                         case GikoSys.Setting.BrowserFontBold of
1516                                 -1: UserOptionalStyle := UserOptionalStyle + 'font-weight:normal;';
1517                                 1: UserOptionalStyle := UserOptionalStyle + 'font-weight:bold;';
1518                         end;
1519                         case GikoSys.Setting.BrowserFontItalic of
1520                                 -1: UserOptionalStyle := UserOptionalStyle + 'font-style:normal;';
1521                                 1: UserOptionalStyle := UserOptionalStyle + 'font-style:italic;';
1522                         end;
1523
1524
1525                         if GikoSys.Setting.UseSkin then begin
1526                                 // \83X\83L\83\93\8eg\97p
1527                                 // \83X\83L\83\93\82Ì\90Ý\92è
1528                                 try
1529                                         SkinHeader := LoadSkin( GetSkinHeaderFileName );
1530                                         if Length( UserOptionalStyle ) > 0 then
1531                                                 SkinHeader := CustomStringReplace( SkinHeader, '</head>',
1532                                                         '<style type="text/css">body {' + UserOptionalStyle + '}</style></head>');
1533                                         //\90â\91Î\8eQ\8fÆ\82©\82ç\91\8a\91Î\8eQ\8fÆ\82Ö
1534                                         tmp1 := './' +Setting.CSSFileName;
1535                                         tmp1 := CustomStringReplace(tmp1, GetConfigDir, '');
1536                                         tmp1 := CustomStringReplace(tmp1, '\', '/');
1537                                         SkinHeader := CustomStringReplace(SkinHeader, ExtractFilePath(Setting.CSSFileName),  tmp1);
1538                                         html.Append( SkinHeader );
1539                                 except
1540                                 end;
1541                                 try
1542                                         SkinRes := LoadSkin( GetSkinResFileName );
1543                                 except
1544                                 end;
1545                                 html.Append('<a name="top"></a>');
1546                                 for i := 0 to ReadList.Count - 1 do begin
1547                                         if (Trim(ReadList[i]) <> '') then begin
1548                                                 No := IntToStr(i + 1);
1549
1550                                                 Res := DivideStrLine(ReadList[i]);
1551                                                 if Res.FType = glt2chOld then begin
1552                                                         Res.FMailTo := CustomStringReplace(Res.FMailTo, '\81\97\81M', ',');
1553                                                         Res.FName := CustomStringReplace(Res.FName, '\81\97\81M', ',');
1554                                                         Res.FBody := CustomStringReplace(Res.FBody, '\81\97\81M', ',');
1555                                                 end;
1556
1557                                                 Res.FBody := AddAnchorTag(Res.FBody);
1558                                                 Res.FBody := ConvertResAnchor(ConvRes(Res.FBody, ThreadItem.ParentBoard.BBSID, ChangeFileExt(ThreadItem.FileName, ''), 'bbs', 'key', 'st', 'to', 'nofirst', 'true', true));
1559
1560                                                 try
1561                                                         html.Append( ReplaceRes( SkinRes ) );
1562                                                 except
1563                                                 end;
1564                                         end;
1565
1566                                 end;
1567                                 html.Append('<a name="bottom"></a>');
1568                                 // \83X\83L\83\93(\83t\83b\83^)
1569                                 try
1570                                         html.Append( LoadSkin( GetSkinFooterFileName ) );
1571                                 except
1572                                 end;
1573                         end else if GikoSys.Setting.UseCSS and FileExists(CSSFileName) then begin
1574                                 //CSS\8eg\97p
1575                                 //CSSFileName := GetAppDir + CSS_FILE_NAME;
1576                                 html.Append('<html><head>');
1577                                 html.Append('<meta http-equiv="Content-type" content="text/html; charset=Shift_JIS">');
1578                                 html.Append('<title>' + sTitle + '</title>');
1579                                 //\90â\91Î\8eQ\8fÆ\82©\82ç\91\8a\91Î\8eQ\8fÆ\82Ö
1580                                 tmp1 := './' + CSSFileName;
1581                                 tmp1 := CustomStringReplace(tmp1, GetConfigDir, '');
1582                                 tmp1 := CustomStringReplace(tmp1, '\', '/');
1583
1584                                 html.Append('<link rel="stylesheet" href="'+tmp1+'" type="text/css">');
1585                                 if Length( UserOptionalStyle ) > 0 then
1586                                         html.Append('<style type="text/css">body {' + UserOptionalStyle + '}</style>');
1587                                 html.Append('</head>');
1588                                 html.Append('<body>');
1589                                 html.Append('<a name="top"></a>');
1590                                 html.Append('<div class="title">' + sTitle + '</div>');
1591                                 for i := 0 to ReadList.Count - 1 do begin
1592                                         if (Trim(ReadList[i]) <> '') then begin
1593                                                 No := IntToStr(i + 1);
1594                                                 Res := DivideStrLine(ReadList[i]);
1595                                                 Res.FBody := AddAnchorTag(Res.FBody);
1596                                                 Res.FBody := ConvertResAnchor(ConvRes(Res.FBody, ThreadItem.ParentBoard.BBSID, ChangeFileExt(ThreadItem.FileName, ''), 'bbs', 'key', 'st', 'to', 'nofirst', 'true', true));
1597                                                 if Res.FMailTo = '' then
1598                                                         html.Append('<a name="' + No + '"></a>'
1599                                                                                         + '<div class="header"><span class="no"><a href="menu:' + No + '">' + No + '</a></span> '
1600                                                                                         + '<span class="name_label">\96¼\91O\81F</span> '
1601                                                                                         + '<span class="name"><b>' + Res.FName + '</b></span> '
1602                                                                                         + '<span class="date_label">\93\8a\8de\93ú\81F</span> '
1603                                                                                         + '<span class="date">' + Res.FDateTime+ '</span></div>'
1604                                                                                                                                                                                 + '<div class="mes">' + Res.FBody + ' </div>')
1605                                                 else if GikoSys.Setting.ShowMail then
1606                                                         html.Append('<a name="' + No + '"></a>'
1607                                                                                         + '<div class="header"><span class="no"><a href="menu:' + No + '">' + No + '</a></span>'
1608                                                                                                                                                                                 + '<span class="name_label"> \96¼\91O\81F </span>'
1609                                                                                         + '<a class="name_mail" href="mailto:' + Res.FMailTo + '">'
1610                                                                                         + '<b>' + Res.FName + '</b></a><span class="mail"> [' + Res.FMailTo + ']</span>'
1611                                                                                         + '<span class="date_label"> \93\8a\8de\93ú\81F</span>'
1612                                                                                         + '<span class="date"> ' + Res.FDateTime+ '</span></div>'
1613                                                                                         + '<div class="mes">' + Res.FBody + ' </div>')
1614                                                 else
1615                                                         html.Append('<a name="' + No + '"></a>'
1616                                                                                         + '<div class="header"><span class="no"><a href="menu:' + No + '">' + No + '</a></span>'
1617                                                                                         + '<span class="name_label"> \96¼\91O\81F </span>'
1618                                                                                         + '<a class="name_mail" href="mailto:' + Res.FMailTo + '">'
1619                                                                                         + '<b>' + Res.FName + '</b></a>'
1620                                                                                         + '<span class="date_label"> \93\8a\8de\93ú\81F</span>'
1621                                                                                         + '<span class="date"> ' + Res.FDateTime+ '</span></div>'
1622                                                                                                                                                                                 + '<div class="mes">' + Res.FBody + ' </div>');
1623                                         end;
1624                                 end;
1625                                 html.Append('<a name="bottom"></a>');
1626                                 html.Append('</body></html>');
1627                                 html.Append('<a name="last"></a>');
1628                                 html.Append('</body></html>');
1629                         end else begin
1630                                 //CSS\94ñ\8eg\97p
1631                                 html.Append('<html><head>');
1632                                 html.Append('<meta http-equiv="Content-type" content="text/html; charset=Shift_JIS">');
1633                                 html.Append('<title>' + sTitle + '</title></head>');
1634                                 html.Append('<body TEXT="#000000" BGCOLOR="#EFEFEF" link="#0000FF" alink="#FF0000" vlink="#660099">');
1635                                 html.Append('<a name="top"></a>');
1636                                 html.Append('<font size=+1 color="#FF0000">' + sTitle + '</font>');
1637                                 html.Append('<dl>');
1638                                 for i := 0 to ReadList.Count - 1 do begin
1639                                         if (Trim(ReadList[i]) <> '') then begin
1640                                                 No := IntToStr(i + 1);
1641                                                 Res := DivideStrLine(ReadList[i]);
1642                                                 if Res.FType = glt2chOld then begin
1643                                                         Res.FMailTo := CustomStringReplace(Res.FMailTo, '\81\97\81M', ',');
1644                                                         Res.FName := CustomStringReplace(Res.FName, '\81\97\81M', ',');
1645                                                         Res.FBody := CustomStringReplace(Res.FBody, '\81\97\81M', ',');
1646                                                 end;
1647                                                 Res.FBody := AddAnchorTag(Res.FBody);
1648                                                 Res.FBody := ConvertResAnchor(ConvRes(Res.FBody, ThreadItem.ParentBoard.BBSID, ChangeFileExt(ThreadItem.FileName, ''), 'bbs', 'key', 'st', 'to', 'nofirst', 'true', true));
1649                                                 if Res.FMailTo = '' then
1650                                                         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>')
1651                                                 else if GikoSys.Setting.ShowMail then
1652                                                         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>')
1653                                                 else
1654                                                         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>');
1655                                         end;
1656                                 end;
1657                                 html.Append('</dl>');
1658                                 html.Append('<a name="bottom"></a>');
1659                                 html.Append('</body></html>');
1660                         end;
1661                 finally
1662                         html.EndUpdate;
1663                 end;
1664         finally
1665                 ReadList.Free;
1666         end;
1667 end;
1668 function TGikoSys.ConvertResAnchor(res: string): string;
1669 const
1670         _HEAD : string = '<a href="../';
1671         _TAIL : string = ' target="_blank">';
1672         _ST: string = '&st=';
1673         _TO: string = '&to=';
1674         _STA: string = '&START=';
1675         _END: string = '&END=';
1676 var
1677         i, j, k: Integer;
1678         tmp: string;
1679 begin
1680         Result := '';
1681         i := AnsiPos(_HEAD, res);
1682         while i <> 0 do begin
1683                 Result := Result + Copy(res, 1, i -1);
1684                 Delete(res, 1, i - 1);
1685                 j := AnsiPos(_TAIL, res);
1686                 if j = 0 then begin
1687                         Result := Result + res;
1688                         Exit;
1689                 end;
1690                 tmp := Copy(res, 1, j - 1);
1691                 Delete(res, 1, j + 16);
1692                 if (AnsiPos(_ST, tmp) <> 0) and (AnsiPos(_TO, tmp) <> 0) then begin
1693                         Delete(tmp, 1, AnsiPos(_ST, tmp) + 3);
1694                         Delete(tmp, AnsiPos(_TO, tmp), Length(tmp));
1695                         Result := Result + '<a href="#' + tmp + '">';
1696                 end else if (AnsiPos(_STA, tmp) <> 0) and (AnsiPos(_END, tmp) <> 0) then begin
1697                         Delete(tmp, 1, AnsiPos(_STA, tmp) + 6);
1698                         Delete(tmp, AnsiPos(_END, tmp), Length(tmp));
1699                         Result := Result + '<a href="#' + tmp + '">';
1700                 end else begin
1701                         k := LastDelimiter('/', tmp);
1702                         Delete(tmp, 1, k);
1703                         if AnsiPos('-', tmp) < AnsiPos('"', tmp) then
1704                                 Delete(tmp, AnsiPos('-', tmp), Length(tmp))
1705                         else
1706                                 Delete(tmp, AnsiPos('"', tmp), Length(tmp));
1707
1708                         Result := Result + '<a href="#' + tmp + '">';
1709                 end;
1710                 i := AnsiPos(_HEAD, res);
1711         end;
1712         Result := Result + res;
1713
1714 end;
1715
1716 (*************************************************************************
1717  *http://\82Ì\95\8e\9a\97ñ\82ðanchor\83^\83O\95t\82«\82É\82·\82é\81B
1718  *************************************************************************)
1719 function TGikoSys.AddAnchorTag(s: string): string;
1720 const
1721         URL_CHAR: string = '0123456789'
1722                                                                          + 'abcdefghijklmnopqrstuvwxyz'
1723                                                                          + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
1724                                                                          + '#$%&()*+,-./:;=?@[]^_`{|}~!''\';
1725         ANCHOR_REF      = 'href=';
1726         RES_REF                 = '&gt;&gt;';
1727 var
1728         wkIdx: array[0..9] of Integer;
1729         url: string;
1730         href: string;
1731         i, b: Integer;
1732         idx: Integer;
1733         anchorLen : Integer;
1734 begin
1735         Result := '';
1736         // + 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ß
1737         anchorLen := Length( ANCHOR_REF ) + 3;
1738
1739         while True do begin
1740                 wkIdx[0] := AnsiPos('http://', s);
1741                 wkIdx[1] := AnsiPos('ttp://', s);
1742                 wkIdx[2] := AnsiPos('tp://', s);
1743                 wkIdx[3] := AnsiPos('ms-help://', s);
1744                 wkIdx[4] := AnsiPos('p://', s);
1745                 wkIdx[5] := AnsiPos('https://', s);
1746                 wkIdx[6] := AnsiPos('www.', s);
1747                 wkIdx[7] := AnsiPos('ftp://', s);
1748                 wkIdx[8] := AnsiPos('news://', s);
1749                 wkIdx[9] := AnsiPos('rtsp://', s);
1750
1751                 idx := MaxInt;
1752                 for i := 0 to 9 do
1753                         if wkIdx[i] <> 0 then idx := Min(wkIdx[i], idx);
1754
1755                 if idx = MaxInt then begin
1756                         //\83\8a\83\93\83N\82ª\96³\82¢\82æ\81B
1757                         Result := Result + s;
1758                         Break;
1759                 end;
1760
1761                 if (idx > 1) and
1762                         (Pos( ANCHOR_REF, Copy(s, idx - anchorLen, anchorLen ) ) > 0) then begin
1763                         //\8aù\82É\83\8a\83\93\83N\83^\83O\82ª\82Â\82¢\82Ä\82¢\82é\82Á\82Û\82¢\82Æ\82«\82Í\83\80\83V
1764                         href := Copy( s, idx, Length( s ) );
1765                         Result := Result + Copy( s, 1, idx + Pos( '</a>', href ) + Length( '</a>' ) - 2 );
1766                         s := href;
1767                         s := Copy( s, Pos( '</a>', s ) + Length( '</a>' ), Length( s ) );
1768
1769                         Continue;
1770                 end;
1771
1772                 Result := Result + Copy(s, 0, idx - 1);
1773
1774                 s := Copy(s, idx, length(s));
1775
1776                 b := Length( s ) + 1;
1777                 for i := 1 to b do begin
1778                         if i = b then
1779         idx := 0
1780       else
1781                                 idx := AnsiPos(s[i], URL_CHAR);
1782                         if idx = 0 then begin
1783                                 //URL\82\82á\82È\82¢\95\8e\9a\94­\8c©\81I\82Æ\82©\81A\95\8e\9a\82ª\82È\82­\82È\82Á\82½\81B
1784                                 url := Copy(s, 0, i - 1);
1785
1786                                 if AnsiPos('ttp://', url) = 1 then
1787                                         href := 'h' + url
1788                                 else if AnsiPos('tp://', url) = 1 then
1789                                         href := 'ht' + url
1790                                 else if AnsiPos('p://', url) = 1 then
1791                                         href := 'htt' + url
1792                                 else if AnsiPos('www.', url) = 1 then
1793                                         href := 'http://' + url
1794                                 else
1795                                         href := url;
1796                                 Result := Result + '<a href="' + href + '" target="_blank">' + url + '</a>';
1797                                 s := Copy(s, i, MaxInt);
1798                                 Break;
1799                         end;
1800                 end;
1801         end;
1802 end;
1803
1804 (*************************************************************************
1805  *\83T\83u\83W\83F\83N\83g\88ê\8ds\82ð\95ª\8a\84
1806  *************************************************************************)
1807 function TGikoSys.DivideSubject(Line: string): TSubjectRec;
1808 var
1809         i: integer;
1810         ws: WideString;
1811         Delim: string;
1812         LeftK: string;
1813         RightK: string;
1814 begin
1815         Result.FCount := 0;
1816
1817         if AnsiPos('<>', Line) = 0 then
1818                 Delim := ','
1819         else
1820                 Delim := '<>';
1821         Result.FFileName := RemoveToken(Line, Delim);
1822         Result.FTitle := RemoveToken(Line, Delim);
1823
1824         ws := Trim(Result.FTitle);
1825
1826         if Copy(ws, Length(ws), 1) = ')' then begin
1827                 LeftK := '(';
1828                 RightK := ')';
1829         end else if Copy(ws, Length(ws), 1) = '\81j' then begin
1830                 LeftK := '\81i';
1831                 RightK := '\81j';
1832         end else if Copy(ws, Length(ws), 1) = '<' then begin
1833                 LeftK := '<';
1834                 RightK := '>';
1835         end;
1836
1837         for i := Length(ws) - 1 downto 1 do begin
1838                 if ws[i] = LeftK then begin
1839                         ws := Copy(ws, i + 1, Length(ws) - i - 1);
1840                         if IsNumeric(ws) then
1841                                 Result.FCount := StrToInt(ws);
1842                         Result.FTitle := Trim(CustomStringReplace(Result.FTitle, LeftK + ws + RightK, ''));
1843                         break;
1844                 end;
1845         end;
1846 end;
1847
1848 (*************************************************************************
1849  * dat\83t\83@\83C\83\8b\82Ì\88ê\83\89\83C\83\93\82ð\95ª\89ð
1850  *************************************************************************)
1851 function TGikoSys.DivideStrLine(Line: string): TResRec;
1852 var
1853         Delim: string;
1854                 bufbody : String;
1855 begin
1856         if AnsiPos('<>', Line) = 0 then begin
1857                 Delim := ',';
1858                 Result.FType := glt2chOld;
1859         end else begin
1860                 Delim := '<>';
1861                 Result.FType := glt2chNew;
1862         end;
1863         Result.FName := Trim(RemoveToken(Line, Delim));
1864         Result.FMailTo := Trim(RemoveToken(Line, Delim));
1865         Result.FDateTime := Trim(RemoveToken(Line, Delim));
1866         bufBody := Trim(RemoveToken(Line, Delim));
1867
1868         if bufbody = '' then begin
1869                 Insert('&nbsp;',bufbody, 1);
1870         end;
1871         Result.FBody := bufBody;
1872         Result.FTitle := Trim(RemoveToken(Line, Delim));
1873
1874 end;
1875
1876 (*************************************************************************
1877  * URL\82©\82çBBSID\82ð\8eæ\93¾
1878  *************************************************************************)
1879 function TGikoSys.UrlToID(url: string): string;
1880 var
1881         i: integer;
1882 begin
1883         Result := '';
1884         url := Trim(url);
1885
1886         if url = '' then Exit;
1887
1888         url := Copy(url, 0, Length(url) - 1);
1889         for i := Length(url) downto 0 do begin
1890                 if url[i] = '/' then begin
1891                         Result := Copy(url, i + 1, Length(url));
1892                         Break;
1893                 end;
1894         end;
1895 end;
1896
1897 (*************************************************************************
1898  *URL\82©\82çBBSID\88È\8aO\82Ì\95\94\95ª(http://teri.2ch.net/)\82ð\8eæ\93¾
1899  *************************************************************************)
1900 function TGikoSys.UrlToServer(url: string): string;
1901 var
1902         i: integer;
1903         wsURL: WideString;
1904 begin
1905         Result := '';
1906         wsURL := url;
1907         wsURL := Trim(wsURL);
1908
1909         if wsURL = '' then exit;
1910
1911         if Copy(wsURL, Length(wsURL), 1) = '/' then
1912                 wsURL := Copy(wsURL, 0, Length(wsURL) - 1);
1913
1914         for i := Length(wsURL) downto 0 do begin
1915                 if wsURL[i] = '/' then begin
1916                         Result := Copy(wsURL, 0, i);
1917                         break;
1918                 end;
1919         end;
1920 end;
1921
1922 (*************************************************************************
1923  *\83f\83B\83\8c\83N\83g\83\8a\82ª\91\8dÝ\82·\82é\82©\83`\83F\83b\83N
1924  *************************************************************************)
1925 function TGikoSys.DirectoryExistsEx(const Name: string): Boolean;
1926 var
1927         Code: Integer;
1928 begin
1929         Code := GetFileAttributes(PChar(Name));
1930         Result := (Code <> -1) and (FILE_ATTRIBUTE_DIRECTORY and Code <> 0);
1931 end;
1932
1933 (*************************************************************************
1934  *\83f\83B\83\8c\83N\83g\83\8a\8dì\90¬\81i\95¡\90\94\8aK\91w\91Î\89\9e\81j
1935  *************************************************************************)
1936 function TGikoSys.ForceDirectoriesEx(Dir: string): Boolean;
1937 begin
1938         Result := True;
1939         if Length(Dir) = 0 then
1940                 raise Exception.Create('\83t\83H\83\8b\83_\82ª\8dì\90¬\8fo\97\88\82Ü\82¹\82ñ');
1941         Dir := ExcludeTrailingPathDelimiter(Dir);
1942         if (Length(Dir) < 3) or DirectoryExistsEx(Dir)
1943                 or (ExtractFilePath(Dir) = Dir) then Exit; // avoid 'xyz:\' problem.
1944         Result := ForceDirectoriesEx(ExtractFilePath(Dir)) and CreateDir(Dir);
1945 end;
1946
1947 (*************************************************************************
1948  *\95\8e\9a\97ñ\82©\82ç\83g\81[\83N\83\93\82Ì\90Ø\82è\8fo\82µ\81i\8f\89\8aú\8f\88\97\9d\81j
1949  *FDelphi\82©\82ç\82Ì\83p\83N\83\8a
1950  *************************************************************************)
1951 function TGikoSys.StrTokFirst(const s:string; const sep: TStrTokSeparator; var Rec: TStrTokRec): string;
1952 begin
1953         Rec.Str := s;
1954         Rec.Pos := 1;
1955         Result := StrTokNext(sep, Rec);
1956 end;
1957
1958 (*************************************************************************
1959  *\95\8e\9a\97ñ\82©\82ç\83g\81[\83N\83\93\82Ì\90Ø\82è\8fo\82µ
1960  *FDelphi\82©\82ç\82Ì\83p\83N\83\8a
1961  *************************************************************************)
1962 function TGikoSys.StrTokNext(const sep: TStrTokSeparator; var Rec: TStrTokRec): string;
1963 var
1964         Len, I: Integer;
1965 begin
1966         with Rec do     begin
1967                 Len := Length(Str);
1968                 Result := '';
1969                 if Len >= Pos then begin
1970                         while (Pos <= Len) and (Str[Pos] in sep) do begin
1971                          Inc(Pos);
1972                         end;
1973                         I := Pos;
1974                         while (Pos<= Len) and not (Str[Pos] in sep) do begin
1975                                 if IsDBCSLeadByte(Byte(Str[Pos])) then begin
1976                                         Inc(Pos);
1977                                 end;
1978                                 Inc(Pos);
1979                         end;
1980                         Result := Copy(Str, I, Pos - I);
1981                         while (Pos <= Len) and (Str[Pos] in sep) do begin// \82±\82ê\82Í\82¨\8dD\82Ý
1982                                 Inc(Pos);
1983                         end;
1984                 end;
1985         end;
1986 end;
1987
1988 (*************************************************************************
1989  *\83t\83@\83C\83\8b\83T\83C\83Y\8eæ\93¾
1990  *************************************************************************)
1991 function TGikoSys.GetFileSize(FileName : string): longint;
1992 var
1993         F : File;
1994 begin
1995         try
1996                 if not FileExists(FileName) then begin
1997                         Result := 0;
1998                         Exit;
1999                 end;
2000                 Assign(F, FileName);
2001                 Reset(F, 1);
2002                 Result := FileSize(F);
2003                 CloseFile(F);
2004         except
2005                 Result := 0;
2006         end;
2007 end;
2008
2009 (*************************************************************************
2010  *\83t\83@\83C\83\8b\8ds\90\94\8eæ\93¾
2011  *************************************************************************)
2012 function TGikoSys.GetFileLineCount(FileName : string): longint;
2013 var
2014         sl: TStringList;
2015 begin
2016         sl := TStringList.Create;
2017         try
2018                 try
2019                         sl.LoadFromFile(FileName);
2020                         Result := sl.Count;
2021                 except
2022                         Result := 0;
2023                 end;
2024         finally
2025                 sl.Free;
2026         end;
2027
2028 end;
2029
2030 (*************************************************************************
2031  *\83X\83\8c\83b\83h\83t\83@\83C\83\8b\82©\82ç\8ew\92è\8ds\82ð\8eæ\93¾
2032  *************************************************************************)
2033 function TGikoSys.ReadThreadFile(FileName: string; Line: Integer): string;
2034 var
2035         fileTmp : TStringList;
2036 begin
2037         Result := '';
2038         if FileExists(FileName) then begin
2039                 fileTmp := TStringList.Create;
2040                 try
2041                         try
2042                                 fileTmp.LoadFromFile( FileName );
2043                                 if ( Line       >= 1 ) and ( Line       < fileTmp.Count + 1 ) then begin
2044                                         Result := fileTmp.Strings[ Line-1 ];
2045                                 end;
2046                         except
2047                                 //on EFOpenError do Result := '';
2048                         end;
2049                 finally
2050                         fileTmp.Free;
2051                 end;
2052         end;
2053 end;
2054
2055 (*************************************************************************
2056  *\83V\83X\83e\83\80\83\81\83j\83\85\81[\83t\83H\83\93\83g\82Ì\91®\90«\82ð\8eæ\93¾
2057  *************************************************************************)
2058 procedure TGikoSys.MenuFont(Font: TFont);
2059 var
2060         lf: LOGFONT;
2061         nm: NONCLIENTMETRICS;
2062 begin
2063         nm.cbSize := sizeof(NONCLIENTMETRICS);
2064
2065         SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, @nm, 0);
2066         lf := nm.lfMenuFont;
2067
2068         Font.Name := lf.lfFaceName;
2069         Font.Height := lf.lfHeight;
2070         Font.Style := [];
2071         if lf.lfWeight >= 700 then
2072                 Font.Style := Font.Style + [fsBold];
2073         if lf.lfItalic = 1 then
2074                 Font.Style := Font.Style + [fsItalic];
2075 end;
2076
2077 (*************************************************************************
2078  *
2079  *\82Ç\82±\82©\82Ì\83T\83C\83g\82©\82ç\82Ì\83p\83N\83\8a
2080  *************************************************************************)
2081 function TGikoSys.RemoveToken(var s: string;const delimiter: string): string;
2082 var
2083         p: Integer;
2084 begin
2085         p := AnsiPos(delimiter, s);
2086         if p = 0 then
2087                 Result := s
2088         else
2089                 Result := Copy(s, 1, p - 1);
2090         s := Copy(s, Length(Result) + Length(delimiter) + 1, Length(s));
2091 end;
2092
2093 (*************************************************************************
2094  *
2095  *\82Ç\82±\82©\82Ì\83T\83C\83g\82©\82ç\82Ì\83p\83N\83\8a
2096  *************************************************************************)
2097 function TGikoSys.GetTokenIndex(s: string; delimiter: string; index: Integer): string;
2098 var
2099         i: Integer;
2100 begin
2101         Result := '';
2102         for i := 0 to index do
2103                 Result := RemoveToken(s, delimiter);
2104 end;
2105
2106 (*************************************************************************
2107  *
2108  *************************************************************************)
2109 function TGikoSys.DeleteLink(const s: string): string;
2110 var
2111         s1: string;
2112         s2: string;
2113         idx: Integer;
2114         i: Integer;
2115 begin
2116         i := 0;
2117         Result := '';
2118         while True do begin
2119                 s1 := GetTokenIndex(s, '<a href="', i);
2120                 s2 := GetTokenIndex(s, '<a href="', i + 1);
2121
2122                 idx := Pos('">', s1);
2123                 if idx <> 0 then
2124                         Delete(s1, 1, idx + 1);
2125                 idx := Pos('">', s2);
2126                 if idx <> 0 then
2127                         Delete(s2, 1, idx + 1);
2128
2129                 Result := Result + s1 + s2;
2130
2131                 if s2 = '' then
2132                         Break;
2133
2134                 inc(i, 2);
2135         end;
2136 end;
2137
2138 //\83C\83\93\83f\83b\83N\83X\96¢\8dX\90V\83o\83b\83t\83@\82ð\83t\83\89\83b\83V\83\85\81I
2139 {procedure TGikoSys.FlashExitWrite;
2140 var
2141         i: Integer;
2142 begin
2143         //\83X\83\8c\83b\83h\83f\81[\83^\83t\83@\83C\83\8b\82ð\8dX\90V
2144         for i := 0 to FExitWrite.Count - 1 do
2145                 WriteThreadDat(FExitWrite[i]);
2146         FExitWrite.Clear;
2147 end;}
2148
2149 (*************************************************************************
2150  *\83X\83\8c\96¼\82È\82Ç\82ð\92Z\82¢\96¼\91O\82É\95Ï\8a·\82·\82é
2151  *from HotZonu
2152  *************************************************************************)
2153 function TGikoSys.GetShortName(const LongName: string; ALength: integer): string;
2154 const
2155         ERASECHAR : array [1..39] of string =
2156                 ('\81\99','\81\9a','\81¡','\81 ','\81\9f','\81\9e','\81Q','\81\94','\81£','\81¥',
2157                  '\81¢','\81¤','\81\9c','\81\9b','\81\9d','\81y','\81z','\81ô','\81s','\81t',
2158                  '\81g','\81h','\81k','\81l','\81e','\81f','\81\83','\81\84','\81á','\81â',
2159                  '\81o','\81p','\81q','\81r','\81w','\81x','\81¬','\81c', '\81@');
2160 var
2161         Chr : array [0..255]    of      char;
2162         S : string;
2163         i : integer;
2164 begin
2165         s := Trim(LongName);
2166         if (Length(s) <= ALength) then begin
2167                 Result := s;
2168         end else begin
2169                 S := s;
2170                 for i := Low(ERASECHAR) to      High(ERASECHAR) do      begin
2171                         S := CustomStringReplace(S, ERASECHAR[i], '');
2172                 end;
2173                 if (Length(S) <= ALength) then begin
2174                         Result := S;
2175                 end else begin
2176                         Windows.LCMapString(
2177                                         GetUserDefaultLCID(),
2178                                         LCMAP_HALFWIDTH,
2179                                         PChar(S),
2180                                         Length(S) + 1,
2181                                         chr,
2182                                         Sizeof(chr)
2183                                         );
2184                         S := Chr;
2185                         S := Copy(S,1,ALength);
2186                         while true do begin
2187                                 if (ByteType(S, Length(S)) = mbLeadByte ) then begin
2188                                         S := Copy(S, 1, Length(S) - 1);
2189                                 end else begin
2190                                         Break;
2191                                 end;
2192                         end;
2193                         Result := S;
2194                 end;
2195         end;
2196 end;
2197
2198 (*************************************************************************
2199  *
2200  * from HotZonu
2201  *************************************************************************)
2202 function TGikoSys.ConvRes(const Body, Bbs, Key,
2203         ParamBBS, ParamKey, ParamStart, ParamTo, ParamNoFirst, ParamTrue : string;
2204         DatToHTML: boolean = false): string;
2205 type
2206         PIndex = ^TIndex;
2207         TIndex = record
2208                 FIndexFrom      : integer;
2209                 FIndexTo                : integer;
2210                 FNo                              : string;
2211         end;
2212 const
2213         GT      = '&gt;';
2214         SN      = '0123456789-';
2215         ZN      = '\82O\82P\82Q\82R\82S\82T\82U\82V\82W\82X\81|';
2216 var
2217         i : integer;
2218         s,r : string;
2219         b : TMbcsByteType;
2220         sw: boolean;
2221         sp: integer;
2222         No: string;
2223         sx: string;
2224         List: TList;
2225         oc      : string;
2226         st, et: string;
2227         chk : boolean;
2228         al : boolean;
2229         procedure Add(IndexFrom, IndexTo: integer; const No: string);
2230         var
2231                 FIndex : PIndex;
2232         begin
2233                 New(FIndex);
2234                 FIndex.FIndexFrom       := IndexFrom;
2235                 FIndex.FIndexTo         := IndexTo;
2236                 FIndex.FNo                               := No;
2237                 List.Add(FIndex);
2238         end;
2239         function ChooseString(const Text, Separator: string; Index: integer): string;
2240         var
2241                 S : string;
2242                 i, p : integer;
2243         begin
2244                 S :=    Text;
2245                 for i :=        0 to    Index - 1 do    begin
2246                         if      (AnsiPos(Separator, S) = 0) then        S :=    ''
2247                         else    S :=    Copy(S, AnsiPos(Separator, S) + Length(Separator), Length(S));
2248                 end;
2249                 p :=    AnsiPos(Separator, S);
2250                 if      (p > 0) then    Result  :=      Copy(S, 1, p - 1) else Result :=        S;
2251         end;
2252 begin
2253         { v1.0 b2 - 03 }
2254         s        :=     Body;
2255         r        :=     Body;
2256         i        :=     1;
2257         sw      :=      False;
2258         No      :=      '';
2259         List:=  TList.Create;
2260         oc      :=      '';
2261         sp      :=      0;
2262         chk :=  False;
2263         al      :=      False;
2264         while true      do      begin
2265                 b :=    ByteType(s, i);
2266                 case    b of
2267                         mbSingleByte    : begin
2268                                 if      (not sw) and (Copy(s,i,8) = GT + GT) then       begin
2269                                         if      (AnsiPos('<A HREF', AnsiUpperCase(oc)) = 0) then        begin
2270                                                 sw      :=      True;
2271                                                 sp      :=      i;
2272                                                 i :=    i + 7;
2273                                                 oc:='';
2274                                                 chk :=  True;
2275                                         end;
2276                                 end else
2277                                 if      (not sw) and (Copy(s,i,8) = GT + GT) then       begin
2278                                         if      (AnsiPos('<A HREF', AnsiUpperCase(oc)) = 1) then        begin
2279                                                 i :=    i + 7;
2280                                                 oc:='';
2281                                                 chk :=  True;
2282                                         end;
2283                                 end else
2284                                 if      (not sw) and (Copy(s,i,4) = GT) then    begin
2285                                         if      (AnsiPos('<A HREF', AnsiUpperCase(oc)) = 0) then        begin
2286                                                 sw      :=      True;
2287                                                 sp      :=      i;
2288                                                 i :=    i + 3;
2289                                                 oc:='';
2290                                                 chk :=  True;
2291                                         end;
2292                                 end else
2293                                 if      ((not sw) and (Copy(s,i,1) = ',')) or
2294                                                 ((not sw) and (Copy(s,i,1) = '=')) then begin
2295                                         if      ((not Chk) and (AnsiLowerCase(oc) = '</a>')) or
2296                                                         ((Chk) and      (oc = '')) or
2297                                                         ((not Chk) and (al)) then
2298                                         begin
2299                                                 sw      :=      True;
2300                                                 sp      :=      i;
2301                                                 //i :=  i + 1;
2302                                                 oc:='';
2303                                         end;
2304                                 end else
2305                                 if      (sw) then begin
2306                                         sx      :=      Copy(s,i,1);
2307                                         if      (AnsiPos(sx, SN) > 0)   then    begin
2308                                                 No      :=      No      + sx;
2309                                         end else begin
2310                                                 if      (No <> '') and (No <> '-')       then   begin
2311                                                         Add(sp, i, No);
2312                                                         al := True;
2313                                                 end;
2314                                                 sw      :=      False;
2315                                                 //
2316                                                 i := i - 1;
2317                                                 //
2318                                                 No      := '';
2319                                                 oc:='';
2320                                                 //chk :=        False;
2321                                         end;
2322                                 end else begin
2323                                         if      Copy(s,i,1) = '<' then  oc      :=      '';
2324                                         oc      :=      oc + Copy(s,i,1);
2325                                         chk :=  False;
2326                                         al      :=      False;
2327                                 end;
2328                         end;
2329                         mbLeadByte      : begin
2330                                 if      (not sw) and (Copy(s,i,4) = '\81\84\81\84') then        begin
2331                                         sw      :=      True;
2332                                         sp      :=      i;
2333                                         i :=    i + 3;
2334                                         chk :=  True;
2335                                 end else
2336                                 if      (not sw) and (Copy(s,i,2) = '\81\84') then  begin
2337                                         sw      :=      True;
2338                                         sp      :=      i;
2339                                         i :=    i + 1;
2340                                         chk :=  True;
2341                                 end else
2342                                 if      (sw) then begin
2343                                         sx      :=      Copy(s,i,2);
2344                                         if      (AnsiPos(sx, ZN) > 0)   then    begin
2345                                                 No      :=      No      + ZenToHan(sx);
2346                                         end else begin
2347                                                 if      (No <> '') and (No <> '-')      and (No <> '\81|') then   begin
2348                                                         Add(sp, i, No);
2349                                                 end;
2350                                                 sw      :=      False;
2351                                                 i := i - 1;
2352                                                 No      :=      '';
2353                                         end;
2354                                 end else begin
2355                                         oc      :=      '';
2356                                         chk :=  False;
2357                                 end;
2358                                 al      :=      False;
2359                         end;
2360                 end;
2361                 inc(i);
2362                 if      (i > Length(Body))      then    begin
2363                         if      (sw)    then    begin
2364                                 if      (No <> '')      then    Add(sp, i, No);
2365                         end;
2366                         Break;
2367                 end;
2368         end;
2369         for i :=        List.Count - 1  downto  0 do    begin
2370                 if      (AnsiPos('-', PIndex(List[i]).FNo) > 0) then    begin
2371                         st      :=      ChooseString(PIndex(List[i]).FNo, '-', 0);
2372                         et      :=      ChooseString(PIndex(List[i]).FNo, '-', 1);
2373                 end else begin
2374                         st      :=      PIndex(List[i]).FNo;
2375                         et      :=      PIndex(List[i]).FNo;
2376                 end;
2377                 if not DatToHTML then
2378                 r :=    Copy(r,0, PIndex(List[i]).FIndexFrom - 1) +
2379                                         Format('<a href="../test/read.cgi?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s" target="_blank">',
2380                                                                 [ParamBBS, Bbs, ParamKey, Key, ParamStart, st, ParamTo, et, ParamNoFirst, ParamTrue]) +
2381                                         Copy(r,PIndex(List[i]).FIndexFrom, PIndex(List[i]).FIndexTo - PIndex(List[i]).FIndexFrom) + '</A>' +
2382                                         Copy(r,PIndex(List[i]).FIndexTo,Length(r))
2383                 else
2384                 r :=    Copy(r,0, PIndex(List[i]).FIndexFrom - 1) +
2385                                         Format('<a href="#%s">', [st]) +
2386                                         Copy(r,PIndex(List[i]).FIndexFrom, PIndex(List[i]).FIndexTo - PIndex(List[i]).FIndexFrom) + '</A>' +
2387                                         Copy(r,PIndex(List[i]).FIndexTo,Length(r));
2388
2389                 Dispose(PIndex(List[i]));
2390         end;
2391         List.Free;
2392         Result  :=      r;
2393 end;
2394
2395 function TGikoSys.ConvRes(
2396         const Body, Bbs, Key, ParamBBS, ParamKey,
2397     ParamStart, ParamTo, ParamNoFirst,
2398         ParamTrue, FullURL : string
2399 ): string;
2400 type
2401         PIndex = ^TIndex;
2402         TIndex = record
2403                 FIndexFrom      : integer;
2404                 FIndexTo                : integer;
2405                 FNo                              : string;
2406         end;
2407 const
2408         GT      = '&gt;';
2409         SN      = '0123456789-';
2410         ZN      = '\82O\82P\82Q\82R\82S\82T\82U\82V\82W\82X\81|';
2411 var
2412         i : integer;
2413         s,r : string;
2414         b : TMbcsByteType;
2415         sw: boolean;
2416         sp: integer;
2417         No: string;
2418         sx: string;
2419         List: TList;
2420         oc      : string;
2421         st, et: string;
2422         chk : boolean;
2423         al : boolean;
2424         procedure Add(IndexFrom, IndexTo: integer; const No: string);
2425         var
2426                 FIndex : PIndex;
2427         begin
2428                 New(FIndex);
2429                 FIndex.FIndexFrom       := IndexFrom;
2430                 FIndex.FIndexTo         := IndexTo;
2431                 FIndex.FNo                               := No;
2432                 List.Add(FIndex);
2433         end;
2434         function ChooseString(const Text, Separator: string; Index: integer): string;
2435         var
2436                 S : string;
2437                 i, p : integer;
2438         begin
2439                 S :=    Text;
2440                 for i :=        0 to    Index - 1 do    begin
2441                         if      (AnsiPos(Separator, S) = 0) then        S :=    ''
2442                         else    S :=    Copy(S, AnsiPos(Separator, S) + Length(Separator), Length(S));
2443                 end;
2444                 p :=    AnsiPos(Separator, S);
2445                 if      (p > 0) then    Result  :=      Copy(S, 1, p - 1) else Result :=        S;
2446         end;
2447 begin
2448         { v1.0 b2 - 03 }
2449         s        :=     Body;
2450         r        :=     Body;
2451         i        :=     1;
2452         sw      :=      False;
2453         No      :=      '';
2454         List:=  TList.Create;
2455         oc      :=      '';
2456         sp      :=      0;
2457         chk :=  False;
2458         al      :=      False;
2459         while true      do      begin
2460                 b :=    ByteType(s, i);
2461                 case    b of
2462                         mbSingleByte    : begin
2463                                 if      (not sw) and (Copy(s,i,8) = GT + GT) then       begin
2464                                         if      (AnsiPos('<A HREF', AnsiUpperCase(oc)) = 0) then        begin
2465                                                 sw      :=      True;
2466                                                 sp      :=      i;
2467                                                 i :=    i + 7;
2468                                                 oc:='';
2469                                                 chk :=  True;
2470                                         end;
2471                                 end else
2472                                 if      (not sw) and (Copy(s,i,8) = GT + GT) then       begin
2473                                         if      (AnsiPos('<A HREF', AnsiUpperCase(oc)) = 1) then        begin
2474                                                 i :=    i + 7;
2475                                                 oc:='';
2476                                                 chk :=  True;
2477                                         end;
2478                                 end else
2479                                 if      (not sw) and (Copy(s,i,4) = GT) then    begin
2480                                         if      (AnsiPos('<A HREF', AnsiUpperCase(oc)) = 0) then        begin
2481                                                 sw      :=      True;
2482                                                 sp      :=      i;
2483                                                 i :=    i + 3;
2484                                                 oc:='';
2485                                                 chk :=  True;
2486                                         end;
2487                                 end else
2488                                 if      ((not sw) and (Copy(s,i,1) = ',')) or
2489                                                 ((not sw) and (Copy(s,i,1) = '=')) then begin
2490                                         if      ((not Chk) and (AnsiLowerCase(oc) = '</a>')) or
2491                                                         ((Chk) and      (oc = '')) or
2492                                                         ((not Chk) and (al)) then
2493                                         begin
2494                                                 sw      :=      True;
2495                                                 sp      :=      i;
2496                                                 //i :=  i + 1;
2497                                                 oc:='';
2498                                         end;
2499                                 end else
2500                                 if      (sw) then begin
2501                                         sx      :=      Copy(s,i,1);
2502                                         if      (AnsiPos(sx, SN) > 0)   then    begin
2503                                                 No      :=      No      + sx;
2504                                         end else begin
2505                                                 if      (No <> '') and (No <> '-')       then   begin
2506                                                         Add(sp, i, No);
2507                                                         al := True;
2508                                                 end;
2509                                                 sw      :=      False;
2510                                                 //
2511                                                 i := i - 1;
2512                                                 //
2513                                                 No      := '';
2514                                                 oc:='';
2515                                                 //chk :=        False;
2516                                         end;
2517                                 end else begin
2518                                         if      Copy(s,i,1) = '<' then  oc      :=      '';
2519                                         oc      :=      oc + Copy(s,i,1);
2520                                         chk :=  False;
2521                                         al      :=      False;
2522                                 end;
2523                         end;
2524                         mbLeadByte      : begin
2525                                 if      (not sw) and (Copy(s,i,4) = '\81\84\81\84') then        begin
2526                                         sw      :=      True;
2527                                         sp      :=      i;
2528                                         i :=    i + 3;
2529                                         chk :=  True;
2530                                 end else
2531                                 if      (not sw) and (Copy(s,i,2) = '\81\84') then  begin
2532                                         sw      :=      True;
2533                                         sp      :=      i;
2534                                         i :=    i + 1;
2535                                         chk :=  True;
2536                                 end else
2537                                 if      (sw) then begin
2538                                         sx      :=      Copy(s,i,2);
2539                                         if      (AnsiPos(sx, ZN) > 0)   then    begin
2540                                                 No      :=      No      + ZenToHan(sx);
2541                                         end else begin
2542                                                 if      (No <> '') and (No <> '-')      and (No <> '\81|') then   begin
2543                                                         Add(sp, i, No);
2544                                                 end;
2545                                                 sw      :=      False;
2546                                                 i := i - 1;
2547                                                 No      :=      '';
2548                                         end;
2549                                 end else begin
2550                                         oc      :=      '';
2551                                         chk :=  False;
2552                                 end;
2553                                 al      :=      False;
2554                         end;
2555                 end;
2556                 inc(i);
2557                 if      (i > Length(Body))      then    begin
2558                         if      (sw)    then    begin
2559                                 if      (No <> '')      then    Add(sp, i, No);
2560                         end;
2561                         Break;
2562                 end;
2563         end;
2564         for i :=        List.Count - 1  downto  0 do    begin
2565         //plName := Copy(PluginName, LastDelimiter('\',PluginName) + 1, Length(PluginName) - LastDelimiter('/',PluginName) -1 );
2566                 if      (AnsiPos('-', PIndex(List[i]).FNo) > 0) then    begin
2567                         st      :=      ChooseString(PIndex(List[i]).FNo, '-', 0);
2568                         et      :=      ChooseString(PIndex(List[i]).FNo, '-', 1);
2569                 end else begin
2570                         st      :=      PIndex(List[i]).FNo;
2571                         et      :=      PIndex(List[i]).FNo;
2572                 end;
2573                 r :=    Copy(r,0, PIndex(List[i]).FIndexFrom - 1) +
2574                                         Format('<a href="%s&%s=%s&%s=%s&%s=%s" target="_blank">',
2575                                                                 [FullURL, ParamStart, st, ParamTo, et, ParamNoFirst, ParamTrue]) +
2576                                         Copy(r,PIndex(List[i]).FIndexFrom, PIndex(List[i]).FIndexTo - PIndex(List[i]).FIndexFrom) + '</A>' +
2577                                         Copy(r,PIndex(List[i]).FIndexTo,Length(r));
2578                 Dispose(PIndex(List[i]));
2579         end;
2580         List.Free;
2581         Result  :=      r;
2582 end;
2583
2584
2585 function TGikoSys.BoolToInt(b: Boolean): Integer;
2586 begin
2587         Result := IfThen(b, 1, 0);
2588 end;
2589
2590 function TGikoSys.IntToBool(i: Integer): Boolean;
2591 begin
2592         Result := i = 1;
2593 end;
2594
2595 //gzip\82Å\88³\8fk\82³\82ê\82½\82Ì\82ð\96ß\82·
2596 function TGikoSys.GzipDecompress(ResStream: TStream; ContentEncoding: string): string;
2597 const
2598         BUF_SIZE = 4096;
2599 var
2600         GZipStream: TGzipDecompressStream;
2601         TextStream: TStringStream;
2602         buf: array[0..BUF_SIZE - 1] of Byte;
2603         cnt: Integer;
2604         s: string;
2605         i: Integer;
2606 begin
2607         Result := '';
2608         TextStream := TStringStream.Create('');
2609         try
2610 //\83m\81[\83g\83\93\83E\83\93\83`\83E\83B\83\8b\83X2003\91Î\8dô(x-gzip\82Æ\82©\82É\82È\82é\82Ý\82½\82¢)
2611 //              if LowerCase(Trim(ContentEncoding)) = 'gzip' then begin
2612                 if AnsiPos('gzip', LowerCase(Trim(ContentEncoding))) > 0 then begin
2613                         ResStream.Position := 0;
2614                         GZipStream := TGzipDecompressStream.Create(TextStream);
2615                         try
2616                                 repeat
2617                                         FillChar(buf, BUF_SIZE, 0);
2618                                         cnt := ResStream.Read(buf, BUF_SIZE);
2619                                         if cnt > 0 then
2620                                                 GZipStream.Write(buf, BUF_SIZE);
2621                                 until cnt = 0;
2622                         finally
2623                                 GZipStream.Free;
2624                         end;
2625                 end else begin
2626                         ResStream.Position := 0;
2627                         repeat
2628                                 FillChar(buf, BUF_SIZE, 0);
2629                                 cnt := ResStream.Read(buf, BUF_SIZE);
2630                                 if cnt > 0 then
2631                                         TextStream.Write(buf, BUF_SIZE);
2632                         until cnt = 0;
2633                 end;
2634
2635                 //NULL\95\8e\9a\82ð"*"\82É\82·\82é
2636                 s := TextStream.DataString;
2637                 i := Length(s);
2638                 while (i > 0) and (s[i] = #0) do
2639                         Dec(i);
2640                 s := Copy(s, 1, i);
2641
2642                 i := Pos(#0, s);
2643                 while i <> 0 do begin
2644                         s[i] := '*';
2645                         i := Pos(#0, s);
2646                 end;
2647                 Result := s;
2648         finally
2649                 TextStream.Free;
2650         end;
2651 end;
2652
2653 procedure TGikoSys.LoadKeySetting(ActionList: TActionList);
2654 const
2655         STD_SEC = 'KeySetting';
2656 var
2657         i: Integer;
2658         ini: TMemIniFile;
2659         ActionName: string;
2660         ActionKey: Integer;
2661         SecList: TStringList;
2662         Component: TComponent;
2663 begin
2664         if not FileExists(GetConfigDir + KEY_SETTING_FILE_NAME) then
2665                 Exit;
2666         SecList := TStringList.Create;
2667         ini := TMemIniFile.Create(GetConfigDir + KEY_SETTING_FILE_NAME);
2668         try
2669                 ini.ReadSection(STD_SEC, SecList);
2670                 for i := 0 to SecList.Count - 1 do begin
2671                         ActionName := SecList[i];
2672                         ActionKey := ini.ReadInteger(STD_SEC, ActionName, -1);
2673                         if ActionKey <> -1 then begin
2674                                 Component := ActionList.Owner.FindComponent(ActionName);
2675                                 if TObject(Component) is TAction then begin
2676                                         TAction(Component).ShortCut := ActionKey;
2677                                 end;
2678                         end;
2679                 end;
2680         finally
2681                 ini.Free;
2682                 SecList.Free;
2683         end;
2684 end;
2685
2686 procedure TGikoSys.SaveKeySetting(ActionList: TActionList);
2687 const
2688         STD_SEC = 'KeySetting';
2689 var
2690         i: Integer;
2691         ini: TMemIniFile;
2692 begin
2693         ini := TMemIniFile.Create(GetConfigDir + KEY_SETTING_FILE_NAME);
2694         try
2695                 for i := 0 to ActionList.ActionCount - 1 do begin
2696                         if ActionList.Actions[i].Tag = -1 then
2697                                 Continue;
2698                         ini.WriteInteger(STD_SEC, ActionList.Actions[i].Name, TAction(ActionList.Actions[i]).ShortCut);
2699                 end;
2700                 ini.UpdateFile;
2701         finally
2702                 ini.Free;
2703         end;
2704 end;
2705
2706 procedure TGikoSys.LoadEditorKeySetting(ActionList: TActionList);
2707 const
2708         STD_SEC = 'KeySetting';
2709 var
2710         i: Integer;
2711         ini: TMemIniFile;
2712         ActionName: string;
2713         ActionKey: Integer;
2714         SecList: TStringList;
2715         Component: TComponent;
2716 begin
2717         if not FileExists(GetConfigDir + EKEY_SETTING_FILE_NAME) then
2718                 Exit;
2719         SecList := TStringList.Create;
2720         ini := TMemIniFile.Create(GetConfigDir + EKEY_SETTING_FILE_NAME);
2721         try
2722                 ini.ReadSection(STD_SEC, SecList);
2723                 for i := 0 to SecList.Count - 1 do begin
2724                         ActionName := SecList[i];
2725                         ActionKey := ini.ReadInteger(STD_SEC, ActionName, -1);
2726                         if ActionKey <> -1 then begin
2727                                 Component := ActionList.Owner.FindComponent(ActionName);
2728                                 if TObject(Component) is TAction then begin
2729                                         TAction(Component).ShortCut := ActionKey;
2730                                 end;
2731                         end;
2732                 end;
2733         finally
2734                 ini.Free;
2735                 SecList.Free;
2736         end;
2737 end;
2738
2739 procedure TGikoSys.SaveEditorKeySetting(ActionList: TActionList);
2740 const
2741         STD_SEC = 'KeySetting';
2742 var
2743         i: Integer;
2744         ini: TMemIniFile;
2745 begin
2746         ini := TMemIniFile.Create(GetConfigDir + EKEY_SETTING_FILE_NAME);
2747         try
2748                 for i := 0 to ActionList.ActionCount - 1 do begin
2749                         if ActionList.Actions[i].Tag = -1 then
2750                                 Continue;
2751                         ini.WriteInteger(STD_SEC, ActionList.Actions[i].Name, TAction(ActionList.Actions[i]).ShortCut);
2752                 end;
2753                 ini.UpdateFile;
2754         finally
2755                 ini.Free;
2756         end;
2757 end;
2758
2759 //
2760 procedure TGikoSys.CreateProcess(const AppPath: string; const Param: string);
2761 var
2762         PI: TProcessInformation;
2763         SI: TStartupInfo;
2764         Path: string;
2765 begin
2766         Path := '"' + AppPath + '"';
2767         if Param <> '' then
2768                 Path := Path + ' ' + Param;
2769
2770         SI.Cb := SizeOf(Si);
2771         SI.lpReserved   := nil;
2772         SI.lpDesktop     := nil;
2773         SI.lpTitle               := nil;
2774         SI.dwFlags               := 0;
2775         SI.cbReserved2 := 0;
2776         SI.lpReserved2 := nil;
2777         SI.dwysize               := 0;
2778         Windows.CreateProcess(nil,
2779                                                                 PChar(Path),
2780                                                                 nil,
2781                                                                 nil,
2782                                                                 False,
2783                                                                 0,
2784                                                                 nil,
2785                                                                 nil,
2786                                                                 SI,
2787                                                                 PI);
2788 end;
2789
2790 procedure TGikoSys.OpenBrowser(URL: string; BrowserType: TGikoBrowserType);
2791 begin
2792         case BrowserType of
2793                 gbtIE:
2794                         HlinkNavigateString(nil, PWideChar(WideString(URL)));
2795                 gbtUserApp, gbtAuto:
2796                         if (Setting.URLApp) and (FileExists(Setting.URLAppFile)) then
2797                                 GikoSys.CreateProcess(Setting.URLAppFile, URL)
2798                         else
2799                                 HlinkNavigateString(nil, PWideChar(WideString(URL)));
2800         end;
2801 end;
2802
2803 function TGikoSys.HTMLDecode(const AStr: String): String;
2804 var
2805         Sp, Rp, Cp, Tp: PChar;
2806         S: String;
2807         I, Code: Integer;
2808         Num: Boolean;
2809 begin
2810         SetLength(Result, Length(AStr));
2811         Sp := PChar(AStr);
2812         Rp := PChar(Result);
2813         //Cp := Sp;
2814         try
2815                 while Sp^ <> #0 do begin
2816                         case Sp^ of
2817                                 '&': begin
2818                                                          //Cp := Sp;
2819                                                          Inc(Sp);
2820                                                          case Sp^ of
2821                                                                  'a': if AnsiStrPos(Sp, 'amp;') = Sp then
2822                                                                                         begin
2823                                                                                                 Inc(Sp, 3);
2824                                                                                                 Rp^ := '&';
2825                                                                                         end;
2826                                                                  'l',
2827                                                                  'g': if (AnsiStrPos(Sp, 'lt;') = Sp) or (AnsiStrPos(Sp, 'gt;') = Sp) then
2828                                                                                         begin
2829                                                                                                 Cp := Sp;
2830                                                                                                 Inc(Sp, 2);
2831                                                                                                 while (Sp^ <> ';') and (Sp^ <> #0) do
2832                                                                                                         Inc(Sp);
2833                                                                                                 if Cp^ = 'l' then
2834                                                                                                         Rp^ := '<'
2835                                                                                                 else
2836                                                                                                         Rp^ := '>';
2837                                                                                         end;
2838                                                                  'q': if AnsiStrPos(Sp, 'quot;') = Sp then
2839                                                                                         begin
2840                                                                                                 Inc(Sp,4);
2841                                                                                                 Rp^ := '"';
2842                                                                                         end;
2843                                                                  '#': begin
2844                                                                                                 Tp := Sp;
2845                                                                                                 Inc(Tp);
2846                                                                                                 Num := IsNumeric(Copy(Tp, 1, 1));
2847                                                                                                 while (Sp^ <> ';') and (Sp^ <> #0) do begin
2848                                                                                                         if (Num) and (not IsNumeric(Copy(Sp, 1, 1))) then
2849                                                                                                                 Break;
2850                                                                                                         Inc(Sp);
2851                                                                                                 end;
2852                                                                                                 SetString(S, Tp, Sp - Tp);
2853                                                                                                 Val(S, I, Code);
2854                                                                                                 Rp^ := Chr((I));
2855                                                                                         end;
2856                                                          //      else
2857                                                                          //raise EConvertError.CreateFmt(sInvalidHTMLEncodedChar,
2858                                                                                  //[Cp^ + Sp^, Cp - PChar(AStr)])
2859                                                          end;
2860                                          end
2861                         else
2862                                 Rp^ := Sp^;
2863                         end;
2864                         Inc(Rp);
2865                         Inc(Sp);
2866                 end;
2867         except
2868 //              on E:EConvertError do
2869 //                      raise EConvertError.CreateFmt(sInvalidHTMLEncodedChar,
2870 //                              [Cp^ + Sp^, Cp - PChar(AStr)])
2871         end;
2872         SetLength(Result, Rp - PChar(Result));
2873 end;
2874
2875 function TGikoSys.GetHRefText(s: string): string;
2876 var
2877         Index: Integer;
2878         Index2: Integer;
2879 begin
2880         Result := '';
2881         s := Trim(s);
2882         if s = '' then
2883                 Exit;
2884
2885         Index := AnsiPos('href', LowerCase(s));
2886         if Index = 0 then
2887                 Exit;
2888         s := Trim(Copy(s, Index + 4, Length(s)));
2889         s := Trim(Copy(s, 2, Length(s)));
2890
2891         //\8en\82ß\82Ì\95\8e\9a\82ª'"'\82È\82ç\8eæ\82è\8f\9c\82­
2892         //if Copy(s, 1, 1) = '"' then begin
2893     if s[1]  = '"' then begin
2894                 s := Trim(Copy(s, 2, Length(s)));
2895         end;
2896
2897         Index := AnsiPos('"', s);
2898         if Index <> 0 then begin
2899                 //'"'\82Ü\82ÅURL\82Æ\82·\82é
2900                 s := Copy(s, 1, Index - 1);
2901         end else begin
2902                 //'"'\82ª\96³\82¯\82ê\82Î\83X\83y\81[\83X\82©">"\82Ì\91\81\82¢\95û\82Ü\82Å\82ðURL\82Æ\82·\82é
2903                 Index := AnsiPos(' ', s);
2904                 Index2 := AnsiPos('>', s);
2905                 if Index = 0 then
2906                         Index := Index2;
2907                 if Index > Index2 then
2908                         Index := Index2;
2909                 if Index <> 0 then
2910                         s := Copy(s, 1, Index - 1)
2911                 else
2912                         //\82±\82ê\88È\8fã\82à\82¤\92m\82ç\82ñ\82Ê
2913                         ;
2914         end;
2915         Result := Trim(s);
2916 end;
2917
2918 //\83z\83X\83g\96¼\82ª\82Q\82\83\82\88\82©\82Ç\82¤\82©\83`\83F\83b\83N\82·\82é
2919 function TGikoSys.Is2chHost(Host: string): Boolean;
2920 const
2921         HOST_NAME: array[0..1] of string = ('2ch.net', 'bbspink.com');
2922 var
2923         i: Integer;
2924 //      Len: Integer;
2925 begin
2926         Result := False;
2927         if RightStr( Host, 1 ) = '/' then
2928                 Host := Copy( Host, 1, Length( Host ) - 1 );
2929         OutputDebugString(pchar(HOST_NAME[0]));
2930         for i := 0 to Length(HOST_NAME) - 1 do begin
2931 //              Len := Length(HOST_NAME[i]);
2932                 if AnsiPos(HOST_NAME[i], Host) = (Length(Host) - Length(HOST_NAME[i]) + 1) then begin
2933                         Result := True;
2934                         Exit;
2935                 end;
2936         end;
2937 end;
2938
2939 function TGikoSys.Parse2chURL(const url: string; const path: string; const document: string; var BBSID: string; var BBSKey: string): Boolean;
2940 var
2941         Index: Integer;
2942         s: string;
2943         SList: TStringList;
2944 begin
2945         BBSID := '';
2946         BBSKey := '';
2947         Result := False;
2948
2949         Index := AnsiPos(READ_PATH, path);
2950         if Index <> 0 then begin
2951                 s := Copy(path, Index + Length(READ_PATH), Length(path));
2952                 if s[1] = '/' then
2953                         Delete(s, 1, 1);
2954                 BBSID := GetTokenIndex(s, '/', 0);
2955                 BBSKey := GetTokenIndex(s, '/', 1);
2956                 if BBSKey = '' then
2957                         BBSKey := Document;
2958                 Result := (BBSID <> '') or (BBSKey <> '');
2959                 Exit;
2960         end;
2961         Index := AnsiPos(KAKO_PATH, path);
2962         if Index <> 0 then begin
2963                 s := Copy(path, 2, Length(path));
2964                 BBSID := GetTokenIndex(s, '/', 0);
2965                 if (BBSID = 'log') and (GetTokenIndex(s, '/', 2) = 'kako') then
2966                         BBSID := GetTokenIndex(s, '/', 1);
2967                 BBSKey := ChangeFileExt(Document, '');
2968                 Result := (BBSID <> '') or (BBSKey <> '');
2969                 Exit;
2970         end;
2971         Index := AnsiPos('read.cgi?', URL);
2972         if Index <> 0 then begin
2973                 SList := TStringList.Create;
2974                 try
2975                         try
2976 //                              s := HTMLDecode(Document);
2977                                 ExtractHTTPFields(['?', '&'], [], PChar(URL), SList, False);
2978                                 BBSID := SList.Values['bbs'];
2979                                 BBSKey := SList.Values['key'];
2980                                 Result := (BBSID <> '') or (BBSKey <> '');
2981                                 Exit;
2982                         except
2983                                 Exit;
2984                         end;
2985                 finally
2986                         SList.Free;
2987                 end;
2988         end;
2989 end;
2990 procedure TGikoSys.GetPopupResNumber(URL : string; var stRes, endRes : Int64);
2991 var
2992     buf : String;
2993     convBuf : String;
2994     ps : Int64;
2995     pch : PChar;
2996 begin
2997         URL := Trim(LowerCase(URL));
2998     if (AnsiPos('&st=', URL ) <> 0) and ( AnsiPos( '&to=',URL) <> 0 ) then begin
2999         try
3000             stRes := StrToInt64( Copy( URL, AnsiPos('&st=', URL ) + 4, AnsiPos( '&to=',URL) - AnsiPos('&st=', URL ) - 4 ) );
3001             if AnsiPos( '&nofirst=',URL) <> 0 then begin
3002                 buf := Copy( URL, AnsiPos('&to=', URL ) + 4, AnsiPos( '&nofirst=',URL) - AnsiPos('&to=', URL ) - 4);
3003             end else begin
3004                 buf := Copy( URL, AnsiPos('&to=', URL ) + 4, Length( URL ) - AnsiPos('&to=', URL ) - 4 + 1 );
3005                 ps := 0;
3006                 pch := PChar(buf);
3007                 while  ( ps < Length(buf) )and ( pch[ps] >= '0' ) and ( pch[ps] <= '9' ) do Inc(ps);
3008                 buf := Copy( buf, 1, ps );
3009             end;
3010             try
3011                 if buf <> '' then
3012                     endRes := StrToInt64(buf);
3013             except
3014                 endRes := 0;
3015             end;
3016         except
3017             stRes := 0;
3018         end;
3019         GikoSys.GetBrowsableThreadURL( URL );
3020     end else if( AnsiPos('&res=', URL ) <> 0 ) then begin
3021         endRes := 0;
3022         buf := Copy( URL, AnsiPos('&res=', URL ) + 5, Length( URL ) - AnsiPos('&res=', URL ) - 5 + 1 );
3023         ps := 0;
3024         pch := PChar(buf);
3025         while  ( ps < Length(buf) )and ( pch[ps] >= '0' ) and ( pch[ps] <= '9' ) do Inc(ps);
3026         buf := Copy( buf, 1, ps );
3027         try
3028             if buf <> '' then
3029                 stRes := StrToInt(buf)
3030             else begin
3031                 stRes := 0;
3032             end;
3033         except
3034             stRes := 0;
3035         end;
3036     end else if (AnsiPos('&start=', URL ) <> 0) and ( AnsiPos( '&end=',URL) <> 0 ) then begin
3037         try
3038             stRes := StrToInt64( Copy( URL, AnsiPos('&start=', URL ) + 7, AnsiPos( '&end=',URL) - AnsiPos('&start=', URL ) - 7 ) );
3039             if AnsiPos( '&nofirst=',URL) <> 0 then begin
3040                 buf := Copy( URL, AnsiPos('&end=', URL ) + 5, AnsiPos( '&nofirst=',URL) - AnsiPos('&end=', URL ) - 5);
3041             end else begin
3042                 buf := Copy( URL, AnsiPos('&end=', URL ) + 5, Length( URL ) - AnsiPos('&to=', URL ) - 5 + 1 );
3043                 ps := 0;
3044                 pch := PChar(buf);
3045                 while  ( ps < Length(buf) )and ( pch[ps] >= '0' ) and ( pch[ps] <= '9' ) do Inc(ps);
3046                 buf := Copy( buf, 1, ps );
3047             end;
3048             try
3049                 if buf <> '' then
3050                     endRes := StrToInt64(buf);
3051             except
3052                 endRes := 0;
3053             end;
3054         except
3055             stRes := 0;
3056         end;
3057     end else if ( AnsiPos('.html',URL) <> Length(URL) -4 ) and ( AnsiPos('.htm',URL) <> Length(URL) -3 ) then begin
3058         buf := Copy(URL, LastDelimiter('/',URL)+1,Length(URL)-LastDelimiter('/',URL)+1);
3059         if  Length(buf) > 0 then begin
3060             ps := 0;
3061             pch := PChar(buf);
3062             while  ( ps < Length(buf) )and ( pch[ps] >= '0' ) and ( pch[ps] <= '9' ) do Inc(ps);
3063             try
3064                 convBuf := Copy( buf, 1, ps );
3065                 if convBuf <> '' then begin
3066                     stRes := StrToInt64(convBuf);
3067                     Delete(buf,1,ps+1);
3068                     ps := 0;
3069                     pch := PChar(buf);
3070                     while  ( ps < Length(buf) )and ( pch[ps] >= '0' ) and ( pch[ps] <= '9' ) do Inc(ps);
3071                     try
3072                         convBuf := Copy( buf, 1, ps );
3073                         if convBuf <> '' then
3074                             endRes := StrToInt64(convBuf)
3075                         else
3076                             endRes := 0;
3077                     except
3078                         endRes := 0;
3079                     end;
3080                 end else begin
3081                     stRes := 0;
3082                 end;
3083
3084             except
3085                 stRes := 0;
3086                 endRes := 0;
3087             end;
3088
3089         end;
3090     end else begin
3091             //stRes := 0;
3092         //endRes := 0;
3093     end;
3094 end;
3095
3096 function TGikoSys.Parse2chURL2(URL: string): TPathRec;
3097 var
3098         i: Integer;
3099         s: string;
3100 //      buf : String;
3101 //      convBuf : String;
3102         wk: string;
3103         wkMin: Integer;
3104         wkMax: Integer;
3105         wkInt: Integer;
3106         RStart: Integer;
3107         RLength: Integer;
3108 //      ps : Integer;
3109 //      pch : PChar;
3110         SList: TStringList;
3111 begin
3112         URL := Trim(LowerCase(URL));
3113         Result.FBBS := '';
3114         Result.FKey := '';
3115         Result.FSt := 0;
3116         Result.FTo := 0;
3117         Result.FFirst := False;
3118         Result.FStBegin := False;
3119         Result.FToEnd := False;
3120         Result.FDone := False;
3121
3122         wkMin := 0;
3123         wkMax := 1;
3124         if URL[length(URL)] = '\' then
3125                 URL := URL + 'n';
3126         FAWKStr.RegExp := 'http://.+\.(2ch\.net|bbspink\.com)/';
3127         if FAWKStr.Match(FAWKStr.ProcessEscSeq(URL), RStart, RLength) <> 0 then begin
3128                 s := Copy(URL, RStart + RLength - 1, Length(URL));
3129
3130                 //\95W\8f\80\8f\91\8e®
3131                 //\8dÅ\8cã\82Íl50, 10, 10-20, 10n, 10-20n, -10, 10-, 10n- \82È\82Ç
3132                 //http://xxx.2ch.net/test/read.cgi/bbsid/1000000000/
3133                 FAWKStr.RegExp := '/test/read.cgi/.+/[0-9]+/?.*';
3134                 if FAWKStr.Match(FAWKStr.ProcessEscSeq(s), RStart, RLength) > 0 then begin
3135                         s := Copy(s, 15, Length(s));
3136
3137                         SList := TStringList.Create;
3138                         try
3139                                 SList.Clear;
3140                                 FAWKStr.RegExp := '/';
3141                                 if FAWKStr.Split(FAWKStr.ProcessEscSeq(s), SList) >= 3 then begin
3142                                         Result.FBBS := SList[1];
3143                                         Result.FKey := SList[2];
3144                                         if SList.Count >= 4 then
3145                                                 s := SList[3]
3146                                         else begin
3147                                                 s := '';
3148                                                 Result.FSt := 1;
3149                                                 Result.FTo := 1;
3150                                         end;
3151                                 end else
3152                                         Exit;
3153
3154                                 SList.Clear;
3155                                 FAWKStr.LineSeparator := mcls_CRLF;
3156                                 FAWKStr.RegExp := '-';
3157                                 if FAWKStr.Split(FAWKStr.ProcessEscSeq(s), SList) = 0 then begin
3158                                         Result.FFirst := True;
3159                                 end else begin
3160                                         FAWKStr.RegExp := 'l[0-9]+';
3161                                         if FAWKStr.Match(FAWKStr.ProcessEscSeq(s), RStart, RLength) > 0 then begin
3162                                                 Result.FFirst := True;
3163                                         end else begin
3164                                                 for i := 0 to SList.Count - 1 do begin
3165                                                         if Trim(SList[i]) = '' then begin
3166                                                                 if i = 0 then
3167                                                                         Result.FStBegin := True;
3168                                                                 if i = (SList.Count - 1) then
3169                                                                         Result.FToEnd := True;
3170                                                         end else if IsNumeric(SList[i]) then begin
3171                                                                 wkInt := StrToInt(SList[i]);
3172                                                                 wkMax := Max(wkMax, wkInt);
3173                                                                 if wkMin = 0 then
3174                                                                         wkMin := wkInt
3175                                                                 else
3176                                                                         wkMin := Min(wkMin, wkInt);
3177                                                         end else if Trim(SList[i]) = 'n' then begin
3178                                                                 Result.FFirst := True;
3179                                                         end else begin
3180                                                                 FAWKStr.RegExp := '^n[0-9]+$|^[0-9]+n$';
3181                                                                 if FAWKStr.Match(FAWKStr.ProcessEscSeq(SList[i]), RStart, RLength) > 0 then begin
3182                                                                         if Copy(SList[i], 1, 1) = 'n' then
3183                                                                                 wkInt := StrToInt(Copy(SList[i], 2, Length(SList[i])))
3184                                                                         else
3185                                                                                 wkInt := StrToInt(Copy(SList[i], 1, Length(SList[i]) - 1));
3186                                                                         Result.FFirst := True;
3187                                                                         wkMax := Max(wkMax, wkInt);
3188                                                                         if wkMin = 1 then
3189                                                                                 wkMin := wkInt
3190                                                                         else
3191                                                                                 wkMin := Min(wkMin, wkInt);
3192                                                                 end;
3193                                                         end;
3194                                                 end;
3195                                                 if Result.FStBegin and (not Result.FToEnd) then
3196                                                         Result.FSt := wkMin
3197                                                 else if (not Result.FStBegin) and Result.FToEnd then
3198                                                         Result.FTo := wkMax
3199                                                 else if (not Result.FStBegin) and (not Result.FToEnd) then begin
3200                                                         Result.FSt := wkMin;
3201                                                         Result.FTo := wkMax;
3202                                                 end;
3203                                                 //Result.FSt := wkMin;
3204                                                 //Result.FTo := wkMax;
3205                                         end;
3206                                 end;
3207                         finally
3208                                 SList.Free;
3209                         end;
3210                         Result.FDone := True;
3211                         Exit;
3212                 end;
3213
3214                 //\90Vkako\8f\91\8e®
3215                 //http://server.2ch.net/ITA_NAME/kako/1000/10000/1000000000.html
3216                 FAWKStr.RegExp := '/.+/kako/[0-9]+/[0-9]+/[0-9]+\.html';
3217                 if FAWKStr.Match(FAWKStr.ProcessEscSeq(s), RStart, RLength) > 0 then begin
3218                         SList := TStringList.Create;
3219                         try
3220                                 SList.Clear;
3221                                 FAWKStr.RegExp := '/';
3222                                 if FAWKStr.Split(FAWKStr.ProcessEscSeq(s), SList) >= 6 then begin
3223                                         Result.FBBS := SList[1];
3224                                         Result.FKey := ChangeFileExt(SList[5], '');
3225                                         Result.FFirst := True;
3226                                 end else
3227                                         Exit;
3228                         finally
3229                                 SList.Free;
3230                         end;
3231                         Result.FDone := True;
3232                         Exit;
3233                 end;
3234
3235                 //\8b\8ckako\8f\91\8e®
3236                 //http://server.2ch.net/ITA_NAME/kako/999/999999999.html
3237                 FAWKStr.RegExp := '/.+/kako/[0-9]+/[0-9]+\.html';
3238                 if FAWKStr.Match(FAWKStr.ProcessEscSeq(s), RStart, RLength) > 0 then begin
3239                         SList := TStringList.Create;
3240                         try
3241                                 SList.Clear;
3242                                 FAWKStr.RegExp := '/';
3243                                 if FAWKStr.Split(FAWKStr.ProcessEscSeq(s), SList) >= 5 then begin
3244                                         Result.FBBS := SList[1];
3245                                         Result.FKey := ChangeFileExt(SList[4], '');
3246                                         Result.FFirst := True;
3247                                 end else
3248                                         Exit;
3249                         finally
3250                                 SList.Free;
3251                         end;
3252                         Result.FDone := True;
3253                         Exit;
3254                 end;
3255
3256                 //log\8by\82Ñlog2\8f\91\8e®
3257                 //http://server.2ch.net/log/ITA_NAME/kako/999/999999999.html
3258                 //http://server.2ch.net/log2/ITA_NAME/kako/999/999999999.html
3259                 FAWKStr.RegExp := '/log2?/.+/kako/[0-9]+/[0-9]+\.html';
3260                 if FAWKStr.Match(FAWKStr.ProcessEscSeq(s), RStart, RLength) > 0 then begin
3261                         SList := TStringList.Create;
3262                         try
3263                                 SList.Clear;
3264                                 FAWKStr.RegExp := '/';
3265                                 if FAWKStr.Split(FAWKStr.ProcessEscSeq(s), SList) >= 6 then begin
3266                                         Result.FBBS := SList[2];
3267                                         Result.FKey := ChangeFileExt(SList[5], '');
3268                                         Result.FFirst := True;
3269                                 end else
3270                                         Exit;
3271                         finally
3272                                 SList.Free;
3273                         end;
3274                         Result.FDone := True;
3275                         Exit;
3276                 end;
3277
3278
3279                 //\8b\8cURL\8f\91\8e®
3280                 //http://server.2ch.net/test/read.cgi?bbs=ITA_NAME&key=1000000000&st=1&to=5&nofirst=true
3281                 FAWKStr.RegExp := '/test/read\.cgi\?';
3282                 if FAWKStr.Match(FAWKStr.ProcessEscSeq(s), RStart, RLength) > 0 then begin
3283                         s := Copy(s, 16, Length(s));
3284                         SList := TStringList.Create;
3285                         try
3286                                 SList.Clear;
3287                                 FAWKStr.RegExp := '&';
3288                                 if FAWKStr.Split(FAWKStr.ProcessEscSeq(s), SList) >= 2 then begin
3289                                         Result.FFirst := True;
3290                                         for i := 0 to SList.Count - 1 do begin
3291                                                 if Pos('bbs=', SList[i]) = 1 then begin
3292                                                         Result.FBBS := Copy(SList[i], 5, Length(SList[i]));
3293                                                 end else if Pos('key=', SList[i]) = 1 then begin
3294                                                         Result.FKey := Copy(SList[i], 5, Length(SList[i]));
3295                                                 end else if Pos('st=', SList[i]) = 1 then begin
3296                                                         wk := Copy(SList[i], 4, Length(SList[i]));
3297                                                         if IsNumeric(wk) then
3298                                                                 Result.FSt := StrToInt(wk)
3299                                                         else if wk = '' then
3300                                                                 Result.FStBegin := True;
3301                                                 end else if Pos('to=', SList[i]) = 1 then begin
3302                                                         wk := Copy(SList[i], 4, Length(SList[i]));
3303                                                         if IsNumeric(wk) then
3304                                                                 Result.FTo := StrToInt(wk)
3305                                                         else if wk = '' then
3306                                                                 Result.FToEnd := True;
3307                                                 end else if Pos('nofirst=', SList[i]) = 1 then begin
3308                                                         Result.FFirst := False;
3309                                                 end;
3310                                         end;
3311                                 end else
3312                                         Exit;
3313                         finally
3314                                 SList.Free;
3315                         end;
3316
3317                         if (Result.FBBS <> '') and (Result.FKey <> '') then begin
3318                                 Result.FDone := True;
3319                         end;
3320                         Exit;
3321                 end;
3322         end;
3323 end;
3324
3325 procedure TGikoSys.ParseURI(var URL, Protocol, Host, Path, Document, Port, Bookmark: string);
3326 var
3327         URI: TIdURI;
3328 begin
3329         Protocol := '';
3330         Host := '';
3331         Path := '';
3332         Document := '';
3333         Port := '';
3334         Bookmark := '';
3335         URI := TIdURI.Create(URL);
3336         try
3337                 Protocol := URI.Protocol;
3338                 Host := URI.Host;
3339                 Path := URI.Path;
3340                 Document := URI.Document;
3341                 Port := URI.Port;
3342                 Bookmark := URI.Bookmark;
3343         finally
3344                 URI.Free;
3345         end;
3346 end;
3347
3348 function TGikoSys.GetVersionBuild: Integer;
3349 var
3350         FixedFileInfo: PVSFixedFileInfo;
3351         VersionHandle, VersionSize: DWORD;
3352         pVersionInfo: Pointer;
3353         ItemLen : UInt;
3354         AppFile: string;
3355 begin
3356         Result := 0;
3357         AppFile := Application.ExeName;
3358         VersionSize := GetFileVersionInfoSize(pChar(AppFile), VersionHandle);
3359         if VersionSize = 0 then
3360                 Exit;
3361         GetMem(pVersionInfo, VersionSize);
3362         try
3363                 if GetFileVersionInfo(PChar(AppFile),VersionHandle,VersionSize, pVersionInfo) then
3364                         if VerQueryValue(pVersionInfo, '\', Pointer(FixedFileInfo), ItemLen) then
3365                                 Result := LOWORD(FixedFileInfo^.dwFileVersionLS);
3366         finally
3367                 FreeMem(pVersionInfo, VersionSize);
3368         end;
3369 end;
3370
3371 function        TGikoSys.GetBrowsableThreadURL(
3372         inURL : string
3373 ) : string;
3374 var
3375         threadItem      : TThreadItem;
3376         boardPlugIn     : TBoardPlugIn;
3377         i                                               : Integer;
3378 begin
3379
3380         //===== \83v\83\89\83O\83C\83\93
3381         try
3382                 for i := Length( BoardPlugIns ) - 1 downto 0 do begin
3383                         if Assigned( Pointer( BoardPlugIns[ i ].Module ) ) then begin
3384                                 if BoardPlugIns[ i ].AcceptURL( inURL ) = atThread then begin
3385                                         boardPlugIn := BoardPlugIns[ i ];
3386                                         threadItem      := TThreadItem.Create( boardPlugIn, inURL );
3387                                         Result                  := threadItem.URL;
3388                                         threadItem.Free;
3389
3390                                         Break;
3391                                 end;
3392                         end;
3393                 end;
3394         except
3395                 // exception \82ª\94­\90\82µ\82½\8fê\8d\87\82Í\93à\95\94\8f\88\97\9d\82É\94C\82¹\82½\82¢\82Ì\82Å\82±\82±\82Å\82Í\89½\82à\82µ\82È\82¢
3396         end;
3397
3398         if Length( Result ) = 0 then
3399                 Result := GikoSys.Get2chBrowsableThreadURL( inURL );
3400
3401 end;
3402
3403 function        TGikoSys.GetThreadURL2BoardURL(
3404         inURL : string
3405 ) : string;
3406 var
3407         threadItem      : TThreadItem;
3408         boardPlugIn     : TBoardPlugIn;
3409         i                                               : Integer;
3410 begin
3411
3412         //===== \83v\83\89\83O\83C\83\93
3413         try
3414                 for i := Length( BoardPlugIns ) - 1 downto 0 do begin
3415                         if Assigned( Pointer( BoardPlugIns[ i ].Module ) ) then begin
3416                                 if BoardPlugIns[ i ].AcceptURL( inURL ) = atThread then begin
3417                                         boardPlugIn := BoardPlugIns[ i ];
3418                                         threadItem      := TThreadItem.Create( boardPlugIn, inURL );
3419                                         Result                  := BoardPlugIns[ i ].GetBoardURL( Longword( threadItem ) );
3420                                         threadItem.Free;
3421
3422                                         Break;
3423                                 end;
3424                         end;
3425                 end;
3426         except
3427                 // exception \82ª\94­\90\82µ\82½\8fê\8d\87\82Í\93à\95\94\8f\88\97\9d\82É\94C\82¹\82½\82¢\82Ì\82Å\82±\82±\82Å\82Í\89½\82à\82µ\82È\82¢
3428         end;
3429
3430         if Length( Result ) = 0 then
3431                 Result := GikoSys.Get2chThreadURL2BoardURL( inURL );
3432
3433 end;
3434
3435 function        TGikoSys.Get2chThreadURL2BoardURL(
3436         inURL : string
3437 ) : string;
3438 var
3439         Protocol, Host, Path, Document, Port, Bookmark : string;
3440         BBSID, BBSKey : string;
3441         foundPos                        : Integer;
3442 begin
3443
3444         ParseURI( inURL, Protocol, Host, Path, Document, Port, Bookmark );
3445         Parse2chURL( inURL, Path, Document, BBSID, BBSKey );
3446
3447         foundPos := Pos( '/test/read.cgi', inURL );
3448         if {(Is2chHost(Host)) and} (foundPos > 0) then
3449                 Result := Copy( inURL, 1, foundPos ) + BBSID + '/'
3450         else
3451                 Result := Protocol + '://' + Host + '/' + BBSID + '/';
3452
3453 end;
3454
3455 function        TGikoSys.Get2chBrowsableThreadURL(
3456         inURL                   : string
3457 ) : string;
3458 var
3459         Protocol, Host, Path, Document, Port, Bookmark : string;
3460         BBSID, BBSKey : string;
3461         foundPos        : Integer;
3462 begin
3463
3464 //      if Pos( KAKO_PATH, inURL ) > 0 then begin
3465 //              Result := inURL;
3466 //      end else begin
3467                 ParseURI( inURL, Protocol, Host, Path, Document, Port, Bookmark );
3468                 Parse2chURL( inURL, Path, Document, BBSID, BBSKey );
3469                 foundPos := Pos( '/test/read.cgi', inURL ) - 1;
3470
3471                 if Is2chHost( Host ) then begin
3472                         Result := Protocol + '://' + Host +
3473                                 READ_PATH + BBSID + '/' + BBSKey + '/l50';
3474                 end else begin
3475                         if foundPos > 0 then
3476                                 Result := Copy( inURL, 1, foundPos ) +
3477                                         OLD_READ_PATH + 'bbs=' + BBSID + '&key=' + BBSKey + '&ls=50'
3478                         else
3479                                 Result := Protocol + '://' + Host +
3480                                         OLD_READ_PATH + 'bbs=' + BBSID + '&key=' + BBSKey + '&ls=50';
3481                 end;
3482 //      end;
3483
3484 end;
3485
3486 function        TGikoSys.Get2chBoard2ThreadURL(
3487         inBoard : TBoard;
3488         inKey           : string
3489 ) : string;
3490 var
3491         server  : string;
3492 begin
3493
3494         server := UrlToServer( inBoard.URL );
3495         if Is2chHost( server ) then
3496                 Result := server + 'test/read.cgi/' + inBoard.BBSID + '/' + inKey + '/l50'
3497         else
3498                 Result := server + 'test/read.cgi?bbs=' + inBoard.BBSID + '&key=' + inKey + '&ls=50';
3499
3500 end;
3501
3502 (*************************************************************************
3503  *\8b@\94\\96¼\81@\81@\81F\83{\81[\83h\83t\83@\83C\83\8b\97ñ\8b\93
3504  *\89Â\8e\8b\81@\81@\81@\81FPublic
3505  *************************************************************************)
3506 procedure TGikoSys.ListBoardFile;
3507 var
3508         boardFileList   : TStringList;
3509         i, l, k                                 : Integer;
3510 begin
3511
3512   // BBS \82Ì\8aJ\95ú
3513   try
3514         for i := 0 to Length( BBSs ) - 1 do
3515           BBSs[ i ].Free;
3516   except
3517   end;
3518   SetLength( BBSs, 0 );
3519
3520   l := 0;
3521   // \94Â\83\8a\83X\83g\82Ì\97ñ\8b\93
3522   if FileExists( GikoSys.GetBoardFileName ) then begin
3523         SetLength( BBSs, l + 1 );
3524         BBSs[ l ]                               := TBBS.Create( GikoSys.GetBoardFileName );
3525         BBSs[ l ].Title := '\82Q\82¿\82á\82ñ\82Ë\82é';
3526                 Inc( l );
3527   end;
3528
3529   if FileExists( GikoSys.GetCustomBoardFileName ) then begin
3530         SetLength( BBSs, l + 1 );
3531         BBSs[ l ]                               := TBBS.Create( GikoSys.GetCustomBoardFileName );
3532         BBSs[ l ].Title := '\82»\82Ì\91¼';
3533                 Inc( l );
3534   end;
3535
3536   // Board \83t\83H\83\8b\83_
3537   if DirectoryExists( GikoSys.Setting.GetBoardDir ) then begin
3538         BoardFileList := TStringList.Create;
3539         try
3540           GikoSys.GetFileList( GikoSys.Setting.GetBoardDir, '*', BoardFileList, True, True );
3541           for k := BoardFileList.Count - 1 downto 0 do begin
3542                 if AnsiCompareText(ExtractFileExt(BoardFileList[ k ]), '.bak') = 0 then
3543                         BoardFileList.Delete(k);
3544           end;
3545                         SetLength( BBSs, l + BoardFileList.Count );
3546           for i := BoardFileList.Count - 1 downto 0 do begin
3547                 BBSs[ l ]                               := TBBS.Create( BoardFileList[ i ] );
3548                 BBSs[ l ].Title := ChangeFileExt( ExtractFileName( BoardFileList[ i ] ), '' );
3549
3550                 Inc( l );
3551           end;
3552         finally
3553           BoardFileList.Free;
3554         end;
3555   end;
3556
3557 end;
3558
3559 (*************************************************************************
3560  *\8b@\94\\96¼\81@\81@\81F\83{\81[\83h\83t\83@\83C\83\8b\93Ç\82Ý\8d\9e\82Ý
3561  *\89Â\8e\8b\81@\81@\81@\81FPublic
3562  *************************************************************************)
3563 procedure TGikoSys.ReadBoardFile( bbs : TBBS );
3564 var
3565         idx                                             : Integer;
3566         ini                                             : TMemIniFile;
3567
3568         boardFile                       : TStringList;
3569         CategoryList    : TStringList;
3570         BoardList                       : TStringList;
3571         Category                        : TCategory;
3572         Board                                   : TBoard;
3573         inistr                          : string;
3574         RoundItem                       : TRoundItem;
3575
3576         i, iBound                       : Integer;
3577         j, jBound                       : Integer;
3578         k, kBound                       : Integer;
3579 begin
3580
3581   if not FileExists( bbs.FilePath ) then
3582     Exit;
3583
3584         bbs.Clear;
3585   ini := TMemIniFile.Create('');
3586   boardFile := TStringList.Create;
3587   try
3588     boardFile.LoadFromFile( bbs.FilePath );
3589
3590     ini.SetStrings( boardFile );
3591     CategoryList        := TStringList.Create;
3592     BoardList                   := TStringList.Create;
3593     try
3594       ini.ReadSections( CategoryList );
3595
3596       iBound := CategoryList.Count - 1;
3597       for i := 0 to iBound do begin
3598         ini.ReadSection( CategoryList[i], BoardList );
3599         Category                                := TCategory.Create;
3600         Category.No                     := i + 1;
3601         Category.Title  := CategoryList[i];
3602
3603         jBound := BoardList.Count - 1;
3604         for j := 0 to jBound do begin
3605           Board := nil;
3606           inistr := ini.ReadString(CategoryList[i], BoardList[j], '');
3607
3608           //===== \83v\83\89\83O\83C\83\93
3609           try
3610             kBound := Length( BoardPlugIns ) - 1;
3611             for k := 0 to kBound do begin
3612               if Assigned( Pointer( BoardPlugIns[ k ].Module ) ) then begin
3613                 if BoardPlugIns[ k ].AcceptURL( inistr ) = atBoard then begin
3614                   Board := TBoard.Create( BoardPlugIns[ k ], inistr );
3615
3616                   Break;
3617                 end;
3618               end;
3619             end;
3620           except
3621             // exception \82ª\94­\90\82µ\82½\8fê\8d\87\82Í\93à\95\94\8f\88\97\9d\82É\94C\82¹\82½\82¢\82Ì\82Å\82±\82±\82Å\82Í\89½\82à\82µ\82È\82¢
3622           end;
3623
3624           if Board = nil then
3625             Board := TBoard.Create( nil, inistr );
3626           Board.BeginUpdate;
3627           Board.No := j + 1;
3628           Board.Title := BoardList[j];
3629           Board.RoundDate := ZERO_DATE;
3630
3631           idx := RoundList.Find(Board);
3632           if idx <> -1 then begin
3633             RoundItem                           := RoundList.Items[idx, grtBoard];
3634             Board.Round                 := True;
3635             Board.RoundName     := RoundItem.RoundName;
3636           end;
3637
3638           Category.Add(Board);
3639           Board.LoadSettings;
3640           Board.EndUpdate;
3641         end;
3642
3643         bbs.Add( Category );
3644       end;
3645                         bbs.IsBoardFileRead := True;
3646     finally
3647       BoardList.Free;
3648       CategoryList.Free;
3649     end;
3650   finally
3651     boardFile.Free;
3652     ini.Free;
3653   end;
3654
3655 end;
3656
3657 function        TGikoSys.GetUnknownCategory : TCategory;
3658 const
3659         UNKNOWN_CATEGORY = '(\96¼\8fÌ\95s\96¾)';
3660 begin
3661
3662         if Length( BBSs ) < 2 then begin
3663                 Result := nil;
3664                 Exit;
3665         end;
3666
3667         Result := BBSs[ 1 ].FindCategoryFromTitle( UNKNOWN_CATEGORY );
3668         if Result = nil then begin
3669                 Result                          := TCategory.Create;
3670                 Result.Title    := UNKNOWN_CATEGORY;
3671                 BBSs[ 1 ].Add( Result );
3672         end;
3673
3674 end;
3675
3676 function        TGikoSys.GetUnknownBoard( inPlugIn : TBoardPlugIn; inURL : string ) : TBoard;
3677 var
3678         category : TCategory;
3679 const
3680         UNKNOWN_BOARD = '(\96¼\8fÌ\95s\96¾)';
3681 begin
3682
3683         category := GetUnknownCategory;
3684         if category = nil then begin
3685                 Result := nil;
3686         end else begin
3687                 Result := category.FindBoardFromTitle( UNKNOWN_BOARD );
3688                 if Result = nil then begin
3689                         Result                          := TBoard.Create( inPlugIn, inURL );
3690                         Result.Title    := UNKNOWN_BOARD;
3691                         category.Add( Result );
3692                 end;
3693         end;
3694
3695 end;
3696 function TGikoSys.GetSambaFileName : string;
3697 begin
3698         Result := Setting.GetSambaFileName;
3699 end;
3700 procedure TGikoSys.SambaFileExists();
3701 var
3702         sambaTmp: string;
3703     sambaStrList: TStringList;
3704 begin
3705     if not FileExists(GikoSys.GetSambaFileName) then begin
3706         sambaTmp := ChangeFileExt(GikoSys.GetSambaFileName, '.default');
3707         sambaStrList := TStringList.Create;
3708         try
3709             if FileExists(sambaTmp) then begin
3710                         sambaStrList.LoadFromFile(sambaTmp);
3711                 sambaStrList.SaveToFile(GikoSys.GetSambaFileName);
3712             end;
3713         finally
3714                 sambaStrList.Free;
3715         end;
3716     end;
3717 end;
3718
3719 initialization
3720         GikoSys := TGikoSys.Create;
3721
3722 finalization
3723         if GikoSys <> nil then begin
3724                 GikoSys.Free;
3725                 GikoSys := nil;
3726         end;
3727 end.