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