OSDN Git Service

・板がない場合は IE で開くように変更。
[gikonavigoeson/gikonavi.git] / GikoSystem.pas
index 64271ea..ffc398b 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
@@ -77,7 +78,7 @@ type
                FSt: Integer;                           //\8aJ\8en\83\8c\83X\94Ô
                FTo: Integer;                           //\8fI\97¹\83\8c\83X\94Ô
                FFirst: Boolean;                //>>1\82Ì\95\\8e¦
-               FStBegin: Boolean;  //1\81`\95\\8e¦
+               FStBegin: Boolean;      //1\81`\95\\8e¦
                FToEnd: Boolean;                //\81`\8dÅ\8cã\82Ü\82Å\95\\8e¦
                FDone: Boolean;                 //\90¬\8c÷
        end;
@@ -88,17 +89,17 @@ type
                FSetting: TSetting;
                FDolib: TDolib;
                FAWKStr: TAWKStr;
+               FOnlyAHundredRes : Boolean;
 //             FExitWrite: TStringList;
 //             function StrToFloatDef(s: string; Default: Double): Double;
-
        public
                { Public \90é\8c¾ }
-        FAbon : TAbon;
-        FSelectResFilter : TAbon;
+               FAbon : TAbon;
+               FSelectResFilter : TAbon;
                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;
@@ -115,9 +116,15 @@ type
                function GetTempFolder: string;
                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;
 
                procedure ReadSubjectFile(Board: TBoard);
@@ -125,6 +132,7 @@ type
                procedure WriteThreadDat(Board: TBoard);
                function ParseIndexLine(Line: string): TIndexRec;
                procedure GetFileList(Path: string; Mask: string; 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);
                function AddAnchorTag(s: string): string;
@@ -175,17 +183,32 @@ type
                function Parse2chURL2(URL: string): TPathRec;
                procedure ParseURI(var URL, Protocol, Host, Path, Document, Port, Bookmark: string);
                function GetVersionBuild: Integer;
+               function        GetThreadURL2BoardURL( inURL : string ) : string;
+               function        Get2chThreadURL2BoardURL( inURL : string ) : string;
+               function        Get2chBrowsableThreadURL( inURL : string ) : string;
+               function        Get2chBoard2ThreadURL( inBoard : TBoard; inKey : string ) : string;
+               procedure ReadBoardFile;
+
+               function        GetUnknownCategory : TCategory;
+               function        GetUnknownBoard( inPlugIn : TBoardPlugIn; inURL : string ) : TBoard;
+
+               // \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;
+
        end;
 
 var
        GikoSys: TGikoSys;
 const
-       LENGTH_RESTITLE     = 40;
-       ZERO_DATE: Integer  = 25569;
+       LENGTH_RESTITLE                 = 40;
+       ZERO_DATE: Integer      = 25569;
        BETA_VERSION_NAME_E = 'beta';
        BETA_VERSION_NAME_J = 'ÊÞÀ';
-       BETA_VERSION        = 37;
-       BETA_VERSION_BUILD  = '';                               //debug\94Å\82È\82Ç
+       BETA_VERSION                            = 44;
+       BETA_VERSION_BUILD      = '';                           //debug\94Å\82È\82Ç
+       APP_NAME                                                = 'gikoNavi';
 
 implementation
 
@@ -193,19 +216,14 @@ 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';
-       FOLDER_INDEX_VERSION          = '1.01';
-       USER_AGENT                    = 'Monazilla';
-       APP_NAME                      = 'gikoNavi';
-               DEFAULT_NGWORD_FILE_NAME : String = 'NGword.txt';
-        NGWORDs_DIR_NAME : String = 'NGwords';
+       FOLDER_INDEX_VERSION                                    = '1.01';
+       USER_AGENT                                                                              = 'Monazilla';
+       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^
@@ -215,16 +233,23 @@ begin
        FSetting := TSetting.Create;
        FDolib := TDolib.Create;
        FAWKStr := TAWKStr.Create(nil);
-    if DirectoryExists(GetConfigDir) = false then begin
-       CreateDir(GetConfigDir);
-    end;
+       if DirectoryExists(GetConfigDir) = false then begin
+               CreateDir(GetConfigDir);
+       end;
        FAbon := TAbon.Create;
        FAbon.Setroot(GetConfigDir+NGWORDs_DIR_NAME);
-    //FAbon.SetNGwordpath(DEFAULT_NGWORD_FILE_NAME);
-    FAbon.GoHome;
-    FSelectResFilter := TAbon.Create;
+       FAbon.GoHome;
+       FAbon.ReturnNGwordLineNum := FSetting.ShowNGLinesNum;
+       FAbon.SetNGResAnchor := FSetting.AddResAnchor;
+       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;
 
 (*************************************************************************
@@ -242,7 +267,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
@@ -285,7 +311,7 @@ end;
  *************************************************************************)
 function TGikoSys.GetBoardFileName: string;
 begin
-       Result := GetAppDir + CONFIG_DIR_NAME + '\' + BOARD_FILE_NAME;
+       Result := Setting.GetBoardFileName;
 end;
 
 (*************************************************************************
@@ -293,7 +319,7 @@ end;
  *************************************************************************)
 function TGikoSys.GetCustomBoardFileName: string;
 begin
-       Result := GetAppDir + CONFIG_DIR_NAME + '\' + CUSTOMBOARD_FILE_NAME;
+       Result := Setting.GetCustomBoardFileName;
 end;
 
 (*************************************************************************
@@ -301,7 +327,7 @@ end;
  *************************************************************************)
 function TGikoSys.GetHtmlTempFileName: string;
 begin
-       Result := TEMP_FOLDER;
+       Result := Setting.GetHtmlTempFileName;
 end;
 
 
@@ -310,7 +336,7 @@ end;
  *************************************************************************)
 function TGikoSys.GetAppDir: string;
 begin
-       Result := ExtractFilePath(Application.ExeName);
+       Result := Setting.GetAppDir;
 end;
 
 (*************************************************************************
@@ -318,7 +344,7 @@ end;
  *************************************************************************)
 function TGikoSys.GetTempFolder: string;
 begin
-       Result := GetAppDir + TEMP_FOLDER;
+       Result := Setting.GetTempFolder;
 end;
 
 (*************************************************************************
@@ -326,7 +352,7 @@ end;
  *************************************************************************)
 function TGikoSys.GetSentFileName: string;
 begin
-       Result := GetAppDir + SENT_FILE_NAME;
+       Result := Setting.GetSentFileName;
 end;
 
 (*************************************************************************
@@ -334,7 +360,7 @@ end;
  *************************************************************************)
 function TGikoSys.GetOutBoxFileName: string;
 begin
-       Result := GetAppDir + OUTBOX_FILE_NAME;
+       Result := Setting.GetOutBoxFileName;
 end;
 
 (*************************************************************************
@@ -342,25 +368,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;
 
-(*************************************************************************
- *URL\82ð\8dì\90¬(\83R\83s\83y\97p)
- *************************************************************************)
-function TGikoSys.GetURL(BBSID: string; FileName: string): string;
-var
-       Board: TBoard;
+function TGikoSys.GetSkinDir: string;
+begin
+       Result := Setting.GetSkinDir;
+end;
+
+function TGikoSys.GetSkinHeaderFileName: string;
+begin
+       Result := Setting.GetSkinHeaderFileName;
+end;
+
+function TGikoSys.GetSkinFooterFileName: 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.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
+       Result := Setting.GetSkinNewmarkFileName;
 end;
 
 // UserAgent\8eæ\93¾
@@ -444,42 +492,59 @@ var
        ResRec: TResRec;
        RoundItem: TRoundItem;
        idx: Integer;
+       usePlugIn : Boolean;
 begin
        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
                        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
+               for i := sl.Count - 1 downto 1 do begin
                        Rec := ParseIndexLine(sl[i]);
 
-                       ThreadItem := TThreadItem.Create;
+                       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;
@@ -499,15 +564,6 @@ begin
                        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);
@@ -548,6 +604,7 @@ begin
                        if (ThreadItem.IsLogFile) and (ThreadItem.UnRead) then
                                Inc(UnRead);
                end;
+
                if UnRead <> Board.UnRead then
                        Board.UnRead := UnRead;
 
@@ -556,7 +613,13 @@ 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 ), Rec.FFileName ) )
+                       else
+                               ThreadItem := TThreadItem.Create(
+                                       nil, Get2chBoard2ThreadURL( Board, ChangeFileExt( Rec.FFileName, '' ) ) );
                        ThreadItem.No := Board.Count + 1;
                        ThreadItem.FileName := FileList[i];
                        ThreadItem.Title := ResRec.FTitle;
@@ -622,7 +685,7 @@ begin
                                         + Format('%x', [0]) + #1                                               //LastModified
                                         + Format('%x', [0]) + #1                                               //Kokomade
                                         + Format('%x', [0]) + #1                                               //NewReceive
-                                        + '0' + #1                                                             //\96¢\8eg\97p
+                                        + '0' + #1                                                                                             //\96¢\8eg\97p
                                         + Format('%x', [0]) + #1                                               //UnRead
                                         + Format('%x', [0]) + #1                                               //ScrollTop
                                         + Format('%x', [Rec.FCount]) + #1      //AllResCount
@@ -658,7 +721,7 @@ begin
        if not Board.IsThreadDatRead then
                Exit;
        FileName := Board.GetFolderIndexFileName;
-       ForceDirectoriesEx(Board.ParentCategory.ParentBBS2ch.GetLogFolder + Board.BBSID);
+       ForceDirectoriesEx( ExtractFilePath( FileName ) );
 
        sl := TStringList.Create;
        try
@@ -761,11 +824,163 @@ begin
        end;
 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é
+procedure TGikoSys.GetDirectoryList(Path: string; Mask: string; List: TStringList; SubDir: Boolean);
+var
+       rc: Integer;
+       SearchRec : TSearchRec;
+       s: string;
+begin
+       Path := IncludeTrailingPathDelimiter(Path);
+       rc := FindFirst(Path + '*.*', faDirectory, SearchRec);
+       try
+               while rc = 0 do begin
+                       if (SearchRec.Name <> '..') and (SearchRec.Name <> '.') then begin
+                               s := Path + SearchRec.Name;
+                               //if (SearchRec.Attr and faDirectory > 0) then
+                               //      s := IncludeTrailingPathDelimiter(s)
+
+                               if (SearchRec.Attr and faDirectory > 0) and (MatchesMask(s, Mask)) then
+                                       List.Add( IncludeTrailingPathDelimiter( s ) );
+                               if SubDir and (SearchRec.Attr and faDirectory > 0) then
+                                       GetDirectoryList(s, Mask, List, True);
+                       end;
+                       rc := FindNext(SearchRec);
+               end;
+       finally
+               SysUtils.FindClose(SearchRec);
+       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);
+                                                                                        //Skin.Text := CustomStringReplace( Skin.Text, '<BBSNAME/>', ThreadItem.ParentBoard.ParentCategory.ParenTBBS.Title);
+                               //Skin.Text := CustomStringReplace( Skin.Text, '<THREADURL/>', ThreadItem.URL);
+                                                               CustomStringReplace( Skin, '<THREADURL/>', ThreadItem.URL);
+                       except end;
+                       //Skin.Text := CustomStringReplace( Skin.Text, '<BOARDNAME/>', ThreadItem.ParentBoard.Title);
+                                               CustomStringReplace( Skin, '<BOARDNAME/>', ThreadItem.ParentBoard.Title);
+                       //Skin.Text := CustomStringReplace( Skin.Text, '<BOARDURL/>', ThreadItem.ParentBoard.URL);
+                                               CustomStringReplace( Skin, '<BOARDURL/>', ThreadItem.ParentBoard.URL);
+                       //Skin.Text := CustomStringReplace( Skin.Text, '<THREADNAME/>', ThreadItem.Title);
+                                               CustomStringReplace( Skin, '<THREADNAME/>', ThreadItem.Title);
+                       //Skin.Text := CustomStringReplace( Skin.Text, '<SKINPATH/>', Setting.CSSFileName);
+                                               CustomStringReplace( Skin, '<SKINPATH/>', Setting.CSSFileName);
+                       //Skin.Text := CustomStringReplace( Skin.Text, '<GETRESCOUNT/>', IntToStr( ThreadItem.NewReceive - 1 ));
+                                               CustomStringReplace( Skin, '<GETRESCOUNT/>', IntToStr( ThreadItem.NewReceive - 1 ));
+                       //Skin.Text := CustomStringReplace( Skin.Text, '<NEWRESCOUNT/>', IntToStr( ThreadItem.NewResCount ));
+                                               CustomStringReplace( Skin, '<NEWRESCOUNT/>', IntToStr( ThreadItem.NewResCount ));
+                       //Skin.Text := CustomStringReplace( Skin.Text, '<ALLRESCOUNT/>', IntToStr( ThreadItem.AllResCount ));
+                                               CustomStringReplace( Skin, '<ALLRESCOUNT/>', IntToStr( ThreadItem.AllResCount ));
+
+                       //Skin.Text := CustomStringReplace( Skin.Text, '<NEWDATE/>',
+                       //FormatDateTime('yyyy/mm/dd(ddd) hh:mm', ThreadItem.RoundDate));
+                                               CustomStringReplace( Skin, '<NEWDATE/>',FormatDateTime('yyyy/mm/dd(ddd) hh:mm', ThreadItem.RoundDate));
+                       //Skin.Text := CustomStringReplace( Skin.Text, '<SIZEKB/>', IntToStr( Floor( SizeByte / 1024 ) ));
+                                               CustomStringReplace( Skin, '<SIZEKB/>', IntToStr( Floor( SizeByte / 1024 ) ));
+                       //Skin.Text := CustomStringReplace( Skin.Text, '<SIZE/>', IntToStr( SizeByte ));
+                                               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);
+                                               //Skin.Text := CustomStringReplace( Skin.Text, '&BBSNAME', ThreadItem.ParentBoard.ParentCategory.ParenTBBS.Title);
+                               //Skin.Text := CustomStringReplace( Skin.Text, '&THREADURL', ThreadItem.URL);
+                                                               CustomStringReplace( Skin, '&THREADURL', ThreadItem.URL);
+                       except end;
+                       //Skin.Text := CustomStringReplace( Skin.Text, '&BOARDNAME', ThreadItem.ParentBoard.Title);
+                                               CustomStringReplace( Skin, '&BOARDNAME', ThreadItem.ParentBoard.Title);
+                       //Skin.Text := CustomStringReplace( Skin.Text, '&BOARDURL', ThreadItem.ParentBoard.URL);
+                                               CustomStringReplace( Skin, '&BOARDURL', ThreadItem.ParentBoard.URL);
+                       //Skin.Text := CustomStringReplace( Skin.Text, '&THREADNAME', ThreadItem.Title);
+                                               CustomStringReplace( Skin, '&THREADNAME', ThreadItem.Title);
+                       //Skin.Text := CustomStringReplace( Skin.Text, '&SKINPATH', Setting.CSSFileName);
+                                               CustomStringReplace( Skin, '&SKINPATH', Setting.CSSFileName);
+                       //Skin.Text := CustomStringReplace( Skin.Text, '&GETRESCOUNT', IntToStr( ThreadItem.NewReceive - 1 ));
+                                               CustomStringReplace( Skin, '&GETRESCOUNT', IntToStr( ThreadItem.NewReceive - 1 ));
+                       //Skin.Text := CustomStringReplace( Skin.Text, '&NEWRESCOUNT', IntToStr( ThreadItem.NewResCount ));
+                                               CustomStringReplace( Skin, '&NEWRESCOUNT', IntToStr( ThreadItem.NewResCount ));
+                       //Skin.Text := CustomStringReplace( Skin.Text, '&ALLRESCOUNT', IntToStr( ThreadItem.AllResCount ));
+                                               CustomStringReplace( Skin, '&ALLRESCOUNT', IntToStr( ThreadItem.AllResCount ));
+
+                       //Skin.Text := CustomStringReplace( Skin.Text, '&NEWDATE',
+                       //              FormatDateTime('yyyy/mm/dd(ddd) hh:mm', ThreadItem.RoundDate));
+                                               CustomStringReplace( Skin, '&NEWDATE', FormatDateTime('yyyy/mm/dd(ddd) hh:mm', ThreadItem.RoundDate));
+                       //Skin.Text := CustomStringReplace( Skin.Text, '&SIZEKB', IntToStr( Floor( SizeByte / 1024 ) ));
+                                               CustomStringReplace( Skin, '&SIZEKB', IntToStr( Floor( SizeByte / 1024 ) ));
+                       //Skin.Text := CustomStringReplace( Skin.Text, '&SIZE', IntToStr( SizeByte ));
+                                               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="mailo:' + 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="mailo:' + 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;
@@ -773,54 +988,275 @@ var
        FileName: string;
        NewReceiveNo: Integer;
        Res: TResRec;
+       boardPlugIn : TBoardPlugIn;
+
+       UserOptionalStyle: string;
+       SkinHeader: string;
+       SkinNewRes: string;
+       SkinRes: string;
+       SizeByte: Integer;
+
+       function LoadSkin( fileName: string ): string;
+       begin
+               Result := LoadFromSkin( fileName, ThreadItem, SizeByte );
+       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
+                                                               SaveList.Add( LoadSkin( GetSkinNewmarkFileName ) );
+                                                       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
+                                                               SaveList.Add( LoadSkin( GetSkinBookmarkFileName ) );
+                                                       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
-            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é
+                       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';
 
+                       // \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.UseCSS and FileExists(CSSFileName) then begin
+                       if GikoSys.Setting.UseSkin then begin
+                               // \83X\83L\83\93\8eg\97p
+                               // \83X\83L\83\93\82Ì\90Ý\92è
+                               try
+                                       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;
+
+                               SaveList.Add('<a name="top"></a>');
+
+                               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);
+
+                                               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 := 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);
+                                               if Res.FName = '' then
+                                                       Res.FName := '&nbsp;';
+
+                                               // \90V\92\85\83}\81[\83N
+                                               if (NewReceiveNo = (i + 1)) or ((NewReceiveNo = 0) and (i = 0)) then begin
+                                                       try
+                                                               SaveList.Add( LoadSkin( GetSkinNewmarkFileName ) );
+                                                       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
+                                                               SaveList.Add( LoadSkin( GetSkinBookmarkFileName ) );
+                                                       except
+                                                               SaveList.Add( '<a name="koko"></a>' );
+                                                       end;
+                                               end;
+                                       end;
+                                       SizeByte := SizeByte + Length( SaveList.Text );
+                                       doc.Write(SaveList.Text);
+                                       SaveList.Clear;
+                               end;
+                               SaveList.Add('<a name="bottom"></a>');
+                               SizeByte := SizeByte + Length( SaveList.Text );
+                               // \83X\83L\83\93(\83t\83b\83^)
+                               try
+                                       SaveList.Add( LoadSkin( GetSkinFooterFileName ) );
+                               except
+                               end;
+                               doc.Write(SaveList.Text);
+
+                       end else if GikoSys.Setting.UseCSS and FileExists(CSSFileName) then begin
                                //CSS\8eg\97p
                                //CSSFileName := GetAppDir + CSS_FILE_NAME;
 //                             SaveList.Add('<html lang="ja"><head>');
                                SaveList.Add('<html><head>');
                                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">');
+                               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
@@ -828,73 +1264,49 @@ begin
                                                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]);
-                                               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 + '</a></b><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 + '</a></b>'
-                                                                                                        + '<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('</dl>');
                                SaveList.Add('<a name="last"></a>');
                                SaveList.Add('</body></html>');
+
                                doc.Write(SaveList.Text);
                        end else begin
                                //CSS\94ñ\8eg\97p
@@ -910,6 +1322,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);
 
@@ -922,33 +1337,28 @@ begin
                                                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);
                                                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>');
@@ -963,7 +1373,6 @@ begin
                ReadList.Free;
        end;
 end;
-
 (*************************************************************************
  *http://\82Ì\95\8e\9a\97ñ\82ðanchor\83^\83O\95t\82«\82É\82·\82é\81B
  *************************************************************************)
@@ -973,14 +1382,19 @@ const
                                                                         + 'abcdefghijklmnopqrstuvwxyz'
                                                                         + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
                                                                         + '#$%&()*+,-./:;=?@[]^_`{|}~!''\';
+       ANCHOR_REF      = 'href=';
+       RES_REF                 = '&gt;&gt;';
 var
        wkIdx: array[0..9] of Integer;
        url: string;
        href: string;
        i: 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);
@@ -995,7 +1409,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
@@ -1004,10 +1418,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;
 
@@ -1078,7 +1496,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;
@@ -1090,7 +1508,7 @@ end;
 function TGikoSys.DivideStrLine(Line: string): TResRec;
 var
        Delim: string;
-    bufbody : String;
+               bufbody : String;
 begin
        if Pos('<>', Line) = 0 then begin
                Delim := ',';
@@ -1102,11 +1520,11 @@ begin
        Result.FName := Trim(GetTokenIndex(Line, Delim, 0));
        Result.FMailTo := Trim(GetTokenIndex(Line, Delim, 1));
        Result.FDateTime := Trim(GetTokenIndex(Line, Delim, 2));
-    bufBody := Trim(GetTokenIndex(Line, Delim, 3));
-    if bufbody = '' then begin
-        Insert('&nbsp;',bufbody, 1);
-    end;
-    Result.FBody := bufBody;
+       bufBody := Trim(GetTokenIndex(Line, Delim, 3));
+       if bufbody = '' then begin
+               Insert('&nbsp;',bufbody, 1);
+       end;
+       Result.FBody := bufBody;
        Result.FTitle := Trim(GetTokenIndex(Line, Delim, 4));
 
 end;
@@ -1253,12 +1671,12 @@ var
 begin
        sl := TStringList.Create;
        try
-        try
+               try
                        sl.LoadFromFile(FileName);
                        Result := sl.Count;
-        except
-               Result := 0;
-        end;
+               except
+                       Result := 0;
+               end;
        finally
                sl.Free;
        end;
@@ -1269,32 +1687,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;
@@ -1405,7 +1814,7 @@ const
                 '\81g','\81h','\81k','\81l','\81e','\81f','\81\83','\81\84','\81á','\81â',
                 '\81o','\81p','\81q','\81r','\81w','\81x','\81¬','\81c', '\81@');
 var
-       Chr : array [0..255]  of  char;
+       Chr : array [0..255]    of      char;
        S : string;
        i : integer;
 begin
@@ -1414,8 +1823,8 @@ begin
                Result := s;
        end else begin
                S := s;
-               for i := Low(ERASECHAR)  to  High(ERASECHAR) do  begin
-                       S := StringReplace(S, ERASECHAR[i], '', [rfReplaceAll]);
+               for i := Low(ERASECHAR) to      High(ERASECHAR) do      begin
+                       S := CustomStringReplace(S, ERASECHAR[i], '');
                end;
                if (Length(S) <= ALength) then begin
                        Result := S;
@@ -1451,14 +1860,14 @@ function TGikoSys.ConvRes(const Body, Bbs, Key,
 type
        PIndex = ^TIndex;
        TIndex = record
-               FIndexFrom  : integer;
-               FIndexTo    : integer;
-               FNo         : string;
+               FIndexFrom      : integer;
+               FIndexTo                : integer;
+               FNo                              : string;
        end;
 const
-       GT  = '&gt;';
-       SN  = '0123456789-';
-       ZN  = '\82O\82P\82Q\82R\82S\82T\82U\82V\82W\82X\81|';
+       GT      = '&gt;';
+       SN      = '0123456789-';
+       ZN      = '\82O\82P\82Q\82R\82S\82T\82U\82V\82W\82X\81|';
 var
        i : integer;
        s,r : string;
@@ -1468,7 +1877,7 @@ var
        No: string;
        sx: string;
        List: TList;
-       oc  : string;
+       oc      : string;
        st, et: string;
        chk : boolean;
        al : boolean;
@@ -1477,9 +1886,9 @@ var
                FIndex : PIndex;
        begin
                New(FIndex);
-               FIndex.FIndexFrom  := IndexFrom;
-               FIndex.FIndexTo    := IndexTo;
-               FIndex.FNo         := No;
+               FIndex.FIndexFrom       := IndexFrom;
+               FIndex.FIndexTo         := IndexTo;
+               FIndex.FNo                               := No;
                List.Add(FIndex);
        end;
        function ChooseString(const Text, Separator: string; Index: integer): string;
@@ -1487,140 +1896,140 @@ 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));
+               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;
+               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;
+       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;
+                                               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;
+                               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;
+                                               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;
+                               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;
+                                               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
+                               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
+                                               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;
+                                                       al := True;
                                                end;
-            sw  :=  False;
-            //
+                                               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);
+                                               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;
+                                               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);
+                               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
-    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) +
+                       Break;
+               end;
+       end;
+       for i :=        List.Count - 1  downto  0 do    begin
+               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="../test/read.cgi?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s" target="_blank">',
                                                                [ParamBBS, Bbs, ParamKey, Key, ParamStart, st, ParamTo, et, ParamNoFirst, ParamTrue]) +
                                        Copy(r,PIndex(List[i]).FIndexFrom, PIndex(List[i]).FIndexTo - PIndex(List[i]).FIndexFrom) + '</A>' +
@@ -1628,7 +2037,7 @@ begin
                Dispose(PIndex(List[i]));
        end;
        List.Free;
-       Result  :=  r;
+       Result  :=      r;
 end;
 
 (*************************************************************************
@@ -1792,13 +2201,13 @@ begin
                Path := Path + ' ' + Param;
 
        SI.Cb := SizeOf(Si);
-       SI.lpReserved  := nil;
-       SI.lpDesktop   := nil;
-       SI.lpTitle     := nil;
-       SI.dwFlags     := 0;
+       SI.lpReserved   := nil;
+       SI.lpDesktop     := nil;
+       SI.lpTitle               := nil;
+       SI.dwFlags               := 0;
        SI.cbReserved2 := 0;
        SI.lpReserved2 := nil;
-       SI.dwysize     := 0;
+       SI.dwysize               := 0;
        Windows.CreateProcess(nil,
                                                                PChar(Path),
                                                                nil,
@@ -1947,6 +2356,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]);
@@ -1958,10 +2369,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;
@@ -2236,23 +2643,23 @@ procedure TGikoSys.ParseURI(var URL, Protocol, Host, Path, Document, Port, Bookm
 var
        URI: TIdURI;
 begin
-               Protocol := '';
-               Host := '';
-               Path := '';
-               Document := '';
-               Port := '';
-               Bookmark := '';
-               URI := TIdURI.Create(URL);
-               try
-                       Protocol := URI.Protocol;
-                       Host := URI.Host;
-                       Path := URI.Path;
-                       Document := URI.Document;
-                       Port := URI.Port;
-                       Bookmark := URI.Bookmark;
-               finally
-                       URI.Free;
-               end;
+       Protocol := '';
+       Host := '';
+       Path := '';
+       Document := '';
+       Port := '';
+       Bookmark := '';
+       URI := TIdURI.Create(URL);
+       try
+               Protocol := URI.Protocol;
+               Host := URI.Host;
+               Path := URI.Path;
+               Document := URI.Document;
+               Port := URI.Port;
+               Bookmark := URI.Bookmark;
+       finally
+               URI.Free;
+       end;
 end;
 
 function TGikoSys.GetVersionBuild: Integer;
@@ -2278,6 +2685,285 @@ begin
        end;
 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\93Ç\82Ý\8d\9e\82Ý
+ *\89Â\8e\8b\81@\81@\81@\81FPublic
+ *\97\9a\97ð\82P\81@\81@\81F\90V\8bK\8dì\90¬
+ *************************************************************************)
+procedure TGikoSys.ReadBoardFile;
+var
+       idx: Integer;
+       ini: TMemIniFile;
+       CategoryList: TStringList;
+       BoardList: TStringList;
+       Category: TCategory;
+       Board: TBoard;
+       inistr: string;
+       RoundItem: TRoundItem;
+
+       // BBS \94z\97ñ(1 \83{\81[\83h\83t\83@\83C\83\8b\82É\82Â\82« 1 \8d\80\96Ú)
+       bbsList                         : array of TStringList;
+       boardFileList   : TStringList;
+
+       i, iBound                       : Integer;
+       j, jBound                       : Integer;
+       k, kBound                       : Integer;
+       l, lBound                       : Integer;
+begin
+       ini := TMemIniFile.Create('');
+       try
+               // BBS \82Ì\8aJ\95ú
+               try
+                       for i := 0 to Length( BBSs ) - 1 do
+                               BBSs[ i ].Free;
+               except
+               end;
+               SetLength( BBSs, 0 );
+
+               // \94Â\83\8a\83X\83g\82Ì\97ñ\8b\93
+               if FileExists( GikoSys.GetBoardFileName ) then begin
+                       l                                                               := Length( bbsList );
+                       SetLength( bbsList, l + 1 );
+                       bbsList[ l ]            := TStringList.Create;
+                       bbsList[ l ].LoadFromFile( GikoSys.GetBoardFileName );
+
+                       SetLength( BBSs, l + 1 );
+                       BBSs[ l ]                               := TBBS.Create( GikoSys.Setting.LogFolder );
+                       BBSs[ l ].Title := '\82Q\82¿\82á\82ñ\82Ë\82é';
+               end;
+
+               if FileExists( GikoSys.GetCustomBoardFileName ) then begin
+                       l                                                               := Length( bbsList );
+                       SetLength( bbsList, l + 1 );
+                       bbsList[ l ]            := TStringList.Create;
+                       bbsList[ l ].LoadFromFile( GikoSys.GetCustomBoardFileName );
+
+                       SetLength( BBSs, l + 1 );
+                       BBSs[ l ]                               := TBBS.Create( GikoSys.Setting.LogFolder );
+                       BBSs[ l ].Title := '\82»\82Ì\91¼';
+               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 );
+                               l := Length( bbsList );
+                               for i := BoardFileList.Count - 1 downto 0 do begin
+                                       SetLength( bbsList, l + 1 );
+                                       bbsList[ l ]            := TStringList.Create;
+                                       bbsList[ l ].LoadFromFile( BoardFileList[ i ] );
+
+                                       SetLength( BBSs, l + 1 );
+                                       BBSs[ l ]                               := TBBS.Create( GikoSys.Setting.LogFolder );
+                                       BBSs[ l ].Title := ChangeFileExt( ExtractFileName( BoardFileList[ i ] ), '' );
+
+                                       Inc( l );
+                               end;
+                       finally
+                               BoardFileList.Free;
+                       end;
+               end;
+
+               lBound := Length( bbsList ) - 1;
+               for l := 0 to lBound do begin
+                       ini.SetStrings( bbsList[ l ] );
+                       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;
+
+                                       BBSs[ l ].Add( Category );
+                               end;
+                       finally
+                               BoardList.Free;
+                               CategoryList.Free;
+                       end;
+               end;
+       finally
+               ini.Free;
+               lBound := Length( bbsList ) - 1;
+               for l := 0 to lBound do
+                       bbsList[ l ].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;
+
 initialization
        GikoSys := TGikoSys.Create;