OSDN Git Service

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