OSDN Git Service

・不要なものや紛らわしい記述を排除。
[gikonavigoeson/gikonavi.git] / BoardGroup.pas
1 unit BoardGroup;
2
3 interface
4
5 uses
6         Windows, SysUtils, Classes, ComCtrls, IniFiles, {HTTPApp,} YofUtils, IdGlobal,
7         ExternalBoardManager, ExternalBoardPlugInMain;
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 Init;
185         public
186                 constructor Create( inPlugIn : TBoardPlugIn; inURL : string );
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 Init;
288         public
289                 constructor Create( inPlugIn : TBoardPlugIn; inURL : string );
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         board                   : TBoard;
438         boardURL        : string;
439 begin
440
441         boardURL        := GikoSys.GetThreadURL2BoardURL( inURL );
442         board                   := BBSsFindBoardFromURL( boardURL );
443         if board = nil then
444                 Result := nil
445         else
446                 Result := board.FindThreadFromURL( inURL );
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         inherited Create;
457         Title := BBS2CH_NAME;
458         FLogFolder := LogFolder;
459 end;
460
461 (*************************************************************************
462  *\8b@\94\\96¼\81FTBBS\83f\83X\83g\83\89\83N\83^
463  *Public
464  *************************************************************************)
465 destructor TBBS.Destroy;
466 begin
467         Clear;
468         inherited;
469 end;
470
471 (*************************************************************************
472  *\8b@\94\\96¼\81F
473  *Public
474  *************************************************************************)
475 function TBBS.GetCategory(index: integer): TCategory;
476 begin
477         Result := TCategory(inherited Items[index]);
478 end;
479
480 procedure TBBS.SetCategory(index: integer; value: TCategory);
481 begin
482         inherited Items[index] := value;
483 end;
484
485 function TBBS.Add(item: TCategory): integer;
486 begin
487         Item.ParenTBBS := self;
488         Result := inherited Add(item);
489 end;
490
491 procedure TBBS.Delete(index: integer);
492 begin
493         if Items[index] <> nil then
494                 TCategory(Items[index]).Free;
495         Items[index] := nil;
496         inherited Delete(index);
497 end;
498
499 procedure TBBS.Clear;
500 var
501         i: integer;
502 begin
503         for i := Count - 1 downto 0 do
504                 Delete(i);
505 end;
506
507 function TBBS.Find(key: string): TCategory;
508 begin
509         Result := nil;
510 end;
511
512 function TBBS.FindBBSID(BBSID: string): TBoard;
513 var
514         i       : Integer;
515 begin
516         for i := Count - 1 downto 0 do begin
517                 Result := Items[ i ].FindBBSID(BBSID);
518                 if Result <> nil then
519                         Exit;
520         end;
521         Result := nil;
522 end;
523
524 //*************************************************************************
525 // \83^\83C\83g\83\8b\82Ì\88ê\92v\82·\82é\94Â\82ð\92T\82·
526 //*************************************************************************)
527 function TBBS.FindBoardFromTitle(Title: string): TBoard;
528 var
529         i: Integer;
530 begin
531         for i := Count - 1 downto 0 do begin
532                 Result := Items[ i ].FindBoardFromTitle(Title);
533                 if Result <> nil then
534                         Exit;
535         end;
536         Result := nil;
537 end;
538
539 //*************************************************************************
540 // URL \82ð\8eó\82¯\95t\82¯\82é\94Â\82ð\92T\82·
541 //*************************************************************************)
542 function TBBS.FindBoardFromURL(inURL: string): TBoard;
543 var
544         i                                       : Integer;
545 begin
546         for i := Count - 1 downto 0 do begin
547                 Result := Items[ i ].FindBoardFromURL( inURL );
548                 if Result <> nil then
549                         Exit;
550         end;
551         Result := nil;
552 end;
553
554 //*************************************************************************
555 // URL \82ð\8eó\82¯\95t\82¯\82é\83X\83\8c\83b\83h\82ð\92T\82·
556 //*************************************************************************)
557 function TBBS.FindThreadFromURL(inURL: string): TThreadItem;
558 var
559         board                   : TBoard;
560         boardURL        : string;
561 begin
562
563         boardURL        := GikoSys.GetThreadURL2BoardURL( inURL );
564         board                   := FindBoardFromURL( boardURL );
565         if board = nil then
566                 Result := nil
567         else
568                 Result := board.FindThreadFromURL( inURL );
569
570 end;
571
572 function TBBS.FindThreadItem(BBSID: string; FileName: string): TThreadItem;
573 var
574         Board: TBoard;
575 begin
576         Result := nil;
577         Board := FindBBSID(BBSID);
578         if Board = nil then
579                 Exit;
580         Result := Board.Find(FileName);
581 end;
582
583 (*************************************************************************
584  *\83\8d\83O\83t\83H\83\8b\83_\8eæ\93¾
585  *
586  *************************************************************************)
587 function TBBS.GetLogFolder: string;
588 begin
589         Result := IncludeTrailingPathDelimiter(FLogFolder)
590                                         + BBS2CH_LOG_FOLDER + PATH_DELIM;
591 end;
592
593 procedure TBBS.SetSelectText(s: string);
594 begin
595         FSelectText := s;
596         ShortSelectText := GikoSys.ZenToHan(s);
597 end;
598
599 {class function TBBS.GetColumnName(Index: Integer): string;
600 begin
601         Result := COLUMN_CATEGORY[Index];
602 end;
603
604 class function TBBS.GetColumnCount: Integer;
605 begin
606         Result := Length(COLUMN_CATEGORY);
607 end;}
608
609 //===================
610 //TCategory
611 //===================
612 constructor TCategory.Create;
613 begin
614         inherited;
615 end;
616
617 destructor TCategory.Destroy;
618 begin
619         Clear;
620         inherited;
621 end;
622
623 function TCategory.GetBoard(index: integer): TBoard;
624 begin
625         Result := TBoard(inherited Items[index]);
626 end;
627
628 procedure TCategory.SetBoard(index: integer; value: TBoard);
629 begin
630         inherited Items[index] := value;
631 end;
632
633 function TCategory.Add(item: TBoard): integer;
634 begin
635         Item.ParentCategory := self;
636         Result := inherited Add(item);
637 end;
638
639 procedure TCategory.Delete(index: integer);
640 begin
641         if Items[index] <> nil then
642                 TBoard(Items[index]).Free;
643         Items[index] := nil;
644         inherited Delete(index);
645 end;
646
647 procedure TCategory.Clear;
648 var
649         i: integer;
650 begin
651         for i := Count - 1 downto 0 do
652                 Delete(i);
653 end;
654
655 function TCategory.FindName(key: string): TBoard;
656 begin
657         Result := nil;
658 end;
659
660 function TCategory.FindBBSID(BBSID: string): TBoard;
661 var
662         i       : integer;
663 begin
664         for i := Count - 1 downto 0 do begin
665                 if Items[i].FBBSID = BBSID then begin
666                         Result := Items[i];
667                         Exit;
668                 end;
669         end;
670         Result := nil;
671 end;
672
673 //*************************************************************************
674 // \83^\83C\83g\83\8b\82Ì\88ê\92v\82·\82é\94Â\82ð\92T\82·
675 //*************************************************************************)
676 function TCategory.FindBoardFromTitle(Title: string): TBoard;
677 var
678         i       : integer;
679 begin
680         for i := Count - 1 downto 0 do begin
681                 if Items[i].FTitle = Title then begin
682                         Result := Items[i];
683                         Exit;
684                 end;
685         end;
686         Result := nil;
687 end;
688
689 //*************************************************************************
690 // URL \82ð\8eó\82¯\95t\82¯\82é\94Â\82ð\92T\82·
691 //*************************************************************************)
692 function TCategory.FindBoardFromURL(inURL: string): TBoard;
693 var
694         i       : Integer;
695 begin
696         for i := Count - 1 downto 0 do begin
697                 if Pos( Items[i].URL, inURL ) = 1 then begin
698                         Result := Items[i];
699                         Exit;
700                 end;
701         end;
702         Result := nil;
703 end;
704
705 //*************************************************************************
706 // URL \82ð\8eó\82¯\95t\82¯\82é\83X\83\8c\83b\83h\82ð\92T\82·
707 //*************************************************************************)
708 function TCategory.FindThreadFromURL(inURL: string): TThreadItem;
709 var
710         board                   : TBoard;
711         boardURL        : string;
712 begin
713
714         boardURL        := GikoSys.GetThreadURL2BoardURL( inURL );
715         board                   := FindBoardFromURL( boardURL );
716         if board = nil then
717                 Result := nil
718         else
719                 Result := board.FindThreadFromURL( inURL );
720
721 end;
722
723 function TCategory.IsMidoku: Boolean;
724 var
725         i: Integer;
726         j: Integer;
727 begin
728         Result := False;
729         for i := 0 to Count - 1 do begin
730                 if Items[i] <> nil then begin
731                         for j := 0 to Items[i].Count - 1 do begin
732                                 if Items[i].Items[j] <> nil then begin
733 //                                      if (Items[i].Items[j].IsLogFile) and (Items[i].Items[j].Count > Items[i].Items[j].Kokomade) then begin
734                                         if (Items[i].Items[j].IsLogFile) and (Items[i].Items[j].UnRead) then begin
735                                                 Result := True;
736                                                 Exit;
737                                         end;
738                                 end;
739                         end;
740                 end;
741         end;
742 end;
743
744 {class function TCategory.GetColumnName(Index: Integer): string;
745 begin
746         Result := COLUMN_BOARD[Index];
747 end;
748
749 class function TCategory.GetColumnCount: Integer;
750 begin
751         Result := Length(COLUMN_BOARD);
752 end;}
753
754 //===================
755 //TBoard
756 //===================
757 procedure TBoard.Init;
758 begin
759         FNo := 0;
760         FTitle := '';
761         FBBSID := '';
762         FURL := '';
763         FRound := False;
764         FRoundDate := ZERO_DATE;
765         FLastModified := ZERO_DATE;
766         FLastGetTime := ZERO_DATE;
767         FIsThreadDatRead := False;
768         FUnRead := 0;
769 //      FListStyle := vsReport;
770 //      FItemNoVisible := True;
771
772         FUpdate := True;
773 end;
774
775 // *************************************************************************
776 // \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^
777 // *************************************************************************
778 constructor TBoard.Create(
779         inPlugIn        : TBoardPlugIn;
780         inURL                   : string
781 );
782 var
783         protocol, host, path, document, port, bookmark  : string;
784         BBSID                   : string;
785 begin
786
787         inherited Create;
788         Init;
789
790         FBoardPlugIn    := inPlugIn;
791         URL                                             := inURL;
792         BBSID                                   := GikoSys.UrlToID( inURL );
793
794         if inPlugIn = nil then begin
795                 // subject.txt \82Ì\95Û\91\83p\83X\82ð\90Ý\92è
796                 GikoSys.ParseURI( inURL, protocol, host, path, document, port, bookmark );
797                 if GikoSys.Is2chHost( host ) then
798                         FilePath :=
799                                 IncludeTrailingPathDelimiter( GikoSys.Setting.LogFolder ) +
800                                 BBS2CH_LOG_FOLDER + PATH_DELIM + BBSID + PATH_DELIM + SUBJECT_FILENAME
801                 else
802                         FilePath :=
803                                 IncludeTrailingPathDelimiter( GikoSys.Setting.LogFolder ) +
804                                 EXTERNAL_LOG_FOLDER + PATH_DELIM + host + PATH_DELIM + BBSID + PATH_DELIM + SUBJECT_FILENAME
805         end else begin
806                 // \83v\83\89\83O\83C\83\93\82É TBoardItem \82ª\8dì\90¬\82³\82ê\82½\82±\82Æ\82ð\93`\82¦\82é
807                 inPlugIn.CreateBoardItem( DWORD( Self ) );
808         end;
809
810 end;
811
812 // *************************************************************************
813 // \83f\83X\83g\83\89\83N\83^
814 // *************************************************************************
815 destructor TBoard.Destroy;
816 begin
817         if FModified then begin
818                 GikoSys.WriteThreadDat(Self);
819                 SaveSettings;
820         end;
821
822         // \83v\83\89\83O\83C\83\93\82É TBoardItem \82ª\94j\8aü\82³\82ê\82½\82±\82Æ\82ð\93`\82¦\82é
823         if IsBoardPlugInAvailable then
824                 BoardPlugIn.DisposeBoardItem( DWORD( Self ) );
825
826         Clear;
827         inherited;
828 end;
829
830 // *************************************************************************
831 // \8aO\95\94\94Â\83v\83\89\83O\83C\83\93\82ª\8eg\97p\89Â\94\\82©
832 // *************************************************************************
833 function        TBoard.IsBoardPlugInAvailable : Boolean;
834 begin
835
836         repeat
837                 if BoardPlugIn = nil then
838                         Break;
839                         
840                 if not Assigned( Pointer( BoardPlugIn.Module ) ) then
841                         Break;
842
843                 Result := True;
844                 Exit;
845         until True;
846
847         Result := False;
848
849 end;
850
851 function TBoard.GetThreadItem(index: integer): TThreadItem;
852 begin
853         Result := TThreadItem(inherited Items[index]);
854 end;
855
856 procedure TBoard.SetThreadItem(index: integer; value: TThreadItem);
857 begin
858         inherited Items[index] := value;
859 end;
860
861 function TBoard.Add(Item: TThreadItem): Integer;
862 begin
863         Item.ParentBoard := Self;
864         Result := inherited Add(Item);
865 end;
866
867 procedure TBoard.Insert(Index: Integer; Item: TThreadItem);
868 begin
869         Item.ParentBoard := Self;
870         inherited Insert(Index, Item);
871 end;
872
873 //Index\82Å\8ew\92è\82³\82ê\82½\83X\83\8c\83b\83h\83I\83u\83W\83F\83N\83g\82ð\94j\8aü
874 procedure TBoard.Delete(index: Integer);
875 begin
876         if Items[index] <> nil then
877                 TThreadItem(Items[index]).Free;
878         Items[index] := nil;
879         inherited Delete(index);
880 end;
881
882 //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
883 procedure TBoard.DeleteList(index: integer);
884 begin
885         inherited Delete(index);
886 end;
887
888 procedure TBoard.Clear;
889 var
890         i: integer;
891 begin
892 //      FUnRead := 0;
893         for i := Count - 1 downto 0 do
894                 Delete(i);
895 end;
896
897 function TBoard.Find(ItemFileName: string): TThreadItem;
898 var
899         i: integer;
900 begin
901         Result := nil;
902         for i := 0 to Count - 1 do begin
903                 if Items[i].FileName = ItemFileName then begin
904                         Result := Items[i];
905                         Exit;
906                 end;
907         end;
908 end;
909
910 function TBoard.GetIndex(ItemFileName: string): Integer;
911 var
912         i: integer;
913 begin
914         Result := -1;
915         for i := 0 to Count - 1 do begin
916                 if Items[i].FileName = ItemFileName then begin
917                         Result := i;
918                         Exit;
919                 end;
920         end;
921 end;
922
923 function TBoard.GetIndexFromURL(URL: string): Integer;
924 var
925         i: integer;
926 begin
927         Result := -1;
928         for i := 0 to Count - 1 do begin
929                 if Items[i].URL = URL then begin
930                         Result := i;
931                         Exit;
932                 end;
933         end;
934 end;
935
936 function TBoard.FindThreadFromURL( inURL : string ) : TThreadItem;
937 var
938         i : Integer;
939 begin
940
941         if not IsThreadDatRead then
942                 GikoSys.ReadSubjectFile( Self );
943                 
944         for i := Count - 1 downto 0 do begin
945                 if Pos( Items[ i ].URL, inURL ) = 1 then begin
946                         Result := Items[ i ];
947                         Exit;
948                 end;
949         end;
950         Result := nil;
951
952 end;
953
954 {function TBoard.GetMidokuCount: Integer;
955 var
956         i: integer;
957 begin
958         Result := 0;
959         for i := 0 to Count- 1 do begin
960                 if Items[i] <> nil then begin
961                         if (Items[i].IsLogFile) and (Items[i].Count > Items[i].Kokomade) then
962                                 inc(Result);
963                 end;
964         end;
965 end;
966 }
967
968 procedure TBoard.LoadSettings;
969 var
970         ini: TMemIniFile;
971         FileName: string;
972 begin
973         if Length( FilePath ) > 0 then
974                 FileName := ExtractFilePath( FilePath ) + FOLDER_INI_FILENAME
975         else
976                 FileName := ParentCategory.ParenTBBS.GetLogFolder
977                                                         + BBSID + PATH_DELIM + FOLDER_INI_FILENAME;
978
979         if not FileExists(FileName) then
980                 Exit;
981         ini := TMemIniFile.Create(FileName);
982         try
983 //              Round := ini.ReadBool('Status', 'Round', False);
984                 FRoundDate := ini.ReadDateTime('Status', 'RoundDate', ZERO_DATE);
985                 FLastModified := ini.ReadDateTime('Status', 'LastModified', ZERO_DATE);
986                 FLastGetTime := ini.ReadDateTime('Status', 'LastGetTime', ZERO_DATE);
987                 FUnRead := ini.ReadInteger('Status', 'UnRead', 0);
988                 FSPID := ini.ReadString('Cookie', 'SPID', '');
989                 FPON := ini.ReadString('Cookie', 'PON', '');
990                 FKotehanName := ini.ReadString('Kotehan', 'Name', '');
991                 FKotehanMail := ini.ReadString('Kotehan', 'Mail', '');
992 //              ListStyle := TViewStyle(Ord(ini.ReadInteger('Status', 'ListStyle', 3)));
993 //              ItemNoVisible := ini.ReadBool('Status', 'ItemNoVisible', True);
994 //              ViewType := TGikoViewType(Ord(ini.ReadInteger('Status', 'ViewType', 0)));
995                 if UnRead < 0 then
996                         UnRead := 0;
997         finally
998                 ini.Free;
999         end;
1000 end;
1001
1002 procedure TBoard.SaveSettings;
1003 var
1004         ini: TMemIniFile;
1005         FileName: string;
1006 begin
1007         if Length( FilePath ) > 0 then
1008                 FileName := ExtractFilePath( FilePath )
1009         else
1010                 FileName := ParentCategory.ParenTBBS.GetLogFolder
1011                                                         + BBSID + PATH_DELIM;
1012         if not GikoSys.DirectoryExistsEx(FileName) then
1013                 GikoSys.ForceDirectoriesEx(FileName);
1014         FileName := FileName + FOLDER_INI_FILENAME;
1015         ini := TMemIniFile.Create(FileName);
1016         try
1017                 if UnRead < 0 then
1018                         UnRead := 0;
1019 //              ini.WriteBool('Status', 'Round', Round);
1020                 ini.WriteDateTime('Status', 'RoundDate', FRoundDate);
1021                 ini.WriteDateTime('Status', 'LastModified', FLastModified);
1022                 ini.WriteDateTime('Status', 'LastGetTime', FLastGetTime);
1023                 ini.WriteInteger('Status', 'UnRead', FUnRead);
1024                 ini.WriteString('Cookie', 'SPID', FSPID);
1025                 ini.WriteString('Cookie', 'PON', FPON);
1026                 ini.WriteString('Kotehan', 'Name', FKotehanName);
1027                 ini.WriteString('Kotehan', 'Mail', FKotehanMail);
1028 //              ini.WriteInteger('Status', 'ListStyle', Ord(ListStyle));
1029 //              ini.WriteBool('Status', 'ItemNoVisible', ItemNoVisible);
1030 //              ini.WriteInteger('Status', 'ViewType', Ord(ViewType));
1031                 ini.UpdateFile;
1032         finally
1033                 ini.Free;
1034         end;
1035 end;
1036
1037 // \83T\83u\83W\83F\83N\83gURL\8eæ\93¾
1038 function TBoard.GetReadCgiURL: string;
1039 begin
1040         //Result := URL + SUBJECT_FILENAME;
1041         //Result := GikoSys.UrlToServer(URL)
1042         //                              + 'test/read.cgi/' + BBSID + '/?raw=0.0';
1043         Result := URL + SUBJECT_FILENAME;
1044
1045 end;
1046
1047 // \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
1048 function TBoard.GetSubjectFileName: string;
1049 begin
1050         if Length( FilePath ) > 0 then
1051                 Result := FilePath
1052         else
1053                 Result := ParentCategory.ParenTBBS.GetLogFolder
1054                                                 + BBSID + PATH_DELIM + SUBJECT_FILENAME;
1055 end;
1056
1057 // \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
1058 function TBoard.GetFolderIndexFileName: string;
1059 begin
1060         if Length( FilePath ) > 0 then
1061                 Result := ExtractFilePath( FilePath ) + FOLDER_INDEX_FILENAME
1062         else
1063                 Result := ParentCategory.ParenTBBS.GetLogFolder
1064                                                 + BBSID + PATH_DELIM + FOLDER_INDEX_FILENAME;
1065 end;
1066
1067 // \83X\83\8c\97§\82Ä\91\97\90MURL
1068 function TBoard.GetSendURL: string;
1069 begin
1070         Result := GikoSys.UrlToServer(URL) + 'test/subbbs.cgi';
1071 end;
1072
1073 procedure TBoard.SetRound(b: Boolean);
1074 begin
1075         if b then
1076                 RoundList.Add(Self)
1077         else
1078                 RoundList.Delete(Self);
1079         if FRound = b then Exit;
1080         FRound := b;
1081         if FUpdate then
1082                 FModified := True;
1083 end;
1084
1085 procedure TBoard.SetRoundName(s: string);
1086 begin
1087         if FRoundName = s then Exit;
1088         FRoundName := s;
1089         if FUpdate then
1090                 FModified := True;
1091 end;
1092
1093 procedure TBoard.SetLastModified(d: TDateTime);
1094 begin
1095         if FLastModified = d then Exit;
1096         FLastModified := d;
1097         if FUpdate then
1098                 FModified := True;
1099 end;
1100
1101 procedure TBoard.SetLastGetTime(d: TDateTime);
1102 begin
1103         if FLastGetTime = d then Exit;
1104         FLastGetTime := d;
1105         if FUpdate then
1106                 FModified := True;
1107 end;
1108
1109 procedure TBoard.SetUnRead(i: Integer);
1110 begin
1111         if FUnRead = i then Exit;
1112         if i < 0 then i := 0;
1113         FUnRead := i;
1114         if FUpdate then
1115                 FModified := True;
1116 end;
1117
1118 procedure TBoard.SetKotehanName(s: string);
1119 begin
1120         if FKotehanName = s then Exit;
1121         FKotehanName := s;
1122         if FUpdate then
1123                 FModified := True;
1124 end;
1125
1126 procedure TBoard.SetKotehanMail(s: string);
1127 begin
1128         if FKotehanMail = s then Exit;
1129         FKotehanMail := s;
1130         if FUpdate then
1131                 FModified := True;
1132 end;
1133
1134 function TBoard.GetNewThreadCount: Integer;
1135 var
1136         i: Integer;
1137 begin
1138         Result := 0;
1139   if Length( ParentCategory.ParenTBBS.ShortSelectText ) = 0 then
1140   begin
1141     for i := 0 to Count - 1 do begin
1142       if Items[i].NewArrival then
1143               inc(Result);
1144     end;
1145   end else begin
1146     for i := 0 to Count - 1 do begin
1147       if Items[i].NewArrival then
1148       begin
1149         if Items[i].ShortTitle = '' then
1150                 Items[i].ShortTitle := GikoSys.ZenToHan(Items[i].Title);
1151         if AnsiPos(ParentCategory.ParenTBBS.ShortSelectText, Items[i].ShortTitle) <> 0 then
1152               inc(Result);
1153       end;
1154     end;
1155   end;
1156 end;
1157
1158 function TBoard.GetLogThreadCount: Integer;
1159 var
1160         i: Integer;
1161 begin
1162         Result := 0;
1163   if Length( ParentCategory.ParenTBBS.ShortSelectText ) = 0 then
1164   begin
1165     for i := 0 to Count - 1 do begin
1166             if Items[i].IsLogFile then
1167                     inc(Result);
1168     end;
1169   end else begin
1170     for i := 0 to Count - 1 do begin
1171       if Items[i].IsLogFile then
1172       begin
1173         if Items[i].ShortTitle = '' then
1174                 Items[i].ShortTitle := GikoSys.ZenToHan(Items[i].Title);
1175         if AnsiPos(ParentCategory.ParenTBBS.ShortSelectText, Items[i].ShortTitle) <> 0 then
1176                 inc(Result);
1177       end;
1178     end;
1179   end;
1180 end;
1181
1182 function TBoard.GetUserThreadCount: Integer;
1183 var
1184         i: Integer;
1185 begin
1186         Result := 0;
1187   if Length( ParentCategory.ParenTBBS.ShortSelectText ) = 0 then
1188           Result := Count
1189   else
1190     for i := 0 to Count - 1 do begin
1191       if Items[i].ShortTitle = '' then
1192         Items[i].ShortTitle := GikoSys.ZenToHan(Items[i].Title);
1193       if AnsiPos(ParentCategory.ParenTBBS.ShortSelectText, Items[i].ShortTitle) <> 0 then
1194         inc(Result);
1195     end;
1196 end;
1197
1198 function TBoard.GetNewThread(Index: Integer): TThreadItem;
1199 var
1200         i: Integer;
1201         Cnt: Integer;
1202 begin
1203         Result := nil;
1204         Cnt := 0;
1205   if Length( ParentCategory.ParenTBBS.ShortSelectText ) = 0 then
1206   begin
1207     for i := 0 to Count - 1 do begin
1208       if Items[i].NewArrival then
1209                   begin
1210         if Index = Cnt then begin
1211           Result := Items[i];
1212           Exit;
1213         end;
1214         inc(Cnt);
1215       end;
1216     end;
1217   end else begin
1218     for i := 0 to Count - 1 do begin
1219       if Items[i].NewArrival then
1220       begin
1221         if Items[i].ShortTitle = '' then
1222           Items[i].ShortTitle := GikoSys.ZenToHan(Items[i].Title);
1223         if AnsiPos(ParentCategory.ParenTBBS.ShortSelectText, Items[i].ShortTitle) <> 0 then begin
1224           if Index = Cnt then begin
1225             Result := Items[i];
1226             Exit;
1227           end;
1228           inc(Cnt);
1229         end;
1230       end;
1231     end;
1232   end;
1233 end;
1234
1235 function TBoard.GetLogThread(Index: Integer): TThreadItem;
1236 var
1237         i: Integer;
1238         Cnt: Integer;
1239 begin
1240   Cnt := 0;
1241   if Length( ParentCategory.ParenTBBS.ShortSelectText ) = 0 then
1242   begin
1243     for i := 0 to Count - 1 do begin
1244       if Items[i].IsLogFile then
1245                   begin
1246         if Index = Cnt then begin
1247           Result := Items[i];
1248           Exit;
1249         end;
1250         inc(Cnt);
1251       end;
1252     end;
1253   end else begin
1254     for i := 0 to Count - 1 do begin
1255       if Items[i].IsLogFile then
1256         begin
1257           if Items[i].ShortTitle = '' then
1258             Items[i].ShortTitle := GikoSys.ZenToHan(Items[i].Title);
1259           if AnsiPos(ParentCategory.ParenTBBS.ShortSelectText, Items[i].ShortTitle) <> 0 then begin
1260             if Index = Cnt then begin
1261               Result := Items[i];
1262               Exit;
1263           end;
1264           inc(Cnt);
1265         end;
1266       end;
1267           end;
1268   end;
1269   Result := nil;
1270 end;
1271
1272 function TBoard.GetUserThread(Index: Integer): TThreadItem;
1273 var
1274         i: Integer;
1275         Cnt: Integer;
1276 begin
1277         Result := nil;
1278         Cnt := 0;
1279   if Length( ParentCategory.ParenTBBS.ShortSelectText ) = 0 then
1280   begin
1281     for i := 0 to Count - 1 do begin
1282       if Index = Cnt then
1283       begin
1284         Result := Items[ i ];
1285         Exit;
1286       end;
1287       inc( Cnt );
1288     end;
1289   end else begin
1290     for i := 0 to Count - 1 do begin
1291       if Items[i].ShortTitle = '' then
1292         Items[i].ShortTitle := GikoSys.ZenToHan(Items[i].Title);
1293       if AnsiPos(ParentCategory.ParenTBBS.ShortSelectText, Items[i].ShortTitle) <> 0 then begin
1294         if Index = Cnt then begin
1295           Result := Items[i];
1296           Exit;
1297         end;
1298         inc(Cnt);
1299       end;
1300     end;
1301         end;
1302 end;
1303
1304 procedure TBoard.BeginUpdate;
1305 begin
1306         FUpdate := False;
1307 end;
1308
1309 procedure TBoard.EndUpdate;
1310 begin
1311         FUpdate := True;
1312 end;
1313
1314 {class function TBoard.GetColumnName(Index: Integer): string;
1315 begin
1316         Result := COLUMN_THREADITEM[Index];
1317 end;
1318
1319 class function TBoard.GetColumnCount: Integer;
1320 begin
1321         Result := Length(COLUMN_THREADITEM);
1322 end;}
1323
1324 //constructor TThreadItem.Create(AOwner: TComponent);
1325 procedure TThreadItem.Init;
1326 begin
1327         FNo := 0;
1328         FFileName := '';
1329         FTitle := '';
1330         FRoundDate := ZERO_DATE;
1331         FLastModified := ZERO_DATE;
1332         FCount := 0;
1333         FAllResCount := 0;
1334         FNewResCount := 0;
1335         FSize := 0;
1336         FRound := False;
1337         FIsLogFile := False;
1338         FParentBoard := nil;
1339         FKokomade := -1;
1340         FNewReceive := 0;
1341         FNewArrival := False;
1342
1343         FUpdate := True;
1344         FURL := '';
1345         FBoardPlugIn := nil;
1346 end;
1347
1348 // *************************************************************************
1349 // \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^
1350 // *************************************************************************
1351 constructor TThreadItem.Create(
1352         inPlugIn        : TBoardPlugIn;
1353         inURL                   : string
1354 );
1355 var
1356         foundPos                        : Integer;
1357         protocol, host, path, document, port, bookmark  : string;
1358         BBSID, BBSKey   : string;
1359 const
1360         READ_PATH                                                       = '/test/read.cgi';
1361 begin
1362
1363         inherited Create;
1364         Init;
1365
1366         FBoardPlugIn    := inPlugIn;
1367         URL                                             := inURL;
1368
1369         if inPlugIn = nil then begin
1370                 foundPos := Pos( READ_PATH, inURL );
1371                 if foundPos > 0 then begin
1372                         // dat \82Ì\95Û\91\83p\83X\82ð\90Ý\92è
1373                         GikoSys.ParseURI( inURL, protocol, host, path, document, port, bookmark );
1374                         GikoSys.Parse2chURL( inURL, path, document, BBSID, BBSKey );
1375                         if GikoSys.Is2chHost( host ) then
1376                                 FilePath :=
1377                                         IncludeTrailingPathDelimiter( GikoSys.Setting.LogFolder ) +
1378                                         BBS2CH_LOG_FOLDER + PATH_DELIM + BBSID + PATH_DELIM + BBSKey + '.dat'
1379                         else
1380                                 FilePath :=
1381                                         IncludeTrailingPathDelimiter( GikoSys.Setting.LogFolder ) +
1382                                         EXTERNAL_LOG_FOLDER + PATH_DELIM + host + PATH_DELIM + BBSID + PATH_DELIM + BBSKey + '.dat';
1383                         FileName        := BBSKey + '.dat';
1384                         IsLogFile       := FileExists( FilePath );
1385                 end;
1386         end else begin
1387                 // \83v\83\89\83O\83C\83\93\82É TThreadItem \82ª\8dì\90¬\82³\82ê\82½\82±\82Æ\82ð\93`\82¦\82é
1388                 inPlugIn.CreateThreadItem( DWORD( Self ) );
1389         end;
1390
1391 end;
1392
1393 // *************************************************************************
1394 // \83f\83X\83g\83\89\83N\83^
1395 // *************************************************************************
1396 destructor TThreadItem.Destroy;
1397 begin
1398
1399         // \83v\83\89\83O\83C\83\93\82É TThreadItem \82ª\94j\8aü\82³\82ê\82½\82±\82Æ\82ð\93`\82¦\82é
1400         if IsBoardPlugInAvailable then
1401                 FBoardPlugIn.DisposeThreadItem( DWORD( Self ) );
1402
1403         inherited;
1404
1405 end;
1406
1407 // *************************************************************************
1408 // \8aO\95\94\94Â\83v\83\89\83O\83C\83\93\82ª\8eg\97p\89Â\94\\82©
1409 // *************************************************************************
1410 function        TThreadItem.IsBoardPlugInAvailable : Boolean;
1411 begin
1412
1413         repeat
1414                 if BoardPlugIn = nil then
1415                         Break;
1416
1417                 if not Assigned( Pointer( BoardPlugIn.Module ) ) then
1418                         Break;
1419
1420                 Result := True;
1421                 Exit;
1422         until True;
1423
1424         Result := False;
1425
1426 end;
1427
1428 function TThreadItem.GetDatURL: string;
1429 var
1430         Protocol, Host, Path, Document, Port, Bookmark: string;
1431 begin
1432         Result := ParentBoard.URL
1433                                         + 'dat/'
1434                                         + FileName;
1435         if FDownloadHost <> '' then begin
1436                 GikoSys.ParseURI(Result, Protocol, Host, Path, Document, Port, Bookmark);
1437                 Result := Format('%s://%s%s%s', [Protocol,
1438                                                                                                                                                  FDownloadHost,
1439                                                                                                                                                  Path,
1440                                                                                                                                                  Document]);
1441         end;
1442 //      Result := GikoSys.UrlToServer(ParentBoard.URL)
1443 //                                      + 'test/read.cgi/' + ParentBoard.BBSID + '/'
1444 //                                      + ChangeFileExt(FileName, '') + '/?raw='
1445 //                                      + IntToStr(ResNum) + '.' + IntToStr(ResSize);
1446 end;
1447
1448 function TThreadItem.GetDatgzURL: string;
1449         function isOldKako(s: string): Boolean;
1450         begin
1451                 Result := False;
1452                 if AnsiPos('piza.', s) <> 0 then
1453                         Result := True
1454                 else if AnsiPos('www.bbspink.', s) <> 0 then
1455                         Result := True
1456                 else if AnsiPos('tako.', s) <> 0 then
1457                         Result := True;
1458         end;
1459 var
1460         Protocol, Host, Path, Document, Port, Bookmark: string;
1461         DatNo: string;
1462 begin
1463         if FDownloadHost = '' then begin
1464                 DatNo := ChangeFileExt(FileName, '');
1465                 if isOldKako(ParentBoard.URL) then begin
1466                         Result := Format('%s%s/%.3s/%s.dat', [ParentBoard.URL, 'kako', DatNo, DatNo]);
1467                 end else begin
1468                         if Length(DatNo) > 9 then begin
1469                                 //http://xxx.2ch.net/xxx/kako/9999/99999/999999999.dat.gz
1470                                 Result := Format('%s%s/%.4s/%.5s/%s.dat.gz', [ParentBoard.URL, 'kako', DatNo, DatNo, DatNo]);
1471                         end else begin
1472                                 //http://xxx.2ch.net/xxx/kako/999/999999999.dat.gz
1473                                 Result := Format('%s%s/%.3s/%s.dat.gz', [ParentBoard.URL, 'kako', DatNo, DatNo]);
1474                         end;
1475                 end;
1476         end else begin
1477                 Gikosys.ParseURI(Result, Protocol, Host, Path, Document, Port, Bookmark);
1478                 DatNo := ChangeFileExt(Document, '');
1479                 if isOldKako(DownloadHost) then begin
1480                         Result := Format('%s://%s/%s/kako/%.3s/%s.dat', [Protocol, DownloadHost, ParentBoard.FBBSID, DatNo, DatNo]);
1481                 end else begin
1482                         if Length(DatNo) > 9 then begin
1483                                 Result := Format('%s://%s/%s/kako/%.4s/%.5s/%s.dat.gz', [Protocol, DownloadHost, ParentBoard.FBBSID, DatNo, DatNo, DatNo]);
1484                         end else begin
1485                                 Result := Format('%s://%s/%s/kako/%.3s/%s.dat.gz', [Protocol, DownloadHost, ParentBoard.FBBSID, DatNo, DatNo]);
1486                         end;
1487                 end;
1488         end;
1489 end;
1490
1491 {function TThreadItem.GetOldDatgzURL: string;
1492 var
1493         Protocol, Host, Path, Document, Port, Bookmark: string;
1494 begin
1495         Result := Format('%s%s/%.3s/%s.gz', [ParentBoard.URL,
1496                                                                                                                                                          'kako',
1497                                                                                                                                                          FileName,
1498                                                                                                                                                          FileName]);
1499         if FDownloadHost <> '' then begin
1500                 ParseURI(Result, Protocol, Host, Path, Document, Port, Bookmark);
1501                 Result := Format('%s://%s%s%s', [Protocol,
1502                                                                                                                                                  DownloadHost,
1503                                                                                                                                                  Path,
1504                                                                                                                                                  Document]);
1505
1506         end;
1507 end;}
1508
1509 function TThreadItem.GetOfflawCgiURL(SessionID: string): string;
1510 //var
1511 //      Protocol, Host, Path, Document, Port, Bookmark: string;
1512 begin
1513 //      Result := GikoSys.UrlToServer(ParentBoard.URL)
1514 //                                      + 'test/offlaw.cgi/' + ParentBoard.BBSID + '/'
1515 //                                      + ChangeFileExt(FileName, '') + '/?raw=.0&sid=' + HttpEncode(SessionID);
1516         if FDownloadHost = '' then begin
1517                 Result := GikoSys.UrlToServer(ParentBoard.URL)
1518                                                 + 'test/offlaw.cgi/' + ParentBoard.BBSID + '/'
1519                                                 + ChangeFileExt(FileName, '') + '/?raw=.0&sid=' + HttpEncode(SessionID);
1520         end else begin
1521                 //http://news.2ch.net/test/offlaw.cgi/newsplus/1014038577/?raw=.196928&sid=
1522                 //GikoSys.ParseURI(Result, Protocol, Host, Path, Document, Port, Bookmark);
1523                 Result := 'http://' + FDownloadHost
1524                                                 + '/test/offlaw.cgi/' + ParentBoard.BBSID + '/'
1525                                                 + ChangeFileExt(FileName, '') + '/?raw=.0&sid=' + HttpEncode(SessionID);
1526 //              Result := Format('%s://%s%s%s', [Protocol,
1527 //                                                                                                                                               DownloadHost,
1528 //                                                                                                                                               Path,
1529 //                                                                                                                                               Document]);
1530         end;
1531 end;
1532
1533 function TThreadItem.GetSendURL: string;
1534 begin
1535         Result := GikoSys.UrlToServer(ParentBoard.URL)
1536                                         + 'test/bbs.cgi';
1537 end;
1538
1539 procedure TThreadItem.DeleteLogFile;
1540 begin
1541         DeleteFile(GetThreadFileName);
1542                 if FileExists(ChangeFileExt(GetThreadFileName,'.NG')) = true then
1543                         DeleteFile(ChangeFileExt(GetThreadFileName,'.NG'));
1544         FRoundDate := ZERO_DATE;
1545         FLastModified := ZERO_DATE;
1546         FSize := 0;
1547         FIsLogFile := False;
1548         FKokomade := -1;
1549         FNewReceive := 0;
1550         FNewArrival := False;
1551         FUnRead := False;
1552         FScrollTop := 0;
1553         FRound := False;
1554         FDownloadHost := '';
1555         FAgeSage := gasNone;
1556
1557         FCount := 0;
1558         FNewResCount := 0;
1559         FRoundName := '';
1560 end;
1561
1562 function TThreadItem.GetThreadFileName: string;
1563 begin
1564         if Length( FilePath ) > 0 then
1565                 Result := FilePath
1566         else
1567                 Result := ParentBoard.ParentCategory.ParenTBBS.GetLogFolder
1568                                                 + ParentBoard.BBSID + PATH_DELIM + FileName;
1569 end;
1570
1571 procedure TThreadItem.SetLastModified(d: TDateTime);
1572 begin
1573         if FLastModified = d then Exit;
1574         FLastModified := d;
1575         if FUpdate and (ParentBoard <> nil) then
1576                 ParentBoard.FModified := True;
1577 end;
1578
1579 {procedure TThreadItem.SetRoundNo(i: Integer);
1580 begin
1581         if FRoundNo = i then Exit;
1582         FRoundNo := i;
1583         if FUpdate and (ParentBoard <> nil) then
1584                 ParentBoard.FModified := True;
1585 end;}
1586
1587 procedure TThreadItem.SetRound(b: Boolean);
1588 begin
1589         if b then
1590                 RoundList.Add(Self)
1591         else
1592                 RoundList.Delete(Self);
1593         if FRound = b then Exit;
1594         FRound := b;
1595         if FUpdate and (ParentBoard <> nil) then
1596                 ParentBoard.FModified := True;
1597 end;
1598
1599 procedure TThreadItem.SetRoundName(s: string);
1600 begin
1601         if FRoundName = s then Exit;
1602         FRoundName := s;
1603         if FUpdate and (ParentBoard <> nil) then
1604                 ParentBoard.FModified := True;
1605 end;
1606
1607 procedure TThreadItem.SetKokomade(i: Integer);
1608 begin
1609         if FKokomade = i then Exit;
1610         FKokomade := i;
1611         if FUpdate and (ParentBoard <> nil) then
1612                 ParentBoard.FModified := True;
1613 end;
1614
1615 procedure TThreadItem.SetUnRead(b: Boolean);
1616 begin
1617         if FUnRead = b then Exit;
1618         FUnRead := b;
1619         if FUpdate and (ParentBoard <> nil) then
1620                 ParentBoard.FModified := True;
1621 end;
1622
1623 procedure TThreadItem.SetScrollTop(i: Integer);
1624 begin
1625         if FScrollTop = i then Exit;
1626         FScrollTop := i;
1627         if FUpdate and (ParentBoard <> nil) then
1628                 ParentBoard.FModified := True;
1629 end;
1630
1631 procedure TThreadItem.BeginUpdate;
1632 begin
1633         FUpdate := False;
1634 end;
1635
1636 procedure TThreadItem.EndUpdate;
1637 begin
1638         FUpdate := True;
1639 end;
1640
1641 {initialization
1642         BBS2ch := TBBS.Create;
1643
1644 finalization
1645         if BBS2ch <> nil then
1646                 BBS2ch.Free;}
1647 end.
1648