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