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