OSDN Git Service

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