OSDN Git Service

バックアップファイルが更新されない不具合の修正
[gikonavigoeson/gikonavi.git] / BoardGroup.pas
index 21865fc..3bada6b 100644 (file)
@@ -4,7 +4,7 @@ interface
 
 uses
        Windows, SysUtils, Classes, ComCtrls, IniFiles, {HTTPApp,} YofUtils, IdGlobal,
-       ExternalBoardManager, ExternalBoardPlugInMain;
+       ExternalBoardManager, ExternalBoardPlugInMain, StrUtils, DateUtils;
 
 type
        //\83\8a\83X\83g\82Ì\95\\8e¦\83A\83C\83e\83\80\91I\91ð
@@ -14,7 +14,7 @@ type
        //\8f\84\89ñ\94Ô\8d\86
        //TGikoRoundNo = (grnNone, grn1, grn2, grn3, grn4, grn5, grnOnce);
        //\83\8a\83X\83g\82Ì\8fã\82°\89º\82°
-       TGikoAgeSage = (gasNone, gasAge, gasSage, gasNew);
+       TGikoAgeSage = (gasNone, gasAge, gasSage, gasNew, gasNull);
 
 {      TFolder = class
        private
@@ -70,45 +70,49 @@ type
        TBoard = class;
        TThreadItem = class;
 
-       //\82Æ\82è\82 \82¦\82¸\82Q\82¿\82á\82ñ\82Ë\82é\82Ì\83\8b\81[\83g
+       // BBS \82Ì\83\8b\81[\83g
        TBBS = class(TList)
        private
                FTitle: string;
-               FLogFolder: string;
+               FFilePath : string;                                             // \94Â\83\8a\83X\83g\82Ì\83p\83X
                FExpand: Boolean;
                FKubetsuChk: Boolean;                                   //\8di\8d\9e\82Ý\8e\9e\91å\95\8e\9a\8f¬\95\8e\9a\8bæ\95Ê
                FSelectText: string;                                    //\8di\8d\9e\82Ý\95\8e\9a\97ñ
                FShortSelectText: string;
+               FIsBoardFileRead : Boolean;             // \94Â\83\8a\83X\83g\82Í\93Ç\82Ý\8d\9e\82Ü\82ê\82Ä\82¢\82é\82©\81H
 
                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;
 
-       //\83J\83e\83S\83\8a
-       TCategory = class(TList)
+       // \83J\83e\83S\83\8a(\94 URL \82Ì\83\8a\83X\83g)
+       TCategory = class(THashedStringList)
        private
                FNo: Integer;
                FTitle: string;
@@ -129,20 +133,20 @@ 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;
 
-       //\94Â
-       TBoard = class(TList)
+       // \94Â(\83X\83\8c\83b\83h URL \82Ì\83\8a\83X\83g)
+       TBoard = class(THashedStringList)
        private
-               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é)
+               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é)
 
                FNo: Integer;                                                                   //\94Ô\8d\86
                FTitle: string;                                                         //\83{\81[\83h\83^\83C\83g\83\8b
@@ -155,7 +159,7 @@ type
                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
                FIsThreadDatRead: Boolean;              //\83X\83\8c\83b\83h\83\8a\83X\83g\82Í\93Ç\82Ý\8d\9e\82Ü\82ê\82Ä\82¢\82é\82©\81H
                FUnRead: Integer;                                                       //\83X\83\8c\83b\83h\96¢\93Ç\90\94
-               FParentCategory: TCategory;      //\90e\83J\83e\83S\83\8a
+               FParentCategory: TCategory;             //\90e\83J\83e\83S\83\8a
                FModified: Boolean;                                             //\8fC\90³\83t\83\89\83O
                FBoolData: Boolean;                                             //\82¢\82ë\82ñ\82È\97p\93r\82É\8eg\82¤yo
                FSPID: string;                                                          //\8f\91\82«\8d\9e\82Ý\97pSPID
@@ -172,6 +176,12 @@ type
                FIntData                        : Integer;                      // \8dD\82«\82É\82¢\82\82Á\82Ä\82æ\82µ\81B\82¢\82ë\82ñ\82È\97p\93r\82É\8eg\82¤yo
                FListData                       : TList;                                // \8dD\82«\82É\82¢\82\82Á\82Ä\82æ\82µ\81B\82¢\82ë\82ñ\82È\97p\93r\82É\8eg\82¤yo
 
+               FSETTINGTXTTime: TDateTime;     //SETTING.TXT\82ð\8eæ\93¾\82µ\82½\93ú\8e\9e
+               FIsSETTINGTXT:          boolean;        //SETTING.TXT\82ð\8eæ\93¾\82µ\82Ä\82¢\82é\82©
+               FHEADTXTTime: TDateTime;                //HEAD.TXT\82ð\8eæ\93¾\82µ\82½\93ú\8e\9e
+               FIsHEADTXT:             boolean;        //HEAD.TXT\82ð\8eæ\93¾\82µ\82Ä\82¢\82é\82©
+        FTitlePictureURL:      string; //top\8aG\82ÌURL
+
                function GetThreadItem(index: integer): TThreadItem;
                procedure SetThreadItem(index: integer; value: TThreadItem);
                procedure SetRound(b: Boolean);
@@ -181,9 +191,9 @@ type
                procedure SetUnRead(i: Integer);
                procedure SetKotehanName(s: string);
                procedure SetKotehanMail(s: string);
-               procedure Create; overload;
+               procedure Init;
        public
-               constructor Create( inPlugIn : TBoardPlugIn; inURL : string ); overload;
+               constructor Create( inPlugIn : TBoardPlugIn; inURL : string );
                destructor Destroy; override;
 
                property Context: DWORD read FContext write FContext;
@@ -215,15 +225,18 @@ 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): 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;
@@ -241,6 +254,13 @@ 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;
+
        end;
 
        //\83X\83\8c
@@ -276,23 +296,23 @@ type
                FURL                                    : string;                               // \82±\82Ì\83X\83\8c\82ð\83u\83\89\83E\83U\82Å\95\\8e¦\82·\82é\8dÛ\82Ì URL
                FBoardPlugIn    : TBoardPlugIn; // \82±\82Ì\83X\83\8c\82ð\83T\83|\81[\83g\82·\82é\83v\83\89\83O\83C\83\93
                FFilePath                       : string;                               // \82±\82Ì\83X\83\8c\82ª\95Û\91\82³\82ê\82Ä\82¢\82é\83p\83X
-               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
 
                procedure SetLastModified(d: TDateTime);
                procedure SetRound(b: Boolean);
-               procedure SetRoundName(s: string);
+               procedure SetRoundName(const s: string);
                procedure SetKokomade(i: Integer);
                procedure SetUnRead(b: Boolean);
                procedure SetScrollTop(i: Integer);
-               procedure Create; overload;
+               procedure Init;
+               function GetCreateDate: TDateTime;
        public
-               constructor Create( inPlugIn : TBoardPlugIn; inURL : string ); overload;
+               constructor Create( inPlugIn : TBoardPlugIn; inURL : string );
                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;
@@ -325,11 +345,10 @@ type
                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;
        end;
 
@@ -354,7 +373,8 @@ type
        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;
 
 var
        BBSs            : array of TBBS;
@@ -362,7 +382,7 @@ var
 implementation
 
 uses
-       GikoSystem, RoundData;
+       GikoSystem, RoundData, MojuUtils;
 
 const
        BBS2CH_NAME:                                     string = '\82Q\82¿\82á\82ñ\82Ë\82é';
@@ -373,26 +393,23 @@ const
        FOLDER_INDEX_FILENAME: string   = 'Folder.idx';
        SUBJECT_FILENAME:                       string  = 'subject.txt';
        PATH_DELIM:                                             string  = '\';
+       SETTINGTXT_FILENAME:            string = 'SETTING.TXT';
+    HEADTXT_FILENAME:          string = 'head.txt';
        //DEFAULT_LIST_COUNT:           Integer = 100;
 
 //     COLUMN_CATEGORY:         array[0..0] of string = ('\83J\83e\83S\83\8a\96¼');
 //     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');
 //     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');
 
+// BBSID \82ð\97p\82¢\82é 2 \82¿\82á\82ñ\82Ë\82é\82Ì\82Ý\92T\82µ\8fo\82µ\82Ü\82·
+// BBSID \82Ì\8eg\97p\82Í\8bÉ\97Í\94ð\82¯\82Ä\82­\82¾\82³\82¢\81B
+// \89Â\94\\82È\8fê\8d\87\82Í URL \82ð\8eg\97p\82µ\82Ä\82­\82¾\82³\82¢\81B
 function       BBSsFindBoardFromBBSID(
        inBBSID : string
 ) : TBoard;
-var
-       i                               : Integer;
 begin
 
-       for i := Length( BBSs ) - 1 downto 0 do begin
-               Result := BBSs[ i ].FindBBSID( inBBSID );
-               if Result <> nil then
-                       Exit;
-       end;
-
-       Result := nil;
+       Result := BBSs[ 0 ].FindBBSID( inBBSID );
 
 end;
 
@@ -431,19 +448,19 @@ begin
 end;
 
 function       BBSsFindThreadFromURL(
-       inURL   : string
+       const inURL                     : string
 ) : TThreadItem;
 var
-       i                       : Integer;
+       board                   : TBoard;
+       boardURL        : string;
 begin
 
-       for i := Length( BBSs ) - 1 downto 0 do begin
-               Result := BBSs[ i ].FindThreadFromURL( inURL );
-               if Result <> nil then
-                       Exit;
-       end;
-
-       Result := nil;
+       boardURL        := GikoSys.GetThreadURL2BoardURL( inURL );
+       board                   := BBSsFindBoardFromURL( boardURL );
+       if board = nil then
+               Result := nil
+       else
+               Result := board.FindThreadFromURL( inURL );
 
 end;
 
@@ -451,10 +468,11 @@ end;
  *\8b@\94\\96¼\81FTBBS\83R\83\93\83X\83g\83\89\83N\83^
  *Public
  *************************************************************************)
-constructor TBBS.Create(LogFolder: string);
+constructor TBBS.Create( boardFilePath : string );
 begin
+       inherited Create;
        Title := BBS2CH_NAME;
-       FLogFolder := LogFolder;
+       FFilePath := boardFilePath;
 end;
 
 (*************************************************************************
@@ -501,6 +519,7 @@ var
 begin
        for i := Count - 1 downto 0 do
                Delete(i);
+    Capacity := Count;
 end;
 
 function TBBS.Find(key: string): TCategory;
@@ -508,10 +527,12 @@ begin
        Result := nil;
 end;
 
-function TBBS.FindBBSID(BBSID: string): TBoard;
+function TBBS.FindBBSID(const BBSID: string): TBoard;
 var
        i       : Integer;
 begin
+       if not IsBoardFileRead then
+       GikoSys.ReadBoardFile( Self );
        for i := Count - 1 downto 0 do begin
                Result := Items[ i ].FindBBSID(BBSID);
                if Result <> nil then
@@ -523,10 +544,12 @@ end;
 //*************************************************************************
 // \83^\83C\83g\83\8b\82Ì\88ê\92v\82·\82é\94Â\82ð\92T\82·
 //*************************************************************************)
-function TBBS.FindBoardFromTitle(Title: string): TBoard;
+function TBBS.FindBoardFromTitle(const Title: string): TBoard;
 var
        i: Integer;
 begin
+       if not IsBoardFileRead then
+       GikoSys.ReadBoardFile( Self );
        for i := Count - 1 downto 0 do begin
                Result := Items[ i ].FindBoardFromTitle(Title);
                if Result <> nil then
@@ -538,10 +561,12 @@ end;
 //*************************************************************************
 // URL \82ð\8eó\82¯\95t\82¯\82é\94Â\82ð\92T\82·
 //*************************************************************************)
-function TBBS.FindBoardFromURL(inURL: string): TBoard;
+function TBBS.FindBoardFromURL(const inURL: string): TBoard;
 var
        i                                       : Integer;
 begin
+       if not IsBoardFileRead then
+       GikoSys.ReadBoardFile( Self );
        for i := Count - 1 downto 0 do begin
                Result := Items[ i ].FindBoardFromURL( inURL );
                if Result <> nil then
@@ -553,19 +578,22 @@ end;
 //*************************************************************************
 // URL \82ð\8eó\82¯\95t\82¯\82é\83X\83\8c\83b\83h\82ð\92T\82·
 //*************************************************************************)
-function TBBS.FindThreadFromURL(inURL: string): TThreadItem;
+function TBBS.FindThreadFromURL(const inURL: string): TThreadItem;
 var
-       i       : Integer;
+       board                   : TBoard;
+       boardURL        : string;
 begin
-       for i := Count - 1 downto 0 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
@@ -573,23 +601,29 @@ begin
        Board := FindBBSID(BBSID);
        if Board = nil then
                Exit;
-       Result := Board.Find(FileName);
+       Result := Board.FindThreadFromFileName(FileName);
 end;
 
-(*************************************************************************
- *\83\8d\83O\83t\83H\83\8b\83_\8eæ\93¾
- *
- *************************************************************************)
-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 := ZenToHan(s);
 end;
 
 {class function TBBS.GetColumnName(Index: Integer): string;
@@ -607,6 +641,7 @@ end;}
 //===================
 constructor TCategory.Create;
 begin
+       inherited;
 end;
 
 destructor TCategory.Destroy;
@@ -617,25 +652,25 @@ 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);
 end;
 
@@ -645,19 +680,20 @@ 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;
 begin
        for i := Count - 1 downto 0 do begin
-               if Items[i].FBBSID = BBSID then begin
+               if AnsiCompareStr(Items[i].FBBSID, BBSID) = 0 then begin
                        Result := Items[i];
                        Exit;
                end;
@@ -668,12 +704,12 @@ end;
 //*************************************************************************
 // \83^\83C\83g\83\8b\82Ì\88ê\92v\82·\82é\94Â\82ð\92T\82·
 //*************************************************************************)
-function TCategory.FindBoardFromTitle(Title: string): TBoard;
+function TCategory.FindBoardFromTitle(const Title: string): TBoard;
 var
        i       : integer;
 begin
        for i := Count - 1 downto 0 do begin
-               if Items[i].FTitle = Title then begin
+               if AnsiCompareStr(Items[i].FTitle, Title) = 0 then begin
                        Result := Items[i];
                        Exit;
                end;
@@ -684,33 +720,32 @@ end;
 //*************************************************************************
 // URL \82ð\8eó\82¯\95t\82¯\82é\94Â\82ð\92T\82·
 //*************************************************************************)
-function TCategory.FindBoardFromURL(inURL: string): TBoard;
+function TCategory.FindBoardFromURL(const inURL: string): TBoard;
 var
        i       : Integer;
 begin
-       for i := Count - 1 downto 0 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 := TBoard( Objects[ i ] )
+       else
+               Result := nil;
 end;
 
 //*************************************************************************
 // URL \82ð\8eó\82¯\95t\82¯\82é\83X\83\8c\83b\83h\82ð\92T\82·
 //*************************************************************************)
-function TCategory.FindThreadFromURL(inURL: string): TThreadItem;
+function TCategory.FindThreadFromURL(const inURL: string): TThreadItem;
 var
-       i                                               : Integer;
+       board                   : TBoard;
+       boardURL        : string;
 begin
 
-       for i := Count - 1 downto 0 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;
 
@@ -748,7 +783,7 @@ end;}
 //===================
 //TBoard
 //===================
-procedure TBoard.Create;
+procedure TBoard.Init;
 begin
        FNo := 0;
        FTitle := '';
@@ -764,8 +799,6 @@ begin
 //     FItemNoVisible := True;
 
        FUpdate := True;
-
-       FBoardPlugIn := nil;
 end;
 
 // *************************************************************************
@@ -777,16 +810,15 @@ constructor TBoard.Create(
 );
 var
        protocol, host, path, document, port, bookmark  : string;
-       BBSID                   : string;
 begin
 
-       Create;
+       inherited Create;
+       Init;
 
        FBoardPlugIn    := inPlugIn;
        URL                                             := inURL;
        BBSID                                   := GikoSys.UrlToID( inURL );
 
-       // \83v\83\89\83O\83C\83\93\82É TBoardItem \82ª\8dì\90¬\82³\82ê\82½\82±\82Æ\82ð\93`\82¦\82é
        if inPlugIn = nil then begin
                // subject.txt \82Ì\95Û\91\83p\83X\82ð\90Ý\92è
                GikoSys.ParseURI( inURL, protocol, host, path, document, port, bookmark );
@@ -799,6 +831,7 @@ begin
                                IncludeTrailingPathDelimiter( GikoSys.Setting.LogFolder ) +
                                EXTERNAL_LOG_FOLDER + PATH_DELIM + host + PATH_DELIM + BBSID + PATH_DELIM + SUBJECT_FILENAME
        end else begin
+               // \83v\83\89\83O\83C\83\93\82É TBoardItem \82ª\8dì\90¬\82³\82ê\82½\82±\82Æ\82ð\93`\82¦\82é
                inPlugIn.CreateBoardItem( DWORD( Self ) );
        end;
 
@@ -845,24 +878,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\82Å\8ew\92è\82³\82ê\82½\83X\83\8c\83b\83h\83I\83u\83W\83F\83N\83g\82ð\94j\8aü
@@ -870,7 +905,6 @@ procedure TBoard.Delete(index: Integer);
 begin
        if Items[index] <> nil then
                TThreadItem(Items[index]).Free;
-       Items[index] := nil;
        inherited Delete(index);
 end;
 
@@ -887,22 +921,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
@@ -915,34 +950,24 @@ begin
        end;
 end;
 
-function TBoard.GetIndexFromURL(URL: string): Integer;
-var
-       i: integer;
+function TBoard.GetIndexFromURL(const URL: string): Integer;
 begin
-       Result := -1;
-       for i := 0 to Count - 1 do begin
-               if Items[i].URL = URL then begin
-                       Result := i;
-                       Exit;
-               end;
-       end;
+       Result := IndexOf( URL );
 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 := Count - 1 downto 0 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;
 
@@ -964,29 +989,41 @@ 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 := IncludeTrailingPathDelimiter( GikoSys.Setting.LogFolder )
+                                                       + 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', '');
                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
@@ -1002,8 +1039,8 @@ begin
        if Length( FilePath ) > 0 then
                FileName := ExtractFilePath( FilePath )
        else
-               FileName := ParentCategory.ParenTBBS.GetLogFolder
-                                                       + BBSID + PATH_DELIM;
+               FileName := IncludeTrailingPathDelimiter( GikoSys.Setting.LogFolder )
+                                                       + BBS2CH_LOG_FOLDER + PATH_DELIM + BBSID + PATH_DELIM;
        if not GikoSys.DirectoryExistsEx(FileName) then
                GikoSys.ForceDirectoriesEx(FileName);
        FileName := FileName + FOLDER_INI_FILENAME;
@@ -1020,6 +1057,13 @@ begin
                ini.WriteString('Cookie', 'PON', FPON);
                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));
@@ -1028,7 +1072,62 @@ begin
                ini.Free;
        end;
 end;
-
+//\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ð
+//        2003/02/08 0:32:13\82É\95Ï\8a·\82·\82é
+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;
 // \83T\83u\83W\83F\83N\83gURL\8eæ\93¾
 function TBoard.GetReadCgiURL: string;
 begin
@@ -1045,8 +1144,8 @@ begin
        if Length( FilePath ) > 0 then
                Result := FilePath
        else
-               Result := ParentCategory.ParenTBBS.GetLogFolder
-                                               + BBSID + PATH_DELIM + SUBJECT_FILENAME;
+               Result := IncludeTrailingPathDelimiter( GikoSys.Setting.LogFolder )
+                                               + BBS2CH_LOG_FOLDER + PATH_DELIM + BBSID + PATH_DELIM + SUBJECT_FILENAME;
 end;
 
 // \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
@@ -1055,8 +1154,41 @@ begin
        if Length( FilePath ) > 0 then
                Result := ExtractFilePath( FilePath ) + FOLDER_INDEX_FILENAME
        else
-               Result := ParentCategory.ParenTBBS.GetLogFolder
-                                               + BBSID + PATH_DELIM + FOLDER_INDEX_FILENAME;
+               Result := IncludeTrailingPathDelimiter( GikoSys.Setting.LogFolder )
+                                               + BBS2CH_LOG_FOLDER + PATH_DELIM + BBSID + PATH_DELIM + FOLDER_INDEX_FILENAME;
+end;
+//SETTING.TXT\82Ì\83t\83@\83C\83\8b\96¼\8eæ\93¾
+function TBoard.GetSETTINGTXTFileName: string;
+begin
+       if Length( FilePath ) > 0 then
+               Result := ExtractFilePath( FilePath ) + SETTINGTXT_FILENAME
+       else
+               Result := IncludeTrailingPathDelimiter( GikoSys.Setting.LogFolder )
+                                               + 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 := IncludeTrailingPathDelimiter( GikoSys.Setting.LogFolder )
+                                               + 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 := IncludeTrailingPathDelimiter( GikoSys.Setting.LogFolder )
+                                                       + BBS2CH_LOG_FOLDER + PATH_DELIM + BBSID + PATH_DELIM + tmpName;
+       end;
 end;
 
 // \83X\83\8c\97§\82Ä\91\97\90MURL
@@ -1131,23 +1263,23 @@ 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 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 := ZenToHan(Items[i].Title);
+                               if AnsiPos(ParentCategory.ParenTBBS.ShortSelectText, Items[i].ShortTitle) <> 0 then
+                                       inc(Result);
+                       end;
+               end;
+       end;
 end;
 
 function TBoard.GetLogThreadCount: Integer;
@@ -1155,23 +1287,23 @@ 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;
+       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 := ZenToHan(Items[i].Title);
+                               if AnsiPos(ParentCategory.ParenTBBS.ShortSelectText, Items[i].ShortTitle) <> 0 then
+                                       inc(Result);
+                       end;
+               end;
+       end;
 end;
 
 function TBoard.GetUserThreadCount: Integer;
@@ -1179,15 +1311,15 @@ 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;
+       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 := ZenToHan(Items[i].Title);
+                       if AnsiPos(ParentCategory.ParenTBBS.ShortSelectText, Items[i].ShortTitle) <> 0 then
+                               inc(Result);
+               end;
 end;
 
 function TBoard.GetNewThread(Index: Integer): TThreadItem;
@@ -1197,34 +1329,34 @@ var
 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 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 := 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;
 
 function TBoard.GetLogThread(Index: Integer): TThreadItem;
@@ -1232,36 +1364,36 @@ var
        i: Integer;
        Cnt: Integer;
 begin
-                               Cnt := 0;
-                               if Length( ParentCategory.ParenTBBS.ShortSelectText ) = 0 then
+       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
-                                       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;
+                                       if Items[i].ShortTitle = '' then
+                                               Items[i].ShortTitle := 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;
-                               Result := nil;
+                       end;
+               end;
+       end;
+       Result := nil;
 end;
 
 function TBoard.GetUserThread(Index: Integer): TThreadItem;
@@ -1271,29 +1403,29 @@ var
 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;
+       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 := 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;
 
 procedure TBoard.BeginUpdate;
@@ -1317,7 +1449,7 @@ begin
 end;}
 
 //constructor TThreadItem.Create(AOwner: TComponent);
-procedure TThreadItem.Create;
+procedure TThreadItem.Init;
 begin
        FNo := 0;
        FFileName := '';
@@ -1355,7 +1487,8 @@ const
        READ_PATH                                                       = '/test/read.cgi';
 begin
 
-       Create;
+       inherited Create;
+       Init;
 
        FBoardPlugIn    := inPlugIn;
        URL                                             := inURL;
@@ -1374,7 +1507,9 @@ begin
                                FilePath :=
                                        IncludeTrailingPathDelimiter( GikoSys.Setting.LogFolder ) +
                                        EXTERNAL_LOG_FOLDER + PATH_DELIM + host + PATH_DELIM + BBSID + PATH_DELIM + BBSKey + '.dat';
-                       FileName := BBSKey + '.dat';
+                       FileName        := BBSKey + '.dat';
+                       IsLogFile       := FileExists( FilePath );
+                       URL                             := GikoSys.Get2chBrowsableThreadURL( inURL );
                end;
        end else begin
                // \83v\83\89\83O\83C\83\93\82É TThreadItem \82ª\8dì\90¬\82³\82ê\82½\82±\82Æ\82ð\93`\82¦\82é
@@ -1499,7 +1634,7 @@ begin
        end;
 end;}
 
-function TThreadItem.GetOfflawCgiURL(SessionID: string): string;
+function TThreadItem.GetOfflawCgiURL(const SessionID: string): string;
 //var
 //     Protocol, Host, Path, Document, Port, Bookmark: string;
 begin
@@ -1531,6 +1666,8 @@ end;
 
 procedure TThreadItem.DeleteLogFile;
 begin
+       ParentBoard.BeginUpdate;
+
        DeleteFile(GetThreadFileName);
                if FileExists(ChangeFileExt(GetThreadFileName,'.NG')) = true then
                        DeleteFile(ChangeFileExt(GetThreadFileName,'.NG'));
@@ -1550,6 +1687,9 @@ begin
        FCount := 0;
        FNewResCount := 0;
        FRoundName := '';
+
+       ParentBoard.EndUpdate;
+       ParentBoard.Modified := True;
 end;
 
 function TThreadItem.GetThreadFileName: string;
@@ -1557,8 +1697,8 @@ begin
        if Length( FilePath ) > 0 then
                Result := FilePath
        else
-               Result := ParentBoard.ParentCategory.ParenTBBS.GetLogFolder
-                                               + ParentBoard.BBSID + PATH_DELIM + FileName;
+               Result := IncludeTrailingPathDelimiter( GikoSys.Setting.LogFolder )
+                                               + BBS2CH_LOG_FOLDER + PATH_DELIM + ParentBoard.BBSID + PATH_DELIM + FileName;
 end;
 
 procedure TThreadItem.SetLastModified(d: TDateTime);
@@ -1589,7 +1729,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;
@@ -1637,5 +1777,40 @@ end;
 finalization
        if BBS2ch <> nil then
                BBS2ch.Free;}
+function TThreadItem.GetCreateDate: TDateTime;
+var
+       unixtime: Int64;
+    tmp: string;
+begin
+       // \83t\83@\83C\83\8b\96¼\82©\82ç\83X\83\8c\8dì\90¬\93ú\8e\9e\82ð\8b\81\82ß\82é
+       try
+               if ( GikoSys.Setting.CreationTimeLogs ) and not IsLogFile  then
+            Result := ZERO_DATE
+        else begin
+            // \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
+                       tmp := ChangeFileExt(FFileName, '');
+                       if AnsiPos('_', tmp) <> 0 then
+                               if AnsiPos('_', tmp) > 9 then
+                                       tmp := Copy(tmp, 1, AnsiPos('_', tmp)-1)
+                               else
+                                       Delete(tmp, AnsiPos('_', tmp), 1);
+
+                       if ( Length(tmp) = 9) and ( tmp[1] = '0' ) then
+                               Insert('1', tmp, 1);
+
+                       unixtime := StrToInt64Def(tmp, ZERO_DATE);
+                       Result := UnixToDateTime(unixtime) + OffsetFromUTC;
+                       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;
+
 end.