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