OSDN Git Service

1.52.1.658
[gikonavigoeson/gikonavi.git] / HTMLCreate.pas
index 82707a9..baf9a40 100644 (file)
@@ -15,9 +15,32 @@ uses
        {HttpApp,} YofUtils, {URLMon,} BoardGroup, {gzip,} {Dolib,}
        {bmRegExp,} AbonUnit,   MojuUtils, Setting,
        ExternalBoardManager, ExternalBoardPlugInMain{,}
-       {Sort,} ,GikoBayesian;
+       {Sort,} ,GikoBayesian, HintWindow, ActiveX;
 
 type
+
+       PResLinkRec = ^TResLinkRec;
+       TResLinkRec = record
+               FBbs: string;
+               FKey : string;
+       end;
+
+       TBufferedWebBrowser = class(TStringList)
+       private
+               //! \8f\91\82«\8d\9e\82Þ\83u\83\89\83E\83U
+               FBrowser: TWebBrowser;
+               //! \89½\8ds\82Ü\82Å\82½\82ß\82é\82©\82Ì\83T\83C\83Y
+               FBuffSize: Integer;
+               //! \83u\83\89\83E\83U\82ÌIHTMLDocument2\83C\83\93\83^\83t\83F\81[\83X\82ð\95Û\8e\9d\82·\82é open\82©\82çclose\82Ì\8aÔ\82Å
+               FBrowserDoc: Variant;
+       public
+               constructor Create(Browser: TWebBrowser; BuffSize: Integer);
+               destructor Destory;
+               procedure Open;
+               procedure Close;
+               procedure Flush;
+               function Add(const S: string): Integer; override;
+       end;
        THTMLCreate = class(TObject)
        private
                { Private \90é\8c¾ }
@@ -31,20 +54,34 @@ type
                constructor Create;
 
                function AddBeProfileLink(AID : string; ANum: Integer):string ;
-               procedure CreateUsePluginHTML(doc: Variant; ThreadItem: TThreadItem; var sTitle: string);
-               procedure CreateUseSKINHTML(doc: Variant; ThreadItem: TThreadItem; ReadList: TStringList);
-               procedure CreateUseCSSHTML(doc: Variant; ThreadItem: TThreadItem; ReadList: TStringList; sTitle: string );
-               procedure CreateDefaultHTML (doc: Variant; ThreadItem: TThreadItem; ReadList: TStringList; sTitle: string );
-               function ConvertResAnchor(res: string): string;
+               procedure CreateUsePluginHTML(html:TBufferedWebBrowser; ThreadItem: TThreadItem; var sTitle: string);
+               procedure CreateUseSKINHTML(html:TBufferedWebBrowser; ThreadItem: TThreadItem; ReadList: TStringList);
+               procedure CreateUseCSSHTML(html:TBufferedWebBrowser; ThreadItem: TThreadItem; ReadList: TStringList; sTitle: string );
+               procedure CreateDefaultHTML (html:TBufferedWebBrowser; ThreadItem: TThreadItem; ReadList: TStringList; sTitle: string );
+               procedure ConvertResAnchor(PRes: PResRec);
+               procedure separateNumber(var st: String; var et: String; const Text, Separator: String);
+               function checkComma(const s : String; var j : Integer; var No  : String) : boolean;
+               function addResAnchor(PAddRes: PResRec; PResLink : PResLinkRec; dat : boolean;
+                var s : String; j : Integer; const No: String) : string;
        public
                { Public \90é\8c¾ }
-               function AddAnchorTag(s: string): string;
+               procedure AddAnchorTag(PRes: PResRec);
                function LoadFromSkin(fileName: string; ThreadItem: TThreadItem; SizeByte: Integer): string;
-               function SkinedRes(skin: string; Res: TResRec; No: string): string;
+               function SkinedRes(const skin: string; PRes: PResRec; const No: string): string;
+               procedure ConvRes( PRes : PResRec; PResLink : PResLinkRec; DatToHTML: boolean = false); overload;
                function ConvRes(const Body, Bbs, Key,  ParamBBS, ParamKey, ParamStart, ParamTo, ParamNoFirst, ParamTrue : string; DatToHTML: boolean = false): string; overload;
-               function ConvRes(const Body, Bbs, Key,  ParamBBS, ParamKey, ParamStart, ParamTo, ParamNoFirst, ParamTrue, FullURL : string): string; overload;
-               procedure CreateHTML2(doc: Variant; ThreadItem: TThreadItem; var sTitle: string);
+               procedure CreateHTML2(Browser: TWebBrowser; ThreadItem: TThreadItem; var sTitle: string);
                procedure CreateHTML3(var html: TStringList; ThreadItem: TThreadItem; var sTitle: string);
+               //\83\8c\83X\83|\83b\83v\83A\83b\83v\82Ì\8dì\90¬
+               procedure SetResPopupText(Hint :TResPopup; threadItem: TThreadItem; StNum, ToNum: Integer; Title, First: Boolean);
+               //\83\8a\83\93\83N\82Ì\95\8e\9a\97ñ\82©\82ç\83\8c\83X\83|\83b\83v\83A\83b\83v\97p\82ÌURL\82É\95Ï\8a·\82·\82é
+               class function GetRespopupURL(AText, AThreadURL : string): string;
+               //\8ew\92è\82µ\82½\83p\83X\82É\83X\83L\83\93\82à\82µ\82­\82ÍCSS\82Ì\83t\83@\83C\83\8b\82Ì\83R\83s\81[\82ð\8dì\82é
+               class procedure SkinorCSSFilesCopy(path: string);
+               //dat\82P\8ds\82ð\83\8c\83X\82É\95ª\89ð\82·\82é
+               class procedure DivideStrLine(Line: string; PRes: PResRec);
+        //HTML\82©\82ç\83\8a\83\93\83N\83^\83O\82ð\8dí\8f\9c\82·\82é
+               class function DeleteLink(const s: string): string;
        end;
 
 var
@@ -120,23 +157,25 @@ begin
 
                        //----- \82Æ\82è\82 \82¦\82¸\82©\82¿\82ã\81`\82µ\82á\8cÝ\8a·\97p\81B\83R\83\81\83\93\83g\83A\83E\83g\82µ\82Ä\82à\82æ\82µ
                        // \82â\82è\82©\82½\82ª\8bê\82µ\82¢\82¯\82Ç\81A\83I\83v\83V\83\87\83\93\83_\83C\83A\83\8d\83O\82Ì\83v\83\8c\83r\83\85\81[\97p try
-                       try
-                               if ThreadItem.ParentBoard <> nil then
-                                       if ThreadItem.ParentBoard.ParentCategory <> nil then
-                                               CustomStringReplace( Skin, '&BBSNAME', ThreadItem.ParentBoard.ParentCategory.ParenTBBS.Title);
-                                       CustomStringReplace( Skin, '&THREADURL', ThreadItem.URL);
-                       except end;
-                       CustomStringReplace( Skin, '&BOARDNAME', ThreadItem.ParentBoard.Title);
-                       CustomStringReplace( Skin, '&BOARDURL', ThreadItem.ParentBoard.URL);
-                       CustomStringReplace( Skin, '&THREADNAME', ThreadItem.Title);
-                       CustomStringReplace( Skin, '&SKINPATH', GikoSys.Setting.CSSFileName);
-                       CustomStringReplace( Skin, '&GETRESCOUNT', IntToStr( ThreadItem.NewReceive - 1 ));
-                       CustomStringReplace( Skin, '&NEWRESCOUNT', IntToStr( ThreadItem.NewResCount ));
-                       CustomStringReplace( Skin, '&ALLRESCOUNT', IntToStr( ThreadItem.AllResCount ));
-
-                       CustomStringReplace( Skin, '&NEWDATE', FormatDateTime('yyyy/mm/dd(ddd) hh:mm', ThreadItem.RoundDate));
-                       CustomStringReplace( Skin, '&SIZEKB', IntToStr( Floor( SizeByte / 1024 ) ));
-                       CustomStringReplace( Skin, '&SIZE', IntToStr( SizeByte ));
+                       if GikoSys.Setting.UseKatjushaType then begin
+                               try
+                                       if ThreadItem.ParentBoard <> nil then
+                                               if ThreadItem.ParentBoard.ParentCategory <> nil then
+                                                       CustomStringReplace( Skin, '&BBSNAME', ThreadItem.ParentBoard.ParentCategory.ParenTBBS.Title);
+                                               CustomStringReplace( Skin, '&THREADURL', ThreadItem.URL);
+                               except end;
+                               CustomStringReplace( Skin, '&BOARDNAME', ThreadItem.ParentBoard.Title);
+                               CustomStringReplace( Skin, '&BOARDURL', ThreadItem.ParentBoard.URL);
+                               CustomStringReplace( Skin, '&THREADNAME', ThreadItem.Title);
+                               CustomStringReplace( Skin, '&SKINPATH', GikoSys.Setting.CSSFileName);
+                               CustomStringReplace( Skin, '&GETRESCOUNT', IntToStr( ThreadItem.NewReceive - 1 ));
+                               CustomStringReplace( Skin, '&NEWRESCOUNT', IntToStr( ThreadItem.NewResCount ));
+                               CustomStringReplace( Skin, '&ALLRESCOUNT', IntToStr( ThreadItem.AllResCount ));
+
+                               CustomStringReplace( Skin, '&NEWDATE', FormatDateTime('yyyy/mm/dd(ddd) hh:mm', ThreadItem.RoundDate));
+                               CustomStringReplace( Skin, '&SIZEKB', IntToStr( Floor( SizeByte / 1024 ) ));
+                               CustomStringReplace( Skin, '&SIZE', IntToStr( SizeByte ));
+                       end
                        //----- \82±\82±\82Ü\82Å
                end;
                Result := Skin.Text;
@@ -147,56 +186,70 @@ end;
 
 // \83\8c\83X\82Ì\92l\82ð\92u\8a·\82·\82é
 function THTMLCreate.SkinedRes(
-       skin: string;
-       Res: TResRec;
-       No: string
+       const skin: string;
+       PRes: PResRec;
+       const No: string
 ): string;
+const
+       FORMT_NAME = '<b>%s</b>';
+       FORMT_NUM  = '<a href="menu:%s" name="%s">%s</a>';
+       FORMT_MAILNAME  = '<a href="mailto:%s"><b>%s</b></a>';
 var
        spamminess      : Extended;
+{$IFDEF SPAM_FILTER_ENABLED}
        wordCount               : TWordCount;
+{$ENDIF}
 begin
-
+{$IFDEF SPAM_FILTER_ENABLED}
        wordCount := TWordCount.Create;
        try
                spamminess := Floor( GikoSys.SpamParse(
                        Res.FName + '<>' + Res.FMailTo + '<>' + Res.FBody, wordCount ) * 100 );
-
-               Skin := CustomStringReplace( Skin, '<NUMBER/>',
-                       '<a href="menu:' + No + '" name="' + No + '">' + No + '</a>');
-               Skin := CustomStringReplace( Skin, '<PLAINNUMBER/>', No);
-               Skin := CustomStringReplace( Skin, '<NAME/>', '<b>' + Res.FName + '</b>');
-               Skin := CustomStringReplace( Skin, '<MAILNAME/>',
-                       '<a href="mailto:' + Res.FMailTo + '"><b>' + Res.FName + '</b></a>');
-               Skin := CustomStringReplace( Skin, '<MAIL/>', Res.FMailTo);
-               Skin := CustomStringReplace( Skin, '<DATE/>', Res.FDateTime);
-               Skin := CustomStringReplace( Skin, '<MESSAGE/>', Res.FBody);
-               Skin := CustomStringReplace( Skin, '<SPAMMINESS/>', FloatToStr( spamminess ) );
-               Skin := CustomStringReplace( Skin, '<NONSPAMMINESS/>', FloatToStr( 100 - spamminess ) );
+{$ELSE}
+       spamminess := 0;
+{$ENDIF}
+               Result := CustomStringReplace( skin, '<SPAMMINESS/>', FloatToStr( spamminess ) );
+               Result := CustomStringReplace( Result, '<NONSPAMMINESS/>', FloatToStr( 100 - spamminess ) );
+               Result := CustomStringReplace( Result, '<MAIL/>', PRes.FMailTo);
+               Result := CustomStringReplace( Result, '<DATE/>', PRes.FDateTime);
+               Result := CustomStringReplace( Result, '<PLAINNUMBER/>', No);
+               Result := CustomStringReplace( Result, '<NAME/>',
+                       Format(FORMT_NAME, [PRes.FName]));
+               Result := CustomStringReplace( Result, '<NUMBER/>',
+                       Format(FORMT_NUM, [No, No, No]));
+               Result := CustomStringReplace( Result, '<MAILNAME/>',
+                       Format(FORMT_MAILNAME,[PRes.FMailTo, PRes.FName]));
+               Result := CustomStringReplace( Result, '<MESSAGE/>', PRes.FBody);
 
                //----- \82©\82¿\82ã\81`\82µ\82á\8cÝ\8a·\97p\81B\83R\83\81\83\93\83g\83A\83E\83g\82µ\82Ä\82à\82æ\82µ
-               Skin := CustomStringReplace( Skin, '&NUMBER',
-                       '<a href="menu:' + No + '" name="' + No + '">' + No + '</a>');
-               Skin := CustomStringReplace( Skin, '&PLAINNUMBER', No);
-               Skin := CustomStringReplace( Skin, '&NAME', '<b>' + Res.FName + '</b>');
-               Skin := CustomStringReplace( Skin, '&MAILNAME',
-                       '<a href="mailto:' + Res.FMailTo + '"><b>' + Res.FName + '</b></a>');
-               Skin := CustomStringReplace( Skin, '&MAIL', Res.FMailTo);
-               Skin := CustomStringReplace( Skin, '&DATE', Res.FDateTime);
-               Skin := CustomStringReplace( Skin, '&MESSAGE', Res.FBody);
-               Skin := CustomStringReplace( Skin, '&SPAMMINESS', FloatToStr( spamminess ) );
-               Skin := CustomStringReplace( Skin, '&NONSPAMMINESS', FloatToStr( 100 - spamminess ) );
+               if GikoSys.Setting.UseKatjushaType then begin
+                       Result := CustomStringReplace( Result, '&NUMBER',
+                               '<a href="menu:' + No + '" name="' + No + '">' + No + '</a>');
+                       Result := CustomStringReplace( Result, '&PLAINNUMBER', No);
+                       Result := CustomStringReplace( Result, '&NAME', '<b>' + PRes.FName + '</b>');
+                       Result := CustomStringReplace( Result, '&MAILNAME',
+                               '<a href="mailto:' + PRes.FMailTo + '"><b>' + PRes.FName + '</b></a>');
+                       Result := CustomStringReplace( Result, '&MAIL', PRes.FMailTo);
+                       Result := CustomStringReplace( Result, '&DATE', PRes.FDateTime);
+                       Result := CustomStringReplace( Result, '&MESSAGE', PRes.FBody);
+                       Result := CustomStringReplace( Result, '&SPAMMINESS', FloatToStr( spamminess ) );
+                       Result := CustomStringReplace( Result, '&NONSPAMMINESS', FloatToStr( 100 - spamminess ) );
+               end;
                //----- \82±\82±\82Ü\82Å
-
-               Result := Skin;
+{$IFDEF SPAM_FILTER_ENABLED}
        finally
                wordCount.Free;
        end;
+{$ENDIF}
 
 end;
 (*************************************************************************
  *http://\82Ì\95\8e\9a\97ñ\82ðanchor\83^\83O\95t\82«\82É\82·\82é\81B
  *************************************************************************)
-function THTMLCreate.AddAnchorTag(s: string): string;
+procedure THTMLCreate.AddAnchorTag(PRes: PResRec);
+const
+       _HEAD : array[0..9] of String =
+               ('', 'h', 'ht', '', 'htt', '', 'http://', '', '', '');
 var
        url: string;
        href: string;
@@ -205,10 +258,14 @@ var
        idx, idx2: Integer;
        pos : PChar;
        pp, pe : PChar;
+       s : String;
+       len : Integer;
 begin
-       Result := '';
+       s := PRes.FBody;
+       PRes.FBody := '';
 
-       while True do begin
+       //while True do begin
+       repeat
                idx  := MaxInt;
                idx2 := MaxInt;
                pp := PChar(s);
@@ -225,63 +282,62 @@ begin
 
                if idx = MaxInt then begin
                        //\83\8a\83\93\83N\82ª\96³\82¢\82æ\81B
-                       Result := Result + s;
-                       Break;
-               end;
-
-               if (idx > 1) and (idx > anchorLen) and
-                       (AnsiStrPosEx(pp + idx - 1 - anchorLen, pp + idx, pANCHORs, pANCHORe) <> nil) 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
-                       //</a></A>\82ð\92T\82·\81A\8f¬\95\8e\9a\82Å\8c©\82Â\82©\82ç\82È\82¯\82ê\82Î\91å\95\8e\9a\82Å\8c\9f\8dõ
-                       pos := AnsiStrPosEx(pp + idx, pe, pCTAGLs, pCTAGLe);
-                       if pos = nil then
-                               pos := AnsiStrPosEx(pp + idx, pe, pCTAGUs, pCTAGUe);
-                       if pos = nil then
-                               b := Length(REF_MARK[idx2])
-                       else
-                               b := pos - pp + 1;
-
-                       Result := Result + Copy(s, 1, idx + b);
-                       Delete(s, 1, idx + b);
-                       Continue;
-               end;
-
-               Result := Result + Copy(s, 1, idx - 1);
-               Delete(s, 1, idx - 1);
-               b := Length( s ) + 1;
-               pp      := PChar(s);
-               for i := 1 to b do begin
-                       pe := AnsiStrPosEx(pURLCHARs, pURLCHARe, pp, pp + 1);
-
-                       if pe = nil then begin
-                               //URL\82\82á\82È\82¢\95\8e\9a\94­\8c©\81I\82Æ\82©\81A\95\8e\9a\82ª\82È\82­\82È\82Á\82½\81B
-                               url := Copy(s, 1, i - 1);
-                               case idx2 of
-                                       1 : href := 'h' + url;
-                                       2 : href := 'ht' + url;
-                                       4 : href := 'htt' + url;
-                                       6 : href := 'http://' + url;
+                       len := Length(PRes.FBody);
+                       SetLength(PRes.FBody, Length(s) + len);
+                       Move(pp^, PRes.FBody[len + 1], Length(s));
+               end else begin
+                       if (idx > anchorLen) and
+                               (AnsiStrPosEx(pp + idx - 1 - anchorLen, pp + idx, pANCHORs, pANCHORe) <> nil) 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
+                               //</a></A>\82ð\92T\82·\81A\8f¬\95\8e\9a\82Å\8c©\82Â\82©\82ç\82È\82¯\82ê\82Î\91å\95\8e\9a\82Å\8c\9f\8dõ
+                               pos := AnsiStrPosEx(pp + idx, pe, pCTAGLs, pCTAGLe);
+                               if pos = nil then
+                                       pos := AnsiStrPosEx(pp + idx, pe, pCTAGUs, pCTAGUe);
+                               if pos = nil then
+                                       b := Length(REF_MARK[idx2])
                                else
-                                       href := url;
+                                       b := pos - (pp  + idx) + 1;
+
+                               len := Length(PRes.FBody);
+                               SetLength(PRes.FBody, len + idx + b );
+                               Move(pp^, PRes.FBody[len + 1], idx + b);
+                               Delete(s, 1, idx + b);
+                       end else begin
+                               pp      := PChar(s);
+                               len     := Length(PRes.FBody);
+                               SetLength(PRes.FBody, len + idx - 1);
+                               Move(pp^, PRes.FBody[len + 1], idx - 1);
+
+                               Delete(s, 1, idx - 1);
+                               b := Length( s ) + 1;
+                               pp      := PChar(s);
+                               for i := 1 to b do begin
+                                       //\82P\83o\83C\83g\95\8e\9a\82ÅURL\82É\8eg\82¦\82È\82¢\95\8e\9a\82È\82ç
+                                       if (AnsiStrPosEx(pURLCHARs, pURLCHARe, pp, pp + 1) = nil) then begin
+                                               url := Copy(s, 1, i - 1);
+                                               Delete(s, 1, i - 1);
+                                               href := Format('%s%s', [_HEAD[idx2], url]);
+                                               PRes.FBody
+                                                       := Format('%s<a href="%s" target="_blank">%s</a>', [PRes.FBody, href, url]);
+                                               Break;
+                                       end;
+                                       //\88ê\95\8e\9a\90i\82ß\82é\81B
+                                       Inc(pp);
                                end;
-
-                               Result := Result + '<a href="' + href + '" target="_blank">' + url + '</a>';
-                               Delete(s, 1, i - 1);
-                               Break;
                        end;
-                       //\88ê\95\8e\9a\90i\82ß\82é\81B
-                       Inc(pp);
                end;
-       end;
+       until idx = MaxInt;
 end;
 
 //\88ø\90\94\81AAID\81F\91Î\8fÛ\82Æ\82È\82é\93ú\95tID\95\8e\9a\97ñ\81AANum:\83\8c\83X\94Ô AURL\81F\82»\82Ì\83X\83\8c\83b\83h\82ÌURL
 function THTMLCreate.AddBeProfileLink(AID : string; ANum: Integer):string ;
+const
+       BE_MARK : string = 'BE:';
 var
        p : integer;
        BNum, BMark : string;
 begin
-       p := AnsiPos('BE:', AnsiUpperCase(AID));
+       p := AnsiPos(BE_MARK, AnsiUpperCase(AID));
        if p > 0 then begin
                BNum := Copy(AID, p, Length(AID));
                AID := Copy(AID, 1, p - 1);
@@ -296,393 +352,398 @@ begin
        end else
                Result := AID;
 end;
-(*************************************************************************
- *
- * from HotZonu
- *************************************************************************)
-function THTMLCreate.ConvRes(const Body, Bbs, Key,
-       ParamBBS, ParamKey, ParamStart, ParamTo, ParamNoFirst, ParamTrue : string;
-       DatToHTML: boolean = false): string;
-type
-       PIndex = ^TIndex;
-       TIndex = record
-               FIndexFrom      : integer;
-               FIndexTo                : integer;
-               FNo                              : string;
+procedure THTMLCreate.separateNumber(var st: String; var et: String; const Text:String; const Separator: String);
+var
+       p : Integer;
+begin
+       p := Pos(Separator,Text);
+       if (p > 0 ) then begin
+               st := Copy(Text, 1, p - 1);
+               et := Copy(Text, p + Length(Separator), Length(Text));
+       end else begin
+               st := Text;
+               et := Text;
        end;
+end;
+procedure THTMLCreate.ConvRes( PRes : PResRec; PResLink : PResLinkRec; DatToHTML: boolean = false);
 const
        GT      = '&gt;';
-       SN      = '0123456789-';
-       ZN      = '\82O\82P\82Q\82R\82S\82T\82U\82V\82W\82X\81|';
+       SN      = '0123456789';
+       //\8c\9f\8dõ\91Î\8fÛ\82Ì\95\8e\9a\97ñ\8cS
+       TOKEN : array[0..5] of string = (GT+GT, GT, '\81\84\81\84', '\81\84', '<a ', '<A ');
 var
        i : integer;
-       s,r : string;
-       b : TMbcsByteType;
+       s : string;
        sw: boolean;
-       sp: integer;
+       cm: boolean;
        No: string;
-       sx: string;
-       List: TList;
        oc      : string;
-       st, et: string;
-       chk : boolean;
-       al : boolean;
-       procedure Add(IndexFrom, IndexTo: integer; const No: string);
-       var
-               FIndex : PIndex;
-       begin
-               New(FIndex);
-               FIndex.FIndexFrom       := IndexFrom;
-               FIndex.FIndexTo         := IndexTo;
-               FIndex.FNo                               := No;
-               List.Add(FIndex);
-       end;
-       function ChooseString(const Text, Separator: string; Index: integer): string;
-       var
-               S : string;
-               i, p : integer;
+       pos, pmin : integer;
+       j : integer;
+       ch : string;
+       db : boolean;
+       len : integer;
+       rink : string;
+
+       procedure getNumberString;
        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));
+               while (j <= len) do begin
+                       if (ByteType(s, j) = mbSingleByte) then begin
+                               //1byte\95\8e\9a
+                               ch := s[j];
+                               Inc(j);
+                               db := false;
+                       end else begin
+                               //2byte\95\8e\9a
+                               ch := ZenToHan(Copy(s, j, 2));
+                               Inc(j, 2);
+                               db := true;
+                       end;
+
+                       if System.Pos(ch, SN) > 0 then begin
+                               No := No + ch;
+                       end else if (ch = '-') then begin
+                               if sw then break;
+                               if No = '' then break;
+                               No := No + ch;
+                               sw := true;
+                       end else begin
+                               break;
+                       end;
                end;
-               p :=    AnsiPos(Separator, S);
-               if      (p > 0) then    Result  :=      Copy(S, 1, p - 1) else Result :=        S;
        end;
+
 begin
-       { v1.0 b2 - 03 }
-       s        :=     Body;
-       r        :=     Body;
-       i        :=     1;
-       sw      :=      False;
-       No      :=      '';
-       List:=  TList.Create;
-       oc      :=      '';
-       sp      :=      0;
-       chk :=  False;
-       al      :=      False;
-       while true      do      begin
-               b :=    ByteType(s, i);
-               case    b of
-                       mbSingleByte    : begin
-                               if      (not sw) and (Copy(s,i,8) = GT + GT) then       begin
-                                       if      (AnsiPos('<A HREF', AnsiUpperCase(oc)) = 0) then        begin
-                                               sw      :=      True;
-                                               sp      :=      i;
-                                               i :=    i + 7;
-                                               oc:='';
-                                               chk :=  True;
-                                       end;
-                               end else
-                               if      (not sw) and (Copy(s,i,8) = GT + GT) then       begin
-                                       if      (AnsiPos('<A HREF', AnsiUpperCase(oc)) = 1) then        begin
-                                               i :=    i + 7;
-                                               oc:='';
-                                               chk :=  True;
-                                       end;
-                               end else
-                               if      (not sw) and (Copy(s,i,4) = GT) then    begin
-                                       if      (AnsiPos('<A HREF', AnsiUpperCase(oc)) = 0) then        begin
-                                               sw      :=      True;
-                                               sp      :=      i;
-                                               i :=    i + 3;
-                                               oc:='';
-                                               chk :=  True;
-                                       end;
-                               end else
-                               if      ((not sw) and (Copy(s,i,1) = ',')) or
-                                               ((not sw) and (Copy(s,i,1) = '=')) then begin
-                                       if      ((not Chk) and (AnsiLowerCase(oc) = '</a>')) or
-                                                       ((Chk) and      (oc = '')) or
-                                                       ((not Chk) and (al)) then
-                                       begin
-                                               sw      :=      True;
-                                               sp      :=      i;
-                                               //i :=  i + 1;
-                                               oc:='';
-                                       end;
-                               end else
-                               if      (sw) then begin
-                                       sx      :=      Copy(s,i,1);
-                                       if      (AnsiPos(sx, SN) > 0)   then    begin
-                                               No      :=      No      + sx;
-                                       end else begin
-                                               if      (No <> '') and (No <> '-')       then   begin
-                                                       Add(sp, i, No);
-                                                       al := True;
-                                               end;
-                                               sw      :=      False;
-                                               //
-                                               i := i - 1;
-                                               //
-                                               No      := '';
-                                               oc:='';
-                                               //chk :=        False;
+       //s \82É\96{\95\82ð\91S\95\94\93ü\82ê\82é
+       s        :=     PRes.FBody;
+       //\8c\8b\89Ê\82ð\83N\83\8a\83A
+       PRes.FBody       :=     '';
+
+       //
+       while Length(s) > 2 do begin
+               pmin := Length(s) + 1;
+               i       := Length(token);
+               for j := 0 to 5 do begin
+                       pos := AnsiPos(TOKEN[j], s);
+                       if pos <> 0 then begin
+                               if pos < pmin then begin
+                                       //\82Ç\82ê\82Å\83q\83b\83g\82µ\82½\82©\95Û\91
+                                       i := j;
+                                       //\8dÅ\8f¬\92l\82ð\8dX\90V
+                                       pmin := pos;
+                               end;
+                       end;
+               end;
+
+               //\83q\83b\83g\82µ\82½\95\8e\9a\97ñ\82Ì\88ê\82Â\8eè\91O\82Ü\82Å\8c\8b\89Ê\82É\83R\83s\81[
+               PRes.FBody := PRes.FBody + Copy(s, 1, pmin - 1);
+               Delete(s, 1, pmin - 1);
+
+               if i = 6 then begin
+                       //\83q\83b\83g\82È\82µ
+               end else if (i = 4) or (i = 5) then begin
+                       //'<a ' or '<A' \82Å\83q\83b\83g '</a>' or '</A>' \82Ü\82Å\83R\83s\81[
+                       pmin := AnsiPos('</a>' , s);
+                       pos := AnsiPos('</A>' , s);
+                       if (pmin <> 0) and (pos <> 0) then begin
+                               if (pmin > pos) then begin
+                                       pmin := pos;
+                               end;
+                       end else if (pos <> 0) then begin
+                               pmin := pos;
+                       end;
+                       rink := Copy(s, 1, pmin + 3);
+                       PRes.FBody := PRes.FBody + rink;
+                       Delete(s, 1, pmin + 3);
+
+                       pmin := Length(rink);
+                       i       := Length(TOKEN);
+                       for j := 0 to 3 do begin
+                               pos := AnsiPos(TOKEN[j], rink);
+                               if pos <> 0 then begin
+                                       if pos < pmin then begin
+                                               //\82Ç\82ê\82Å\83q\83b\83g\82µ\82½\82©\95Û\91
+                                               i := j;
+                                               //\8dÅ\8f¬\92l\82ð\8dX\90V
+                                               pmin := pos;
                                        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      :=      '';
+                       // \83\8c\83X\83A\83\93\83J\81[\82ª\8aÜ\82Ü\82ê\82Ä\82¢\82½\82ç,\82ª\91±\82­\8cÀ\82è\83A\83\93\83J\81[\82Æ\82µ\82Ä\88µ\82¤
+                       if i <= 3 then begin
+                               No := '';
+                               j := 1;
+                               len := Length(s);
+                               cm := checkComma(s, j, No);
+                               len := Length(s);
+                               while cm do begin
+                                       oc := '';
+                                       No := '';
+                                       sw := false;
+                                       db := false;
+                                       getNumberString;
+                                       //\8fI\92[\82Ü\82Å\8ds\82Á\82Ä\82Ì\8fI\97¹\82©\83`\83F\83b\83N
+                                       if j <= len then begin
+                                               if db then j := j - 2
+                                               else j := j - 1;
                                        end;
-                               end else begin
-                                       oc      :=      '';
-                                       chk :=  False;
+                                       addResAnchor(PRes, PResLink, DatToHTML, s, j, No);
+                                       j := 1;
+                                       len := Length(s);
+                                       cm := checkComma(s, j, No);
                                end;
-                               al      :=      False;
                        end;
-               end;
-               inc(i);
-               if      (i > Length(Body))      then    begin
-                       if      (sw)    then    begin
-                               if      (No <> '')      then    Add(sp, i, No);
+               end else begin
+                       //\89½\82©\82µ\82ç\8c©\82Â\82©\82Á\82½\83p\83^\81[\83\93
+                       j := Length(TOKEN[i]) + 1;
+                       oc := '';
+                       No := '';
+                       sw := false;
+                       db := false;
+                       len := Length(s);
+                       getNumberString;
+                       //\8fI\92[\82Ü\82Å\8ds\82Á\82Ä\82Ì\8fI\97¹\82©\83`\83F\83b\83N
+                       if j <= len then begin
+                               if db then j := j - 2
+                               else j := j - 1;
                        end;
-                       Break;
+                       addResAnchor(PRes, PResLink, DatToHTML, s, j, No);
                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;
+       if Length(s) > 0 then begin
+               PRes.FBody := PRes.FBody + s;
+       end;
+end;
+function THTMLCreate.checkComma(
+       const s : String;
+       var j : Integer;
+       var No  : String
+) : boolean;
+var
+       bType : TMbcsByteType;
+begin
+       Result := false;
+       if (Length(s) > 0) then begin
+               bType := ByteType(s, j);
+               if ((bType = mbSingleByte) and (s[j] = ',') or
+                       ((bType = mbLeadByte) and (ZenToHan(Copy(s, j ,2)) = ','))) then begin
+                       Result := true;
+                       if (bType = mbSingleByte) then
+                               Inc(j)
+                       else
+                               Inc(j, 2);
+                       No := '';
                end;
-               if not DatToHTML then
-               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>' +
-                                       Copy(r,PIndex(List[i]).FIndexTo,Length(r))
-               else
-               r :=    Copy(r,0, PIndex(List[i]).FIndexFrom - 1) +
-                                       Format('<a href="#%s">', [st]) +
-                                       Copy(r,PIndex(List[i]).FIndexFrom, PIndex(List[i]).FIndexTo - PIndex(List[i]).FIndexFrom) + '</A>' +
-                                       Copy(r,PIndex(List[i]).FIndexTo,Length(r));
-
-               Dispose(PIndex(List[i]));
        end;
-       List.Free;
-       Result  :=      r;
 end;
+function THTMLCreate.addResAnchor(
+       PAddRes: PResRec; PResLink : PResLinkRec; dat : boolean;
+       var s : String; j : Integer; const No: String) : string;
+const
+       FORMAT_LINK = '<a href="../test/read.cgi?bbs=%s&key=%s&st=%s&to=%s&nofirst=true" target="_blank">';
+var
+       st,et : string;
+begin
 
-function THTMLCreate.ConvRes(
-       const Body, Bbs, Key, ParamBBS, ParamKey,
-       ParamStart, ParamTo, ParamNoFirst,
-       ParamTrue, FullURL : string
-): string;
-type
-       PIndex = ^TIndex;
-       TIndex = record
-               FIndexFrom      : integer;
-               FIndexTo                : integer;
-               FNo                              : string;
+       //\89½\82à\90\94\8e\9a\82ª\8c©\82Â\82©\82ç\82È\82¢\82Æ\82«
+       if No = '' then begin
+               PAddRes.FBody := PAddRes.FBody + Copy(s, 1, j - 1);
+       end else begin
+               separateNumber(st, et, No, '-');
+
+               if not dat then begin
+                       PAddRes.FBody := PAddRes.FBody +
+                               Format(FORMAT_LINK, [PResLink.FBbs, PResLink.FKey, st, et]);
+               end else begin
+                       PAddRes.FBody := PAddRes.FBody + Format('<a href="#%s">', [st]);
+               end;
+               PAddRes.FBody := PAddRes.FBody + Copy(s, 1, j - 1) + '</a>';
        end;
+       Delete(s, 1, j - 1);
+end;
+
+(*************************************************************************
+ *
+ * from HotZonu
+ *************************************************************************)
+function THTMLCreate.ConvRes(const Body, Bbs, Key,
+       ParamBBS, ParamKey, ParamStart, ParamTo, ParamNoFirst, ParamTrue : string;
+       DatToHTML: boolean = false): string;
 const
        GT      = '&gt;';
-       SN      = '0123456789-';
-       ZN      = '\82O\82P\82Q\82R\82S\82T\82U\82V\82W\82X\81|';
+       SN      = '0123456789';
+       FORMAT_LINK = '<a href="../test/read.cgi?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s" target="_blank">';
+       //\8c\9f\8dõ\91Î\8fÛ\82Ì\95\8e\9a\97ñ\8cS
+       TOKEN : array[0..5] of string = (GT+GT, GT, '\81\84\81\84', '\81\84', '<a ', '<A ');
 var
        i : integer;
-       s,r : string;
-       b : TMbcsByteType;
+       s : string;
        sw: boolean;
-       sp: integer;
+       cm: boolean;
        No: string;
-       sx: string;
-       List: TList;
        oc      : string;
-       st, et: string;
-       chk : boolean;
-       al : boolean;
-       procedure Add(IndexFrom, IndexTo: integer; const No: string);
+       pos, pmin : integer;
+       j : integer;
+       ch : string;
+       db : boolean;
+       len : integer;
+       rink : string;
+       function addResAnchor(const Left :string) : string;
        var
-               FIndex : PIndex;
+               st,et : string;
        begin
-               New(FIndex);
-               FIndex.FIndexFrom       := IndexFrom;
-               FIndex.FIndexTo         := IndexTo;
-               FIndex.FNo                               := No;
-               List.Add(FIndex);
+               //\8fI\92[\82Ü\82Å\8ds\82Á\82Ä\82Ì\8fI\97¹\82©\83`\83F\83b\83N
+               if j <= len then begin
+                       if db then j := j - 2
+                       else j := j - 1;
+               end;
+               //\89½\82à\90\94\8e\9a\82ª\8c©\82Â\82©\82ç\82È\82¢\82Æ\82«
+               if No = '' then begin
+                       Result := Left + Copy(s, 1, j - 1);
+               end else begin
+                       separateNumber(st, et, No, '-');
+
+                       if not DatToHTML then begin
+                               Result := Left + Format(FORMAT_LINK,
+                                                       [ParamBBS, Bbs, ParamKey, Key, ParamStart, st, ParamTo, et, ParamNoFirst, ParamTrue]);
+                       end else begin
+                               Result := Left + Format('<a href="#%s">', [st]);
+                       end;
+                       Result := Result + Copy(s, 1, j - 1) + '</a>';
+               end;
+               Delete(s, 1, j - 1);
        end;
-       function ChooseString(const Text, Separator: string; Index: integer): string;
-       var
-               S : string;
-               i, p : integer;
+
+       procedure getNumberString;
        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));
+               while (j <= len) do begin
+                       if (ByteType(s, j) = mbSingleByte) then begin
+                               //1byte\95\8e\9a
+                               ch := s[j];
+                               Inc(j);
+                               db := false;
+                       end else begin
+                               //2byte\95\8e\9a
+                               ch := ZenToHan(Copy(s, j, 2));
+                               Inc(j, 2);
+                               db := true;
+                       end;
+
+                       if System.Pos(ch, SN) > 0 then begin
+                               No := No + ch;
+                       end else if (ch = '-') then begin
+                               if sw then break;
+                               if No = '' then break;
+                               No := No + ch;
+                               sw := true;
+                       end else begin
+                               break;
+                       end;
+               end;
+       end;
+
+       function checkComma : boolean;
+       begin
+               j := 1;
+               len := Length(s);
+               if ((len > 0) and (s[j] = ',')) or ((len > 1) and (ZenToHan(Copy(s, j ,2)) = ','))  then begin
+                       Result := true;
+                       if (ByteType(s, j) = mbSingleByte) then
+                               Inc(j)
+                       else
+                               Inc(j, 2);
+                       No := '';
+               end else begin
+                       Result := false;
                end;
-               p :=    AnsiPos(Separator, S);
-               if      (p > 0) then    Result  :=      Copy(S, 1, p - 1) else Result :=        S;
        end;
 begin
-       { v1.0 b2 - 03 }
+       //s \82É\96{\95\82ð\91S\95\94\93ü\82ê\82é
        s        :=     Body;
-       r        :=     Body;
-       i        :=     1;
-       sw      :=      False;
-       No      :=      '';
-       List:=  TList.Create;
-       oc      :=      '';
-       sp      :=      0;
-       chk :=  False;
-       al      :=      False;
-       while true      do      begin
-               b :=    ByteType(s, i);
-               case    b of
-                       mbSingleByte    : begin
-                               if      (not sw) and (Copy(s,i,8) = GT + GT) then       begin
-                                       if      (AnsiPos('<A HREF', AnsiUpperCase(oc)) = 0) then        begin
-                                               sw      :=      True;
-                                               sp      :=      i;
-                                               i :=    i + 7;
-                                               oc:='';
-                                               chk :=  True;
-                                       end;
-                               end else
-                               if      (not sw) and (Copy(s,i,8) = GT + GT) then       begin
-                                       if      (AnsiPos('<A HREF', AnsiUpperCase(oc)) = 1) then        begin
-                                               i :=    i + 7;
-                                               oc:='';
-                                               chk :=  True;
-                                       end;
-                               end else
-                               if      (not sw) and (Copy(s,i,4) = GT) then    begin
-                                       if      (AnsiPos('<A HREF', AnsiUpperCase(oc)) = 0) then        begin
-                                               sw      :=      True;
-                                               sp      :=      i;
-                                               i :=    i + 3;
-                                               oc:='';
-                                               chk :=  True;
-                                       end;
-                               end else
-                               if      ((not sw) and (Copy(s,i,1) = ',')) or
-                                               ((not sw) and (Copy(s,i,1) = '=')) then begin
-                                       if      ((not Chk) and (AnsiLowerCase(oc) = '</a>')) or
-                                                       ((Chk) and      (oc = '')) or
-                                                       ((not Chk) and (al)) then
-                                       begin
-                                               sw      :=      True;
-                                               sp      :=      i;
-                                               //i :=  i + 1;
-                                               oc:='';
-                                       end;
-                               end else
-                               if      (sw) then begin
-                                       sx      :=      Copy(s,i,1);
-                                       if      (AnsiPos(sx, SN) > 0)   then    begin
-                                               No      :=      No      + sx;
-                                       end else begin
-                                               if      (No <> '') and (No <> '-')       then   begin
-                                                       Add(sp, i, No);
-                                                       al := True;
-                                               end;
-                                               sw      :=      False;
-                                               //
-                                               i := i - 1;
-                                               //
-                                               No      := '';
-                                               oc:='';
-                                               //chk :=        False;
-                                       end;
-                               end else begin
-                                       if      Copy(s,i,1) = '<' then  oc      :=      '';
-                                       oc      :=      oc + Copy(s,i,1);
-                                       chk :=  False;
-                                       al      :=      False;
+       //\8c\8b\89Ê\82ð\83N\83\8a\83A
+       Result   :=     '';
+
+       //
+       while Length(s) > 2 do begin
+               pmin := Length(s) + 1;
+               i       := Length(token);
+               for j := 0 to 5 do begin
+                       pos := AnsiPos(TOKEN[j], s);
+                       if pos <> 0 then begin
+                               if pos < pmin then begin
+                                       //\82Ç\82ê\82Å\83q\83b\83g\82µ\82½\82©\95Û\91
+                                       i := j;
+                                       //\8dÅ\8f¬\92l\82ð\8dX\90V
+                                       pmin := pos;
                                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;
+
+               //\83q\83b\83g\82µ\82½\95\8e\9a\97ñ\82Ì\88ê\82Â\8eè\91O\82Ü\82Å\8c\8b\89Ê\82É\83R\83s\81[
+               Result := Result + Copy(s, 1, pmin - 1);
+               Delete(s, 1, pmin - 1);
+
+               if i = 6 then begin
+                       //\83q\83b\83g\82È\82µ
+               end else if (i = 4) or (i = 5) then begin
+                       //'<a ' or '<A' \82Å\83q\83b\83g '</a>' or '</A>' \82Ü\82Å\83R\83s\81[
+                       pmin := AnsiPos('</a>' , s);
+                       pos := AnsiPos('</A>' , s);
+                       if (pmin <> 0) and (pos <> 0) then begin
+                               if (pmin > pos) then begin
+                                       pmin := pos;
+                               end;
+                       end else if (pos <> 0) then begin
+                               pmin := pos;
+                       end;
+                       rink := Copy(s, 1, pmin + 3);
+                       Result := Result + rink;
+                       Delete(s, 1, pmin + 3);
+
+                       pmin := Length(rink);
+                       i       := Length(TOKEN);
+                       for j := 0 to 3 do begin
+                               pos := AnsiPos(TOKEN[j], rink);
+                               if pos <> 0 then begin
+                                       if pos < pmin then begin
+                                               //\82Ç\82ê\82Å\83q\83b\83g\82µ\82½\82©\95Û\91
+                                               i := j;
+                                               //\8dÅ\8f¬\92l\82ð\8dX\90V
+                                               pmin := pos;
                                        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);
+                       // \83\8c\83X\83A\83\93\83J\81[\82ª\8aÜ\82Ü\82ê\82Ä\82¢\82½\82ç,\82ª\91±\82­\8cÀ\82è\83A\83\93\83J\81[\82Æ\82µ\82Ä\88µ\82¤
+                       if i <= 3 then begin
+                               No := '';
+                               cm := checkComma;
+                               len := Length(s);
+                               while cm do begin
+                                       oc := '';
+                                       No := '';
+                                       sw := false;
+                                       db := false;
+                                       getNumberString;
+                                       Result := addResAnchor(Result);
+                                       cm := checkComma;
+                               end;
                        end;
-                       Break;
-               end;
-       end;
-       for i :=        List.Count - 1  downto  0 do    begin
-               //plName := Copy(PluginName, LastDelimiter('\',PluginName) + 1, Length(PluginName) - LastDelimiter('/',PluginName) -1 );
-               if      (AnsiPos('-', PIndex(List[i]).FNo) > 0) then    begin
-                       st      :=      ChooseString(PIndex(List[i]).FNo, '-', 0);
-                       et      :=      ChooseString(PIndex(List[i]).FNo, '-', 1);
                end else begin
-                       st      :=      PIndex(List[i]).FNo;
-                       et      :=      PIndex(List[i]).FNo;
+                       //\89½\82©\82µ\82ç\8c©\82Â\82©\82Á\82½\83p\83^\81[\83\93
+                       j := Length(TOKEN[i]) + 1;
+                       oc := '';
+                       No := '';
+                       sw := false;
+                       db := false;
+                       len := Length(s);
+                       getNumberString;
+                       Result := addResAnchor(Result);
                end;
-               r :=    Copy(r,0, PIndex(List[i]).FIndexFrom - 1) +
-                                       Format('<a href="%s&%s=%s&%s=%s&%s=%s" target="_blank">',
-                                                               [FullURL, ParamStart, st, ParamTo, et, ParamNoFirst, ParamTrue]) +
-                                       Copy(r,PIndex(List[i]).FIndexFrom, PIndex(List[i]).FIndexTo - PIndex(List[i]).FIndexFrom) + '</A>' +
-                                       Copy(r,PIndex(List[i]).FIndexTo,Length(r));
-               Dispose(PIndex(List[i]));
        end;
-       List.Free;
-       Result  :=      r;
+       Result := Result + s;
 end;
 
-function THTMLCreate.ConvertResAnchor(res: string): string;
+procedure THTMLCreate.ConvertResAnchor(PRes: PResRec);
 const
        _HEAD : string = '<a href="../';
        _TAIL : string = ' target="_blank">';
@@ -693,15 +754,17 @@ const
 var
        i, j, k: Integer;
        tmp: string;
+       res: string;
 begin
-       Result := '';
+       res := PRes.FBody;
+       PRes.FBody := '';
        i := AnsiPos(_HEAD, res);
        while i <> 0 do begin
-               Result := Result + Copy(res, 1, i -1);
+               PRes.FBody := PRes.FBody + Copy(res, 1, i -1);
                Delete(res, 1, i - 1);
                j := AnsiPos(_TAIL, res);
                if j = 0 then begin
-                       Result := Result + res;
+                       PRes.FBody := PRes.FBody + res;
                        Exit;
                end;
                tmp := Copy(res, 1, j - 1);
@@ -709,11 +772,11 @@ begin
                if (AnsiPos(_ST, tmp) <> 0) and (AnsiPos(_TO, tmp) <> 0) then begin
                        Delete(tmp, 1, AnsiPos(_ST, tmp) + 3);
                        Delete(tmp, AnsiPos(_TO, tmp), Length(tmp));
-                       Result := Result + '<a href="#' + tmp + '">';
+                       PRes.FBody := PRes.FBody + '<a href="#' + tmp + '">';
                end else if (AnsiPos(_STA, tmp) <> 0) and (AnsiPos(_END, tmp) <> 0) then begin
                        Delete(tmp, 1, AnsiPos(_STA, tmp) + 6);
                        Delete(tmp, AnsiPos(_END, tmp), Length(tmp));
-                       Result := Result + '<a href="#' + tmp + '">';
+                       PRes.FBody := PRes.FBody + '<a href="#' + tmp + '">';
                end else begin
                        k := LastDelimiter('/', tmp);
                        Delete(tmp, 1, k);
@@ -722,237 +785,206 @@ begin
                        else
                                Delete(tmp, AnsiPos('"', tmp), Length(tmp));
 
-                       Result := Result + '<a href="#' + tmp + '">';
+                       PRes.FBody := PRes.FBody + '<a href="#' + tmp + '">';
                end;
                i := AnsiPos(_HEAD, res);
        end;
-       Result := Result + res;
+       PRes.FBody := PRes.FBody + res;
 
 end;
 
 //Plugin\82ð\97\98\97p\82·\82éBoard\82Ì\83X\83\8c\83b\83h\82ÌHTML\82ð\8dì\90¬\82µ\82Ädoc\82É\8f\91\82«\8d\9e\82Þ
-procedure THTMLCreate.CreateUsePluginHTML(doc: Variant; ThreadItem: TThreadItem; var sTitle: string);
+procedure THTMLCreate.CreateUsePluginHTML(html:TBufferedWebBrowser; ThreadItem: TThreadItem; var sTitle: string);
 var
        i: integer;
        NewReceiveNo: Integer;
        boardPlugIn : TBoardPlugIn;
        UserOptionalStyle: string;
 begin
-       if ThreadItem <> nil then begin
-               if ThreadItem.ParentBoard.IsBoardPlugInAvailable then begin
-                       //===== \83v\83\89\83O\83C\83\93\82É\82æ\82é\95\\8e¦
-                       boardPlugIn             := ThreadItem.ParentBoard.BoardPlugIn;
-                       NewReceiveNo    := ThreadItem.NewReceive;
-                       // \83t\83H\83\93\83g\82â\83T\83C\83Y\82Ì\90Ý\92è
-                       UserOptionalStyle := GikoSys.SetUserOptionalStyle;
-                       try
-                               doc.open;
-                               // \83w\83b\83_
-                               doc.Write( boardPlugIn.GetHeader( DWORD( threadItem ),
-                                       '<style type="text/css">body {' + UserOptionalStyle + '}</style>' ) + #13#10 );
-                               doc.Write('<p id="idSearch"></p>' + #13#10 );
-
-                               for i := 0 to threadItem.Count - 1 do begin
-                                       // 1 \82Í\95K\82¸\95\\8e¦
-                                       if i <> 0 then begin
-                                               // \95\\8e¦\94Í\88Í\82ð\8cÀ\92è
-                                               case GikoSys.ResRange of
-                                               Ord( grrKoko ):
-                                                       if ThreadItem.Kokomade > (i + 1) then
-                                                               Continue;
-                                               Ord( grrNew ):
-                                                       if NewReceiveNo > (i + 1) then
-                                                               Continue;
-                                               10..65535:
-                                                       if (threadItem.Count - i) > GikoSys.ResRange then
-                                                               Continue;
-                                               end;
-                                       end;
-
-                                       // \90V\92\85\83}\81[\83N
-                                       if (NewReceiveNo = (i + 1)) or ((NewReceiveNo = 0) and (i = 0)) then begin
-                                               try
-                                                       if GikoSys.Setting.UseSkin then begin
-                                                               if FileExists( GikoSys.GetSkinNewmarkFileName ) then
-                                                                       doc.Write( LoadFromSkin( GikoSys.GetSkinNewmarkFileName, ThreadItem, ThreadItem.Size ) + #13#10 )
-                                                               else
-                                                                       doc.Write( '<a name="new"></a>' + #13#10 );
-                                                       end else if GikoSys.Setting.UseCSS then begin
-                                                               doc.Write('<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>' + #13#10);
-                                                       end else begin
-                                                               doc.Write('</dl>');
-                                                               doc.Write('<a name="new"></a>');
-                                                               doc.Write('<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>');
-                                                               doc.Write('<dl> + #13#10');
-                                                       end;
-                                               except
-                                                       doc.Write( '<a name="new"></a>' + #13#10);
-                                               end;
-                                       end;
-
-                                       // \83\8c\83X
-                                       doc.Write( boardPlugIn.GetRes( DWORD( threadItem ), i + 1 ) + #13#10 );
+       //===== \83v\83\89\83O\83C\83\93\82É\82æ\82é\95\\8e¦
+       boardPlugIn             := ThreadItem.ParentBoard.BoardPlugIn;
+       NewReceiveNo    := ThreadItem.NewReceive;
+       // \83t\83H\83\93\83g\82â\83T\83C\83Y\82Ì\90Ý\92è
+       UserOptionalStyle := GikoSys.SetUserOptionalStyle;
+       html.add(boardPlugIn.GetHeader( DWORD( threadItem ),
+               '<style type="text/css">body {' + UserOptionalStyle + '}</style>' ));
+       html.Add('<p id="idSearch"></p>');
+       html.Flush;
+       
+       for i := 0 to threadItem.Count - 1 do begin
+               // 1 \82Í\95K\82¸\95\\8e¦
+               if i <> 0 then begin
+                       // \95\\8e¦\94Í\88Í\82ð\8cÀ\92è
+                       case GikoSys.ResRange of
+                       Ord( grrKoko ):
+                               if ThreadItem.Kokomade > (i + 1) then
+                                       Continue;
+                       Ord( grrNew ):
+                               if NewReceiveNo > (i + 1) then
+                                       Continue;
+                       10..65535:
+                               if (threadItem.Count - i) > GikoSys.ResRange then
+                                       Continue;
+                       end;
+               end;
 
-                                       if ThreadItem.Kokomade = (i + 1) then begin
-                                               // \82±\82±\82Ü\82Å\93Ç\82ñ\82¾
-                                               try
-                                                       if GikoSys.Setting.UseSkin then begin
-                                                               if FileExists( GikoSys.GetSkinBookmarkFileName ) then
-                                                                       doc.Write( LoadFromSkin( GikoSys.GetSkinBookmarkFileName, ThreadItem, ThreadItem.Size ) + #13#10 )
-                                                               else
-                                                                       doc.Write( '<a name="koko"></a>' + #13#10 );
-                                                       end else if GikoSys.Setting.UseCSS then begin
-                                                               doc.Write('<a name="koko"></a><div class="koko">\83R\83R\82Ü\82Å\93Ç\82ñ\82¾</div>' + #13#10 );
-                                                       end else begin
-                                                               doc.Write('</dl>');
-                                                               doc.Write('<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>');
-                                                               doc.Write('<dl>' + #13#10 );
-                                                       end;
-                                               except
-                                                       doc.Write( '<a name="koko"></a>' + #13#10 );
-                                               end;
-                                       end;
+               // \90V\92\85\83}\81[\83N
+               if (NewReceiveNo = (i + 1)) or ((NewReceiveNo = 0) and (i = 0)) then begin
+                       try
+                               if GikoSys.Setting.UseSkin then begin
+                                       if FileExists( GikoSys.GetSkinNewmarkFileName ) then
+                                               html.Add( LoadFromSkin( GikoSys.GetSkinNewmarkFileName, ThreadItem, ThreadItem.Size ))
+                                       else
+                                               html.Add( '<a name="new"></a>');
+                               end else if GikoSys.Setting.UseCSS then begin
+                                       html.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
+                                       html.Add('</dl>');
+                                       html.Add('<a name="new"></a>');
+                                       html.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>');
+                                       html.Add('<dl>');
                                end;
+                       except
+                               html.Add( '<a name="new"></a>');
+                       end;
+               end;
 
+               // \83\8c\83X
+               html.Add( boardPlugIn.GetRes( DWORD( threadItem ), i + 1 ));
 
-                               // \83X\83L\83\93(\83t\83b\83^)
-                               doc.Write( boardPlugIn.GetFooter( DWORD( threadItem ), '<a name="bottom"></a>' ) + #13#10 );
-                       finally
-                               doc.Close;
+               if ThreadItem.Kokomade = (i + 1) then begin
+                       // \82±\82±\82Ü\82Å\93Ç\82ñ\82¾
+                       try
+                               if GikoSys.Setting.UseSkin then begin
+                                       if FileExists( GikoSys.GetSkinBookmarkFileName ) then
+                                               html.Add( LoadFromSkin( GikoSys.GetSkinBookmarkFileName, ThreadItem, ThreadItem.Size ))
+                                       else
+                                               html.Add( '<a name="koko"></a>');
+                               end else if GikoSys.Setting.UseCSS then begin
+                                       html.Add('<a name="koko"></a><div class="koko">\83R\83R\82Ü\82Å\93Ç\82ñ\82¾</div>');
+                               end else begin
+                                       html.Add('</dl>');
+                                       html.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>');
+                                       html.Add('<dl>');
+                               end;
+                       except
+                               html.Add('<a name="koko"></a>');
                        end;
-
                end;
        end;
+
+
+       // \83X\83L\83\93(\83t\83b\83^)
+       html.Add( boardPlugIn.GetFooter( DWORD( threadItem ), '<a name="bottom"></a>' ));
 end;
 
 
-procedure THTMLCreate.CreateUseSKINHTML(doc: Variant; ThreadItem: TThreadItem; ReadList: TStringList);
+procedure THTMLCreate.CreateUseSKINHTML(html:TBufferedWebBrowser; ThreadItem: TThreadItem; ReadList: TStringList);
+const
+       KOKO_TAG = '<a name="koko"></a>';
+       NEW_TAG = '<a name="new"></a>';
 var
        i: integer;
-       No: string;
-       CSSFileName: string;
        NewReceiveNo: Integer;
        Res: TResRec;
        UserOptionalStyle: string;
        SkinHeader: string;
        SkinNewRes: string;
        SkinRes: string;
-       strTmp : string;
-       function ReplaceRes( skin: string ): string;
-       begin
-               Result := SkinedRes( skin, Res, No );
-       end;
+       ThreadName : string;
+       ResLink :TResLinkRec;
 begin
-       if ThreadItem <> nil then begin
-               // \83X\83L\83\93\8eg\97p
-               if GikoSys.Setting.UseSkin then begin
-                       NewReceiveNo := ThreadItem.NewReceive;
-                       // \83t\83H\83\93\83g\82â\83T\83C\83Y\82Ì\90Ý\92è
-                       UserOptionalStyle := GikoSys.SetUserOptionalStyle;
-                       CSSFileName := GikoSys.GetStyleSheetDir + GikoSys.Setting.CSSFileName;
-                       doc.open;
-                       try
-                               doc.charset := 'Shift_JIS';
-
-                               // \83X\83L\83\93\82Ì\90Ý\92è
-                               try
-                                       SkinHeader := LoadFromSkin( GikoSys.GetSkinHeaderFileName, ThreadItem, ThreadItem.Size);
-                                       if Length( UserOptionalStyle ) > 0 then
-                                               SkinHeader := CustomStringReplace( SkinHeader, '</head>',
-                                                       '<style type="text/css">body {' + UserOptionalStyle + '}</style></head>');
-                                       doc.Write( SkinHeader + #13#10);
-                               except
-                               end;
-
-                               try
-                                       SkinNewRes := LoadFromSkin( GikoSys.GetSkinNewResFileName, ThreadItem, ThreadItem.Size);
-                               except
-                               end;
-
-                               try
-                                       SkinRes := LoadFromSkin( GikoSys.GetSkinResFileName, ThreadItem, ThreadItem.Size );
-                               except
-                               end;
-
-                               doc.Write('<p id="idSearch"></p>' + #13#10);
-                               doc.Write('<a name="top"></a>' + #13#10);
-
-                               for i := 0 to ReadList.Count - 1 do begin
-                                       // 1 \82Í\95K\82¸\95\\8e¦
-                                       if i <> 0 then begin
-                                               // \95\\8e¦\94Í\88Í\82ð\8cÀ\92è
-                                               case GikoSys.ResRange of
-                                               Ord( grrKoko ):
-                                                       if ThreadItem.Kokomade > (i + 1) then
-                                                               Continue;
-                                               Ord( grrNew ):
-                                                       if NewReceiveNo > (i + 1) then
-                                                               Continue;
-                                               10..65535:
-                                                       if (threadItem.Count - i) > GikoSys.ResRange then
-                                                               Continue;
-                                               end;
-                                       end;
-
-                                       // \90V\92\85\83}\81[\83N
-                                       if (NewReceiveNo = i + 1) or ((NewReceiveNo = 0) and (i = 0)) then begin
-                                               try
-                                                       if FileExists( GikoSys.GetSkinNewmarkFileName ) then
-                                                               doc.Write( LoadFromSkin( GikoSys.GetSkinNewmarkFileName, ThreadItem, ThreadItem.Size )  + #13#10)
-                                                       else
-                                                               doc.Write( '<a name="new"></a>' + #13#10 );
-                                               except
-                                                       doc.Write( '<a name="new"></a>' + #13#10 );
-                                               end;
-                                       end;
+       NewReceiveNo := ThreadItem.NewReceive;
+       // \83t\83H\83\93\83g\82â\83T\83C\83Y\82Ì\90Ý\92è
+       UserOptionalStyle := GikoSys.SetUserOptionalStyle;
+       ThreadName := ChangeFileExt(ThreadItem.FileName, '');
+       ResLink.FBbs := ThreadItem.ParentBoard.BBSID;
+       ResLink.FKey := ThreadName;
+       // \83X\83L\83\93\82Ì\90Ý\92è
+       try
+               SkinHeader := LoadFromSkin( GikoSys.GetSkinHeaderFileName, ThreadItem, ThreadItem.Size);
+               if Length( UserOptionalStyle ) > 0 then
+                       SkinHeader := CustomStringReplace( SkinHeader, '</head>',
+                               '<style type="text/css">body {' + UserOptionalStyle + '}</style></head>');
+               html.Add( SkinHeader );
+       except
+       end;
 
-                                       if (Trim(ReadList[i]) <> '') then begin
-                                               No := IntToStr(i + 1);
+       SkinNewRes := LoadFromSkin( GikoSys.GetSkinNewResFileName, ThreadItem, ThreadItem.Size);
+       SkinRes := LoadFromSkin( GikoSys.GetSkinResFileName, ThreadItem, ThreadItem.Size );
+
+       html.Add('<p id="idSearch"></p>'#13#10'<a name="top"></a>');
+       html.Flush;
+
+       for i := 0 to ReadList.Count - 1 do begin
+               // 1 \82Í\95K\82¸\95\\8e¦
+               if i <> 0 then begin
+                       // \95\\8e¦\94Í\88Í\82ð\8cÀ\92è
+                       case GikoSys.ResRange of
+                       Ord( grrKoko ):
+                               if ThreadItem.Kokomade > (i + 1) then
+                                       Continue;
+                       Ord( grrNew ):
+                               if NewReceiveNo > (i + 1) then
+                                       Continue;
+                       10..65535:
+                               if (threadItem.Count - i) > GikoSys.ResRange then
+                                       Continue;
+                       end;
+               end;
 
-                                               Res := DivideStrLine(ReadList[i]);
-                                               Res.FBody := ConvRes(AddAnchorTag(Res.FBody), ThreadItem.ParentBoard.BBSID, ChangeFileExt(ThreadItem.FileName, ''), 'bbs', 'key', 'st', 'to', 'nofirst', 'true');
-                                               Res.FDateTime := AddBeProfileLink(Res.FDateTime, i + 1);
+               // \90V\92\85\83}\81[\83N
+               if (NewReceiveNo = i + 1) or ((NewReceiveNo = 0) and (i = 0)) then begin
+                       if FileExists( GikoSys.GetSkinNewmarkFileName ) then
+                               html.Add( LoadFromSkin( GikoSys.GetSkinNewmarkFileName, ThreadItem, ThreadItem.Size ))
+                       else
+                               html.Add( NEW_TAG );
+               end;
 
-                                               try
-                                                       if NewReceiveNo <= (i + 1) then
-                                                               // \90V\92\85\83\8c\83X
-                                                               strTmp := ReplaceRes( SkinNewRes )
-                                                       else
-                                                               // \92Ê\8fí\82Ì\83\8c\83X
-                                                               strTmp := ReplaceRes( SkinRes );
-
-                                                       doc.Write( strTmp + #13#10 );
-                                               except
-                                               end;
-                                       end;
+               if (Trim(ReadList[i]) <> '') then begin
+                       DivideStrLine(ReadList[i], @Res);
+                       AddAnchorTag(@Res);
+                       ConvRes(@Res, @ResLink);
+                       Res.FDateTime := AddBeProfileLink(Res.FDateTime, i + 1);
 
-                                       if ThreadItem.Kokomade = (i + 1) then begin
-                                               // \82±\82±\82Ü\82Å\93Ç\82ñ\82¾
-                                               try
-                                                       if FileExists( GikoSys.GetSkinBookmarkFileName ) then
-                                                               doc.Write( LoadFromSkin( GikoSys.GetSkinBookmarkFileName, ThreadItem, ThreadItem.Size ) + #13#10 )
-                                                       else
-                                                               doc.Write( '<a name="koko"></a>' + #13#10 );
-                                               except
-                                                       doc.Write( '<a name="koko"></a>' + #13#10 );
-                                               end;
-                                       end;
-                               end;
+                       if NewReceiveNo <= (i + 1) then
+                               // \90V\92\85\83\8c\83X
+                               html.Add(SkinedRes(SkinNewRes, @Res, IntToStr(i + 1)))
+                       else
+                               // \92Ê\8fí\82Ì\83\8c\83X
+                               html.Add(SkinedRes(SkinRes, @Res, IntToStr(i + 1)));
+               end;
 
-                               doc.Write('<a name="bottom"></a>' + #13#10);
-                               // \83X\83L\83\93(\83t\83b\83^)
-                               try
-                                       doc.Write( LoadFromSkin( GikoSys.GetSkinFooterFileName, ThreadItem, ThreadItem.Size ) + #13#10 );
-                               except
-                               end;
-                       finally
-                               doc.close;
-                       end;
+               if ThreadItem.Kokomade = (i + 1) then begin
+                       // \82±\82±\82Ü\82Å\93Ç\82ñ\82¾
+                       if FileExists( GikoSys.GetSkinBookmarkFileName ) then
+                               html.Add( LoadFromSkin( GikoSys.GetSkinBookmarkFileName, ThreadItem, ThreadItem.Size ))
+                       else
+                               html.Add( KOKO_TAG );
                end;
        end;
+
+       html.Add('<a name="bottom"></a>');
+       // \83X\83L\83\93(\83t\83b\83^)
+       html.Add( LoadFromSkin( GikoSys.GetSkinFooterFileName, ThreadItem, ThreadItem.Size ) );
 end;
 
-procedure THTMLCreate.CreateUseCSSHTML(doc: Variant; ThreadItem: TThreadItem; ReadList: TStringList; sTitle: string );
+procedure THTMLCreate.CreateUseCSSHTML(html:TBufferedWebBrowser; ThreadItem: TThreadItem; ReadList: TStringList; sTitle: string );
+const
+       FORMAT_NOMAIL  = '<a name="%s"></a><div class="header"><span class="no"><a href="menu:%s">%s</a></span>'
+                                       + '<span class="name_label"> \96¼\91O\81F </span> <span class="name"><b>%s</b></span>'
+                                       + '<span class="date_label"> \93\8a\8de\93ú\81F</span> <span class="date">%s</span></div>'
+                                       + '<div class="mes">%s</div>';
+
+       FORMAT_SHOWMAIL = '<a name="%s"></a><div class="header"><span class="no"><a href="menu:%s">%s</a></span>'
+                                       + '<span class="name_label"> \96¼\91O\81F </span><a class="name_mail" href="mailto:%s">'
+                                       + '<b>%s</b></a><span class="mail"> [%s]</span><span class="date_label"> \93\8a\8de\93ú\81F</span>'
+                                       + '<span class="date"> %s</span></div><div class="mes">%s</div>';
+
+       FORMAT_NOSHOW = '<a name="%s"></a><div class="header"><span class="no"><a href="menu:%s">%s</a></span>'
+                                       + '<span class="name_label"> \96¼\91O\81F </span><a class="name_mail" href="mailto:%s">'
+                                       + '<b>%s</b></a><span class="date_label"> \93\8a\8de\93ú\81F</span><span class="date"> %s</span></div>'
+                                       + '<div class="mes">%s</div>';
 var
        i: integer;
        No: string;
@@ -960,175 +992,150 @@ var
        NewReceiveNo: Integer;
        Res: TResRec;
        UserOptionalStyle: string;
+       ThreadName :String;
+       ResLink :TResLinkRec;
 begin
-       if ThreadItem <> nil then begin
-               doc.open;
-               try
-                       doc.charset := 'Shift_JIS';
-                       NewReceiveNo := ThreadItem.NewReceive;
-                       // \83t\83H\83\93\83g\82â\83T\83C\83Y\82Ì\90Ý\92è
-                       UserOptionalStyle := GikoSys.SetUserOptionalStyle;
-                       CSSFileName := GikoSys.GetStyleSheetDir + GikoSys.Setting.CSSFileName;
-                       if GikoSys.Setting.UseCSS and FileExists(CSSFileName) then begin
-                               //CSS\8eg\97p
-                               doc.Write('<html><head>' + #13#10);
-                               doc.Write('<meta http-equiv="Content-type" content="text/html; charset=Shift_JIS">' + #13#10);
-                               doc.Write('<title>' + sTitle + '</title>' + #13#10);
-                               doc.Write('<link rel="stylesheet" href="'+CSSFileName+'" type="text/css">' + #13#10);
-                               if Length( UserOptionalStyle ) > 0 then
-                                       doc.Write('<style type="text/css">body {' + UserOptionalStyle + '}</style>' + #13#10);
-                               doc.Write('</head>' + #13#10);
-                               doc.Write('<body>' + #13#10);
-                               doc.Write('<a name="top"></a>' + #13#10);
-                               doc.Write('<p id="idSearch"></p>' + #13#10);
-                               doc.Write('<div class="title">' + sTitle + '</div>' + #13#10);
-                               for i := 0 to ReadList.Count - 1 do begin
-                                       // 1 \82Í\95K\82¸\95\\8e¦
-                                       if i <> 0 then begin
-                                               // \95\\8e¦\94Í\88Í\82ð\8cÀ\92è
-                                               case GikoSys.ResRange of
-                                               Ord( grrKoko ):
-                                                       if ThreadItem.Kokomade > (i + 1) then
-                                                               Continue;
-                                               Ord( grrNew ):
-                                                       if NewReceiveNo > (i + 1) then
-                                                               Continue;
-                                               10..65535:
-                                                       if (threadItem.Count - i) > GikoSys.ResRange then
-                                                               Continue;
-                                               end;
-                                       end;
-
-                                       if (NewReceiveNo = (i + 1)) or ((NewReceiveNo = 0) and (i = 0)) then begin
-                                               doc.Write('<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>' + #13#10);
-                                       end;
-
-                                       if (Trim(ReadList[i]) <> '') then begin
-                                               No := IntToStr(i + 1);
-                                               Res := DivideStrLine(ReadList[i]);
-                                               Res.FBody := ConvRes(AddAnchorTag(Res.FBody), ThreadItem.ParentBoard.BBSID, ChangeFileExt(ThreadItem.FileName, ''), 'bbs', 'key', 'st', 'to', 'nofirst', 'true');
-                                               Res.FDateTime := AddBeProfileLink(Res.FDateTime, i + 1);
-                                               if Res.FMailTo = '' then
-                                                       doc.Write('<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> '
-                                                                               + '<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>' + #13#10)
-                                               else if GikoSys.Setting.ShowMail then
-                                                       doc.Write('<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>' + #13#10)
-                                               else
-                                                       doc.Write('<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>' + #13#10);
-                                       end;
+       NewReceiveNo := ThreadItem.NewReceive;
+       ThreadName := ChangeFileExt(ThreadItem.FileName, '');
+       ResLink.FBbs := ThreadItem.ParentBoard.BBSID;
+       ResLink.FKey := ThreadName;
+       // \83t\83H\83\93\83g\82â\83T\83C\83Y\82Ì\90Ý\92è
+       UserOptionalStyle := GikoSys.SetUserOptionalStyle;
+       CSSFileName := GikoSys.GetStyleSheetDir + GikoSys.Setting.CSSFileName;
+       if GikoSys.Setting.UseCSS and FileExists(CSSFileName) then begin
+               //CSS\8eg\97p
+               html.Add('<html><head>');
+               html.Add('<meta http-equiv="Content-type" content="text/html; charset=Shift_JIS">');
+               html.Add('<title>' + sTitle + '</title>');
+               html.Add('<link rel="stylesheet" href="'+CSSFileName+'" type="text/css">');
+               if Length( UserOptionalStyle ) > 0 then
+                       html.Add('<style type="text/css">body {' + UserOptionalStyle + '}</style>');
+               html.Add('</head>'#13#10'<body>');
+               html.Add('<a name="top"></a>'#13#10'<p id="idSearch"></p>');
+               html.Add('<div class="title">' + sTitle + '</div>');
+               html.Flush;
+               for i := 0 to ReadList.Count - 1 do begin
+                       // 1 \82Í\95K\82¸\95\\8e¦
+                       if i <> 0 then begin
+                               // \95\\8e¦\94Í\88Í\82ð\8cÀ\92è
+                               case GikoSys.ResRange of
+                               Ord( grrKoko ):
+                                       if ThreadItem.Kokomade > (i + 1) then
+                                               Continue;
+                               Ord( grrNew ):
+                                       if NewReceiveNo > (i + 1) then
+                                               Continue;
+                               10..65535:
+                                       if (threadItem.Count - i) > GikoSys.ResRange then
+                                               Continue;
+                               end;
+                       end;
 
-                                       if ThreadItem.Kokomade = (i + 1) then begin
-                                               doc.Write('<a name="koko"></a><div class="koko">\83R\83R\82Ü\82Å\93Ç\82ñ\82¾</div>' + #13#10);
-                                       end;
+                       if (NewReceiveNo = (i + 1)) or ((NewReceiveNo = 0) and (i = 0)) then begin
+                               html.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;
 
-                               end;
+                       if (Trim(ReadList[i]) <> '') then begin
+                               No := IntToStr(i + 1);
+                               DivideStrLine(ReadList[i], @Res);
+                               AddAnchorTag(@Res);
+                               ConvRes(@Res, @ResLink);
+                               Res.FDateTime := AddBeProfileLink(Res.FDateTime, i + 1);
+                               if Res.FMailTo = '' then
+                                       html.Add(Format(FORMAT_NOMAIL, [No, No, No, Res.FName, Res.FDateTime, Res.FBody]))
+                               else if GikoSys.Setting.ShowMail then
+                                       html.Add(Format(FORMAT_SHOWMAIL, [No, No, No, Res.FMailTo, Res.FName, Res.FMailTo, Res.FDateTime, Res.FBody]))
+                               else
+                                       html.Add(Format(FORMAT_NOSHOW, [No, No, No, Res.FMailTo, Res.FName, Res.FDateTime, Res.FBody]));
+                       end;
 
-                               doc.Write('<a name="bottom"></a>' + #13#10);
-                               doc.Write('<a name="last"></a>' + #13#10);
-                               doc.Write('</body></html>' + #13#10);
+                       if ThreadItem.Kokomade = (i + 1) then begin
+                               html.Add('<a name="koko"></a><div class="koko">\83R\83R\82Ü\82Å\93Ç\82ñ\82¾</div>');
                        end;
-               finally
-                       doc.Close;
+
                end;
+
+               html.Add('<a name="bottom"></a>');
+               html.Add('<a name="last"></a>');
+               html.Add('</body></html>');
        end;
 end;
 
-procedure THTMLCreate.CreateDefaultHTML (doc: Variant; ThreadItem: TThreadItem; ReadList: TStringList; sTitle: string );
+procedure THTMLCreate.CreateDefaultHTML (html:TBufferedWebBrowser; ThreadItem: TThreadItem; ReadList: TStringList; sTitle: string );
 var
        i: integer;
        No: string;
        NewReceiveNo: Integer;
        Res: TResRec;
+       ThreadName: String;
+       ResLink : TResLinkRec;
 begin
-       if ThreadItem <> nil then begin
-               doc.open;
-               try
-                       doc.charset := 'Shift_JIS';
-                       NewReceiveNo := ThreadItem.NewReceive;
-                       doc.Write('<html><head>' + #13#10);
-                       doc.Write('<meta http-equiv="Content-type" content="text/html; charset=Shift_JIS">' + #13#10);
-                       doc.Write('<title>' + sTitle + '</title></head>' + #13#10);
-                       doc.Write('<body TEXT="#000000" BGCOLOR="#EFEFEF" link="#0000FF" alink="#FF0000" vlink="#660099">' + #13#10);
-                       doc.Write('<a name="top"></a>' + #13#10);
-                       doc.Write('<font size=+1 color="#FF0000">' + sTitle + '</font>' + #13#10);
-                       doc.Write('<dl>' + #13#10);
-                       doc.Write('<p id="idSearch"></p>' + #13#10);
-                       for i := 0 to ReadList.Count - 1 do begin
-                               // 1 \82Í\95K\82¸\95\\8e¦
-                               if i <> 0 then begin
-                                       // \95\\8e¦\94Í\88Í\82ð\8cÀ\92è
-                                       case GikoSys.ResRange of
-                                       Ord( grrKoko ):
-                                               if ThreadItem.Kokomade > (i + 1) then
-                                                       Continue;
-                                       Ord( grrNew ):
-                                               if NewReceiveNo > (i + 1) then
-                                                       Continue;
-                                       10..65535:
-                                               if (threadItem.Count - i) > GikoSys.ResRange then
-                                                       Continue;
-                                       end;
-                               end;
+       NewReceiveNo := ThreadItem.NewReceive;
+       ThreadName := ChangeFileExt(ThreadItem.FileName, '');
+       ResLink.FBbs := ThreadItem.ParentBoard.BBSID;
+       ResLink.FKey := ThreadName;
+       html.Add('<html><head>');
+       html.Add('<meta http-equiv="Content-type" content="text/html; charset=Shift_JIS">');
+       html.Add('<title>' + sTitle + '</title></head>');
+       html.Add('<body TEXT="#000000" BGCOLOR="#EFEFEF" link="#0000FF" alink="#FF0000" vlink="#660099">');
+       html.Add('<a name="top"></a>');
+       html.Add('<font size=+1 color="#FF0000">' + sTitle + '</font>');
+       html.Add('<dl>');
+       html.Add('<p id="idSearch"></p>');
+       html.Flush;
+       for i := 0 to ReadList.Count - 1 do begin
+               // 1 \82Í\95K\82¸\95\\8e¦
+               if i <> 0 then begin
+                       // \95\\8e¦\94Í\88Í\82ð\8cÀ\92è
+                       case GikoSys.ResRange of
+                       Ord( grrKoko ):
+                               if ThreadItem.Kokomade > (i + 1) then
+                                       Continue;
+                       Ord( grrNew ):
+                               if NewReceiveNo > (i + 1) then
+                                       Continue;
+                       10..65535:
+                               if (threadItem.Count - i) > GikoSys.ResRange then
+                                       Continue;
+                       end;
+               end;
 
-                               if (NewReceiveNo = (i + 1)) or ((NewReceiveNo = 0) and (i = 0)) then begin
-                                       doc.Write('</dl>' + #13#10);
-                                       doc.Write('<a name="new"></a>' + #13#10);
-                                       doc.Write('<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>' + #13#10);
-                                       doc.Write('<dl>' + #13#10);
-                               end;
+               if (NewReceiveNo = (i + 1)) or ((NewReceiveNo = 0) and (i = 0)) then begin
+                       html.Add('</dl>');
+                       html.Add('<a name="new"></a>');
+                       html.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>');
+                       html.Add('<dl>');
+               end;
 
-                               if (Trim(ReadList[i]) <> '') then begin
-                                       No := IntToStr(i + 1);
-                                       Res := DivideStrLine(ReadList[i]);
-                                       Res.FBody := ConvRes(AddAnchorTag(Res.FBody), ThreadItem.ParentBoard.BBSID, ChangeFileExt(ThreadItem.FileName, ''), 'bbs', 'key', 'st', 'to', 'nofirst', 'true');
-                                       Res.FDateTime := AddBeProfileLink(Res.FDateTime, i + 1);
-                                       if Res.FMailTo = '' then
-                                               doc.Write('<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 <span class="date">' + Res.FDateTime+ '</span><br><dd>' + Res.Fbody + ' <br><br><br>' + #13#10)
-                                       else if GikoSys.Setting.ShowMail then
-                                               doc.Write('<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 <span class="date">' + Res.FDateTime+ '</span><br><dd>' + Res.Fbody + ' <br><br><br>' + #13#10)
-                                       else
-                                               doc.Write('<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 <span class="date">' + Res.FDateTime+ '</span><br><dd>' + Res.Fbody + ' <br><br><br>' + #13#10);
-                               end;
-                               if ThreadItem.Kokomade = (i + 1) then begin
-                                       doc.Write('</dl>' + #13#10);
-                                       doc.Write('<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>' + #13#10);
-                                       doc.Write('<dl>' + #13#10);
-                               end;
-                       end;
-                       doc.Write('</dl>' + #13#10);
-                       doc.Write('<a name="bottom"></a>' + #13#10);
-                       doc.Write('</body></html>' + #13#10);
-               finally
-                       doc.Close;
+               if (Trim(ReadList[i]) <> '') then begin
+                       No := IntToStr(i + 1);
+                       DivideStrLine(ReadList[i], @Res);
+                       AddAnchorTag(@Res);
+                       ConvRes(@Res, @ResLink);
+                       Res.FDateTime := AddBeProfileLink(Res.FDateTime, i + 1);
+                       if Res.FMailTo = '' then
+                               html.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 <span class="date">' + Res.FDateTime+ '</span><br><dd>' + Res.Fbody + ' <br><br><br>'#13#10)
+                       else if GikoSys.Setting.ShowMail then
+                               html.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 <span class="date">' + Res.FDateTime+ '</span><br><dd>' + Res.Fbody + ' <br><br><br>'#13#10)
+                       else
+                               html.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 <span class="date">' + Res.FDateTime+ '</span><br><dd>' + Res.Fbody + ' <br><br><br>'#13#10);
+               end;
+               if ThreadItem.Kokomade = (i + 1) then begin
+                       html.Add('</dl>');
+                       html.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>');
+                       html.Add('<dl>');
                end;
        end;
+       html.Add('</dl>'#13#10'<a name="bottom"></a>'#13#10'</body></html>');
 end;
 
-procedure THTMLCreate.CreateHTML2(doc: Variant; ThreadItem: TThreadItem; var sTitle: string);
+procedure THTMLCreate.CreateHTML2(Browser: TWebBrowser; ThreadItem: TThreadItem; var sTitle: string);
 var
        ReadList: TStringList;
        CSSFileName: string;
        FileName: string;
        Res: TResRec;
+       body : TBufferedWebBrowser;
 {$IFDEF DEBUG}
        st, rt: Cardinal;
 {$ENDIF}
@@ -1138,43 +1145,51 @@ begin
        st := GetTickCount;
 {$ENDIF}
        if ThreadItem <> nil then begin
-               if ThreadItem.ParentBoard.IsBoardPlugInAvailable then begin
-                       CreateUsePluginHTML(doc, ThreadItem, sTitle);
-               end else begin
-                       ShortDayNames[1] := '\93ú';               ShortDayNames[2] := '\8c\8e';
-                       ShortDayNames[3] := '\89Î';               ShortDayNames[4] := '\90\85';
-                       ShortDayNames[5] := '\96Ø';               ShortDayNames[6] := '\8bà';
-                       ShortDayNames[7] := '\93y';
-
-                       ReadList := TStringList.Create;
-                       try
-                               if ThreadItem.IsLogFile then begin
-                                       FileName := ThreadItem.GetThreadFileName;
-                                       ReadList.LoadFromFile(FileName);
-                                       GikoSys.FAbon.IndividualAbon(ReadList, ChangeFileExt(FileName,'.NG'));
-                                       GikoSys.FAbon.Execute(ReadList);                //       \82 \82Ú\81`\82ñ\82µ\82Ä
-                                       GikoSys.FSelectResFilter.Execute(ReadList); //\83\8c\83X\82Ì\83t\83B\83\8b\83^\83\8a\83\93\83O\82ð\82·\82é
-                                       if ThreadItem.Title = '' then begin
-                                               Res := DivideStrLine(ReadList[0]);
-                                               sTitle := Res.FTitle;
-                                       end else
-                                               sTitle := ThreadItem.Title
-                               end else begin
-                                       sTitle := CustomStringReplace(ThreadItem.Title, '\81\97\81M', ',');
-                               end;
-
-                               // \83t\83H\83\93\83g\82â\83T\83C\83Y\82Ì\90Ý\92è
-                               CSSFileName := GikoSys.GetStyleSheetDir + GikoSys.Setting.CSSFileName;
-                               if GikoSys.Setting.UseSkin then begin
-                                       CreateUseSKINHTML(doc, ThreadItem, ReadList);
-                               end else if GikoSys.Setting.UseCSS and FileExists(CSSFileName) then begin
-                                       CreateUseCSSHTML(doc, ThreadItem, ReadList, sTitle);
-                               end else begin
-                                       CreateDefaultHTML(doc, ThreadItem, ReadList, sTitle);
+               body := TBufferedWebBrowser.Create(Browser, 100);
+               try
+                       body.Open;
+                       if ThreadItem.ParentBoard.IsBoardPlugInAvailable then begin
+                               CreateUsePluginHTML(body, ThreadItem, sTitle);
+                       end else begin
+                               ShortDayNames[1] := '\93ú';               ShortDayNames[2] := '\8c\8e';
+                               ShortDayNames[3] := '\89Î';               ShortDayNames[4] := '\90\85';
+                               ShortDayNames[5] := '\96Ø';               ShortDayNames[6] := '\8bà';
+                               ShortDayNames[7] := '\93y';
+
+                               ReadList := TStringList.Create;
+                               try
+                                       if ThreadItem.IsLogFile then begin
+                                               ReadList.BeginUpdate;
+                                               FileName := ThreadItem.GetThreadFileName;
+                                               ReadList.LoadFromFile(FileName);
+                                               ReadList.EndUpdate;
+                                               GikoSys.FAbon.IndividualAbon(ReadList, ChangeFileExt(FileName,'.NG'));
+                                               GikoSys.FAbon.Execute(ReadList);                //       \82 \82Ú\81`\82ñ\82µ\82Ä
+                                               GikoSys.FSelectResFilter.Execute(ReadList); //\83\8c\83X\82Ì\83t\83B\83\8b\83^\83\8a\83\93\83O\82ð\82·\82é
+                                               if ThreadItem.Title = '' then begin
+                                                       DivideStrLine(ReadList[0], @Res);
+                                                       sTitle := Res.FTitle;
+                                               end else
+                                                       sTitle := ThreadItem.Title
+                                       end else begin
+                                               sTitle := CustomStringReplace(ThreadItem.Title, '\81\97\81M', ',');
+                                       end;
+                                       // \83t\83H\83\93\83g\82â\83T\83C\83Y\82Ì\90Ý\92è
+                                       CSSFileName := GikoSys.GetStyleSheetDir + GikoSys.Setting.CSSFileName;
+                                       if GikoSys.Setting.UseSkin then begin
+                                               CreateUseSKINHTML(body, ThreadItem, ReadList);
+                                       end else if GikoSys.Setting.UseCSS and FileExists(CSSFileName) then begin
+                                               CreateUseCSSHTML(body, ThreadItem, ReadList, sTitle);
+                                       end else begin
+                                               CreateDefaultHTML(body, ThreadItem, ReadList, sTitle);
+                                       end;
+                               finally
+                                       ReadList.Free;
                                end;
-                       finally
-                               ReadList.Free;
                        end;
+               finally
+                       body.Close;
+                       body.Free;
                end;
        end;
 {$IFDEF DEBUG}
@@ -1201,18 +1216,23 @@ var
        SkinHeader: string;
        SkinRes: string;
        tmp, tmp1: string;
+       ThreadName: String;
+       ResLink : TResLinkRec;
        function LoadSkin( fileName: string ): string;
        begin
                Result := LoadFromSkin( fileName, ThreadItem, ThreadItem.Size );
        end;
        function ReplaceRes( skin: string ): string;
        begin
-               Result := SkinedRes( skin, Res, No );
+               Result := SkinedRes( skin, @Res, No );
        end;
 
 begin
        if ThreadItem <> nil then begin
                CSSFileName := GikoSys.GetStyleSheetDir + GikoSys.Setting.CSSFileName;
+               ThreadName := ChangeFileExt(ThreadItem.FileName, '');
+               ResLink.FBbs := ThreadItem.ParentBoard.BBSID;
+               ResLink.FKey := ThreadName;
                html.Clear;
                html.BeginUpdate;
                //if ThreadItem.IsBoardPlugInAvailable then begin
@@ -1244,7 +1264,9 @@ begin
                                for i := 0 to threadItem.Count - 1 do begin
 
                                        // \83\8c\83X
-                                       html.Append( ConvertResAnchor(boardPlugIn.GetRes( DWORD( threadItem ), i + 1 )) );
+                                       Res.FBody := boardPlugIn.GetRes( DWORD( threadItem ), i + 1 );
+                                       ConvertResAnchor(@Res);
+                                       html.Append( Res.FBody );
 
                                end;
                                // \83X\83L\83\93(\83t\83b\83^)
@@ -1267,7 +1289,7 @@ begin
                                        GikoSys.FAbon.IndividualAbon(ReadList, ChangeFileExt(FileName,'.NG'));
                                        GikoSys.FAbon.Execute(ReadList);                //       \82 \82Ú\81`\82ñ\82µ\82Ä
                                        GikoSys.FSelectResFilter.Execute(ReadList); //\83\8c\83X\82Ì\83t\83B\83\8b\83^\83\8a\83\93\83O\82ð\82·\82é
-                                       Res := DivideStrLine(ReadList[0]);
+                                       DivideStrLine(ReadList[0], @Res);
                                        //Res.FTitle := CustomStringReplace(Res.FTitle, '\81\97\81M', ',');
                                        sTitle := Res.FTitle;
                                end else begin
@@ -1302,9 +1324,10 @@ begin
                                                        if (Trim(ReadList[i]) <> '') then begin
                                                                No := IntToStr(i + 1);
 
-                                                               Res := DivideStrLine(ReadList[i]);
-                                                               Res.FBody := AddAnchorTag(Res.FBody);
-                                                               Res.FBody := ConvertResAnchor(ConvRes(Res.FBody, ThreadItem.ParentBoard.BBSID, ChangeFileExt(ThreadItem.FileName, ''), 'bbs', 'key', 'st', 'to', 'nofirst', 'true', true));
+                                                               DivideStrLine(ReadList[i], @Res);
+                                                               AddAnchorTag(@Res);
+                                                               ConvRes(@Res, @ResLink, true);
+                                                               ConvertResAnchor(@Res);
 
                                                                try
                                                                        html.Append( ReplaceRes( SkinRes ) );
@@ -1340,9 +1363,10 @@ begin
                                                for i := 0 to ReadList.Count - 1 do begin
                                                        if (Trim(ReadList[i]) <> '') then begin
                                                                No := IntToStr(i + 1);
-                                                               Res := DivideStrLine(ReadList[i]);
-                                                               Res.FBody := AddAnchorTag(Res.FBody);
-                                                               Res.FBody := ConvertResAnchor(ConvRes(Res.FBody, ThreadItem.ParentBoard.BBSID, ChangeFileExt(ThreadItem.FileName, ''), 'bbs', 'key', 'st', 'to', 'nofirst', 'true', true));
+                                                               DivideStrLine(ReadList[i], @Res);
+                                                               AddAnchorTag(@Res);
+                                                               ConvRes(@Res, @ResLink, true);
+                                                               ConvertResAnchor(@Res);
                                                                if Res.FMailTo = '' then
                                                                        html.Append('<a name="' + No + '"></a>'
                                                                                                        + '<div class="header"><span class="no"><a href="menu:' + No + '">' + No + '</a></span> '
@@ -1386,9 +1410,10 @@ begin
                                                for i := 0 to ReadList.Count - 1 do begin
                                                        if (Trim(ReadList[i]) <> '') then begin
                                                                No := IntToStr(i + 1);
-                                                               Res := DivideStrLine(ReadList[i]);
-                                                               Res.FBody := AddAnchorTag(Res.FBody);
-                                                               Res.FBody := ConvertResAnchor(ConvRes(Res.FBody, ThreadItem.ParentBoard.BBSID, ChangeFileExt(ThreadItem.FileName, ''), 'bbs', 'key', 'st', 'to', 'nofirst', 'true', true));
+                                                               DivideStrLine(ReadList[i], @Res);
+                                                               AddAnchorTag(@Res);
+                                                               ConvRes(@Res, @ResLink, true);
+                                                               ConvertResAnchor(@Res);
                                                                if Res.FMailTo = '' then
                                                                        html.Append('<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
@@ -1411,6 +1436,335 @@ begin
        end;
 end;
 
+procedure THTMLCreate.SetResPopupText(Hint : TResPopup; threadItem: TThreadItem; StNum, ToNum: Integer; Title, First: Boolean);
+var
+       i: Integer;
+       tmp: string;
+       FileName: string;
+       Line: Integer;
+
+       wkInt: Integer;
+
+       Res: TResRec;
+       Header: string;
+       Body: string;
+    boardPlugIn : TBoardPlugIn;
+begin
+       try
+               if StNum > ToNum then begin
+                       wkInt := StNum;
+                       StNum := ToNum;
+                       ToNum := wkInt;
+               end;
+
+               //\8dÅ\91å10\83\8c\83X\82Ü\82Å\95\\8e¦
+               if StNum + MAX_POPUP_RES < ToNum then
+                       ToNum := StNum + MAX_POPUP_RES;
+
+               //\83^\83C\83g\83\8b\95\\8e¦
+               if Title then
+                               if ThreadItem <> nil then
+                                       Hint.Title := ThreadItem.Title;
+
+        if ThreadItem <> nil then begin
+            //if ThreadItem.IsBoardPlugInAvailable then begin
+            if ThreadItem.ParentBoard.IsBoardPlugInAvailable then begin
+                //===== \83v\83\89\83O\83C\83\93\82É\82æ\82é\95\\8e¦
+                //boardPlugIn          := ThreadItem.BoardPlugIn;
+                boardPlugIn            := ThreadItem.ParentBoard.BoardPlugIn;
+
+                // \83t\83H\83\93\83g\82â\83T\83C\83Y\82Ì\90Ý\92è
+                // \95\8e\9a\83R\81[\83h\82Í\83v\83\89\83O\83C\83\93\82É\94C\82¹\82é
+                for i := StNum to ToNum do begin
+                    Line := i;
+                                       //\82±\82±\82Å\82Q\82¿\82á\82ñ\82Ë\82é\82Ìdat\82Ì\8c`\8e®\82Å\82P\8ds\93Ç\82Ý\8d\9e\82ß\82ê\82Î¥¥¥\81B\81«\93Ç\82ß\82é\82æ\82¤\82É\82È\82Á\82½
+                                       tmp := boardPlugIn.GetDat( DWORD( threadItem ), i );
+                    if (tmp <> '') And ( not GikoSys.FAbon.CheckAbonPopupRes(tmp) And( not GikoSys.FAbon.CheckIndividualAbonList(line))) then begin
+                                               DivideStrLine(tmp, @Res);
+                        if (GikoSys.Setting.ShowMail = false) or (Length(res.FMailTo) = 0) then
+                               Header := IntToStr(Line) + ' \96¼\91O\81F ' + Res.FName + ' \93\8a\8de\93ú\81F ' + Res.FDateTime
+                        else
+                               Header := IntToStr(Line) + ' \96¼\91O\81F ' + Res.FName + ' [' + res.FMailTo + '] \93\8a\8de\93ú\81F ' + Res.FDateTime;
+                                               Header := DeleteFontTag(Header);
+                                               Header := CustomStringReplace(Header, '<br>', '',true);
+
+                                               Body := CustomStringReplace(Res.FBody, '<br> ', #10,true);
+                                               Body := CustomStringReplace(Body, '<br>', #10,true);
+                        Body := CustomStringReplace(Body, '</a>', '',true);
+                                               Body := THTMLCreate.DeleteLink(Body);
+                        Body := CustomStringReplace(Body, '&lt;', '<');
+                        Body := CustomStringReplace(Body, '&gt;', '>');
+                        Body := CustomStringReplace(Body, '&quot;', '"');
+                        Body := CustomStringReplace(Body, '&amp;', '&');
+                        Body := CustomStringReplace(Body, '&nbsp;', ' ');
+
+                                               Hint.Add(Header, Body);
+                                       end;
+                               end;
+                       end else begin
+                               for i := StNum to ToNum do begin
+                                       Line := i;
+                                       FileName := ThreadItem.FilePath;
+                                       tmp := GikoSys.ReadThreadFile(FileName, Line);
+                                       if (tmp <> '') And ( not GikoSys.FAbon.CheckAbonPopupRes(tmp) And( not GikoSys.FAbon.CheckIndividualAbonList(line))) then begin
+                                               DivideStrLine(tmp, @Res);
+                                               if (GikoSys.Setting.ShowMail = false) or (Length(res.FMailTo) = 0) then
+                                                       Header := IntToStr(Line) + ' \96¼\91O\81F ' + Res.FName + ' \93\8a\8de\93ú\81F ' + Res.FDateTime
+                                               else
+                                                       Header := IntToStr(Line) + ' \96¼\91O\81F ' + Res.FName + ' [' + res.FMailTo + '] \93\8a\8de\93ú\81F ' + Res.FDateTime;
+
+                                               Body := DeleteFontTag(Res.FBody);
+                                               Body := CustomStringReplace(Body, '<br> ', #10,true);
+                                               Body := CustomStringReplace(Body, '<br>', #10,true);
+                                               Body := CustomStringReplace(Body, '</a>', '',true);
+                                               Body := THTMLCreate.DeleteLink(Body);
+                                               Body := CustomStringReplace(Body, '&lt;', '<');
+                                               Body := CustomStringReplace(Body, '&gt;', '>');
+                                               Body := CustomStringReplace(Body, '&quot;', '"');
+                                               Body := CustomStringReplace(Body, '&amp;', '&');
+                                                Body := CustomStringReplace(Body, '&nbsp;', ' ');
+                                               Hint.Add(Header, Body);
+                                       end;
+                               end;
+                       end;
+               end;
+       finally
+       end;
+end;
+
+//\83\8a\83\93\83N\82Ì\95\8e\9a\97ñ\82©\82ç\83\8c\83X\83|\83b\83v\83A\83b\83v\97p\82ÌURL\82É\95Ï\8a·\82·\82é
+class function THTMLCreate.GetRespopupURL(AText, AThreadURL : string): string;
+var
+       wkInt: Integer;
+begin
+       Result := '';
+       if Pos('about:blank..', AText) = 1 then begin
+               wkInt := LastDelimiter( '/', AThreadURL );
+               if Pos( '?', Copy( AThreadURL, wkInt, MaxInt ) ) = 0 then begin
+                       // Thread.URL \82Í PATH_INFO \93n\82µ
+                       Result := Copy( AThreadURL, 1,  LastDelimiter( '/', AThreadURL ) );
+                       wkInt := LastDelimiter( '/', AText );
+                       if Pos( '?', Copy( AText, wkInt, MaxInt ) ) = 0 then
+                               // Text \82à PATH_INFO \93n\82µ
+                               Result := Result + Copy( AText, LastDelimiter( '/', AText ) + 1, MaxInt )
+                       else
+                               // Text \82Í QUERY_STRING \93n\82µ
+                               Result := Result + Copy( AText, LastDelimiter( '?', AText ) + 1, MaxInt );
+               end else begin
+                       // Thread.URL \82Í QUERY_STRING \93n\82µ
+                       Result := Copy( AThreadURL, 1,  LastDelimiter( '?', AThreadURL ) );
+                       wkInt := LastDelimiter( '/', AText );
+                       if Pos( '?', Copy( AText, wkInt, MaxInt ) ) = 0 then begin
+                               // Text \82Í PATH_INFO \93n\82µ
+                               // URL \82É\94Â\82Æ\83L\81[\82ª\91«\82ç\82È\82¢\82Ì\82Å Text \82©\82ç\92¸\91Õ\82·\82é
+                               wkInt := LastDelimiter( '/', Copy( AText, 1, wkInt - 1 ) );
+                               wkInt := LastDelimiter( '/', Copy( AText, 1, wkInt - 1 ) );
+                               Result := Copy( Result, 1, Length( Result ) - 1 ) + Copy( AText, wkInt, MaxInt );
+                       end else begin
+                               // Text \82à QUERY_STRING \93n\82µ
+                               Result := Result + Copy( AText, LastDelimiter( '?', AText ) + 1, MaxInt )
+                       end;
+               end;
+       end else if Pos('about:blank/bbs/', AText) = 1 then begin
+               //\82µ\82½\82ç\82ÎJBBS\82Ì\8ed\95Ï\82Ì\8bz\8eû
+               AText := CustomStringReplace(AText, 'about:blank/bbs/', 'about:blank../../bbs/');
+               Result := GetRespopupURL(AText, AThreadURL);
+       end else begin
+               Result := AText;
+       end;
+
+end;
+//\8ew\92è\82µ\82½\83p\83X\82É\83X\83L\83\93\82à\82µ\82­\82ÍCSS\82Ì\83t\83@\83C\83\8b\82Ì\83R\83s\81[\82ð\8dì\82é
+class procedure THTMLCreate.SkinorCSSFilesCopy(path: string);
+var
+       tmp, tmpD, tmpF: string;
+       current: string;
+       dirs: TStringList;
+       files: TStringList;
+       i, j: Integer;
+begin
+       if GikoSys.Setting.UseSkin then begin
+               current := ExtractFilePath(GikoSys.GetSkinDir);
+               tmp := GikoSys.Setting.CSSFileName;
+       end else if GikoSys.Setting.UseCSS then begin
+               current := ExtractFilePath(GikoSys.GetStyleSheetDir);
+               tmp := ExtractFilePath(GikoSys.GetStyleSheetDir + GikoSys.Setting.CSSFileName);
+       end;
+       dirs := TStringList.Create;
+       try
+               dirs.Add(tmp);
+               if tmp <> current then begin
+                       GikoSys.GetDirectoryList(current, '*.*', dirs, true);
+                       for i := 0 to dirs.Count - 1 do begin
+                               files := TStringList.Create;
+                               try
+                                       files.BeginUpdate;
+                                       gikoSys.GetFileList(dirs[i], '*.*', files, true);
+                                       files.EndUpdate;
+                                       tmpD := CustomStringReplace(dirs[i], GikoSys.GetConfigDir, path);
+                                       if (AnsiPos(dirs[i], tmp) <> 0) and not (DirectoryExists(tmpD)) then
+                                               ForceDirectories(tmpD);
+
+                                       if(dirs[i] = tmp) and (dirs[i] <> current) then begin
+                                               for j := 0 to files.Count - 1 do begin
+                                                       tmpF := CustomStringReplace(files[j], GikoSys.GetConfigDir, path);
+                                                       if not FileExists(tmpF) then begin
+                                                               CopyFile(PChar(files[j]), PChar(tmpF),True);
+                                                       end;
+                                               end;
+                                       end;
+                               finally
+                                       files.Free;
+                               end;
+                       end;
+               end else begin
+                       tmpD := CustomStringReplace(dirs[0], GikoSys.GetConfigDir, path);
+                       if not DirectoryExists(tmpD) then
+                               ForceDirectories(tmpD);
+                       tmpF := CustomStringReplace(GikoSys.GetStyleSheetDir + GikoSys.Setting.CSSFileName
+                                       , GikoSys.GetConfigDir, path);
+                       if not FileExists(tmpF) then begin
+                               CopyFile(PChar(GikoSys.GetStyleSheetDir + GikoSys.Setting.CSSFileName)
+                                       , PChar(tmpF), True);
+                       end;
+               end;
+       finally
+               dirs.Free;
+       end;
+end;{!
+\brief dat\83t\83@\83C\83\8b\82Ì\88ê\83\89\83C\83\93\82ð\95ª\89ð
+\param Line dat\83t\83@\83C\83\8b\82ð\8d\\90¬\82·\82é 1 \8ds
+\return     \83\8c\83X\8fî\95ñ
+}
+class procedure THTMLCreate.DivideStrLine(Line: string; PRes: PResRec);
+const
+       delimiter = '<>';
+var
+       pds, pde : PChar;
+       pss, pse : PChar;
+       ppos : PChar;
+begin
+       //\8cÅ\92è
+       PRes.FType := glt2chNew;
+
+       pss := PChar(Line);
+       pse := pss + Length(Line);
+       pds := PChar(delimiter);
+       pde := pds + Length(delimiter);
+
+       ppos := AnsiStrPosEx(pss, pse, pds, pde);
+       if (ppos = nil) then begin
+               Line := CustomStringReplace(Line, '<>', '&lt;&gt;');
+               Line := CustomStringReplace(Line, ',', '<>');
+               Line := CustomStringReplace(Line, '\81\97\81M', ',');
+       end;
+       //Trim\82µ\82Ä\82Í\82¢\82¯\82È\82¢\8bC\82ª\82·\82é\81@by\82à\82\82ã
+       PRes.FName := RemoveToken(Line, delimiter);
+       PRes.FMailTo := RemoveToken(Line, delimiter);
+       PRes.FDateTime := RemoveToken(Line, delimiter);
+       PRes.FBody := RemoveToken(Line, delimiter);
+       //\82Q\82¿\82á\82ñ\82Ë\82é\82Æ\82©\82¾\82Æ\81A\96{\95\82Ì\90æ\93ª\82É\82P\82Â\94¼\8ap\8bó\94\92\82ª\93ü\82Á\82Ä\82¢\82é\82Ì\82Å\8dí\8f\9c\82·\82é
+       //\91¼\82Ì\8cf\8e¦\94Â\82Å\81A\83\8c\83X\8e©\91Ì\82Ì\8bó\94\92\82©\82à\82µ\82ê\82È\82¢\82¯\82Ç\82»\82ê\82Í\92ú\82ß\82é
+       PRes.FBody := TrimLeft(PRes.FBody);
+       //\8bó\82¾\82Æ\96â\91è\82ª\8bN\82«\82é\82©\82ç\81A\8bó\94\92\82ð\90Ý\92è\82·\82é
+       if PRes.FBody = '' then
+               PRes.FBody := '&nbsp;';
+
+       PRes.FTitle := RemoveToken(Line, delimiter);
+end;
+
+{!
+\brief HTML \82©\82ç\83A\83\93\83J\81[\83^\83O\82ð\8dí\8f\9c
+\param s \8c³\82É\82È\82é HTML
+\return  \83A\83\93\83J\81[\83^\83O\82ª\8dí\8f\9c\82³\82ê\82½ HTML
+}
+class function THTMLCreate.DeleteLink(const s: string): string;
+var
+       s1: string;
+       s2: string;
+       idx: Integer;
+       i: Integer;
+begin
+       i := 0;
+       Result := '';
+       while True do begin
+               s1 := GikoSys.GetTokenIndex(s, '<a href="', i);
+               s2 := GikoSys.GetTokenIndex(s, '<a href="', i + 1);
+
+               idx := Pos('">', s1);
+               if idx <> 0 then
+                       Delete(s1, 1, idx + 1);
+               idx := Pos('">', s2);
+               if idx <> 0 then
+                       Delete(s2, 1, idx + 1);
+
+               Result := Result + s1 + s2;
+
+               if s2 = '' then
+                       Break;
+
+               inc(i, 2);
+       end;
+end;
+
+constructor TBufferedWebBrowser.Create(Browser: TWebBrowser; BuffSize: Integer);
+begin
+       inherited Create;
+       Self.Sorted := False;
+       if (Browser = nil) then
+               Raise  Exception.Create('Browser is NULL');
+       FBrowser := Browser;
+
+       // \83o\83b\83t\83@\82·\82é\8ds\90\94\82ð
+       if (BuffSize < 0) then begin
+               FBuffSize := 100;
+       end else begin
+               FBuffSize := BuffSize;
+       end;
+       Self.Capacity := FBuffSize + 10;
+end;
+procedure TBufferedWebBrowser.Open;
+begin
+       FBrowserDoc := Idispatch( olevariant(FBrowser.ControlInterface).Document);
+       FBrowserDoc.open;
+       FBrowserDoc.charset := 'Shift_JIS';
+end;
+procedure TBufferedWebBrowser.Close;
+begin
+       Self.Flush;
+       try
+               FBrowserDoc.Close;
+       except
+       end;
+       FBrowser := nil;
+end;
+function TBufferedWebBrowser.Add(const S: string): Integer;
+begin
+       Result := inherited Add(TrimRight(s));
+       if (Self.Count > FBuffSize) then begin
+               FBrowserDoc.Write(Self.Text);
+               Self.Clear;
+       end;
+end;
+procedure TBufferedWebBrowser.Flush ;
+begin
+       if (Self.Count > 0) then begin
+               FBrowserDoc.Write(Self.Text);
+               Self.Clear;
+       end;
+end;
+destructor TBufferedWebBrowser.Destory;
+begin
+       try
+               if (FBrowserDoc <> 0) then begin
+                       FBrowserDoc.close;
+                       FBrowserDoc := 0;
+               end;
+       except
+       end;
+       inherited;
+end;
+
 initialization
         HTMLCreater := THTMLCreate.Create;