OSDN Git Service

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