OSDN Git Service

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