OSDN Git Service

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