OSDN Git Service

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