OSDN Git Service

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