OSDN Git Service

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