OSDN Git Service

・今までコンストラクタを呼び出す側に URL の整形をさせていたが、
[gikonavigoeson/gikonavi.git] / BoardGroup.pas
1 unit BoardGroup;
2
3 interface
4
5 uses
6         Windows, SysUtils, Classes, ComCtrls, IniFiles, {HTTPApp,} YofUtils, IdGlobal,
7         ExternalBoardManager, ExternalBoardPlugInMain;
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Ì\8eæ\93¾\8c\8f\90\94
13         //TGikoListCount = (glc50, glc100, glc200, glc500, glc1000, glcAll);
14         //\8f\84\89ñ\94Ô\8d\86
15         //TGikoRoundNo = (grnNone, grn1, grn2, grn3, grn4, grn5, grnOnce);
16         //\83\8a\83X\83g\82Ì\8fã\82°\89º\82°
17         TGikoAgeSage = (gasNone, gasAge, gasSage, gasNew);
18
19 {       TFolder = class
20         private
21                 FItemList: TList;       //\8eq\83A\83C\83e\83\80\83\8a\83X\83g
22                 FLeaf: Boolean;         //\89º\82É\83t\83H\83\8b\83_\82ð\8e\9d\82Â\82±\82Æ\82ª\8fo\97\88\82é\82©
23         public
24                 function Add(Item: TFolder): Integer;
25                 procedure Clear;
26                 procedure Delete(Index: Integer);
27                 procedure Exchange(Index1, Index2: Integer);
28                 procedure Insert(Index: Integer; Item: TFolder);
29                 procedure Move(CurIndex, NewIndex: Integer);
30                 function Remove(Item: TFolder): Integer;
31                 procedure Sort(Compare: TListSortCompare);
32                 property Capacity: Integer read FCapacity write SetCapacity;
33                 property Count: Integer read FCount write SetCount;
34                 property Items[Index: Integer]: TFolder read Get write Put; default;
35
36                 property Leaf: Boolean read FLeaf;
37         end;
38
39         TBBS = class(TFolder)
40         end;
41         TCategory class(TFolder)
42         end;
43         TBoard = class(TFolder)
44         end;
45         TThreadItem = class(TFolder)
46         end;
47 }
48
49 {
50         TBBS = class(TBBS)
51         end;
52         TBoard2ch = class(TBoard)
53         end;
54         TThreadItem2ch = class(TThreadItem)
55         end;
56 }
57
58 //      ITest = interface
59 //      end;
60 //      IBBS = interface
61 //      end;
62 //      ICategory = interface
63 //      end;
64 //      IBoard = interface
65 //      end;
66 //      IThreadItem = interface
67 //      end;
68
69         TCategory = class;
70         TBoard = class;
71         TThreadItem = class;
72
73         //\82Æ\82è\82 \82¦\82¸\82Q\82¿\82á\82ñ\82Ë\82é\82Ì\83\8b\81[\83g
74         TBBS = class(TList)
75         private
76                 FTitle: string;
77                 FLogFolder: string;
78                 FExpand: Boolean;
79                 FKubetsuChk: Boolean;                                   //\8di\8d\9e\82Ý\8e\9e\91å\95\8e\9a\8f¬\95\8e\9a\8bæ\95Ê
80                 FSelectText: string;                                    //\8di\8d\9e\82Ý\95\8e\9a\97ñ
81                 FShortSelectText: string;
82
83                 function GetCategory(index: integer): TCategory;
84                 procedure SetCategory(index: integer; value: TCategory);
85                 procedure SetSelectText(s: string);
86         public
87                 constructor Create(LogFolder: string);
88                 destructor Destroy; override;
89
90                 function Add(item: TCategory): integer;
91                 procedure Delete(index: integer);
92                 procedure Clear; override;
93                 function Find(key: string): TCategory;
94                 function FindBBSID(BBSID: string): TBoard;
95                 function FindBoardFromTitle(Title: string): TBoard;
96                 function FindBoardFromURL(inURL: string): TBoard;
97                 function FindThreadFromURL( inURL : string ) : TThreadItem;
98                 function FindThreadItem(BBSID: string; FileName: string): TThreadItem;
99                 function FindCategoryFromTitle( inTitle : string ) : TCategory;
100                 function GetLogFolder: string;
101
102                 property Items[index: integer]: TCategory read GetCategory write SetCategory;
103                 property Title: string read FTitle write FTitle;
104                 property NodeExpand: Boolean read FExpand write FExpand;
105                                                                                  
106                 property KubetsuChk: Boolean read FKubetsuChk write FKubetsuChk;
107                 property SelectText: string read FSelectText write SetSelectText;
108                 property ShortSelectText: string read FShortSelectText write FShortSelectText;
109         end;
110
111         //\83J\83e\83S\83\8a
112         TCategory = class(TList)
113         private
114                 FNo: Integer;
115                 FTitle: string;
116                 FParenTBBS: TBBS;
117                 FExpand: Boolean;
118
119                 function GetBoard(index: integer): TBoard;
120                 procedure SetBoard(index: integer; value: TBoard);
121         public
122                 constructor Create;
123                 destructor Destroy; override;
124
125                 property No: Integer read FNo write FNo;
126                 property Title: string read FTitle write FTitle;
127                 property Items[index: integer]: TBoard read GetBoard write SetBoard;
128                 property ParenTBBS: TBBS read FParenTBBS write FParenTBBS;
129
130                 function Add(item: TBoard): integer;
131                 procedure Delete(index: integer);
132                 procedure Clear; override;
133                 function FindName(key: string): TBoard;
134                 function FindBBSID(BBSID: string): TBoard;
135                 function FindBoardFromTitle(Title: string): TBoard;
136                 function FindBoardFromURL(inURL: string): TBoard;
137                 function FindThreadFromURL( inURL : string ) : TThreadItem;
138                 function IsMidoku: Boolean;
139
140                 property NodeExpand: Boolean read FExpand write FExpand;
141         end;
142
143         //\94Â
144         TBoard = class(TList)
145         private
146                 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é)
147
148                 FNo: Integer;                                                                   //\94Ô\8d\86
149                 FTitle: string;                                                         //\83{\81[\83h\83^\83C\83g\83\8b
150                 FBBSID: string;                                                         //BBSID
151                 FURL: string;                                                                   //\83{\81[\83hURL
152                 FRound: Boolean;                                                        //\83X\83\8c\83b\83h\88ê\97\97\8f\84\89ñ\97\\96ñ
153                 FRoundName: string;                                             //\8f\84\89ñ\96¼
154                 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
155                 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
156                 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
157                 FIsThreadDatRead: Boolean;              //\83X\83\8c\83b\83h\83\8a\83X\83g\82Í\93Ç\82Ý\8d\9e\82Ü\82ê\82Ä\82¢\82é\82©\81H
158                 FUnRead: Integer;                                                       //\83X\83\8c\83b\83h\96¢\93Ç\90\94
159                 FParentCategory: TCategory;      //\90e\83J\83e\83S\83\8a
160                 FModified: Boolean;                                             //\8fC\90³\83t\83\89\83O
161                 FBoolData: Boolean;                                             //\82¢\82ë\82ñ\82È\97p\93r\82É\8eg\82¤yo
162                 FSPID: string;                                                          //\8f\91\82«\8d\9e\82Ý\97pSPID
163                 FPON: string;                                                                   //\8f\91\82«\8d\9e\82Ý\97pPON
164                 FKotehanName: string;                                   //\83R\83e\83n\83\93\96¼\91O
165                 FKotehanMail: string;                                   //\83R\83e\83n\83\93\83\81\81[\83\8b
166
167                 FUpdate: Boolean;
168                 FExpand: Boolean;
169
170                 FBoardPlugIn    : TBoardPlugIn; // \82±\82Ì\94Â\82ð\83T\83|\81[\83g\82·\82é\83v\83\89\83O\83C\83\93
171                 FFilePath                       : string;                               // \82±\82Ì\83X\83\8c\88ê\97\97\82ª\95Û\91\82³\82ê\82Ä\82¢\82é\83p\83X
172                 FIsLogFile              : Boolean;                      // \83\8d\83O\91\8dÝ\83t\83\89\83O
173                 FIntData                        : Integer;                      // \8dD\82«\82É\82¢\82\82Á\82Ä\82æ\82µ\81B\82¢\82ë\82ñ\82È\97p\93r\82É\8eg\82¤yo
174                 FListData                       : TList;                                // \8dD\82«\82É\82¢\82\82Á\82Ä\82æ\82µ\81B\82¢\82ë\82ñ\82È\97p\93r\82É\8eg\82¤yo
175
176                 function GetThreadItem(index: integer): TThreadItem;
177                 procedure SetThreadItem(index: integer; value: TThreadItem);
178                 procedure SetRound(b: Boolean);
179                 procedure SetRoundName(s: string);
180                 procedure SetLastModified(d: TDateTime);
181                 procedure SetLastGetTime(d: TDateTime);
182                 procedure SetUnRead(i: Integer);
183                 procedure SetKotehanName(s: string);
184                 procedure SetKotehanMail(s: string);
185                 procedure Init;
186         public
187                 constructor Create( inPlugIn : TBoardPlugIn; inURL : string );
188                 destructor Destroy; override;
189
190                 property Context: DWORD read FContext write FContext;
191
192                 property Items[index: integer]: TThreadItem read GetThreadItem write SetThreadItem;
193                 property No: Integer read FNo write FNo;
194                 property Title: string read FTitle write FTitle;
195                 property BBSID: string read FBBSID write FBBSID;
196                 property URL: string read FURL write FURL;
197                 property Round: Boolean read FRound write SetRound;
198                 property RoundName: string read FRoundName write SetRoundName;
199                 property RoundDate: TDateTime read FRoundDate write FRoundDate;
200                 property LastModified: TDateTime read FLastModified write SetLastModified;
201                 property LastGetTime: TDateTime read FLastGetTime write SetLastGetTime;
202                 property UnRead: Integer read FUnRead write SetUnRead;
203                 property Modified: Boolean read FModified write FModified;
204                 property IsThreadDatRead: Boolean read FIsThreadDatRead write FIsThreadDatRead;
205                 property ParentCategory: TCategory read FParentCategory write FParentCategory;
206
207                 property        BoardPlugIn     : TBoardPlugIn  read FBoardPlugIn;
208                 property        FilePath                : string                                read FFilePath write FFilePath;
209                 property        IsLogFile               : Boolean                               read FIsLogFile write FIsLogFile;
210                 property        IntData                 : Integer                               read FIntData write FIntData;
211                 property        ListData                : TList                                 read FListData write FListData;
212                 function        IsBoardPlugInAvailable : Boolean;
213
214                 function Add(item: TThreadItem): integer;
215                 procedure Insert(Index: Integer; Item: TThreadItem);
216                 procedure Delete(index: integer);
217                 procedure DeleteList(index: integer);
218                 procedure Clear; override;
219                 function Find(ItemFileName: string): TThreadItem;
220                 function FindThreadFromURL( inURL : string ) : TThreadItem;
221                 function GetIndex(ItemFileName: string): Integer;
222                 function GetIndexFromURL(URL: string): Integer;
223                 procedure LoadSettings;
224                 procedure SaveSettings;
225                 function GetReadCgiURL: string;
226                 function GetSubjectFileName: string;
227                 function GetFolderIndexFileName: string;
228                 function GetSendURL: string;
229
230                 function GetNewThreadCount: Integer;
231                 function GetLogThreadCount: Integer;
232                 function GetUserThreadCount: Integer;
233                 function GetNewThread(Index: Integer): TThreadItem;
234                 function GetLogThread(Index: Integer): TThreadItem;
235                 function GetUserThread(Index: Integer): TThreadItem;
236
237                 procedure BeginUpdate;
238                 procedure EndUpdate;
239                 property NodeExpand: Boolean read FExpand write FExpand;
240                 property BoolData: Boolean read FBoolData write FBoolData;
241                 property SPID: string read FSPID write FSPID;
242                 property PON: string read FPON write FPON;
243                 property KotehanName: string read FKotehanName write SetKotehanName;
244                 property KotehanMail: string read FKotehanMail write SetKotehanMail;
245         end;
246
247         //\83X\83\8c
248         TThreadItem = class(TObject)
249         private
250                 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é)
251
252                 FNo: Integer;                                                   //\94Ô\8d\86
253                 FFileName: string;                              //\83X\83\8c\83b\83h\83t\83@\83C\83\8b\96¼
254                 FTitle: string;                                         //\83X\83\8c\83b\83h\83^\83C\83g\83\8b
255                 FShortTitle: string;                    //\92Z\82¢\83X\83\8c\83b\83h\83^\83C\83g\83\8b\81i\8c\9f\8dõ\97p\81j
256                 FRoundDate: TDateTime;          //\83X\83\8c\83b\83h\82ð\8eæ\93¾\82µ\82½\93ú\8e\9e\81i\8f\84\89ñ\93ú\8e\9e\81j
257                 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
258                 FCount: Integer;                                        //\83X\83\8c\83b\83h\83J\83E\83\93\83g\81i\83\8d\81[\83J\83\8b\81j
259                 FAllResCount: Integer;          //\83X\83\8c\83b\83h\83J\83E\83\93\83g\81i\83T\81[\83o\81j
260                 FNewResCount: Integer;          //\83X\83\8c\83b\83h\90V\92\85\90\94
261                 FSize: Integer;                                         //\83X\83\8c\83b\83h\83T\83C\83Y
262                 FRound: Boolean;                                        //\8f\84\89ñ\83t\83\89\83O
263                 FRoundName: string;                             //\8f\84\89ñ\96¼
264                 FIsLogFile: Boolean;                    //\83\8d\83O\91\8dÝ\83t\83\89\83O
265                 FParentBoard: TBoard;                   //\90e\83{\81[\83h
266                 FKokomade: Integer;                             //\83R\83R\82Ü\82Å\93Ç\82ñ\82¾\94Ô\8d\86
267                 FNewReceive: Integer;           //\83R\83R\82©\82ç\90V\8bK\8eó\90M
268                 FNewArrival: Boolean;                   //\90V\92\85
269                 FUnRead: Boolean;                                       //\96¢\93Ç\83t\83\89\83O
270                 FScrollTop: Integer;                    //\83X\83N\83\8d\81[\83\8b\88Ê\92u
271                 FDownloadHost: string;          //\8d¡\82Ì\83z\83X\83g\82Æ\88á\82¤\8fê\8d\87\82Ì\83z\83X\83g
272                 FAgeSage: TGikoAgeSage;         //\83A\83C\83e\83\80\82Ì\8fã\82°\89º\82°
273 //              FSPID: string;                                          //\8f\91\82«\8d\9e\82Ý\97pSPID
274
275                 FUpdate: Boolean;
276                 FExpand: Boolean;
277                 FURL                                    : string;                               // \82±\82Ì\83X\83\8c\82ð\83u\83\89\83E\83U\82Å\95\\8e¦\82·\82é\8dÛ\82Ì URL
278                 FBoardPlugIn    : TBoardPlugIn; // \82±\82Ì\83X\83\8c\82ð\83T\83|\81[\83g\82·\82é\83v\83\89\83O\83C\83\93
279                 FFilePath                       : string;                               // \82±\82Ì\83X\83\8c\82ª\95Û\91\82³\82ê\82Ä\82¢\82é\83p\83X
280                 FSizeByte                       : Integer;                      // CreateHTML2 \82ð\8eÀ\8ds\82µ\82Ä\82¢\82é\8dÅ\92\86\82É\88ê\8e\9e\93I\82É\95Û\91\82³\82ê\82é\92l
281
282                 procedure SetLastModified(d: TDateTime);
283                 procedure SetRound(b: Boolean);
284                 procedure SetRoundName(s: string);
285                 procedure SetKokomade(i: Integer);
286                 procedure SetUnRead(b: Boolean);
287                 procedure SetScrollTop(i: Integer);
288                 procedure Init;
289         public
290                 constructor Create( inPlugIn : TBoardPlugIn; inURL : string );
291                 destructor Destroy; override;
292
293                 function GetDatURL: string;
294                 function GetDatgzURL: string;
295 //              function GetOldDatgzURL: string;
296                 function GetOfflawCgiURL(SessionID: string): string;
297                 function GetSendURL: string;
298                 procedure DeleteLogFile;
299                 function GetThreadFileName: string;
300                 procedure BeginUpdate;
301                 procedure EndUpdate;
302
303                 property Context: DWORD read FContext write FContext;
304
305                 property No: Integer read FNo write FNo;
306                 property FileName: string read FFileName write FFileName;
307                 property Title: string read FTitle write FTitle;
308                 property ShortTitle: string read FShortTitle write FShortTitle;
309                 property RoundDate: TDateTime read FRoundDate write FRoundDate;
310                 property LastModified: TDateTime read FLastModified write SetLastModified;
311                 property Count: Integer read FCount write FCount;
312                 property AllResCount: Integer read FAllResCount write FAllResCount;
313                 property NewResCount: Integer read FNewResCount write FNewResCount;
314                 property Size: Integer read FSize write FSize;
315                 property Round: Boolean read FRound write SetRound;
316                 property RoundName: string read FRoundName write SetRoundName;
317
318                 property IsLogFile: Boolean read FIsLogFile write FIsLogFile;
319                 property ParentBoard: TBoard read FParentBoard write FParentBoard;
320                 property Kokomade: Integer read FKokomade write SetKokomade;
321                 property NewReceive: Integer read FNewReceive write FNewReceive;
322                 property NewArrival: Boolean read FNewArrival write FNewArrival;
323                 property UnRead: Boolean read FUnRead write SetUnRead;
324                 property ScrollTop: Integer read FScrollTop write SetScrollTop;
325                 property Expand: Boolean read FExpand write FExpand;
326                 property DownloadHost: string read FDownloadHost write FDownloadHost;
327                 property AgeSage: TGikoAgeSage read FAgeSage write FAgeSage;
328 //              property SPID: string read FSPID write FSPID;
329
330                 property        URL                                     : string                                read FURL write FURL;
331                 property        BoardPlugIn     : TBoardPlugIn  read FBoardPlugIn;
332                 property        FilePath                : string                                read FFilePath write FFilePath;
333                 property        SizeByte                : Integer                               read FSizeByte write FSizeByte;
334                 function        IsBoardPlugInAvailable : Boolean;
335         end;
336
337
338
339         //\8c\9f\8dõ\8c\8b\89Ê\83\8a\83X\83g
340 {       TSearchList = class(TList)
341         private
342                 function GetThreadItem(index: integer): TThreadItem;
343                 procedure SetThreadItem(index: integer; value: TThreadItem);
344         public
345                 constructor Create;
346                 destructor Destroy; override;
347
348                 property Items[index: integer]: TThreadItem read GetThreadItem write SetThreadItem;
349
350                 function Add(item: TThreadItem): integer;
351                 procedure Delete(index: integer);
352                 procedure Clear; override;
353         end;}
354
355         function        BBSsFindBoardFromBBSID( inBBSID : string ) : TBoard;
356         function        BBSsFindBoardFromURL( inURL : string ) : TBoard;
357         function        BBSsFindBoardFromTitle( inTitle : string ) : TBoard;
358         function        BBSsFindThreadFromURL( inURL : string ) : TThreadItem;
359
360 var
361         BBSs            : array of TBBS;
362
363 implementation
364
365 uses
366         GikoSystem, RoundData;
367
368 const
369         BBS2CH_NAME:                                     string = '\82Q\82¿\82á\82ñ\82Ë\82é';
370         BBS2CH_LOG_FOLDER:               string = '2ch';
371         EXTERNAL_LOG_FOLDER:            string  = 'exboard';
372
373         FOLDER_INI_FILENAME:     string = 'Folder.ini';
374         FOLDER_INDEX_FILENAME: string   = 'Folder.idx';
375         SUBJECT_FILENAME:                       string  = 'subject.txt';
376         PATH_DELIM:                                             string  = '\';
377         //DEFAULT_LIST_COUNT:           Integer = 100;
378
379 //      COLUMN_CATEGORY:         array[0..0] of string = ('\83J\83e\83S\83\8a\96¼');
380 //      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');
381 //      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');
382
383 function        BBSsFindBoardFromBBSID(
384         inBBSID : string
385 ) : TBoard;
386 var
387         i                               : Integer;
388 begin
389
390         for i := Length( BBSs ) - 1 downto 0 do begin
391                 Result := BBSs[ i ].FindBBSID( inBBSID );
392                 if Result <> nil then
393                         Exit;
394         end;
395
396         Result := nil;
397
398 end;
399
400 function        BBSsFindBoardFromURL(
401         inURL   : string
402 ) : TBoard;
403 var
404         i                       : Integer;
405 begin
406
407         for i := Length( BBSs ) - 1 downto 0 do begin
408                 Result := BBSs[ i ].FindBoardFromURL( inURL );
409                 if Result <> nil then
410                         Exit;
411         end;
412
413         Result := nil;
414
415 end;
416
417 function        BBSsFindBoardFromTitle(
418         inTitle : string
419 ) : TBoard;
420 var
421         i                               : Integer;
422 begin
423
424         for i := Length( BBSs ) - 1 downto 0 do begin
425                 Result := BBSs[ i ].FindBoardFromTitle( inTitle );
426                 if Result <> nil then
427                         Exit;
428         end;
429
430         Result := nil;
431
432 end;
433
434 function        BBSsFindThreadFromURL(
435         inURL                   : string
436 ) : TThreadItem;
437 var
438         board                   : TBoard;
439         boardURL        : string;
440 begin
441
442         boardURL        := GikoSys.GetThreadURL2BoardURL( inURL );
443         board                   := BBSsFindBoardFromURL( boardURL );
444         if board = nil then
445                 Result := nil
446         else
447                 Result := board.FindThreadFromURL( inURL );
448
449 end;
450
451 (*************************************************************************
452  *\8b@\94\\96¼\81FTBBS\83R\83\93\83X\83g\83\89\83N\83^
453  *Public
454  *************************************************************************)
455 constructor TBBS.Create(LogFolder: string);
456 begin
457         inherited Create;
458         Title := BBS2CH_NAME;
459         FLogFolder := LogFolder;
460 end;
461
462 (*************************************************************************
463  *\8b@\94\\96¼\81FTBBS\83f\83X\83g\83\89\83N\83^
464  *Public
465  *************************************************************************)
466 destructor TBBS.Destroy;
467 begin
468         Clear;
469         inherited;
470 end;
471
472 (*************************************************************************
473  *\8b@\94\\96¼\81F
474  *Public
475  *************************************************************************)
476 function TBBS.GetCategory(index: integer): TCategory;
477 begin
478         Result := TCategory(inherited Items[index]);
479 end;
480
481 procedure TBBS.SetCategory(index: integer; value: TCategory);
482 begin
483         inherited Items[index] := value;
484 end;
485
486 function TBBS.Add(item: TCategory): integer;
487 begin
488         Item.ParenTBBS := self;
489         Result := inherited Add(item);
490 end;
491
492 procedure TBBS.Delete(index: integer);
493 begin
494         if Items[index] <> nil then
495                 TCategory(Items[index]).Free;
496         Items[index] := nil;
497         inherited Delete(index);
498 end;
499
500 procedure TBBS.Clear;
501 var
502         i: integer;
503 begin
504         for i := Count - 1 downto 0 do
505                 Delete(i);
506 end;
507
508 function TBBS.Find(key: string): TCategory;
509 begin
510         Result := nil;
511 end;
512
513 function TBBS.FindBBSID(BBSID: string): TBoard;
514 var
515         i       : Integer;
516 begin
517         for i := Count - 1 downto 0 do begin
518                 Result := Items[ i ].FindBBSID(BBSID);
519                 if Result <> nil then
520                         Exit;
521         end;
522         Result := nil;
523 end;
524
525 //*************************************************************************
526 // \83^\83C\83g\83\8b\82Ì\88ê\92v\82·\82é\94Â\82ð\92T\82·
527 //*************************************************************************)
528 function TBBS.FindBoardFromTitle(Title: string): TBoard;
529 var
530         i: Integer;
531 begin
532         for i := Count - 1 downto 0 do begin
533                 Result := Items[ i ].FindBoardFromTitle(Title);
534                 if Result <> nil then
535                         Exit;
536         end;
537         Result := nil;
538 end;
539
540 //*************************************************************************
541 // URL \82ð\8eó\82¯\95t\82¯\82é\94Â\82ð\92T\82·
542 //*************************************************************************)
543 function TBBS.FindBoardFromURL(inURL: string): TBoard;
544 var
545         i                                       : Integer;
546 begin
547         for i := Count - 1 downto 0 do begin
548                 Result := Items[ i ].FindBoardFromURL( inURL );
549                 if Result <> nil then
550                         Exit;
551         end;
552         Result := nil;
553 end;
554
555 //*************************************************************************
556 // URL \82ð\8eó\82¯\95t\82¯\82é\83X\83\8c\83b\83h\82ð\92T\82·
557 //*************************************************************************)
558 function TBBS.FindThreadFromURL(inURL: string): TThreadItem;
559 var
560         board                   : TBoard;
561         boardURL        : string;
562 begin
563
564         boardURL        := GikoSys.GetThreadURL2BoardURL( inURL );
565         board                   := FindBoardFromURL( boardURL );
566         if board = nil then
567                 Result := nil
568         else
569                 Result := board.FindThreadFromURL( inURL );
570
571 end;
572
573 function TBBS.FindThreadItem(BBSID: string; FileName: string): TThreadItem;
574 var
575         Board: TBoard;
576 begin
577         Result := nil;
578         Board := FindBBSID(BBSID);
579         if Board = nil then
580                 Exit;
581         Result := Board.Find(FileName);
582 end;
583
584 function TBBS.FindCategoryFromTitle( inTitle : string ) : TCategory;
585 var
586         i : Integer;
587 begin
588
589         for i := Count - 1 downto 0 do begin
590                 if Items[ i ].Title = inTitle then begin
591                         Result := Items[ i ];
592                         Exit;
593                 end;
594         end;
595
596         Result := nil;
597
598 end;
599
600 (*************************************************************************
601  *\83\8d\83O\83t\83H\83\8b\83_\8eæ\93¾
602  *
603  *************************************************************************)
604 function TBBS.GetLogFolder: string;
605 begin
606         Result := IncludeTrailingPathDelimiter(FLogFolder)
607                                         + BBS2CH_LOG_FOLDER + PATH_DELIM;
608 end;
609
610 procedure TBBS.SetSelectText(s: string);
611 begin
612         FSelectText := s;
613         ShortSelectText := GikoSys.ZenToHan(s);
614 end;
615
616 {class function TBBS.GetColumnName(Index: Integer): string;
617 begin
618         Result := COLUMN_CATEGORY[Index];
619 end;
620
621 class function TBBS.GetColumnCount: Integer;
622 begin
623         Result := Length(COLUMN_CATEGORY);
624 end;}
625
626 //===================
627 //TCategory
628 //===================
629 constructor TCategory.Create;
630 begin
631         inherited;
632 end;
633
634 destructor TCategory.Destroy;
635 begin
636         Clear;
637         inherited;
638 end;
639
640 function TCategory.GetBoard(index: integer): TBoard;
641 begin
642         Result := TBoard(inherited Items[index]);
643 end;
644
645 procedure TCategory.SetBoard(index: integer; value: TBoard);
646 begin
647         inherited Items[index] := value;
648 end;
649
650 function TCategory.Add(item: TBoard): integer;
651 begin
652         Item.ParentCategory := self;
653         Result := inherited Add(item);
654 end;
655
656 procedure TCategory.Delete(index: integer);
657 begin
658         if Items[index] <> nil then
659                 TBoard(Items[index]).Free;
660         Items[index] := nil;
661         inherited Delete(index);
662 end;
663
664 procedure TCategory.Clear;
665 var
666         i: integer;
667 begin
668         for i := Count - 1 downto 0 do
669                 Delete(i);
670 end;
671
672 function TCategory.FindName(key: string): TBoard;
673 begin
674         Result := nil;
675 end;
676
677 function TCategory.FindBBSID(BBSID: string): TBoard;
678 var
679         i       : integer;
680 begin
681         for i := Count - 1 downto 0 do begin
682                 if Items[i].FBBSID = BBSID then begin
683                         Result := Items[i];
684                         Exit;
685                 end;
686         end;
687         Result := nil;
688 end;
689
690 //*************************************************************************
691 // \83^\83C\83g\83\8b\82Ì\88ê\92v\82·\82é\94Â\82ð\92T\82·
692 //*************************************************************************)
693 function TCategory.FindBoardFromTitle(Title: string): TBoard;
694 var
695         i       : integer;
696 begin
697         for i := Count - 1 downto 0 do begin
698                 if Items[i].FTitle = Title then begin
699                         Result := Items[i];
700                         Exit;
701                 end;
702         end;
703         Result := nil;
704 end;
705
706 //*************************************************************************
707 // URL \82ð\8eó\82¯\95t\82¯\82é\94Â\82ð\92T\82·
708 //*************************************************************************)
709 function TCategory.FindBoardFromURL(inURL: string): TBoard;
710 var
711         i       : Integer;
712 begin
713         for i := Count - 1 downto 0 do begin
714                 if Pos( Items[i].URL, inURL ) = 1 then begin
715                         Result := Items[i];
716                         Exit;
717                 end;
718         end;
719         Result := nil;
720 end;
721
722 //*************************************************************************
723 // URL \82ð\8eó\82¯\95t\82¯\82é\83X\83\8c\83b\83h\82ð\92T\82·
724 //*************************************************************************)
725 function TCategory.FindThreadFromURL(inURL: string): TThreadItem;
726 var
727         board                   : TBoard;
728         boardURL        : string;
729 begin
730
731         boardURL        := GikoSys.GetThreadURL2BoardURL( inURL );
732         board                   := FindBoardFromURL( boardURL );
733         if board = nil then
734                 Result := nil
735         else
736                 Result := board.FindThreadFromURL( inURL );
737
738 end;
739
740 function TCategory.IsMidoku: Boolean;
741 var
742         i: Integer;
743         j: Integer;
744 begin
745         Result := False;
746         for i := 0 to Count - 1 do begin
747                 if Items[i] <> nil then begin
748                         for j := 0 to Items[i].Count - 1 do begin
749                                 if Items[i].Items[j] <> nil then begin
750 //                                      if (Items[i].Items[j].IsLogFile) and (Items[i].Items[j].Count > Items[i].Items[j].Kokomade) then begin
751                                         if (Items[i].Items[j].IsLogFile) and (Items[i].Items[j].UnRead) then begin
752                                                 Result := True;
753                                                 Exit;
754                                         end;
755                                 end;
756                         end;
757                 end;
758         end;
759 end;
760
761 {class function TCategory.GetColumnName(Index: Integer): string;
762 begin
763         Result := COLUMN_BOARD[Index];
764 end;
765
766 class function TCategory.GetColumnCount: Integer;
767 begin
768         Result := Length(COLUMN_BOARD);
769 end;}
770
771 //===================
772 //TBoard
773 //===================
774 procedure TBoard.Init;
775 begin
776         FNo := 0;
777         FTitle := '';
778         FBBSID := '';
779         FURL := '';
780         FRound := False;
781         FRoundDate := ZERO_DATE;
782         FLastModified := ZERO_DATE;
783         FLastGetTime := ZERO_DATE;
784         FIsThreadDatRead := False;
785         FUnRead := 0;
786 //      FListStyle := vsReport;
787 //      FItemNoVisible := True;
788
789         FUpdate := True;
790 end;
791
792 // *************************************************************************
793 // \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^
794 // *************************************************************************
795 constructor TBoard.Create(
796         inPlugIn        : TBoardPlugIn;
797         inURL                   : string
798 );
799 var
800         protocol, host, path, document, port, bookmark  : string;
801 begin
802
803         inherited Create;
804         Init;
805
806         FBoardPlugIn    := inPlugIn;
807         URL                                             := inURL;
808         BBSID                                   := GikoSys.UrlToID( inURL );
809
810         if inPlugIn = nil then begin
811                 // subject.txt \82Ì\95Û\91\83p\83X\82ð\90Ý\92è
812                 GikoSys.ParseURI( inURL, protocol, host, path, document, port, bookmark );
813                 if GikoSys.Is2chHost( host ) then
814                         FilePath :=
815                                 IncludeTrailingPathDelimiter( GikoSys.Setting.LogFolder ) +
816                                 BBS2CH_LOG_FOLDER + PATH_DELIM + BBSID + PATH_DELIM + SUBJECT_FILENAME
817                 else
818                         FilePath :=
819                                 IncludeTrailingPathDelimiter( GikoSys.Setting.LogFolder ) +
820                                 EXTERNAL_LOG_FOLDER + PATH_DELIM + host + PATH_DELIM + BBSID + PATH_DELIM + SUBJECT_FILENAME
821         end else begin
822                 // \83v\83\89\83O\83C\83\93\82É TBoardItem \82ª\8dì\90¬\82³\82ê\82½\82±\82Æ\82ð\93`\82¦\82é
823                 inPlugIn.CreateBoardItem( DWORD( Self ) );
824         end;
825
826 end;
827
828 // *************************************************************************
829 // \83f\83X\83g\83\89\83N\83^
830 // *************************************************************************
831 destructor TBoard.Destroy;
832 begin
833         if FModified then begin
834                 GikoSys.WriteThreadDat(Self);
835                 SaveSettings;
836         end;
837
838         // \83v\83\89\83O\83C\83\93\82É TBoardItem \82ª\94j\8aü\82³\82ê\82½\82±\82Æ\82ð\93`\82¦\82é
839         if IsBoardPlugInAvailable then
840                 BoardPlugIn.DisposeBoardItem( DWORD( Self ) );
841
842         Clear;
843         inherited;
844 end;
845
846 // *************************************************************************
847 // \8aO\95\94\94Â\83v\83\89\83O\83C\83\93\82ª\8eg\97p\89Â\94\\82©
848 // *************************************************************************
849 function        TBoard.IsBoardPlugInAvailable : Boolean;
850 begin
851
852         repeat
853                 if BoardPlugIn = nil then
854                         Break;
855                         
856                 if not Assigned( Pointer( BoardPlugIn.Module ) ) then
857                         Break;
858
859                 Result := True;
860                 Exit;
861         until True;
862
863         Result := False;
864
865 end;
866
867 function TBoard.GetThreadItem(index: integer): TThreadItem;
868 begin
869         Result := TThreadItem(inherited Items[index]);
870 end;
871
872 procedure TBoard.SetThreadItem(index: integer; value: TThreadItem);
873 begin
874         inherited Items[index] := value;
875 end;
876
877 function TBoard.Add(Item: TThreadItem): Integer;
878 begin
879         Item.ParentBoard := Self;
880         Result := inherited Add(Item);
881 end;
882
883 procedure TBoard.Insert(Index: Integer; Item: TThreadItem);
884 begin
885         Item.ParentBoard := Self;
886         inherited Insert(Index, Item);
887 end;
888
889 //Index\82Å\8ew\92è\82³\82ê\82½\83X\83\8c\83b\83h\83I\83u\83W\83F\83N\83g\82ð\94j\8aü
890 procedure TBoard.Delete(index: Integer);
891 begin
892         if Items[index] <> nil then
893                 TThreadItem(Items[index]).Free;
894         Items[index] := nil;
895         inherited Delete(index);
896 end;
897
898 //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
899 procedure TBoard.DeleteList(index: integer);
900 begin
901         inherited Delete(index);
902 end;
903
904 procedure TBoard.Clear;
905 var
906         i: integer;
907 begin
908 //      FUnRead := 0;
909         for i := Count - 1 downto 0 do
910                 Delete(i);
911 end;
912
913 function TBoard.Find(ItemFileName: string): TThreadItem;
914 var
915         i: integer;
916 begin
917         Result := nil;
918         for i := 0 to Count - 1 do begin
919                 if Items[i].FileName = ItemFileName then begin
920                         Result := Items[i];
921                         Exit;
922                 end;
923         end;
924 end;
925
926 function TBoard.GetIndex(ItemFileName: string): Integer;
927 var
928         i: integer;
929 begin
930         Result := -1;
931         for i := 0 to Count - 1 do begin
932                 if Items[i].FileName = ItemFileName then begin
933                         Result := i;
934                         Exit;
935                 end;
936         end;
937 end;
938
939 function TBoard.GetIndexFromURL(URL: string): Integer;
940 var
941         i: integer;
942 begin
943         Result := -1;
944         for i := 0 to Count - 1 do begin
945                 if Pos( URL, Items[ i ].URL ) = 1 then begin
946                         Result := i;
947                         Exit;
948                 end;
949         end;
950 end;
951
952 function TBoard.FindThreadFromURL( inURL : string ) : TThreadItem;
953 var
954         i : Integer;
955 begin
956
957         if not IsThreadDatRead then
958                 GikoSys.ReadSubjectFile( Self );
959                 
960         for i := Count - 1 downto 0 do begin
961                 if Pos( inURL, Items[ i ].URL ) = 1 then begin
962                         Result := Items[ i ];
963                         Exit;
964                 end;
965         end;
966         Result := nil;
967
968 end;
969
970 {function TBoard.GetMidokuCount: Integer;
971 var
972         i: integer;
973 begin
974         Result := 0;
975         for i := 0 to Count- 1 do begin
976                 if Items[i] <> nil then begin
977                         if (Items[i].IsLogFile) and (Items[i].Count > Items[i].Kokomade) then
978                                 inc(Result);
979                 end;
980         end;
981 end;
982 }
983
984 procedure TBoard.LoadSettings;
985 var
986         ini: TMemIniFile;
987         FileName: string;
988 begin
989         if Length( FilePath ) > 0 then
990                 FileName := ExtractFilePath( FilePath ) + FOLDER_INI_FILENAME
991         else
992                 FileName := ParentCategory.ParenTBBS.GetLogFolder
993                                                         + BBSID + PATH_DELIM + FOLDER_INI_FILENAME;
994
995         if not FileExists(FileName) then
996                 Exit;
997         ini := TMemIniFile.Create(FileName);
998         try
999 //              Round := ini.ReadBool('Status', 'Round', False);
1000                 FRoundDate := ini.ReadDateTime('Status', 'RoundDate', ZERO_DATE);
1001                 FLastModified := ini.ReadDateTime('Status', 'LastModified', ZERO_DATE);
1002                 FLastGetTime := ini.ReadDateTime('Status', 'LastGetTime', ZERO_DATE);
1003                 FUnRead := ini.ReadInteger('Status', 'UnRead', 0);
1004                 FSPID := ini.ReadString('Cookie', 'SPID', '');
1005                 FPON := ini.ReadString('Cookie', 'PON', '');
1006                 FKotehanName := ini.ReadString('Kotehan', 'Name', '');
1007                 FKotehanMail := ini.ReadString('Kotehan', 'Mail', '');
1008 //              ListStyle := TViewStyle(Ord(ini.ReadInteger('Status', 'ListStyle', 3)));
1009 //              ItemNoVisible := ini.ReadBool('Status', 'ItemNoVisible', True);
1010 //              ViewType := TGikoViewType(Ord(ini.ReadInteger('Status', 'ViewType', 0)));
1011                 if UnRead < 0 then
1012                         UnRead := 0;
1013         finally
1014                 ini.Free;
1015         end;
1016 end;
1017
1018 procedure TBoard.SaveSettings;
1019 var
1020         ini: TMemIniFile;
1021         FileName: string;
1022 begin
1023         if Length( FilePath ) > 0 then
1024                 FileName := ExtractFilePath( FilePath )
1025         else
1026                 FileName := ParentCategory.ParenTBBS.GetLogFolder
1027                                                         + BBSID + PATH_DELIM;
1028         if not GikoSys.DirectoryExistsEx(FileName) then
1029                 GikoSys.ForceDirectoriesEx(FileName);
1030         FileName := FileName + FOLDER_INI_FILENAME;
1031         ini := TMemIniFile.Create(FileName);
1032         try
1033                 if UnRead < 0 then
1034                         UnRead := 0;
1035 //              ini.WriteBool('Status', 'Round', Round);
1036                 ini.WriteDateTime('Status', 'RoundDate', FRoundDate);
1037                 ini.WriteDateTime('Status', 'LastModified', FLastModified);
1038                 ini.WriteDateTime('Status', 'LastGetTime', FLastGetTime);
1039                 ini.WriteInteger('Status', 'UnRead', FUnRead);
1040                 ini.WriteString('Cookie', 'SPID', FSPID);
1041                 ini.WriteString('Cookie', 'PON', FPON);
1042                 ini.WriteString('Kotehan', 'Name', FKotehanName);
1043                 ini.WriteString('Kotehan', 'Mail', FKotehanMail);
1044 //              ini.WriteInteger('Status', 'ListStyle', Ord(ListStyle));
1045 //              ini.WriteBool('Status', 'ItemNoVisible', ItemNoVisible);
1046 //              ini.WriteInteger('Status', 'ViewType', Ord(ViewType));
1047                 ini.UpdateFile;
1048         finally
1049                 ini.Free;
1050         end;
1051 end;
1052
1053 // \83T\83u\83W\83F\83N\83gURL\8eæ\93¾
1054 function TBoard.GetReadCgiURL: string;
1055 begin
1056         //Result := URL + SUBJECT_FILENAME;
1057         //Result := GikoSys.UrlToServer(URL)
1058         //                              + 'test/read.cgi/' + BBSID + '/?raw=0.0';
1059         Result := URL + SUBJECT_FILENAME;
1060
1061 end;
1062
1063 // \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
1064 function TBoard.GetSubjectFileName: string;
1065 begin
1066         if Length( FilePath ) > 0 then
1067                 Result := FilePath
1068         else
1069                 Result := ParentCategory.ParenTBBS.GetLogFolder
1070                                                 + BBSID + PATH_DELIM + SUBJECT_FILENAME;
1071 end;
1072
1073 // \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
1074 function TBoard.GetFolderIndexFileName: string;
1075 begin
1076         if Length( FilePath ) > 0 then
1077                 Result := ExtractFilePath( FilePath ) + FOLDER_INDEX_FILENAME
1078         else
1079                 Result := ParentCategory.ParenTBBS.GetLogFolder
1080                                                 + BBSID + PATH_DELIM + FOLDER_INDEX_FILENAME;
1081 end;
1082
1083 // \83X\83\8c\97§\82Ä\91\97\90MURL
1084 function TBoard.GetSendURL: string;
1085 begin
1086         Result := GikoSys.UrlToServer(URL) + 'test/subbbs.cgi';
1087 end;
1088
1089 procedure TBoard.SetRound(b: Boolean);
1090 begin
1091         if b then
1092                 RoundList.Add(Self)
1093         else
1094                 RoundList.Delete(Self);
1095         if FRound = b then Exit;
1096         FRound := b;
1097         if FUpdate then
1098                 FModified := True;
1099 end;
1100
1101 procedure TBoard.SetRoundName(s: string);
1102 begin
1103         if FRoundName = s then Exit;
1104         FRoundName := s;
1105         if FUpdate then
1106                 FModified := True;
1107 end;
1108
1109 procedure TBoard.SetLastModified(d: TDateTime);
1110 begin
1111         if FLastModified = d then Exit;
1112         FLastModified := d;
1113         if FUpdate then
1114                 FModified := True;
1115 end;
1116
1117 procedure TBoard.SetLastGetTime(d: TDateTime);
1118 begin
1119         if FLastGetTime = d then Exit;
1120         FLastGetTime := d;
1121         if FUpdate then
1122                 FModified := True;
1123 end;
1124
1125 procedure TBoard.SetUnRead(i: Integer);
1126 begin
1127         if FUnRead = i then Exit;
1128         if i < 0 then i := 0;
1129         FUnRead := i;
1130         if FUpdate then
1131                 FModified := True;
1132 end;
1133
1134 procedure TBoard.SetKotehanName(s: string);
1135 begin
1136         if FKotehanName = s then Exit;
1137         FKotehanName := s;
1138         if FUpdate then
1139                 FModified := True;
1140 end;
1141
1142 procedure TBoard.SetKotehanMail(s: string);
1143 begin
1144         if FKotehanMail = s then Exit;
1145         FKotehanMail := s;
1146         if FUpdate then
1147                 FModified := True;
1148 end;
1149
1150 function TBoard.GetNewThreadCount: Integer;
1151 var
1152         i: Integer;
1153 begin
1154         Result := 0;
1155         if Length( ParentCategory.ParenTBBS.ShortSelectText ) = 0 then
1156         begin
1157                 for i := 0 to Count - 1 do begin
1158                         if Items[i].NewArrival then
1159                                 inc(Result);
1160                 end;
1161         end else begin
1162                 for i := 0 to Count - 1 do begin
1163                         if Items[i].NewArrival then
1164                         begin
1165                                 if Items[i].ShortTitle = '' then
1166                                         Items[i].ShortTitle := GikoSys.ZenToHan(Items[i].Title);
1167                                 if AnsiPos(ParentCategory.ParenTBBS.ShortSelectText, Items[i].ShortTitle) <> 0 then
1168                                         inc(Result);
1169                         end;
1170                 end;
1171         end;
1172 end;
1173
1174 function TBoard.GetLogThreadCount: Integer;
1175 var
1176         i: Integer;
1177 begin
1178         Result := 0;
1179         if Length( ParentCategory.ParenTBBS.ShortSelectText ) = 0 then
1180         begin
1181                 for i := 0 to Count - 1 do begin
1182                         if Items[i].IsLogFile then
1183                                 inc(Result);
1184                 end;
1185         end else begin
1186                 for i := 0 to Count - 1 do begin
1187                         if Items[i].IsLogFile then
1188                         begin
1189                                 if Items[i].ShortTitle = '' then
1190                                         Items[i].ShortTitle := GikoSys.ZenToHan(Items[i].Title);
1191                                 if AnsiPos(ParentCategory.ParenTBBS.ShortSelectText, Items[i].ShortTitle) <> 0 then
1192                                         inc(Result);
1193                         end;
1194                 end;
1195         end;
1196 end;
1197
1198 function TBoard.GetUserThreadCount: Integer;
1199 var
1200         i: Integer;
1201 begin
1202         Result := 0;
1203         if Length( ParentCategory.ParenTBBS.ShortSelectText ) = 0 then
1204                 Result := Count
1205         else
1206                 for i := 0 to Count - 1 do begin
1207                         if Items[i].ShortTitle = '' then
1208                                 Items[i].ShortTitle := GikoSys.ZenToHan(Items[i].Title);
1209                         if AnsiPos(ParentCategory.ParenTBBS.ShortSelectText, Items[i].ShortTitle) <> 0 then
1210                                 inc(Result);
1211                 end;
1212 end;
1213
1214 function TBoard.GetNewThread(Index: Integer): TThreadItem;
1215 var
1216         i: Integer;
1217         Cnt: Integer;
1218 begin
1219         Result := nil;
1220         Cnt := 0;
1221         if Length( ParentCategory.ParenTBBS.ShortSelectText ) = 0 then
1222         begin
1223                 for i := 0 to Count - 1 do begin
1224                         if Items[i].NewArrival then
1225                                                                         begin
1226                                 if Index = Cnt then begin
1227                                         Result := Items[i];
1228                                         Exit;
1229                                 end;
1230                                 inc(Cnt);
1231                         end;
1232                 end;
1233         end else begin
1234                 for i := 0 to Count - 1 do begin
1235                         if Items[i].NewArrival then
1236                         begin
1237                                 if Items[i].ShortTitle = '' then
1238                                         Items[i].ShortTitle := GikoSys.ZenToHan(Items[i].Title);
1239                                 if AnsiPos(ParentCategory.ParenTBBS.ShortSelectText, Items[i].ShortTitle) <> 0 then begin
1240                                         if Index = Cnt then begin
1241                                                 Result := Items[i];
1242                                                 Exit;
1243                                         end;
1244                                         inc(Cnt);
1245                                 end;
1246                         end;
1247                 end;
1248         end;
1249 end;
1250
1251 function TBoard.GetLogThread(Index: Integer): TThreadItem;
1252 var
1253         i: Integer;
1254         Cnt: Integer;
1255 begin
1256         Cnt := 0;
1257         if Length( ParentCategory.ParenTBBS.ShortSelectText ) = 0 then
1258         begin
1259                 for i := 0 to Count - 1 do begin
1260                         if Items[i].IsLogFile then
1261                                                                         begin
1262                                 if Index = Cnt then begin
1263                                         Result := Items[i];
1264                                         Exit;
1265                                 end;
1266                                 inc(Cnt);
1267                         end;
1268                 end;
1269         end else begin
1270                 for i := 0 to Count - 1 do begin
1271                         if Items[i].IsLogFile then
1272                                 begin
1273                                         if Items[i].ShortTitle = '' then
1274                                                 Items[i].ShortTitle := GikoSys.ZenToHan(Items[i].Title);
1275                                         if AnsiPos(ParentCategory.ParenTBBS.ShortSelectText, Items[i].ShortTitle) <> 0 then begin
1276                                                 if Index = Cnt then begin
1277                                                         Result := Items[i];
1278                                                         Exit;
1279                                         end;
1280                                         inc(Cnt);
1281                                 end;
1282                         end;
1283                 end;
1284         end;
1285         Result := nil;
1286 end;
1287
1288 function TBoard.GetUserThread(Index: Integer): TThreadItem;
1289 var
1290         i: Integer;
1291         Cnt: Integer;
1292 begin
1293         Result := nil;
1294         Cnt := 0;
1295         if Length( ParentCategory.ParenTBBS.ShortSelectText ) = 0 then
1296         begin
1297                 for i := 0 to Count - 1 do begin
1298                         if Index = Cnt then
1299                         begin
1300                                 Result := Items[ i ];
1301                                 Exit;
1302                         end;
1303                         inc( Cnt );
1304                 end;
1305         end else begin
1306                 for i := 0 to Count - 1 do begin
1307                         if Items[i].ShortTitle = '' then
1308                                 Items[i].ShortTitle := GikoSys.ZenToHan(Items[i].Title);
1309                         if AnsiPos(ParentCategory.ParenTBBS.ShortSelectText, Items[i].ShortTitle) <> 0 then begin
1310                                 if Index = Cnt then begin
1311                                         Result := Items[i];
1312                                         Exit;
1313                                 end;
1314                                 inc(Cnt);
1315                         end;
1316                 end;
1317         end;
1318 end;
1319
1320 procedure TBoard.BeginUpdate;
1321 begin
1322         FUpdate := False;
1323 end;
1324
1325 procedure TBoard.EndUpdate;
1326 begin
1327         FUpdate := True;
1328 end;
1329
1330 {class function TBoard.GetColumnName(Index: Integer): string;
1331 begin
1332         Result := COLUMN_THREADITEM[Index];
1333 end;
1334
1335 class function TBoard.GetColumnCount: Integer;
1336 begin
1337         Result := Length(COLUMN_THREADITEM);
1338 end;}
1339
1340 //constructor TThreadItem.Create(AOwner: TComponent);
1341 procedure TThreadItem.Init;
1342 begin
1343         FNo := 0;
1344         FFileName := '';
1345         FTitle := '';
1346         FRoundDate := ZERO_DATE;
1347         FLastModified := ZERO_DATE;
1348         FCount := 0;
1349         FAllResCount := 0;
1350         FNewResCount := 0;
1351         FSize := 0;
1352         FRound := False;
1353         FIsLogFile := False;
1354         FParentBoard := nil;
1355         FKokomade := -1;
1356         FNewReceive := 0;
1357         FNewArrival := False;
1358
1359         FUpdate := True;
1360         FURL := '';
1361         FBoardPlugIn := nil;
1362 end;
1363
1364 // *************************************************************************
1365 // \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^
1366 // *************************************************************************
1367 constructor TThreadItem.Create(
1368         inPlugIn        : TBoardPlugIn;
1369         inURL                   : string
1370 );
1371 var
1372         foundPos                        : Integer;
1373         protocol, host, path, document, port, bookmark  : string;
1374         BBSID, BBSKey   : string;
1375 const
1376         READ_PATH                                                       = '/test/read.cgi';
1377 begin
1378
1379         inherited Create;
1380         Init;
1381
1382         FBoardPlugIn    := inPlugIn;
1383         URL                                             := inURL;
1384
1385         if inPlugIn = nil then begin
1386                 foundPos := Pos( READ_PATH, inURL );
1387                 if foundPos > 0 then begin
1388                         // dat \82Ì\95Û\91\83p\83X\82ð\90Ý\92è
1389                         GikoSys.ParseURI( inURL, protocol, host, path, document, port, bookmark );
1390                         GikoSys.Parse2chURL( inURL, path, document, BBSID, BBSKey );
1391                         if GikoSys.Is2chHost( host ) then
1392                                 FilePath :=
1393                                         IncludeTrailingPathDelimiter( GikoSys.Setting.LogFolder ) +
1394                                         BBS2CH_LOG_FOLDER + PATH_DELIM + BBSID + PATH_DELIM + BBSKey + '.dat'
1395                         else
1396                                 FilePath :=
1397                                         IncludeTrailingPathDelimiter( GikoSys.Setting.LogFolder ) +
1398                                         EXTERNAL_LOG_FOLDER + PATH_DELIM + host + PATH_DELIM + BBSID + PATH_DELIM + BBSKey + '.dat';
1399                         FileName        := BBSKey + '.dat';
1400                         IsLogFile       := FileExists( FilePath );
1401                         URL                             := GikoSys.Get2chBrowsableThreadURL( inURL );
1402                 end;
1403         end else begin
1404                 // \83v\83\89\83O\83C\83\93\82É TThreadItem \82ª\8dì\90¬\82³\82ê\82½\82±\82Æ\82ð\93`\82¦\82é
1405                 inPlugIn.CreateThreadItem( DWORD( Self ) );
1406         end;
1407
1408 end;
1409
1410 // *************************************************************************
1411 // \83f\83X\83g\83\89\83N\83^
1412 // *************************************************************************
1413 destructor TThreadItem.Destroy;
1414 begin
1415
1416         // \83v\83\89\83O\83C\83\93\82É TThreadItem \82ª\94j\8aü\82³\82ê\82½\82±\82Æ\82ð\93`\82¦\82é
1417         if IsBoardPlugInAvailable then
1418                 FBoardPlugIn.DisposeThreadItem( DWORD( Self ) );
1419
1420         inherited;
1421
1422 end;
1423
1424 // *************************************************************************
1425 // \8aO\95\94\94Â\83v\83\89\83O\83C\83\93\82ª\8eg\97p\89Â\94\\82©
1426 // *************************************************************************
1427 function        TThreadItem.IsBoardPlugInAvailable : Boolean;
1428 begin
1429
1430         repeat
1431                 if BoardPlugIn = nil then
1432                         Break;
1433
1434                 if not Assigned( Pointer( BoardPlugIn.Module ) ) then
1435                         Break;
1436
1437                 Result := True;
1438                 Exit;
1439         until True;
1440
1441         Result := False;
1442
1443 end;
1444
1445 function TThreadItem.GetDatURL: string;
1446 var
1447         Protocol, Host, Path, Document, Port, Bookmark: string;
1448 begin
1449         Result := ParentBoard.URL
1450                                         + 'dat/'
1451                                         + FileName;
1452         if FDownloadHost <> '' then begin
1453                 GikoSys.ParseURI(Result, Protocol, Host, Path, Document, Port, Bookmark);
1454                 Result := Format('%s://%s%s%s', [Protocol,
1455                                                                                                                                                  FDownloadHost,
1456                                                                                                                                                  Path,
1457                                                                                                                                                  Document]);
1458         end;
1459 //      Result := GikoSys.UrlToServer(ParentBoard.URL)
1460 //                                      + 'test/read.cgi/' + ParentBoard.BBSID + '/'
1461 //                                      + ChangeFileExt(FileName, '') + '/?raw='
1462 //                                      + IntToStr(ResNum) + '.' + IntToStr(ResSize);
1463 end;
1464
1465 function TThreadItem.GetDatgzURL: string;
1466         function isOldKako(s: string): Boolean;
1467         begin
1468                 Result := False;
1469                 if AnsiPos('piza.', s) <> 0 then
1470                         Result := True
1471                 else if AnsiPos('www.bbspink.', s) <> 0 then
1472                         Result := True
1473                 else if AnsiPos('tako.', s) <> 0 then
1474                         Result := True;
1475         end;
1476 var
1477         Protocol, Host, Path, Document, Port, Bookmark: string;
1478         DatNo: string;
1479 begin
1480         if FDownloadHost = '' then begin
1481                 DatNo := ChangeFileExt(FileName, '');
1482                 if isOldKako(ParentBoard.URL) then begin
1483                         Result := Format('%s%s/%.3s/%s.dat', [ParentBoard.URL, 'kako', DatNo, DatNo]);
1484                 end else begin
1485                         if Length(DatNo) > 9 then begin
1486                                 //http://xxx.2ch.net/xxx/kako/9999/99999/999999999.dat.gz
1487                                 Result := Format('%s%s/%.4s/%.5s/%s.dat.gz', [ParentBoard.URL, 'kako', DatNo, DatNo, DatNo]);
1488                         end else begin
1489                                 //http://xxx.2ch.net/xxx/kako/999/999999999.dat.gz
1490                                 Result := Format('%s%s/%.3s/%s.dat.gz', [ParentBoard.URL, 'kako', DatNo, DatNo]);
1491                         end;
1492                 end;
1493         end else begin
1494                 Gikosys.ParseURI(Result, Protocol, Host, Path, Document, Port, Bookmark);
1495                 DatNo := ChangeFileExt(Document, '');
1496                 if isOldKako(DownloadHost) then begin
1497                         Result := Format('%s://%s/%s/kako/%.3s/%s.dat', [Protocol, DownloadHost, ParentBoard.FBBSID, DatNo, DatNo]);
1498                 end else begin
1499                         if Length(DatNo) > 9 then begin
1500                                 Result := Format('%s://%s/%s/kako/%.4s/%.5s/%s.dat.gz', [Protocol, DownloadHost, ParentBoard.FBBSID, DatNo, DatNo, DatNo]);
1501                         end else begin
1502                                 Result := Format('%s://%s/%s/kako/%.3s/%s.dat.gz', [Protocol, DownloadHost, ParentBoard.FBBSID, DatNo, DatNo]);
1503                         end;
1504                 end;
1505         end;
1506 end;
1507
1508 {function TThreadItem.GetOldDatgzURL: string;
1509 var
1510         Protocol, Host, Path, Document, Port, Bookmark: string;
1511 begin
1512         Result := Format('%s%s/%.3s/%s.gz', [ParentBoard.URL,
1513                                                                                                                                                          'kako',
1514                                                                                                                                                          FileName,
1515                                                                                                                                                          FileName]);
1516         if FDownloadHost <> '' then begin
1517                 ParseURI(Result, Protocol, Host, Path, Document, Port, Bookmark);
1518                 Result := Format('%s://%s%s%s', [Protocol,
1519                                                                                                                                                  DownloadHost,
1520                                                                                                                                                  Path,
1521                                                                                                                                                  Document]);
1522
1523         end;
1524 end;}
1525
1526 function TThreadItem.GetOfflawCgiURL(SessionID: string): string;
1527 //var
1528 //      Protocol, Host, Path, Document, Port, Bookmark: string;
1529 begin
1530 //      Result := GikoSys.UrlToServer(ParentBoard.URL)
1531 //                                      + 'test/offlaw.cgi/' + ParentBoard.BBSID + '/'
1532 //                                      + ChangeFileExt(FileName, '') + '/?raw=.0&sid=' + HttpEncode(SessionID);
1533         if FDownloadHost = '' then begin
1534                 Result := GikoSys.UrlToServer(ParentBoard.URL)
1535                                                 + 'test/offlaw.cgi/' + ParentBoard.BBSID + '/'
1536                                                 + ChangeFileExt(FileName, '') + '/?raw=.0&sid=' + HttpEncode(SessionID);
1537         end else begin
1538                 //http://news.2ch.net/test/offlaw.cgi/newsplus/1014038577/?raw=.196928&sid=
1539                 //GikoSys.ParseURI(Result, Protocol, Host, Path, Document, Port, Bookmark);
1540                 Result := 'http://' + FDownloadHost
1541                                                 + '/test/offlaw.cgi/' + ParentBoard.BBSID + '/'
1542                                                 + ChangeFileExt(FileName, '') + '/?raw=.0&sid=' + HttpEncode(SessionID);
1543 //              Result := Format('%s://%s%s%s', [Protocol,
1544 //                                                                                                                                               DownloadHost,
1545 //                                                                                                                                               Path,
1546 //                                                                                                                                               Document]);
1547         end;
1548 end;
1549
1550 function TThreadItem.GetSendURL: string;
1551 begin
1552         Result := GikoSys.UrlToServer(ParentBoard.URL)
1553                                         + 'test/bbs.cgi';
1554 end;
1555
1556 procedure TThreadItem.DeleteLogFile;
1557 begin
1558         DeleteFile(GetThreadFileName);
1559                 if FileExists(ChangeFileExt(GetThreadFileName,'.NG')) = true then
1560                         DeleteFile(ChangeFileExt(GetThreadFileName,'.NG'));
1561         FRoundDate := ZERO_DATE;
1562         FLastModified := ZERO_DATE;
1563         FSize := 0;
1564         FIsLogFile := False;
1565         FKokomade := -1;
1566         FNewReceive := 0;
1567         FNewArrival := False;
1568         FUnRead := False;
1569         FScrollTop := 0;
1570         FRound := False;
1571         FDownloadHost := '';
1572         FAgeSage := gasNone;
1573
1574         FCount := 0;
1575         FNewResCount := 0;
1576         FRoundName := '';
1577 end;
1578
1579 function TThreadItem.GetThreadFileName: string;
1580 begin
1581         if Length( FilePath ) > 0 then
1582                 Result := FilePath
1583         else
1584                 Result := ParentBoard.ParentCategory.ParenTBBS.GetLogFolder
1585                                                 + ParentBoard.BBSID + PATH_DELIM + FileName;
1586 end;
1587
1588 procedure TThreadItem.SetLastModified(d: TDateTime);
1589 begin
1590         if FLastModified = d then Exit;
1591         FLastModified := d;
1592         if FUpdate and (ParentBoard <> nil) then
1593                 ParentBoard.FModified := True;
1594 end;
1595
1596 {procedure TThreadItem.SetRoundNo(i: Integer);
1597 begin
1598         if FRoundNo = i then Exit;
1599         FRoundNo := i;
1600         if FUpdate and (ParentBoard <> nil) then
1601                 ParentBoard.FModified := True;
1602 end;}
1603
1604 procedure TThreadItem.SetRound(b: Boolean);
1605 begin
1606         if b then
1607                 RoundList.Add(Self)
1608         else
1609                 RoundList.Delete(Self);
1610         if FRound = b then Exit;
1611         FRound := b;
1612         if FUpdate and (ParentBoard <> nil) then
1613                 ParentBoard.FModified := True;
1614 end;
1615
1616 procedure TThreadItem.SetRoundName(s: string);
1617 begin
1618         if FRoundName = s then Exit;
1619         FRoundName := s;
1620         if FUpdate and (ParentBoard <> nil) then
1621                 ParentBoard.FModified := True;
1622 end;
1623
1624 procedure TThreadItem.SetKokomade(i: Integer);
1625 begin
1626         if FKokomade = i then Exit;
1627         FKokomade := i;
1628         if FUpdate and (ParentBoard <> nil) then
1629                 ParentBoard.FModified := True;
1630 end;
1631
1632 procedure TThreadItem.SetUnRead(b: Boolean);
1633 begin
1634         if FUnRead = b then Exit;
1635         FUnRead := b;
1636         if FUpdate and (ParentBoard <> nil) then
1637                 ParentBoard.FModified := True;
1638 end;
1639
1640 procedure TThreadItem.SetScrollTop(i: Integer);
1641 begin
1642         if FScrollTop = i then Exit;
1643         FScrollTop := i;
1644         if FUpdate and (ParentBoard <> nil) then
1645                 ParentBoard.FModified := True;
1646 end;
1647
1648 procedure TThreadItem.BeginUpdate;
1649 begin
1650         FUpdate := False;
1651 end;
1652
1653 procedure TThreadItem.EndUpdate;
1654 begin
1655         FUpdate := True;
1656 end;
1657
1658 {initialization
1659         BBS2ch := TBBS.Create;
1660
1661 finalization
1662         if BBS2ch <> nil then
1663                 BBS2ch.Free;}
1664 end.
1665