OSDN Git Service

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