X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=BoardGroup.pas;h=4b3d7f7773a3b41db22ee33d05aed954d95a1455;hb=3c51e182523ceb4f4cce262a5e3fd0776e1dd175;hp=1df651fe531984ba40be9e8eeb9093c454c44af3;hpb=d122de4fa969c9ae911ba8ad188b36e0ca8b0346;p=gikonavigoeson%2Fgikonavi.git diff --git a/BoardGroup.pas b/BoardGroup.pas index 1df651f..4b3d7f7 100644 --- a/BoardGroup.pas +++ b/BoardGroup.pas @@ -3,112 +3,63 @@ unit BoardGroup; interface uses - Windows, SysUtils, Classes, ComCtrls, IniFiles, {HTTPApp,} YofUtils, IdGlobal, - ExternalBoardManager, ExternalBoardPlugInMain; + Windows, SysUtils, Classes, ComCtrls, {HTTPApp,} YofUtils, IdGlobal, + ExternalBoardManager, ExternalBoardPlugInMain, StrUtils; type //ƒŠƒXƒg‚Ì•\Ž¦ƒAƒCƒeƒ€‘I‘ð - TGikoViewType = (gvtAll, gvtLog, gvtNew, gvtUser); - //ƒŠƒXƒg‚̎擾Œ” - //TGikoListCount = (glc50, glc100, glc200, glc500, glc1000, glcAll); - //„‰ñ”ԍ† - //TGikoRoundNo = (grnNone, grn1, grn2, grn3, grn4, grn5, grnOnce); + TGikoViewType = (gvtAll, gvtLog, gvtNew, gvtLive, gvtArch, gvtUser); //ƒŠƒXƒg‚̏グ‰º‚° - TGikoAgeSage = (gasNone, gasAge, gasSage, gasNew); - -{ TFolder = class - private - FItemList: TList; //ŽqƒAƒCƒeƒ€ƒŠƒXƒg - FLeaf: Boolean; //‰º‚ɃtƒHƒ‹ƒ_‚ðŽ‚Â‚±‚Æ‚ªo—ˆ‚é‚© - public - function Add(Item: TFolder): Integer; - procedure Clear; - procedure Delete(Index: Integer); - procedure Exchange(Index1, Index2: Integer); - procedure Insert(Index: Integer; Item: TFolder); - procedure Move(CurIndex, NewIndex: Integer); - function Remove(Item: TFolder): Integer; - procedure Sort(Compare: TListSortCompare); - property Capacity: Integer read FCapacity write SetCapacity; - property Count: Integer read FCount write SetCount; - property Items[Index: Integer]: TFolder read Get write Put; default; - - property Leaf: Boolean read FLeaf; - end; - - TBBS = class(TFolder) - end; - TCategory class(TFolder) - end; - TBoard = class(TFolder) - end; - TThreadItem = class(TFolder) - end; -} - -{ - TBBS = class(TBBS) - end; - TBoard2ch = class(TBoard) - end; - TThreadItem2ch = class(TThreadItem) - end; -} - -// ITest = interface -// end; -// IBBS = interface -// end; -// ICategory = interface -// end; -// IBoard = interface -// end; -// IThreadItem = interface -// end; + TGikoAgeSage = (gasNone, gasAge, gasSage, gasNew, gasArch, gasNull); TCategory = class; TBoard = class; TThreadItem = class; - //‚Æ‚è‚ ‚¦‚¸‚Q‚¿‚á‚ñ‚Ë‚é‚̃‹[ƒg + + // BBS ‚̃‹[ƒg TBBS = class(TList) private FTitle: string; - FLogFolder: string; + FFilePath : string; // ”ƒŠƒXƒg‚̃pƒX FExpand: Boolean; FKubetsuChk: Boolean; //iž‚ÝŽž‘啶Žš¬•¶Žš‹æ•Ê FSelectText: string; //iž‚Ý•¶Žš—ñ FShortSelectText: string; + FIsBoardFileRead : Boolean; // ”ƒŠƒXƒg‚͓ǂݍž‚Ü‚ê‚Ä‚¢‚é‚©H function GetCategory(index: integer): TCategory; procedure SetCategory(index: integer; value: TCategory); procedure SetSelectText(s: string); public - constructor Create(LogFolder: string); + constructor Create( boardFilePath : string ); destructor Destroy; override; function Add(item: TCategory): integer; procedure Delete(index: integer); procedure Clear; override; function Find(key: string): TCategory; - function FindBBSID(BBSID: string): TBoard; - function FindBoardFromTitle(Title: string): TBoard; - function FindBoardFromURL(inURL: string): TBoard; - function FindThreadFromURL( inURL : string ) : TThreadItem; - function FindThreadItem(BBSID: string; FileName: string): TThreadItem; - function GetLogFolder: string; + function FindBBSID(const BBSID: string): TBoard; + function FindBoardFromTitle(const Title: string): TBoard; + function FindBoardFromURL(const inURL: string): TBoard; + function FindThreadFromURL(const inURL : string ) : TThreadItem; + function FindThreadItem(const BBSID, FileName: string): TThreadItem; + function FindCategoryFromTitle(const inTitle : string ) : TCategory; + property FilePath : string read FFilePath write FFilePath; property Items[index: integer]: TCategory read GetCategory write SetCategory; property Title: string read FTitle write FTitle; property NodeExpand: Boolean read FExpand write FExpand; - + property KubetsuChk: Boolean read FKubetsuChk write FKubetsuChk; property SelectText: string read FSelectText write SetSelectText; property ShortSelectText: string read FShortSelectText write FShortSelectText; + + property IsBoardFileRead : Boolean read FIsBoardFileRead write FIsBoardFileRead; end; - //ƒJƒeƒSƒŠ - TCategory = class(TList) + // ƒJƒeƒSƒŠ(” URL ‚̃ŠƒXƒg) + TCategory = class(TStringList) private FNo: Integer; FTitle: string; @@ -129,20 +80,23 @@ type function Add(item: TBoard): integer; procedure Delete(index: integer); procedure Clear; override; - function FindName(key: string): TBoard; - function FindBBSID(BBSID: string): TBoard; - function FindBoardFromTitle(Title: string): TBoard; - function FindBoardFromURL(inURL: string): TBoard; - function FindThreadFromURL( inURL : string ) : TThreadItem; + function FindName(const key: string): TBoard; + function FindBBSID(const BBSID: string): TBoard; + function FindBoardFromTitle(const Title: string): TBoard; + function FindBoardFromURL(const inURL: string): TBoard; + function FindThreadFromURL(const inURL : string ) : TThreadItem; function IsMidoku: Boolean; property NodeExpand: Boolean read FExpand write FExpand; end; - //” - TBoard = class(TList) + //! ƒXƒŒƒbƒh”ƒJƒEƒ“ƒgðŒ•¶ + TThreadCount = function(Item : TThreadItem): Boolean; + + // ”Â(ƒXƒŒƒbƒh URL ‚̃ŠƒXƒg) + TBoard = class(TStringList) private - FContext: DWORD; // ƒvƒ‰ƒOƒCƒ“‚ªŽ©—R‚ɐݒ肵‚Ä‚¢‚¢’l(Žå‚ɃCƒ“ƒXƒ^ƒ“ƒX‚ª“ü‚é) + FContext: DWORD; // ƒvƒ‰ƒOƒCƒ“‚ªŽ©—R‚ɐݒ肵‚Ä‚¢‚¢’l(Žå‚ɃCƒ“ƒXƒ^ƒ“ƒX‚ª“ü‚é) FNo: Integer; //”ԍ† FTitle: string; //ƒ{[ƒhƒ^ƒCƒgƒ‹ @@ -155,11 +109,13 @@ type FLastGetTime: TDateTime; //ƒXƒŒƒbƒh‚Ü‚½‚̓XƒŒƒbƒhˆê——‚ðÅŒã‚ɍXV‚µ‚½“úŽžiƒT[ƒo‘¤“úŽžE‘‚«ž‚ÝŽž‚ÉŽg—p‚·‚éj FIsThreadDatRead: Boolean; //ƒXƒŒƒbƒhƒŠƒXƒg‚͓ǂݍž‚Ü‚ê‚Ä‚¢‚é‚©H FUnRead: Integer; //ƒXƒŒƒbƒh–¢“ǐ” - FParentCategory: TCategory; //eƒJƒeƒSƒŠ + FParentCategory: TCategory; //eƒJƒeƒSƒŠ FModified: Boolean; //C³ƒtƒ‰ƒO FBoolData: Boolean; //‚¢‚ë‚ñ‚È—p“r‚ÉŽg‚¤yo FSPID: string; //‘‚«ž‚Ý—pSPID FPON: string; //‘‚«ž‚Ý—pPON + FCookie: string; //‘‚«ž‚Ý—pCookie•¶Žš—ñ + FExpires: TDateTime; //Cookie‚Ì—LŒøŠúŒÀ FKotehanName: string; //ƒRƒeƒnƒ“–¼‘O FKotehanMail: string; //ƒRƒeƒnƒ“ƒ[ƒ‹ @@ -172,18 +128,31 @@ type FIntData : Integer; // D‚«‚É‚¢‚¶‚Á‚Ă悵B‚¢‚ë‚ñ‚È—p“r‚ÉŽg‚¤yo FListData : TList; // D‚«‚É‚¢‚¶‚Á‚Ă悵B‚¢‚ë‚ñ‚È—p“r‚ÉŽg‚¤yo + FSETTINGTXTTime : TDateTime; //SETTING.TXT‚ðŽæ“¾‚µ‚½“úŽž + FIsSETTINGTXT : boolean; //SETTING.TXT‚ðŽæ“¾‚µ‚Ä‚¢‚é‚© + FHEADTXTTime : TDateTime; //HEAD.TXT‚ðŽæ“¾‚µ‚½“úŽž + FIsHEADTXT : boolean; //HEAD.TXT‚ðŽæ“¾‚µ‚Ä‚¢‚é‚© + FTitlePictureURL: string; //topŠG‚ÌURL + FMultiplicity : Integer; //d•¡‚µ‚Ä‚¢‚é‚©‚Ç‚¤‚©H + FIs2ch : Boolean; //host‚ª2ch‚©‚Ç‚¤‚© + FNewThreadCount: Integer; //V’…ƒXƒŒƒbƒh‚̐” + FLogThreadCount: Integer; //ƒƒO—L‚èƒXƒŒƒbƒh‚̐” + FUserThreadCount: Integer; //H + FLiveThreadCount: Integer; //¶‘¶ƒXƒŒƒbƒh” + FArchiveThreadCount: Integer; //DAT—Ž‚¿ƒXƒŒƒbƒh” function GetThreadItem(index: integer): TThreadItem; procedure SetThreadItem(index: integer; value: TThreadItem); procedure SetRound(b: Boolean); procedure SetRoundName(s: string); + //procedure SetRoundName(s: PChar); procedure SetLastModified(d: TDateTime); procedure SetLastGetTime(d: TDateTime); procedure SetUnRead(i: Integer); procedure SetKotehanName(s: string); procedure SetKotehanMail(s: string); + procedure Init; public - constructor Create; overload; - constructor Create( inPlugIn : TBoardPlugIn; inURL : string = '' ); overload; + constructor Create( inPlugIn : TBoardPlugIn; inURL : string ); destructor Destroy; override; property Context: DWORD read FContext write FContext; @@ -194,6 +163,7 @@ type property BBSID: string read FBBSID write FBBSID; property URL: string read FURL write FURL; property Round: Boolean read FRound write SetRound; + //property RoundName: PChar read FRoundName write SetRoundName; property RoundName: string read FRoundName write SetRoundName; property RoundDate: TDateTime read FRoundDate write FRoundDate; property LastModified: TDateTime read FLastModified write SetLastModified; @@ -215,24 +185,32 @@ type procedure Delete(index: integer); procedure DeleteList(index: integer); procedure Clear; override; - function Find(ItemFileName: string): TThreadItem; - function FindThreadFromURL( inURL : string ) : TThreadItem; - function GetIndex(ItemFileName: string): Integer; - function GetIndexFromURL(URL: string): Integer; + function FindThreadFromFileName(const ItemFileName: string): TThreadItem; + function FindThreadFromURL(const inURL : string ) : TThreadItem; + function GetIndexFromFileName(const ItemFileName: string): Integer; + function GetIndexFromURL(const URL: string; reverse : Boolean = False): Integer; procedure LoadSettings; procedure SaveSettings; function GetReadCgiURL: string; function GetSubjectFileName: string; function GetFolderIndexFileName: string; + function GetSETTINGTXTFileName: string; + function GETHEADTXTFileName: string; + function GetTitlePictureFileName: string; function GetSendURL: string; function GetNewThreadCount: Integer; function GetLogThreadCount: Integer; + function GetArchiveThreadCount: Integer; + function GetLiveThreadCount: Integer; function GetUserThreadCount: Integer; function GetNewThread(Index: Integer): TThreadItem; - function GetLogThread(Index: Integer): TThreadItem; + function GetLogThread(Index: Integer): TThreadItem; overload; + function GetArchiveThread(Index: Integer): TThreadItem; + function GetLiveThread(Index: Integer): TThreadItem; function GetUserThread(Index: Integer): TThreadItem; - + function GetThreadCount(func :TThreadCount ): Integer; + function GetThread(func :TThreadCount;const Index :Integer ): TThreadItem; procedure BeginUpdate; procedure EndUpdate; property NodeExpand: Boolean read FExpand write FExpand; @@ -241,13 +219,28 @@ type property PON: string read FPON write FPON; property KotehanName: string read FKotehanName write SetKotehanName; property KotehanMail: string read FKotehanMail write SetKotehanMail; + + property SETTINGTXTTime: TDateTime read FSETTINGTXTTime write FSETTINGTXTTime; + property IsSETTINGTXT: boolean read FIsSETTINGTXT write FIsSETTINGTXT; + property HEADTXTTime: TDateTime read FHEADTXTTime write FHEADTXTTime; + property IsHEADTXT: boolean read FIsHEADTXT write FIsHEADTXT; + property TitlePictureURL: string read FTitlePictureURL write FTitlePictureURL; + property Multiplicity: Integer read FMultiplicity write FMultiplicity; + property Is2ch : boolean read FIs2ch write FIs2ch; + property NewThreadCount: Integer read FNewThreadCount write FNewThreadCount; //V’…ƒXƒŒƒbƒh‚̐” + property LogThreadCount: Integer read FLogThreadCount write FLogThreadCount; //ƒƒO—L‚èƒXƒŒƒbƒh‚̐” + property UserThreadCount: Integer read FUserThreadCount write FUserThreadCount; //H + property LiveThreadCount: Integer read FLiveThreadCount write FLiveThreadCount; + property ArchiveThreadCount: Integer read FArchiveThreadCount write FArchiveThreadCount; + + property Cookie: string read FCookie write FCookie; + property Expires: TDateTime read FExpires write FExpires; end; //ƒXƒŒ TThreadItem = class(TObject) private FContext: DWORD; // ƒvƒ‰ƒOƒCƒ“‚ªŽ©—R‚ɐݒ肵‚Ä‚¢‚¢’l(Žå‚ɃCƒ“ƒXƒ^ƒ“ƒX‚ª“ü‚é) - FNo: Integer; //”ԍ† FFileName: string; //ƒXƒŒƒbƒhƒtƒ@ƒCƒ‹–¼ FTitle: string; //ƒXƒŒƒbƒhƒ^ƒCƒgƒ‹ @@ -269,30 +262,31 @@ type FScrollTop: Integer; //ƒXƒNƒ[ƒ‹ˆÊ’u FDownloadHost: string; //¡‚̃zƒXƒg‚ƈႤê‡‚̃zƒXƒg FAgeSage: TGikoAgeSage; //ƒAƒCƒeƒ€‚̏グ‰º‚° -// FSPID: string; //‘‚«ž‚Ý—pSPID - FUpdate: Boolean; FExpand: Boolean; FURL : string; // ‚±‚̃XƒŒ‚ðƒuƒ‰ƒEƒU‚Å•\Ž¦‚·‚éÛ‚Ì URL - FBoardPlugIn : TBoardPlugIn; // ‚±‚̃XƒŒ‚ðƒTƒ|[ƒg‚·‚éƒvƒ‰ƒOƒCƒ“ - FFilePath : string; // ‚±‚̃XƒŒ‚ª•Û‘¶‚³‚ê‚Ä‚¢‚éƒpƒX - FSizeByte : Integer; // CreateHTML2 ‚ðŽÀs‚µ‚Ä‚¢‚éÅ’†‚Ɉꎞ“I‚É•Û‘¶‚³‚ê‚é’l - + FJumpAddress : Integer; //ƒŒƒX”ԍ†Žw’èURL‚𓥂ñ‚¾‚Æ‚«‚ÉŽw’肳‚ê‚郌ƒX‚̔ԍ†‚ª“ü‚é procedure SetLastModified(d: TDateTime); procedure SetRound(b: Boolean); - procedure SetRoundName(s: string); + procedure SetRoundName(const s: string); + //procedure SetRoundName(const s: PChar); procedure SetKokomade(i: Integer); procedure SetUnRead(b: Boolean); procedure SetScrollTop(i: Integer); + procedure Init; + function GetCreateDate: TDateTime; + function GetFilePath: String; public - constructor Create; overload; - constructor Create( inPlugIn : TBoardPlugIn; inURL : string = '' ); overload; + constructor Create(const inPlugIn : TBoardPlugIn; const inBoard : TBoard; inURL : string ); overload; + constructor Create(const inPlugIn : TBoardPlugIn; const inBoard : TBoard; + inURL : string; inExist: Boolean; const inFilename: string ); overload; + destructor Destroy; override; function GetDatURL: string; function GetDatgzURL: string; // function GetOldDatgzURL: string; - function GetOfflawCgiURL(SessionID: string): string; + function GetOfflawCgiURL(const SessionID: string): string; function GetSendURL: string; procedure DeleteLogFile; function GetThreadFileName: string; @@ -313,6 +307,7 @@ type property Size: Integer read FSize write FSize; property Round: Boolean read FRound write SetRound; property RoundName: string read FRoundName write SetRoundName; + //property RoundName: PChar read FRoundName write SetRoundName; property IsLogFile: Boolean read FIsLogFile write FIsLogFile; property ParentBoard: TBoard read FParentBoard write FParentBoard; @@ -324,140 +319,258 @@ type property Expand: Boolean read FExpand write FExpand; property DownloadHost: string read FDownloadHost write FDownloadHost; property AgeSage: TGikoAgeSage read FAgeSage write FAgeSage; -// property SPID: string read FSPID write FSPID; - + property CreateDate: TDateTime read GetCreateDate; property URL : string read FURL write FURL; - property BoardPlugIn : TBoardPlugIn read FBoardPlugIn; - property FilePath : string read FFilePath write FFilePath; - property SizeByte : Integer read FSizeByte write FSizeByte; - function IsBoardPlugInAvailable : Boolean; + property FilePath : string read GetFilePath; + property JumpAddress : Integer read FJumpAddress write FJumpAddress; end; - - - //ŒŸõŒ‹‰ÊƒŠƒXƒg -{ TSearchList = class(TList) - private - function GetThreadItem(index: integer): TThreadItem; - procedure SetThreadItem(index: integer; value: TThreadItem); - public - constructor Create; + TBoardGroup = class(TStringList) + private + FBoardPlugIn : TBoardPlugIn; // ‚±‚̔‚ðƒTƒ|[ƒg‚·‚éƒvƒ‰ƒOƒCƒ“ + public destructor Destroy; override; + procedure Clear ; override; + property BoardPlugIn : TBoardPlugIn read FBoardPlugIn write FBoardPlugIn; + end; - property Items[index: integer]: TThreadItem read GetThreadItem write SetThreadItem; - - function Add(item: TThreadItem): integer; - procedure Delete(index: integer); - procedure Clear; override; - end;} + // “ÁŽê—p“r—pTBoard + TSpecialBoard = class(TBoard) + public + function Add(item: TThreadItem): integer; overload; + procedure Clear; overload; + end; function BBSsFindBoardFromBBSID( inBBSID : string ) : TBoard; function BBSsFindBoardFromURL( inURL : string ) : TBoard; function BBSsFindBoardFromTitle( inTitle : string ) : TBoard; - function BBSsFindThreadFromURL( inURL : string ) : TThreadItem; + function BBSsFindThreadFromURL(const inURL : string ) : TThreadItem; + function ConvertDateTimeString( inDateTimeString : string) : TDateTime; + + procedure DestorySpecialBBS( inBBS : TBBS ); var BBSs : array of TBBS; + BoardGroups : array of TBoardGroup; + SpecialBBS : TBBS; + SpecialBoard: TSpecialBoard; implementation uses - GikoSystem, RoundData; + GikoSystem, RoundData, MojuUtils, DateUtils, IniFiles; const BBS2CH_NAME: string = '‚Q‚¿‚á‚ñ‚Ë‚é'; BBS2CH_LOG_FOLDER: string = '2ch'; + EXTERNAL_LOG_FOLDER: string = 'exboard'; FOLDER_INI_FILENAME: string = 'Folder.ini'; FOLDER_INDEX_FILENAME: string = 'Folder.idx'; SUBJECT_FILENAME: string = 'subject.txt'; PATH_DELIM: string = '\'; + SETTINGTXT_FILENAME: string = 'SETTING.TXT'; + HEADTXT_FILENAME: string = 'head.html'; //DEFAULT_LIST_COUNT: Integer = 100; -// COLUMN_CATEGORY: array[0..0] of string = ('ƒJƒeƒSƒŠ–¼'); -// COLUMN_BOARD: array[0..3] of string = ('”–¼', 'Žæ“¾”', '„‰ñ—\–ñ', '‘O‰ñ„‰ñ“úŽž'); -// COLUMN_THREADITEM: array[0..3] of string = ('ƒXƒŒƒbƒh–¼', 'ƒJƒEƒ“ƒg', '„‰ñ—\–ñ', '‘O‰ñ„‰ñ“úŽž'); +//! ƒƒO‚ðŽ‚Á‚Ä‚¢‚é‚È‚ç^‚ð•Ô‚· +function CountLog(Item: TThreadItem): Boolean; +begin + Result := Item.IsLogFile; +end; +//! V’…‚È‚ç^‚ð•Ô‚· +function CountNew(Item: TThreadItem): Boolean; +begin + Result := Item.NewArrival; +end; +//! DAT—Ž‚¿‚È‚ç^‚ð•Ô‚· +function CountDat(Item: TThreadItem): Boolean; +begin + Result := (Item.AgeSage = gasArch); +end; +//! ¶‘¶ƒXƒŒ‚È‚ç^‚ð•Ô‚· +function CountLive(Item: TThreadItem): Boolean; +begin + Result := (Item.AgeSage <> gasArch); +end; + +//! í‚ɐ^ +function CountAll(Item: TThreadItem): Boolean; +begin + Result := True; +end; + + +// BBSID ‚ð—p‚¢‚é 2 ‚¿‚á‚ñ‚Ë‚é‚Ì‚Ý’T‚µo‚µ‚Ü‚· +// BBSID ‚ÌŽg—p‚Í‹É—Í”ð‚¯‚Ä‚­‚¾‚³‚¢B +// ‰Â”\‚ȏꍇ‚Í URL ‚ðŽg—p‚µ‚Ä‚­‚¾‚³‚¢B function BBSsFindBoardFromBBSID( - inBBSID : string + inBBSID : string ) : TBoard; var - i, bound : Integer; + i : Integer; + tmpBoard : TBoard; begin - bound := Length( BBSs ) - 1; - for i := 0 to bound do begin - Result := BBSs[ i ].FindBBSID( inBBSID ); - if Result <> nil then - Exit; - end; - +// Result := BBSs[ 0 ].FindBBSID( inBBSID ); Result := nil; + if Length(BoardGroups) > 0 then begin + for i := BoardGroups[0].Count - 1 downto 0 do begin + tmpBoard := TBoard(BoardGroups[0].Objects[i]); + if tmpBoard.Is2ch then begin + if AnsiCompareStr(tmpBoard.BBSID, inBBSID) = 0 then begin + Result := tmpBoard; + EXIT; + end; + end; + end; + end; end; - +{********************************************** +‚±‚̊֐”‚Í•K‚¸”‚ÌURL‚ÌŒ`Ž®‚Å“n‚µ‚Ä‚­‚¾‚³‚¢B +plugin‚ðŽg—p‚·‚é‚È‚ç‚΁AExtractBoardURL( inURL ) +2ch‚È‚ç‚΁AGikoSys.Get2chThreadURL2BoardURL( inURL ); +‚Å•ÏŠ·‚µ‚Ä‚©‚çŒÄ‚яo‚µ‚Ä‚­‚¾‚³‚¢B +**********************************************} function BBSsFindBoardFromURL( - inURL : string + inURL : string ) : TBoard; var - i, bound : Integer; + i,p : Integer; + accept : TAcceptType; + protocol, host, path, document, port, bookmark : string; begin - - bound := Length( BBSs ) - 1; - for i := 0 to bound do begin - Result := BBSs[ i ].FindBoardFromURL( inURL ); - if Result <> nil then - Exit; - end; - Result := nil; + for i := Length(BoardGroups) - 1 downto 1 do begin + accept := BoardGroups[i].BoardPlugIn.AcceptURL(inURL); + if (accept = atBoard) or (accept = atThread) then begin + if BoardGroups[i].Find(inURL, p) then begin + Result := TBoard(BoardGroups[i].Objects[p]); + Exit; + end else begin + inURL := BoardGroups[i].BoardPlugIn.ExtractBoardURL(inURL); + if BoardGroups[i].Find(inURL, p) then begin + Result := TBoard(BoardGroups[i].Objects[p]); + Exit; + end; + end; + end; + end; + //‚±‚±‚É‚«‚½‚çAplugin‚ðŽg‚í‚È‚¢‚â‚‚ç‚𒲂ׂé + if BoardGroups[0].Find(inURL, p) then + Result := TBoard(BoardGroups[0].Objects[p]); + + if (Result = nil) then begin + GikoSys.ParseURI( inURL, protocol, host, path, document, port, bookmark ); + //ƒzƒXƒg‚ª2ch‚È‚çBBSID‚Å’²‚ׂé + if GikoSys.Is2chHost(host) then begin + Result := BBSsFindBoardFromBBSID(GikoSys.URLToID( inURL )); + end; + end; end; function BBSsFindBoardFromTitle( - inTitle : string + inTitle : string ) : TBoard; var - i, bound : Integer; -begin - - bound := Length( BBSs ) - 1; - for i := 0 to bound do begin - Result := BBSs[ i ].FindBoardFromTitle( inTitle ); - if Result <> nil then - Exit; + i,j : Integer; + tmpBoard : TBoard; +begin + Result := nil; + for i := Length( BBSs ) - 1 downto 0 do begin + for j := BoardGroups[i].Count - 1 downto 0 do begin + tmpBoard := TBoard(BoardGroups[i].Objects[j]); + if ( AnsiCompareStr(tmpBoard.Title, inTitle) = 0) then begin + Result := tmpBoard; + Exit; + end; + end; end; - Result := nil; - end; function BBSsFindThreadFromURL( - inURL : string + const inURL : string ) : TThreadItem; var - i, bound : Integer; -begin - - bound := Length( BBSs ) - 1; - for i := 0 to bound do begin - Result := BBSs[ i ].FindThreadFromURL( inURL ); - if Result <> nil then - Exit; + board : TBoard; + tmpThread : TThreadItem; + boardURL : string; + protocol, host, path, document, port, bookmark : string; + BBSID, BBSKey : string; + i, bi : Integer; +begin + + boardURL := GikoSys.GetThreadURL2BoardURL( inURL ); + board := BBSsFindBoardFromURL( boardURL ); + if board = nil then + Result := nil + else begin + Result := board.FindThreadFromURL( inURL ); + //‚à‚µ‚à2ch‚̔‚Ȃç + if (Result = nil) and (board.Is2ch) then begin + GikoSys.ParseURI( inURL, protocol, host, path, document, port, bookmark ); + GikoSys.Parse2chURL( inURL, path, document, BBSID, BBSKey ); + Result := board.FindThreadFromFileName(BBSKey + '.dat'); + end else if (Result = nil) and not (board.Is2ch) then begin + //ƒvƒ‰ƒOƒCƒ“Œn‚Ì’TõiŽå‚ÉURL‚ª“r’†‚ŕύX‚É‚È‚Á‚½—Þ) + try + bi := Length(BoardGroups) - 1; + for i := 1 to bi do begin + if (BoardGroups[i].BoardPlugIn <> nil) and (Assigned(Pointer(BoardGroups[i].BoardPlugIn.Module))) then begin + if BoardGroups[i].BoardPlugIn.AcceptURL( inURL ) = atThread then begin + tmpThread := TThreadItem.Create( BoardGroups[i].BoardPlugIn, Board, inURL ); + if not board.IsThreadDatRead then begin + GikoSys.ReadSubjectFile( board ); + end; + Result := Board.FindThreadFromFileName( tmpThread.FileName ); + tmpThread.Free; + Break; + end; + end; + end; + except + Result := nil; + end; + end; end; - Result := nil; - +end; +{! +\brief “ÁŽê—p“rBBSíœ +\param bbs íœ‚·‚é“ÁŽê—p“rBBS +} +procedure DestorySpecialBBS( inBBS : TBBS ); +var + sCategory : TCategory; + sBoard : TSpecialBoard; +begin + if inBBS <> nil then begin + sCategory := inBBS.Items[0]; + if sCategory <> nil then begin + sBoard := TSpecialBoard(sCategory.Items[0]); + if sBoard <> nil then begin + sBoard.Modified := False; + sBoard.Clear; + FreeAndNil(sBoard); + end; + end; + FreeAndNil(inBBS); + end; end; (************************************************************************* *‹@”\–¼FTBBSƒRƒ“ƒXƒgƒ‰ƒNƒ^ *Public *************************************************************************) -constructor TBBS.Create(LogFolder: string); +constructor TBBS.Create( boardFilePath : string ); begin + inherited Create; Title := BBS2CH_NAME; - FLogFolder := LogFolder; + FFilePath := boardFilePath; end; (************************************************************************* @@ -504,6 +617,7 @@ var begin for i := Count - 1 downto 0 do Delete(i); + Capacity := Count; end; function TBBS.Find(key: string): TCategory; @@ -511,79 +625,73 @@ begin Result := nil; end; -function TBBS.FindBBSID(BBSID: string): TBoard; +function TBBS.FindBBSID(const BBSID: string): TBoard; var - i: Integer; - Category: TCategory; - Board: TBoard; + i : Integer; begin - Result := nil; - for i := 0 to Count - 1 do begin - Category := Items[i]; - Board := Category.FindBBSID(BBSID); - if Board <> nil then begin - Result := Board; + if not IsBoardFileRead then + GikoSys.ReadBoardFile( Self ); + for i := Count - 1 downto 0 do begin + Result := Items[ i ].FindBBSID(BBSID); + if Result <> nil then Exit; - end; end; + Result := nil; end; //************************************************************************* // ƒ^ƒCƒgƒ‹‚̈ê’v‚·‚锂ð’T‚· //*************************************************************************) -function TBBS.FindBoardFromTitle(Title: string): TBoard; +function TBBS.FindBoardFromTitle(const Title: string): TBoard; var i: Integer; - Category: TCategory; - Board: TBoard; begin - Result := nil; - for i := 0 to Count - 1 do begin - Category := Items[i]; - Board := Category.FindBoardFromTitle(Title); - if Board <> nil then begin - Result := Board; + if not IsBoardFileRead then + GikoSys.ReadBoardFile( Self ); + for i := Count - 1 downto 0 do begin + Result := Items[ i ].FindBoardFromTitle(Title); + if Result <> nil then Exit; - end; end; + Result := nil; end; //************************************************************************* // URL ‚ðŽó‚¯•t‚¯‚锂ð’T‚· //*************************************************************************) -function TBBS.FindBoardFromURL(inURL: string): TBoard; +function TBBS.FindBoardFromURL(const inURL: string): TBoard; var - i: Integer; - Category: TCategory; - Board: TBoard; + i : Integer; begin - Result := nil; - for i := 0 to Count - 1 do begin - Category := Items[i]; - Board := Category.FindBoardFromURL(inURL); - if Board <> nil then begin - Result := Board; + if not IsBoardFileRead then + GikoSys.ReadBoardFile( Self ); + for i := Count - 1 downto 0 do begin + Result := Items[ i ].FindBoardFromURL( inURL ); + if Result <> nil then Exit; - end; end; + Result := nil; end; //************************************************************************* // URL ‚ðŽó‚¯•t‚¯‚éƒXƒŒƒbƒh‚ð’T‚· //*************************************************************************) -function TBBS.FindThreadFromURL(inURL: string): TThreadItem; +function TBBS.FindThreadFromURL(const inURL: string): TThreadItem; var - i: Integer; + board : TBoard; + boardURL : string; begin - for i := 0 to Count - 1 do begin - Result := Items[ i ].FindThreadFromURL( inURL ); - if Result <> nil then - Exit; - end; - Result := nil; + + boardURL := GikoSys.GetThreadURL2BoardURL( inURL ); + board := FindBoardFromURL( boardURL ); + if board = nil then + Result := nil + else + Result := board.FindThreadFromURL( inURL ); + end; -function TBBS.FindThreadItem(BBSID: string; FileName: string): TThreadItem; +function TBBS.FindThreadItem(const BBSID, FileName: string): TThreadItem; var Board: TBoard; begin @@ -591,23 +699,29 @@ begin Board := FindBBSID(BBSID); if Board = nil then Exit; - Result := Board.Find(FileName); + Result := Board.FindThreadFromFileName(FileName); end; -(************************************************************************* - *ƒƒOƒtƒHƒ‹ƒ_Žæ“¾ - * - *************************************************************************) -function TBBS.GetLogFolder: string; +function TBBS.FindCategoryFromTitle(const inTitle : string ) : TCategory; +var + i : Integer; begin - Result := IncludeTrailingPathDelimiter(FLogFolder) - + BBS2CH_LOG_FOLDER + PATH_DELIM; + + for i := Count - 1 downto 0 do begin + if AnsiCompareStr(Items[ i ].Title, inTitle) = 0 then begin + Result := Items[ i ]; + Exit; + end; + end; + + Result := nil; + end; procedure TBBS.SetSelectText(s: string); begin FSelectText := s; - ShortSelectText := GikoSys.ZenToHan(s); + ShortSelectText := CustomStringReplace(ZenToHan(s), ' ', ''); end; {class function TBBS.GetColumnName(Index: Integer): string; @@ -625,6 +739,11 @@ end;} //=================== constructor TCategory.Create; begin + inherited; + + Duplicates := dupIgnore; + CaseSensitive := False; + //Sorted := True; end; destructor TCategory.Destroy; @@ -635,26 +754,24 @@ end; function TCategory.GetBoard(index: integer): TBoard; begin - Result := TBoard(inherited Items[index]); + Result := TBoard( Objects[index] ); end; procedure TCategory.SetBoard(index: integer; value: TBoard); begin - inherited Items[index] := value; + Objects[index] := value; + Strings[index] := value.URL end; function TCategory.Add(item: TBoard): integer; begin Item.ParentCategory := self; - Result := inherited Add(item); + Result := AddObject( item.URL, item ); end; procedure TCategory.Delete(index: integer); begin - if Items[index] <> nil then - TBoard(Items[index]).Free; - Items[index] := nil; - inherited Delete(index); + inherited Delete(index); end; procedure TCategory.Clear; @@ -663,72 +780,72 @@ var begin for i := Count - 1 downto 0 do Delete(i); + Capacity := Count; end; -function TCategory.FindName(key: string): TBoard; +function TCategory.FindName(const key: string): TBoard; begin Result := nil; end; -function TCategory.FindBBSID(BBSID: string): TBoard; +function TCategory.FindBBSID(const BBSID: string): TBoard; var - i: integer; + i : integer; begin - Result := nil; - for i := 0 to Count - 1 do begin - if Items[i].FBBSID = BBSID then begin + for i := Count - 1 downto 0 do begin + if AnsiCompareStr(Items[i].FBBSID, BBSID) = 0 then begin Result := Items[i]; Exit; end; end; + Result := nil; end; //************************************************************************* // ƒ^ƒCƒgƒ‹‚̈ê’v‚·‚锂ð’T‚· //*************************************************************************) -function TCategory.FindBoardFromTitle(Title: string): TBoard; +function TCategory.FindBoardFromTitle(const Title: string): TBoard; var - i: integer; + i : integer; begin - Result := nil; - for i := 0 to Count - 1 do begin - if Items[i].FTitle = Title then begin + for i := Count - 1 downto 0 do begin + if AnsiCompareStr(Items[i].FTitle, Title) = 0 then begin Result := Items[i]; Exit; end; end; + Result := nil; end; //************************************************************************* // URL ‚ðŽó‚¯•t‚¯‚锂ð’T‚· //*************************************************************************) -function TCategory.FindBoardFromURL(inURL: string): TBoard; +function TCategory.FindBoardFromURL(const inURL: string): TBoard; var - i: integer; + i : Integer; begin - Result := nil; - for i := 0 to Count - 1 do begin - if Pos( Items[i].URL, inURL ) = 1 then begin - Result := Items[i]; - Exit; - end; - end; + i := IndexOf( inURL ); + if i >= 0 then + Result := TBoard( Objects[ i ] ) + else + Result := nil; end; //************************************************************************* // URL ‚ðŽó‚¯•t‚¯‚éƒXƒŒƒbƒh‚ð’T‚· //*************************************************************************) -function TCategory.FindThreadFromURL(inURL: string): TThreadItem; +function TCategory.FindThreadFromURL(const inURL: string): TThreadItem; var - i : Integer; + board : TBoard; + boardURL : string; begin - for i := 0 to Count - 1 do begin - Result := Items[ i ].FindThreadFromURL( inURL ); - if Result <> nil then - Exit; - end; - Result := nil; + boardURL := GikoSys.GetThreadURL2BoardURL( inURL ); + board := FindBoardFromURL( boardURL ); + if board = nil then + Result := nil + else + Result := board.FindThreadFromURL( inURL ); end; @@ -766,8 +883,12 @@ end;} //=================== //TBoard //=================== -constructor TBoard.Create; +procedure TBoard.Init; begin + Duplicates := dupIgnore; + CaseSensitive := False; + //Sorted := True; + FNo := 0; FTitle := ''; FBBSID := ''; @@ -778,12 +899,11 @@ begin FLastGetTime := ZERO_DATE; FIsThreadDatRead := False; FUnRead := 0; + FMultiplicity := 0; // FListStyle := vsReport; // FItemNoVisible := True; FUpdate := True; - - FBoardPlugIn := nil; end; // ************************************************************************* @@ -791,19 +911,38 @@ end; // ************************************************************************* constructor TBoard.Create( inPlugIn : TBoardPlugIn; - inURL : string = '' + inURL : string ); +var + protocol, host, path, document, port, bookmark : string; begin - Create; + inherited Create; + Init; FBoardPlugIn := inPlugIn; URL := inURL; BBSID := GikoSys.UrlToID( inURL ); - // ƒvƒ‰ƒOƒCƒ“‚É TBoardItem ‚ªì¬‚³‚ꂽ‚±‚Æ‚ð“`‚¦‚é - if inPlugIn <> nil then + if inPlugIn = nil then begin + // subject.txt ‚Ì•Û‘¶ƒpƒX‚ðÝ’è + GikoSys.ParseURI( inURL, protocol, host, path, document, port, bookmark ); + if GikoSys.Is2chHost( host ) then begin + Self.Is2ch := True; + FilePath := + GikoSys.Setting.LogFolderP + + BBS2CH_LOG_FOLDER + PATH_DELIM + BBSID + PATH_DELIM + SUBJECT_FILENAME + end else begin + Self.Is2ch := False; + FilePath := + GikoSys.Setting.LogFolderP + + EXTERNAL_LOG_FOLDER + PATH_DELIM + host + PATH_DELIM + BBSID + PATH_DELIM + SUBJECT_FILENAME + end; + end else begin + // ƒvƒ‰ƒOƒCƒ“‚É TBoardItem ‚ªì¬‚³‚ꂽ‚±‚Æ‚ð“`‚¦‚é inPlugIn.CreateBoardItem( DWORD( Self ) ); + //Self.Is2ch := False; //plugin‘¤‚Őݒ肷‚é + end; end; @@ -848,24 +987,26 @@ end; function TBoard.GetThreadItem(index: integer): TThreadItem; begin - Result := TThreadItem(inherited Items[index]); + Result := TThreadItem( Objects[index] ); end; procedure TBoard.SetThreadItem(index: integer; value: TThreadItem); begin - inherited Items[index] := value; + Objects[index] := value; + Strings[index] := value.URL; end; function TBoard.Add(Item: TThreadItem): Integer; begin Item.ParentBoard := Self; - Result := inherited Add(Item); + Result := inherited AddObject(Item.URL, Item); end; procedure TBoard.Insert(Index: Integer; Item: TThreadItem); begin Item.ParentBoard := Self; - inherited Insert(Index, Item); + inherited InsertObject(Index, Item.URL, Item); + end; //Index‚ÅŽw’肳‚ꂽƒXƒŒƒbƒhƒIƒuƒWƒFƒNƒg‚ð”jŠü @@ -873,7 +1014,6 @@ procedure TBoard.Delete(index: Integer); begin if Items[index] <> nil then TThreadItem(Items[index]).Free; - Items[index] := nil; inherited Delete(index); end; @@ -890,22 +1030,23 @@ begin // FUnRead := 0; for i := Count - 1 downto 0 do Delete(i); + Capacity := Count; end; -function TBoard.Find(ItemFileName: string): TThreadItem; +function TBoard.FindThreadFromFileName(const ItemFileName: string): TThreadItem; var i: integer; begin Result := nil; for i := 0 to Count - 1 do begin - if Items[i].FileName = ItemFileName then begin + if AnsiCompareStr(Items[i].FileName, ItemFileName) = 0 then begin Result := Items[i]; Exit; end; end; end; -function TBoard.GetIndex(ItemFileName: string): Integer; +function TBoard.GetIndexFromFileName(const ItemFileName: string): Integer; var i: integer; begin @@ -918,34 +1059,36 @@ begin end; end; -function TBoard.GetIndexFromURL(URL: string): Integer; +function TBoard.GetIndexFromURL(const URL: string; reverse : Boolean = False): Integer; var - i: integer; + i : Integer; begin - Result := -1; - for i := 0 to Count - 1 do begin - if Items[i].URL = URL then begin - Result := i; - Exit; + if not reverse then + Result := IndexOf( URL ) + else begin + Result := -1; + for i := Self.Count - 1 downto 0 do begin + if Strings[i] = URL then begin + Result := i; + break; + end; end; end; end; -function TBoard.FindThreadFromURL( inURL : string ) : TThreadItem; +function TBoard.FindThreadFromURL(const inURL : string ) : TThreadItem; var i : Integer; begin if not IsThreadDatRead then GikoSys.ReadSubjectFile( Self ); - - for i := 0 to Count - 1 do begin - if Pos( Items[ i ].URL, inURL ) = 1 then begin - Result := Items[ i ]; - Exit; - end; - end; - Result := nil; + + i := IndexOf( inURL ); + if i >= 0 then + Result := TThreadItem( Objects[ i ] ) + else + Result := nil; end; @@ -967,29 +1110,44 @@ procedure TBoard.LoadSettings; var ini: TMemIniFile; FileName: string; + tmp: string; begin if Length( FilePath ) > 0 then FileName := ExtractFilePath( FilePath ) + FOLDER_INI_FILENAME else - FileName := ParentCategory.ParenTBBS.GetLogFolder - + BBSID + PATH_DELIM + FOLDER_INI_FILENAME; + FileName := GikoSys.Setting.LogFolderP + + BBS2CH_LOG_FOLDER + PATH_DELIM + BBSID + PATH_DELIM + FOLDER_INI_FILENAME; if not FileExists(FileName) then Exit; ini := TMemIniFile.Create(FileName); try // Round := ini.ReadBool('Status', 'Round', False); - FRoundDate := ini.ReadDateTime('Status', 'RoundDate', ZERO_DATE); - FLastModified := ini.ReadDateTime('Status', 'LastModified', ZERO_DATE); - FLastGetTime := ini.ReadDateTime('Status', 'LastGetTime', ZERO_DATE); + tmp := ini.ReadString('Status', 'RoundDate', DateTimeToStr(ZERO_DATE)); + FRoundDate := ConvertDateTimeString(tmp); + tmp := ini.ReadString('Status', 'LastModified', DateTimeToStr(ZERO_DATE)); + FLastModified := ConvertDateTimeString(tmp); + tmp := ini.ReadString('Status', 'LastGetTime', DateTimeToStr(ZERO_DATE)); + FLastGetTime := ConvertDateTimeString(tmp); + + tmp := ini.ReadString('BoardInformation', 'SETTINGTXTTime', DateTimeToStr(ZERO_DATE)); + FSETTINGTXTTime := ConvertDateTimeString(tmp); + tmp := ini.ReadString('BoardInformation', 'HEADTXTTime', DateTimeToStr(ZERO_DATE)); + FHEADTXTTime := ConvertDateTimeString(tmp); + + FIsSETTINGTXT := ini.ReadBool('BoardInformation', 'IsSETTINGTXT', false); + FIsHEADTXT := ini.ReadBool('BoardInformation', 'IsHEADTXT', false); + FTitlePictureURL := ini.ReadString('BoardInformation', 'TitlePictureURL', ''); + FUnRead := ini.ReadInteger('Status', 'UnRead', 0); FSPID := ini.ReadString('Cookie', 'SPID', ''); FPON := ini.ReadString('Cookie', 'PON', ''); + FCookie := ini.ReadString('Cookie', 'Cookie', ''); + tmp := ini.ReadString('Cookie', 'Expires', DateTimeToStr(ZERO_DATE)); + FExpires := ConvertDateTimeString(tmp); FKotehanName := ini.ReadString('Kotehan', 'Name', ''); FKotehanMail := ini.ReadString('Kotehan', 'Mail', ''); -// ListStyle := TViewStyle(Ord(ini.ReadInteger('Status', 'ListStyle', 3))); -// ItemNoVisible := ini.ReadBool('Status', 'ItemNoVisible', True); -// ViewType := TGikoViewType(Ord(ini.ReadInteger('Status', 'ViewType', 0))); + if UnRead < 0 then UnRead := 0; finally @@ -1005,8 +1163,8 @@ begin if Length( FilePath ) > 0 then FileName := ExtractFilePath( FilePath ) else - FileName := ParentCategory.ParenTBBS.GetLogFolder - + BBSID + PATH_DELIM; + FileName := GikoSys.Setting.LogFolderP + + BBS2CH_LOG_FOLDER + PATH_DELIM + BBSID + PATH_DELIM; if not GikoSys.DirectoryExistsEx(FileName) then GikoSys.ForceDirectoriesEx(FileName); FileName := FileName + FOLDER_INI_FILENAME; @@ -1021,8 +1179,17 @@ begin ini.WriteInteger('Status', 'UnRead', FUnRead); ini.WriteString('Cookie', 'SPID', FSPID); ini.WriteString('Cookie', 'PON', FPON); + ini.WriteString('Cookie', 'Cookie', FCookie); + ini.WriteDateTime('Cookie', 'Expires', FExpires); ini.WriteString('Kotehan', 'Name', FKotehanName); ini.WriteString('Kotehan', 'Mail', FKotehanMail); + + ini.WriteDateTime('BoardInformation', 'SETTINGTXTTime', FSETTINGTXTTime); + ini.WriteDateTime('BoardInformation', 'HEADTXTTime', FHEADTXTTime); + + ini.WriteBool('BoardInformation', 'IsSETTINGTXT', FIsSETTINGTXT); + ini.WriteBool('BoardInformation', 'IsHEADTXT', FIsHEADTXT); + ini.WriteString('BoardInformation', 'TitlePictureURL', FTitlePictureURL); // ini.WriteInteger('Status', 'ListStyle', Ord(ListStyle)); // ini.WriteBool('Status', 'ItemNoVisible', ItemNoVisible); // ini.WriteInteger('Status', 'ViewType', Ord(ViewType)); @@ -1031,41 +1198,131 @@ begin ini.Free; end; end; - -// ƒTƒuƒWƒFƒNƒgURLŽæ“¾ +//‚Æ‚«‚½‚Ü2003 02 08 0:32:13‚±‚ñ‚ÈŒ`Ž®‚Ì“ú•t‚ª‚ ‚é‚Ì‚Å‚»‚ê‚ð +// 2003/02/08 0:32:13‚É•ÏŠ·‚·‚é +function ConvertDateTimeString( inDateTimeString : string) : TDateTime; +const + ZERO_DATE_STRING : string = '1970/01/01 0:00:00'; +var + i : Integer; + y: Integer; + m: Integer; + d: Integer; + hour: Integer; + min: Integer; + sec: Integer; +begin + if inDateTimeString = '' then + inDateTimeString := ZERO_DATE_STRING; + + if ( AnsiPos('/', inDateTimeString ) = 0 ) and + ( AnsiCompareStr( DateTimeToStr(ZERO_DATE), inDateTimeString) <> 0 ) then begin + for i := 0 to 1 do begin + Insert('/',inDateTimeString, AnsiPos(' ', inDateTimeString) + 1 ); + Delete(inDateTimeString, AnsiPos(' ', inDateTimeString), 1); + end; + end; + try + Result := StrToDateTime( inDateTimeString ); + except + if( inDateTimeString[5] = '/' ) and ( inDateTimeString[8] = '/' ) then begin + y := StrToIntDef( Copy(inDateTimeString, 1, 4), 1970 ); + m := StrToIntDef( Copy(inDateTimeString, 6, 2), 1 ); + d := StrToIntDef( Copy(inDateTimeString, 9, 2), 1 ); + hour := 0; min := 0; sec := 0; + + if Length(inDateTimeString) > 11 then begin + if( inDateTimeString[13] = ':' ) and ( inDateTimeString[16] = ':' ) then begin + hour := StrToIntDef( Copy(inDateTimeString, 12, 1), 0 ); + min := StrToIntDef( Copy(inDateTimeString, 14, 2), 0 ); + sec := StrToIntDef( Copy(inDateTimeString, 17, 2), 0 ); + end else if( inDateTimeString[14] = ':' ) and ( inDateTimeString[17] = ':' ) then begin + hour := StrToIntDef( Copy(inDateTimeString, 12, 2), 0 ); + min := StrToIntDef( Copy(inDateTimeString, 15, 2), 0 ); + sec := StrToIntDef( Copy(inDateTimeString, 18, 2), 0 ); + end; + end; + try + Result := EncodeDateTime(y ,m, d, hour, min, sec, 0); + except + Result := ZERO_DATE; + end; + end else + Result := ZERO_DATE; + end; + + + // Result := inDateTimeString; +end; +//! ƒTƒuƒWƒFƒNƒgURLŽæ“¾ function TBoard.GetReadCgiURL: string; begin - //Result := URL + SUBJECT_FILENAME; - //Result := GikoSys.UrlToServer(URL) - // + 'test/read.cgi/' + BBSID + '/?raw=0.0'; Result := URL + SUBJECT_FILENAME; end; -// ƒTƒuƒWƒFƒNƒgƒtƒ@ƒCƒ‹–¼Žæ“¾iƒpƒX{ƒtƒ@ƒCƒ‹–¼j +//! ƒTƒuƒWƒFƒNƒgƒtƒ@ƒCƒ‹–¼Žæ“¾iƒpƒX{ƒtƒ@ƒCƒ‹–¼j function TBoard.GetSubjectFileName: string; begin if Length( FilePath ) > 0 then Result := FilePath else - Result := ParentCategory.ParenTBBS.GetLogFolder - + BBSID + PATH_DELIM + SUBJECT_FILENAME; + Result := GikoSys.Setting.LogFolderP + + BBS2CH_LOG_FOLDER + PATH_DELIM + BBSID + PATH_DELIM + SUBJECT_FILENAME; end; -// ƒCƒ“ƒfƒbƒNƒXƒtƒ@ƒCƒ‹–¼(folder.idx)Žæ“¾iƒpƒX{ƒtƒ@ƒCƒ‹–¼j +//! ƒCƒ“ƒfƒbƒNƒXƒtƒ@ƒCƒ‹–¼(folder.idx)Žæ“¾iƒpƒX{ƒtƒ@ƒCƒ‹–¼j function TBoard.GetFolderIndexFileName: string; begin if Length( FilePath ) > 0 then Result := ExtractFilePath( FilePath ) + FOLDER_INDEX_FILENAME else - Result := ParentCategory.ParenTBBS.GetLogFolder - + BBSID + PATH_DELIM + FOLDER_INDEX_FILENAME; + Result := GikoSys.Setting.LogFolderP + + BBS2CH_LOG_FOLDER + PATH_DELIM + BBSID + PATH_DELIM + FOLDER_INDEX_FILENAME; +end; +//! SETTING.TXT‚̃tƒ@ƒCƒ‹–¼Žæ“¾ +function TBoard.GetSETTINGTXTFileName: string; +begin + if Length( FilePath ) > 0 then + Result := ExtractFilePath( FilePath ) + SETTINGTXT_FILENAME + else + Result := GikoSys.Setting.LogFolderP + + BBS2CH_LOG_FOLDER + PATH_DELIM + BBSID + PATH_DELIM + SETTINGTXT_FILENAME; +end; + +function TBoard.GETHEADTXTFileName: string; +begin + if Length( FilePath ) > 0 then + Result := ExtractFilePath( FilePath ) + HEADTXT_FILENAME + else + Result := GikoSys.Setting.LogFolderP + + BBS2CH_LOG_FOLDER + PATH_DELIM + BBSID + PATH_DELIM + HEADTXT_FILENAME; +end; +function TBoard.GetTitlePictureFileName: string; +var + tmpName: string; +begin + if FTitlePictureURL = '' then + Result := '' + else begin + tmpName := Copy(FTitlePictureURL, LastDelimiter('/', FTitlePictureURL) + 1, Length(FTitlePictureURL)); + if Length( FilePath ) > 0 then + Result := ExtractFilePath( FilePath ) + tmpName + else + Result := GikoSys.Setting.LogFolderP + + BBS2CH_LOG_FOLDER + PATH_DELIM + BBSID + PATH_DELIM + tmpName; + end; end; // ƒXƒŒ—§‚Ä‘—MURL function TBoard.GetSendURL: string; begin - Result := GikoSys.UrlToServer(URL) + 'test/subbbs.cgi'; + Result := GikoSys.UrlToServer(URL); + if Self.Is2ch then + Result := Result + 'test/bbs.cgi' + else + Result := Result + 'test/subbbs.cgi'; + end; procedure TBoard.SetRound(b: Boolean); @@ -1128,175 +1385,114 @@ begin if FUpdate then FModified := True; end; - -function TBoard.GetNewThreadCount: Integer; +//! func‚ÌðŒ‚Éˆê’v‚·‚éƒXƒŒƒbƒh‚̐”‚ð•Ô‚· +function TBoard.GetThreadCount(func :TThreadCount ): Integer; var i: Integer; begin Result := 0; - if Length( ParentCategory.ParenTBBS.ShortSelectText ) = 0 then - begin - for i := 0 to Count - 1 do begin - if Items[i].NewArrival then - inc(Result); - end; - end else begin - for i := 0 to Count - 1 do begin - if Items[i].NewArrival then - begin - if Items[i].ShortTitle = '' then - Items[i].ShortTitle := GikoSys.ZenToHan(Items[i].Title); - if AnsiPos(ParentCategory.ParenTBBS.ShortSelectText, Items[i].ShortTitle) <> 0 then - inc(Result); - end; - end; - end; + if Length( ParentCategory.ParenTBBS.ShortSelectText ) = 0 then + begin + for i := 0 to Count - 1 do begin + if func(Items[i]) then + inc(Result); + end; + end else begin + for i := 0 to Count - 1 do begin + if func(Items[i]) then + begin + if Items[i].ShortTitle = '' then + Items[i].ShortTitle := CustomStringReplace(ZenToHan(Items[i].Title), ' ', ''); + if AnsiPos(ParentCategory.ParenTBBS.ShortSelectText, Items[i].ShortTitle) <> 0 then + inc(Result); + end; + end; + end; end; - +//! V’…ƒXƒŒƒbƒh‚̐”‚ðŽæ“¾‚·‚é +function TBoard.GetNewThreadCount: Integer; +begin + Result := GetThreadCount(CountNew); +end; +//! ƒƒO—L‚èƒXƒŒƒbƒh‚̐”‚ðŽæ“¾‚·‚é function TBoard.GetLogThreadCount: Integer; -var - i: Integer; begin - Result := 0; - if Length( ParentCategory.ParenTBBS.ShortSelectText ) = 0 then - begin - for i := 0 to Count - 1 do begin - if Items[i].IsLogFile then - inc(Result); - end; - end else begin - for i := 0 to Count - 1 do begin - if Items[i].IsLogFile then - begin - if Items[i].ShortTitle = '' then - Items[i].ShortTitle := GikoSys.ZenToHan(Items[i].Title); - if AnsiPos(ParentCategory.ParenTBBS.ShortSelectText, Items[i].ShortTitle) <> 0 then - inc(Result); - end; - end; - end; + Result := GetThreadCount(CountLog); end; - +//! iž‚ÝðŒ‚Éˆê’v‚·‚éƒXƒŒƒbƒh‚̐”‚ðŽæ“¾‚·‚é function TBoard.GetUserThreadCount: Integer; -var - i: Integer; begin - Result := 0; - if Length( ParentCategory.ParenTBBS.ShortSelectText ) = 0 then - Result := Count - else - for i := 0 to Count - 1 do begin - if Items[i].ShortTitle = '' then - Items[i].ShortTitle := GikoSys.ZenToHan(Items[i].Title); - if AnsiPos(ParentCategory.ParenTBBS.ShortSelectText, Items[i].ShortTitle) <> 0 then - inc(Result); - end; + Result := GetThreadCount(CountAll); end; - -function TBoard.GetNewThread(Index: Integer): TThreadItem; +//! DAT—Ž‚¿ƒXƒŒƒbƒh‚̐”‚ðŽæ“¾‚·‚é +function TBoard.GetArchiveThreadCount: Integer; +begin + Result := GetThreadCount(CountDat); +end; +//! ¶‘¶ƒXƒŒƒbƒh‚̐”‚ðŽæ“¾‚·‚é +function TBoard.GetLiveThreadCount: Integer; +begin + Result := GetThreadCount(CountLive); +end; +//! func‚ÌðŒ‚É“K‡‚·‚éIndex”Ԗڂ̃XƒŒƒbƒh‚ðŽæ“¾‚·‚é +function TBoard.GetThread(func :TThreadCount;const Index :Integer ): TThreadItem; var i: Integer; Cnt: Integer; begin Result := nil; Cnt := 0; - if Length( ParentCategory.ParenTBBS.ShortSelectText ) = 0 then - begin - for i := 0 to Count - 1 do begin - if Items[i].NewArrival then - begin - if Index = Cnt then begin - Result := Items[i]; - Exit; - end; - inc(Cnt); - end; - end; - end else begin - for i := 0 to Count - 1 do begin - if Items[i].NewArrival then - begin - if Items[i].ShortTitle = '' then - Items[i].ShortTitle := GikoSys.ZenToHan(Items[i].Title); - if AnsiPos(ParentCategory.ParenTBBS.ShortSelectText, Items[i].ShortTitle) <> 0 then begin - if Index = Cnt then begin - Result := Items[i]; - Exit; - end; - inc(Cnt); - end; - end; + if Length( ParentCategory.ParenTBBS.ShortSelectText ) = 0 then + begin + for i := 0 to Count - 1 do begin + if func(Items[i]) then begin + if Index = Cnt then begin + Result := Items[i]; + Exit; + end; + inc(Cnt); + end; + end; + end else begin + for i := 0 to Count - 1 do begin + if func(Items[i]) then begin + if Length(Items[i].ShortTitle) = 0 then + Items[i].ShortTitle := CustomStringReplace(ZenToHan(Items[i].Title), ' ', ''); + if AnsiPos(ParentCategory.ParenTBBS.ShortSelectText, Items[i].ShortTitle) <> 0 then begin + if Index = Cnt then begin + Result := Items[i]; + Exit; end; + inc(Cnt); end; + end; + end; + end; end; - +//! DAT—Ž‚¿ƒXƒŒƒbƒh‚ÅIndex”Ԗڂ̃XƒŒƒbƒh‚ðŽæ“¾‚·‚é +function TBoard.GetArchiveThread(Index: Integer): TThreadItem; +begin + Result := GetThread(CountDat, Index); +end; +//! ¶‘¶ƒXƒŒƒbƒh‚ÅIndex”Ԗڂ̃XƒŒƒbƒh‚ðŽæ“¾‚·‚é +function TBoard.GetLiveThread(Index: Integer): TThreadItem; +begin + Result := GetThread(CountLive, Index); +end; +//! V’…ƒXƒŒƒbƒh‚ÅIndex”Ԗڂ̃XƒŒƒbƒh‚ðŽæ“¾‚·‚é +function TBoard.GetNewThread(Index: Integer): TThreadItem; +begin + Result := GetThread(CountNew, Index); +end; +//! Log‚ ‚èƒXƒŒƒbƒh‚ÌIndex”Ԗڂ̃XƒŒƒbƒh‚ðŽæ“¾‚·‚é function TBoard.GetLogThread(Index: Integer): TThreadItem; -var - i: Integer; - Cnt: Integer; begin - Cnt := 0; - if Length( ParentCategory.ParenTBBS.ShortSelectText ) = 0 then - begin - for i := 0 to Count - 1 do begin - if Items[i].IsLogFile then - begin - if Index = Cnt then begin - Result := Items[i]; - Exit; - end; - inc(Cnt); - end; - end; - end else begin - for i := 0 to Count - 1 do begin - if Items[i].IsLogFile then - begin - if Items[i].ShortTitle = '' then - Items[i].ShortTitle := GikoSys.ZenToHan(Items[i].Title); - if AnsiPos(ParentCategory.ParenTBBS.ShortSelectText, Items[i].ShortTitle) <> 0 then begin - if Index = Cnt then begin - Result := Items[i]; - Exit; - end; - inc(Cnt); - end; - end; - end; - end; - Result := nil; + Result := GetThread(CountLog, Index); end; - +//! iž‚Ý‚ÅIndex”Ԗڂ̃XƒŒƒbƒh‚ðŽæ“¾‚·‚é function TBoard.GetUserThread(Index: Integer): TThreadItem; -var - i: Integer; - Cnt: Integer; begin - Result := nil; - Cnt := 0; - if Length( ParentCategory.ParenTBBS.ShortSelectText ) = 0 then - begin - for i := 0 to Count - 1 do begin - if Index = Cnt then - begin - Result := Items[ i ]; - Exit; - end; - inc( Cnt ); - end; - end else begin - for i := 0 to Count - 1 do begin - if Items[i].ShortTitle = '' then - Items[i].ShortTitle := GikoSys.ZenToHan(Items[i].Title); - if AnsiPos(ParentCategory.ParenTBBS.ShortSelectText, Items[i].ShortTitle) <> 0 then begin - if Index = Cnt then begin - Result := Items[i]; - Exit; - end; - inc(Cnt); - end; - end; - end; + Result := GetThread(CountAll, Index); end; procedure TBoard.BeginUpdate; @@ -1309,18 +1505,8 @@ begin FUpdate := True; end; -{class function TBoard.GetColumnName(Index: Integer): string; -begin - Result := COLUMN_THREADITEM[Index]; -end; - -class function TBoard.GetColumnCount: Integer; -begin - Result := Length(COLUMN_THREADITEM); -end;} - //constructor TThreadItem.Create(AOwner: TComponent); -constructor TThreadItem.Create; +procedure TThreadItem.Init; begin FNo := 0; FFileName := ''; @@ -1340,61 +1526,87 @@ begin FUpdate := True; FURL := ''; - FBoardPlugIn := nil; + FJumpAddress := 0; end; // ************************************************************************* // ŠO•””ƒvƒ‰ƒOƒCƒ“‚ðŽw’肵‚½ƒRƒ“ƒXƒgƒ‰ƒNƒ^ // ************************************************************************* constructor TThreadItem.Create( - inPlugIn : TBoardPlugIn; - inURL : string = '' + const inPlugIn : TBoardPlugIn; + const inBoard : TBoard; + inURL : string ); -begin - - Create; - - FBoardPlugIn := inPlugIn; - URL := inURL; - - // ƒvƒ‰ƒOƒCƒ“‚É TThreadItem ‚ªì¬‚³‚ꂽ‚±‚Æ‚ð“`‚¦‚é - if inPlugIn <> nil then +var + foundPos : Integer; + protocol, host, path, document, port, bookmark : string; + BBSID, BBSKey : string; +const + READ_PATH = '/test/read.cgi'; +begin + + inherited Create; + Init; + FParentBoard := inBoard; + //FBoardPlugIn := inPlugIn; + URL := inURL; + + if inPlugIn = nil then begin + foundPos := Pos( READ_PATH, inURL ); + if foundPos > 0 then begin + // dat ‚Ì•Û‘¶ƒpƒX‚ðÝ’è + GikoSys.ParseURI( inURL, protocol, host, path, document, port, bookmark ); + GikoSys.Parse2chURL( inURL, path, document, BBSID, BBSKey ); + FileName := BBSKey + '.dat'; + IsLogFile := FileExists( FilePath ); + URL := GikoSys.Get2chBrowsableThreadURL( inURL ); + end; + end else begin + // ƒvƒ‰ƒOƒCƒ“‚É TThreadItem ‚ªì¬‚³‚ꂽ‚±‚Æ‚ð“`‚¦‚é inPlugIn.CreateThreadItem( DWORD( Self ) ); + end; end; - // ************************************************************************* -// ƒfƒXƒgƒ‰ƒNƒ^ +// ŠO•””ƒvƒ‰ƒOƒCƒ“‚ðŽw’肵‚½ƒRƒ“ƒXƒgƒ‰ƒNƒ^ Log—L‚è‚©‚Ç‚¤‚©”»’fÏ‚Ý +// FileName‚àŽæ“¾Ï‚݁@¨@ReadSubject—p // ************************************************************************* -destructor TThreadItem.Destroy; +constructor TThreadItem.Create( + const inPlugIn : TBoardPlugIn; + const inBoard : TBoard; + inURL : string; + inExist: Boolean; + const inFilename: string +); begin - // ƒvƒ‰ƒOƒCƒ“‚É TThreadItem ‚ª”jŠü‚³‚ꂽ‚±‚Æ‚ð“`‚¦‚é - if IsBoardPlugInAvailable then - FBoardPlugIn.DisposeThreadItem( DWORD( Self ) ); + inherited Create; + Init; + FParentBoard := inBoard; + URL := inURL; - inherited; + if inPlugIn = nil then begin + // dat ‚Ì•Û‘¶ƒpƒX‚ðÝ’è + FileName := inFilename; + IsLogFile := inExist; + URL := GikoSys.Get2chBrowsableThreadURL( inURL ); + end else begin + // ƒvƒ‰ƒOƒCƒ“‚É TThreadItem ‚ªì¬‚³‚ꂽ‚±‚Æ‚ð“`‚¦‚é + inPlugIn.CreateThreadItem( DWORD( Self ) ); + end; end; - // ************************************************************************* -// ŠO•””ƒvƒ‰ƒOƒCƒ“‚ªŽg—p‰Â”\‚© +// ƒfƒXƒgƒ‰ƒNƒ^ // ************************************************************************* -function TThreadItem.IsBoardPlugInAvailable : Boolean; +destructor TThreadItem.Destroy; begin - repeat - if BoardPlugIn = nil then - Break; - - if not Assigned( Pointer( BoardPlugIn.Module ) ) then - Break; - - Result := True; - Exit; - until True; + // ƒvƒ‰ƒOƒCƒ“‚É TThreadItem ‚ª”jŠü‚³‚ꂽ‚±‚Æ‚ð“`‚¦‚é + if Self.ParentBoard.IsBoardPlugInAvailable then + Self.ParentBoard.BoardPlugIn.DisposeThreadItem( DWORD( Self ) ); - Result := False; + inherited; end; @@ -1461,31 +1673,8 @@ begin end; end; -{function TThreadItem.GetOldDatgzURL: string; -var - Protocol, Host, Path, Document, Port, Bookmark: string; -begin - Result := Format('%s%s/%.3s/%s.gz', [ParentBoard.URL, - 'kako', - FileName, - FileName]); - if FDownloadHost <> '' then begin - ParseURI(Result, Protocol, Host, Path, Document, Port, Bookmark); - Result := Format('%s://%s%s%s', [Protocol, - DownloadHost, - Path, - Document]); - - end; -end;} - -function TThreadItem.GetOfflawCgiURL(SessionID: string): string; -//var -// Protocol, Host, Path, Document, Port, Bookmark: string; +function TThreadItem.GetOfflawCgiURL(const SessionID: string): string; begin -// Result := GikoSys.UrlToServer(ParentBoard.URL) -// + 'test/offlaw.cgi/' + ParentBoard.BBSID + '/' -// + ChangeFileExt(FileName, '') + '/?raw=.0&sid=' + HttpEncode(SessionID); if FDownloadHost = '' then begin Result := GikoSys.UrlToServer(ParentBoard.URL) + 'test/offlaw.cgi/' + ParentBoard.BBSID + '/' @@ -1496,10 +1685,6 @@ begin Result := 'http://' + FDownloadHost + '/test/offlaw.cgi/' + ParentBoard.BBSID + '/' + ChangeFileExt(FileName, '') + '/?raw=.0&sid=' + HttpEncode(SessionID); -// Result := Format('%s://%s%s%s', [Protocol, -// DownloadHost, -// Path, -// Document]); end; end; @@ -1510,10 +1695,20 @@ begin end; procedure TThreadItem.DeleteLogFile; +var + tmpFileName: String; begin + ParentBoard.BeginUpdate; + + if FUnRead then + ParentBoard.UnRead := ParentBoard.UnRead - 1; DeleteFile(GetThreadFileName); - if FileExists(ChangeFileExt(GetThreadFileName,'.NG')) = true then - DeleteFile(ChangeFileExt(GetThreadFileName,'.NG')); + //ŽŽŒ±“I‚Étmp‚àíœ‚µ‚Ä‚Ý‚é + tmpFileName := StringReplace(GetThreadFileName, 'dat', 'tmp', [rfReplaceAll]); + DeleteFile(tmpFileName); + + if FileExists(ChangeFileExt(GetThreadFileName,'.NG')) = true then + DeleteFile(ChangeFileExt(GetThreadFileName,'.NG')); FRoundDate := ZERO_DATE; FLastModified := ZERO_DATE; FSize := 0; @@ -1530,6 +1725,9 @@ begin FCount := 0; FNewResCount := 0; FRoundName := ''; + + ParentBoard.EndUpdate; + ParentBoard.Modified := True; end; function TThreadItem.GetThreadFileName: string; @@ -1537,8 +1735,8 @@ begin if Length( FilePath ) > 0 then Result := FilePath else - Result := ParentBoard.ParentCategory.ParenTBBS.GetLogFolder - + ParentBoard.BBSID + PATH_DELIM + FileName; + Result := GikoSys.Setting.LogFolderP + + BBS2CH_LOG_FOLDER + PATH_DELIM + ParentBoard.BBSID + PATH_DELIM + FileName; end; procedure TThreadItem.SetLastModified(d: TDateTime); @@ -1549,14 +1747,6 @@ begin ParentBoard.FModified := True; end; -{procedure TThreadItem.SetRoundNo(i: Integer); -begin - if FRoundNo = i then Exit; - FRoundNo := i; - if FUpdate and (ParentBoard <> nil) then - ParentBoard.FModified := True; -end;} - procedure TThreadItem.SetRound(b: Boolean); begin if b then @@ -1569,7 +1759,7 @@ begin ParentBoard.FModified := True; end; -procedure TThreadItem.SetRoundName(s: string); +procedure TThreadItem.SetRoundName(const s: string); begin if FRoundName = s then Exit; FRoundName := s; @@ -1577,6 +1767,7 @@ begin ParentBoard.FModified := True; end; + procedure TThreadItem.SetKokomade(i: Integer); begin if FKokomade = i then Exit; @@ -1589,8 +1780,14 @@ procedure TThreadItem.SetUnRead(b: Boolean); begin if FUnRead = b then Exit; FUnRead := b; - if FUpdate and (ParentBoard <> nil) then + if FUpdate and (ParentBoard <> nil) then begin ParentBoard.FModified := True; + if FUnRead then begin + ParentBoard.UnRead := ParentBoard.UnRead + 1; + end else begin + ParentBoard.UnRead := ParentBoard.UnRead - 1; + end; + end; end; procedure TThreadItem.SetScrollTop(i: Integer); @@ -1611,11 +1808,73 @@ begin FUpdate := True; end; -{initialization - BBS2ch := TBBS.Create; +function TThreadItem.GetCreateDate: TDateTime; +begin + // ƒtƒ@ƒCƒ‹–¼‚©‚çƒXƒŒì¬“úŽž‚ð‹‚ß‚é + try + if ( GikoSys.Setting.CreationTimeLogs ) and not IsLogFile then + Result := ZERO_DATE + else begin + // ƒƒOƒtƒ@ƒCƒ‹‚ÌŠg’£Žq‚ð‚Í‚¸‚µ‚½‚à‚Ì‚ªƒXƒŒì¬“úŽž + Result := GikoSys.GetCreateDateFromName(FFileName); + if GikoSys.Setting.FutureThread then begin + if CompareDateTime(Result, Now) = 1 then + Result := ZERO_DATE; + end; + end; + + except + on E: Exception do + Result := ZERO_DATE; + end; +end; +function TThreadItem.GetFilePath: String; +var + path : String; +begin + path := ExtractFilePath(Self.ParentBoard.FilePath) + Self.FileName; + Result := path; +end; + +destructor TBoardGroup.Destroy; +begin + Clear; + inherited; +end; +procedure TBoardGroup.Clear; +var + i : Integer; +begin + for i := Self.Count - 1 downto 0 do begin + try + TBoard(Self.Objects[i]).Free; + except + end; + end; + inherited Clear; + Self.Capacity := 0; + try + if FBoardPlugIn <> nil then + FBoardPlugIn.Free; + FBoardPlugIn := nil; + except + end; + +end; + +function TSpecialBoard.Add(item: TThreadItem): integer; +begin + Result := inherited AddObject(Item.URL, Item); +end; + +procedure TSpecialBoard.Clear; +var + i: integer; +begin + for i := Count - 1 downto 0 do + DeleteList(i); + Capacity := 0; +end; -finalization - if BBS2ch <> nil then - BBS2ch.Free;} end.