OSDN Git Service

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