OSDN Git Service

・r1.263 で消し忘れのゴミが残っていたので削除。
[gikonavigoeson/gikonavi.git] / GikoSystem.pas
index 9c20d8c..24ac1f1 100644 (file)
@@ -13,7 +13,8 @@ uses
        MSHTML_TLB,
 {$IFEND}
        {HttpApp,} YofUtils, URLMon, IdGlobal, IdURI, {Masks,}
-       Setting, BoardGroup, gzip, Dolib, bmRegExp, AbonUnit;
+       Setting, BoardGroup, gzip, Dolib, bmRegExp, AbonUnit,
+       MojuUtils, ExternalBoardManager, ExternalBoardPlugInMain;
 
 type
        //BBS\83^\83C\83v
@@ -74,8 +75,8 @@ type
        TPathRec = record
                FBBS: string;                           //BBSID
                FKey: string;                           //ThreadID
-               FSt: Integer;                           //\8aJ\8en\83\8c\83X\94Ô
-               FTo: Integer;                           //\8fI\97¹\83\8c\83X\94Ô
+               FSt: Int64;                             //\8aJ\8en\83\8c\83X\94Ô
+               FTo: Int64;                             //\8fI\97¹\83\8c\83X\94Ô
                FFirst: Boolean;                //>>1\82Ì\95\\8e¦
                FStBegin: Boolean;      //1\81`\95\\8e¦
                FToEnd: Boolean;                //\81`\8dÅ\8cã\82Ü\82Å\95\\8e¦
@@ -88,9 +89,10 @@ type
                FSetting: TSetting;
                FDolib: TDolib;
                FAWKStr: TAWKStr;
+               FOnlyAHundredRes : Boolean;
+
 //             FExitWrite: TStringList;
 //             function StrToFloatDef(s: string; Default: Double): Double;
-
        public
                { Public \90é\8c¾ }
                FAbon : TAbon;
@@ -98,8 +100,7 @@ type
                constructor Create;
 
                destructor Destroy; override;
-
-
+               property OnlyAHundredRes : Boolean read FOnlyAHundredRes write FOnlyAHundredRes;
 //             function MsgBox(Msg: string; Title: string; Flags: Longint): integer; overload;
 //             function MsgBox(Handle: THandle; Msg: string; Title: string; Flags: Longint): integer; overload;
                function IsNumeric(s: string): boolean;
@@ -116,16 +117,22 @@ type
                function GetSentFileName: string;
                function GetConfigDir: string;
                function GetSkinDir: string;
+               function GetSkinHeaderFileName: string;
+               function GetSkinFooterFileName: string;
+               function GetSkinResFileName: string;
+               function GetSkinNewResFileName: string;
+               function GetSkinBookmarkFileName: string;
+               function GetSkinNewmarkFileName: string;
                function GetStyleSheetDir: string;
                function GetOutBoxFileName: string;
-               function GetURL(BBSID: string; FileName: string): string;
                function GetUserAgent: string;
+        function GetSambaFileName : string;
 
                procedure ReadSubjectFile(Board: TBoard);
                procedure CreateThreadDat(Board: TBoard);
                procedure WriteThreadDat(Board: TBoard);
                function ParseIndexLine(Line: string): TIndexRec;
-               procedure GetFileList(Path: string; Mask: string; List: TStringList; SubDir: Boolean; IsPathAdd: Boolean);
+               procedure GetFileList(Path: string; Mask: string; var List: TStringList; SubDir: Boolean; IsPathAdd: Boolean);
                procedure GetDirectoryList(Path: string; Mask: string; List: TStringList; SubDir: Boolean);
 
                procedure CreateHTML2(doc: Variant; ThreadItem: TThreadItem; var sTitle: string);
@@ -147,7 +154,7 @@ type
                function GetFileLineCount(FileName : string): longint;
                function Get2chDate(aDate: TDateTime): string;
                function IntToDateTime(val: Int64): TDateTime;
-               function DateTimeToInt(ADate: TDateTime): Integer;
+               function DateTimeToInt(ADate: TDateTime): Int64;
 
                function ReadThreadFile(FileName: string; Line: Integer): string;
 
@@ -159,7 +166,8 @@ type
                function DeleteLink(const s: string): string;
 
                function GetShortName(const LongName: string; ALength: integer): string;
-               function ConvRes(const Body, Bbs, Key,  ParamBBS, ParamKey, ParamStart, ParamTo, ParamNoFirst, ParamTrue : string): string;
+               function ConvRes(const Body, Bbs, Key,  ParamBBS, ParamKey, ParamStart, ParamTo, ParamNoFirst, ParamTrue : string): string; overload;
+        function ConvRes(const Body, Bbs, Key, ParamBBS, ParamKey, ParamStart, ParamTo, ParamNoFirst, ParamTrue, FullURL : string): string; overload;
 
                function ZenToHan(const s: string): string;
                function VaguePos(const Substr, S: string): Integer;
@@ -168,6 +176,9 @@ type
                function GzipDecompress(ResStream: TStream; ContentEncoding: string): string;
                procedure LoadKeySetting(ActionList: TActionList);
                procedure SaveKeySetting(ActionList: TActionList);
+               procedure LoadEditorKeySetting(ActionList: TActionList);
+               procedure SaveEditorKeySetting(ActionList: TActionList);
+
                procedure CreateProcess(const AppPath: string; const Param: string);
                procedure OpenBrowser(URL: string; BrowserType: TGikoBrowserType);
                function HTMLDecode(const AStr: String): String;
@@ -177,17 +188,38 @@ type
                function Parse2chURL2(URL: string): TPathRec;
                procedure ParseURI(var URL, Protocol, Host, Path, Document, Port, Bookmark: string);
                function GetVersionBuild: Integer;
+               function        GetBrowsableThreadURL( inURL : string ) : string;
+               function        GetThreadURL2BoardURL( inURL : string ) : string;
+               function        Get2chThreadURL2BoardURL( inURL : string ) : string;
+               function        Get2chBrowsableThreadURL( inURL : string ) : string;
+               function        Get2chBoard2ThreadURL( inBoard : TBoard; inKey : string ) : string;
+               procedure ListBoardFile;
+               procedure ReadBoardFile( bbs : TBBS );
+
+               function        GetUnknownCategory : TCategory;
+               function        GetUnknownBoard( inPlugIn : TBoardPlugIn; inURL : string ) : TBoard;
+
+        procedure GetPopupResNumber(URL : string; var stRes, endRes : Int64);
+
+               // \83X\83L\83\93\82ð\93Ç\82Ý\8d\9e\82Ý\81A\92l\82ð\92u\8a·\82·\82é
+               function LoadFromSkin( fileName: string; ThreadItem: TThreadItem; SizeByte: Integer ): string;
+       // \83\8c\83X\82Ì\92l\82ð\92u\8a·\82·\82é
+               function SkinedRes( skin: string; Res: TResRec; No: string ): string;
+
+        //Samba24\82Ì\83t\83@\83C\83\8b\82ª\91\8dÝ\82·\82é\82©\81B\91\8dÝ\82µ\82È\82¢\8fê\8d\87\81Adefault\83t\83@\83C\83\8b\82ðrename\82·\82é
+        procedure SambaFileExists();
        end;
 
 var
        GikoSys: TGikoSys;
 const
-       LENGTH_RESTITLE                 = 40;
+       //LENGTH_RESTITLE                       = 40;
        ZERO_DATE: Integer      = 25569;
        BETA_VERSION_NAME_E = 'beta';
        BETA_VERSION_NAME_J = 'ÊÞÀ';
-       BETA_VERSION                            = 40;
+       BETA_VERSION                            = 47;
        BETA_VERSION_BUILD      = '';                           //debug\94Å\82È\82Ç
+       APP_NAME                                                = 'gikoNavi';
 
 implementation
 
@@ -195,25 +227,15 @@ uses
        Giko, RoundData;
 
 const
-       BOARD_FILE_NAME                                                         = 'board.2ch';
-       CUSTOMBOARD_FILE_NAME                                   = 'custom.2ch';
-       KEY_SETTING_FILE_NAME                                   = 'key.ini';
-       TEMP_FOLDER                                                                             = 'Temp';
-       OUTBOX_FILE_NAME                                                        = 'outbox.ini';
-       SENT_FILE_NAME                                                          = 'sent.ini';
-       CONFIG_DIR_NAME                                                         = 'config';
-       CSS_DIR_NAME                                                                    = 'css';
-       SKIN_DIR_NAME                                                                   = 'skin';
-  SKIN_HEADER_FILE_NAME                                        = 'Header.html';
-  SKIN_FOOTER_FILE_NAME                                        = 'Footer.html';
-  SKIN_NEWRES_FILE_NAME                                        = 'NewRes.html';
-  SKIN_RES_FILE_NAME                                           = 'Res.html';
        FOLDER_INDEX_VERSION                                    = '1.01';
        USER_AGENT                                                                              = 'Monazilla';
-       APP_NAME                                                                                        = 'gikoNavi';
        DEFAULT_NGWORD_FILE_NAME : String = 'NGword.txt';
        NGWORDs_DIR_NAME : String               = 'NGwords';
 
+       READ_PATH: string =                     '/test/read.cgi/';
+       OLD_READ_PATH: string =         '/test/read.cgi?';
+       KAKO_PATH: string =                     '/kako/';
+
 (*************************************************************************
  *GikoSys\83R\83\93\83X\83g\83\89\83N\83^
  *************************************************************************)
@@ -227,11 +249,19 @@ begin
        end;
        FAbon := TAbon.Create;
        FAbon.Setroot(GetConfigDir+NGWORDs_DIR_NAME);
-       //FAbon.SetNGwordpath(DEFAULT_NGWORD_FILE_NAME);
        FAbon.GoHome;
+       FAbon.ReturnNGwordLineNum := FSetting.ShowNGLinesNum;
+       FAbon.SetNGResAnchor := FSetting.AddResAnchor;
+    FAbon.DeleteSyria := FSetting.DeleteSyria;
+       FAbon.Deleterlo := FSetting.AbonDeleterlo;
+       FAbon.Replaceul := FSetting.AbonReplaceul;
+       FAbon.AbonPopupRes := FSetting.PopUpAbon;
+
        FSelectResFilter := TAbon.Create;
        // \8di\82è\8d\9e\82Þ\82Æ\82«\82Í\8bÉ\97Í\88ê\97\97\82ª\8c©\82ç\82ê\82é\82Ù\82¤\82ª\82¢\82¢\82Ì\82Å\91¼\82Í\8a®\91S\82É\8dí\8f\9c
        FSelectResFilter.AbonString := '';
+       //
+       OnlyAHundredRes := FSetting.OnlyAHundredRes;
 end;
 
 (*************************************************************************
@@ -249,7 +279,8 @@ begin
        FAWKStr.Free;
        FSetting.Free;
        FDolib.Free;
-
+       FAbon.Free;
+       FSelectResFilter.Free;
        //\83e\83\93\83|\83\89\83\8aHTML\82ð\8dí\8f\9c
        FileList := TStringList.Create;
        try
@@ -292,7 +323,7 @@ end;
  *************************************************************************)
 function TGikoSys.GetBoardFileName: string;
 begin
-       Result := GetAppDir + CONFIG_DIR_NAME + '\' + BOARD_FILE_NAME;
+       Result := Setting.GetBoardFileName;
 end;
 
 (*************************************************************************
@@ -300,7 +331,7 @@ end;
  *************************************************************************)
 function TGikoSys.GetCustomBoardFileName: string;
 begin
-       Result := GetAppDir + CONFIG_DIR_NAME + '\' + CUSTOMBOARD_FILE_NAME;
+       Result := Setting.GetCustomBoardFileName;
 end;
 
 (*************************************************************************
@@ -308,7 +339,7 @@ end;
  *************************************************************************)
 function TGikoSys.GetHtmlTempFileName: string;
 begin
-       Result := TEMP_FOLDER;
+       Result := Setting.GetHtmlTempFileName;
 end;
 
 
@@ -317,7 +348,7 @@ end;
  *************************************************************************)
 function TGikoSys.GetAppDir: string;
 begin
-       Result := ExtractFilePath(Application.ExeName);
+       Result := Setting.GetAppDir;
 end;
 
 (*************************************************************************
@@ -325,7 +356,7 @@ end;
  *************************************************************************)
 function TGikoSys.GetTempFolder: string;
 begin
-       Result := GetAppDir + TEMP_FOLDER;
+       Result := Setting.GetTempFolder;
 end;
 
 (*************************************************************************
@@ -333,7 +364,7 @@ end;
  *************************************************************************)
 function TGikoSys.GetSentFileName: string;
 begin
-       Result := GetAppDir + SENT_FILE_NAME;
+       Result := Setting.GetSentFileName;
 end;
 
 (*************************************************************************
@@ -341,7 +372,7 @@ end;
  *************************************************************************)
 function TGikoSys.GetOutBoxFileName: string;
 begin
-       Result := GetAppDir + OUTBOX_FILE_NAME;
+       Result := Setting.GetOutBoxFileName;
 end;
 
 (*************************************************************************
@@ -349,30 +380,47 @@ end;
  *************************************************************************)
 function TGikoSys.GetConfigDir: string;
 begin
-       Result := IncludeTrailingPathDelimiter(GetAppDir + CONFIG_DIR_NAME);
+       Result := Setting.GetConfigDir;
 end;
 
 function TGikoSys.GetStyleSheetDir: string;
 begin
-       Result := IncludeTrailingPathDelimiter(GetConfigDir + CSS_DIR_NAME);
+       Result := Setting.GetStyleSheetDir;
 end;
 
 function TGikoSys.GetSkinDir: string;
 begin
-       Result := IncludeTrailingPathDelimiter(GetConfigDir + SKIN_DIR_NAME);
+       Result := Setting.GetSkinDir;
 end;
 
-(*************************************************************************
- *URL\82ð\8dì\90¬(\83R\83s\83y\97p)
- *************************************************************************)
-function TGikoSys.GetURL(BBSID: string; FileName: string): string;
-var
-       Board: TBoard;
+function TGikoSys.GetSkinHeaderFileName: string;
+begin
+       Result := Setting.GetSkinHeaderFileName;
+end;
+
+function TGikoSys.GetSkinFooterFileName: string;
+begin
+       Result := Setting.GetSkinFooterFileName;
+end;
+
+function TGikoSys.GetSkinNewResFileName: string;
+begin
+       Result := Setting.GetSkinNewResFileName;
+end;
+
+function TGikoSys.GetSkinResFileName: string;
+begin
+       Result := Setting.GetSkinResFileName;
+end;
+
+function TGikoSys.GetSkinBookmarkFileName: string;
+begin
+       Result := Setting.GetSkinBookmarkFileName;
+end;
+
+function TGikoSys.GetSkinNewmarkFileName: string;
 begin
-       Board := BoardGroup.BBS2ch.GetBoardFromBBSID(BBSID);
-       Result := UrlToServer(Board.URL) + 'test/read.cgi/' + UrlToID(Board.URL) + '/' + ChangeFileExt(FileName, '') + '/l50';
-       //http://teri.2ch.net/test/read.cgi?bbs=accuse&key=974619522&ls=50
-       //http://pc.2ch.net/test/read.cgi/tech/1003664165/l50
+       Result := Setting.GetSkinNewmarkFileName;
 end;
 
 // UserAgent\8eæ\93¾
@@ -420,17 +468,17 @@ var
        d2: tdatetime;
 begin
        d1 := EncodeDate(1970, 1, 1);
-       d2 := (val * 1000) / (24 * 60 * 60 * 1000);
+       d2 := val / 86400.0;//(val * 1000) / (24 * 60 * 60 * 1000);
        Result := d1 + d2;
 end;
 
-function TGikoSys.DateTimeToInt(ADate: TDateTime): Integer;
+function TGikoSys.DateTimeToInt(ADate: TDateTime): Int64;
 var
        d: TDateTime;
        c: Currency;
 begin
        d := EncodeDate(1970, 1, 1);
-       c := (ADate - d) * 24 * 60 * 60;
+       c := (ADate - d) * 86400; //(ADate - d) * 24 * 60 * 60;
        Result := Trunc(c);
 end;
 
@@ -456,110 +504,131 @@ var
        ResRec: TResRec;
        RoundItem: TRoundItem;
        idx: Integer;
+       usePlugIn : Boolean;
+    tmpStr: string;
 begin
+    if Board.IsThreadDatRead then
+       Exit;
        Board.Clear;
        UnRead := 0;
 //     TmpUpdate := False;
 
+       usePlugIn := Board.IsBoardPlugInAvailable;
+
        FileName := Board.GetFolderIndexFileName;
        if not FileExists(FileName) then CreateThreadDat(Board);
 //     if not FileExists(FileName) then Exit;
 
-       //IsLogFile\97pDAT\83t\83@\83C\83\8b\83\8a\83X\83g
+       {       R := FindFirst(ExtractFileDir(Board.GetFolderIndexFileName) + '\*.dat', 0, SrchRec);
+               while R = 0 do begin
+                       FileList.Add(SrchRec.Name);
+                       R := FindNext(SrchRec);
+               end;
+               FindClose(SrchRec);}
+
        FileList := TStringList.Create;
        FileList.Sorted := True;
+       TmpFileList := TStringList.Create;
+       TmpFileList.Sorted := True;
+
+       //IsLogFile\97pDAT\83t\83@\83C\83\8b\83\8a\83X\83g
        GetFileList(ExtractFileDir(Board.GetFolderIndexFileName), '*.dat', FileList, False, False);
 
        //\91O\89ñ\88Ù\8fí\8fI\97¹\8e\9e\97pTmp\83t\83@\83C\83\8b\83\8a\83X\83g
-       TmpFileList := TStringList.Create;
-       TmpFileList.Sorted := True;
        GetFileList(ExtractFileDir(Board.GetFolderIndexFileName), '*.tmp', TmpFileList, False, False);
 
-{      R := FindFirst(ExtractFileDir(Board.GetFolderIndexFileName) + '\*.dat', 0, SrchRec);
-       while R = 0 do begin
-               FileList.Add(SrchRec.Name);
-               R := FindNext(SrchRec);
-       end;
-       FindClose(SrchRec);}
-
        sl := TStringList.Create;
        try
-               if FileExists(FileName) then
+               if FileExists(FileName) then begin
                        sl.LoadFromFile(FileName);
 
-               //\82Q\8ds\96Ú\82©\82ç\81i\82P\8ds\96Ú\82Í\83o\81[\83W\83\87\83\93\81j
-               for i := 1 to sl.Count - 1 do begin
-                       Rec := ParseIndexLine(sl[i]);
-
-                       ThreadItem := TThreadItem.Create;
-                       ThreadItem.BeginUpdate;
-                       ThreadItem.No := Rec.FNo;
-                       ThreadItem.FileName := Rec.FFileName;
-                       ThreadItem.Title := Rec.FTitle;
-                       ThreadItem.Count := Rec.FCount;
-                       ThreadItem.Size := Rec.FSize;
-//                     ThreadItem.RoundNo := Rec.FRoundNo;
-                       ThreadItem.RoundDate := Rec.FRoundDate;
-                       ThreadItem.LastModified := Rec.FLastModified;
-                       ThreadItem.Kokomade := Rec.FKokomade;
-                       ThreadItem.NewReceive := Rec.FNewReceive;
-//                     ThreadItem.Round := Rec.FRound;
-                       ThreadItem.UnRead := Rec.FUnRead;
-                       ThreadItem.ScrollTop := Rec.FScrollTop;
-                       ThreadItem.AllResCount := Rec.FAllResCount;
-                       ThreadItem.NewResCount := Rec.FNewResCount;
-                       ThreadItem.AgeSage := Rec.FAgeSage;
-                       ThreadItem.ParentBoard := Board;
-
-                       //IsLogFile\83`\83F\83b\83N
-                       ThreadItem.IsLogFile := False;
-                       if FileList.Count <> 0 then begin
-                               if FileList.Find(ThreadItem.FileName, Index) then begin
-                                       ThreadItem.IsLogFile := True;
-                                       FileList.Delete(Index);
-                               end;
-                       end;
-
-                       //\8f\84\89ñ\83\8a\83X\83g\82É\91\8dÝ\82µ\82½\82ç\8f\84\89ñ\83t\83\89\83O\83Z\83b\83g
-                       if ThreadItem.IsLogFile then begin
-                               idx := RoundList.Find(ThreadItem);
-                               if idx <> -1 then begin
-                                       RoundItem := RoundList.Items[idx, grtItem];
-                                       ThreadItem.RoundName := RoundItem.RoundName;
-                                       ThreadItem.Round := True;
-                               end;
-                       end;
-
-                       //\91O\89ñ\88Ù\8fí\8fI\97¹\8e\9e\83`\83F\83b\83N
-                       if TmpFileList.Count <> 0 then begin
-                               if TmpFileList.Find(ChangeFileExt(ThreadItem.FileName, '.tmp'), Index) then begin
-                                       ini := TMemIniFile.Create(ChangeFileExt(ThreadItem.GetThreadFileName, '.tmp'));
-                                       try
-                                               ThreadItem.RoundDate := ini.ReadDateTime('Setting', 'RoundDate', ZERO_DATE);
-                                               ThreadItem.LastModified := ini.ReadDateTime('Setting', 'LastModified', ZERO_DATE);
-                                               ThreadItem.Size := ini.ReadInteger('Setting', 'Size', 0);
-                                               ThreadItem.Count := ini.ReadInteger('Setting', 'Count', 0);
-                                               ThreadItem.NewReceive := ini.ReadInteger('Setting', 'NewReceive', 0);
-                                               ThreadItem.Round := ini.ReadBool('Setting', 'Round', False);
-                                               ThreadItem.UnRead := False;//ini.ReadBool('Setting', 'UnRead', False);
-                                               ThreadItem.ScrollTop := ini.ReadInteger('Setting', 'ScrollTop', 0);
-                                               ThreadItem.AllResCount := ini.ReadInteger('Setting', 'AllResCount', 0);
-                                               ThreadItem.NewResCount := ini.ReadInteger('Setting', 'NewResCount', 0);
-                                               ThreadItem.AgeSage := TGikoAgeSage(ini.ReadInteger('Setting', 'AgeSage', Ord(gasNone)));
-                                       finally
-                                               ini.Free;
-                                       end;
-                                       TmpFileList.Delete(Index);
-                               end;
-                       end;
-
-                       ThreadItem.EndUpdate;
-                       Board.Add(ThreadItem);
-
-//                     if (ThreadItem.IsLogFile) and (ThreadItem.Count > ThreadItem.Kokomade) then
-                       if (ThreadItem.IsLogFile) and (ThreadItem.UnRead) then
-                               Inc(UnRead);
+            //\82Q\8ds\96Ú\82©\82ç\81i\82P\8ds\96Ú\82Í\83o\81[\83W\83\87\83\93\81j
+            for i := sl.Count - 1 downto 1 do begin
+                Rec := ParseIndexLine(sl[i]);
+                if usePlugIn then
+                    ThreadItem := TThreadItem.Create(
+                        Board.BoardPlugIn,
+                        Board.BoardPlugIn.FileName2ThreadURL( DWORD( Board ), Rec.FFileName ) )
+                else
+                    ThreadItem := TThreadItem.Create(
+                        nil,
+                        Get2chBoard2ThreadURL( Board, ChangeFileExt( Rec.FFileName, '' ) ) );
+
+                if FileList.Count <> 0 then
+                    if FileList.Find( ThreadItem.FileName, Index ) then
+                        //ThreadItem.IsLogFile := True;
+                        FileList.Delete( Index );
+
+                ThreadItem.BeginUpdate;
+                ThreadItem.No := Rec.FNo;
+                ThreadItem.FileName := Rec.FFileName;
+                ThreadItem.Title := Rec.FTitle;
+                ThreadItem.Count := Rec.FCount;
+                ThreadItem.Size := Rec.FSize;
+    //                 ThreadItem.RoundNo := Rec.FRoundNo;
+                ThreadItem.RoundDate := Rec.FRoundDate;
+                ThreadItem.LastModified := Rec.FLastModified;
+                ThreadItem.Kokomade := Rec.FKokomade;
+                ThreadItem.NewReceive := Rec.FNewReceive;
+    //                 ThreadItem.Round := Rec.FRound;
+                ThreadItem.UnRead := Rec.FUnRead;
+                ThreadItem.ScrollTop := Rec.FScrollTop;
+                ThreadItem.AllResCount := Rec.FAllResCount;
+                ThreadItem.NewResCount := Rec.FNewResCount;
+                ThreadItem.AgeSage := Rec.FAgeSage;
+                ThreadItem.ParentBoard := Board;
+
+                //\8f\84\89ñ\83\8a\83X\83g\82É\91\8dÝ\82µ\82½\82ç\8f\84\89ñ\83t\83\89\83O\83Z\83b\83g
+                if ThreadItem.IsLogFile then begin
+                    idx := RoundList.Find(ThreadItem);
+                    if idx <> -1 then begin
+                        RoundItem := RoundList.Items[idx, grtItem];
+                        ThreadItem.RoundName := RoundItem.RoundName;
+                        ThreadItem.Round := True;
+                    end;
+                end;
+
+                //\91O\89ñ\88Ù\8fí\8fI\97¹\8e\9e\83`\83F\83b\83N
+                if TmpFileList.Count <> 0 then begin
+                    if TmpFileList.Find(ChangeFileExt(ThreadItem.FileName, '.tmp'), Index) then begin
+                        ini := TMemIniFile.Create(ChangeFileExt(ThreadItem.GetThreadFileName, '.tmp'));
+                        try
+                            //ThreadItem.RoundDate := ini.ReadDateTime('Setting', 'RoundDate', ZERO_DATE);
+                            tmpStr := ini.ReadString('Setting', 'RoundDate', DateTimeToStr(ZERO_DATE));
+                            ThreadItem.RoundDate := ConvertDateTimeString(tmpStr);
+
+                            //ThreadItem.LastModified := ini.ReadDateTime('Setting', 'LastModified', ZERO_DATE);
+                            tmpStr := ini.ReadString('Setting', 'LastModified', DateTimeToStr(ZERO_DATE));
+                            ThreadItem.LastModified := ConvertDateTimeString(tmpStr);
+
+                            ThreadItem.Size := ini.ReadInteger('Setting', 'Size', 0);
+                            if ThreadItem.Size = 0 then begin
+                                ThreadItem.Size := FileSizeByName(ThreadItem.FileName) - ThreadItem.Count;
+                            end;
+                            ThreadItem.Count := ini.ReadInteger('Setting', 'Count', 0);
+                            ThreadItem.NewReceive := ini.ReadInteger('Setting', 'NewReceive', 0);
+                            ThreadItem.Round := ini.ReadBool('Setting', 'Round', False);
+                            ThreadItem.UnRead := False;//ini.ReadBool('Setting', 'UnRead', False);
+                            ThreadItem.ScrollTop := ini.ReadInteger('Setting', 'ScrollTop', 0);
+                            ThreadItem.AllResCount := ini.ReadInteger('Setting', 'AllResCount', ThreadItem.Count);
+                            ThreadItem.NewResCount := ini.ReadInteger('Setting', 'NewResCount', 0);
+                            ThreadItem.AgeSage := TGikoAgeSage(ini.ReadInteger('Setting', 'AgeSage', Ord(gasNone)));
+                        finally
+                            ini.Free;
+                        end;
+                        TmpFileList.Delete(Index);
+                    end;
+                end;
+
+                ThreadItem.EndUpdate;
+                Board.Add(ThreadItem);
+
+    //                 if (ThreadItem.IsLogFile) and (ThreadItem.Count > ThreadItem.Kokomade) then
+                if (ThreadItem.IsLogFile) and (ThreadItem.UnRead) then
+                    Inc(UnRead);
+            end;
                end;
+
                if UnRead <> Board.UnRead then
                        Board.UnRead := UnRead;
 
@@ -568,31 +637,41 @@ begin
                        FileName := ExtractFileDir(Board.GetFolderIndexFileName) + '\' + FileList[i];
 
                        ResRec := DivideStrLine(ReadThreadFile(FileName, 1));
-                       ThreadItem := TThreadItem.Create;
+                       if usePlugIn then
+                               ThreadItem := TThreadItem.Create(
+                                       Board.BoardPlugIn,
+                                       Board.BoardPlugIn.FileName2ThreadURL( DWORD( Board ), FileList[i] ) )
+                       else
+                               ThreadItem := TThreadItem.Create(
+                                       nil, Get2chBoard2ThreadURL( Board, ChangeFileExt( FileList[i], '' ) ) );
+
+            ThreadItem.BeginUpdate;
+            ThreadItem.FilePath := FileName;
                        ThreadItem.No := Board.Count + 1;
                        ThreadItem.FileName := FileList[i];
                        ThreadItem.Title := ResRec.FTitle;
                        ThreadItem.Count := GetFileLineCount(FileName);
                        ThreadItem.AllResCount := ThreadItem.Count;
-                       ThreadItem.NewResCount := 0;
-                       ThreadItem.Size := 0;
+                       ThreadItem.NewResCount := ThreadItem.Count;
+                       ThreadItem.Size := FileSizeByName(FileName) - ThreadItem.Count;//1byte\82¸\82ê\82é\82Æ\82«\82ª\82 \82é\82¯\82Ç\82»\82ê\82Í\82 \82«\82ç\82ß\82é
                        ThreadItem.RoundDate := ZERO_DATE;
                        ThreadItem.LastModified := ZERO_DATE;
                        ThreadItem.Kokomade := -1;
-                       ThreadItem.NewReceive := 0;
+                       ThreadItem.NewReceive := ThreadItem.Count;
                        ThreadItem.ParentBoard := Board;
                        ThreadItem.IsLogFile := True;
                        ThreadItem.Round := False;
                        ThreadItem.UnRead := False;
                        ThreadItem.ScrollTop := 0;
                        ThreadItem.AgeSage := gasNone;
+            ThreadItem.EndUpdate;
                        Board.Add(ThreadItem);
                end;
        finally
                sl.Free;
+               FileList.Free;
+               TmpFileList.Free;
        end;
-       FileList.Free;
-       TmpFileList.Free;
        Board.IsThreadDatRead := True;
 end;
 
@@ -662,23 +741,56 @@ procedure TGikoSys.WriteThreadDat(Board: TBoard);
 //     Values: array[Boolean] of string = ('0', '1');
 var
        i: integer;
+    Index: Integer;
+    tmpSize: Integer;
        FileName: string;
        sl: TStringList;
        s: string;
-       FileList: TStringList;
+       TmpFileList: TStringList;
+    ini : TMemIniFIle;
 begin
        if not Board.IsThreadDatRead then
                Exit;
        FileName := Board.GetFolderIndexFileName;
-       ForceDirectoriesEx(Board.ParentCategory.ParentBBS2ch.GetLogFolder + Board.BBSID);
+       ForceDirectoriesEx( ExtractFilePath( FileName ) );
 
        sl := TStringList.Create;
+    TmpFileList := TStringList.Create;
        try
+       GetFileList(ExtractFileDir(Board.GetFolderIndexFileName), '*.tmp', TmpFileList, False, true);
+
+        sl.BeginUpdate;
                sl.Add(FOLDER_INDEX_VERSION);
                for i := 0 to Board.Count - 1 do begin
                        if Board.Items[i].No = 0 then
                                Board.Items[i].No := i + 1;
 
+                       if TmpFileList.Count <> 0 then begin
+                               if TmpFileList.Find(ChangeFileExt(Board.Items[i].FileName, '.tmp'), Index) then begin
+                                       ini := TMemIniFile.Create(ChangeFileExt(Board.Items[i].GetThreadFileName, '.tmp'));
+                    try
+                        tmpSize := ini.ReadInteger('Setting', 'Size', 0);
+                       if Board.Items[i].Size <  tmpSize then begin
+                                                       //Board.Items[i].RoundDate := ini.ReadDateTime('Setting', 'RoundDate', ZERO_DATE);
+                                                       //Board.Items[i].LastModified := ini.ReadDateTime('Setting', 'LastModified', ZERO_DATE);
+                                                       Board.Items[i].Size := tmpSize;
+                                                       Board.Items[i].Count := ini.ReadInteger('Setting', 'Count', 0);
+                                                       Board.Items[i].NewReceive := ini.ReadInteger('Setting', 'NewReceive', 0);
+                                                       //Board.Items[i].Round := ini.ReadBool('Setting', 'Round', False);
+                                                       //Board.Items[i].UnRead := False;//ini.ReadBool('Setting', 'UnRead', False);
+                                                       //Board.Items[i].ScrollTop := ini.ReadInteger('Setting', 'ScrollTop', 0);
+                                                       Board.Items[i].AllResCount := ini.ReadInteger('Setting', 'AllResCount', Board.Items[i].Count);
+                                                       Board.Items[i].NewResCount := ini.ReadInteger('Setting', 'NewResCount', 0);
+                                                       //Board.Items[i].AgeSage := TGikoAgeSage(ini.ReadInteger('Setting', 'AgeSage', Ord(gasNone)));
+                        end;
+                                       finally
+                                               ini.Free;
+                                       end;
+                    DeleteFile(TmpFileList.Strings[Index]);
+                                       TmpFileList.Delete(Index);
+                               end;
+                       end;
+
                        s := Format('%x', [Board.Items[i].No]) + #1
                                 + Board.Items[i].FileName + #1
                                 + Board.Items[i].Title + #1
@@ -697,19 +809,15 @@ begin
 
                        sl.Add(s);
                end;
-
+        sl.EndUpdate;
                sl.SaveToFile(FileName);
 
-               FileList := TStringList.Create;
-               try
-                       GetFileList(ExtractFileDir(Board.GetFolderIndexFileName), '*.tmp', FileList, False, True);
-                       for i := 0 to FileList.Count - 1 do begin
-                               DeleteFile(FileList[i]);
-                       end;
-               finally
-                       FileList.Free;
-               end;
+        for i := 0 to TmpFileList.Count - 1 do begin
+               DeleteFile(TmpFileList[i]);
+        end;
+
        finally
+       TmpFileList.Free;
                sl.Free;
        end;
 end;
@@ -743,7 +851,7 @@ end;
 
 //\8ew\92è\83t\83H\83\8b\83_\93à\82Ì\8ew\92è\83t\83@\83C\83\8b\88ê\97\97\82ð\8eæ\93¾\82·\82é
 // ListFiles('c:\', '*.txt', list, True);
-procedure TGikoSys.GetFileList(Path: string; Mask: string; List: TStringList; SubDir: Boolean; IsPathAdd: Boolean);
+procedure TGikoSys.GetFileList(Path: string; Mask: string; var List: TStringList; SubDir: Boolean; IsPathAdd: Boolean);
 var
        rc: Integer;
        SearchRec : TSearchRec;
@@ -771,6 +879,7 @@ begin
        finally
                SysUtils.FindClose(SearchRec);
        end;
+    List.Sort;
 end;
 
 //\8ew\92è\83t\83H\83\8b\83_\93à\82Ì\83f\83B\83\8c\83N\83g\83\8a\88ê\97\97\82ð\8eæ\93¾\82·\82é
@@ -801,11 +910,109 @@ begin
        end;
 end;
 
+// \83X\83L\83\93\82ð\93Ç\82Ý\8d\9e\82Ý\81A\92l\82ð\92u\8a·\82·\82é
+function TGikoSys.LoadFromSkin(
+       fileName: string;
+       ThreadItem: TThreadItem;
+       SizeByte: Integer
+): string;
+var
+       Skin: TStringList;
+begin
+
+       Skin := TStringList.Create;
+       try
+               if FileExists( fileName ) then begin
+                       Skin.LoadFromFile( fileName );
+
+                       // \82â\82è\82©\82½\82ª\8bê\82µ\82¢\82¯\82Ç\81A\83I\83v\83V\83\87\83\93\83_\83C\83A\83\8d\83O\82Ì\83v\83\8c\83r\83\85\81[\97p try
+                       try
+                               if ThreadItem.ParentBoard <> nil then
+                                       if ThreadItem.ParentBoard.ParentCategory <> nil then
+                       CustomStringReplace( Skin, '<BBSNAME/>', ThreadItem.ParentBoard.ParentCategory.ParenTBBS.Title);
+                    CustomStringReplace( Skin, '<THREADURL/>', ThreadItem.URL);
+                       except end;
+            CustomStringReplace( Skin, '<BOARDNAME/>', ThreadItem.ParentBoard.Title);
+            CustomStringReplace( Skin, '<BOARDURL/>', ThreadItem.ParentBoard.URL);
+            CustomStringReplace( Skin, '<THREADNAME/>', ThreadItem.Title);
+            CustomStringReplace( Skin, '<SKINPATH/>', Setting.CSSFileName);
+            CustomStringReplace( Skin, '<GETRESCOUNT/>', IntToStr( ThreadItem.NewReceive - 1 ));
+            CustomStringReplace( Skin, '<NEWRESCOUNT/>', IntToStr( ThreadItem.NewResCount ));
+            CustomStringReplace( Skin, '<ALLRESCOUNT/>', IntToStr( ThreadItem.AllResCount ));
+
+            CustomStringReplace( Skin, '<NEWDATE/>',FormatDateTime('yyyy/mm/dd(ddd) hh:mm', ThreadItem.RoundDate));
+            CustomStringReplace( Skin, '<SIZEKB/>', IntToStr( Floor( SizeByte / 1024 ) ));
+            CustomStringReplace( Skin, '<SIZE/>', IntToStr( SizeByte ));
+
+                       //----- \82Æ\82è\82 \82¦\82¸\82©\82¿\82ã\81`\82µ\82á\8cÝ\8a·\97p\81B\83R\83\81\83\93\83g\83A\83E\83g\82µ\82Ä\82à\82æ\82µ
+                       // \82â\82è\82©\82½\82ª\8bê\82µ\82¢\82¯\82Ç\81A\83I\83v\83V\83\87\83\93\83_\83C\83A\83\8d\83O\82Ì\83v\83\8c\83r\83\85\81[\97p try
+                       try
+                               if ThreadItem.ParentBoard <> nil then
+                                       if ThreadItem.ParentBoard.ParentCategory <> nil then
+                       CustomStringReplace( Skin, '&BBSNAME', ThreadItem.ParentBoard.ParentCategory.ParenTBBS.Title);
+                    CustomStringReplace( Skin, '&THREADURL', ThreadItem.URL);
+                       except end;
+            CustomStringReplace( Skin, '&BOARDNAME', ThreadItem.ParentBoard.Title);
+            CustomStringReplace( Skin, '&BOARDURL', ThreadItem.ParentBoard.URL);
+            CustomStringReplace( Skin, '&THREADNAME', ThreadItem.Title);
+            CustomStringReplace( Skin, '&SKINPATH', Setting.CSSFileName);
+            CustomStringReplace( Skin, '&GETRESCOUNT', IntToStr( ThreadItem.NewReceive - 1 ));
+            CustomStringReplace( Skin, '&NEWRESCOUNT', IntToStr( ThreadItem.NewResCount ));
+            CustomStringReplace( Skin, '&ALLRESCOUNT', IntToStr( ThreadItem.AllResCount ));
+
+            CustomStringReplace( Skin, '&NEWDATE', FormatDateTime('yyyy/mm/dd(ddd) hh:mm', ThreadItem.RoundDate));
+            CustomStringReplace( Skin, '&SIZEKB', IntToStr( Floor( SizeByte / 1024 ) ));
+            CustomStringReplace( Skin, '&SIZE', IntToStr( SizeByte ));
+                       //----- \82±\82±\82Ü\82Å
+               end;
+               Result := Skin.Text;
+       finally
+               Skin.Free;
+       end;
+end;
+
+// \83\8c\83X\82Ì\92l\82ð\92u\8a·\82·\82é
+function TGikoSys.SkinedRes(
+       skin: string;
+       Res: TResRec;
+       No: string
+): string;
+begin
+
+       try
+               Skin := CustomStringReplace( Skin, '<NUMBER/>',
+                       '<a href="menu:' + No + '" name="' + No + '">' + No + '</a>');
+               Skin := CustomStringReplace( Skin, '<PLAINNUMBER/>', No);
+               Skin := CustomStringReplace( Skin, '<NAME/>', '<b>' + Res.FName + '</b>');
+               Skin := CustomStringReplace( Skin, '<MAILNAME/>',
+                       '<a href="mailto:' + Res.FMailTo + '"><b>' + Res.FName + '</b></a>');
+               Skin := CustomStringReplace( Skin, '<MAIL/>', Res.FMailTo);
+               Skin := CustomStringReplace( Skin, '<DATE/>', Res.FDateTime);
+               Skin := CustomStringReplace( Skin, '<MESSAGE/>', Res.FBody);
+
+               //----- \82©\82¿\82ã\81`\82µ\82á\8cÝ\8a·\97p\81B\83R\83\81\83\93\83g\83A\83E\83g\82µ\82Ä\82à\82æ\82µ
+               Skin := CustomStringReplace( Skin, '&NUMBER',
+                       '<a href="menu:' + No + '" name="' + No + '">' + No + '</a>');
+               Skin := CustomStringReplace( Skin, '&PLAINNUMBER', No);
+               Skin := CustomStringReplace( Skin, '&NAME', '<b>' + Res.FName + '</b>');
+               Skin := CustomStringReplace( Skin, '&MAILNAME',
+                       '<a href="mailto:' + Res.FMailTo + '"><b>' + Res.FName + '</b></a>');
+               Skin := CustomStringReplace( Skin, '&MAIL', Res.FMailTo);
+               Skin := CustomStringReplace( Skin, '&DATE', Res.FDateTime);
+               Skin := CustomStringReplace( Skin, '&MESSAGE', Res.FBody);
+               //----- \82±\82±\82Ü\82Å
+
+               Result := Skin;
+       finally
+       end;
+
+end;
+
 procedure TGikoSys.CreateHTML2(doc: Variant; ThreadItem: TThreadItem; var sTitle: string);
 var
        i: integer;
        No: string;
-               //bufList : TStringList;
+       //bufList : TStringList;
        ReadList: TStringList;
        SaveList: TStringList;
        CSSFileName: string;
@@ -813,155 +1020,265 @@ var
        FileName: string;
        NewReceiveNo: Integer;
        Res: TResRec;
-       Skin: TStringList;
-  SkinHeaderFileName: string;
-  SkinNewRes: TStringList;
-  SkinRes: TStringList;
-  SizeByte: Integer;
+       boardPlugIn : TBoardPlugIn;
+
+       UserOptionalStyle: string;
+       SkinHeader: string;
+       SkinNewRes: string;
+       SkinRes: string;
+//     SizeByte: Integer;
+
+       function LoadSkin( fileName: string ): string;
+       begin
+               Result := LoadFromSkin( fileName, ThreadItem, ThreadItem.Size );
+       end;
+       function ReplaceRes( skin: string ): string;
+       begin
+               Result := SkinedRes( skin, Res, No );
+       end;
 begin
+       if ThreadItem <> nil then begin
+               if ThreadItem.IsBoardPlugInAvailable then begin
+                       //===== \83v\83\89\83O\83C\83\93\82É\82æ\82é\95\\8e¦
+                       boardPlugIn             := ThreadItem.BoardPlugIn;
+                       NewReceiveNo    := ThreadItem.NewReceive;
+                       // \83t\83H\83\93\83g\82â\83T\83C\83Y\82Ì\90Ý\92è
+                       if Length( GikoSys.Setting.BrowserFontName ) > 0 then
+                               UserOptionalStyle := UserOptionalStyle +
+                                                               'font-family:"' + GikoSys.Setting.BrowserFontName + '";';
+                       if GikoSys.Setting.BrowserFontSize <> 0 then
+                               UserOptionalStyle := UserOptionalStyle +
+                                                               'font-size:' + IntToStr( GikoSys.Setting.BrowserFontSize ) + 'pt;';
+                       if GikoSys.Setting.BrowserFontColor <> -1 then
+                               UserOptionalStyle := UserOptionalStyle +
+                                                               'color:#' + IntToHex( GikoSys.Setting.BrowserFontColor, 6 ) + ';';
+                       if GikoSys.Setting.BrowserBackColor <> -1 then
+                               UserOptionalStyle := UserOptionalStyle +
+                                                               'background-color:#' + IntToHex( GikoSys.Setting.BrowserBackColor, 6 ) + ';';
+                       case GikoSys.Setting.BrowserFontBold of
+                               -1: UserOptionalStyle := UserOptionalStyle + 'font-weight:normal;';
+                               1: UserOptionalStyle := UserOptionalStyle + 'font-weight:bold;';
+                       end;
+                       case GikoSys.Setting.BrowserFontItalic of
+                               -1: UserOptionalStyle := UserOptionalStyle + 'font-style:normal;';
+                               1: UserOptionalStyle := UserOptionalStyle + 'font-style:italic;';
+                       end;
+
+                       SaveList := TStringList.Create;
+                       try
+                               doc.open;
+                               // \95\8e\9a\83R\81[\83h\82Í\83v\83\89\83O\83C\83\93\82É\94C\82¹\82é
+                               // doc.charset := 'Shift_JIS';
+                               threadItem.SizeByte := 0;
+
+                               // \83w\83b\83_
+                               SaveList.Add( boardPlugIn.GetHeader( DWORD( threadItem ),
+                                       '<style type="text/css">body {' + UserOptionalStyle + '}</style>' ) );
+
+                               for i := 0 to threadItem.Count - 1 do begin
+                                       if (OnlyAHundredRes = true) and ( i <> 0 ) and ( (threadItem.Count-i) > 101 ) then begin
+                                               Continue;
+                                       end;
+
+                                       // \90V\92\85\83}\81[\83N
+                                       if (NewReceiveNo = (i + 1)) or ((NewReceiveNo = 0) and (i = 0)) then begin
+                                               try
+                                                       if GikoSys.Setting.UseSkin then begin
+                                                               if FileExists( GetSkinNewmarkFileName ) then
+                                                                       SaveList.Add( LoadSkin( GetSkinNewmarkFileName ) )
+                                                               else
+                                                                       SaveList.Add( '<a name="new"></a>' );
+                                                       end else if GikoSys.Setting.UseCSS then begin
+                                                               SaveList.Add('<a name="new"></a><div class="new">\90V\92\85\83\8c\83X <span class="newdate">' + FormatDateTime('yyyy/mm/dd(ddd) hh:mm', ThreadItem.RoundDate) + '</span></div>');
+                                                       end else begin
+                                                               SaveList.Add('</dl>');
+                                                               SaveList.Add('<a name="new"></a>');
+                                                               SaveList.Add('<table width="100%" bgcolor="#3333CC" cellpadding="0" cellspacing="1"><tr><td align="center" bgcolor="#6666FF" valign="middle"><font size="-1" color="#ffffff"><b>\90V\92\85\83\8c\83X ' + FormatDateTime('yyyy/mm/dd(ddd) hh:mm', ThreadItem.RoundDate) + '</b></font></td></tr></table>');
+                                                               SaveList.Add('<dl>');
+                                                       end;
+                                               except
+                                                       SaveList.Add( '<a name="new"></a>' );
+                                               end;
+                                       end;
+
+                                       // \83\8c\83X
+                                       SaveList.Add( boardPlugIn.GetRes( DWORD( threadItem ), i + 1 ) );
+
+                                       if ThreadItem.Kokomade = (i + 1) then begin
+                                               // \82±\82±\82Ü\82Å\93Ç\82ñ\82¾
+                                               try
+                                                       if GikoSys.Setting.UseSkin then begin
+                                                               if FileExists( GetSkinBookmarkFileName ) then
+                                                                       SaveList.Add( LoadSkin( GetSkinBookmarkFileName ) )
+                                                               else
+                                                                       SaveList.Add( '<a name="koko"></a>' );
+                                                       end else if GikoSys.Setting.UseCSS then begin
+                                                               SaveList.Add('<a name="koko"></a><div class="koko">\83R\83R\82Ü\82Å\93Ç\82ñ\82¾</div>');
+                                                       end else begin
+                                                               SaveList.Add('</dl>');
+                                                               SaveList.Add('<a name="koko"></a><table width="100%" bgcolor="#55AA55" cellpadding="0" cellspacing="1"><tr><td align="center" bgcolor="#77CC77" valign="middle"><font size="-1" color="#ffffff"><b>\83R\83R\82Ü\82Å\93Ç\82ñ\82¾</b></font></td></tr></table>');
+                                                               SaveList.Add('<dl>');
+                                                       end;
+                                               except
+                                                       SaveList.Add( '<a name="koko"></a>' );
+                                               end;
+                                       end;
+
+                                       threadItem.SizeByte := threadItem.SizeByte + Length( SaveList.Text );
+                                       doc.Write(SaveList.Text);
+                                       SaveList.Clear;
+                               end;
+
+                               threadItem.SizeByte := threadItem.SizeByte + Length( SaveList.Text );
+
+                               // \83X\83L\83\93(\83t\83b\83^)
+                               SaveList.Add( boardPlugIn.GetFooter( DWORD( threadItem ), '<a name="bottom"></a>' ) );
+
+                               doc.Write(SaveList.Text);
+                       finally
+                               SaveList.Free;
+                               doc.Close;
+                       end;
+
+                       Exit;
+               end;
+       end;
        ShortDayNames[1] := '\93ú';               ShortDayNames[2] := '\8c\8e';
        ShortDayNames[3] := '\89Î';               ShortDayNames[4] := '\90\85';
        ShortDayNames[5] := '\96Ø';               ShortDayNames[6] := '\8bà';
        ShortDayNames[7] := '\93y';
+//     SizeByte := 0;
        BBSID := ThreadItem.ParentBoard.BBSID;
-       FileName := ThreadItem.FileName;
        NewReceiveNo := ThreadItem.NewReceive;
-       FileName := ThreadItem.GetThreadFileName;
        ReadList := TStringList.Create;
-       FAbon.Deleterlo := FSetting.AbonDeleterlo;
-       FAbon.Replaceul := FSetting.AbonReplaceul;
-       FAbon.AbonPopupRes := FSetting.PopUpAbon;
        try
                if ThreadItem.IsLogFile then begin
+                       FileName := ThreadItem.GetThreadFileName;
                        ReadList.LoadFromFile(FileName);
                        FAbon.IndividualAbon(ReadList, ChangeFileExt(FileName,'.NG'));
                        FAbon.Execute(ReadList);                //       \82 \82Ú\81`\82ñ\82µ\82Ä
                        FSelectResFilter.Execute(ReadList); //\83\8c\83X\82Ì\83t\83B\83\8b\83^\83\8a\83\93\83O\82ð\82·\82é
                        Res := DivideStrLine(ReadList[0]);
-                       Res.FTitle := StringReplace(Res.FTitle, '\81\97\81M', ',', [rfReplaceAll]);
+                       Res.FTitle := CustomStringReplace(Res.FTitle, '\81\97\81M', ',');
                        sTitle := Res.FTitle;
-
                end else begin
-                       sTitle := StringReplace(ThreadItem.Title, '\81\97\81M', ',', [rfReplaceAll]);
+                       sTitle := CustomStringReplace(ThreadItem.Title, '\81\97\81M', ',');
                end;
                SaveList := TStringList.Create;
                try
                        doc.open;
                        doc.charset := 'Shift_JIS';
 
-                       CSSFileName := GetStyleSheetDir + Setting.CSSFileName;
-      SkinHeaderFileName := Setting.CSSFileName + SKIN_HEADER_FILE_NAME;
-      if GikoSys.Setting.UseCSS and
-       (Pos(GetSkinDir, Setting.CSSFileName) > 0) and
-        FileExists( SkinHeaderFileName ) then begin
-       // \83X\83L\83\93\8eg\97p
-
-                               SaveList.Add('<html><head>');
-                               SaveList.Add('<meta http-equiv="Content-type" content="text/html; charset=Shift_JIS">');
-                               SaveList.Add('<title>' + sTitle + '</title>');
-
-                               // CSS \82Ì\90Ý\92è
-                               // SaveList.Add('<link rel="stylesheet" href="'+CSSFileName+'" type="text/css">');
+                       // \83t\83H\83\93\83g\82â\83T\83C\83Y\82Ì\90Ý\92è
+                       if Length( GikoSys.Setting.BrowserFontName ) > 0 then
+                               UserOptionalStyle := UserOptionalStyle +
+                                                               'font-family:"' + GikoSys.Setting.BrowserFontName + '";';
+                       if GikoSys.Setting.BrowserFontSize <> 0 then
+                               UserOptionalStyle := UserOptionalStyle +
+                                                               'font-size:' + IntToStr( GikoSys.Setting.BrowserFontSize ) + 'pt;';
+                       if GikoSys.Setting.BrowserFontColor <> -1 then
+                               UserOptionalStyle := UserOptionalStyle +
+                                                               'color:#' + IntToHex( GikoSys.Setting.BrowserFontColor, 6 ) + ';';
+                       if GikoSys.Setting.BrowserBackColor <> -1 then
+                               UserOptionalStyle := UserOptionalStyle +
+                                                               'background-color:#' + IntToHex( GikoSys.Setting.BrowserBackColor, 6 ) + ';';
+                       case GikoSys.Setting.BrowserFontBold of
+                               -1: UserOptionalStyle := UserOptionalStyle + 'font-weight:normal;';
+                               1: UserOptionalStyle := UserOptionalStyle + 'font-weight:bold;';
+                       end;
+                       case GikoSys.Setting.BrowserFontItalic of
+                               -1: UserOptionalStyle := UserOptionalStyle + 'font-style:normal;';
+                               1: UserOptionalStyle := UserOptionalStyle + 'font-style:italic;';
+                       end;
 
+                       CSSFileName := GetStyleSheetDir + Setting.CSSFileName;
+                       if GikoSys.Setting.UseSkin then begin
+                               // \83X\83L\83\93\8eg\97p
                                // \83X\83L\83\93\82Ì\90Ý\92è
-        Skin := TStringList.Create;
                                try
-                                       Skin.LoadFromFile( SkinHeaderFileName );
-          Skin.Text := StringReplace( Skin.Text, '&GETRESCOUNT', IntToStr( NewReceiveNo ), [rfReplaceAll] );
-          Skin.Text := StringReplace( Skin.Text, '&SKINPATH', Setting.CSSFileName, [rfReplaceAll] );
-                                       SaveList.AddStrings( Skin );
-        finally
-                                       Skin.Free;
+                                       SkinHeader := LoadSkin( GetSkinHeaderFileName );
+                                       if Length( UserOptionalStyle ) > 0 then
+                                               SkinHeader := CustomStringReplace( SkinHeader, '</head>',
+                                                       '<style type="text/css">body {' + UserOptionalStyle + '}</style></head>');
+                                       SaveList.Add( SkinHeader );
+                               except
+                               end;
+                               try
+                                       SkinNewRes := LoadSkin( GetSkinNewResFileName );
+                               except
+                                                               end;
+                               try
+                                       SkinRes := LoadSkin( GetSkinResFileName );
+                               except
                                end;
-        SkinNewRes := TStringList.Create;
-        SkinRes := TStringList.Create;
-        try
-               SkinNewRes.LoadFromFile( Setting.CSSFileName + SKIN_NEWRES_FILE_NAME );
-               SkinRes.LoadFromFile( Setting.CSSFileName + SKIN_RES_FILE_NAME );
-        except
-        end;
 
-                               //SaveList.Add('</head>');
-                               //SaveList.Add('<body>');
-                               //SaveList.Add('<dl id="dl">');
                                SaveList.Add('<a name="top"></a>');
-                               //SaveList.Add('<div class="title">' + sTitle + '</div>');
 
                                for i := 0 to ReadList.Count - 1 do begin
+                                       if (OnlyAHundredRes = true) and ( i <> 0 ) and ( (ReadList.Count-i) > 101 ) then begin
+                                               Continue;
+                                       end;
                                        if (Trim(ReadList[i]) <> '') then begin
                                                No := IntToStr(i + 1);
-                       Skin := TStringList.Create;
-                                               if (NewReceiveNo = (i + 1)) or ((NewReceiveNo = 0) and (i = 0)) then
-               Skin.AddStrings( SkinNewRes )
-            else
-               Skin.AddStrings( SkinRes );
 
                                                Res := DivideStrLine(ReadList[i]);
-                                               Res.FBody := ConvRes(Res.FBody, ThreadItem.ParentBoard.BBSID, ChangeFileExt(ThreadItem.FileName, ''), 'bbs', 'key', 'st', 'to', 'nofirst', 'true');
-
                                                if Res.FType = glt2chOld then begin
-                                                       Res.FMailTo := StringReplace(Res.FMailTo, '\81\97\81M', ',', [rfReplaceAll]);
-                                                       Res.FName := StringReplace(Res.FName, '\81\97\81M', ',', [rfReplaceAll]);
-                                                       Res.FBody := StringReplace(Res.FBody, '\81\97\81M', ',', [rfReplaceAll]);
+                                                       Res.FMailTo := CustomStringReplace(Res.FMailTo, '\81\97\81M', ',');
+                                                       Res.FName := CustomStringReplace(Res.FName, '\81\97\81M', ',');
+                                                       Res.FBody := CustomStringReplace(Res.FBody, '\81\97\81M', ',');
                                                end;
 
                                                Res.FBody := AddAnchorTag(Res.FBody);
+                                               Res.FBody := ConvRes(Res.FBody, ThreadItem.ParentBoard.BBSID, ChangeFileExt(ThreadItem.FileName, ''), 'bbs', 'key', 'st', 'to', 'nofirst', 'true');
+
                                                if Res.FName = '' then
                                                        Res.FName := '&nbsp;';
 
-            Skin.Text := StringReplace( Skin.Text, '&NUMBER', No, [rfReplaceAll] );
-            Skin.Text := StringReplace( Skin.Text, '&NAME', Res.FName, [rfReplaceAll] );
-            Skin.Text := StringReplace( Skin.Text, '&MAIL', Res.FMailTo, [rfReplaceAll] );
-            Skin.Text := StringReplace( Skin.Text, '&DATE', Res.FDateTime, [rfReplaceAll] );
-            Skin.Text := StringReplace( Skin.Text, '&MESSAGE', Res.FBody, [rfReplaceAll] );
-            SaveList.AddStrings( Skin );
-
-            Skin.Free;
-
-            if ThreadItem.Kokomade = (i + 1) then
-              SaveList.Add('<dt><a name="koko">\83R\83R\82Ü\82Å\93Ç\82ñ\82¾</a></dt>');
-                                       end;
-
-                                       //if SaveList.Count > 50 then begin
-                                       if i = 20 then begin
-                                               //Sleep(1);
-                                               //Application.ProcessMessages;
-
-                                               doc.Write(SaveList.Text);
-                                               //while GikoForm.Browser.Busy do begin
-                                               //      Sleep(1);
-                                               //      Application.ProcessMessages;
-                                               //end;
-                                               while (GikoForm.Browser.ReadyState <> READYSTATE_COMPLETE) and
-                                                                       (GikoForm.Browser.ReadyState <> READYSTATE_INTERACTIVE) do begin
-                                                       //Sleep(1);
-                                                       //Application.ProcessMessages;
+                                               // \90V\92\85\83}\81[\83N
+                                               if (NewReceiveNo = (i + 1)) or ((NewReceiveNo = 0) and (i = 0)) then begin
+                                                       try
+                                                               if FileExists( GetSkinNewmarkFileName ) then
+                                                                       SaveList.Add( LoadSkin( GetSkinNewmarkFileName ) )
+                                                               else
+                                                                       SaveList.Add( '<a name="new"></a>' );
+                                                       except
+                                                               SaveList.Add( '<a name="new"></a>' );
+                                                       end;
+                                               end;
+                                               try
+                                                       if NewReceiveNo <= (i + 1) then
+                                                               // \90V\92\85\83\8c\83X
+                                                               SaveList.Add( ReplaceRes( SkinNewRes ) )
+                                                       else
+                                                               // \92Ê\8fí\82Ì\83\8c\83X
+                                                               SaveList.Add( ReplaceRes( SkinRes ) );
+                                               except
+                                               end;
+                                               if ThreadItem.Kokomade = (i + 1) then begin
+                                                       // \82±\82±\82Ü\82Å\93Ç\82ñ\82¾
+                                                       try
+                                                               if FileExists( GetSkinBookmarkFileName ) then
+                                                                       SaveList.Add( LoadSkin( GetSkinBookmarkFileName ) )
+                                                               else
+                                                                       SaveList.Add( '<a name="koko"></a>' );
+                                                       except
+                                                               SaveList.Add( '<a name="koko"></a>' );
+                                                       end;
                                                end;
-                                               SaveList.Clear;
                                        end;
+//                                     SizeByte := SizeByte + Length( SaveList.Text );
+                                       doc.Write(SaveList.Text);
+                                       SaveList.Clear;
                                end;
-
                                SaveList.Add('<a name="bottom"></a>');
-
-        // \83X\83L\83\93(\83t\83b\83^)
-        Skin := TStringList.Create;
+//                             SizeByte := SizeByte + Length( SaveList.Text );
+                               // \83X\83L\83\93(\83t\83b\83^)
                                try
-                                       Skin.LoadFromFile( Setting.CSSFileName + SKIN_FOOTER_FILE_NAME );
-          SizeByte := Length( SaveList.Text );
-          Skin.Text := StringReplace( Skin.Text, '&SIZEKB', IntToStr( Floor( SizeByte / 1024 ) ), [rfReplaceAll] );
-          Skin.Text := StringReplace( Skin.Text, '&SIZE', IntToStr( SizeByte ), [rfReplaceAll] );
-                                       SaveList.AddStrings( Skin );
-        finally
-                                       Skin.Free;
+                                       SaveList.Add( LoadSkin( GetSkinFooterFileName ) );
+                               except
                                end;
-
-                               SaveList.Add('<a name="last"></a>');
-                               SaveList.Add('</body></html>');
-
                                doc.Write(SaveList.Text);
 
-        SkinNewRes.Free;
-        SkinRes.Free;
                        end else if GikoSys.Setting.UseCSS and FileExists(CSSFileName) then begin
                                //CSS\8eg\97p
                                //CSSFileName := GetAppDir + CSS_FILE_NAME;
@@ -970,83 +1287,65 @@ begin
                                SaveList.Add('<meta http-equiv="Content-type" content="text/html; charset=Shift_JIS">');
                                SaveList.Add('<title>' + sTitle + '</title>');
                                SaveList.Add('<link rel="stylesheet" href="'+CSSFileName+'" type="text/css">');
+                               if Length( UserOptionalStyle ) > 0 then
+                                       SaveList.Add('<style type="text/css">body {' + UserOptionalStyle + '}</style>');
                                SaveList.Add('</head>');
                                SaveList.Add('<body>');
                                SaveList.Add('<a name="top"></a>');
                                SaveList.Add('<div class="title">' + sTitle + '</div>');
-                               //doc.Write(SaveList.Text);
-                               //SaveList.Clear;
+                               doc.Write(SaveList.Text);
+                               SaveList.Clear;
                                //Application.ProcessMessages;
                                for i := 0 to ReadList.Count - 1 do begin
+                                       if (OnlyAHundredRes = true) and ( i <> 0 ) and ( (ReadList.Count-i) > 101 ) then begin
+                                               Continue;
+                                       end;
                                        if (Trim(ReadList[i]) <> '') then begin
                                                No := IntToStr(i + 1);
                                                if (NewReceiveNo = (i + 1)) or ((NewReceiveNo = 0) and (i = 0)) then begin
                                                        SaveList.Add('<a name="new"></a><div class="new">\90V\92\85\83\8c\83X <span class="newdate">' + FormatDateTime('yyyy/mm/dd(ddd) hh:mm', ThreadItem.RoundDate) + '</span></div>');
                                                end;
                                                Res := DivideStrLine(ReadList[i]);
+                        Res.FBody := AddAnchorTag(Res.FBody);
                                                Res.FBody := ConvRes(Res.FBody, ThreadItem.ParentBoard.BBSID, ChangeFileExt(ThreadItem.FileName, ''), 'bbs', 'key', 'st', 'to', 'nofirst', 'true');
 
-                                               if Res.FType = glt2chOld then begin
-                                                       Res.FMailTo := StringReplace(Res.FMailTo, '\81\97\81M', ',', [rfReplaceAll]);
-                                                       Res.FName := StringReplace(Res.FName, '\81\97\81M', ',', [rfReplaceAll]);
-                                                       Res.FBody := StringReplace(Res.FBody, '\81\97\81M', ',', [rfReplaceAll]);
-                                               end;
-                                               //Res.FBody := StringReplace(Res.FBody, '&amphearts;', '&hearts;', [rfReplaceAll]);
-                                               //Res.FBody := StringReplace(Res.FBody, '&ampnbsp;', '&nbsp;', [rfReplaceAll]);
-                                               //Res.FBody := StringReplace(Res.FBody, '&amp#', '&#', [rfReplaceAll]);
-                                               //Res.FBody := StringReplace(Res.FBody, '&amp', '&amp;', [rfReplaceAll]);
-                                               Res.FBody := AddAnchorTag(Res.FBody);
                                                if Res.FName = '' then
                                                        Res.FName := '&nbsp;';
                                                if Res.FMailTo = '' then
                                                        SaveList.Add('<a name="' + No + '"></a>'
-                                                                                                + '<div class="header"><span class="no"><a href="giko://?no=' + No + '">' + No + '</a></span> '
-                                                                                                + '<span class="name_label">\96¼\91O\81F</span> '
-                                                                                                + '<span class="name"><b>' + Res.FName + '</b></span> '
-                                                                                                + '<span class="date_label">\93\8a\8de\93ú\81F</span> '
-                                                                                                + '<span class="date">' + Res.FDateTime+ '</span></div>'
-                                                                                                + '<div class="mes">' + Res.FBody + ' </div>')
+                                                                                       + '<div class="header"><span class="no"><a href="menu:' + No + '">' + No + '</a></span> '
+                                                                                       + '<span class="name_label">\96¼\91O\81F</span> '
+                                                                                       + '<span class="name"><b>' + Res.FName + '</b></span> '
+                                                                                       + '<span class="date_label">\93\8a\8de\93ú\81F</span> '
+                                                                                       + '<span class="date">' + Res.FDateTime+ '</span></div>'
+                                                                                                                                                                               + '<div class="mes">' + Res.FBody + ' </div>')
+                                               else if GikoSys.Setting.ShowMail then
+                                                       SaveList.Add('<a name="' + No + '"></a>'
+                                                                                       + '<div class="header"><span class="no"><a href="menu:' + No + '">' + No + '</a></span>'
+                                                                                                                                                                               + '<span class="name_label"> \96¼\91O\81F </span>'
+                                                                                       + '<a class="name_mail" href="mailto:' + Res.FMailTo + '">'
+                                                                                       + '<b>' + Res.FName + '</b></a><span class="mail"> [' + Res.FMailTo + ']</span>'
+                                                                                       + '<span class="date_label"> \93\8a\8de\93ú\81F</span>'
+                                                                                       + '<span class="date"> ' + Res.FDateTime+ '</span></div>'
+                                                                                       + '<div class="mes">' + Res.FBody + ' </div>')
                                                else
-                                                       if GikoSys.Setting.ShowMail then
-                                                               SaveList.Add('<a name="' + No + '"></a>'
-                                                                                                        + '<div class="header"><span class="no"><a href="giko://?no=' + No + '">' + No + '</a></span>'
-                                                                                                        + '<span class="name_label"> \96¼\91O\81F </span>'
-                                                                                                        + '<a class="name_mail" href="mailto:' + Res.FMailTo + '">'
-                                                                                                        + '<b>' + Res.FName + '</b></a><span class="mail"> [' + Res.FMailTo + ']</span>'
-                                                                                                        + '<span class="date_label"> \93\8a\8de\93ú\81F</span>'
-                                                                                                        + '<span class="date"> ' + Res.FDateTime+ '</span></div>'
-                                                                                                        + '<div class="mes">' + Res.FBody + ' </div>')
-                                                       else
-                                                               SaveList.Add('<a name="' + No + '"></a>'
-                                                                                                        + '<div class="header"><span class="no"><a href="giko://?no=' + No + '">' + No + '</a></span>'
-                                                                                                        + '<span class="name_label"> \96¼\91O\81F </span>'
-                                                                                                        + '<a class="name_mail" href="mailto:' + Res.FMailTo + '">'
-                                                                                                        + '<b>' + Res.FName + '</b></a>'
-                                                                                                        + '<span class="date_label"> \93\8a\8de\93ú\81F</span>'
-                                                                                                        + '<span class="date"> ' + Res.FDateTime+ '</span></div>'
-                                                                                                        + '<div class="mes">' + Res.FBody + ' </div>');
+                                                       SaveList.Add('<a name="' + No + '"></a>'
+                                                                                       + '<div class="header"><span class="no"><a href="menu:' + No + '">' + No + '</a></span>'
+                                                                                       + '<span class="name_label"> \96¼\91O\81F </span>'
+                                                                                       + '<a class="name_mail" href="mailto:' + Res.FMailTo + '">'
+                                                                                       + '<b>' + Res.FName + '</b></a>'
+                                                                                       + '<span class="date_label"> \93\8a\8de\93ú\81F</span>'
+                                                                                       + '<span class="date"> ' + Res.FDateTime+ '</span></div>'
+                                                                                                                                                                               + '<div class="mes">' + Res.FBody + ' </div>');
                                                if ThreadItem.Kokomade = (i + 1) then begin
                                                        SaveList.Add('<a name="koko"></a><div class="koko">\83R\83R\82Ü\82Å\93Ç\82ñ\82¾</div>');
                                                end;
                                        end;
-                                       //if SaveList.Count > 50 then begin
-                                       if i = 20 then begin
-                                               //Sleep(1);
-                                               //Application.ProcessMessages;
 
-                                               doc.Write(SaveList.Text);
-                                               //while GikoForm.Browser.Busy do begin
-                                               //      Sleep(1);
-                                               //      Application.ProcessMessages;
-                                               //end;
-                                               while (GikoForm.Browser.ReadyState <> READYSTATE_COMPLETE) and
-                                                                       (GikoForm.Browser.ReadyState <> READYSTATE_INTERACTIVE) do begin
-                                                       //Sleep(1);
-                                                       //Application.ProcessMessages;
-                                               end;
-                                               SaveList.Clear;
-                                       end;
+                                       doc.Write(SaveList.Text);
+                                       SaveList.Clear;
                                end;
+                               //FOnlyAHundredRes
                                SaveList.Add('<a name="bottom"></a>');
                                SaveList.Add('</body></html>');
                                SaveList.Add('<a name="last"></a>');
@@ -1067,6 +1366,9 @@ begin
                                SaveList.Clear;
                                //Application.ProcessMessages;
                                for i := 0 to ReadList.Count - 1 do begin
+                                       if (OnlyAHundredRes = true) and ( i <> 0 ) and ( (ReadList.Count-i) > 101 ) then begin
+                                               Continue;
+                                       end;
                                        if (Trim(ReadList[i]) <> '') then begin
                                                No := IntToStr(i + 1);
 
@@ -1077,35 +1379,30 @@ begin
                                                        SaveList.Add('<dl>');
                                                end;
                                                Res := DivideStrLine(ReadList[i]);
-                                               Res.FBody := ConvRes(Res.FBody, ThreadItem.ParentBoard.BBSID, ChangeFileExt(ThreadItem.FileName, ''), 'bbs', 'key', 'st', 'to', 'nofirst', 'true');
                                                if Res.FType = glt2chOld then begin
-                                                       Res.FMailTo := StringReplace(Res.FMailTo, '\81\97\81M', ',', [rfReplaceAll]);
-                                                       Res.FName := StringReplace(Res.FName, '\81\97\81M', ',', [rfReplaceAll]);
-                                                       Res.FBody := StringReplace(Res.FBody, '\81\97\81M', ',', [rfReplaceAll]);
+                                                       Res.FMailTo := CustomStringReplace(Res.FMailTo, '\81\97\81M', ',');
+                                                       Res.FName := CustomStringReplace(Res.FName, '\81\97\81M', ',');
+                                                       Res.FBody := CustomStringReplace(Res.FBody, '\81\97\81M', ',');
                                                end;
-                                               //Res.FBody := StringReplace(Res.FBody, '&amphearts;', '&hearts;', [rfReplaceAll]);
-                                               //Res.FBody := StringReplace(Res.FBody, '&ampnbsp;', '&nbsp;', [rfReplaceAll]);
-                                               //Res.FBody := StringReplace(Res.FBody, '&amp#', '&#', [rfReplaceAll]);
-                                               //Res.FBody := StringReplace(Res.FBody, '&amp', '&amp;', [rfReplaceAll]);
                                                Res.FBody := AddAnchorTag(Res.FBody);
+                                               Res.FBody := ConvRes(Res.FBody, ThreadItem.ParentBoard.BBSID, ChangeFileExt(ThreadItem.FileName, ''), 'bbs', 'key', 'st', 'to', 'nofirst', 'true');
                                                if Res.FMailTo = '' then
-                                                       SaveList.Add('<a name="' + No + '"></a><dt><a href="giko://?no=' + No + '">' + No + '</a> \96¼\91O\81F<font color="forestgreen"><b> ' + Res.FName + ' </b></font> \93\8a\8de\93ú\81F ' + Res.FDateTime+ '<br><dd>' + Res.Fbody + ' <br><br><br>')
+                                                       SaveList.Add('<a name="' + No + '"></a><dt><a href="menu:' + No + '">' + No + '</a> \96¼\91O\81F<font color="forestgreen"><b> ' + Res.FName + ' </b></font> \93\8a\8de\93ú\81F ' + Res.FDateTime+ '<br><dd>' + Res.Fbody + ' <br><br><br>')
+                                               else if GikoSys.Setting.ShowMail then
+                                                       SaveList.Add('<a name="' + No + '"></a><dt><a href="menu:' + No + '">' + No + '</a> \96¼\91O\81F<a href="mailto:' + Res.FMailTo + '"><b> ' + Res.FName + ' </B></a> [' + Res.FMailTo + '] \93\8a\8de\93ú\81F ' + Res.FDateTime+ '<br><dd>' + Res.Fbody + ' <br><br><br>')
                                                else
-                                                       if GikoSys.Setting.ShowMail then
-                                                               SaveList.Add('<a name="' + No + '"></a><dt><a href="giko://?no=' + No + '">' + No + '</a> \96¼\91O\81F<a href="mailto:' + Res.FMailTo + '"><b> ' + Res.FName + ' </B></a> [' + Res.FMailTo + '] \93\8a\8de\93ú\81F ' + Res.FDateTime+ '<br><dd>' + Res.Fbody + ' <br><br><br>')
-                                                       else
-                                                               SaveList.Add('<a name="' + No + '"></a><dt><a href="giko://?no=' + No + '">' + No + '</a> \96¼\91O\81F<a href="mailto:' + Res.FMailTo + '"><b> ' + Res.FName + ' </B></a> \93\8a\8de\93ú\81F ' + Res.FDateTime+ '<br><dd>' + Res.Fbody + ' <br><br><br>');
+                                                       SaveList.Add('<a name="' + No + '"></a><dt><a href="menu:' + No + '">' + No + '</a> \96¼\91O\81F<a href="mailto:' + Res.FMailTo + '"><b> ' + Res.FName + ' </B></a> \93\8a\8de\93ú\81F ' + Res.FDateTime+ '<br><dd>' + Res.Fbody + ' <br><br><br>');
                                                if ThreadItem.Kokomade = (i + 1) then begin
                                                        SaveList.Add('</dl>');
                                                        SaveList.Add('<a name="koko"></a><table width="100%" bgcolor="#55AA55" cellpadding="0" cellspacing="1"><tr><td align="center" bgcolor="#77CC77" valign="middle"><font size="-1" color="#ffffff"><b>\83R\83R\82Ü\82Å\93Ç\82ñ\82¾</b></font></td></tr></table>');
                                                        SaveList.Add('<dl>');
                                                end;
                                        end;
-                                       if SaveList.Count > 50 then begin
+                                       //if SaveList.Count > 50 then begin
                                                doc.Write(SaveList.Text);
                                                SaveList.Clear;
                                                //Application.ProcessMessages;
-                                       end;
+                                       //end;
                                end;
                                SaveList.Add('</dl>');
                                SaveList.Add('<a name="bottom"></a>');
@@ -1120,7 +1417,6 @@ begin
                ReadList.Free;
        end;
 end;
-
 (*************************************************************************
  *http://\82Ì\95\8e\9a\97ñ\82ðanchor\83^\83O\95t\82«\82É\82·\82é\81B
  *************************************************************************)
@@ -1130,14 +1426,19 @@ const
                                                                         + 'abcdefghijklmnopqrstuvwxyz'
                                                                         + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
                                                                         + '#$%&()*+,-./:;=?@[]^_`{|}~!''\';
+       ANCHOR_REF      = 'href=';
+       RES_REF                 = '&gt;&gt;';
 var
        wkIdx: array[0..9] of Integer;
        url: string;
        href: string;
-       i: Integer;
+       i, b: Integer;
        idx: Integer;
+       anchorLen : Integer;
 begin
        Result := '';
+       // + 3 \82Í 'href="' ('"'\82Â\82«)\82È\82Ç\82Ì\83o\83\8a\83G\81[\83V\83\87\83\93\82É\97]\97T\82ð\8e\9d\82½\82¹\82é\82½\82ß
+       anchorLen := Length( ANCHOR_REF ) + 3;
 
        while True do begin
                wkIdx[0] := AnsiPos('http://', s);
@@ -1152,7 +1453,7 @@ begin
                wkIdx[9] := AnsiPos('rtsp://', s);
 
                idx := MaxInt;
-               for i := 0 to 8 do
+               for i := 0 to 9 do
                        if wkIdx[i] <> 0 then idx := Min(wkIdx[i], idx);
 
                if idx = MaxInt then begin
@@ -1161,10 +1462,14 @@ begin
                        Break;
                end;
 
-               if (idx > 1) and (Copy(s, idx - 1, 1) = '"') then begin
+               if (idx > 1) and
+                       (Pos( ANCHOR_REF, Copy(s, idx - anchorLen, anchorLen ) ) > 0) then begin
                        //\8aù\82É\83\8a\83\93\83N\83^\83O\82ª\82Â\82¢\82Ä\82¢\82é\82Á\82Û\82¢\82Æ\82«\82Í\83\80\83V
-                       Result := Result + Copy(s, 0, idx + Length('http://') - 1);
-                       s := Copy(s, idx + Length('http://'), length(s));
+                       href := Copy( s, idx, Length( s ) );
+                       Result := Result + Copy( s, 1, idx + Pos( '</a>', href ) + Length( '</a>' ) - 2 );
+                       s := href;
+                       s := Copy( s, Pos( '</a>', s ) + Length( '</a>' ), Length( s ) );
+
                        Continue;
                end;
 
@@ -1172,11 +1477,15 @@ begin
 
                s := Copy(s, idx, length(s));
 
-               for i := 0 to Length(s) do begin
-                       idx := AnsiPos(s[i + 1], URL_CHAR);
-                       if (idx = 0) or (i = (Length(s))) then begin
+               b := Length( s ) + 1;
+               for i := 1 to b do begin
+                       if i = b then
+       idx := 0
+      else
+                               idx := AnsiPos(s[i], URL_CHAR);
+                       if idx = 0 then begin
                                //URL\82\82á\82È\82¢\95\8e\9a\94­\8c©\81I\82Æ\82©\81A\95\8e\9a\82ª\82È\82­\82È\82Á\82½\81B
-                               url := Copy(s, 0, i);
+                               url := Copy(s, 0, i - 1);
 
                                if AnsiPos('ttp://', url) = 1 then
                                        href := 'h' + url
@@ -1189,7 +1498,7 @@ begin
                                else
                                        href := url;
                                Result := Result + '<a href="' + href + '" target="_blank">' + url + '</a>';
-                               s := Copy(s, i + 1, Length(s));
+                               s := Copy(s, i, MaxInt);
                                Break;
                        end;
                end;
@@ -1209,7 +1518,7 @@ var
 begin
        Result.FCount := 0;
 
-       if Pos('<>', Line) = 0 then
+       if AnsiPos('<>', Line) = 0 then
                Delim := ','
        else
                Delim := '<>';
@@ -1235,7 +1544,7 @@ begin
                        ws := Copy(ws, i + 1, Length(ws) - i - 1);
                        if IsNumeric(ws) then
                                Result.FCount := StrToInt(ws);
-                       Result.FTitle := Trim(StringReplace(Result.FTitle, LeftK + ws + RightK, '', [rfReplaceAll]));
+                       Result.FTitle := Trim(CustomStringReplace(Result.FTitle, LeftK + ws + RightK, ''));
                        break;
                end;
        end;
@@ -1249,7 +1558,7 @@ var
        Delim: string;
                bufbody : String;
 begin
-       if Pos('<>', Line) = 0 then begin
+       if AnsiPos('<>', Line) = 0 then begin
                Delim := ',';
                Result.FType := glt2chOld;
        end else begin
@@ -1426,32 +1735,23 @@ end;
  *\83X\83\8c\83b\83h\83t\83@\83C\83\8b\82©\82ç\8ew\92è\8ds\82ð\8eæ\93¾
  *************************************************************************)
 function TGikoSys.ReadThreadFile(FileName: string; Line: Integer): string;
-const
-       BUFFER_SIZE = 1024;
 var
-       f: TextFile;
-       s: string;
-       num: Integer;
-       ArrBuff: array [1..BUFFER_SIZE] of Char;
+       fileTmp : TStringList;
 begin
        Result := '';
        if FileExists(FileName) then begin
-               AssignFile(f, FileName);
-               System.SetTextBuf(f, ArrBuff);
+               fileTmp := TStringList.Create;
                try
-                       Reset(f);
-                       num := 1;
-                       while not Eof(f) do begin
-                               Readln(f, s);
-                               if Line = num then begin
-                                       Result := s;
-//                                     CloseFile(f);
-                                       Break;
+                       try
+                               fileTmp.LoadFromFile( FileName );
+                               if ( Line       >= 1 ) and ( Line       < fileTmp.Count + 1 ) then begin
+                                       Result := fileTmp.Strings[ Line-1 ];
                                end;
-                               inc(num);
+                       except
+                               //on EFOpenError do Result := '';
                        end;
                finally
-                       CloseFile(f);
+                       fileTmp.Free;
                end;
        end;
 end;
@@ -1572,7 +1872,7 @@ begin
        end else begin
                S := s;
                for i := Low(ERASECHAR) to      High(ERASECHAR) do      begin
-                       S := StringReplace(S, ERASECHAR[i], '', [rfReplaceAll]);
+                       S := CustomStringReplace(S, ERASECHAR[i], '');
                end;
                if (Length(S) <= ALength) then begin
                        Result := S;
@@ -1788,32 +2088,221 @@ begin
        Result  :=      r;
 end;
 
-(*************************************************************************
- * \91S\8ap\81¨\94¼\8ap
- * from HotZonu
- *************************************************************************)
-function TGikoSys.ZenToHan(const s: string): string;
+function TGikoSys.ConvRes(
+       const Body, Bbs, Key, ParamBBS, ParamKey,
+    ParamStart, ParamTo, ParamNoFirst,
+    ParamTrue, FullURL : string
+): string;
+type
+       PIndex = ^TIndex;
+       TIndex = record
+               FIndexFrom      : integer;
+               FIndexTo                : integer;
+               FNo                              : string;
+       end;
+const
+       GT      = '&gt;';
+       SN      = '0123456789-';
+       ZN      = '\82O\82P\82Q\82R\82S\82T\82U\82V\82W\82X\81|';
 var
-       Chr: array [0..255] of char;
-begin
-       Windows.LCMapString(
-                GetUserDefaultLCID(),
-//              LCMAP_HALFWIDTH,
-                LCMAP_HALFWIDTH or LCMAP_KATAKANA or LCMAP_LOWERCASE,
-                PChar(s),
-                Length(s) + 1,
-                chr,
-                Sizeof(chr)
-                );
-       Result := Chr;
-end;
-
-(*************************************************************************
- * \91S\8ap\94¼\8ap\82Ð\82ç\82ª\82È\82©\82½\82©\82È\82ð\8bæ\95Ê\82µ\82È\82¢\90¦\82¢Pos
- *************************************************************************)
-function TGikoSys.VaguePos(const Substr, S: string): Integer;
-begin
-       Result := Pos(ZenToHan(Substr), ZenToHan(S));
+       i : integer;
+       s,r : string;
+       b : TMbcsByteType;
+       sw: boolean;
+       sp: integer;
+       No: string;
+       sx: string;
+       List: TList;
+       oc      : string;
+       st, et: string;
+       chk : boolean;
+       al : boolean;
+       procedure Add(IndexFrom, IndexTo: integer; const No: string);
+       var
+               FIndex : PIndex;
+       begin
+               New(FIndex);
+               FIndex.FIndexFrom       := IndexFrom;
+               FIndex.FIndexTo         := IndexTo;
+               FIndex.FNo                               := No;
+               List.Add(FIndex);
+       end;
+       function ChooseString(const Text, Separator: string; Index: integer): string;
+       var
+               S : string;
+               i, p : integer;
+       begin
+               S :=    Text;
+               for i :=        0 to    Index - 1 do    begin
+                       if      (AnsiPos(Separator, S) = 0) then        S :=    ''
+                       else    S :=    Copy(S, AnsiPos(Separator, S) + Length(Separator), Length(S));
+               end;
+               p :=    AnsiPos(Separator, S);
+               if      (p > 0) then    Result  :=      Copy(S, 1, p - 1) else Result :=        S;
+       end;
+begin
+       { v1.0 b2 - 03 }
+       s        :=     Body;
+       r        :=     Body;
+       i        :=     1;
+       sw      :=      False;
+       No      :=      '';
+       List:=  TList.Create;
+       oc      :=      '';
+       sp      :=      0;
+       chk :=  False;
+       al      :=      False;
+       while true      do      begin
+               b :=    ByteType(s, i);
+               case    b of
+                       mbSingleByte    : begin
+                               if      (not sw) and (Copy(s,i,8) = GT + GT) then       begin
+                                       if      (AnsiPos('<A HREF', AnsiUpperCase(oc)) = 0) then        begin
+                                               sw      :=      True;
+                                               sp      :=      i;
+                                               i :=    i + 7;
+                                               oc:='';
+                                               chk :=  True;
+                                       end;
+                               end else
+                               if      (not sw) and (Copy(s,i,8) = GT + GT) then       begin
+                                       if      (AnsiPos('<A HREF', AnsiUpperCase(oc)) = 1) then        begin
+                                               i :=    i + 7;
+                                               oc:='';
+                                               chk :=  True;
+                                       end;
+                               end else
+                               if      (not sw) and (Copy(s,i,4) = GT) then    begin
+                                       if      (AnsiPos('<A HREF', AnsiUpperCase(oc)) = 0) then        begin
+                                               sw      :=      True;
+                                               sp      :=      i;
+                                               i :=    i + 3;
+                                               oc:='';
+                                               chk :=  True;
+                                       end;
+                               end else
+                               if      ((not sw) and (Copy(s,i,1) = ',')) or
+                                               ((not sw) and (Copy(s,i,1) = '=')) then begin
+                                       if      ((not Chk) and (AnsiLowerCase(oc) = '</a>')) or
+                                                       ((Chk) and      (oc = '')) or
+                                                       ((not Chk) and (al)) then
+                                       begin
+                                               sw      :=      True;
+                                               sp      :=      i;
+                                               //i :=  i + 1;
+                                               oc:='';
+                                       end;
+                               end else
+                               if      (sw) then begin
+                                       sx      :=      Copy(s,i,1);
+                                       if      (AnsiPos(sx, SN) > 0)   then    begin
+                                               No      :=      No      + sx;
+                                       end else begin
+                                               if      (No <> '') and (No <> '-')       then   begin
+                                                       Add(sp, i, No);
+                                                       al := True;
+                                               end;
+                                               sw      :=      False;
+                                               //
+                                               i := i - 1;
+                                               //
+                                               No      := '';
+                                               oc:='';
+                                               //chk :=        False;
+                                       end;
+                               end else begin
+                                       if      Copy(s,i,1) = '<' then  oc      :=      '';
+                                       oc      :=      oc + Copy(s,i,1);
+                                       chk :=  False;
+                                       al      :=      False;
+                               end;
+                       end;
+                       mbLeadByte      : begin
+                               if      (not sw) and (Copy(s,i,4) = '\81\84\81\84') then        begin
+                                       sw      :=      True;
+                                       sp      :=      i;
+                                       i :=    i + 3;
+                                       chk :=  True;
+                               end else
+                               if      (not sw) and (Copy(s,i,2) = '\81\84') then  begin
+                                       sw      :=      True;
+                                       sp      :=      i;
+                                       i :=    i + 1;
+                                       chk :=  True;
+                               end else
+                               if      (sw) then begin
+                                       sx      :=      Copy(s,i,2);
+                                       if      (AnsiPos(sx, ZN) > 0)   then    begin
+                                               No      :=      No      + ZenToHan(sx);
+                                       end else begin
+                                               if      (No <> '') and (No <> '-')      and (No <> '\81|') then   begin
+                                                       Add(sp, i, No);
+                                               end;
+                                               sw      :=      False;
+                                               i := i - 1;
+                                               No      :=      '';
+                                       end;
+                               end else begin
+                                       oc      :=      '';
+                                       chk :=  False;
+                               end;
+                               al      :=      False;
+                       end;
+               end;
+               inc(i);
+               if      (i > Length(Body))      then    begin
+                       if      (sw)    then    begin
+                               if      (No <> '')      then    Add(sp, i, No);
+                       end;
+                       Break;
+               end;
+       end;
+       for i :=        List.Count - 1  downto  0 do    begin
+        //plName := Copy(PluginName, LastDelimiter('\',PluginName) + 1, Length(PluginName) - LastDelimiter('/',PluginName) -1 );
+               if      (AnsiPos('-', PIndex(List[i]).FNo) > 0) then    begin
+                       st      :=      ChooseString(PIndex(List[i]).FNo, '-', 0);
+                       et      :=      ChooseString(PIndex(List[i]).FNo, '-', 1);
+               end else begin
+                       st      :=      PIndex(List[i]).FNo;
+                       et      :=      PIndex(List[i]).FNo;
+               end;
+               r :=    Copy(r,0, PIndex(List[i]).FIndexFrom - 1) +
+                                       Format('<a href="%s&%s=%s&%s=%s&%s=%s" target="_blank">',
+                                                               [FullURL, ParamStart, st, ParamTo, et, ParamNoFirst, ParamTrue]) +
+                                       Copy(r,PIndex(List[i]).FIndexFrom, PIndex(List[i]).FIndexTo - PIndex(List[i]).FIndexFrom) + '</A>' +
+                                       Copy(r,PIndex(List[i]).FIndexTo,Length(r));
+               Dispose(PIndex(List[i]));
+       end;
+       List.Free;
+       Result  :=      r;
+end;
+
+(*************************************************************************
+ * \91S\8ap\81¨\94¼\8ap
+ * from HotZonu
+ *************************************************************************)
+function TGikoSys.ZenToHan(const s: string): string;
+var
+       Chr: array [0..255] of char;
+begin
+       Windows.LCMapString(
+                GetUserDefaultLCID(),
+//              LCMAP_HALFWIDTH,
+                LCMAP_HALFWIDTH or LCMAP_KATAKANA or LCMAP_LOWERCASE,
+                PChar(s),
+                Length(s) + 1,
+                chr,
+                Sizeof(chr)
+                );
+       Result := Chr;
+end;
+
+(*************************************************************************
+ * \91S\8ap\94¼\8ap\82Ð\82ç\82ª\82È\82©\82½\82©\82È\82ð\8bæ\95Ê\82µ\82È\82¢\90¦\82¢Pos
+ *************************************************************************)
+function TGikoSys.VaguePos(const Substr, S: string): Integer;
+begin
+       Result := AnsiPos(ZenToHan(Substr), ZenToHan(S));
 end;
 
 function TGikoSys.BoolToInt(b: Boolean): Integer;
@@ -1937,6 +2426,59 @@ begin
        end;
 end;
 
+procedure TGikoSys.LoadEditorKeySetting(ActionList: TActionList);
+const
+       STD_SEC = 'KeySetting';
+var
+       i: Integer;
+       ini: TMemIniFile;
+       ActionName: string;
+       ActionKey: Integer;
+       SecList: TStringList;
+       Component: TComponent;
+begin
+       if not FileExists(GetConfigDir + EKEY_SETTING_FILE_NAME) then
+               Exit;
+       SecList := TStringList.Create;
+       ini := TMemIniFile.Create(GetConfigDir + EKEY_SETTING_FILE_NAME);
+       try
+               ini.ReadSection(STD_SEC, SecList);
+               for i := 0 to SecList.Count - 1 do begin
+                       ActionName := SecList[i];
+                       ActionKey := ini.ReadInteger(STD_SEC, ActionName, -1);
+                       if ActionKey <> -1 then begin
+                               Component := ActionList.Owner.FindComponent(ActionName);
+                               if TObject(Component) is TAction then begin
+                                       TAction(Component).ShortCut := ActionKey;
+                               end;
+                       end;
+               end;
+       finally
+               ini.Free;
+               SecList.Free;
+       end;
+end;
+
+procedure TGikoSys.SaveEditorKeySetting(ActionList: TActionList);
+const
+       STD_SEC = 'KeySetting';
+var
+       i: Integer;
+       ini: TMemIniFile;
+begin
+       ini := TMemIniFile.Create(GetConfigDir + EKEY_SETTING_FILE_NAME);
+       try
+               for i := 0 to ActionList.ActionCount - 1 do begin
+                       if ActionList.Actions[i].Tag = -1 then
+                               Continue;
+                       ini.WriteInteger(STD_SEC, ActionList.Actions[i].Name, TAction(ActionList.Actions[i]).ShortCut);
+               end;
+               ini.UpdateFile;
+       finally
+               ini.Free;
+       end;
+end;
+
 //
 procedure TGikoSys.CreateProcess(const AppPath: string; const Param: string);
 var
@@ -2070,7 +2612,8 @@ begin
        s := Trim(Copy(s, 2, Length(s)));
 
        //\8en\82ß\82Ì\95\8e\9a\82ª'"'\82È\82ç\8eæ\82è\8f\9c\82­
-       if Copy(s, 1, 1) = '"' then begin
+       //if Copy(s, 1, 1) = '"' then begin
+    if s[1]  = '"' then begin
                s := Trim(Copy(s, 2, Length(s)));
        end;
 
@@ -2104,6 +2647,8 @@ var
 //     Len: Integer;
 begin
        Result := False;
+       if RightStr( Host, 1 ) = '/' then
+               Host := Copy( Host, 1, Length( Host ) - 1 );
        OutputDebugString(pchar(HOST_NAME[0]));
        for i := 0 to Length(HOST_NAME) - 1 do begin
 //             Len := Length(HOST_NAME[i]);
@@ -2115,10 +2660,6 @@ begin
 end;
 
 function TGikoSys.Parse2chURL(const url: string; const path: string; const document: string; var BBSID: string; var BBSKey: string): Boolean;
-const
-       READ_PATH: string =                     '/test/read.cgi/';
-       OLD_READ_PATH: string =         '/test/read.cgi?';
-       KAKO_PATH: string =                     '/kako/';
 var
        Index: Integer;
        s: string;
@@ -2167,17 +2708,126 @@ begin
                end;
        end;
 end;
+procedure TGikoSys.GetPopupResNumber(URL : string; var stRes, endRes : Int64);
+var
+    buf : String;
+    convBuf : String;
+    ps : Int64;
+    pch : PChar;
+begin
+       URL := Trim(LowerCase(URL));
+    if (AnsiPos('&st=', URL ) <> 0) and ( AnsiPos( '&to=',URL) <> 0 ) then begin
+        try
+            stRes := StrToInt64( Copy( URL, AnsiPos('&st=', URL ) + 4, AnsiPos( '&to=',URL) - AnsiPos('&st=', URL ) - 4 ) );
+            if AnsiPos( '&nofirst=',URL) <> 0 then begin
+                buf := Copy( URL, AnsiPos('&to=', URL ) + 4, AnsiPos( '&nofirst=',URL) - AnsiPos('&to=', URL ) - 4);
+            end else begin
+                buf := Copy( URL, AnsiPos('&to=', URL ) + 4, Length( URL ) - AnsiPos('&to=', URL ) - 4 + 1 );
+                ps := 0;
+                pch := PChar(buf);
+                while  ( ps < Length(buf) )and ( pch[ps] >= '0' ) and ( pch[ps] <= '9' ) do Inc(ps);
+                buf := Copy( buf, 1, ps );
+            end;
+            try
+                if buf <> '' then
+                    endRes := StrToInt64(buf);
+            except
+                endRes := 0;
+            end;
+        except
+            stRes := 0;
+        end;
+        GikoSys.GetBrowsableThreadURL( URL );
+    end else if( AnsiPos('&res=', URL ) <> 0 ) then begin
+        endRes := 0;
+        buf := Copy( URL, AnsiPos('&res=', URL ) + 5, Length( URL ) - AnsiPos('&res=', URL ) - 5 + 1 );
+        ps := 0;
+        pch := PChar(buf);
+        while  ( ps < Length(buf) )and ( pch[ps] >= '0' ) and ( pch[ps] <= '9' ) do Inc(ps);
+        buf := Copy( buf, 1, ps );
+        try
+            if buf <> '' then
+                stRes := StrToInt(buf)
+            else begin
+                stRes := 0;
+            end;
+        except
+            stRes := 0;
+        end;
+    end else if (AnsiPos('&start=', URL ) <> 0) and ( AnsiPos( '&end=',URL) <> 0 ) then begin
+        try
+            stRes := StrToInt64( Copy( URL, AnsiPos('&start=', URL ) + 7, AnsiPos( '&end=',URL) - AnsiPos('&start=', URL ) - 7 ) );
+            if AnsiPos( '&nofirst=',URL) <> 0 then begin
+                buf := Copy( URL, AnsiPos('&end=', URL ) + 5, AnsiPos( '&nofirst=',URL) - AnsiPos('&end=', URL ) - 5);
+            end else begin
+                buf := Copy( URL, AnsiPos('&end=', URL ) + 5, Length( URL ) - AnsiPos('&to=', URL ) - 5 + 1 );
+                ps := 0;
+                pch := PChar(buf);
+                while  ( ps < Length(buf) )and ( pch[ps] >= '0' ) and ( pch[ps] <= '9' ) do Inc(ps);
+                buf := Copy( buf, 1, ps );
+            end;
+            try
+                if buf <> '' then
+                    endRes := StrToInt64(buf);
+            except
+                endRes := 0;
+            end;
+        except
+            stRes := 0;
+        end;
+    end else if ( AnsiPos('.htm',URL) <> Length(URL) -4 ) and ( AnsiPos('.htm',URL) <> Length(URL) -3 ) then begin
+        buf := Copy(URL, LastDelimiter('/',URL)+1,Length(URL)-LastDelimiter('/',URL)+1);
+        if  Length(buf) > 0 then begin
+            ps := 0;
+            pch := PChar(buf);
+            while  ( ps < Length(buf) )and ( pch[ps] >= '0' ) and ( pch[ps] <= '9' ) do Inc(ps);
+            try
+                convBuf := Copy( buf, 1, ps );
+                if convBuf <> '' then begin
+                    stRes := StrToInt64(convBuf);
+                    Delete(buf,1,ps+1);
+                    ps := 0;
+                    pch := PChar(buf);
+                    while  ( ps < Length(buf) )and ( pch[ps] >= '0' ) and ( pch[ps] <= '9' ) do Inc(ps);
+                    try
+                        convBuf := Copy( buf, 1, ps );
+                        if convBuf <> '' then
+                            endRes := StrToInt64(convBuf)
+                        else
+                            endRes := 0;
+                    except
+                        endRes := 0;
+                    end;
+                end else begin
+                    stRes := 0;
+                end;
+
+            except
+                stRes := 0;
+                endRes := 0;
+            end;
+
+        end;
+    end else begin
+           //stRes := 0;
+        //endRes := 0;
+    end;
+end;
 
 function TGikoSys.Parse2chURL2(URL: string): TPathRec;
 var
        i: Integer;
        s: string;
+//    buf : String;
+//    convBuf : String;
        wk: string;
        wkMin: Integer;
        wkMax: Integer;
        wkInt: Integer;
        RStart: Integer;
        RLength: Integer;
+//    ps : Integer;
+//    pch : PChar;
        SList: TStringList;
 begin
        URL := Trim(LowerCase(URL));
@@ -2192,201 +2842,202 @@ begin
 
        wkMin := 0;
        wkMax := 1;
-
+    if URL[length(URL)] = '\' then
+       URL := URL + 'n';
        FAWKStr.RegExp := 'http://.+\.(2ch\.net|bbspink\.com)/';
-       if FAWKStr.Match(FAWKStr.ProcessEscSeq(URL), RStart, RLength) = 0 then
-               Exit;
-       s := Copy(URL, RStart + RLength - 1, Length(URL));
-
-       //\95W\8f\80\8f\91\8e®
-       //\8dÅ\8cã\82Íl50, 10, 10-20, 10n, 10-20n, -10, 10-, 10n- \82È\82Ç
-       //http://xxx.2ch.net/test/read.cgi/bbsid/1000000000/
-       FAWKStr.RegExp := '/test/read.cgi/.+/[0-9]+/.*';
-       if FAWKStr.Match(FAWKStr.ProcessEscSeq(s), RStart, RLength) > 0 then begin
-               s := Copy(s, 15, Length(s));
-
-               SList := TStringList.Create;
-               try
-                       SList.Clear;
-                       FAWKStr.RegExp := '/';
-                       if FAWKStr.Split(FAWKStr.ProcessEscSeq(s), SList) >= 2 then begin
-                               Result.FBBS := SList[1];
-                               Result.FKey := SList[2];
-                               if SList.Count >= 3 then
-                                       s := SList[3]
-                               else
-                                       s := '';
-                       end else
-                               Exit;
-
-                       SList.Clear;
-                       FAWKStr.LineSeparator := mcls_CRLF;
-                       FAWKStr.RegExp := '-';
-                       if FAWKStr.Split(FAWKStr.ProcessEscSeq(s), SList) = 0 then begin
-                               Result.FFirst := True;
-                       end else begin
-                               FAWKStr.RegExp := 'l[0-9]+';
-                               if FAWKStr.Match(FAWKStr.ProcessEscSeq(s), RStart, RLength) > 0 then begin
-                                       Result.FFirst := True;
-                               end else begin
-                                       for i := 0 to SList.Count - 1 do begin
-                                               if Trim(SList[i]) = '' then begin
-                                                       if i = 0 then
-                                                               Result.FStBegin := True;
-                                                       if i = (SList.Count - 1) then
-                                                               Result.FToEnd := True;
-                                               end else if IsNumeric(SList[i]) then begin
-                                                       wkInt := StrToInt(SList[i]);
-                                                       wkMax := Max(wkMax, wkInt);
-                                                       if wkMin = 0 then
-                                                               wkMin := wkInt
-                                                       else
-                                                               wkMin := Min(wkMin, wkInt);
-                                               end else if Trim(SList[i]) = 'n' then begin
-                                                       Result.FFirst := True;
-                                               end else begin
-                                                       FAWKStr.RegExp := '^n[0-9]+$|^[0-9]+n$';
-                                                       if FAWKStr.Match(FAWKStr.ProcessEscSeq(SList[i]), RStart, RLength) > 0 then begin
-                                                               if Copy(SList[i], 1, 1) = 'n' then
-                                                                       wkInt := StrToInt(Copy(SList[i], 2, Length(SList[i])))
-                                                               else
-                                                                       wkInt := StrToInt(Copy(SList[i], 1, Length(SList[i]) - 1));
-                                                               Result.FFirst := True;
-                                                               wkMax := Max(wkMax, wkInt);
-                                                               if wkMin = 1 then
-                                                                       wkMin := wkInt
-                                                               else
-                                                                       wkMin := Min(wkMin, wkInt);
-                                                       end;
-                                               end;
-                                       end;
-                                       if Result.FStBegin and (not Result.FToEnd) then
-                                               Result.FSt := wkMin
-                                       else if (not Result.FStBegin) and Result.FToEnd then
-                                               Result.FTo := wkMax
-                                       else if (not Result.FStBegin) and (not Result.FToEnd) then begin
-                                               Result.FSt := wkMin;
-                                               Result.FTo := wkMax;
-                                       end;
-                                       //Result.FSt := wkMin;
-                                       //Result.FTo := wkMax;
-                               end;
-                       end;
-               finally
-                       SList.Free;
-               end;
-               Result.FDone := True;
-               Exit;
-       end;
-
-       //\90Vkako\8f\91\8e®
-       //http://server.2ch.net/ITA_NAME/kako/1000/10000/1000000000.html
-       FAWKStr.RegExp := '/.+/kako/[0-9]+/[0-9]+/[0-9]+\.html';
-       if FAWKStr.Match(FAWKStr.ProcessEscSeq(s), RStart, RLength) > 0 then begin
-               SList := TStringList.Create;
-               try
-                       SList.Clear;
-                       FAWKStr.RegExp := '/';
-                       if FAWKStr.Split(FAWKStr.ProcessEscSeq(s), SList) >= 6 then begin
-                               Result.FBBS := SList[1];
-                               Result.FKey := ChangeFileExt(SList[5], '');
-                               Result.FFirst := True;
-                       end else
-                               Exit;
-               finally
-                       SList.Free;
-               end;
-               Result.FDone := True;
-               Exit;
-       end;
+       if FAWKStr.Match(FAWKStr.ProcessEscSeq(URL), RStart, RLength) <> 0 then begin
+               s := Copy(URL, RStart + RLength - 1, Length(URL));
+
+        //\95W\8f\80\8f\91\8e®
+        //\8dÅ\8cã\82Íl50, 10, 10-20, 10n, 10-20n, -10, 10-, 10n- \82È\82Ç
+        //http://xxx.2ch.net/test/read.cgi/bbsid/1000000000/
+        FAWKStr.RegExp := '/test/read.cgi/.+/[0-9]+/.*';
+        if FAWKStr.Match(FAWKStr.ProcessEscSeq(s), RStart, RLength) > 0 then begin
+            s := Copy(s, 15, Length(s));
+
+            SList := TStringList.Create;
+            try
+                SList.Clear;
+                FAWKStr.RegExp := '/';
+                if FAWKStr.Split(FAWKStr.ProcessEscSeq(s), SList) >= 2 then begin
+                    Result.FBBS := SList[1];
+                    Result.FKey := SList[2];
+                    if SList.Count >= 3 then
+                        s := SList[3]
+                    else
+                        s := '';
+                end else
+                    Exit;
+
+                SList.Clear;
+                FAWKStr.LineSeparator := mcls_CRLF;
+                FAWKStr.RegExp := '-';
+                if FAWKStr.Split(FAWKStr.ProcessEscSeq(s), SList) = 0 then begin
+                    Result.FFirst := True;
+                end else begin
+                    FAWKStr.RegExp := 'l[0-9]+';
+                    if FAWKStr.Match(FAWKStr.ProcessEscSeq(s), RStart, RLength) > 0 then begin
+                        Result.FFirst := True;
+                    end else begin
+                        for i := 0 to SList.Count - 1 do begin
+                            if Trim(SList[i]) = '' then begin
+                                if i = 0 then
+                                    Result.FStBegin := True;
+                                if i = (SList.Count - 1) then
+                                    Result.FToEnd := True;
+                            end else if IsNumeric(SList[i]) then begin
+                                wkInt := StrToInt(SList[i]);
+                                wkMax := Max(wkMax, wkInt);
+                                if wkMin = 0 then
+                                    wkMin := wkInt
+                                else
+                                    wkMin := Min(wkMin, wkInt);
+                            end else if Trim(SList[i]) = 'n' then begin
+                                Result.FFirst := True;
+                            end else begin
+                                FAWKStr.RegExp := '^n[0-9]+$|^[0-9]+n$';
+                                if FAWKStr.Match(FAWKStr.ProcessEscSeq(SList[i]), RStart, RLength) > 0 then begin
+                                    if Copy(SList[i], 1, 1) = 'n' then
+                                        wkInt := StrToInt(Copy(SList[i], 2, Length(SList[i])))
+                                    else
+                                        wkInt := StrToInt(Copy(SList[i], 1, Length(SList[i]) - 1));
+                                    Result.FFirst := True;
+                                    wkMax := Max(wkMax, wkInt);
+                                    if wkMin = 1 then
+                                        wkMin := wkInt
+                                    else
+                                        wkMin := Min(wkMin, wkInt);
+                                end;
+                            end;
+                        end;
+                        if Result.FStBegin and (not Result.FToEnd) then
+                            Result.FSt := wkMin
+                        else if (not Result.FStBegin) and Result.FToEnd then
+                            Result.FTo := wkMax
+                        else if (not Result.FStBegin) and (not Result.FToEnd) then begin
+                            Result.FSt := wkMin;
+                            Result.FTo := wkMax;
+                        end;
+                        //Result.FSt := wkMin;
+                        //Result.FTo := wkMax;
+                    end;
+                end;
+            finally
+                SList.Free;
+            end;
+            Result.FDone := True;
+            Exit;
+        end;
 
-       //\8b\8ckako\8f\91\8e®
-       //http://server.2ch.net/ITA_NAME/kako/999/999999999.html
-       FAWKStr.RegExp := '/.+/kako/[0-9]+/[0-9]+\.html';
-       if FAWKStr.Match(FAWKStr.ProcessEscSeq(s), RStart, RLength) > 0 then begin
-               SList := TStringList.Create;
-               try
-                       SList.Clear;
-                       FAWKStr.RegExp := '/';
-                       if FAWKStr.Split(FAWKStr.ProcessEscSeq(s), SList) >= 5 then begin
-                               Result.FBBS := SList[1];
-                               Result.FKey := ChangeFileExt(SList[4], '');
-                               Result.FFirst := True;
-                       end else
-                               Exit;
-               finally
-                       SList.Free;
-               end;
-               Result.FDone := True;
-               Exit;
-       end;
+        //\90Vkako\8f\91\8e®
+        //http://server.2ch.net/ITA_NAME/kako/1000/10000/1000000000.html
+        FAWKStr.RegExp := '/.+/kako/[0-9]+/[0-9]+/[0-9]+\.html';
+        if FAWKStr.Match(FAWKStr.ProcessEscSeq(s), RStart, RLength) > 0 then begin
+            SList := TStringList.Create;
+            try
+                SList.Clear;
+                FAWKStr.RegExp := '/';
+                if FAWKStr.Split(FAWKStr.ProcessEscSeq(s), SList) >= 6 then begin
+                    Result.FBBS := SList[1];
+                    Result.FKey := ChangeFileExt(SList[5], '');
+                    Result.FFirst := True;
+                end else
+                    Exit;
+            finally
+                SList.Free;
+            end;
+            Result.FDone := True;
+            Exit;
+        end;
 
-       //log\8by\82Ñlog2\8f\91\8e®
-       //http://server.2ch.net/log/ITA_NAME/kako/999/999999999.html
-       //http://server.2ch.net/log2/ITA_NAME/kako/999/999999999.html
-       FAWKStr.RegExp := '/log2?/.+/kako/[0-9]+/[0-9]+\.html';
-       if FAWKStr.Match(FAWKStr.ProcessEscSeq(s), RStart, RLength) > 0 then begin
-               SList := TStringList.Create;
-               try
-                       SList.Clear;
-                       FAWKStr.RegExp := '/';
-                       if FAWKStr.Split(FAWKStr.ProcessEscSeq(s), SList) >= 6 then begin
-                               Result.FBBS := SList[2];
-                               Result.FKey := ChangeFileExt(SList[5], '');
-                               Result.FFirst := True;
-                       end else
-                               Exit;
-               finally
-                       SList.Free;
-               end;
-               Result.FDone := True;
-               Exit;
-       end;
+        //\8b\8ckako\8f\91\8e®
+        //http://server.2ch.net/ITA_NAME/kako/999/999999999.html
+        FAWKStr.RegExp := '/.+/kako/[0-9]+/[0-9]+\.html';
+        if FAWKStr.Match(FAWKStr.ProcessEscSeq(s), RStart, RLength) > 0 then begin
+            SList := TStringList.Create;
+            try
+                SList.Clear;
+                FAWKStr.RegExp := '/';
+                if FAWKStr.Split(FAWKStr.ProcessEscSeq(s), SList) >= 5 then begin
+                    Result.FBBS := SList[1];
+                    Result.FKey := ChangeFileExt(SList[4], '');
+                    Result.FFirst := True;
+                end else
+                    Exit;
+            finally
+                SList.Free;
+            end;
+            Result.FDone := True;
+            Exit;
+        end;
 
+        //log\8by\82Ñlog2\8f\91\8e®
+        //http://server.2ch.net/log/ITA_NAME/kako/999/999999999.html
+        //http://server.2ch.net/log2/ITA_NAME/kako/999/999999999.html
+        FAWKStr.RegExp := '/log2?/.+/kako/[0-9]+/[0-9]+\.html';
+        if FAWKStr.Match(FAWKStr.ProcessEscSeq(s), RStart, RLength) > 0 then begin
+            SList := TStringList.Create;
+            try
+                SList.Clear;
+                FAWKStr.RegExp := '/';
+                if FAWKStr.Split(FAWKStr.ProcessEscSeq(s), SList) >= 6 then begin
+                    Result.FBBS := SList[2];
+                    Result.FKey := ChangeFileExt(SList[5], '');
+                    Result.FFirst := True;
+                end else
+                    Exit;
+            finally
+                SList.Free;
+            end;
+            Result.FDone := True;
+            Exit;
+        end;
 
-       //\8b\8cURL\8f\91\8e®
-       //http://server.2ch.net/test/read.cgi?bbs=ITA_NAME&key=1000000000&st=1&to=5&nofirst=true
-       FAWKStr.RegExp := '/test/read\.cgi\?';
-       if FAWKStr.Match(FAWKStr.ProcessEscSeq(s), RStart, RLength) > 0 then begin
-               s := Copy(s, 16, Length(s));
-               SList := TStringList.Create;
-               try
-                       SList.Clear;
-                       FAWKStr.RegExp := '&';
-                       if FAWKStr.Split(FAWKStr.ProcessEscSeq(s), SList) >= 2 then begin
-                               Result.FFirst := True;
-                               for i := 0 to SList.Count - 1 do begin
-                                       if Pos('bbs=', SList[i]) = 1 then begin
-                                               Result.FBBS := Copy(SList[i], 5, Length(SList[i]));
-                                       end else if Pos('key=', SList[i]) = 1 then begin
-                                               Result.FKey := Copy(SList[i], 5, Length(SList[i]));
-                                       end else if Pos('st=', SList[i]) = 1 then begin
-                                               wk := Copy(SList[i], 4, Length(SList[i]));
-                                               if IsNumeric(wk) then
-                                                       Result.FSt := StrToInt(wk)
-                                               else if wk = '' then
-                                                       Result.FStBegin := True;
-                                       end else if Pos('to=', SList[i]) = 1 then begin
-                                               wk := Copy(SList[i], 4, Length(SList[i]));
-                                               if IsNumeric(wk) then
-                                                       Result.FTo := StrToInt(wk)
-                                               else if wk = '' then
-                                                       Result.FToEnd := True;
-                                       end else if Pos('nofirst=', SList[i]) = 1 then begin
-                                               Result.FFirst := False;
-                                       end;
-                               end;
-                       end else
-                               Exit;
-               finally
-                       SList.Free;
-               end;
 
-               if (Result.FBBS <> '') and (Result.FKey <> '') then begin
-                       Result.FDone := True;
-               end;
-               Exit;
-       end;
+        //\8b\8cURL\8f\91\8e®
+        //http://server.2ch.net/test/read.cgi?bbs=ITA_NAME&key=1000000000&st=1&to=5&nofirst=true
+        FAWKStr.RegExp := '/test/read\.cgi\?';
+        if FAWKStr.Match(FAWKStr.ProcessEscSeq(s), RStart, RLength) > 0 then begin
+            s := Copy(s, 16, Length(s));
+            SList := TStringList.Create;
+            try
+                SList.Clear;
+                FAWKStr.RegExp := '&';
+                if FAWKStr.Split(FAWKStr.ProcessEscSeq(s), SList) >= 2 then begin
+                    Result.FFirst := True;
+                    for i := 0 to SList.Count - 1 do begin
+                        if Pos('bbs=', SList[i]) = 1 then begin
+                            Result.FBBS := Copy(SList[i], 5, Length(SList[i]));
+                        end else if Pos('key=', SList[i]) = 1 then begin
+                            Result.FKey := Copy(SList[i], 5, Length(SList[i]));
+                        end else if Pos('st=', SList[i]) = 1 then begin
+                            wk := Copy(SList[i], 4, Length(SList[i]));
+                            if IsNumeric(wk) then
+                                Result.FSt := StrToInt(wk)
+                            else if wk = '' then
+                                Result.FStBegin := True;
+                        end else if Pos('to=', SList[i]) = 1 then begin
+                            wk := Copy(SList[i], 4, Length(SList[i]));
+                            if IsNumeric(wk) then
+                                Result.FTo := StrToInt(wk)
+                            else if wk = '' then
+                                Result.FToEnd := True;
+                        end else if Pos('nofirst=', SList[i]) = 1 then begin
+                            Result.FFirst := False;
+                        end;
+                    end;
+                end else
+                    Exit;
+            finally
+                SList.Free;
+            end;
+
+            if (Result.FBBS <> '') and (Result.FKey <> '') then begin
+                Result.FDone := True;
+            end;
+            Exit;
+        end;
+    end;
 end;
 
 procedure TGikoSys.ParseURI(var URL, Protocol, Host, Path, Document, Port, Bookmark: string);
@@ -2435,6 +3086,341 @@ begin
        end;
 end;
 
+function       TGikoSys.GetBrowsableThreadURL(
+       inURL : string
+) : string;
+var
+       threadItem      : TThreadItem;
+       boardPlugIn     : TBoardPlugIn;
+       i                                               : Integer;
+begin
+
+       //===== \83v\83\89\83O\83C\83\93
+       try
+               for i := Length( BoardPlugIns ) - 1 downto 0 do begin
+                       if Assigned( Pointer( BoardPlugIns[ i ].Module ) ) then begin
+                               if BoardPlugIns[ i ].AcceptURL( inURL ) = atThread then begin
+                                       boardPlugIn := BoardPlugIns[ i ];
+                                       threadItem      := TThreadItem.Create( boardPlugIn, inURL );
+                                       Result                  := threadItem.URL;
+                                       threadItem.Free;
+
+                                       Break;
+                               end;
+                       end;
+               end;
+       except
+               // exception \82ª\94­\90\82µ\82½\8fê\8d\87\82Í\93à\95\94\8f\88\97\9d\82É\94C\82¹\82½\82¢\82Ì\82Å\82±\82±\82Å\82Í\89½\82à\82µ\82È\82¢
+       end;
+
+       if Length( Result ) = 0 then
+               Result := GikoSys.Get2chBrowsableThreadURL( inURL );
+
+end;
+
+function       TGikoSys.GetThreadURL2BoardURL(
+       inURL : string
+) : string;
+var
+       threadItem      : TThreadItem;
+       boardPlugIn     : TBoardPlugIn;
+       i                                               : Integer;
+begin
+
+       //===== \83v\83\89\83O\83C\83\93
+       try
+               for i := Length( BoardPlugIns ) - 1 downto 0 do begin
+                       if Assigned( Pointer( BoardPlugIns[ i ].Module ) ) then begin
+                               if BoardPlugIns[ i ].AcceptURL( inURL ) = atThread then begin
+                                       boardPlugIn := BoardPlugIns[ i ];
+                                       threadItem      := TThreadItem.Create( boardPlugIn, inURL );
+                                       Result                  := BoardPlugIns[ i ].GetBoardURL( Longword( threadItem ) );
+                                       threadItem.Free;
+
+                                       Break;
+                               end;
+                       end;
+               end;
+       except
+               // exception \82ª\94­\90\82µ\82½\8fê\8d\87\82Í\93à\95\94\8f\88\97\9d\82É\94C\82¹\82½\82¢\82Ì\82Å\82±\82±\82Å\82Í\89½\82à\82µ\82È\82¢
+       end;
+
+       if Length( Result ) = 0 then
+               Result := GikoSys.Get2chThreadURL2BoardURL( inURL );
+
+end;
+
+function       TGikoSys.Get2chThreadURL2BoardURL(
+       inURL : string
+) : string;
+var
+       Protocol, Host, Path, Document, Port, Bookmark : string;
+       BBSID, BBSKey : string;
+begin
+
+       ParseURI( inURL, Protocol, Host, Path, Document, Port, Bookmark );
+       Parse2chURL( inURL, Path, Document, BBSID, BBSKey );
+
+       Result := Copy( inURL, 1, Pos( '/test/read.cgi', inURL ) ) + BBSID + '/';
+
+end;
+
+function       TGikoSys.Get2chBrowsableThreadURL(
+       inURL                   : string
+) : string;
+var
+       Protocol, Host, Path, Document, Port, Bookmark : string;
+       BBSID, BBSKey : string;
+       foundPos        : Integer;
+begin
+
+       if Pos( KAKO_PATH, inURL ) > 0 then begin
+               Result := inURL;
+       end else begin
+               ParseURI( inURL, Protocol, Host, Path, Document, Port, Bookmark );
+               Parse2chURL( inURL, Path, Document, BBSID, BBSKey );
+               foundPos := Pos( '/test/read.cgi', inURL ) - 1;
+
+               if Is2chHost( Host ) then begin
+                       Result := Copy( inURL, 1, foundPos ) +
+                               READ_PATH + BBSID + '/' + BBSKey + '/l50';
+               end else begin
+                       Result := Copy( inURL, 1, foundPos ) +
+                               OLD_READ_PATH + 'bbs=' + BBSID + '&key=' + BBSKey + '&ls=50';
+               end;
+       end;
+
+end;
+
+function       TGikoSys.Get2chBoard2ThreadURL(
+       inBoard : TBoard;
+       inKey           : string
+) : string;
+var
+       server  : string;
+begin
+
+       server := UrlToServer( inBoard.URL );
+       if Is2chHost( server ) then
+               Result := server + 'test/read.cgi/' + inBoard.BBSID + '/' + inKey + '/l50'
+       else
+               Result := server + 'test/read.cgi?bbs=' + inBoard.BBSID + '&key=' + inKey + '&ls=50';
+
+end;
+
+(*************************************************************************
+ *\8b@\94\\96¼\81@\81@\81F\83{\81[\83h\83t\83@\83C\83\8b\97ñ\8b\93
+ *\89Â\8e\8b\81@\81@\81@\81FPublic
+ *************************************************************************)
+procedure TGikoSys.ListBoardFile;
+var
+       boardFileList   : TStringList;
+       i, l                                    : Integer;
+begin
+
+  // BBS \82Ì\8aJ\95ú
+  try
+    for i := 0 to Length( BBSs ) - 1 do
+      BBSs[ i ].Free;
+  except
+  end;
+  SetLength( BBSs, 0 );
+
+  l := 0;
+  // \94Â\83\8a\83X\83g\82Ì\97ñ\8b\93
+  if FileExists( GikoSys.GetBoardFileName ) then begin
+    SetLength( BBSs, l + 1 );
+    BBSs[ l ]                          := TBBS.Create( GikoSys.GetBoardFileName );
+    BBSs[ l ].Title    := '\82Q\82¿\82á\82ñ\82Ë\82é';
+               Inc( l );
+  end;
+
+  if FileExists( GikoSys.GetCustomBoardFileName ) then begin
+    SetLength( BBSs, l + 1 );
+    BBSs[ l ]                          := TBBS.Create( GikoSys.GetCustomBoardFileName );
+    BBSs[ l ].Title    := '\82»\82Ì\91¼';
+               Inc( l );
+  end;
+
+  // Board \83t\83H\83\8b\83_
+  if DirectoryExists( GikoSys.Setting.GetBoardDir ) then begin
+    BoardFileList := TStringList.Create;
+    try
+      GikoSys.GetFileList( GikoSys.Setting.GetBoardDir, '*', BoardFileList, True, True );
+                       SetLength( BBSs, l + BoardFileList.Count );
+      for i := BoardFileList.Count - 1 downto 0 do begin
+        BBSs[ l ]                              := TBBS.Create( BoardFileList[ i ] );
+        BBSs[ l ].Title        := ChangeFileExt( ExtractFileName( BoardFileList[ i ] ), '' );
+
+        Inc( l );
+      end;
+    finally
+      BoardFileList.Free;
+    end;
+  end;
+
+end;
+
+(*************************************************************************
+ *\8b@\94\\96¼\81@\81@\81F\83{\81[\83h\83t\83@\83C\83\8b\93Ç\82Ý\8d\9e\82Ý
+ *\89Â\8e\8b\81@\81@\81@\81FPublic
+ *************************************************************************)
+procedure TGikoSys.ReadBoardFile( bbs : TBBS );
+var
+       idx                                             : Integer;
+       ini                                             : TMemIniFile;
+
+       boardFile                       : TStringList;
+       CategoryList    : TStringList;
+       BoardList                       : TStringList;
+       Category                        : TCategory;
+       Board                                   : TBoard;
+       inistr                          : string;
+       RoundItem                       : TRoundItem;
+
+       i, iBound                       : Integer;
+       j, jBound                       : Integer;
+       k, kBound                       : Integer;
+begin
+
+  if not FileExists( bbs.FilePath ) then
+    Exit;
+
+       bbs.Clear;
+  ini := TMemIniFile.Create('');
+  boardFile := TStringList.Create;
+  try
+    boardFile.LoadFromFile( bbs.FilePath );
+
+    ini.SetStrings( boardFile );
+    CategoryList       := TStringList.Create;
+    BoardList                  := TStringList.Create;
+    try
+      ini.ReadSections( CategoryList );
+
+      iBound := CategoryList.Count - 1;
+      for i := 0 to iBound do begin
+        ini.ReadSection( CategoryList[i], BoardList );
+        Category                               := TCategory.Create;
+        Category.No                    := i + 1;
+        Category.Title := CategoryList[i];
+
+        jBound := BoardList.Count - 1;
+        for j := 0 to jBound do begin
+          Board := nil;
+          inistr := ini.ReadString(CategoryList[i], BoardList[j], '');
+
+          //===== \83v\83\89\83O\83C\83\93
+          try
+            kBound := Length( BoardPlugIns ) - 1;
+            for k := 0 to kBound do begin
+              if Assigned( Pointer( BoardPlugIns[ k ].Module ) ) then begin
+                if BoardPlugIns[ k ].AcceptURL( inistr ) = atBoard then begin
+                  Board := TBoard.Create( BoardPlugIns[ k ], inistr );
+
+                  Break;
+                end;
+              end;
+            end;
+          except
+            // exception \82ª\94­\90\82µ\82½\8fê\8d\87\82Í\93à\95\94\8f\88\97\9d\82É\94C\82¹\82½\82¢\82Ì\82Å\82±\82±\82Å\82Í\89½\82à\82µ\82È\82¢
+          end;
+
+          if Board = nil then
+            Board := TBoard.Create( nil, inistr );
+          Board.BeginUpdate;
+          Board.No := j + 1;
+          Board.Title := BoardList[j];
+          Board.RoundDate := ZERO_DATE;
+
+          idx := RoundList.Find(Board);
+          if idx <> -1 then begin
+            RoundItem                          := RoundList.Items[idx, grtBoard];
+            Board.Round                        := True;
+            Board.RoundName    := RoundItem.RoundName;
+          end;
+
+          Category.Add(Board);
+          Board.LoadSettings;
+          Board.EndUpdate;
+        end;
+
+        bbs.Add( Category );
+      end;
+                       bbs.IsBoardFileRead := True;
+    finally
+      BoardList.Free;
+      CategoryList.Free;
+    end;
+  finally
+    boardFile.Free;
+    ini.Free;
+  end;
+
+end;
+
+function       TGikoSys.GetUnknownCategory : TCategory;
+const
+       UNKNOWN_CATEGORY = '(\96¼\8fÌ\95s\96¾)';
+begin
+
+       if Length( BBSs ) < 2 then begin
+               Result := nil;
+               Exit;
+       end;
+
+       Result := BBSs[ 1 ].FindCategoryFromTitle( UNKNOWN_CATEGORY );
+       if Result = nil then begin
+               Result                          := TCategory.Create;
+               Result.Title    := UNKNOWN_CATEGORY;
+               BBSs[ 1 ].Add( Result );
+       end;
+
+end;
+
+function       TGikoSys.GetUnknownBoard( inPlugIn : TBoardPlugIn; inURL : string ) : TBoard;
+var
+       category : TCategory;
+const
+       UNKNOWN_BOARD = '(\96¼\8fÌ\95s\96¾)';
+begin
+
+       category := GetUnknownCategory;
+       if category = nil then begin
+               Result := nil;
+       end else begin
+               Result := category.FindBoardFromTitle( UNKNOWN_BOARD );
+               if Result = nil then begin
+                       Result                          := TBoard.Create( inPlugIn, inURL );
+                       Result.Title    := UNKNOWN_BOARD;
+                       category.Add( Result );
+               end;
+       end;
+
+end;
+function TGikoSys.GetSambaFileName : string;
+begin
+       Result := Setting.GetSambaFileName;
+end;
+procedure TGikoSys.SambaFileExists();
+var
+       sambaTmp: string;
+    sambaStrList: TStringList;
+begin
+    if not FileExists(GikoSys.GetSambaFileName) then begin
+       sambaTmp := ChangeFileExt(GikoSys.GetSambaFileName, '.default');
+        sambaStrList := TStringList.Create;
+        try
+            if FileExists(sambaTmp) then begin
+                       sambaStrList.LoadFromFile(sambaTmp);
+                sambaStrList.SaveToFile(GikoSys.GetSambaFileName);
+            end;
+        finally
+               sambaStrList.Free;
+        end;
+    end;
+end;
+
 initialization
        GikoSys := TGikoSys.Create;