OSDN Git Service

タブに表示されているスレッドの一覧をスレッド一覧に表示する機能を作成
[gikonavigoeson/gikonavi.git] / BoardGroup.pas
1 unit BoardGroup;
2
3 interface
4
5 uses
6         Windows, SysUtils, Classes, ComCtrls, {HTTPApp,} YofUtils, IdGlobal,
7         ExternalBoardManager, ExternalBoardPlugInMain, StrUtils;
8
9 type
10         //\83\8a\83X\83g\82Ì\95\\8e¦\83A\83C\83e\83\80\91I\91ð
11         TGikoViewType = (gvtAll, gvtLog, gvtNew, gvtLive, gvtArch, gvtUser);
12         //\83\8a\83X\83g\82Ì\8fã\82°\89º\82°
13         TGikoAgeSage = (gasNone, gasAge, gasSage, gasNew, gasArch, gasNull);
14
15         TCategory = class;
16         TBoard = class;
17         TThreadItem = class;
18
19
20         // BBS \82Ì\83\8b\81[\83g
21         TBBS = class(TList)
22         private
23                 FTitle: string;
24                 FFilePath : string;                                             // \94Â\83\8a\83X\83g\82Ì\83p\83X
25                 FExpand: Boolean;
26                 FKubetsuChk: Boolean;                                   //\8di\8d\9e\82Ý\8e\9e\91å\95\8e\9a\8f¬\95\8e\9a\8bæ\95Ê
27                 FSelectText: string;                                    //\8di\8d\9e\82Ý\95\8e\9a\97ñ
28                 FShortSelectText: string;
29                 FIsBoardFileRead : Boolean;             // \94Â\83\8a\83X\83g\82Í\93Ç\82Ý\8d\9e\82Ü\82ê\82Ä\82¢\82é\82©\81H
30
31                 function GetCategory(index: integer): TCategory;
32                 procedure SetCategory(index: integer; value: TCategory);
33                 procedure SetSelectText(s: string);
34         public
35                 constructor Create( boardFilePath : string );
36                 destructor Destroy; override;
37
38                 function Add(item: TCategory): integer;
39                 procedure Delete(index: integer);
40                 procedure Clear; override;
41                 function Find(key: string): TCategory;
42                 function FindBBSID(const BBSID: string): TBoard;
43                 function FindBoardFromTitle(const Title: string): TBoard;
44                 function FindBoardFromURL(const inURL: string): TBoard;
45                 function FindThreadFromURL(const inURL : string ) : TThreadItem;
46                 function FindThreadItem(const BBSID, FileName: string): TThreadItem;
47                 function FindCategoryFromTitle(const inTitle : string ) : TCategory;
48                 property FilePath : string read FFilePath write FFilePath;
49
50                 property Items[index: integer]: TCategory read GetCategory write SetCategory;
51                 property Title: string read FTitle write FTitle;
52                 property NodeExpand: Boolean read FExpand write FExpand;
53
54                 property KubetsuChk: Boolean read FKubetsuChk write FKubetsuChk;
55                 property SelectText: string read FSelectText write SetSelectText;
56                 property ShortSelectText: string read FShortSelectText write FShortSelectText;
57
58                 property        IsBoardFileRead : Boolean read FIsBoardFileRead write FIsBoardFileRead;
59         end;
60
61         // \83J\83e\83S\83\8a(\94 URL \82Ì\83\8a\83X\83g)
62         TCategory = class(TStringList)
63         private
64                 FNo: Integer;
65                 FTitle: string;
66                 FParenTBBS: TBBS;
67                 FExpand: Boolean;
68
69                 function GetBoard(index: integer): TBoard;
70                 procedure SetBoard(index: integer; value: TBoard);
71         public
72                 constructor Create;
73                 destructor Destroy; override;
74
75                 property No: Integer read FNo write FNo;
76                 property Title: string read FTitle write FTitle;
77                 property Items[index: integer]: TBoard read GetBoard write SetBoard;
78                 property ParenTBBS: TBBS read FParenTBBS write FParenTBBS;
79
80                 function Add(item: TBoard): integer;
81                 procedure Delete(index: integer);
82                 procedure Clear; override;
83                 function FindName(const key: string): TBoard;
84                 function FindBBSID(const BBSID: string): TBoard;
85                 function FindBoardFromTitle(const Title: string): TBoard;
86                 function FindBoardFromURL(const inURL: string): TBoard;
87                 function FindThreadFromURL(const inURL : string ) : TThreadItem;
88                 function IsMidoku: Boolean;
89
90                 property NodeExpand: Boolean read FExpand write FExpand;
91         end;
92
93         //! \83X\83\8c\83b\83h\90\94\83J\83E\83\93\83g\8fð\8c\8f\95
94         TThreadCount = function(Item : TThreadItem): Boolean;
95
96         // \94Â(\83X\83\8c\83b\83h URL \82Ì\83\8a\83X\83g)
97         TBoard = class(TStringList)
98         private
99                 FContext: DWORD;                                                        // \83v\83\89\83O\83C\83\93\82ª\8e©\97R\82É\90Ý\92è\82µ\82Ä\82¢\82¢\92l(\8eå\82É\83C\83\93\83X\83^\83\93\83X\82ª\93ü\82é)
100
101                 FNo: Integer;                                                                   //\94Ô\8d\86
102                 FTitle: string;                                                         //\83{\81[\83h\83^\83C\83g\83\8b
103                 FBBSID: string;                                                         //BBSID
104                 FURL: string;                                                                   //\83{\81[\83hURL
105                 FRound: Boolean;                                                        //\83X\83\8c\83b\83h\88ê\97\97\8f\84\89ñ\97\\96ñ
106                 FRoundName: string;                                             //\8f\84\89ñ\96¼
107                 FRoundDate: TDateTime;                          //\83X\83\8c\83b\83h\88ê\97\97\82ð\8eæ\93¾\82µ\82½\93ú\8e\9e\81i\8f\84\89ñ\93ú\8e\9e\81j
108                 FLastModified: TDateTime;                       //\83X\83\8c\83b\83h\88ê\97\97\82ª\8dX\90V\82³\82ê\82Ä\82¢\82é\93ú\8e\9e\81i\83T\81[\83o\91¤\93ú\8e\9e\81j
109                 FLastGetTime: TDateTime;                        //\83X\83\8c\83b\83h\82Ü\82½\82Í\83X\83\8c\83b\83h\88ê\97\97\82ð\8dÅ\8cã\82É\8dX\90V\82µ\82½\93ú\8e\9e\81i\83T\81[\83o\91¤\93ú\8e\9e\81E\8f\91\82«\8d\9e\82Ý\8e\9e\82É\8eg\97p\82·\82é\81j
110                 FIsThreadDatRead: Boolean;              //\83X\83\8c\83b\83h\83\8a\83X\83g\82Í\93Ç\82Ý\8d\9e\82Ü\82ê\82Ä\82¢\82é\82©\81H
111                 FUnRead: Integer;                                                       //\83X\83\8c\83b\83h\96¢\93Ç\90\94
112                 FParentCategory: TCategory;             //\90e\83J\83e\83S\83\8a
113                 FModified: Boolean;                                             //\8fC\90³\83t\83\89\83O
114                 FBoolData: Boolean;                                             //\82¢\82ë\82ñ\82È\97p\93r\82É\8eg\82¤yo
115                 FSPID: string;                                                          //\8f\91\82«\8d\9e\82Ý\97pSPID
116                 FPON: string;                                                                   //\8f\91\82«\8d\9e\82Ý\97pPON
117                 FCookie: string;                                                //\8f\91\82«\8d\9e\82Ý\97pCookie\95\8e\9a\97ñ
118                 FExpires: TDateTime;                                    //Cookie\82Ì\97L\8cø\8aú\8cÀ
119                 FKotehanName: string;                                   //\83R\83e\83n\83\93\96¼\91O
120                 FKotehanMail: string;                                   //\83R\83e\83n\83\93\83\81\81[\83\8b
121
122                 FUpdate: Boolean;
123                 FExpand: Boolean;
124
125                 FBoardPlugIn    : TBoardPlugIn; // \82±\82Ì\94Â\82ð\83T\83|\81[\83g\82·\82é\83v\83\89\83O\83C\83\93
126                 FFilePath                       : string;                               // \82±\82Ì\83X\83\8c\88ê\97\97\82ª\95Û\91\82³\82ê\82Ä\82¢\82é\83p\83X
127                 FIsLogFile              : Boolean;                      // \83\8d\83O\91\8dÝ\83t\83\89\83O
128                 FIntData                        : Integer;                      // \8dD\82«\82É\82¢\82\82Á\82Ä\82æ\82µ\81B\82¢\82ë\82ñ\82È\97p\93r\82É\8eg\82¤yo
129                 FListData                       : TList;                                // \8dD\82«\82É\82¢\82\82Á\82Ä\82æ\82µ\81B\82¢\82ë\82ñ\82È\97p\93r\82É\8eg\82¤yo
130
131                 FSETTINGTXTTime : TDateTime;    //SETTING.TXT\82ð\8eæ\93¾\82µ\82½\93ú\8e\9e
132                 FIsSETTINGTXT   : boolean;      //SETTING.TXT\82ð\8eæ\93¾\82µ\82Ä\82¢\82é\82©
133                 FHEADTXTTime    : TDateTime;            //HEAD.TXT\82ð\8eæ\93¾\82µ\82½\93ú\8e\9e
134                 FIsHEADTXT              : boolean;      //HEAD.TXT\82ð\8eæ\93¾\82µ\82Ä\82¢\82é\82©
135                 FTitlePictureURL: string;       //top\8aG\82ÌURL
136                 FMultiplicity   : Integer; //\8fd\95¡\82µ\82Ä\82¢\82é\82©\82Ç\82¤\82©\81H
137                 FIs2ch                  : Boolean; //host\82ª2ch\82©\82Ç\82¤\82©
138                 FNewThreadCount: Integer;       //\90V\92\85\83X\83\8c\83b\83h\82Ì\90\94
139                 FLogThreadCount: Integer;       //\83\8d\83O\97L\82è\83X\83\8c\83b\83h\82Ì\90\94
140                 FUserThreadCount: Integer;      //\81H
141                 FLiveThreadCount: Integer;      //\90\91\83X\83\8c\83b\83h\90\94
142                 FArchiveThreadCount: Integer;   //DAT\97\8e\82¿\83X\83\8c\83b\83h\90\94
143                 function GetThreadItem(index: integer): TThreadItem;
144                 procedure SetThreadItem(index: integer; value: TThreadItem);
145                 procedure SetRound(b: Boolean);
146                 procedure SetRoundName(s: string);
147                 //procedure SetRoundName(s: PChar);
148                 procedure SetLastModified(d: TDateTime);
149                 procedure SetLastGetTime(d: TDateTime);
150                 procedure SetUnRead(i: Integer);
151                 procedure SetKotehanName(s: string);
152                 procedure SetKotehanMail(s: string);
153                 procedure Init;
154         public
155                 constructor Create( inPlugIn : TBoardPlugIn; inURL : string );
156                 destructor Destroy; override;
157
158                 property Context: DWORD read FContext write FContext;
159
160                 property Items[index: integer]: TThreadItem read GetThreadItem write SetThreadItem;
161                 property No: Integer read FNo write FNo;
162                 property Title: string read FTitle write FTitle;
163                 property BBSID: string read FBBSID write FBBSID;
164                 property URL: string read FURL write FURL;
165                 property Round: Boolean read FRound write SetRound;
166                 //property RoundName: PChar read FRoundName write SetRoundName;
167                 property RoundName: string read FRoundName write SetRoundName;
168                 property RoundDate: TDateTime read FRoundDate write FRoundDate;
169                 property LastModified: TDateTime read FLastModified write SetLastModified;
170                 property LastGetTime: TDateTime read FLastGetTime write SetLastGetTime;
171                 property UnRead: Integer read FUnRead write SetUnRead;
172                 property Modified: Boolean read FModified write FModified;
173                 property IsThreadDatRead: Boolean read FIsThreadDatRead write FIsThreadDatRead;
174                 property ParentCategory: TCategory read FParentCategory write FParentCategory;
175
176                 property        BoardPlugIn     : TBoardPlugIn  read FBoardPlugIn;
177                 property        FilePath                : string                                read FFilePath write FFilePath;
178                 property        IsLogFile               : Boolean                               read FIsLogFile write FIsLogFile;
179                 property        IntData                 : Integer                               read FIntData write FIntData;
180                 property        ListData                : TList                                 read FListData write FListData;
181                 function        IsBoardPlugInAvailable : Boolean;
182
183                 function Add(item: TThreadItem): integer;
184                 procedure Insert(Index: Integer; Item: TThreadItem);
185                 procedure Delete(index: integer);
186                 procedure DeleteList(index: integer);
187                 procedure Clear; override;
188                 function FindThreadFromFileName(const ItemFileName: string): TThreadItem;
189                 function FindThreadFromURL(const inURL : string ) : TThreadItem;
190                 function GetIndexFromFileName(const ItemFileName: string): Integer;
191                 function GetIndexFromURL(const URL: string; reverse : Boolean = False): Integer;
192                 procedure LoadSettings;
193                 procedure SaveSettings;
194                 function GetReadCgiURL: string;
195                 function GetSubjectFileName: string;
196                 function GetFolderIndexFileName: string;
197                 function GetSETTINGTXTFileName: string;
198                 function GETHEADTXTFileName: string;
199                 function GetTitlePictureFileName: string;
200                 function GetSendURL: string;
201
202                 function GetNewThreadCount: Integer;
203                 function GetLogThreadCount: Integer;
204                 function GetArchiveThreadCount: Integer;
205                 function GetLiveThreadCount: Integer;
206                 function GetUserThreadCount: Integer;
207                 function GetNewThread(Index: Integer): TThreadItem;
208                 function GetLogThread(Index: Integer): TThreadItem; overload;
209                 function GetArchiveThread(Index: Integer): TThreadItem;
210                 function GetLiveThread(Index: Integer): TThreadItem;
211                 function GetUserThread(Index: Integer): TThreadItem;
212                 function GetThreadCount(func :TThreadCount ): Integer;
213                 function GetThread(func :TThreadCount;const Index :Integer ): TThreadItem;
214                 procedure BeginUpdate;
215                 procedure EndUpdate;
216                 property NodeExpand: Boolean read FExpand write FExpand;
217                 property BoolData: Boolean read FBoolData write FBoolData;
218                 property SPID: string read FSPID write FSPID;
219                 property PON: string read FPON write FPON;
220                 property KotehanName: string read FKotehanName write SetKotehanName;
221                 property KotehanMail: string read FKotehanMail write SetKotehanMail;
222
223                 property SETTINGTXTTime: TDateTime read FSETTINGTXTTime write FSETTINGTXTTime;
224                 property IsSETTINGTXT:  boolean read FIsSETTINGTXT write FIsSETTINGTXT;
225                 property HEADTXTTime: TDateTime read FHEADTXTTime write FHEADTXTTime;
226                 property IsHEADTXT:     boolean read FIsHEADTXT write FIsHEADTXT;
227                 property TitlePictureURL: string read FTitlePictureURL write FTitlePictureURL;
228                 property Multiplicity: Integer read FMultiplicity write FMultiplicity;
229                 property Is2ch  : boolean       read FIs2ch     write FIs2ch;
230                 property NewThreadCount: Integer        read FNewThreadCount write FNewThreadCount;     //\90V\92\85\83X\83\8c\83b\83h\82Ì\90\94
231                 property LogThreadCount: Integer        read FLogThreadCount write FLogThreadCount;             //\83\8d\83O\97L\82è\83X\83\8c\83b\83h\82Ì\90\94
232                 property UserThreadCount: Integer       read FUserThreadCount write FUserThreadCount;   //\81H
233                 property LiveThreadCount: Integer       read FLiveThreadCount write     FLiveThreadCount;
234                 property ArchiveThreadCount: Integer read FArchiveThreadCount write FArchiveThreadCount;
235
236                 property Cookie: string                         read FCookie write FCookie;
237                 property Expires: TDateTime                     read FExpires write FExpires;
238         end;
239
240         //\83X\83\8c
241         TThreadItem = class(TObject)
242         private
243                 FContext: DWORD;                                        // \83v\83\89\83O\83C\83\93\82ª\8e©\97R\82É\90Ý\92è\82µ\82Ä\82¢\82¢\92l(\8eå\82É\83C\83\93\83X\83^\83\93\83X\82ª\93ü\82é)
244                 FNo: Integer;                                                   //\94Ô\8d\86
245                 FFileName: string;                              //\83X\83\8c\83b\83h\83t\83@\83C\83\8b\96¼
246                 FTitle: string;                                         //\83X\83\8c\83b\83h\83^\83C\83g\83\8b
247                 FShortTitle: string;                    //\92Z\82¢\83X\83\8c\83b\83h\83^\83C\83g\83\8b\81i\8c\9f\8dõ\97p\81j
248                 FRoundDate: TDateTime;          //\83X\83\8c\83b\83h\82ð\8eæ\93¾\82µ\82½\93ú\8e\9e\81i\8f\84\89ñ\93ú\8e\9e\81j
249                 FLastModified: TDateTime; //\83X\83\8c\83b\83h\82ª\8dX\90V\82³\82ê\82Ä\82¢\82é\93ú\8e\9e\81i\83T\81[\83o\91¤\93ú\8e\9e\81j
250                 FCount: Integer;                                        //\83X\83\8c\83b\83h\83J\83E\83\93\83g\81i\83\8d\81[\83J\83\8b\81j
251                 FAllResCount: Integer;          //\83X\83\8c\83b\83h\83J\83E\83\93\83g\81i\83T\81[\83o\81j
252                 FNewResCount: Integer;          //\83X\83\8c\83b\83h\90V\92\85\90\94
253                 FSize: Integer;                                         //\83X\83\8c\83b\83h\83T\83C\83Y
254                 FRound: Boolean;                                        //\8f\84\89ñ\83t\83\89\83O
255                 FRoundName: string;                             //\8f\84\89ñ\96¼
256                 FIsLogFile: Boolean;                    //\83\8d\83O\91\8dÝ\83t\83\89\83O
257                 FParentBoard: TBoard;                   //\90e\83{\81[\83h
258                 FKokomade: Integer;                             //\83R\83R\82Ü\82Å\93Ç\82ñ\82¾\94Ô\8d\86
259                 FNewReceive: Integer;           //\83R\83R\82©\82ç\90V\8bK\8eó\90M
260                 FNewArrival: Boolean;                   //\90V\92\85
261                 FUnRead: Boolean;                                       //\96¢\93Ç\83t\83\89\83O
262                 FScrollTop: Integer;                    //\83X\83N\83\8d\81[\83\8b\88Ê\92u
263                 FDownloadHost: string;          //\8d¡\82Ì\83z\83X\83g\82Æ\88á\82¤\8fê\8d\87\82Ì\83z\83X\83g
264                 FAgeSage: TGikoAgeSage;         //\83A\83C\83e\83\80\82Ì\8fã\82°\89º\82°
265                 FUpdate: Boolean;
266                 FExpand: Boolean;
267                 FURL                                    : string;                               // \82±\82Ì\83X\83\8c\82ð\83u\83\89\83E\83U\82Å\95\\8e¦\82·\82é\8dÛ\82Ì URL
268                 FJumpAddress : Integer;         //\83\8c\83X\94Ô\8d\86\8ew\92èURL\82ð\93¥\82ñ\82¾\82Æ\82«\82É\8ew\92è\82³\82ê\82é\83\8c\83X\82Ì\94Ô\8d\86\82ª\93ü\82é
269                 procedure SetLastModified(d: TDateTime);
270                 procedure SetRound(b: Boolean);
271                 procedure SetRoundName(const s: string);
272                 //procedure SetRoundName(const s: PChar);
273                 procedure SetKokomade(i: Integer);
274                 procedure SetUnRead(b: Boolean);
275                 procedure SetScrollTop(i: Integer);
276                 procedure Init;
277                 function GetCreateDate: TDateTime;
278         function GetFilePath: String;
279         public
280                 constructor Create(const inPlugIn : TBoardPlugIn; const inBoard : TBoard; inURL : string ); overload;
281                 constructor Create(const inPlugIn : TBoardPlugIn; const inBoard : TBoard;
282                                          inURL : string; inExist: Boolean; const inFilename: string ); overload;
283
284                 destructor Destroy; override;
285
286                 function GetDatURL: string;
287                 function GetDatgzURL: string;
288 //              function GetOldDatgzURL: string;
289                 function GetOfflawCgiURL(const SessionID: string): string;
290                 function GetSendURL: string;
291                 procedure DeleteLogFile;
292                 function GetThreadFileName: string;
293                 procedure BeginUpdate;
294                 procedure EndUpdate;
295
296                 property Context: DWORD read FContext write FContext;
297
298                 property No: Integer read FNo write FNo;
299                 property FileName: string read FFileName write FFileName;
300                 property Title: string read FTitle write FTitle;
301                 property ShortTitle: string read FShortTitle write FShortTitle;
302                 property RoundDate: TDateTime read FRoundDate write FRoundDate;
303                 property LastModified: TDateTime read FLastModified write SetLastModified;
304                 property Count: Integer read FCount write FCount;
305                 property AllResCount: Integer read FAllResCount write FAllResCount;
306                 property NewResCount: Integer read FNewResCount write FNewResCount;
307                 property Size: Integer read FSize write FSize;
308                 property Round: Boolean read FRound write SetRound;
309                 property RoundName: string read FRoundName write SetRoundName;
310                 //property RoundName: PChar read FRoundName write SetRoundName;
311
312                 property IsLogFile: Boolean read FIsLogFile write FIsLogFile;
313                 property ParentBoard: TBoard read FParentBoard write FParentBoard;
314                 property Kokomade: Integer read FKokomade write SetKokomade;
315                 property NewReceive: Integer read FNewReceive write FNewReceive;
316                 property NewArrival: Boolean read FNewArrival write FNewArrival;
317                 property UnRead: Boolean read FUnRead write SetUnRead;
318                 property ScrollTop: Integer read FScrollTop write SetScrollTop;
319                 property Expand: Boolean read FExpand write FExpand;
320                 property DownloadHost: string read FDownloadHost write FDownloadHost;
321                 property AgeSage: TGikoAgeSage read FAgeSage write FAgeSage;
322                 property CreateDate: TDateTime read GetCreateDate;
323                 property        URL                                     : string                                read FURL write FURL;
324                 property        FilePath                : string        read GetFilePath;
325                 property JumpAddress : Integer read FJumpAddress write FJumpAddress;
326         end;
327
328         TBoardGroup = class(TStringList)
329     private
330         FBoardPlugIn    : TBoardPlugIn; // \82±\82Ì\94Â\82ð\83T\83|\81[\83g\82·\82é\83v\83\89\83O\83C\83\93
331     public
332                 destructor Destroy; override;
333                 procedure       Clear   ; override;
334         property        BoardPlugIn     : TBoardPlugIn  read FBoardPlugIn write FBoardPlugIn;
335     end;
336
337     // \93Á\8eê\97p\93r\97pTBoard
338     TSpecialBoard = class(TBoard)
339     public
340         function Add(item: TThreadItem): integer; overload;
341         procedure Clear; overload;
342     end;
343
344         function        BBSsFindBoardFromBBSID( inBBSID : string ) : TBoard;
345         function        BBSsFindBoardFromURL( inURL : string ) : TBoard;
346         function        BBSsFindBoardFromTitle( inTitle : string ) : TBoard;
347         function        BBSsFindThreadFromURL(const inURL : string ) : TThreadItem;
348         function        ConvertDateTimeString( inDateTimeString : string) : TDateTime;
349
350     procedure    DestorySpecialBBS( inBBS : TBBS );
351
352 var
353         BBSs            : array of TBBS;
354     BoardGroups : array of TBoardGroup;
355     SpecialBBS  : TBBS;
356     
357 implementation
358
359 uses
360         GikoSystem, RoundData, MojuUtils, DateUtils, IniFiles;
361
362 const
363         BBS2CH_NAME:                                     string = '\82Q\82¿\82á\82ñ\82Ë\82é';
364         BBS2CH_LOG_FOLDER:               string = '2ch';
365         EXTERNAL_LOG_FOLDER:            string  = 'exboard';
366
367         FOLDER_INI_FILENAME:     string = 'Folder.ini';
368         FOLDER_INDEX_FILENAME: string   = 'Folder.idx';
369         SUBJECT_FILENAME:                       string  = 'subject.txt';
370         PATH_DELIM:                                             string  = '\';
371         SETTINGTXT_FILENAME:            string = 'SETTING.TXT';
372     HEADTXT_FILENAME:           string = 'head.html';
373         //DEFAULT_LIST_COUNT:           Integer = 100;
374
375 //! \83\8d\83O\82ð\8e\9d\82Á\82Ä\82¢\82é\82È\82ç\90^\82ð\95Ô\82·
376 function CountLog(Item: TThreadItem): Boolean;
377 begin
378         Result := Item.IsLogFile;
379 end;
380 //! \90V\92\85\82È\82ç\90^\82ð\95Ô\82·
381 function CountNew(Item: TThreadItem): Boolean;
382 begin
383         Result := Item.NewArrival;
384 end;
385 //! DAT\97\8e\82¿\82È\82ç\90^\82ð\95Ô\82·
386 function CountDat(Item: TThreadItem): Boolean;
387 begin
388         Result := (Item.AgeSage = gasArch);
389 end;
390 //! \90\91\83X\83\8c\82È\82ç\90^\82ð\95Ô\82·
391 function CountLive(Item: TThreadItem): Boolean;
392 begin
393         Result := (Item.AgeSage <> gasArch);
394 end;
395
396 //! \8fí\82É\90^
397 function CountAll(Item: TThreadItem): Boolean;
398 begin
399     Result := True;
400 end;
401
402
403
404 // BBSID \82ð\97p\82¢\82é 2 \82¿\82á\82ñ\82Ë\82é\82Ì\82Ý\92T\82µ\8fo\82µ\82Ü\82·
405 // BBSID \82Ì\8eg\97p\82Í\8bÉ\97Í\94ð\82¯\82Ä\82­\82¾\82³\82¢\81B
406 // \89Â\94\\82È\8fê\8d\87\82Í URL \82ð\8eg\97p\82µ\82Ä\82­\82¾\82³\82¢\81B
407 function        BBSsFindBoardFromBBSID(
408         inBBSID : string
409 ) : TBoard;
410 var
411         i : Integer;
412         tmpBoard : TBoard;
413 begin
414
415 //      Result := BBSs[ 0 ].FindBBSID( inBBSID );
416         Result := nil;
417         if Length(BoardGroups) > 0 then begin
418                 for i := BoardGroups[0].Count - 1 downto 0 do begin
419                         tmpBoard := TBoard(BoardGroups[0].Objects[i]);
420                         if tmpBoard.Is2ch then begin
421                                 if AnsiCompareStr(tmpBoard.BBSID, inBBSID) = 0 then begin
422                                         Result := tmpBoard;
423                                         EXIT;
424                                 end;
425                         end;
426                 end;
427         end;
428
429 end;
430 {**********************************************
431 \82±\82Ì\8aÖ\90\94\82Í\95K\82¸\94Â\82ÌURL\82Ì\8c`\8e®\82Å\93n\82µ\82Ä\82­\82¾\82³\82¢\81B
432 plugin\82ð\8eg\97p\82·\82é\82È\82ç\82Î\81AExtractBoardURL( inURL )
433 2ch\82È\82ç\82Î\81AGikoSys.Get2chThreadURL2BoardURL( inURL );
434 \82Å\95Ï\8a·\82µ\82Ä\82©\82ç\8cÄ\82Ñ\8fo\82µ\82Ä\82­\82¾\82³\82¢\81B
435 **********************************************}
436 function        BBSsFindBoardFromURL(
437         inURL   : string
438 ) : TBoard;
439 var
440         i,p                     : Integer;
441         accept          : TAcceptType;
442         protocol, host, path, document, port, bookmark : string;
443 begin
444         Result := nil;
445         for i := Length(BoardGroups) - 1 downto 1 do begin
446                 accept := BoardGroups[i].BoardPlugIn.AcceptURL(inURL);
447                 if (accept = atBoard) or (accept = atThread) then begin
448                         if BoardGroups[i].Find(inURL, p) then begin
449                                 Result := TBoard(BoardGroups[i].Objects[p]);
450                                 Exit;
451                         end else begin
452                                 inURL := BoardGroups[i].BoardPlugIn.ExtractBoardURL(inURL);
453                                 if BoardGroups[i].Find(inURL, p) then begin
454                                         Result := TBoard(BoardGroups[i].Objects[p]);
455                                         Exit;
456                                 end;
457                         end;
458                 end;
459         end;
460         //\82±\82±\82É\82«\82½\82ç\81Aplugin\82ð\8eg\82í\82È\82¢\82â\82Â\82ç\82ð\92²\82×\82é
461         if BoardGroups[0].Find(inURL, p) then
462                 Result := TBoard(BoardGroups[0].Objects[p]);
463                 
464         if (Result = nil) then begin
465                 GikoSys.ParseURI( inURL, protocol, host, path, document, port, bookmark );
466                 //\83z\83X\83g\82ª2ch\82È\82çBBSID\82Å\92²\82×\82é
467                 if GikoSys.Is2chHost(host) then begin
468                         Result := BBSsFindBoardFromBBSID(GikoSys.URLToID( inURL ));
469                 end;
470         end;
471
472 end;
473
474 function        BBSsFindBoardFromTitle(
475         inTitle : string
476 ) : TBoard;
477 var
478         i,j                             : Integer;
479         tmpBoard                : TBoard;
480 begin
481     Result := nil;
482         for i := Length( BBSs ) - 1 downto 0 do begin
483                 for j := BoardGroups[i].Count - 1 downto 0 do begin
484                         tmpBoard := TBoard(BoardGroups[i].Objects[j]);
485                         if ( AnsiCompareStr(tmpBoard.Title, inTitle) = 0) then begin
486                                 Result := tmpBoard;
487                                 Exit;
488                         end;
489                 end;
490         end;
491
492 end;
493
494 function        BBSsFindThreadFromURL(
495         const inURL                     : string
496 ) : TThreadItem;
497 var
498         board                   : TBoard;
499         tmpThread               : TThreadItem;
500         boardURL        : string;
501         protocol, host, path, document, port, bookmark : string;
502         BBSID, BBSKey : string;
503         i, bi : Integer;
504 begin
505
506         boardURL        := GikoSys.GetThreadURL2BoardURL( inURL );
507         board                   := BBSsFindBoardFromURL( boardURL );
508         if board = nil then
509                 Result := nil
510         else begin
511                 Result := board.FindThreadFromURL( inURL );
512                 //\82à\82µ\82à2ch\82Ì\94Â\82È\82ç
513                 if (Result = nil) and (board.Is2ch) then begin
514                         GikoSys.ParseURI( inURL, protocol, host, path, document, port, bookmark );
515                         GikoSys.Parse2chURL( inURL, path, document, BBSID, BBSKey );
516                         Result := board.FindThreadFromFileName(BBSKey + '.dat');
517                 end else if (Result = nil) and not (board.Is2ch) then begin
518                 //\83v\83\89\83O\83C\83\93\8cn\82Ì\92T\8dõ\81i\8eå\82ÉURL\82ª\93r\92\86\82Å\95Ï\8dX\82É\82È\82Á\82½\97Þ)
519                         try
520                                 bi := Length(BoardGroups) - 1;
521                                 for i := 1 to bi do begin
522                                         if (BoardGroups[i].BoardPlugIn <> nil) and (Assigned(Pointer(BoardGroups[i].BoardPlugIn.Module))) then begin
523                                                 if BoardGroups[i].BoardPlugIn.AcceptURL( inURL ) = atThread then begin
524                                                         tmpThread               := TThreadItem.Create( BoardGroups[i].BoardPlugIn, Board, inURL );
525                                                         if not board.IsThreadDatRead then begin
526                                                                 GikoSys.ReadSubjectFile( board );
527                                                         end;
528                                                         Result := Board.FindThreadFromFileName( tmpThread.FileName );
529                                                         tmpThread.Free;
530                                                         Break;
531                                                 end;
532                                         end;
533                                 end;
534                         except
535                 Result := nil;
536                         end;
537                 end;
538         end;
539
540 end;
541 {!
542 \brief \93Á\8eê\97p\93rBBS\8dí\8f\9c
543 \param bbs \8dí\8f\9c\82·\82é\93Á\8eê\97p\93rBBS
544 }
545 procedure DestorySpecialBBS( inBBS : TBBS );
546 var
547     sCategory : TCategory;
548     sBoard    : TSpecialBoard;
549 begin
550     if inBBS <> nil then begin
551         sCategory := inBBS.Items[0];
552         if sCategory <> nil then begin
553             sBoard := TSpecialBoard(sCategory.Items[0]);
554             if sBoard <> nil then begin
555                 sBoard.Modified := False;
556                 sBoard.Clear;
557                 FreeAndNil(sBoard);
558             end;
559         end;
560         FreeAndNil(inBBS);
561     end;
562 end;
563
564 (*************************************************************************
565  *\8b@\94\\96¼\81FTBBS\83R\83\93\83X\83g\83\89\83N\83^
566  *Public
567  *************************************************************************)
568 constructor TBBS.Create( boardFilePath : string );
569 begin
570         inherited Create;
571         Title := BBS2CH_NAME;
572         FFilePath := boardFilePath;
573 end;
574
575 (*************************************************************************
576  *\8b@\94\\96¼\81FTBBS\83f\83X\83g\83\89\83N\83^
577  *Public
578  *************************************************************************)
579 destructor TBBS.Destroy;
580 begin
581         Clear;
582         inherited;
583 end;
584
585 (*************************************************************************
586  *\8b@\94\\96¼\81F
587  *Public
588  *************************************************************************)
589 function TBBS.GetCategory(index: integer): TCategory;
590 begin
591         Result := TCategory(inherited Items[index]);
592 end;
593
594 procedure TBBS.SetCategory(index: integer; value: TCategory);
595 begin
596         inherited Items[index] := value;
597 end;
598
599 function TBBS.Add(item: TCategory): integer;
600 begin
601         Item.ParenTBBS := self;
602         Result := inherited Add(item);
603 end;
604
605 procedure TBBS.Delete(index: integer);
606 begin
607         if Items[index] <> nil then
608                 TCategory(Items[index]).Free;
609         Items[index] := nil;
610         inherited Delete(index);
611 end;
612
613 procedure TBBS.Clear;
614 var
615         i: integer;
616 begin
617         for i := Count - 1 downto 0 do
618                 Delete(i);
619     Capacity := Count;
620 end;
621
622 function TBBS.Find(key: string): TCategory;
623 begin
624         Result := nil;
625 end;
626
627 function TBBS.FindBBSID(const BBSID: string): TBoard;
628 var
629         i       : Integer;
630 begin
631         if not IsBoardFileRead then
632         GikoSys.ReadBoardFile( Self );
633         for i := Count - 1 downto 0 do begin
634                 Result := Items[ i ].FindBBSID(BBSID);
635                 if Result <> nil then
636                         Exit;
637         end;
638         Result := nil;
639 end;
640
641 //*************************************************************************
642 // \83^\83C\83g\83\8b\82Ì\88ê\92v\82·\82é\94Â\82ð\92T\82·
643 //*************************************************************************)
644 function TBBS.FindBoardFromTitle(const Title: string): TBoard;
645 var
646         i: Integer;
647 begin
648         if not IsBoardFileRead then
649         GikoSys.ReadBoardFile( Self );
650         for i := Count - 1 downto 0 do begin
651                 Result := Items[ i ].FindBoardFromTitle(Title);
652                 if Result <> nil then
653                         Exit;
654         end;
655         Result := nil;
656 end;
657
658 //*************************************************************************
659 // URL \82ð\8eó\82¯\95t\82¯\82é\94Â\82ð\92T\82·
660 //*************************************************************************)
661 function TBBS.FindBoardFromURL(const inURL: string): TBoard;
662 var
663         i                                       : Integer;
664 begin
665         if not IsBoardFileRead then
666         GikoSys.ReadBoardFile( Self );
667         for i := Count - 1 downto 0 do begin
668                 Result := Items[ i ].FindBoardFromURL( inURL );
669                 if Result <> nil then
670                         Exit;
671         end;
672         Result := nil;
673 end;
674
675 //*************************************************************************
676 // URL \82ð\8eó\82¯\95t\82¯\82é\83X\83\8c\83b\83h\82ð\92T\82·
677 //*************************************************************************)
678 function TBBS.FindThreadFromURL(const inURL: string): TThreadItem;
679 var
680         board                   : TBoard;
681         boardURL        : string;
682 begin
683
684         boardURL        := GikoSys.GetThreadURL2BoardURL( inURL );
685         board                   := FindBoardFromURL( boardURL );
686         if board = nil then
687                 Result := nil
688         else
689                 Result := board.FindThreadFromURL( inURL );
690
691 end;
692
693 function TBBS.FindThreadItem(const BBSID, FileName: string): TThreadItem;
694 var
695         Board: TBoard;
696 begin
697         Result := nil;
698         Board := FindBBSID(BBSID);
699         if Board = nil then
700                 Exit;
701         Result := Board.FindThreadFromFileName(FileName);
702 end;
703
704 function TBBS.FindCategoryFromTitle(const inTitle : string ) : TCategory;
705 var
706         i : Integer;
707 begin
708
709         for i := Count - 1 downto 0 do begin
710                 if AnsiCompareStr(Items[ i ].Title, inTitle) = 0 then begin
711                         Result := Items[ i ];
712                         Exit;
713                 end;
714         end;
715
716         Result := nil;
717
718 end;
719
720 procedure TBBS.SetSelectText(s: string);
721 begin
722         FSelectText := s;
723         ShortSelectText := CustomStringReplace(ZenToHan(s), ' ', '');
724 end;
725
726 {class function TBBS.GetColumnName(Index: Integer): string;
727 begin
728         Result := COLUMN_CATEGORY[Index];
729 end;
730
731 class function TBBS.GetColumnCount: Integer;
732 begin
733         Result := Length(COLUMN_CATEGORY);
734 end;}
735
736 //===================
737 //TCategory
738 //===================
739 constructor TCategory.Create;
740 begin
741         inherited;
742
743         Duplicates              := dupIgnore;
744         CaseSensitive   := False;
745         //Sorted                                := True;
746 end;
747
748 destructor TCategory.Destroy;
749 begin
750         Clear;
751         inherited;
752 end;
753
754 function TCategory.GetBoard(index: integer): TBoard;
755 begin
756         Result := TBoard( Objects[index] );
757 end;
758
759 procedure TCategory.SetBoard(index: integer; value: TBoard);
760 begin
761         Objects[index] := value;
762         Strings[index] := value.URL
763 end;
764
765 function TCategory.Add(item: TBoard): integer;
766 begin
767         Item.ParentCategory := self;
768         Result := AddObject( item.URL, item );
769 end;
770
771 procedure TCategory.Delete(index: integer);
772 begin
773     inherited Delete(index);
774 end;
775
776 procedure TCategory.Clear;
777 var
778         i: integer;
779 begin
780         for i := Count - 1 downto 0 do
781                 Delete(i);
782         Capacity := Count;
783 end;
784
785 function TCategory.FindName(const key: string): TBoard;
786 begin
787         Result := nil;
788 end;
789
790 function TCategory.FindBBSID(const BBSID: string): TBoard;
791 var
792         i       : integer;
793 begin
794         for i := Count - 1 downto 0 do begin
795                 if AnsiCompareStr(Items[i].FBBSID, BBSID) = 0 then begin
796                         Result := Items[i];
797                         Exit;
798                 end;
799         end;
800         Result := nil;
801 end;
802
803 //*************************************************************************
804 // \83^\83C\83g\83\8b\82Ì\88ê\92v\82·\82é\94Â\82ð\92T\82·
805 //*************************************************************************)
806 function TCategory.FindBoardFromTitle(const Title: string): TBoard;
807 var
808         i       : integer;
809 begin
810         for i := Count - 1 downto 0 do begin
811                 if AnsiCompareStr(Items[i].FTitle, Title) = 0 then begin
812                         Result := Items[i];
813                         Exit;
814                 end;
815         end;
816         Result := nil;
817 end;
818
819 //*************************************************************************
820 // URL \82ð\8eó\82¯\95t\82¯\82é\94Â\82ð\92T\82·
821 //*************************************************************************)
822 function TCategory.FindBoardFromURL(const inURL: string): TBoard;
823 var
824         i       : Integer;
825 begin
826         i := IndexOf( inURL );
827         if i >= 0 then
828                 Result := TBoard( Objects[ i ] )
829         else
830                 Result := nil;
831 end;
832
833 //*************************************************************************
834 // URL \82ð\8eó\82¯\95t\82¯\82é\83X\83\8c\83b\83h\82ð\92T\82·
835 //*************************************************************************)
836 function TCategory.FindThreadFromURL(const inURL: string): TThreadItem;
837 var
838         board                   : TBoard;
839         boardURL        : string;
840 begin
841
842         boardURL        := GikoSys.GetThreadURL2BoardURL( inURL );
843         board                   := FindBoardFromURL( boardURL );
844         if board = nil then
845                 Result := nil
846         else
847                 Result := board.FindThreadFromURL( inURL );
848
849 end;
850
851 function TCategory.IsMidoku: Boolean;
852 var
853         i: Integer;
854         j: Integer;
855 begin
856         Result := False;
857         for i := 0 to Count - 1 do begin
858                 if Items[i] <> nil then begin
859                         for j := 0 to Items[i].Count - 1 do begin
860                                 if Items[i].Items[j] <> nil then begin
861 //                                      if (Items[i].Items[j].IsLogFile) and (Items[i].Items[j].Count > Items[i].Items[j].Kokomade) then begin
862                                         if (Items[i].Items[j].IsLogFile) and (Items[i].Items[j].UnRead) then begin
863                                                 Result := True;
864                                                 Exit;
865                                         end;
866                                 end;
867                         end;
868                 end;
869         end;
870 end;
871
872 {class function TCategory.GetColumnName(Index: Integer): string;
873 begin
874         Result := COLUMN_BOARD[Index];
875 end;
876
877 class function TCategory.GetColumnCount: Integer;
878 begin
879         Result := Length(COLUMN_BOARD);
880 end;}
881
882 //===================
883 //TBoard
884 //===================
885 procedure TBoard.Init;
886 begin
887         Duplicates              := dupIgnore;
888         CaseSensitive   := False;
889         //Sorted                                := True;
890
891         FNo := 0;
892         FTitle := '';
893         FBBSID := '';
894         FURL := '';
895         FRound := False;
896         FRoundDate := ZERO_DATE;
897         FLastModified := ZERO_DATE;
898         FLastGetTime := ZERO_DATE;
899         FIsThreadDatRead := False;
900         FUnRead := 0;
901         FMultiplicity := 0;
902 //      FListStyle := vsReport;
903 //      FItemNoVisible := True;
904
905         FUpdate := True;
906 end;
907
908 // *************************************************************************
909 // \8aO\95\94\94Â\83v\83\89\83O\83C\83\93\82ð\8ew\92è\82µ\82½\83R\83\93\83X\83g\83\89\83N\83^
910 // *************************************************************************
911 constructor TBoard.Create(
912         inPlugIn        : TBoardPlugIn;
913         inURL                   : string
914 );
915 var
916         protocol, host, path, document, port, bookmark  : string;
917 begin
918
919         inherited Create;
920         Init;
921
922         FBoardPlugIn    := inPlugIn;
923         URL                                             := inURL;
924         BBSID                                   := GikoSys.UrlToID( inURL );
925
926         if inPlugIn = nil then begin
927                 // subject.txt \82Ì\95Û\91\83p\83X\82ð\90Ý\92è
928                 GikoSys.ParseURI( inURL, protocol, host, path, document, port, bookmark );
929                 if GikoSys.Is2chHost( host ) then begin
930                         Self.Is2ch := True;
931                         FilePath :=
932                                 GikoSys.Setting.LogFolderP  +
933                                 BBS2CH_LOG_FOLDER + PATH_DELIM + BBSID + PATH_DELIM + SUBJECT_FILENAME
934                 end else begin
935                         Self.Is2ch := False;
936                         FilePath :=
937                                 GikoSys.Setting.LogFolderP +
938                                 EXTERNAL_LOG_FOLDER + PATH_DELIM + host + PATH_DELIM + BBSID + PATH_DELIM + SUBJECT_FILENAME
939                 end;
940         end else begin
941                 // \83v\83\89\83O\83C\83\93\82É TBoardItem \82ª\8dì\90¬\82³\82ê\82½\82±\82Æ\82ð\93`\82¦\82é
942                 inPlugIn.CreateBoardItem( DWORD( Self ) );
943                 //Self.Is2ch := False;  //plugin\91¤\82Å\90Ý\92è\82·\82é
944         end;
945
946 end;
947
948 // *************************************************************************
949 // \83f\83X\83g\83\89\83N\83^
950 // *************************************************************************
951 destructor TBoard.Destroy;
952 begin
953         if FModified then begin
954                 GikoSys.WriteThreadDat(Self);
955                 SaveSettings;
956         end;
957
958         // \83v\83\89\83O\83C\83\93\82É TBoardItem \82ª\94j\8aü\82³\82ê\82½\82±\82Æ\82ð\93`\82¦\82é
959         if IsBoardPlugInAvailable then
960                 BoardPlugIn.DisposeBoardItem( DWORD( Self ) );
961
962         Clear;
963         inherited;
964 end;
965
966 // *************************************************************************
967 // \8aO\95\94\94Â\83v\83\89\83O\83C\83\93\82ª\8eg\97p\89Â\94\\82©
968 // *************************************************************************
969 function        TBoard.IsBoardPlugInAvailable : Boolean;
970 begin
971
972         repeat
973                 if BoardPlugIn = nil then
974                         Break;
975                         
976                 if not Assigned( Pointer( BoardPlugIn.Module ) ) then
977                         Break;
978
979                 Result := True;
980                 Exit;
981         until True;
982
983         Result := False;
984
985 end;
986
987 function TBoard.GetThreadItem(index: integer): TThreadItem;
988 begin
989         Result := TThreadItem( Objects[index] );
990 end;
991
992 procedure TBoard.SetThreadItem(index: integer; value: TThreadItem);
993 begin
994         Objects[index] := value;
995         Strings[index] := value.URL;
996 end;
997
998 function TBoard.Add(Item: TThreadItem): Integer;
999 begin
1000         Item.ParentBoard := Self;
1001         Result := inherited AddObject(Item.URL, Item);
1002 end;
1003
1004 procedure TBoard.Insert(Index: Integer; Item: TThreadItem);
1005 begin
1006         Item.ParentBoard := Self;
1007         inherited InsertObject(Index, Item.URL, Item);
1008
1009 end;
1010
1011 //Index\82Å\8ew\92è\82³\82ê\82½\83X\83\8c\83b\83h\83I\83u\83W\83F\83N\83g\82ð\94j\8aü
1012 procedure TBoard.Delete(index: Integer);
1013 begin
1014         if Items[index] <> nil then
1015                 TThreadItem(Items[index]).Free;
1016         inherited Delete(index);
1017 end;
1018
1019 //Index\82Å\8ew\92è\82³\82ê\82½\83X\83\8c\83b\83h\82ð\83\8a\83X\83g\82©\82ç\8dí\8f\9c\81i\83X\83\8c\83I\83u\83W\83F\83N\83g\82Í\82Ì\82±\82·\81j
1020 procedure TBoard.DeleteList(index: integer);
1021 begin
1022         inherited Delete(index);
1023 end;
1024
1025 procedure TBoard.Clear;
1026 var
1027         i: integer;
1028 begin
1029 //      FUnRead := 0;
1030         for i := Count - 1 downto 0 do
1031                 Delete(i);
1032          Capacity := Count;
1033 end;
1034
1035 function TBoard.FindThreadFromFileName(const ItemFileName: string): TThreadItem;
1036 var
1037         i: integer;
1038 begin
1039         Result := nil;
1040         for i := 0 to Count - 1 do begin
1041                 if AnsiCompareStr(Items[i].FileName, ItemFileName) = 0 then begin
1042                         Result := Items[i];
1043                         Exit;
1044                 end;
1045         end;
1046 end;
1047
1048 function TBoard.GetIndexFromFileName(const ItemFileName: string): Integer;
1049 var
1050         i: integer;
1051 begin
1052         Result := -1;
1053         for i := 0 to Count - 1 do begin
1054                 if Items[i].FileName = ItemFileName then begin
1055                         Result := i;
1056                         Exit;
1057                 end;
1058         end;
1059 end;
1060
1061 function TBoard.GetIndexFromURL(const URL: string; reverse : Boolean = False): Integer;
1062 var
1063         i : Integer;
1064 begin
1065         if not reverse then
1066                 Result := IndexOf( URL )
1067         else begin
1068         Result := -1;
1069                 for i := Self.Count - 1 downto 0 do begin
1070                         if Strings[i] = URL then begin
1071                                 Result := i;
1072                                 break;
1073                         end;
1074                 end;
1075         end;
1076 end;
1077
1078 function TBoard.FindThreadFromURL(const inURL : string ) : TThreadItem;
1079 var
1080         i : Integer;
1081 begin
1082
1083         if not IsThreadDatRead then
1084                 GikoSys.ReadSubjectFile( Self );
1085
1086         i := IndexOf( inURL );
1087         if i >= 0 then
1088                 Result := TThreadItem( Objects[ i ] )
1089         else
1090                 Result := nil;
1091
1092 end;
1093
1094 {function TBoard.GetMidokuCount: Integer;
1095 var
1096         i: integer;
1097 begin
1098         Result := 0;
1099         for i := 0 to Count- 1 do begin
1100                 if Items[i] <> nil then begin
1101                         if (Items[i].IsLogFile) and (Items[i].Count > Items[i].Kokomade) then
1102                                 inc(Result);
1103                 end;
1104         end;
1105 end;
1106 }
1107
1108 procedure TBoard.LoadSettings;
1109 var
1110         ini: TMemIniFile;
1111         FileName: string;
1112         tmp: string;
1113 begin
1114         if Length( FilePath ) > 0 then
1115                 FileName := ExtractFilePath( FilePath ) + FOLDER_INI_FILENAME
1116         else
1117                 FileName := GikoSys.Setting.LogFolderP
1118                                                         + BBS2CH_LOG_FOLDER + PATH_DELIM + BBSID + PATH_DELIM + FOLDER_INI_FILENAME;
1119
1120         if not FileExists(FileName) then
1121                 Exit;
1122         ini := TMemIniFile.Create(FileName);
1123         try
1124 //              Round := ini.ReadBool('Status', 'Round', False);
1125                 tmp := ini.ReadString('Status', 'RoundDate', DateTimeToStr(ZERO_DATE));
1126                 FRoundDate := ConvertDateTimeString(tmp);
1127                 tmp := ini.ReadString('Status', 'LastModified', DateTimeToStr(ZERO_DATE));
1128                 FLastModified := ConvertDateTimeString(tmp);
1129                 tmp := ini.ReadString('Status', 'LastGetTime', DateTimeToStr(ZERO_DATE));
1130                 FLastGetTime := ConvertDateTimeString(tmp);
1131
1132                 tmp := ini.ReadString('BoardInformation', 'SETTINGTXTTime', DateTimeToStr(ZERO_DATE));
1133                 FSETTINGTXTTime := ConvertDateTimeString(tmp);
1134                 tmp := ini.ReadString('BoardInformation', 'HEADTXTTime', DateTimeToStr(ZERO_DATE));
1135                 FHEADTXTTime := ConvertDateTimeString(tmp);
1136
1137                 FIsSETTINGTXT := ini.ReadBool('BoardInformation', 'IsSETTINGTXT', false);
1138                 FIsHEADTXT := ini.ReadBool('BoardInformation', 'IsHEADTXT', false);
1139                 FTitlePictureURL := ini.ReadString('BoardInformation', 'TitlePictureURL', '');
1140
1141                 FUnRead := ini.ReadInteger('Status', 'UnRead', 0);
1142                 FSPID := ini.ReadString('Cookie', 'SPID', '');
1143                 FPON := ini.ReadString('Cookie', 'PON', '');
1144                 FCookie  := ini.ReadString('Cookie', 'Cookie', '');
1145                 tmp := ini.ReadString('Cookie', 'Expires', DateTimeToStr(ZERO_DATE));
1146                 FExpires := ConvertDateTimeString(tmp);
1147                 FKotehanName := ini.ReadString('Kotehan', 'Name', '');
1148                 FKotehanMail := ini.ReadString('Kotehan', 'Mail', '');
1149
1150                 if UnRead < 0 then
1151                         UnRead := 0;
1152         finally
1153                 ini.Free;
1154         end;
1155 end;
1156
1157 procedure TBoard.SaveSettings;
1158 var
1159         ini: TMemIniFile;
1160         FileName: string;
1161 begin
1162         if Length( FilePath ) > 0 then
1163                 FileName := ExtractFilePath( FilePath )
1164         else
1165                 FileName := GikoSys.Setting.LogFolderP
1166                                                         + BBS2CH_LOG_FOLDER + PATH_DELIM + BBSID + PATH_DELIM;
1167         if not GikoSys.DirectoryExistsEx(FileName) then
1168                 GikoSys.ForceDirectoriesEx(FileName);
1169         FileName := FileName + FOLDER_INI_FILENAME;
1170         ini := TMemIniFile.Create(FileName);
1171         try
1172                 if UnRead < 0 then
1173                         UnRead := 0;
1174 //              ini.WriteBool('Status', 'Round', Round);
1175                 ini.WriteDateTime('Status', 'RoundDate', FRoundDate);
1176                 ini.WriteDateTime('Status', 'LastModified', FLastModified);
1177                 ini.WriteDateTime('Status', 'LastGetTime', FLastGetTime);
1178                 ini.WriteInteger('Status', 'UnRead', FUnRead);
1179                 ini.WriteString('Cookie', 'SPID', FSPID);
1180                 ini.WriteString('Cookie', 'PON', FPON);
1181                 ini.WriteString('Cookie', 'Cookie', FCookie);
1182                 ini.WriteDateTime('Cookie', 'Expires', FExpires);
1183                 ini.WriteString('Kotehan', 'Name', FKotehanName);
1184                 ini.WriteString('Kotehan', 'Mail', FKotehanMail);
1185
1186                 ini.WriteDateTime('BoardInformation', 'SETTINGTXTTime', FSETTINGTXTTime);
1187                 ini.WriteDateTime('BoardInformation', 'HEADTXTTime', FHEADTXTTime);
1188
1189                 ini.WriteBool('BoardInformation', 'IsSETTINGTXT', FIsSETTINGTXT);
1190                 ini.WriteBool('BoardInformation', 'IsHEADTXT', FIsHEADTXT);
1191                 ini.WriteString('BoardInformation', 'TitlePictureURL', FTitlePictureURL);
1192 //              ini.WriteInteger('Status', 'ListStyle', Ord(ListStyle));
1193 //              ini.WriteBool('Status', 'ItemNoVisible', ItemNoVisible);
1194 //              ini.WriteInteger('Status', 'ViewType', Ord(ViewType));
1195                 ini.UpdateFile;
1196         finally
1197                 ini.Free;
1198         end;
1199 end;
1200 //\82Æ\82«\82½\82Ü2003 02 08 0:32:13\82±\82ñ\82È\8c`\8e®\82Ì\93ú\95t\82ª\82 \82é\82Ì\82Å\82»\82ê\82ð
1201 //        2003/02/08 0:32:13\82É\95Ï\8a·\82·\82é
1202 function        ConvertDateTimeString( inDateTimeString : string) : TDateTime;
1203 const
1204         ZERO_DATE_STRING : string = '1970/01/01 0:00:00';
1205 var
1206         i : Integer;
1207     y: Integer;
1208     m: Integer;
1209     d: Integer;
1210     hour: Integer;
1211     min: Integer;
1212     sec: Integer;
1213 begin
1214     if inDateTimeString = '' then
1215         inDateTimeString := ZERO_DATE_STRING;
1216
1217     if ( AnsiPos('/', inDateTimeString ) = 0 ) and
1218         ( AnsiCompareStr( DateTimeToStr(ZERO_DATE), inDateTimeString) <> 0 ) then begin
1219                 for i := 0 to 1 do begin
1220                 Insert('/',inDateTimeString, AnsiPos(' ', inDateTimeString) + 1 );
1221                 Delete(inDateTimeString, AnsiPos(' ', inDateTimeString), 1);
1222         end;
1223     end;
1224     try
1225         Result := StrToDateTime( inDateTimeString );
1226     except
1227         if( inDateTimeString[5] = '/' ) and ( inDateTimeString[8] = '/' ) then begin
1228             y := StrToIntDef( Copy(inDateTimeString, 1, 4), 1970 );
1229                         m := StrToIntDef( Copy(inDateTimeString, 6, 2), 1 );
1230             d := StrToIntDef( Copy(inDateTimeString, 9, 2), 1 );
1231             hour := 0; min  := 0; sec  := 0;
1232
1233                 if Length(inDateTimeString) > 11 then begin
1234                 if( inDateTimeString[13] = ':' ) and ( inDateTimeString[16] = ':' ) then begin
1235                         hour := StrToIntDef( Copy(inDateTimeString, 12, 1), 0 );
1236                     min  := StrToIntDef( Copy(inDateTimeString, 14, 2), 0 );
1237                     sec  := StrToIntDef( Copy(inDateTimeString, 17, 2), 0 );
1238                 end else if( inDateTimeString[14] = ':' ) and ( inDateTimeString[17] = ':' ) then begin
1239                         hour := StrToIntDef( Copy(inDateTimeString, 12, 2), 0 );
1240                     min  := StrToIntDef( Copy(inDateTimeString, 15, 2), 0 );
1241                     sec  := StrToIntDef( Copy(inDateTimeString, 18, 2), 0 );
1242                 end;
1243             end;
1244             try
1245                 Result := EncodeDateTime(y ,m, d, hour, min, sec, 0);
1246             except
1247                 Result := ZERO_DATE;
1248             end;
1249         end else
1250                 Result := ZERO_DATE;
1251     end;
1252
1253
1254    // Result := inDateTimeString;
1255 end;
1256 //! \83T\83u\83W\83F\83N\83gURL\8eæ\93¾
1257 function TBoard.GetReadCgiURL: string;
1258 begin
1259         Result := URL + SUBJECT_FILENAME;
1260
1261 end;
1262
1263 //! \83T\83u\83W\83F\83N\83g\83t\83@\83C\83\8b\96¼\8eæ\93¾\81i\83p\83X\81{\83t\83@\83C\83\8b\96¼\81j
1264 function TBoard.GetSubjectFileName: string;
1265 begin
1266         if Length( FilePath ) > 0 then
1267                 Result := FilePath
1268         else
1269                 Result := GikoSys.Setting.LogFolderP
1270                                                 + BBS2CH_LOG_FOLDER + PATH_DELIM + BBSID + PATH_DELIM + SUBJECT_FILENAME;
1271 end;
1272
1273 //! \83C\83\93\83f\83b\83N\83X\83t\83@\83C\83\8b\96¼(folder.idx)\8eæ\93¾\81i\83p\83X\81{\83t\83@\83C\83\8b\96¼\81j
1274 function TBoard.GetFolderIndexFileName: string;
1275 begin
1276         if Length( FilePath ) > 0 then
1277                 Result := ExtractFilePath( FilePath ) + FOLDER_INDEX_FILENAME
1278         else
1279                 Result := GikoSys.Setting.LogFolderP
1280                                                 + BBS2CH_LOG_FOLDER + PATH_DELIM + BBSID + PATH_DELIM + FOLDER_INDEX_FILENAME;
1281 end;
1282 //! SETTING.TXT\82Ì\83t\83@\83C\83\8b\96¼\8eæ\93¾
1283 function TBoard.GetSETTINGTXTFileName: string;
1284 begin
1285         if Length( FilePath ) > 0 then
1286                 Result := ExtractFilePath( FilePath ) + SETTINGTXT_FILENAME
1287         else
1288                 Result := GikoSys.Setting.LogFolderP
1289                                                 + BBS2CH_LOG_FOLDER + PATH_DELIM + BBSID + PATH_DELIM + SETTINGTXT_FILENAME;
1290 end;
1291
1292 function TBoard.GETHEADTXTFileName: string;
1293 begin
1294         if Length( FilePath ) > 0 then
1295                 Result := ExtractFilePath( FilePath ) + HEADTXT_FILENAME
1296         else
1297                 Result := GikoSys.Setting.LogFolderP
1298                                                 + BBS2CH_LOG_FOLDER + PATH_DELIM + BBSID + PATH_DELIM + HEADTXT_FILENAME;
1299 end;
1300 function TBoard.GetTitlePictureFileName: string;
1301 var
1302         tmpName: string;
1303 begin
1304         if FTitlePictureURL = '' then
1305                 Result := ''
1306         else begin
1307                 tmpName := Copy(FTitlePictureURL, LastDelimiter('/', FTitlePictureURL) + 1, Length(FTitlePictureURL));
1308                 if Length( FilePath ) > 0 then
1309                         Result := ExtractFilePath( FilePath ) + tmpName
1310                 else
1311                         Result := GikoSys.Setting.LogFolderP
1312                                                         + BBS2CH_LOG_FOLDER + PATH_DELIM + BBSID + PATH_DELIM + tmpName;
1313         end;
1314 end;
1315
1316 // \83X\83\8c\97§\82Ä\91\97\90MURL
1317 function TBoard.GetSendURL: string;
1318 begin
1319     Result := GikoSys.UrlToServer(URL);
1320         if Self.Is2ch then
1321         Result := Result + 'test/bbs.cgi'
1322     else
1323         Result := Result + 'test/subbbs.cgi';
1324
1325 end;
1326
1327 procedure TBoard.SetRound(b: Boolean);
1328 begin
1329         if b then
1330                 RoundList.Add(Self)
1331         else
1332                 RoundList.Delete(Self);
1333         if FRound = b then Exit;
1334         FRound := b;
1335         if FUpdate then
1336                 FModified := True;
1337 end;
1338
1339 procedure TBoard.SetRoundName(s: string);
1340 begin
1341         if FRoundName = s then Exit;
1342         FRoundName := s;
1343         if FUpdate then
1344                 FModified := True;
1345 end;
1346
1347 procedure TBoard.SetLastModified(d: TDateTime);
1348 begin
1349         if FLastModified = d then Exit;
1350         FLastModified := d;
1351         if FUpdate then
1352                 FModified := True;
1353 end;
1354
1355 procedure TBoard.SetLastGetTime(d: TDateTime);
1356 begin
1357         if FLastGetTime = d then Exit;
1358         FLastGetTime := d;
1359         if FUpdate then
1360                 FModified := True;
1361 end;
1362
1363 procedure TBoard.SetUnRead(i: Integer);
1364 begin
1365         if FUnRead = i then Exit;
1366         if i < 0 then i := 0;
1367         FUnRead := i;
1368         if FUpdate then
1369                 FModified := True;
1370 end;
1371
1372 procedure TBoard.SetKotehanName(s: string);
1373 begin
1374         if FKotehanName = s then Exit;
1375         FKotehanName := s;
1376         if FUpdate then
1377                 FModified := True;
1378 end;
1379
1380 procedure TBoard.SetKotehanMail(s: string);
1381 begin
1382         if FKotehanMail = s then Exit;
1383         FKotehanMail := s;
1384         if FUpdate then
1385                 FModified := True;
1386 end;
1387 //! func\82Ì\8fð\8c\8f\82É\88ê\92v\82·\82é\83X\83\8c\83b\83h\82Ì\90\94\82ð\95Ô\82·
1388 function TBoard.GetThreadCount(func :TThreadCount ): Integer;
1389 var
1390         i: Integer;
1391 begin
1392         Result := 0;
1393         if Length( ParentCategory.ParenTBBS.ShortSelectText ) = 0 then
1394         begin
1395                 for i := 0 to Count - 1 do begin
1396                         if func(Items[i]) then
1397                                 inc(Result);
1398                 end;
1399         end else begin
1400                 for i := 0 to Count - 1 do begin
1401                         if func(Items[i]) then
1402                         begin
1403                                 if Items[i].ShortTitle = '' then
1404                                         Items[i].ShortTitle := CustomStringReplace(ZenToHan(Items[i].Title), ' ', '');
1405                                 if AnsiPos(ParentCategory.ParenTBBS.ShortSelectText, Items[i].ShortTitle) <> 0 then
1406                                         inc(Result);
1407                         end;
1408                 end;
1409         end;
1410 end;
1411 //! \90V\92\85\83X\83\8c\83b\83h\82Ì\90\94\82ð\8eæ\93¾\82·\82é
1412 function TBoard.GetNewThreadCount: Integer;
1413 begin
1414         Result := GetThreadCount(CountNew);
1415 end;
1416 //! \83\8d\83O\97L\82è\83X\83\8c\83b\83h\82Ì\90\94\82ð\8eæ\93¾\82·\82é
1417 function TBoard.GetLogThreadCount: Integer;
1418 begin
1419         Result := GetThreadCount(CountLog);
1420 end;
1421 //! \8di\8d\9e\82Ý\8fð\8c\8f\82É\88ê\92v\82·\82é\83X\83\8c\83b\83h\82Ì\90\94\82ð\8eæ\93¾\82·\82é
1422 function TBoard.GetUserThreadCount: Integer;
1423 begin
1424         Result := GetThreadCount(CountAll);
1425 end;
1426 //! DAT\97\8e\82¿\83X\83\8c\83b\83h\82Ì\90\94\82ð\8eæ\93¾\82·\82é
1427 function TBoard.GetArchiveThreadCount: Integer;
1428 begin
1429         Result := GetThreadCount(CountDat);
1430 end;
1431 //! \90\91\83X\83\8c\83b\83h\82Ì\90\94\82ð\8eæ\93¾\82·\82é
1432 function TBoard.GetLiveThreadCount: Integer;
1433 begin
1434         Result := GetThreadCount(CountLive);
1435 end;
1436 //! func\82Ì\8fð\8c\8f\82É\93K\8d\87\82·\82éIndex\94Ô\96Ú\82Ì\83X\83\8c\83b\83h\82ð\8eæ\93¾\82·\82é
1437 function TBoard.GetThread(func :TThreadCount;const Index :Integer ): TThreadItem;
1438 var
1439         i: Integer;
1440         Cnt: Integer;
1441 begin
1442         Result := nil;
1443         Cnt := 0;
1444         if Length( ParentCategory.ParenTBBS.ShortSelectText ) = 0 then
1445         begin
1446                 for i := 0 to Count - 1 do begin
1447                         if func(Items[i]) then begin
1448                                 if Index = Cnt then begin
1449                                         Result := Items[i];
1450                                         Exit;
1451                                 end;
1452                                 inc(Cnt);
1453                         end;
1454                 end;
1455         end else begin
1456                 for i := 0 to Count - 1 do begin
1457                         if func(Items[i]) then begin
1458                                 if Length(Items[i].ShortTitle) = 0 then
1459                                         Items[i].ShortTitle := CustomStringReplace(ZenToHan(Items[i].Title), ' ', '');
1460                                 if AnsiPos(ParentCategory.ParenTBBS.ShortSelectText, Items[i].ShortTitle) <> 0 then begin
1461                                         if Index = Cnt then begin
1462                                                 Result := Items[i];
1463                                                 Exit;
1464                                         end;
1465                                         inc(Cnt);
1466                                 end;
1467                         end;
1468                 end;
1469         end;
1470 end;
1471 //! DAT\97\8e\82¿\83X\83\8c\83b\83h\82ÅIndex\94Ô\96Ú\82Ì\83X\83\8c\83b\83h\82ð\8eæ\93¾\82·\82é
1472 function TBoard.GetArchiveThread(Index: Integer): TThreadItem;
1473 begin
1474         Result := GetThread(CountDat, Index);
1475 end;
1476 //! \90\91\83X\83\8c\83b\83h\82ÅIndex\94Ô\96Ú\82Ì\83X\83\8c\83b\83h\82ð\8eæ\93¾\82·\82é
1477 function TBoard.GetLiveThread(Index: Integer): TThreadItem;
1478 begin
1479         Result := GetThread(CountLive, Index);
1480 end;
1481 //! \90V\92\85\83X\83\8c\83b\83h\82ÅIndex\94Ô\96Ú\82Ì\83X\83\8c\83b\83h\82ð\8eæ\93¾\82·\82é
1482 function TBoard.GetNewThread(Index: Integer): TThreadItem;
1483 begin
1484         Result := GetThread(CountNew, Index);
1485 end;
1486 //! Log\82 \82è\83X\83\8c\83b\83h\82ÌIndex\94Ô\96Ú\82Ì\83X\83\8c\83b\83h\82ð\8eæ\93¾\82·\82é
1487 function TBoard.GetLogThread(Index: Integer): TThreadItem;
1488 begin
1489         Result := GetThread(CountLog, Index);
1490 end;
1491 //! \8di\8d\9e\82Ý\82ÅIndex\94Ô\96Ú\82Ì\83X\83\8c\83b\83h\82ð\8eæ\93¾\82·\82é
1492 function TBoard.GetUserThread(Index: Integer): TThreadItem;
1493 begin
1494         Result := GetThread(CountAll, Index);
1495 end;
1496
1497 procedure TBoard.BeginUpdate;
1498 begin
1499         FUpdate := False;
1500 end;
1501
1502 procedure TBoard.EndUpdate;
1503 begin
1504         FUpdate := True;
1505 end;
1506
1507 //constructor TThreadItem.Create(AOwner: TComponent);
1508 procedure TThreadItem.Init;
1509 begin
1510         FNo := 0;
1511         FFileName := '';
1512         FTitle := '';
1513         FRoundDate := ZERO_DATE;
1514         FLastModified := ZERO_DATE;
1515         FCount := 0;
1516         FAllResCount := 0;
1517         FNewResCount := 0;
1518         FSize := 0;
1519         FRound := False;
1520         FIsLogFile := False;
1521         FParentBoard := nil;
1522         FKokomade := -1;
1523         FNewReceive := 0;
1524         FNewArrival := False;
1525
1526         FUpdate := True;
1527         FURL := '';
1528         FJumpAddress := 0;
1529 end;
1530
1531 // *************************************************************************
1532 // \8aO\95\94\94Â\83v\83\89\83O\83C\83\93\82ð\8ew\92è\82µ\82½\83R\83\93\83X\83g\83\89\83N\83^
1533 // *************************************************************************
1534 constructor TThreadItem.Create(
1535         const inPlugIn : TBoardPlugIn;
1536         const inBoard : TBoard;
1537         inURL : string
1538 );
1539 var
1540         foundPos                        : Integer;
1541         protocol, host, path, document, port, bookmark  : string;
1542         BBSID, BBSKey   : string;
1543 const
1544         READ_PATH                                                       = '/test/read.cgi';
1545 begin
1546
1547         inherited Create;
1548         Init;
1549         FParentBoard    := inBoard;
1550         //FBoardPlugIn  := inPlugIn;
1551         URL                             := inURL;
1552
1553         if inPlugIn = nil then begin
1554                 foundPos := Pos( READ_PATH, inURL );
1555                 if foundPos > 0 then begin
1556                         // dat \82Ì\95Û\91\83p\83X\82ð\90Ý\92è
1557                         GikoSys.ParseURI( inURL, protocol, host, path, document, port, bookmark );
1558                         GikoSys.Parse2chURL( inURL, path, document, BBSID, BBSKey );
1559                         FileName        := BBSKey + '.dat';
1560                         IsLogFile       := FileExists( FilePath );
1561                         URL                             := GikoSys.Get2chBrowsableThreadURL( inURL );
1562                 end;
1563         end else begin
1564                 // \83v\83\89\83O\83C\83\93\82É TThreadItem \82ª\8dì\90¬\82³\82ê\82½\82±\82Æ\82ð\93`\82¦\82é
1565                 inPlugIn.CreateThreadItem( DWORD( Self ) );
1566         end;
1567
1568 end;
1569 // *************************************************************************
1570 // \8aO\95\94\94Â\83v\83\89\83O\83C\83\93\82ð\8ew\92è\82µ\82½\83R\83\93\83X\83g\83\89\83N\83^ Log\97L\82è\82©\82Ç\82¤\82©\94»\92f\8dÏ\82Ý
1571 // FileName\82à\8eæ\93¾\8dÏ\82Ý\81@\81¨\81@ReadSubject\97p
1572 // *************************************************************************
1573 constructor TThreadItem.Create(
1574         const inPlugIn : TBoardPlugIn;
1575         const inBoard : TBoard;
1576         inURL : string;
1577         inExist: Boolean;
1578         const inFilename: string
1579 );
1580 begin
1581
1582         inherited Create;
1583         Init;
1584         FParentBoard    := inBoard;
1585         URL                             := inURL;
1586
1587         if inPlugIn = nil then begin
1588                 // dat \82Ì\95Û\91\83p\83X\82ð\90Ý\92è
1589                 FileName        := inFilename;
1590                 IsLogFile       := inExist;
1591                 URL                             := GikoSys.Get2chBrowsableThreadURL( inURL );
1592         end else begin
1593                 // \83v\83\89\83O\83C\83\93\82É TThreadItem \82ª\8dì\90¬\82³\82ê\82½\82±\82Æ\82ð\93`\82¦\82é
1594                 inPlugIn.CreateThreadItem( DWORD( Self ) );
1595         end;
1596
1597 end;
1598 // *************************************************************************
1599 // \83f\83X\83g\83\89\83N\83^
1600 // *************************************************************************
1601 destructor TThreadItem.Destroy;
1602 begin
1603
1604         // \83v\83\89\83O\83C\83\93\82É TThreadItem \82ª\94j\8aü\82³\82ê\82½\82±\82Æ\82ð\93`\82¦\82é
1605         if Self.ParentBoard.IsBoardPlugInAvailable then
1606                 Self.ParentBoard.BoardPlugIn.DisposeThreadItem( DWORD( Self ) );
1607
1608         inherited;
1609
1610 end;
1611
1612 function TThreadItem.GetDatURL: string;
1613 var
1614         Protocol, Host, Path, Document, Port, Bookmark: string;
1615 begin
1616         Result := ParentBoard.URL
1617                                         + 'dat/'
1618                                         + FileName;
1619         if FDownloadHost <> '' then begin
1620                 GikoSys.ParseURI(Result, Protocol, Host, Path, Document, Port, Bookmark);
1621                 Result := Format('%s://%s%s%s', [Protocol,
1622                                                                                                                                                  FDownloadHost,
1623                                                                                                                                                  Path,
1624                                                                                                                                                  Document]);
1625         end;
1626 //      Result := GikoSys.UrlToServer(ParentBoard.URL)
1627 //                                      + 'test/read.cgi/' + ParentBoard.BBSID + '/'
1628 //                                      + ChangeFileExt(FileName, '') + '/?raw='
1629 //                                      + IntToStr(ResNum) + '.' + IntToStr(ResSize);
1630 end;
1631
1632 function TThreadItem.GetDatgzURL: string;
1633         function isOldKako(s: string): Boolean;
1634         begin
1635                 Result := False;
1636                 if AnsiPos('piza.', s) <> 0 then
1637                         Result := True
1638                 else if AnsiPos('www.bbspink.', s) <> 0 then
1639                         Result := True
1640                 else if AnsiPos('tako.', s) <> 0 then
1641                         Result := True;
1642         end;
1643 var
1644         Protocol, Host, Path, Document, Port, Bookmark: string;
1645         DatNo: string;
1646 begin
1647         if FDownloadHost = '' then begin
1648                 DatNo := ChangeFileExt(FileName, '');
1649                 if isOldKako(ParentBoard.URL) then begin
1650                         Result := Format('%s%s/%.3s/%s.dat', [ParentBoard.URL, 'kako', DatNo, DatNo]);
1651                 end else begin
1652                         if Length(DatNo) > 9 then begin
1653                                 //http://xxx.2ch.net/xxx/kako/9999/99999/999999999.dat.gz
1654                                 Result := Format('%s%s/%.4s/%.5s/%s.dat.gz', [ParentBoard.URL, 'kako', DatNo, DatNo, DatNo]);
1655                         end else begin
1656                                 //http://xxx.2ch.net/xxx/kako/999/999999999.dat.gz
1657                                 Result := Format('%s%s/%.3s/%s.dat.gz', [ParentBoard.URL, 'kako', DatNo, DatNo]);
1658                         end;
1659                 end;
1660         end else begin
1661                 Gikosys.ParseURI(Result, Protocol, Host, Path, Document, Port, Bookmark);
1662                 DatNo := ChangeFileExt(Document, '');
1663                 if isOldKako(DownloadHost) then begin
1664                         Result := Format('%s://%s/%s/kako/%.3s/%s.dat', [Protocol, DownloadHost, ParentBoard.FBBSID, DatNo, DatNo]);
1665                 end else begin
1666                         if Length(DatNo) > 9 then begin
1667                                 Result := Format('%s://%s/%s/kako/%.4s/%.5s/%s.dat.gz', [Protocol, DownloadHost, ParentBoard.FBBSID, DatNo, DatNo, DatNo]);
1668                         end else begin
1669                                 Result := Format('%s://%s/%s/kako/%.3s/%s.dat.gz', [Protocol, DownloadHost, ParentBoard.FBBSID, DatNo, DatNo]);
1670                         end;
1671                 end;
1672         end;
1673 end;
1674
1675 function TThreadItem.GetOfflawCgiURL(const SessionID: string): string;
1676 begin
1677         if FDownloadHost = '' then begin
1678                 Result := GikoSys.UrlToServer(ParentBoard.URL)
1679                                                 + 'test/offlaw.cgi/' + ParentBoard.BBSID + '/'
1680                                                 + ChangeFileExt(FileName, '') + '/?raw=.0&sid=' + HttpEncode(SessionID);
1681         end else begin
1682                 //http://news.2ch.net/test/offlaw.cgi/newsplus/1014038577/?raw=.196928&sid=
1683                 //GikoSys.ParseURI(Result, Protocol, Host, Path, Document, Port, Bookmark);
1684                 Result := 'http://' + FDownloadHost
1685                                                 + '/test/offlaw.cgi/' + ParentBoard.BBSID + '/'
1686                                                 + ChangeFileExt(FileName, '') + '/?raw=.0&sid=' + HttpEncode(SessionID);
1687         end;
1688 end;
1689
1690 function TThreadItem.GetSendURL: string;
1691 begin
1692         Result := GikoSys.UrlToServer(ParentBoard.URL)
1693                                         + 'test/bbs.cgi';
1694 end;
1695
1696 procedure TThreadItem.DeleteLogFile;
1697 var
1698         tmpFileName: String;
1699 begin
1700         ParentBoard.BeginUpdate;
1701
1702         if FUnRead then
1703                 ParentBoard.UnRead := ParentBoard.UnRead - 1;
1704         DeleteFile(GetThreadFileName);
1705         //\8e\8e\8c±\93I\82Étmp\82à\8dí\8f\9c\82µ\82Ä\82Ý\82é
1706         tmpFileName := StringReplace(GetThreadFileName, 'dat', 'tmp', [rfReplaceAll]);
1707         DeleteFile(tmpFileName);
1708
1709         if FileExists(ChangeFileExt(GetThreadFileName,'.NG')) = true then
1710                 DeleteFile(ChangeFileExt(GetThreadFileName,'.NG'));
1711         FRoundDate := ZERO_DATE;
1712         FLastModified := ZERO_DATE;
1713         FSize := 0;
1714         FIsLogFile := False;
1715         FKokomade := -1;
1716         FNewReceive := 0;
1717         FNewArrival := False;
1718         FUnRead := False;
1719         FScrollTop := 0;
1720         FRound := False;
1721         FDownloadHost := '';
1722         FAgeSage := gasNone;
1723
1724         FCount := 0;
1725         FNewResCount := 0;
1726         FRoundName := '';
1727
1728         ParentBoard.EndUpdate;
1729         ParentBoard.Modified := True;
1730 end;
1731
1732 function TThreadItem.GetThreadFileName: string;
1733 begin
1734         if Length( FilePath ) > 0 then
1735                 Result := FilePath
1736         else
1737                 Result := GikoSys.Setting.LogFolderP
1738                                                 + BBS2CH_LOG_FOLDER + PATH_DELIM + ParentBoard.BBSID + PATH_DELIM + FileName;
1739 end;
1740
1741 procedure TThreadItem.SetLastModified(d: TDateTime);
1742 begin
1743         if FLastModified = d then Exit;
1744         FLastModified := d;
1745         if FUpdate and (ParentBoard <> nil) then
1746                 ParentBoard.FModified := True;
1747 end;
1748
1749 procedure TThreadItem.SetRound(b: Boolean);
1750 begin
1751         if b then
1752                 RoundList.Add(Self)
1753         else
1754                 RoundList.Delete(Self);
1755         if FRound = b then Exit;
1756         FRound := b;
1757         if FUpdate and (ParentBoard <> nil) then
1758                 ParentBoard.FModified := True;
1759 end;
1760
1761 procedure TThreadItem.SetRoundName(const s: string);
1762 begin
1763         if FRoundName = s then Exit;
1764         FRoundName := s;
1765         if FUpdate and (ParentBoard <> nil) then
1766                 ParentBoard.FModified := True;
1767 end;
1768
1769
1770 procedure TThreadItem.SetKokomade(i: Integer);
1771 begin
1772         if FKokomade = i then Exit;
1773         FKokomade := i;
1774         if FUpdate and (ParentBoard <> nil) then
1775                 ParentBoard.FModified := True;
1776 end;
1777
1778 procedure TThreadItem.SetUnRead(b: Boolean);
1779 begin
1780         if FUnRead = b then Exit;
1781         FUnRead := b;
1782         if FUpdate and (ParentBoard <> nil) then begin
1783                 ParentBoard.FModified := True;
1784                 if FUnRead then begin
1785                         ParentBoard.UnRead := ParentBoard.UnRead + 1;
1786                 end else begin
1787             ParentBoard.UnRead := ParentBoard.UnRead - 1;
1788                 end;
1789         end;
1790 end;
1791
1792 procedure TThreadItem.SetScrollTop(i: Integer);
1793 begin
1794         if FScrollTop = i then Exit;
1795         FScrollTop := i;
1796         if FUpdate and (ParentBoard <> nil) then
1797                 ParentBoard.FModified := True;
1798 end;
1799
1800 procedure TThreadItem.BeginUpdate;
1801 begin
1802         FUpdate := False;
1803 end;
1804
1805 procedure TThreadItem.EndUpdate;
1806 begin
1807         FUpdate := True;
1808 end;
1809
1810 function TThreadItem.GetCreateDate: TDateTime;
1811 begin
1812         // \83t\83@\83C\83\8b\96¼\82©\82ç\83X\83\8c\8dì\90¬\93ú\8e\9e\82ð\8b\81\82ß\82é
1813         try
1814                 if ( GikoSys.Setting.CreationTimeLogs ) and not IsLogFile  then
1815             Result := ZERO_DATE
1816         else begin
1817             // \83\8d\83O\83t\83@\83C\83\8b\82Ì\8ag\92£\8eq\82ð\82Í\82¸\82µ\82½\82à\82Ì\82ª\83X\83\8c\8dì\90¬\93ú\8e\9e
1818             Result := GikoSys.GetCreateDateFromName(FFileName);
1819                         if GikoSys.Setting.FutureThread then begin
1820                         if CompareDateTime(Result, Now) = 1 then
1821                         Result := ZERO_DATE;
1822                 end;
1823         end;
1824
1825         except
1826                 on E: Exception do
1827                         Result := ZERO_DATE;
1828         end;
1829 end;
1830 function TThreadItem.GetFilePath: String;
1831 var
1832         path : String;
1833 begin
1834         path := ExtractFilePath(Self.ParentBoard.FilePath) + Self.FileName;
1835     Result := path;
1836 end;
1837
1838 destructor TBoardGroup.Destroy;
1839 begin
1840         Clear;
1841         inherited;
1842 end;
1843 procedure       TBoardGroup.Clear;
1844 var
1845         i       : Integer;
1846 begin
1847         for i := Self.Count - 1 downto 0 do begin
1848                 try
1849                         TBoard(Self.Objects[i]).Free;
1850                 except
1851                 end;
1852     end;
1853     inherited Clear;
1854         Self.Capacity := 0;
1855         try
1856                 if FBoardPlugIn <> nil then
1857                         FBoardPlugIn.Free;
1858         FBoardPlugIn := nil;
1859         except
1860         end;
1861
1862 end;
1863
1864 function TSpecialBoard.Add(item: TThreadItem): integer;
1865 begin
1866     Result := inherited AddObject(Item.URL, Item);
1867 end;
1868
1869 procedure TSpecialBoard.Clear;
1870 var
1871         i: integer;
1872 begin
1873     for i := Count - 1 downto 0 do
1874                 DeleteList(i);
1875     Capacity := 0;
1876 end;
1877
1878 end.
1879