OSDN Git Service

・スレタイの特定ワードを非表示にする機能に「©bbspink.com」も追加
[gikonavigoeson/gikonavi.git] / GikoSystem.pas
index 7977ad3..827e109 100644 (file)
@@ -4,7 +4,7 @@ interface
 
 uses
        Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
-       ComCtrls, IniFiles, ShellAPI, ActnList, Math,
+       ComCtrls, {IniFiles,} ShellAPI, ActnList, Math,
 {$IF Defined(DELPRO) }
        SHDocVw,
        MSHTML,
@@ -12,33 +12,33 @@ uses
        SHDocVw_TLB,
        MSHTML_TLB,
 {$IFEND}
-       {HttpApp,} YofUtils, URLMon, IdGlobal, IdURI, {Masks,}
+       {HttpApp,} URLMon, IdGlobal, IdURI, {Masks,}
        Setting, BoardGroup, gzip, Dolib, bmRegExp, AbonUnit,
        ExternalBoardManager, ExternalBoardPlugInMain,
-       Sort, GikoBayesian;
+       GikoBayesian, GikoMessage, Belib;
 
 type
        TVerResourceKey = (
-                 vrComments,         // \83R\83\81\83\93\83g
-                 vrCompanyName,      // \89ï\8eÐ\96¼
-                 vrFileDescription,  // \90à\96¾
-                 vrFileVersion,      // \83t\83@\83C\83\8b\83o\81[\83W\83\87\83\93
-                 vrInternalName,     // \93à\95\94\96¼
-                 vrLegalCopyright,   // \92\98\8dì\8c 
-                 vrLegalTrademarks,  // \8f¤\95W
-                 vrOriginalFilename, // \90³\8e®\83t\83@\83C\83\8b\96¼
-                 vrPrivateBuild,     // \83v\83\89\83C\83x\81[\83g\83r\83\8b\83h\8fî\95ñ
-                 vrProductName,      // \90»\95i\96¼
-                 vrProductVersion,   // \90»\95i\83o\81[\83W\83\87\83\93
-                 vrSpecialBuild);     // \83X\83y\83V\83\83\83\8b\83r\83\8b\83h\8fî\95ñ
-
-       //BBS\83^\83C\83v
+                       vrComments,         //!< \83R\83\81\83\93\83g
+                       vrCompanyName,      //!< \89ï\8eÐ\96¼
+                       vrFileDescription,  //!< \90à\96¾
+                       vrFileVersion,      //!< \83t\83@\83C\83\8b\83o\81[\83W\83\87\83\93
+                       vrInternalName,     //!< \93à\95\94\96¼
+                       vrLegalCopyright,   //!< \92\98\8dì\8c 
+                       vrLegalTrademarks,  //!< \8f¤\95W
+                       vrOriginalFilename, //!< \90³\8e®\83t\83@\83C\83\8b\96¼
+                       vrPrivateBuild,     //!< \83v\83\89\83C\83x\81[\83g\83r\83\8b\83h\8fî\95ñ
+                       vrProductName,      //!< \90»\95i\96¼
+                       vrProductVersion,   //!< \90»\95i\83o\81[\83W\83\87\83\93
+                       vrSpecialBuild);    //!< \83X\83y\83V\83\83\83\8b\83r\83\8b\83h\8fî\95ñ
+
+       //BBS\83^\83C\83v
        TGikoBBSType = (gbt2ch);
-       //\83\8d\83O\83^\83C\83v
+       //\83\8d\83O\83^\83C\83v
        TGikoLogType = (glt2chNew, glt2chOld);
-       //\83\81\83b\83Z\81[\83W\83A\83C\83R\83\93
+       //\83\81\83b\83Z\81[\83W\83A\83C\83R\83\93
        TGikoMessageIcon = (gmiOK, gmiSAD, gmiNG, gmiWhat, gmiNone);
-       //URL\83I\81[\83v\83\93\83u\83\89\83E\83U\83^\83C\83v
+       //URL\83I\81[\83v\83\93\83u\83\89\83E\83U\83^\83C\83v
        TGikoBrowserType = (gbtIE, gbtUserApp, gbtAuto);
 
 
@@ -48,7 +48,7 @@ type
                Pos: Integer;
        end;
 
-       //\83C\83\93\83f\83b\83N\83X\83t\83@\83C\83\8b\83\8c\83R\81[\83h
+       //\83C\83\93\83f\83b\83N\83X\83t\83@\83C\83\8b\83\8c\83R\81[\83h
        TIndexRec = record
                FNo: Integer;
                FFileName: string;
@@ -60,7 +60,7 @@ type
                FLastModified: TDateTime;
                FKokomade: Integer;
                FNewReceive: Integer;
-               FMishiyou: Boolean;     //\96¢\8eg\97p
+               FMishiyou: Boolean;     //!< \96¢\8eg\97p
                FUnRead: Boolean;
                FScrollTop: Integer;
                //Index Ver 1.01
@@ -69,14 +69,17 @@ type
                FAgeSage: TGikoAgeSage;
        end;
 
-       //\83T\83u\83W\83F\83N\83g\83\8c\83R\81[\83h
+       //\83T\83u\83W\83F\83N\83g\83\8c\83R\81[\83h
        TSubjectRec = record
                FFileName: string;
                FTitle: string;
                FCount: Integer;
        end;
 
-       //\83\8c\83X\83\8c\83R\81[\83h
+       //! \83\8c\83X\83\8c\83R\81[\83h\82Ö\82Ì\83|\83C\83\93\83^
+       PResRec = ^TResRec;
+
+       //! \83\8c\83X\83\8c\83R\81[\83h
        TResRec = record
                FTitle: string;
                FMailTo: string;
@@ -86,23 +89,18 @@ type
                FType: TGikoLogType;
        end;
 
-       //URLPath\83\8c\83R\81[\83h
+       //URLPath\83\8c\83R\81[\83h
        TPathRec = record
-               FBBS: string;                           //BBSID
-               FKey: string;                           //ThreadID
-               FSt: Int64;                             //\8aJ\8en\83\8c\83X\94Ô
-               FTo: Int64;                             //\8fI\97¹\83\8c\83X\94Ô
-               FFirst: Boolean;                //>>1\82Ì\95\\8e¦
-               FStBegin: Boolean;      //1\81`\95\\8e¦
-               FToEnd: Boolean;                //\81`\8dÅ\8cã\82Ü\82Å\95\\8e¦
-               FDone: Boolean;                 //\90¬\8c÷
-               FNoParam: Boolean;              //\83\8c\83X\94Ô\83p\83\89\83\81\81[\83^\82È\82µ
-       end;
-
-       //MessageList
-       TGikoMessageListType = (gmLogout, gmLogin, gmForceLogin, gmSureItiran,
-                       gmUnKnown, gmSureSyutoku, gmSureDiff, gmNotMod, gmAbort, gmError,
-                       gmNewRes, gmNewSure, gmResError, gmSureError);
+               FBBS: string;                           //!< BBSID
+               FKey: string;                           //!< ThreadID
+               FSt: Int64;                               //!< \8aJ\8en\83\8c\83X\94Ô
+               FTo: Int64;                               //!< \8fI\97¹\83\8c\83X\94Ô
+               FFirst: Boolean;                //!< >>1\82Ì\95\\8e¦
+               FStBegin: Boolean;      //!< 1\81`\95\\8e¦
+               FToEnd: Boolean;                //!< \81`\8dÅ\8cã\82Ü\82Å\95\\8e¦
+               FDone: Boolean;                 //!< \90¬\8c÷
+               FNoParam: Boolean;  //!< \83\8c\83X\94Ô\83p\83\89\83\81\81[\83^\82È\82µ
+       end;
 
        TGikoSys = class(TObject)
        private
@@ -112,9 +110,13 @@ type
                FAWKStr: TAWKStr;
                FResRange : Longint;
                FBayesian       : TGikoBayesian;        //!< \83x\83C\83W\83A\83\93\83t\83B\83\8b\83^
-               FVersion : String;              //\83t\83@\83C\83\8b\83o\81[\83W\83\87\83\93
-//             FExitWrite: TStringList;
-//             function StrToFloatDef(s: string; Default: Double): Double;
+               FVersion : String;                    //!< \83t\83@\83C\83\8b\83o\81[\83W\83\87\83\93
+               FGikoMessage: TGikoMessage;
+        FBelib: TBelib;
+               //! \82 \82é\83Z\83p\83\8c\81[\83^\82Å\8bæ\90Ø\82ç\82ê\82½\95\8e\9a\97ñ\82©\82ç\82\8e\94Ô\96Ú\82Ì\95\8e\9a\97ñ\82ð\8eæ\82è\8fo\82·
+               function ChooseString(const Text, Separator: string; Index: integer): string;
+        //! \88ê\8e\9e\83t\83@\83C\83\8b\82©\82ç\82Ì\95\9c\8b\8c
+        procedure RestoreThreadData(Board: TBoard);
        public
                { Public \90é\8c¾ }
                FAbon : TAbon;
@@ -124,15 +126,12 @@ type
 
                destructor Destroy; override;
                property ResRange : Longint read FResRange write FResRange;
-               //\83o\81[\83W\83\87\83\93\8fî\95ñ
+               //\83o\81[\83W\83\87\83\93\8fî\95ñ
                property Version : String read FVersion;
-//             function MsgBox(Msg: string; Title: string; Flags: Longint): integer; overload;
-//             function MsgBox(Handle: THandle; Msg: string; Title: string; Flags: Longint): integer; overload;
                function IsNumeric(s: string): boolean;
                function IsFloat(s: string): boolean;
                function DirectoryExistsEx(const Name: string): Boolean;
                function ForceDirectoriesEx(Dir: string): Boolean;
-//             function GetVersion: string;
 
                function GetBoardFileName: string;
                function GetCustomBoardFileName: string;
@@ -141,6 +140,7 @@ type
                function GetTempFolder: string;
                function GetSentFileName: string;
                function GetConfigDir: string;
+        function GetNGWordsDir: string;
                function GetSkinDir: string;
                function GetSkinHeaderFileName: string;
                function GetSkinFooterFileName: string;
@@ -153,6 +153,9 @@ type
                function GetUserAgent: string;
                                function GetSambaFileName : string;
 
+               function GetMainKeyFileName : String;
+               function GetEditorKeyFileName: String;
+               function GetInputAssistFileName: String;
                procedure ReadSubjectFile(Board: TBoard);
                procedure CreateThreadDat(Board: TBoard);
                procedure WriteThreadDat(Board: TBoard);
@@ -162,10 +165,9 @@ type
                procedure GetDirectoryList(Path: string; Mask: string; List: TStringList; SubDir: Boolean);
 
                function DivideSubject(Line: string): TSubjectRec;
-               function DivideStrLine(Line: string): TResRec;
-
                property Setting: TSetting read FSetting write FSetting;
                property Dolib: TDolib read FDolib write FDolib;
+               property Belib: TBelib read FBelib write FBelib;
 
                function UrlToID(url: string): string;
                function UrlToServer(url: string): string;
@@ -175,7 +177,6 @@ type
 
                function GetFileSize(FileName : string) : longint;
                function GetFileLineCount(FileName : string): longint;
-               function Get2chDate(aDate: TDateTime): string;
                function IntToDateTime(val: Int64): TDateTime;
                function DateTimeToInt(ADate: TDateTime): Int64;
 
@@ -183,21 +184,16 @@ type
 
                procedure MenuFont(Font: TFont);
 
-               function RemoveToken(var s:string; const delimiter:string):string;
+//             function RemoveToken(var s:string; const delimiter:string):string;
                function GetTokenIndex(s: string; delimiter: string; index: Integer): string;
-               function DeleteLink(const s: string): string;
 
                function GetShortName(const LongName: string; ALength: integer): string;
-               function ConvRes(const Body, Bbs, Key,  ParamBBS, ParamKey, ParamStart, ParamTo, ParamNoFirst, ParamTrue : string; DatToHTML: boolean = false): string; overload;
-               function ConvRes(const Body, Bbs, Key,  ParamBBS, ParamKey, ParamStart, ParamTo, ParamNoFirst, ParamTrue, FullURL : string): string; overload;
+               function TrimThreadTitle(const SrcTitle: string): string;
                function BoolToInt(b: Boolean): Integer;
                function IntToBool(i: Integer): Boolean;
                function GzipDecompress(ResStream: TStream; ContentEncoding: string): string;
-               procedure LoadKeySetting(ActionList: TActionList);
-               procedure SaveKeySetting(ActionList: TActionList);
-               procedure LoadEditorKeySetting(ActionList: TActionList);
-               procedure SaveEditorKeySetting(ActionList: TActionList);
-
+               procedure LoadKeySetting(ActionList: TActionList; FileName: String);
+               procedure SaveKeySetting(ActionList: TActionList; FileName: String);
                procedure CreateProcess(const AppPath: string; const Param: string);
                procedure OpenBrowser(URL: string; BrowserType: TGikoBrowserType);
                function HTMLDecode(const AStr: String): String;
@@ -220,17 +216,12 @@ type
 
                procedure GetPopupResNumber(URL : string; var stRes, endRes : Int64);
 
-               //Samba24\82Ì\83t\83@\83C\83\8b\82ª\91\8dÝ\82·\82é\82©\81B\91\8dÝ\82µ\82È\82¢\8fê\8d\87\81Adefault\83t\83@\83C\83\8b\82ðrename\82·\82é
-               procedure SambaFileExists();
-
                property Bayesian : TGikoBayesian read FBayesian write FBayesian;
-               function GetSameIDResAnchor(const AID : string; ThreadItem: TThreadItem; limited: boolean):string; overload;
-               function GetSameIDResAnchor(AIDNum : Integer; ThreadItem: TThreadItem; limited: boolean):string; overload;
+        function CreateResAnchor(var Numbers: TStringList; ThreadItem: TThreadItem; limited: Integer):string;
                procedure GetSameIDRes(const AID : string; ThreadItem: TThreadItem;var body: TStringList); overload;
                procedure GetSameIDRes(AIDNum : Integer; ThreadItem: TThreadItem;var body: TStringList); overload;
-               function GetSameIDResCount(const AID : string; ThreadItem: TThreadItem):Integer; overload;
-               function GetSameIDResCount(AIDNum : Integer; ThreadItem: TThreadItem):Integer; overload;
-
+        function GetResID(AIDNum: Integer; ThreadItem: TThreadItem): String;
+        function ExtructResID(ADateStr: String): String;
                //! \92P\8cê\89ð\90Í
                procedure SpamCountWord( const text : string; wordCount : TWordCount );
                //! \8aw\8fK\83N\83\8a\83A
@@ -239,18 +230,45 @@ type
                procedure SpamLearn( wordCount : TWordCount; isSpam : Boolean );
                //! \83X\83p\83\80\93x\90\94
                function SpamParse( const text : string; wordCount : TWordCount ) : Extended;
-               //\88ø\90\94\82ª\81A\93ú\95t\82Å\82à\8e\9e\8d\8f\82Å\82à\82È\82¢\82±\82Æ\82ð\92²\82×\82é
-               function NotDateorTimeString(const AStr : string): boolean;
 
-               //\88ø\90\94\82É\91\97\82ç\82ê\82Ä\82«\82½\93ú\95t/ID\95\94\82ÉBE\82Ì\95\8e\9a\97ñ\82ª\82 \82Á\82½\82ç\81A\83v\83\8d\83t\83@\83C\83\8b\82Ö\82Ì\83\8a\83\93\83N\82ð\92Ç\89Á
+               //\88ø\90\94\82É\91\97\82ç\82ê\82Ä\82«\82½\93ú\95t/ID\95\94\82ÉBE\82Ì\95\8e\9a\97ñ\82ª\82 \82Á\82½\82ç\81A\83v\83\8d\83t\83@\83C\83\8b\82Ö\82Ì\83\8a\83\93\83N\82ð\92Ç\89Á
                function AddBeProfileLink(AID : string; ANum: Integer): string;
-               //\83o\81[\83W\83\87\83\93\8fî\95ñ\82Ì\8eæ\93¾
+               //\83o\81[\83W\83\87\83\93\8fî\95ñ\82Ì\8eæ\93¾
                function GetVersionInfo(KeyWord: TVerResourceKey): string;
-               //Plugin\82Ì\8fî\95ñ\82Ì\8eæ\93¾
+               //Plugin\82Ì\8fî\95ñ\82Ì\8eæ\93¾
                function GetPluginsInfo(): string;
-               //IE\82Ì\83o\81[\83W\83\87\83\93\8fî\95ñ\82Ì\8eæ\93¾
+               //IE\82Ì\83o\81[\83W\83\87\83\93\8fî\95ñ\82Ì\8eæ\93¾
                function GetIEVersion: string;
                function SetUserOptionalStyle(): string;
+               //! \83M\83R\83i\83r\82Ì\83\81\83b\83Z\81[\83W\82ð\90Ý\92è\82·\82é
+               procedure SetGikoMessage;
+               //! \83M\83R\83i\83r\82Ì\83\81\83b\83Z\81[\83W\82ð\8eæ\93¾\82·\82é
+               function GetGikoMessage(MesType: TGikoMessageListType): String;
+               //! GMT\82Ì\8e\9e\8d\8f\82ðTDateTime\82É\95Ï\8a·\82·\82é
+               function  DateStrToDateTime(const DateStr: string): TDateTime;
+        //! User32.dll\82ª\97\98\97p\82Å\82«\82é\82©
+        function CanUser32DLL: Boolean;
+        //! OE\88ø\97p\95\84\8eæ\93¾
+        function GetOEIndentChar : string;
+        //! \92u\8a·\90Ý\92è\83t\83@\83C\83\8b\8eæ\93¾
+        function GetReplaceFileName: String;
+        //! \83C\83\93\83f\83b\83N\83X\82É\82È\82¢dat\81i\82Í\82®\82êdat\81j\82Ì\92Ç\89Á
+        procedure AddOutofIndexDat(Board: TBoard; DatList: TStringList; AllCreate: boolean = True);
+        //! \83t\83@\83C\83\8b\96¼\82©\82ç\82Ì\83X\83\8c\83b\83h\8dì\90¬\93ú\82Ì\8eæ\93¾
+        function GetCreateDateFromName(FileName: String): TDateTime;
+        function GetExtpreviewFileName: String;
+
+        procedure ShowRefCount(msg: String; unk: IUnknown);
+        //! \96`\8c¯\82Ì\8f\91Cookie\8eæ\93¾
+        function GetBoukenCookie(AURL: String): String;
+        //! \96`\8c¯\82Ì\8f\91Cookie\90Ý\92è
+        procedure SetBoukenCookie(ACookieValue, ADomain: String);
+        //! \96`\8c¯\82Ì\8f\91Cookie\8dí\8f\9c
+        procedure DelBoukenCookie(ADomain: String);
+        //! \96`\8c¯\82Ì\8f\91Domain\88ê\97\97\8eæ\93¾
+        procedure GetBoukenDomain(var ADomain: TStringList);
+        //! \96`\8c¯\82Ì\8f\91\83h\83\81\83C\83\93\96¼Cookie\8eæ\93¾
+        function GetBouken(AURL: String; var Domain: String): String;
        end;
 
 var
@@ -260,8 +278,8 @@ const
        ZERO_DATE: Integer      = 25569;
        BETA_VERSION_NAME_E = 'beta';
        BETA_VERSION_NAME_J = 'ÊÞÀ';
-       BETA_VERSION                            = 51;
-       BETA_VERSION_BUILD      = '';                           //debug\94Å\82È\82Ç
+       BETA_VERSION                            = 68;
+       BETA_VERSION_BUILD      = '';                           //!< debug\94Å\82È\82Ç
        APP_NAME                                                = 'gikoNavi';
        BE_PHP_URL = 'http://be.2ch.net/test/p.php?i=';
 
@@ -269,7 +287,8 @@ const
 implementation
 
 uses
-       Giko, RoundData, Favorite, Registry, HTMLCreate, MojuUtils;
+       Giko, RoundData, Favorite, Registry, HTMLCreate, MojuUtils, Sort, YofUtils,
+       IniFiles, DateUtils, SkinFiles;
 
 const
        FOLDER_INDEX_VERSION                                    = '1.01';
@@ -278,6 +297,7 @@ const
        NGWORDs_DIR_NAME : String               = 'NGwords';
 
        READ_PATH: string =                     '/test/read.cgi/';
+    HTML_READ_PATH: string =        '/test/read.html/';
        OLD_READ_PATH: string =         '/test/read.cgi?';
        KAKO_PATH: string =                     '/kako/';
 
@@ -295,13 +315,15 @@ const
                  'ProductVersion',
                  'SpecialBuild');
 
-(*************************************************************************
- *GikoSys\83R\83\93\83X\83g\83\89\83N\83^
- *************************************************************************)
+// *************************************************************************
+//! GikoSys\83R\83\93\83X\83g\83\89\83N\83^
+// *************************************************************************
 constructor TGikoSys.Create;
 begin
+    Inherited;
        FSetting := TSetting.Create;
        FDolib := TDolib.Create;
+    FBelib := TBelib.Create;
        FAWKStr := TAWKStr.Create(nil);
        if DirectoryExists(GetConfigDir) = false then begin
                CreateDir(GetConfigDir);
@@ -326,27 +348,18 @@ begin
        FVersion := Trim(GetVersionInfo(vrFileVersion));
        FBayesian := TGikoBayesian.Create;
        //FBoardURLList := TStringList.Create;
+       //\83\81\83b\83Z\81[\83W\82Ì\8dì\90¬
+       FGikoMessage := TGikoMessage.Create;
 end;
 
-(*************************************************************************
- *GikoSys\83f\83X\83g\83\89\83N\83^
- *************************************************************************)
+// *************************************************************************
+//! GikoSys\83f\83X\83g\83\89\83N\83^
+// *************************************************************************
 destructor TGikoSys.Destroy;
 var
        i: Integer;
        FileList: TStringList;
 begin
-       //\83X\83\8c\83b\83h\83f\81[\83^\83t\83@\83C\83\8b\82ð\8dX\90V
-//     FlashExitWrite;
-
-//     FExitWrite.Free;
-       FBayesian.Free;
-       FAWKStr.Free;
-       FSetting.Free;
-       FDolib.Free;
-       FAbon.Free;
-       FSelectResFilter.Free;
-       //FBoardURLList.Free;
        //\83e\83\93\83|\83\89\83\8aHTML\82ð\8dí\8f\9c
        FileList := TStringList.Create;
        try
@@ -359,12 +372,22 @@ begin
        finally
                FileList.Free;
        end;
+    FreeAndNil(FGikoMessage);
+       FreeAndNil(FBayesian);
+       FreeAndNil(FSelectResFilter);
+       FreeAndNil(FAbon);
+       FreeAndNil(FAWKStr);
+    FreeAndNil(FBelib);
+       FreeAndNil(FDolib);
+       FreeAndNil(FSetting);
        inherited;
 end;
 
-(*************************************************************************
- *\95\8e\9a\97ñ\90\94\8e\9a\83`\83F\83b\83N
- *************************************************************************)
+{!
+\brief \95\8e\9a\97ñ\90\94\8e\9a\83`\83F\83b\83N
+\param s \83`\83F\83b\83N\82·\82é\95\8e\9a\97ñ
+\return s \82ª\95\84\8d\86\95t\82«\90®\90\94\82Æ\82µ\82Ä\94F\8e¯\89Â\94\\82È\82ç True
+}
 {$HINTS OFF}
 function TGikoSys.IsNumeric(s: string): boolean;
 var
@@ -376,9 +399,11 @@ begin
 end;
 {$HINTS ON}
 
-(*************************************************************************
- *\95\8e\9a\97ñ\95\82\93®\8f¬\90\94\93_\90\94\8e\9a\83`\83F\83b\83N
- *************************************************************************)
+{!
+\brief \95\8e\9a\97ñ\95\82\93®\8f¬\90\94\93_\90\94\8e\9a\83`\83F\83b\83N
+\param s \83`\83F\83b\83N\82·\82é\95\8e\9a\97ñ
+\return s \82ª\95\84\8d\86\95t\82«\95\82\93®\8f¬\90\94\82Æ\82µ\82Ä\94F\8e¯\89Â\94\\82È\82ç True
+}
 function TGikoSys.IsFloat(s: string): boolean;
 var
        v: Extended;
@@ -386,112 +411,126 @@ begin
        Result := TextToFloat(PChar(s), v, fvExtended);
 end;
 
-(*************************************************************************
- *\83{\81[\83h\83t\83@\83C\83\8b\96¼\8eæ\93¾\81i\83p\83X\81{\83t\83@\83C\83\8b\96¼\81j
- *************************************************************************)
+// *************************************************************************
+//! \83{\81[\83h\83t\83@\83C\83\8b\96¼\8eæ\93¾\81i\83p\83X\81{\83t\83@\83C\83\8b\96¼\81j
+// *************************************************************************
 function TGikoSys.GetBoardFileName: string;
 begin
        Result := Setting.GetBoardFileName;
 end;
 
-(*************************************************************************
- *\83{\81[\83h\83t\83@\83C\83\8b\96¼\8eæ\93¾\81i\83p\83X\81{\83t\83@\83C\83\8b\96¼\81j
- *************************************************************************)
+// *************************************************************************
+//! \83{\81[\83h\83t\83@\83C\83\8b\96¼\8eæ\93¾\81i\83p\83X\81{\83t\83@\83C\83\8b\96¼\81j
+// *************************************************************************
 function TGikoSys.GetCustomBoardFileName: string;
 begin
        Result := Setting.GetCustomBoardFileName;
 end;
 
-(*************************************************************************
- *\83e\83\93\83|\83\89\83\8a\83t\83H\83\8b\83_\81[\96¼\8eæ\93¾
- *************************************************************************)
+// *************************************************************************
+//! \83e\83\93\83|\83\89\83\8a\83t\83H\83\8b\83_\81[\96¼\8eæ\93¾
+// *************************************************************************
 function TGikoSys.GetHtmlTempFileName: string;
 begin
        Result := Setting.GetHtmlTempFileName;
 end;
 
 
-(*************************************************************************
- *\8eÀ\8ds\83t\83@\83C\83\8b\83t\83H\83\8b\83_\8eæ\93¾
- *************************************************************************)
+// *************************************************************************
+//! \8eÀ\8ds\83t\83@\83C\83\8b\83t\83H\83\8b\83_\8eæ\93¾
+// *************************************************************************
 function TGikoSys.GetAppDir: string;
 begin
        Result := Setting.GetAppDir;
 end;
 
-(*************************************************************************
- *TempHtml\83t\83@\83C\83\8b\96¼\8eæ\93¾\81i\83p\83X\81{\83t\83@\83C\83\8b\96¼\81j
- *************************************************************************)
+// *************************************************************************
+//! TempHtml\83t\83@\83C\83\8b\96¼\8eæ\93¾\81i\83p\83X\81{\83t\83@\83C\83\8b\96¼\81j
+// *************************************************************************
 function TGikoSys.GetTempFolder: string;
 begin
        Result := Setting.GetTempFolder;
 end;
 
-(*************************************************************************
- *sent.ini\83t\83@\83C\83\8b\96¼\8eæ\93¾\81i\83p\83X\81{\83t\83@\83C\83\8b\96¼\81j
- *************************************************************************)
+// *************************************************************************
+//! sent.ini\83t\83@\83C\83\8b\96¼\8eæ\93¾\81i\83p\83X\81{\83t\83@\83C\83\8b\96¼\81j
+// *************************************************************************)
 function TGikoSys.GetSentFileName: string;
 begin
        Result := Setting.GetSentFileName;
 end;
 
-(*************************************************************************
- *outbox.ini\83t\83@\83C\83\8b\96¼\8eæ\93¾\81i\83p\83X\81{\83t\83@\83C\83\8b\96¼\81j
- *************************************************************************)
+// *************************************************************************
+//! outbox.ini\83t\83@\83C\83\8b\96¼\8eæ\93¾\81i\83p\83X\81{\83t\83@\83C\83\8b\96¼\81j
+// *************************************************************************
 function TGikoSys.GetOutBoxFileName: string;
 begin
        Result := Setting.GetOutBoxFileName;
 end;
 
-(*************************************************************************
- *Config\83t\83H\83\8b\83_\8eæ\93¾
- *************************************************************************)
+// *************************************************************************
+//! Config\83t\83H\83\8b\83_\8eæ\93¾
+// *************************************************************************
 function TGikoSys.GetConfigDir: string;
 begin
        Result := Setting.GetConfigDir;
 end;
 
+function TGikoSys.GetNGWordsDir: string;
+begin
+       Result := Setting.GetConfigDir + NGWORDs_DIR_NAME;
+end;
+
+
+//! \83X\83^\83C\83\8b\83V\81[\83g\83t\83H\83\8b\83_
 function TGikoSys.GetStyleSheetDir: string;
 begin
        Result := Setting.GetStyleSheetDir;
 end;
 
+//! \83X\83L\83\93\83t\83H\83\8b\83_
 function TGikoSys.GetSkinDir: string;
 begin
        Result := Setting.GetSkinDir;
 end;
 
+//! Skin:\83w\83b\83_\82Ì\83t\83@\83C\83\8b\96¼
 function TGikoSys.GetSkinHeaderFileName: string;
 begin
-       Result := Setting.GetSkinHeaderFileName;
+       Result := Setting.SkinFiles.GetSkinHeaderFileName;
 end;
 
+//! Skin:\83t\83b\83^\82Ì\83t\83@\83C\83\8b\96¼
 function TGikoSys.GetSkinFooterFileName: string;
 begin
-       Result := Setting.GetSkinFooterFileName;
+       Result := Setting.SkinFiles.GetSkinFooterFileName;
 end;
 
+//! Skin:\90V\92\85\83\8c\83X\82Ì\83t\83@\83C\83\8b\96¼
 function TGikoSys.GetSkinNewResFileName: string;
 begin
-       Result := Setting.GetSkinNewResFileName;
+       Result := Setting.SkinFiles.GetSkinNewResFileName;
 end;
 
+//! Skin:\94ñ\90V\92\85\83\8c\83X\82Ì\83t\83@\83C\83\8b\96¼
 function TGikoSys.GetSkinResFileName: string;
 begin
-       Result := Setting.GetSkinResFileName;
+       Result := Setting.SkinFiles.GetSkinResFileName;
 end;
 
+//! Skin:\82µ\82¨\82è(\82±\82±\82Ü\82Å\93Ç\82ñ\82¾)\82Ì\83t\83@\83C\83\8b\96¼
 function TGikoSys.GetSkinBookmarkFileName: string;
 begin
-       Result := Setting.GetSkinBookmarkFileName;
+       Result := Setting.SkinFiles.GetSkinBookmarkFileName;
 end;
 
+//! Skin:\82µ\82¨\82è(\90V\92\85\83\8c\83X)\82Ì\83t\83@\83C\83\8b\96¼
 function TGikoSys.GetSkinNewmarkFileName: string;
 begin
-       Result := Setting.GetSkinNewmarkFileName;
+       Result := Setting.SkinFiles.GetSkinNewmarkFileName;
 end;
 
-// UserAgent\8eæ\93¾
+//! UserAgent\8eæ\93¾
 function TGikoSys.GetUserAgent: string;
 begin
        if Dolib.Connected then begin
@@ -512,96 +551,97 @@ begin
        end;
 end;
 
-(*************************************************************************
- *\82Q\82¿\82á\82ñ\82Ë\82é\95û\8e®\8e\9e\8d\8f\8eæ\93¾
- *************************************************************************)
-function TGikoSys.Get2chDate(aDate: TDateTime): string;
-var
-       d2: TDateTime;
-begin
-       d2 := aDate - EncodeTime(9, 0, 0, 0);
-       Result := FloatToStr(Trunc((d2 - ZERO_DATE) * 86400));
-end;
-
-//val\82Í\81A1970/1/1/ 00:00:00 \82©\82ç\82Ì\8co\89ß\8e\9e\8aÔ
+{!
+\brief \8co\89ß\95b\82ð TDateTime \82É\95Ï\8a·
+\param val 1970/1/1/ 00:00:00 \82©\82ç\82Ì\8co\89ß\95b
+\return val \82ð\8e¦\82· TDateTime
+}
 function TGikoSys.IntToDateTime(val: Int64): TDateTime;
 begin
        Result := ZERO_DATE + val / 86400.0;
 end;
-//ADate\82ð1970/1/1/ 00:00:00 \82©\82ç\82Ì\8co\89ß\8e\9e\8aÔ\82É\95Ï\8a·\82·\82é
+
+{!
+\brief TDateTime \82ð\8co\89ß\95b\82É\95Ï\8a·
+\param ADate \95Ï\8a·\82·\82é\8e\9e\8d\8f
+\return 1970/1/1/ 00:00:00 \82©\82ç\82Ì\8co\89ß\95b
+}
 function TGikoSys.DateTimeToInt(ADate: TDateTime): Int64;
 begin
        Result := Trunc((ADate - ZERO_DATE) * 86400);
 end;
 
 
-(*************************************************************************
- *Subject\83t\83@\83C\83\8bRead
- *************************************************************************)
+{!
+\brief Subject\83t\83@\83C\83\8bRead
+\param Board \83X\83\8c\88ê\97\97\82ð\8eæ\93¾\82·\82é\94Â
+}
 procedure TGikoSys.ReadSubjectFile(Board: TBoard);
 var
        ThreadItem: TThreadItem;
        FileName: string;
        FileList: TStringList;
-       TmpFileList: TStringList;
        Index: Integer;
        sl: TStringList;
        i: Integer;
        Rec: TIndexRec;
        UnRead: Integer;
-       ini: TMemIniFile;
-       ResRec: TResRec;
-//     RoundItem: TRoundItem;
-//     idx: Integer;
        usePlugIn : Boolean;
-       tmpStr: string;
-       BoardPath : String;
-       server : String;
        islog : Boolean;
-       //protocol, host, path, document, port, bookmark        : string;
-       //is2ch : Boolean;
+    urlHead: String;
+    datFileCheck: Boolean;
        {*
        FavoThreadItem : TFavoriteThreadItem;
        Node: TTreeNode;
        *}
+{$IFDEF DEBUG}
+    st, rt: Cardinal;
+{$ENDIF}
 begin
+{$IFDEF DEBUG}
+       st := GetTickCount;
+{$ENDIF}
        if Board.IsThreadDatRead then
                Exit;
        Board.Clear;
        UnRead := 0;
-       //is2ch := false;
        usePlugIn := Board.IsBoardPlugInAvailable;
-       server :=  UrlToServer( Board.URL );
-       //is2ch := Is2chHost(server);
+       //server :=  UrlToServer( Board.URL );
+    // \83X\83\8c\83b\83h\82Å\8b¤\92Ê\82ÌURL\95\94
+    if Board.is2ch then begin
+        urlHead := UrlToServer( Board.URL ) + 'test/read.cgi/' + Board.BBSID + '/';
+    end else begin
+        urlHead := UrlToServer( Board.URL ) + 'test/read.cgi?bbs=' + Board.BBSID + '&key=';
+    end;
 
        FileName := Board.GetFolderIndexFileName;
 
-       FileList := TStringList.Create;
-       FileList.Sorted := True;
-       FileList.BeginUpdate;
-       TmpFileList := TStringList.Create;
-       TmpFileList.Sorted := True;
-       TmpFileList.BeginUpdate;
-       //IsLogFile\97pDAT\83t\83@\83C\83\8b\83\8a\83X\83g
-       GetFileList(ExtractFileDir(Board.GetFolderIndexFileName), '*.dat', FileList, False);
-       FileList.EndUpdate;
-       //\91O\89ñ\88Ù\8fí\8fI\97¹\8e\9e\97pTmp\83t\83@\83C\83\8b\83\8a\83X\83g
-       GetFileList(ExtractFileDir(Board.GetFolderIndexFileName), '*.tmp', TmpFileList, False);
-       TmpFileList.EndUpdate;
+    //
+    datFileCheck := (Setting.CheckDatFile) or (not FileExists(FileName));
+    if (datFileCheck) then begin
+        FileList := TStringList.Create;
+        FileList.Sorted := True;
+        FileList.BeginUpdate;
+        //IsLogFile\97pDAT\83t\83@\83C\83\8b\83\8a\83X\83g
+        GetFileList(ExtractFileDir(Board.GetFolderIndexFileName), '*.dat', FileList, False);
+        FileList.EndUpdate;
+    end;
 
        // \8fd\95¡\82ð\96h\82®
        Board.BeginUpdate;
        Board.Sorted := True;
-
        sl := TStringList.Create;
        try
                if FileExists(FileName) then begin
                        sl.LoadFromFile(FileName);
-
                        //\82Q\8ds\96Ú\82©\82ç\81i\82P\8ds\96Ú\82Í\83o\81[\83W\83\87\83\93\81j
                        for i := sl.Count - 1 downto 1 do begin
                                Rec := ParseIndexLine(sl[i]);
-                               islog := FileList.Find( Rec.FFileName, Index );
+                if (datFileCheck) then begin
+                               islog := FileList.Find( Rec.FFileName, Index );
+                end else begin
+                    islog := (Rec.FSize <> 0) and (Rec.FCount <> 0);
+                end;
                                if usePlugIn then
                                        ThreadItem := TThreadItem.Create(
                                                        Board.BoardPlugIn,
@@ -612,7 +652,7 @@ begin
                                                ThreadItem := TThreadItem.Create(
                                                        nil,
                                                        Board,
-                                                       server + 'test/read.cgi/' + Board.BBSID + '/' + ChangeFileExt( Rec.FFileName, '' ) + '/l50',
+                                                       urlHead + ChangeFileExt( Rec.FFileName, '' ) + '/l50',
                                                        islog,
                                                        Rec.FFileName
                                                        );
@@ -620,29 +660,26 @@ begin
                                                ThreadItem := TThreadItem.Create(
                                                        nil,
                                                        Board,
-                                                       server + 'test/read.cgi?bbs=' + Board.BBSID + '&key=' + ChangeFileExt( Rec.FFileName, '' ) + '&ls=50',
+                                                       urlHead + ChangeFileExt( Rec.FFileName, '' ) + '&ls=50',
                                                        islog,
                                                        Rec.FFileName
                                                        );
                                        end;
                                end;
 
-                               ThreadItem.BeginUpdate;
-                               if islog then
+                               //ThreadItem.BeginUpdate;
+                               if (datFileCheck) and (islog) then
                                        FileList.Delete( Index );
 
                                ThreadItem.No := Rec.FNo;
                                ThreadItem.FileName := Rec.FFileName;
-                               ThreadItem.Title := Rec.FTitle;
-                               //ThreadItem.ShortTitle := CustomStringReplace(ZenToHan(ThreadItem.Title), ' ', '');
+                               ThreadItem.Title := MojuUtils.UnSanitize(Rec.FTitle);
                                ThreadItem.Count := Rec.FCount;
                                ThreadItem.Size := Rec.FSize;
-//                     ThreadItem.RoundNo := Rec.FRoundNo;
                                ThreadItem.RoundDate := Rec.FRoundDate;
                                ThreadItem.LastModified := Rec.FLastModified;
                                ThreadItem.Kokomade := Rec.FKokomade;
                                ThreadItem.NewReceive := Rec.FNewReceive;
-//                     ThreadItem.Round := Rec.FRound;
                                ThreadItem.UnRead := Rec.FUnRead;
                                ThreadItem.ScrollTop := Rec.FScrollTop;
                                ThreadItem.AllResCount := Rec.FAllResCount;
@@ -655,21 +692,10 @@ begin
                                Node := FavoriteDM.TreeView.Items.AddChildObject( FavoriteDM.TreeView.Items.Item[0], ThreadItem.Title, FavoThreadItem);
                                *}
 
-                               {//\8f\84\89ñ\83\8a\83X\83g\82É\91\8dÝ\82µ\82½\82ç\8f\84\89ñ\83t\83\89\83O\83Z\83b\83g
-                               if ThreadItem.IsLogFile then begin
-                                       idx := RoundList.Find(ThreadItem);
-                                       if idx <> -1 then begin
-                                               RoundItem := RoundList.Items[idx, grtItem];
-                                               ThreadItem.RoundName := RoundItem.RoundName;
-                                               ThreadItem.Round := True;
-                                       end;
-                               end;
-                               }
-
-                               ThreadItem.EndUpdate;
+                               //ThreadItem.EndUpdate;
                                Board.Add(ThreadItem);
 
-                               if (ThreadItem.IsLogFile) and (ThreadItem.UnRead) then
+                               if (ThreadItem.UnRead) and (ThreadItem.IsLogFile) then
                                        Inc(UnRead);
                        end;
                end;
@@ -677,101 +703,105 @@ begin
                if UnRead <> Board.UnRead then
                        Board.UnRead := UnRead;
 
-               Boardpath := ExtractFilePath(Board.GetFolderIndexFileName);
-               //\83C\83\93\83f\83b\83N\83X\82É\96³\82©\82Á\82½\83\8d\83O\82ð\92Ç\89Á\81i\95\85\82ê\83C\83\93\83f\83b\83N\83X\91Î\89\9e\81j
-               for i := 0 to FileList.Count - 1 do begin
-                       FileName := Boardpath + FileList[i];
-
-                       //ResRec := DivideStrLine(ReadThreadFile(FileName, 1));
-                       if usePlugIn then begin
-                               ThreadItem := TThreadItem.Create(
-                                       Board.BoardPlugIn,
-                                       Board,
-                                       Board.BoardPlugIn.FileName2ThreadURL( DWORD( Board ), FileList[i] ) );
-                               ResRec := DivideStrLine(Board.BoardPlugIn.GetDat( DWORD( ThreadItem ), 1 ));
-                       end else begin
-                               ThreadItem := TThreadItem.Create(
-                                       nil,
-                                       Board,
-                                       Get2chBoard2ThreadURL( Board, ChangeFileExt( FileList[i], '' ) ) );
-                               ResRec := DivideStrLine(ReadThreadFile(FileName, 1));
-                       end;
-
-                       ThreadItem.BeginUpdate;
-                       ThreadItem.FileName := FileList[i];
-                       //ThreadItem.FilePath := FileName;
-                       ThreadItem.No := Board.Count + 1;
-                       ThreadItem.Title := ResRec.FTitle;
-                       ThreadItem.Count := GetFileLineCount(FileName);
-                       ThreadItem.AllResCount := ThreadItem.Count;
-                       ThreadItem.NewResCount := ThreadItem.Count;
-                       ThreadItem.Size := GetFileSize(FileName) - ThreadItem.Count;//1byte\82¸\82ê\82é\82Æ\82«\82ª\82 \82é\82¯\82Ç\82»\82ê\82Í\82 \82«\82ç\82ß\82é
-                       ThreadItem.RoundDate := ZERO_DATE;
-                       ThreadItem.LastModified := ZERO_DATE;
-                       ThreadItem.Kokomade := -1;
-                       ThreadItem.NewReceive := ThreadItem.Count;
-                       ThreadItem.ParentBoard := Board;
-                       ThreadItem.IsLogFile := True;
-                       ThreadItem.Round := False;
-                       ThreadItem.UnRead := False;
-                       ThreadItem.ScrollTop := 0;
-                       ThreadItem.AgeSage := gasNone;
-                       ThreadItem.EndUpdate;
-                       Board.Add(ThreadItem);
-               end;
+        if (datFileCheck) then begin
+                   //\83C\83\93\83f\83b\83N\83X\82É\96³\82©\82Á\82½\83\8d\83O\82ð\92Ç\89Á\81i\95\85\82ê\83C\83\93\83f\83b\83N\83X\91Î\89\9e\81j
+            AddOutofIndexDat(Board, FileList);
+        end;
                Board.EndUpdate;
 
-               //\91O\89ñ\88Ù\8fí\8fI\97¹\8e\9e\83`\83F\83b\83N
-               for i := TmpFileList.Count - 1 downto 0 do begin
-               //if TmpFileList.Count <> 0 then begin
-                       ThreadItem := Board.FindThreadFromFileName(ChangeFileExt(TmpFileList[i], '.dat'));
-                       if ThreadItem <> nil then begin
-                       //if TmpFileList.Find(ChangeFileExt(ThreadItem.FileName, '.tmp'), Index) then begin
-                               ini := TMemIniFile.Create(Boardpath + TmpFileList[i]);
-                               try
-                                       tmpStr := ini.ReadString('Setting', 'RoundDate', DateTimeToStr(ZERO_DATE));
-                                       ThreadItem.RoundDate := ConvertDateTimeString(tmpStr);
-
-                                       tmpStr := ini.ReadString('Setting', 'LastModified', DateTimeToStr(ZERO_DATE));
-                                       ThreadItem.LastModified := ConvertDateTimeString(tmpStr);
-                                       ThreadItem.Count := ini.ReadInteger('Setting', 'Count', 0);
-                                       ThreadItem.NewReceive := ini.ReadInteger('Setting', 'NewReceive', 0);
-
-                                       ThreadItem.Size := ini.ReadInteger('Setting', 'Size', 0);
-                                       if(ThreadItem.Size = 0) and (FileExists(ThreadItem.GetThreadFileName)) then begin
-                                               try
-                                                       ThreadItem.Size := GetFileSize(ThreadItem.GetThreadFileName) - ThreadItem.Count;
-                                               except
-                                               end;
-                                       end;
-
-                    //\8f\84\89ñ\82Ì\90Ý\92è\82ÍRoundData\82Ì\95û\82ª\82â\82é\82©\82ç\8f\9f\8eè\82É\90Ý\92è\82µ\82Ä\82Í\83_\83\81\81I\81@by \82à\82\82ã
-                                       //ThreadItem.Round := ini.ReadBool('Setting', 'Round', False);
-                                       //ThreadItem.RoundName := ini.ReadString('Setting', 'RoundName', ThreadItem.RoundName);
-                                       ThreadItem.UnRead := False;//ini.ReadBool('Setting', 'UnRead', False);
-                                       ThreadItem.ScrollTop := ini.ReadInteger('Setting', 'ScrollTop', 0);
-                                       ThreadItem.AllResCount := ini.ReadInteger('Setting', 'AllResCount', ThreadItem.Count);
-                                       ThreadItem.NewResCount := ini.ReadInteger('Setting', 'NewResCount', 0);
-                                       ThreadItem.AgeSage := TGikoAgeSage(ini.ReadInteger('Setting', 'AgeSage', Ord(gasNone)));
-                               finally
-                                       ini.Free;
-                               end;
-                               DeleteFile(Boardpath + TmpFileList[i]);
-                       end;
-               end;
-
+        //\91O\89ñ\88Ù\8fí\8fI\97¹\8e\9e\83`\83F\83b\83N
+        RestoreThreadData( Board );
        finally
                sl.Free;
-               FileList.Free;
-               TmpFileList.Free;
+        if (datFileCheck) then begin
+               FileList.Free;
+        end;
                Board.Sorted := False;
        end;
        Board.IsThreadDatRead := True;
+{$IFDEF DEBUG}
+       rt := GetTickCount - st;
+       Writeln('Read Done.' + Board.Title + ':' + IntToStr(rt) + ' ms');
+{$ENDIF}
+end;
+{!
+\brief \83C\83\93\83f\83b\83N\83X\82É\82È\82¢dat\81i\82Í\82®\82êdat\81j\82Ì\92Ç\89Á
+\param Board \92Ç\89Á\82·\82é\94Â
+\param DatList  dat\83t\83@\83C\83\8b\96¼
+}
+procedure TGikoSys.AddOutofIndexDat(Board: TBoard; DatList: TStringList; AllCreate: Boolean = True);
+var
+    i : Integer;
+    Boardpath,FileName : String;
+    ResRec: TResRec;
+    ThreadItem: TThreadItem;
+    create: Boolean;
+begin
+    create := False;
+    Boardpath := ExtractFilePath(Board.GetFolderIndexFileName);
+    //\83C\83\93\83f\83b\83N\83X\82É\96³\82©\82Á\82½\83\8d\83O\82ð\92Ç\89Á\81i\95\85\82ê\83C\83\93\83f\83b\83N\83X\91Î\89\9e\81j
+    for i := 0 to DatList.Count - 1 do begin
+        FileName := Boardpath + DatList[i];
+        ThreadItem := nil;
+        if (not AllCreate) then begin
+            create := False;
+            ThreadItem := Board.FindThreadFromFileName(DatList[i]);
+            if (ThreadItem = nil) then begin
+                create := True;
+            end else begin
+                if Board.IsBoardPlugInAvailable then begin
+                    THTMLCreate.DivideStrLine(Board.BoardPlugIn.GetDat( DWORD( ThreadItem ), 1 ), @ResRec);
+                end else begin
+                    THTMLCreate.DivideStrLine(ReadThreadFile(FileName, 1), @ResRec);
+                end;
+            end;
+        end;
+        if (ThreadItem = nil) then begin
+            if Board.IsBoardPlugInAvailable then begin
+                ThreadItem := TThreadItem.Create(
+                    Board.BoardPlugIn,
+                    Board,
+                    Board.BoardPlugIn.FileName2ThreadURL( DWORD( Board ), DatList[i] ) );
+                THTMLCreate.DivideStrLine(Board.BoardPlugIn.GetDat( DWORD( ThreadItem ), 1 ), @ResRec);
+            end else begin
+                ThreadItem := TThreadItem.Create(
+                    nil,
+                    Board,
+                    Get2chBoard2ThreadURL( Board, ChangeFileExt( DatList[i], '' ) ) );
+                THTMLCreate.DivideStrLine(ReadThreadFile(FileName, 1), @ResRec);
+            end;
+        end;
+        
+
+        ThreadItem.BeginUpdate;
+        ThreadItem.FileName := DatList[i];
+        //ThreadItem.FilePath := FileName;
+        ThreadItem.No := Board.Count + 1;
+        ThreadItem.Title := ResRec.FTitle;
+        ThreadItem.Count := GetFileLineCount(FileName);
+        ThreadItem.AllResCount := ThreadItem.Count;
+        ThreadItem.NewResCount := ThreadItem.Count;
+        ThreadItem.Size := GetFileSize(FileName) - ThreadItem.Count;//1byte\82¸\82ê\82é\82Æ\82«\82ª\82 \82é\82¯\82Ç\82»\82ê\82Í\82 \82«\82ç\82ß\82é
+        ThreadItem.RoundDate := FileDateToDateTime( FileAge( FileName ) );
+        ThreadItem.LastModified := ThreadItem.RoundDate;
+        ThreadItem.Kokomade := -1;
+        ThreadItem.NewReceive := 0;
+        ThreadItem.ParentBoard := Board;
+        ThreadItem.IsLogFile := True;
+        ThreadItem.Round := False;
+        ThreadItem.UnRead := False;
+        ThreadItem.ScrollTop := 0;
+        ThreadItem.AgeSage := gasNone;
+        ThreadItem.EndUpdate;
+        if (AllCreate) or (create) then begin
+            Board.Add(ThreadItem);
+        end;
+    end;
 end;
-
-(*************************************************************************
- *\83X\83\8c\83b\83h\83C\83\93\83f\83b\83N\83X\83t\83@\83C\83\8b(Folder.idx)\8dì\90¬
- *************************************************************************)
+{!
+\brief \83X\83\8c\83b\83h\83C\83\93\83f\83b\83N\83X\83t\83@\83C\83\8b(Folder.idx)\8dì\90¬
+\param Board Folder.idx \82ð\8dì\90¬\82·\82é\94Â
+}
 procedure TGikoSys.CreateThreadDat(Board: TBoard);
 var
        i: integer;
@@ -819,7 +849,7 @@ begin
                                                        '%s'#1'%x'#1'%x'#1'%x'#1'%x'#1'%x',
                                        [cnt,                   //\94Ô\8d\86
                                         Rec.FFileName, //\83t\83@\83C\83\8b\96¼
-                                        Rec.FTitle,    //\83^\83C\83g\83\8b
+                                        MojuUtils.Sanitize(Rec.FTitle),    //\83^\83C\83g\83\8b
                                         Rec.FCount,     //\83J\83E\83\93\83g
                                         0,             //size
                                         0,             //RoundDate
@@ -847,10 +877,10 @@ begin
        end;
 end;
 
-(*************************************************************************
- *\83X\83\8c\83b\83h\83C\83\93\83f\83b\83N\83X(Thread.dat)\8f\91\82«\8d\9e\82Ý
- *Public
- *************************************************************************)
+{!
+\brief \83X\83\8c\83b\83h\83C\83\93\83f\83b\83N\83X(Thread.dat)\8f\91\82«\8d\9e\82Ý
+\param Thread.dat \82ð\8dì\90¬\82·\82é\94Â
+}
 procedure TGikoSys.WriteThreadDat(Board: TBoard);
 //const
 //     Values: array[Boolean] of string = ('0', '1');
@@ -877,9 +907,9 @@ begin
                sl.Add(FOLDER_INDEX_VERSION);
 
                // \83X\83\8c\94Ô\8d\86\95Û\91\82Ì\82½\82ß\83\\81[\83g
-               Sort.SortNoFlag := true;
-               Sort.SortOrder := true;
-               Sort.SortIndex := 0;
+               Sort.SetSortNoFlag(true);
+               Sort.SetSortOrder(true);
+               Sort.SetSortIndex(0);
                //Sort.SortNonAcquiredCountFlag := GikoSys.Setting.NonAcquiredCount;
                Board.CustomSort(ThreadItemSortProc);
 
@@ -889,7 +919,7 @@ begin
                                                        '%s'#1'%x'#1'%x'#1'%x'#1'%x'#1'%x',
                                        [Board.Items[i].No,                     //\94Ô\8d\86
                                         Board.Items[i].FileName, //\83t\83@\83C\83\8b\96¼
-                                        Board.Items[i].Title,    //\83^\83C\83g\83\8b
+                     MojuUtils.Sanitize(Board.Items[i].Title),    //\83^\83C\83g\83\8b
                                         Board.Items[i].Count,     //\83J\83E\83\93\83g
                                         Board.Items[i].Size,             //size
                                         DateTimeToInt(Board.Items[i].RoundDate),             //RoundDate
@@ -919,45 +949,59 @@ begin
        end;
 end;
 
+{!
+\brief Folder.idx \82ð 1 \8ds\89ð\8eß
+\param Line Folder.idx \82ð\8d\\90¬\82·\82é 1 \8ds
+\return \83X\83\8c\83b\83h\8fî\95ñ
+}
 function TGikoSys.ParseIndexLine(Line: string): TIndexRec;
 begin
-       Result.FNo := StrToIntDef('$' + RemoveToken(Line, #1), 0);
-       Result.FFileName := RemoveToken(Line, #1);
-       Result.FTitle := RemoveToken(Line, #1);
-       Result.FCount := StrToIntDef('$' + RemoveToken(Line, #1), 0);
-       Result.FSize := StrToIntDef('$' + RemoveToken(Line, #1), 0);
-       Result.FRoundDate := IntToDateTime(StrToIntDef('$' + RemoveToken(Line, #1), ZERO_DATE));
-       Result.FLastModified := IntToDateTime(StrToIntDef('$' + RemoveToken(Line, #1), ZERO_DATE));
-       Result.FKokomade := StrToIntDef('$' + RemoveToken(Line, #1), -1);
-       Result.FNewReceive := StrToIntDef('$' + RemoveToken(Line, #1), 0);
-       RemoveToken(Line, #1);//9: ;    //\96¢\8eg\97p
-       Result.FUnRead := IntToBool(StrToIntDef('$' + RemoveToken(Line, #1), 0));
-       Result.FScrollTop := StrToIntDef('$' + RemoveToken(Line, #1), 0);
-       Result.FAllResCount := StrToIntDef('$' + RemoveToken(Line, #1), 0);
-       Result.FNewResCount := StrToIntDef('$' + RemoveToken(Line, #1), 0);
-       Result.FAgeSage := TGikoAgeSage(StrToIntDef('$' + RemoveToken(Line, #1), 0));
-
-end;
-
-//\8ew\92è\83t\83H\83\8b\83_\93à\82Ì\8ew\92è\83t\83@\83C\83\8b\88ê\97\97\82ð\8eæ\93¾\82·\82é
-// ListFiles('c:\', '*.txt', list, True);
+       Result.FNo := StrToIntDef('$' + MojuUtils.RemoveToken(Line, #1), 0);
+       Result.FFileName := MojuUtils.RemoveToken(Line, #1);
+       Result.FTitle := MojuUtils.UnSanitize(MojuUtils.RemoveToken(Line, #1));
+       Result.FCount := StrToIntDef('$' + MojuUtils.RemoveToken(Line, #1), 0);
+       Result.FSize := StrToIntDef('$' + MojuUtils.RemoveToken(Line, #1), 0);
+       Result.FRoundDate := IntToDateTime(StrToIntDef('$' + MojuUtils.RemoveToken(Line, #1), ZERO_DATE));
+       Result.FLastModified := IntToDateTime(StrToIntDef('$' + MojuUtils.RemoveToken(Line, #1), ZERO_DATE));
+       Result.FKokomade := StrToIntDef('$' + MojuUtils.RemoveToken(Line, #1), -1);
+       Result.FNewReceive := StrToIntDef('$' + MojuUtils.RemoveToken(Line, #1), 0);
+       MojuUtils.RemoveToken(Line, #1);//9: ;  //\96¢\8eg\97p
+       Result.FUnRead := IntToBool(StrToIntDef('$' + MojuUtils.RemoveToken(Line, #1), 0));
+       Result.FScrollTop := StrToIntDef('$' + MojuUtils.RemoveToken(Line, #1), 0);
+       Result.FAllResCount := StrToIntDef('$' + MojuUtils.RemoveToken(Line, #1), 0);
+       Result.FNewResCount := StrToIntDef('$' + MojuUtils.RemoveToken(Line, #1), 0);
+       Result.FAgeSage := TGikoAgeSage(StrToIntDef('$' + MojuUtils.RemoveToken(Line, #1), 0));
+
+end;
+
+{!
+\brief \8ew\92è\83t\83H\83\8b\83_\93à\82Ì\8ew\92è\83t\83@\83C\83\8b\88ê\97\97\82ð\8eæ\93¾\82·\82é
+\param Path      \8bN\93_\82Æ\82È\82é\83t\83H\83\8b\83_\83p\83X
+\param Mask      \83t\83@\83C\83\8b\96¼\82Ì\83}\83X\83N
+\param List      OUT:\8eæ\93¾\82³\82ê\82½\83t\83@\83C\83\8b\96¼\88ê\97\97\82ª\95Ô\82é
+\param SubDir    \92\86\82Ì\83t\83H\83\8b\83_\82Ü\82Å\8dÄ\8bA\93I\82É\83\8a\83X\83g\82·\82é\8fê\8d\87\82Í True
+\param IsPathAdd \83p\83X\95t\82«\82Å\83\8a\83X\83g\83A\83b\83v\82·\82é\8fê\8d\87\82Í True
+
+Mask \82ð '*.txt' \82Ì\82æ\82¤\82É\8ew\92è\82·\82é\82±\82Æ\82Å\81A
+\93Á\92è\82Ì\83t\83@\83C\83\8b\96¼\82â\93Á\92è\82Ì\8ag\92£\8eq\82É\8di\82Á\82½\83\8a\83X\83g\83A\83b\83v\82ª\89Â\94\\82Å\82·\81B
+
+\par \97á:
+\code
+GetFileList('c:\', '*.txt', list, True, True);
+\endcode
+}
 procedure TGikoSys.GetFileList(Path: string; Mask: string; var List: TStringList; SubDir: Boolean; IsPathAdd: Boolean);
 var
        rc: Integer;
        SearchRec : TSearchRec;
        s: string;
-       maskExt: string;
 begin
-       //maskExt := Copy(Mask, 1, Length(Mask) - 1);
-    maskExt := Mask;
        Path := IncludeTrailingPathDelimiter(Path);
        rc := FindFirst(Path + '*.*', faAnyfile, SearchRec);
        try
                while rc = 0 do begin
                        if (SearchRec.Name <> '..') and (SearchRec.Name <> '.') then begin
                                s := Path + SearchRec.Name;
-                               //if (SearchRec.Attr and faDirectory > 0) then
-                               //      s := IncludeTrailingPathDelimiter(s)
 
                                if (SearchRec.Attr and faDirectory = 0) and (MatchesMask(s, Mask)) then
                                                if IsPathAdd then
@@ -974,27 +1018,37 @@ begin
        end;
        List.Sort;
 end;
-//\8ew\92è\83t\83H\83\8b\83_\93à\82Ì\8ew\92è\83t\83@\83C\83\8b\88ê\97\97\82ð\8eæ\93¾\82·\82é
-//\83T\83u\83t\83H\83\8b\83_\82Í\8c\9f\8dõ\82µ\82È\82¢
-// ListFiles('c:\', '*.txt', list, True);
+
+{!
+\breif \8ew\92è\83t\83H\83\8b\83_\93à\82Ì\8ew\92è\83t\83@\83C\83\8b\88ê\97\97\82ð\8eæ\93¾\82·\82é\81B
+                        \83T\83u\83t\83H\83\8b\83_\82Í\8c\9f\8dõ\82µ\82È\82¢
+\param Path      \8bN\93_\82Æ\82È\82é\83t\83H\83\8b\83_\83p\83X
+\param Mask      \83t\83@\83C\83\8b\96¼\82Ì\83}\83X\83N
+\param List      OUT:\8eæ\93¾\82³\82ê\82½\83t\83@\83C\83\8b\96¼\88ê\97\97\82ª\95Ô\82é
+\param IsPathAdd \83p\83X\95t\82«\82Å\83\8a\83X\83g\83A\83b\83v\82·\82é\8fê\8d\87\82Í True
+\note \8dÄ\8bN\8ew\92è\89Â\94\\82È GetFileList() \82ª\82 \82é\82Ì\82Å\82±\82Ì\8aÖ\90\94\82Í\95s\97v?
+\par \97á
+\code
+GetFileList('c:\', '*.txt', list, True);
+\endcode
+}
 procedure TGikoSys.GetFileList(Path: string; Mask: string; var List: TStringList; IsPathAdd: Boolean);
 var
        rc: Integer;
        SearchRec : TSearchRec;
-       s: string;
 begin
        Path := IncludeTrailingPathDelimiter(Path);
        rc := FindFirst(Path + Mask, faAnyfile, SearchRec);
        try
                while rc = 0 do begin
                        if (SearchRec.Name <> '..') and (SearchRec.Name <> '.') then begin
-                               s := Path + SearchRec.Name;
-
-                               if (SearchRec.Attr and faDirectory = 0) then
-                                               if IsPathAdd then
-                                                       List.Add(s)
-                                               else
-                                                       List.Add(SearchRec.Name);
+                               if (SearchRec.Attr and faDirectory = 0) then begin
+                    if IsPathAdd then begin
+                        List.Add(Path + SearchRec.Name)
+                    end else begin
+                        List.Add(SearchRec.Name);
+                    end;
+                end;
                        end;
                        rc := FindNext(SearchRec);
                end;
@@ -1003,7 +1057,22 @@ begin
        end;
        List.Sort;
 end;
-//\8ew\92è\83t\83H\83\8b\83_\93à\82Ì\83f\83B\83\8c\83N\83g\83\8a\88ê\97\97\82ð\8eæ\93¾\82·\82é
+
+{!
+\brief \8ew\92è\83t\83H\83\8b\83_\93à\82Ì\83f\83B\83\8c\83N\83g\83\8a\88ê\97\97\82ð\8eæ\93¾\82·\82é
+\param Path      \8bN\93_\82Æ\82È\82é\83t\83H\83\8b\83_\83p\83X
+\param Mask      \83t\83H\83\8b\83_\96¼\82Ì\83}\83X\83N
+\param List      OUT:\8eæ\93¾\82³\82ê\82½\83t\83H\83\8b\83_\96¼\88ê\97\97\82ª\95Ô\82é
+\param SubDir    \92\86\82Ì\83t\83H\83\8b\83_\82Ü\82Å\8dÄ\8bA\93I\82É\83\8a\83X\83g\82·\82é\8fê\8d\87\82Í True
+
+Mask \82ð '*.txt' \82Ì\82æ\82¤\82É\8ew\92è\82·\82é\82±\82Æ\82Å\81A
+\93Á\92è\82Ì\83t\83@\83C\83\8b\96¼\82â\93Á\92è\82Ì\8ag\92£\8eq\82É\8di\82Á\82½\83\8a\83X\83g\83A\83b\83v\82ª\89Â\94\\82Å\82·\81B
+
+\par \97á:
+\code
+GetDirectoryList('c:\', '*.txt', list, True);
+\endcode
+}
 procedure TGikoSys.GetDirectoryList(Path: string; Mask: string; List: TStringList; SubDir: Boolean);
 var
        rc: Integer;
@@ -1032,9 +1101,11 @@ begin
 end;
 
 
-(*************************************************************************
- *\83T\83u\83W\83F\83N\83g\88ê\8ds\82ð\95ª\8a\84
- *************************************************************************)
+{!
+\brief Subject.txt \88ê\8ds\82ð\89ð\8eß
+\param Line Subject.txt \82ð\8d\\90¬\82·\82é 1 \8ds
+\return     \83X\83\8c\83b\83h\8fî\95ñ
+}
 function TGikoSys.DivideSubject(Line: string): TSubjectRec;
 var
        i: integer;
@@ -1049,8 +1120,8 @@ begin
                Delim := ','
        else
                Delim := '<>';
-       Result.FFileName := RemoveToken(Line, Delim);
-       Result.FTitle := Trim(RemoveToken(Line, Delim));
+       Result.FFileName := MojuUtils.RemoveToken(Line, Delim);
+       Result.FTitle := Trim(MojuUtils.RemoveToken(Line, Delim));
 
        ws := Result.FTitle;
        if Copy(ws, Length(ws), 1) = ')' then begin
@@ -1075,43 +1146,11 @@ begin
        end;
 end;
 
-(*************************************************************************
- * dat\83t\83@\83C\83\8b\82Ì\88ê\83\89\83C\83\93\82ð\95ª\89ð
- *************************************************************************)
-function TGikoSys.DivideStrLine(Line: string): TResRec;
-var
-       Delim: string;
-begin
-       if AnsiPos('<>', Line) = 0 then begin
-               //Delim := ',';
-               //Result.FType := glt2chOld;
-        Line := CustomStringReplace(Line, '<>', '&lt;&gt;');
-               Line := CustomStringReplace(Line, ',', '<>');
-               Line := CustomStringReplace(Line, '\81\97\81M', ',');
-       end;
-       Delim := '<>';
-       Result.FType := glt2chNew;
-       //Trim\82µ\82Ä\82Í\82¢\82¯\82È\82¢\8bC\82ª\82·\82é\81@by\82à\82\82ã
-       Result.FName := RemoveToken(Line, Delim);
-       Result.FMailTo := RemoveToken(Line, Delim);
-       Result.FDateTime := RemoveToken(Line, Delim);
-       Result.FBody := RemoveToken(Line, Delim);
-       //\8bó\82¾\82Æ\96â\91è\82ª\8bN\82«\82é\82©\82ç\81A\8bó\94\92\82ð\90Ý\92è\82·\82é
-       if Result.FBody = '' then begin
-               Result.FBody := '&nbsp;';
-       end else if ( Result.FBody[1] = ' ' ) then begin
-               //\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é
-               Delete(Result.FBody, 1, 1);
-       end;
-       //Result.FTitle := Trim(RemoveToken(Line, Delim));
-       Result.FTitle := RemoveToken(Line, Delim);
-
-end;
-
-(*************************************************************************
- * URL\82©\82çBBSID\82ð\8eæ\93¾
- *************************************************************************)
+{!
+\brief URL\82©\82çBBSID\82ð\8eæ\93¾
+\param url BBSID \82ð\8eæ\93¾\82·\82é URL
+\return    BBSID
+}
 function TGikoSys.UrlToID(url: string): string;
 var
        i: integer;
@@ -1133,9 +1172,13 @@ begin
        end;
 end;
 
-(*************************************************************************
- *URL\82©\82çBBSID\88È\8aO\82Ì\95\94\95ª(http://teri.2ch.net/)\82ð\8eæ\93¾
- *************************************************************************)
+{!
+\brief URL\82©\82ç\8dÅ\8cã\82Ì\97v\91f\82ð\8dí\8f\9c
+\param url \89ð\8eß\82·\82é URL
+\return    \90Ø\82è\8eæ\82ç\82ê\82½\8cã\82Ì URL
+
+URL \82©\82ç BBSID\88È\8aO\82Ì\95\94\95ª\82ð\8eæ\93¾\82·\82é\82Ì\82É\8eg\97p\82µ\82Ü\82·\81B
+}
 function TGikoSys.UrlToServer(url: string): string;
 var
        i: integer;
@@ -1158,20 +1201,24 @@ begin
        end;
 end;
 
-(*************************************************************************
- *\83f\83B\83\8c\83N\83g\83\8a\82ª\91\8dÝ\82·\82é\82©\83`\83F\83b\83N
- *************************************************************************)
+{!
+\brief \83f\83B\83\8c\83N\83g\83\8a\82ª\91\8dÝ\82·\82é\82©\83`\83F\83b\83N
+\param Name \91\8dÝ\82ð\8am\94F\82·\82é\83t\83H\83\8b\83_\83p\83X
+\return     \83t\83H\83\8b\83_\82ª\91\8dÝ\82·\82é\82È\82ç True
+}
 function TGikoSys.DirectoryExistsEx(const Name: string): Boolean;
 var
-       Code: Integer;
+       Code: Cardinal;
 begin
        Code := GetFileAttributes(PChar(Name));
-       Result := (Code <> -1) and (FILE_ATTRIBUTE_DIRECTORY and Code <> 0);
+       Result := (Code <> Cardinal(-1)) and (FILE_ATTRIBUTE_DIRECTORY and Code <> 0);
 end;
 
-(*************************************************************************
- *\83f\83B\83\8c\83N\83g\83\8a\8dì\90¬\81i\95¡\90\94\8aK\91w\91Î\89\9e\81j
- *************************************************************************)
+{!
+\brief \83f\83B\83\8c\83N\83g\83\8a\8dì\90¬\81i\95¡\90\94\8aK\91w\91Î\89\9e\81j
+\param Dir \8dì\90¬\82·\82é\83p\83X
+\return    \8dì\90¬\82É\90¬\8c÷\82µ\82½\8fê\8d\87\82Í True
+}
 function TGikoSys.ForceDirectoriesEx(Dir: string): Boolean;
 begin
        Result := True;
@@ -1183,10 +1230,15 @@ begin
        Result := ForceDirectoriesEx(ExtractFilePath(Dir)) and CreateDir(Dir);
 end;
 
-(*************************************************************************
- *\95\8e\9a\97ñ\82©\82ç\83g\81[\83N\83\93\82Ì\90Ø\82è\8fo\82µ\81i\8f\89\8aú\8f\88\97\9d\81j
- *FDelphi\82©\82ç\82Ì\83p\83N\83\8a
- *************************************************************************)
+{!
+\brief \95\8e\9a\97ñ\82©\82ç\83g\81[\83N\83\93\82Ì\90Ø\82è\8fo\82µ\81i\8f\89\8aú\8f\88\97\9d\81j
+                        FDelphi\82©\82ç\82Ì\83p\83N\83\8a
+\param s   \8c³\82É\82È\82é\83L\83\83\83\89\83N\83^
+\param sep \8bæ\90Ø\82è\82É\82È\82é\95\8e\9a\97ñ
+\param Rec OUT:\95\8e\9a\97ñ\91\96\8d¸\8fî\95ñ\82ª\95Ô\82é
+\return    \90Ø\82è\8fo\82µ\82½\83g\81[\83N\83\93
+\todo Split, RemoveToken, GetTokenIndex, NthField \8ds\82«
+}
 function TGikoSys.StrTokFirst(const s:string; const sep: TStrTokSeparator; var Rec: TStrTokRec): string;
 begin
        Rec.Str := s;
@@ -1194,10 +1246,14 @@ begin
        Result := StrTokNext(sep, Rec);
 end;
 
-(*************************************************************************
- *\95\8e\9a\97ñ\82©\82ç\83g\81[\83N\83\93\82Ì\90Ø\82è\8fo\82µ
- *FDelphi\82©\82ç\82Ì\83p\83N\83\8a
- *************************************************************************)
+{!
+\brief \95\8e\9a\97ñ\82©\82ç\83g\81[\83N\83\93\82Ì\90Ø\82è\8fo\82µ
+                        FDelphi\82©\82ç\82Ì\83p\83N\83\8a
+\param sep \8bæ\90Ø\82è\82É\82È\82é\83L\83\83\83\89\83N\83^
+\param Rec IN/OUT:StrTokFirst\82Å\8dì\90¬\82³\82ê\82½\95\8e\9a\97ñ\91\96\8d¸\8fî\95ñ
+\return    \90Ø\82è\8fo\82µ\82½\83g\81[\83N\83\93
+\todo Split, RemoveToken, GetTokenIndex, NthField \8ds\82«
+}
 function TGikoSys.StrTokNext(const sep: TStrTokSeparator; var Rec: TStrTokRec): string;
 var
        Len, I: Integer;
@@ -1224,9 +1280,11 @@ begin
        end;
 end;
 
-(*************************************************************************
- *\83t\83@\83C\83\8b\83T\83C\83Y\8eæ\93¾
- *************************************************************************)
+{!
+\brief \83t\83@\83C\83\8b\83T\83C\83Y\8eæ\93¾
+\param FileName \83t\83@\83C\83\8b\83T\83C\83Y\82ð\8eæ\93¾\82·\82é\83t\83@\83C\83\8b\83p\83X
+\return         \83t\83@\83C\83\8b\83T\83C\83Y(bytes)
+}
 function TGikoSys.GetFileSize(FileName : string): longint;
 var
        F : File;
@@ -1245,9 +1303,12 @@ begin
        end;
 end;
 
-(*************************************************************************
- *\83t\83@\83C\83\8b\8ds\90\94\8eæ\93¾
- *************************************************************************)
+{!
+\brief \83e\83L\83X\83g\83t\83@\83C\83\8b\82Ì\8ds\90\94\82ð\8eæ\93¾
+\param FileName \8ds\90\94\82ð\8eæ\93¾\82·\82é\83t\83@\83C\83\8b\83p\83X
+\return         \8ds\90\94
+\todo \83\81\83\82\83\8a\83}\83b\83v\83h\83t\83@\83C\83\8b\8ds\82«
+}
 function TGikoSys.GetFileLineCount(FileName : string): longint;
 var
        sl: TStringList;
@@ -1266,9 +1327,13 @@ begin
 
 end;
 
-(*************************************************************************
- *\83X\83\8c\83b\83h\83t\83@\83C\83\8b\82©\82ç\8ew\92è\8ds\82ð\8eæ\93¾
- *************************************************************************)
+{!
+\brief \83t\83@\83C\83\8b\82©\82ç\8ew\92è\8ds\82ð\8eæ\93¾
+\param FileName \83t\83@\83C\83\8b\82Ì\83p\83X
+\param Line     \8ew\92è\8ds
+\return         \8ew\92è\82³\82ê\82½ 1 \8ds
+\todo \83\81\83\82\83\8a\83}\83b\83v\83h\83t\83@\83C\83\8b\8ds\82«
+}
 function TGikoSys.ReadThreadFile(FileName: string; Line: Integer): string;
 var
        fileTmp : TStringList;
@@ -1291,33 +1356,36 @@ begin
        end;
 end;
 
-(*************************************************************************
- *\83V\83X\83e\83\80\83\81\83j\83\85\81[\83t\83H\83\93\83g\82Ì\91®\90«\82ð\8eæ\93¾
- *************************************************************************)
+{!
+\brief \83V\83X\83e\83\80\83\81\83j\83\85\81[\83t\83H\83\93\83g\82Ì\91®\90«\82ð\8eæ\93¾
+\param Font OUT:\8eæ\93¾\82µ\82½\83t\83H\83\93\83g\91®\90«\82ª\95Ô\82é
+}
 procedure TGikoSys.MenuFont(Font: TFont);
 var
        lf: LOGFONT;
        nm: NONCLIENTMETRICS;
 begin
        nm.cbSize := sizeof(NONCLIENTMETRICS);
-
-       SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, @nm, 0);
-       lf := nm.lfMenuFont;
-
-       Font.Name := lf.lfFaceName;
-       Font.Height := lf.lfHeight;
-       Font.Style := [];
-       if lf.lfWeight >= 700 then
-               Font.Style := Font.Style + [fsBold];
-       if lf.lfItalic = 1 then
-               Font.Style := Font.Style + [fsItalic];
-end;
-
-(*************************************************************************
- *
- *\82Ç\82±\82©\82Ì\83T\83C\83g\82©\82ç\82Ì\83p\83N\83\8a
- *************************************************************************)
-function TGikoSys.RemoveToken(var s: string;const delimiter: string): string;
+    SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, @nm, 0);
+    lf := nm.lfMenuFont;
+    Font.Name := lf.lfFaceName;
+    Font.Height := lf.lfHeight;
+    Font.Style := [];
+    if lf.lfWeight >= 700 then
+        Font.Style := Font.Style + [fsBold];
+    if lf.lfItalic = 1 then
+        Font.Style := Font.Style + [fsItalic];
+end;
+
+{!
+\brief \90æ\93ª\82Ì\83g\81[\83N\83\93\82ð\90Ø\82è\8fo\82µ
+\param s         IN/OUT:\8c³\82É\82È\82é\95\8e\9a\97ñ\81A\90Ø\82è\8fo\82µ\82½\8cã\82Ì\8ec\82è\82Ì\95\8e\9a\97ñ
+\param delimiter \8bæ\90Ø\82è\82É\82È\82é\95\8e\9a\97ñ
+\return          \90Ø\82è\8fo\82µ\82½\95\8e\9a\97ñ
+
+\82Ç\82±\82©\82Ì\83T\83C\83g\82©\82ç\82Ì\83p\83N\83\8a
+}
+{function TGikoSys.RemoveToken(var s: string;const delimiter: string): string;
 var
        p: Integer;
 begin
@@ -1328,51 +1396,25 @@ begin
                Result := Copy(s, 1, p - 1);
        Delete(s, 1, Length(Result) + Length(delimiter));
 end;
+}
+
+{!
+\brief n \8cÂ\96Ú\82Ì\83g\81[\83N\83\93\82ð\90Ø\82è\8fo\82µ
+\param s     \8c³\82É\82È\82é\95\8e\9a\97ñ
+\param index 0 \82©\82ç\8en\82Ü\82é\83C\83\93\83f\83b\83N\83X(n \8cÂ\96Ú\82Ì n)
+\return \90Ø\82è\8fo\82µ\82½\83g\81[\83N\83\93
 
-(*************************************************************************
- *
- *\82Ç\82±\82©\82Ì\83T\83C\83g\82©\82ç\82Ì\83p\83N\83\8a
- *************************************************************************)
+\82Ç\82±\82©\82Ì\83T\83C\83g\82©\82ç\82Ì\83p\83N\83\8a
+}
 function TGikoSys.GetTokenIndex(s: string; delimiter: string; index: Integer): string;
 var
        i: Integer;
 begin
        Result := '';
        for i := 0 to index do
-               Result := RemoveToken(s, delimiter);
+               Result := MojuUtils.RemoveToken(s, delimiter);
 end;
 
-(*************************************************************************
- *
- *************************************************************************)
-function TGikoSys.DeleteLink(const s: string): string;
-var
-       s1: string;
-       s2: string;
-       idx: Integer;
-       i: Integer;
-begin
-       i := 0;
-       Result := '';
-       while True do begin
-               s1 := GetTokenIndex(s, '<a href="', i);
-               s2 := 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;
 
 //\83C\83\93\83f\83b\83N\83X\96¢\8dX\90V\83o\83b\83t\83@\82ð\83t\83\89\83b\83V\83\85\81I
 {procedure TGikoSys.FlashExitWrite;
@@ -1385,10 +1427,14 @@ begin
        FExitWrite.Clear;
 end;}
 
-(*************************************************************************
- *\83X\83\8c\96¼\82È\82Ç\82ð\92Z\82¢\96¼\91O\82É\95Ï\8a·\82·\82é
- *from HotZonu
- *************************************************************************)
+{!
+\brief \83X\83\8c\96¼\82È\82Ç\82ð\92Z\82¢\96¼\91O\82É\95Ï\8a·\82·\82é
+\param LongName \8c³\82É\82È\82é\95\8e\9a\97ñ
+\param ALength  \8eû\82ß\82é\95\8e\9a\97ñ\92·(bytes)
+\return         \95Ï\8a·\82³\82ê\82½\95\8e\9a\97ñ
+
+from HotZonu
+}
 function TGikoSys.GetShortName(const LongName: string; ALength: integer): string;
 const
        ERASECHAR : array [1..39] of string =
@@ -1401,7 +1447,7 @@ var
        S : string;
        i : integer;
 begin
-       s := Trim(LongName);
+    s := TrimThreadTitle(Trim(LongName));
        if (Length(s) <= ALength) then begin
                Result := s;
        end else begin
@@ -1434,404 +1480,59 @@ begin
        end;
 end;
 
-(*************************************************************************
- *
- * from HotZonu
- *************************************************************************)
-function TGikoSys.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;
-       end;
-const
-       GT      = '&gt;';
-       SN      = '0123456789-';
-       ZN      = '\82O\82P\82Q\82R\82S\82T\82U\82V\82W\82X\81|';
-var
-       i : integer;
-       s,r : string;
-       b : TMbcsByteType;
-       sw: boolean;
-       sp: integer;
-       No: string;
-       sx: string;
-       List: TList;
-       oc      : string;
-       st, et: string;
-       chk : boolean;
-       al : boolean;
-       procedure Add(IndexFrom, IndexTo: integer; const No: string);
-       var
-               FIndex : PIndex;
-       begin
-               New(FIndex);
-               FIndex.FIndexFrom       := IndexFrom;
-               FIndex.FIndexTo         := IndexTo;
-               FIndex.FNo                               := No;
-               List.Add(FIndex);
-       end;
-       function ChooseString(const Text, Separator: string; Index: integer): string;
-       var
-               S : string;
-               i, p : integer;
-       begin
-               S :=    Text;
-               for i :=        0 to    Index - 1 do    begin
-                       if      (AnsiPos(Separator, S) = 0) then        S :=    ''
-                       else    S :=    Copy(S, AnsiPos(Separator, S) + Length(Separator), Length(S));
-               end;
-               p :=    AnsiPos(Separator, S);
-               if      (p > 0) then    Result  :=      Copy(S, 1, p - 1) else Result :=        S;
-       end;
-begin
-       { v1.0 b2 - 03 }
-       s        :=     Body;
-       r        :=     Body;
-       i        :=     1;
-       sw      :=      False;
-       No      :=      '';
-       List:=  TList.Create;
-       oc      :=      '';
-       sp      :=      0;
-       chk :=  False;
-       al      :=      False;
-       while true      do      begin
-               b :=    ByteType(s, i);
-               case    b of
-                       mbSingleByte    : begin
-                               if      (not sw) and (Copy(s,i,8) = GT + GT) then       begin
-                                       if      (AnsiPos('<A HREF', AnsiUpperCase(oc)) = 0) then        begin
-                                               sw      :=      True;
-                                               sp      :=      i;
-                                               i :=    i + 7;
-                                               oc:='';
-                                               chk :=  True;
-                                       end;
-                               end else
-                               if      (not sw) and (Copy(s,i,8) = GT + GT) then       begin
-                                       if      (AnsiPos('<A HREF', AnsiUpperCase(oc)) = 1) then        begin
-                                               i :=    i + 7;
-                                               oc:='';
-                                               chk :=  True;
-                                       end;
-                               end else
-                               if      (not sw) and (Copy(s,i,4) = GT) then    begin
-                                       if      (AnsiPos('<A HREF', AnsiUpperCase(oc)) = 0) then        begin
-                                               sw      :=      True;
-                                               sp      :=      i;
-                                               i :=    i + 3;
-                                               oc:='';
-                                               chk :=  True;
-                                       end;
-                               end else
-                               if      ((not sw) and (Copy(s,i,1) = ',')) or
-                                               ((not sw) and (Copy(s,i,1) = '=')) then begin
-                                       if      ((not Chk) and (AnsiLowerCase(oc) = '</a>')) or
-                                                       ((Chk) and      (oc = '')) or
-                                                       ((not Chk) and (al)) then
-                                       begin
-                                               sw      :=      True;
-                                               sp      :=      i;
-                                               //i :=  i + 1;
-                                               oc:='';
-                                       end;
-                               end else
-                               if      (sw) then begin
-                                       sx      :=      Copy(s,i,1);
-                                       if      (AnsiPos(sx, SN) > 0)   then    begin
-                                               No      :=      No      + sx;
-                                       end else begin
-                                               if      (No <> '') and (No <> '-')       then   begin
-                                                       Add(sp, i, No);
-                                                       al := True;
-                                               end;
-                                               sw      :=      False;
-                                               //
-                                               i := i - 1;
-                                               //
-                                               No      := '';
-                                               oc:='';
-                                               //chk :=        False;
-                                       end;
-                               end else begin
-                                       if      Copy(s,i,1) = '<' then  oc      :=      '';
-                                       oc      :=      oc + Copy(s,i,1);
-                                       chk :=  False;
-                                       al      :=      False;
-                               end;
-                       end;
-                       mbLeadByte      : begin
-                               if      (not sw) and (Copy(s,i,4) = '\81\84\81\84') then        begin
-                                       sw      :=      True;
-                                       sp      :=      i;
-                                       i :=    i + 3;
-                                       chk :=  True;
-                               end else
-                               if      (not sw) and (Copy(s,i,2) = '\81\84') then  begin
-                                       sw      :=      True;
-                                       sp      :=      i;
-                                       i :=    i + 1;
-                                       chk :=  True;
-                               end else
-                               if      (sw) then begin
-                                       sx      :=      Copy(s,i,2);
-                                       if      (AnsiPos(sx, ZN) > 0)   then    begin
-                                               No      :=      No      + ZenToHan(sx);
-                                       end else begin
-                                               if      (No <> '') and (No <> '-')      and (No <> '\81|') then   begin
-                                                       Add(sp, i, No);
-                                               end;
-                                               sw      :=      False;
-                                               i := i - 1;
-                                               No      :=      '';
-                                       end;
-                               end else begin
-                                       oc      :=      '';
-                                       chk :=  False;
-                               end;
-                               al      :=      False;
-                       end;
-               end;
-               inc(i);
-               if      (i > Length(Body))      then    begin
-                       if      (sw)    then    begin
-                               if      (No <> '')      then    Add(sp, i, No);
-                       end;
-                       Break;
-               end;
-       end;
-       for i :=        List.Count - 1  downto  0 do    begin
-               if      (AnsiPos('-', PIndex(List[i]).FNo) > 0) then    begin
-                       st      :=      ChooseString(PIndex(List[i]).FNo, '-', 0);
-                       et      :=      ChooseString(PIndex(List[i]).FNo, '-', 1);
-               end else begin
-                       st      :=      PIndex(List[i]).FNo;
-                       et      :=      PIndex(List[i]).FNo;
-               end;
-               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 TGikoSys.ConvRes(
-       const Body, Bbs, Key, ParamBBS, ParamKey,
-    ParamStart, ParamTo, ParamNoFirst,
-       ParamTrue, FullURL : string
-): string;
-type
-       PIndex = ^TIndex;
-       TIndex = record
-               FIndexFrom      : integer;
-               FIndexTo                : integer;
-               FNo                              : string;
-       end;
+function TGikoSys.TrimThreadTitle(const SrcTitle: string): string;
 const
-       GT      = '&gt;';
-       SN      = '0123456789-';
-       ZN      = '\82O\82P\82Q\82R\82S\82T\82U\82V\82W\82X\81|';
+    TRIM_STRING: array [1..4] of String =
+        ('[\93]\8dÚ\8bÖ\8e~]', '&copy;2ch.net', '&copy;bbspink.com', #9);
 var
-       i : integer;
-       s,r : string;
-       b : TMbcsByteType;
-       sw: boolean;
-       sp: integer;
-       No: string;
-       sx: string;
-       List: TList;
-       oc      : string;
-       st, et: string;
-       chk : boolean;
-       al : boolean;
-       procedure Add(IndexFrom, IndexTo: integer; const No: string);
-       var
-               FIndex : PIndex;
-       begin
-               New(FIndex);
-               FIndex.FIndexFrom       := IndexFrom;
-               FIndex.FIndexTo         := IndexTo;
-               FIndex.FNo                               := No;
-               List.Add(FIndex);
-       end;
-       function ChooseString(const Text, Separator: string; Index: integer): string;
-       var
-               S : string;
-               i, p : integer;
-       begin
-               S :=    Text;
-               for i :=        0 to    Index - 1 do    begin
-                       if      (AnsiPos(Separator, S) = 0) then        S :=    ''
-                       else    S :=    Copy(S, AnsiPos(Separator, S) + Length(Separator), Length(S));
-               end;
-               p :=    AnsiPos(Separator, S);
-               if      (p > 0) then    Result  :=      Copy(S, 1, p - 1) else Result :=        S;
-       end;
-begin
-       { v1.0 b2 - 03 }
-       s        :=     Body;
-       r        :=     Body;
-       i        :=     1;
-       sw      :=      False;
-       No      :=      '';
-       List:=  TList.Create;
-       oc      :=      '';
-       sp      :=      0;
-       chk :=  False;
-       al      :=      False;
-       while true      do      begin
-               b :=    ByteType(s, i);
-               case    b of
-                       mbSingleByte    : begin
-                               if      (not sw) and (Copy(s,i,8) = GT + GT) then       begin
-                                       if      (AnsiPos('<A HREF', AnsiUpperCase(oc)) = 0) then        begin
-                                               sw      :=      True;
-                                               sp      :=      i;
-                                               i :=    i + 7;
-                                               oc:='';
-                                               chk :=  True;
-                                       end;
-                               end else
-                               if      (not sw) and (Copy(s,i,8) = GT + GT) then       begin
-                                       if      (AnsiPos('<A HREF', AnsiUpperCase(oc)) = 1) then        begin
-                                               i :=    i + 7;
-                                               oc:='';
-                                               chk :=  True;
-                                       end;
-                               end else
-                               if      (not sw) and (Copy(s,i,4) = GT) then    begin
-                                       if      (AnsiPos('<A HREF', AnsiUpperCase(oc)) = 0) then        begin
-                                               sw      :=      True;
-                                               sp      :=      i;
-                                               i :=    i + 3;
-                                               oc:='';
-                                               chk :=  True;
-                                       end;
-                               end else
-                               if      ((not sw) and (Copy(s,i,1) = ',')) or
-                                               ((not sw) and (Copy(s,i,1) = '=')) then begin
-                                       if      ((not Chk) and (AnsiLowerCase(oc) = '</a>')) or
-                                                       ((Chk) and      (oc = '')) or
-                                                       ((not Chk) and (al)) then
-                                       begin
-                                               sw      :=      True;
-                                               sp      :=      i;
-                                               //i :=  i + 1;
-                                               oc:='';
-                                       end;
-                               end else
-                               if      (sw) then begin
-                                       sx      :=      Copy(s,i,1);
-                                       if      (AnsiPos(sx, SN) > 0)   then    begin
-                                               No      :=      No      + sx;
-                                       end else begin
-                                               if      (No <> '') and (No <> '-')       then   begin
-                                                       Add(sp, i, No);
-                                                       al := True;
-                                               end;
-                                               sw      :=      False;
-                                               //
-                                               i := i - 1;
-                                               //
-                                               No      := '';
-                                               oc:='';
-                                               //chk :=        False;
-                                       end;
-                               end else begin
-                                       if      Copy(s,i,1) = '<' then  oc      :=      '';
-                                       oc      :=      oc + Copy(s,i,1);
-                                       chk :=  False;
-                                       al      :=      False;
-                               end;
-                       end;
-                       mbLeadByte      : begin
-                               if      (not sw) and (Copy(s,i,4) = '\81\84\81\84') then        begin
-                                       sw      :=      True;
-                                       sp      :=      i;
-                                       i :=    i + 3;
-                                       chk :=  True;
-                               end else
-                               if      (not sw) and (Copy(s,i,2) = '\81\84') then  begin
-                                       sw      :=      True;
-                                       sp      :=      i;
-                                       i :=    i + 1;
-                                       chk :=  True;
-                               end else
-                               if      (sw) then begin
-                                       sx      :=      Copy(s,i,2);
-                                       if      (AnsiPos(sx, ZN) > 0)   then    begin
-                                               No      :=      No      + ZenToHan(sx);
-                                       end else begin
-                                               if      (No <> '') and (No <> '-')      and (No <> '\81|') then   begin
-                                                       Add(sp, i, No);
-                                               end;
-                                               sw      :=      False;
-                                               i := i - 1;
-                                               No      :=      '';
-                                       end;
-                               end else begin
-                                       oc      :=      '';
-                                       chk :=  False;
-                               end;
-                               al      :=      False;
-                       end;
-               end;
-               inc(i);
-               if      (i > Length(Body))      then    begin
-                       if      (sw)    then    begin
-                               if      (No <> '')      then    Add(sp, i, No);
-                       end;
-                       Break;
-               end;
-       end;
-       for i :=        List.Count - 1  downto  0 do    begin
-        //plName := Copy(PluginName, LastDelimiter('\',PluginName) + 1, Length(PluginName) - LastDelimiter('/',PluginName) -1 );
-               if      (AnsiPos('-', PIndex(List[i]).FNo) > 0) then    begin
-                       st      :=      ChooseString(PIndex(List[i]).FNo, '-', 0);
-                       et      :=      ChooseString(PIndex(List[i]).FNo, '-', 1);
-               end else begin
-                       st      :=      PIndex(List[i]).FNo;
-                       et      :=      PIndex(List[i]).FNo;
-               end;
-               r :=    Copy(r,0, PIndex(List[i]).FIndexFrom - 1) +
-                                       Format('<a href="%s&%s=%s&%s=%s&%s=%s" target="_blank">',
-                                                               [FullURL, ParamStart, st, ParamTo, et, ParamNoFirst, ParamTrue]) +
-                                       Copy(r,PIndex(List[i]).FIndexFrom, PIndex(List[i]).FIndexTo - PIndex(List[i]).FIndexFrom) + '</A>' +
-                                       Copy(r,PIndex(List[i]).FIndexTo,Length(r));
-               Dispose(PIndex(List[i]));
-       end;
-       List.Free;
-       Result  :=      r;
+    i: Integer;
+    Idx: Integer;
+    Len: Integer;
+    DstTitle: String;
+begin
+    if (Setting.ThreadTitleTrim = True) then begin
+        DstTitle := SrcTitle;
+               for i := Low(TRIM_STRING) to High(TRIM_STRING) do begin
+            Len := Length(TRIM_STRING[i]);
+            while (True) do begin
+                Idx := Pos(TRIM_STRING[i], DstTitle);
+                if (Idx < 1) then
+                    Break;
+                Delete(DstTitle, Idx, Len);
+            end;
+        end;
+        Result := Trim(DstTitle);
+    end else begin
+        Result := SrcTitle;
+    end;
 end;
 
-
+{!
+\brief Boolean \82ð Integer \82É\95Ï\8a·
+\return False..0, True..1
+}
 function TGikoSys.BoolToInt(b: Boolean): Integer;
 begin
        Result := IfThen(b, 1, 0);
 end;
 
+{!
+\brief Integer \82ð Boolean \82É\95Ï\8a·
+\return 1..True, other..False
+\todo 0..False, other..True \82Ì\95û\82ª\82¢\82¢\82Ì\82Å\82Í?
+                       (\82±\82Ì\8ed\97l\82É\88Ë\91\82µ\82Ä\82¢\82é\82©\82à\82µ\82ê\82È\82¢\82Ì\82Å\96¢\8fC\90³)
+}
 function TGikoSys.IntToBool(i: Integer): Boolean;
 begin
        Result := i = 1;
 end;
 
-//gzip\82Å\88³\8fk\82³\82ê\82½\82Ì\82ð\96ß\82·
+{!
+\brief gzip\82Å\88³\8fk\82³\82ê\82½\82Ì\82ð\96ß\82·
+\param ResStream       \93Ç\82Ý\8d\9e\82Þ\83X\83g\83\8a\81[\83\80
+\param ContentEncoding \83G\83\93\83R\81[\83f\83B\83\93\83O
+\return                \93W\8aJ\82³\82ê\82½\95\8e\9a\97ñ
+}
 function TGikoSys.GzipDecompress(ResStream: TStream; ContentEncoding: string): string;
 const
        BUF_SIZE = 4096;
@@ -1841,7 +1542,7 @@ var
        buf: array[0..BUF_SIZE - 1] of Byte;
        cnt: Integer;
        s: string;
-       i: Integer;
+       i, ln: Integer;
 begin
        Result := '';
        TextStream := TStringStream.Create('');
@@ -1874,22 +1575,29 @@ begin
                //NULL\95\8e\9a\82ð"*"\82É\82·\82é
                s := TextStream.DataString;
                i := Length(s);
+               ln := i;
                while (i > 0) and (s[i] = #0) do
                        Dec(i);
-               s := Copy(s, 1, i);
+               Delete(s, i + 1, ln - i);
 
                i := Pos(#0, s);
                while i <> 0 do begin
                        s[i] := '*';
                        i := Pos(#0, s);
                end;
+
                Result := s;
        finally
                TextStream.Free;
        end;
 end;
 
-procedure TGikoSys.LoadKeySetting(ActionList: TActionList);
+{!
+\brief \83A\83N\83V\83\87\83\93\82É\83V\83\87\81[\83g\83J\83b\83g\83L\81[\82ð\90Ý\92è
+\param ActionList \90Ý\92è\82·\82é\83A\83N\83V\83\87\83\93\88ê\97\97
+\param FileName Ini\83t\83@\83C\83\8b\82Ì\96¼\91O
+}
+procedure TGikoSys.LoadKeySetting(ActionList: TActionList; FileName: String);
 const
        STD_SEC = 'KeySetting';
 var
@@ -1900,10 +1608,10 @@ var
        SecList: TStringList;
        Component: TComponent;
 begin
-       if not FileExists(GetConfigDir + KEY_SETTING_FILE_NAME) then
+       if not FileExists(fileName) then
                Exit;
        SecList := TStringList.Create;
-       ini := TMemIniFile.Create(GetConfigDir + KEY_SETTING_FILE_NAME);
+       ini := TMemIniFile.Create(fileName);
        try
                ini.ReadSection(STD_SEC, SecList);
                for i := 0 to SecList.Count - 1 do begin
@@ -1922,67 +1630,21 @@ begin
        end;
 end;
 
-procedure TGikoSys.SaveKeySetting(ActionList: TActionList);
-const
-       STD_SEC = 'KeySetting';
-var
-       i: Integer;
-       ini: TMemIniFile;
-begin
-       ini := TMemIniFile.Create(GetConfigDir + KEY_SETTING_FILE_NAME);
-       try
-               for i := 0 to ActionList.ActionCount - 1 do begin
-                       if ActionList.Actions[i].Tag = -1 then
-                               Continue;
-                       ini.WriteInteger(STD_SEC, ActionList.Actions[i].Name, TAction(ActionList.Actions[i]).ShortCut);
-               end;
-               ini.UpdateFile;
-       finally
-               ini.Free;
-       end;
-end;
-
-procedure TGikoSys.LoadEditorKeySetting(ActionList: TActionList);
-const
-       STD_SEC = 'KeySetting';
-var
-       i: Integer;
-       ini: TMemIniFile;
-       ActionName: string;
-       ActionKey: Integer;
-       SecList: TStringList;
-       Component: TComponent;
-begin
-       if not FileExists(GetConfigDir + EKEY_SETTING_FILE_NAME) then
-               Exit;
-       SecList := TStringList.Create;
-       ini := TMemIniFile.Create(GetConfigDir + EKEY_SETTING_FILE_NAME);
-       try
-               ini.ReadSection(STD_SEC, SecList);
-               for i := 0 to SecList.Count - 1 do begin
-                       ActionName := SecList[i];
-                       ActionKey := ini.ReadInteger(STD_SEC, ActionName, -1);
-                       if ActionKey <> -1 then begin
-                               Component := ActionList.Owner.FindComponent(ActionName);
-                               if TObject(Component) is TAction then begin
-                                       TAction(Component).ShortCut := ActionKey;
-                               end;
-                       end;
-               end;
-       finally
-               ini.Free;
-               SecList.Free;
-       end;
-end;
+{!
+\brief \83A\83N\83V\83\87\83\93\82É\90Ý\92è\82³\82ê\82Ä\82¢\82é\83V\83\87\81[\83g\83J\83b\83g\83L\81[\82ð\83t\83@\83C\83\8b\82É\95Û\91
+\param ActionList \95Û\91\82·\82é\83A\83N\83V\83\87\83\93\88ê\97\97
+\param FileName Ini\83t\83@\83C\83\8b\96¼
 
-procedure TGikoSys.SaveEditorKeySetting(ActionList: TActionList);
+ActionList \82É\90Ý\92è\82³\82ê\82Ä\82¢\82é\83V\83\87\81[\83g\83J\83b\83g\83L\81[\82ð FileName \82É\95Û\91\82µ\82Ü\82·\81B
+}
+procedure TGikoSys.SaveKeySetting(ActionList: TActionList; FileName: String);
 const
        STD_SEC = 'KeySetting';
 var
        i: Integer;
        ini: TMemIniFile;
 begin
-       ini := TMemIniFile.Create(GetConfigDir + EKEY_SETTING_FILE_NAME);
+       ini := TMemIniFile.Create(GetConfigDir + FileName);
        try
                for i := 0 to ActionList.ActionCount - 1 do begin
                        if ActionList.Actions[i].Tag = -1 then
@@ -1995,7 +1657,12 @@ begin
        end;
 end;
 
-//
+
+{!
+\brief \83v\83\8d\83Z\83X\82Ì\90\90¬
+\param AppPath \8bN\93®\82·\82é\83v\83\8d\83Z\83X\82Ì\83t\83@\83C\83\8b\83p\83X
+\param Param   AppPath \82É\93n\82·\88ø\90\94
+}
 procedure TGikoSys.CreateProcess(const AppPath: string; const Param: string);
 var
        PI: TProcessInformation;
@@ -2014,7 +1681,7 @@ begin
        SI.cbReserved2 := 0;
        SI.lpReserved2 := nil;
        SI.dwysize               := 0;
-       Windows.CreateProcess(nil,
+    if Windows.CreateProcess(nil,
                                                                PChar(Path),
                                                                nil,
                                                                nil,
@@ -2023,22 +1690,67 @@ begin
                                                                nil,
                                                                nil,
                                                                SI,
-                                                               PI);
+                                                               PI) then
+    begin
+        CloseHandle(PI.hProcess);
+    end;
+
 end;
 
+{!
+\brief Web \83u\83\89\83E\83U\82ð\8bN\93®
+\param URL         Web \83u\83\89\83E\83U\82Å\95\\8e¦\82·\82é URL
+\param BrowserType \83u\83\89\83E\83U\82Ì\83^\83C\83v(IE \82©\82Ç\82¤\82©)
+}
 procedure TGikoSys.OpenBrowser(URL: string; BrowserType: TGikoBrowserType);
+var
+    i, j : Integer;
+    path, arg : String;
+    params : TStringList;
 begin
        case BrowserType of
                gbtIE:
                        HlinkNavigateString(nil, PWideChar(WideString(URL)));
                gbtUserApp, gbtAuto:
-                       if (Setting.URLApp) and (FileExists(Setting.URLAppFile)) then
-                               GikoSys.CreateProcess(Setting.URLAppFile, URL)
-                       else
+                       if (Setting.URLApp) then begin
+                if (FileExists(Setting.URLAppFile)) then begin
+                               GikoSys.CreateProcess(Setting.URLAppFile, URL)
+                end else begin
+                    // \8bN\93®\83p\83\89\83\81\81[\83^\95t\82«\91Î\8dô
+                    path := '';
+                    params := TStringList.Create;
+                    try
+                        params.Delimiter := ' ';
+                        params.DelimitedText := Setting.URLAppFile;
+                        for i := 0 to params.Count - 1 do begin
+                            path := TrimLeft(path + ' ' + params[i]);
+                            if (FileExists(path)) then begin
+                                arg := '';
+                                for j := i + 1 to params.Count - 1 do begin
+                                    arg := arg + ' ' + params[j];
+                                end;
+                                break;
+                            end;
+                        end;
+                        if i < params.Count then begin
+                            GikoSys.CreateProcess(path, arg + ' ' + URL);
+                        end else begin
+                            HlinkNavigateString(nil, PWideChar(WideString(URL)));
+                        end;
+                    finally
+                        params.Free;
+                    end;
+                end;
+                       end else
                                HlinkNavigateString(nil, PWideChar(WideString(URL)));
        end;
 end;
 
+{!
+\brief \95\8e\9a\8eÀ\91Ì\8eQ\8fÆ\82ð\83f\83R\81[\83h
+\param AStr \83f\83R\81[\83h\82·\82é\95\8e\9a\97ñ
+\return     \83f\83R\81[\83h\82³\82ê\82½\95\8e\9a\97ñ
+}
 function TGikoSys.HTMLDecode(const AStr: String): String;
 var
        Sp, Rp, Cp, Tp: PChar;
@@ -2111,6 +1823,11 @@ begin
        SetLength(Result, Rp - PChar(Result));
 end;
 
+{!
+\brief HTML \82Ì\83A\83\93\83J\81[\83^\83O\82©\82ç URL \82ð\8eæ\93¾
+\param s URL \82ð\8eæ\93¾\82·\82é HTML
+\return  \8eæ\93¾\82µ\82½ URL
+}
 function TGikoSys.GetHRefText(s: string): string;
 var
        Index: Integer;
@@ -2154,10 +1871,14 @@ begin
        Result := Trim(s);
 end;
 
-//\83z\83X\83g\96¼\82ª\82Q\82\83\82\88\82©\82Ç\82¤\82©\83`\83F\83b\83N\82·\82é
+{!
+\brief \83z\83X\83g\96¼\82ª\82Q\82\83\82\88\82©\82Ç\82¤\82©\83`\83F\83b\83N\82·\82é
+\param Host \83`\83F\83b\83N\82·\82é\83z\83X\83g\96¼
+\return     2\82¿\82á\82ñ\82Ë\82é\82Ì\83z\83X\83g\96¼\82È\82ç True
+}
 function TGikoSys.Is2chHost(Host: string): Boolean;
 const
-       HOST_NAME: array[0..1] of string = ('2ch.net', 'bbspink.com');
+       HOST_NAME: array[0..1] of string = ('.2ch.net', '.bbspink.com');
 var
        i: Integer;
 //     Len: Integer;
@@ -2176,6 +1897,15 @@ begin
        end;
 end;
 
+{!
+\brief 2\82¿\82á\82ñ\82Ë\82é\8c`\8e®\82Ì URL \82ð\95ª\89ð
+\param url      2\82¿\82á\82ñ\82Ë\82é\8c`\8e®\82Ì URL
+\param path     test/read.cgi \82È\82Ç\82Ì\92\86\8aÔ\83p\83X(ParseURI \82©\82ç\93¾\82é)
+\param document index.html \82È\82Ç\82Ì\83h\83L\83\85\83\81\83\93\83g\96¼(ParseURI \82©\82ç\93¾\82é)
+\param BBSID    OUT:BBSID \82ª\95Ô\82é(ex. giko)
+\param BBSKey   OUT:\83X\83\8c\83b\83h\83L\81[\82ª\95Ô\82é(ex. 10000000000)
+\return 2\82¿\82á\82ñ\82Ë\82é\82Ì URL \82Æ\82µ\82Ä\95ª\89ð\82Å\82«\82½\82È\82ç True
+}
 function TGikoSys.Parse2chURL(const url: string; const path: string; const document: string; var BBSID: string; var BBSKey: string): Boolean;
 var
        Index: Integer;
@@ -2189,7 +1919,13 @@ begin
        Index := AnsiPos(READ_PATH, path);
        if Index <> 0 then begin
                s := Copy(path, Index + Length(READ_PATH), Length(path));
-
+    end else begin
+        Index := AnsiPos(HTML_READ_PATH, path);
+        if Index <> 0 then begin
+            s := Copy(path, Index + Length(HTML_READ_PATH), Length(path));
+        end;
+    end;
+    if Index <> 0 then begin
                if (Length(s) > 0) and (s[1] = '/') then
                        Delete(s, 1, 1);
                BBSID := GetTokenIndex(s, '/', 0);
@@ -2228,85 +1964,104 @@ begin
                end;
        end;
 end;
+
+{!
+\brief 2ch \8c`\8e®\82Ì URL \82©\82ç\83\8c\83X\94Ô\82ð\8eæ\93¾
+\param URL    2\82¿\82á\82ñ\82Ë\82é\8c`\8e®\82Ì URL
+\param stRes  OUT:\8aJ\8en\83\8c\83X\94Ô\82ª\95Ô\82é
+\param endRes OUT:\8fI\97¹\83\8c\83X\94Ô\82ª\95Ô\82é
+
+http://2ch.net/\92\86\97ª/32-50 \n
+\82Ì\8fê\8d\87 stRef = 32, endRes = 50 \82É\82È\82é
+}
 procedure TGikoSys.GetPopupResNumber(URL : string; var stRes, endRes : Int64);
+const
+    START_NAME : array[0..1] of String = ('st=', 'start=');
+    END_NAME : array[0..1] of String = ('to=', 'end=');
+    RES_NAME : array[0..0] of String = ('res=');
 var
        buf : String;
        convBuf : String;
        ps : Int64;
        pch : PChar;
+    bufList : TStringList;
+    i, j, idx : Integer;
 begin
        URL := Trim(LowerCase(URL));
-       if (AnsiPos('&st=', URL ) <> 0) and ( AnsiPos( '&to=',URL) <> 0 ) then begin
-               stRes := 0;
-               endRes := 0;
-               try
-                       buf := Copy( URL, AnsiPos('&st=', URL ) + 4, AnsiPos( '&to=',URL) - AnsiPos('&st=', URL ) - 4 );
-                       if buf <> '' then
-                               stRes := StrToInt64( buf );
-                       if AnsiPos( '&nofirst=',URL) <> 0 then begin
-                               buf := Copy( URL, AnsiPos('&to=', URL ) + 4, AnsiPos( '&nofirst=',URL) - AnsiPos('&to=', URL ) - 4);
-                       end else begin
-                               buf := Copy( URL, AnsiPos('&to=', URL ) + 4, Length( URL ) - AnsiPos('&to=', URL ) - 4 + 1 );
-                               ps := 0;
-                               pch := PChar(buf);
-                               while  ( ps < Length(buf) )and ( pch[ps] >= '0' ) and ( pch[ps] <= '9' ) do Inc(ps);
-                               buf := Copy( buf, 1, ps );
-                       end;
-                       try
-                               if buf <> '' then
-                                       endRes := StrToInt64(buf)
-                       except
-                               endRes := 0;
-                       end;
-               except
-                       stRes := 0;
-               end;
-               if (stRes <> 0) and (endRes = 0) then
-                       endRes := stRes + MAX_POPUP_RES
-               else if (stRes = 0) and (endRes <> 0) then begin
-                       stRes := endRes - MAX_POPUP_RES;
-                       if stRes < 1 then
-                               stRes := 1;
-               end;
-               GikoSys.GetBrowsableThreadURL( URL );
-       end else if( AnsiPos('&res=', URL ) <> 0 ) then begin
-               endRes := 0;
-               buf := Copy( URL, AnsiPos('&res=', URL ) + 5, Length( URL ) - AnsiPos('&res=', URL ) - 5 + 1 );
-               ps := 0;
-               pch := PChar(buf);
-               while  ( ps < Length(buf) )and ( pch[ps] >= '0' ) and ( pch[ps] <= '9' ) do Inc(ps);
-               buf := Copy( buf, 1, ps );
-               try
-                       if buf <> '' then
-                               stRes := StrToInt(buf)
-                       else begin
-                               stRes := 0;
-                       end;
-               except
-                       stRes := 0;
-               end;
-       end else if (AnsiPos('&start=', URL ) <> 0) and ( AnsiPos( '&end=',URL) <> 0 ) then begin
-               try
-                       stRes := StrToInt64( Copy( URL, AnsiPos('&start=', URL ) + 7, AnsiPos( '&end=',URL) - AnsiPos('&start=', URL ) - 7 ) );
-                       if AnsiPos( '&nofirst=',URL) <> 0 then begin
-                               buf := Copy( URL, AnsiPos('&end=', URL ) + 5, AnsiPos( '&nofirst=',URL) - AnsiPos('&end=', URL ) - 5);
-                       end else begin
-                               buf := Copy( URL, AnsiPos('&end=', URL ) + 5, Length( URL ) - AnsiPos('&to=', URL ) - 5 + 1 );
-                               ps := 0;
-                               pch := PChar(buf);
-                               while  ( ps < Length(buf) )and ( pch[ps] >= '0' ) and ( pch[ps] <= '9' ) do Inc(ps);
-                               buf := Copy( buf, 1, ps );
-                       end;
-                       try
-                               if buf <> '' then
-                                       endRes := StrToInt64(buf);
-                       except
-                               endRes := 0;
-                       end;
-               except
-                       stRes := 0;
-               end;
-       end else if ( AnsiPos('.html',URL) <> Length(URL) -4 ) and ( AnsiPos('.htm',URL) <> Length(URL) -3 ) then begin
+    for i := 0 to Length(START_NAME) -1 do begin
+        idx := AnsiPos(START_NAME[i], URL);
+        if (idx <> 0) then begin
+            break;
+        end;
+        idx := AnsiPos(END_NAME[i], URL);
+        if (idx <> 0) then begin
+            break;
+        end;
+
+    end;
+
+    if (idx <> 0) then begin
+        idx := AnsiPos('?', URL);
+        if (idx = 0) then begin
+            idx := LastDelimiter('/', URL);
+        end;
+        stRes := 0;
+        endRes := 0;
+        bufList := TStringList.Create();
+        try
+            bufList.Delimiter := '&';
+            bufList.DelimitedText := Copy(URL, idx + 1, Length(URL));
+            for  i := 0 to bufList.Count - 1 do begin
+                convBuf := '';
+                // \8aJ\8en\83\8c\83X\94Ô\82Ì\8c\9f\8dõ
+                if (stRes = 0) then begin
+                    for j := 0 to Length(START_NAME) - 1 do begin
+                        idx := AnsiPos(START_NAME[j], bufList[i]);
+                        if (idx = 1) then begin
+                            convBuf := Copy(bufList[i], idx + Length(START_NAME[j]), Length(bufList[i]));
+                            stRes := StrToInt64Def( convBuf, 0 );
+                            break;
+                        end;
+                    end;
+                end;
+                // \8fI\97¹\83\8c\83X\94Ô\82Ì\8c\9f\8dõ
+                if (convBuf = '') and (endRes = 0) then begin
+                    for j := 0 to Length(END_NAME) - 1 do begin
+                        idx := AnsiPos(END_NAME[j], bufList[i]);
+                        if (idx = 1) then begin
+                            convBuf := Copy(bufList[i], idx + Length(END_NAME[j]), Length(bufList[i]));
+                            endRes := StrToInt64Def( convBuf, 0 );
+                            break;
+                        end;
+                    end;
+                end;
+                // \83\8c\83X\94Ô\82Ì\8c\9f\8dõ
+                if ((stRes = 0) and (endRes = 0) and (convBuf = '')) then begin
+                  for j := 0 to Length(RES_NAME) - 1 do begin
+                      idx := AnsiPos(RES_NAME[j], bufList[i]);
+                      if (idx = 1) then begin
+                          convBuf := Copy(bufList[i], idx + Length(RES_NAME[j]), Length(bufList[i]));
+                          stRes := StrToInt64Def( convBuf, 0 );
+                          endRes := stRes;
+                          break;
+                      end;
+                  end;
+                end;
+            end;
+
+            if (stRes <> 0) and (endRes = 0) then begin
+                       endRes := stRes + MAX_POPUP_RES;
+               end else if (stRes = 0) and (endRes <> 0) then begin
+                stRes := endRes - MAX_POPUP_RES;
+                       if stRes < 1 then begin
+                               stRes := 1;
+                end;
+            end;
+        finally
+            bufList.clear;
+            bufList.free;
+        end;
+    end else if ( AnsiPos('.html',URL) <> Length(URL) -4 ) and ( AnsiPos('.htm',URL) <> Length(URL) -3 ) then begin
                buf := Copy(URL, LastDelimiter('/',URL)+1,Length(URL)-LastDelimiter('/',URL)+1);
                if  Length(buf) > 0 then begin
                        if AnsiPos('-', buf) = 1 then begin
@@ -2315,15 +2070,10 @@ begin
                                ps := 0;
                                pch := PChar(buf);
                                while  ( ps < Length(buf) )and ( pch[ps] >= '0' ) and ( pch[ps] <= '9' ) do Inc(ps);
-                               try
-                                       convBuf := Copy( buf, 1, ps );
-                                       if convBuf <> '' then
-                                               endRes := StrToInt64(convBuf)
-                                       else
-                                               endRes := 0;
-                               except
-                                       endRes := 0;
-                               end;
+                convBuf := Copy( buf, 1, ps );
+                if convBuf <> '' then begin
+                    endRes := StrToInt64Def(convBuf, 0);
+                end;
                                if endRes <> 0 then begin
                                        stRes := endRes - MAX_POPUP_RES;
                                        if stRes < 1 then
@@ -2341,15 +2091,10 @@ begin
                                                ps := 0;
                                                pch := PChar(buf);
                                                while  ( ps < Length(buf) )and ( pch[ps] >= '0' ) and ( pch[ps] <= '9' ) do Inc(ps);
-                                               try
-                                                       convBuf := Copy( buf, 1, ps );
-                                                       if convBuf <> '' then
-                                                               endRes := StrToInt64(convBuf)
-                                                       else
-                                                               endRes := 0;
-                                               except
-                                                       endRes := 0;
-                                               end;
+                        convBuf := Copy( buf, 1, ps );
+                        if convBuf <> '' then begin
+                            endRes := StrToInt64Def(convBuf, 0);
+                        end;
                                        end else begin
                                                stRes := 0;
                                        end;
@@ -2359,12 +2104,14 @@ begin
                                end;
                        end;
                end;
-       end else begin
-               //stRes := 0;
-               //endRes := 0;
        end;
 end;
 
+{!
+\brief 2\82¿\82á\82ñ\82Ë\82é\8c`\8e®\82Ì URL \82ð\95ª\89ð
+\param URL 2\82¿\82á\82ñ\82Ë\82é\8c`\8e®\82Ì URL
+\return    \95ª\89ð\82³\82ê\82½\97v\91f
+}
 function TGikoSys.Parse2chURL2(URL: string): TPathRec;
 var
        i: Integer;
@@ -2403,7 +2150,7 @@ begin
                //\95W\8f\80\8f\91\8e®
                //\8dÅ\8cã\82Íl50, 10, 10-20, 10n, 10-20n, -10, 10-, 10n- \82È\82Ç
                //http://xxx.2ch.net/test/read.cgi/bbsid/1000000000/
-               FAWKStr.RegExp := '/test/read.cgi/.+/[0-9]+/?.*';
+               FAWKStr.RegExp := '/test/read.(cgi|html)/.+/[0-9]+/?.*';
                if FAWKStr.Match(FAWKStr.ProcessEscSeq(s), RStart, RLength) > 0 then begin
                        s := Copy(s, 15, Length(s));
 
@@ -2594,6 +2341,16 @@ begin
        end;
 end;
 
+{!
+\brief URI \82ð\95ª\89ð
+\param URL      \95ª\89ð\82·\82é URI
+\param Protocol OUT:\83v\83\8d\83g\83R\83\8b\82ª\95Ô\82é(ex. http)
+\param Host     OUT:\83z\83X\83g\82ª\95Ô\82é(ex. hoge.com)
+\param Path     OUT:\92\86\8aÔ\83p\83X\82ª\95Ô\82é(ex. test/read.cgi)
+\param Document OUT:\83h\83L\83\85\83\81\83\93\83g\96¼\82ª\95Ô\82é(ex. index.html)
+\param Port     OUT:\83|\81[\83g\82ª\95Ô\82é(ex. 8080)
+\param Bookmark OUT:\83u\83b\83N\83}\81[\83N(?)\82ª\95Ô\82é
+}
 procedure TGikoSys.ParseURI(const URL : string; var Protocol, Host, Path, Document, Port, Bookmark: string);
 var
        URI: TIdURI;
@@ -2617,6 +2374,10 @@ begin
        end;
 end;
 
+{!
+\brief \83M\83R\83i\83r\82Ì\83o\81[\83W\83\87\83\93\82ð\8eæ\93¾
+\return \83o\81[\83W\83\87\83\93\82Ì\89º 2 \8c\85(dwFileVersionLS)
+}
 function TGikoSys.GetVersionBuild: Integer;
 var
        FixedFileInfo: PVSFixedFileInfo;
@@ -2640,6 +2401,23 @@ begin
        end;
 end;
 
+{!
+\brief \83X\83\8c\83b\83h URL \82Ì\90³\8bK\89»
+\param inURL \90³\8bK\89»\82·\82é\83X\83\8c\83b\83h URL
+\return      \90³\8bK\89»\82³\82ê\82½\83X\83\8c\83b\83h URL
+
+\83X\83\8c\83b\83h URL \82ð\83M\83R\83i\83r\82Ì\92\86\82Å\88ê\88Ó\82È\82à\82Ì\82É\90³\8bK\89»\82µ\82Ü\82·\81B
+\88ê\88Ó\82È URL \82É\82·\82é\8e\96\82Å\81AURL \82©\82ç\83X\83\8c\83b\83h\82ð\93±\82«\8fo\82·\8dì\8bÆ\82ð\8dÅ\93K\89»\82µ\82Ü\82·\81B\n
+\90³\8bK\89»\82Ì\95û\90j\82Æ\82µ\82Ä\81A\83T\83C\83g\82ª\90\84\8f§\82·\82é\83f\83t\83H\83\8b\83g\82Ì URL \82É\82È\82é\82æ\82¤\82É\90S\82ª\82¯\82Ü\82·\81B
+(1-1000 \82Ì\82æ\82¤\82È\95\89\89×\82ð\82©\82¯\82é\82à\82Ì\82É\82Í\82µ\82È\82¢\82±\82Æ)
+
+\97á(\90³\8bK\89»\91O):\n
+http://\92\86\97ª/ \n
+http://\92\86\97ª/20-100
+
+(\90³\8bK\89»\8cã):\n
+http://\92\86\97ª/l50
+}
 function       TGikoSys.GetBrowsableThreadURL(
        inURL : string
 ) : string;
@@ -2676,6 +2454,11 @@ begin
 
 end;
 
+{!
+\brief \83X\83\8c\83b\83h URL \82ð\94 URL \82É\95Ï\8a·
+\param inURL \83X\83\8c\83b\83h URL
+\return      \94 URL
+}
 function       TGikoSys.GetThreadURL2BoardURL(
        inURL : string
 ) : string;
@@ -2710,6 +2493,12 @@ begin
 
 end;
 
+{!
+\brief 2ch\97p:\83X\83\8c\83b\83h URL \82ð\94 URL \82É\95Ï\8a·
+\param inURL \83X\83\8c\83b\83h URL
+\return      \94 URL
+\see TGikoSys.GetThreadURL2BoardURL
+}
 function       TGikoSys.Get2chThreadURL2BoardURL(
        inURL : string
 ) : string;
@@ -2730,6 +2519,12 @@ begin
 
 end;
 
+{!
+\brief 2ch\97p:\83X\83\8c\83b\83h URL \82Ì\90³\8bK\89»
+\param inURL \90³\8bK\89»\82·\82é\83X\83\8c\83b\83h URL
+\return      \90³\8bK\89»\82³\82ê\82½\83X\83\8c\83b\83h URL
+\see TGikoSys.GetBrowsableThreadURL
+}
 function       TGikoSys.Get2chBrowsableThreadURL(
        inURL                   : string
 ) : string;
@@ -2761,6 +2556,12 @@ begin
 
 end;
 
+{!
+\brief 2ch\97p:\94 URL \82©\82ç\83X\83\8c\83b\83h URL \82ð\8dì\90¬
+\param inBoard \94 URL
+\param inKey   \83X\83\8c\83b\83h\83L\81[(ex. 1000000000)
+\return        \83X\83\8c\83b\83h URL
+}
 function       TGikoSys.Get2chBoard2ThreadURL(
        inBoard : TBoard;
        inKey           : string
@@ -2778,14 +2579,16 @@ begin
 
 end;
 
-(*************************************************************************
- *\8b@\94\\96¼\81@\81@\81F\83{\81[\83h\83t\83@\83C\83\8b\97ñ\8b\93
- *\89Â\8e\8b\81@\81@\81@\81FPublic
- *************************************************************************)
+{!
+\brief \83{\81[\83h\83t\83@\83C\83\8b\97ñ\8b\93
+
+\97ñ\8b\93\82³\82ê\82½ BBS(\83{\81[\83h) \82Í BBSs \82É\93ü\82è\82Ü\82·\81B
+}
 procedure TGikoSys.ListBoardFile;
 var
        boardFileList   : TStringList;
-       i, l, k                                 : Integer;
+       i, l                    : Integer;
+    sCategory       : TCategory;
 begin
        // BBS \82Ì\8aJ\95ú
        try
@@ -2816,13 +2619,9 @@ begin
          BoardFileList := TStringList.Create;
          try
         BoardFileList.BeginUpdate;
-               GikoSys.GetFileList( GikoSys.Setting.GetBoardDir, '*', BoardFileList, True, True );
+               GikoSys.GetFileList( GikoSys.Setting.GetBoardDir, '*.txt', BoardFileList, True, True );
         BoardFileList.EndUpdate;
-               for k := BoardFileList.Count - 1 downto 0 do begin
-                 if AnsiCompareText(ExtractFileExt(BoardFileList[ k ]), '.bak') = 0 then
-                         BoardFileList.Delete(k);
-               end;
-                         SetLength( BBSs, l + BoardFileList.Count );
+        SetLength( BBSs, l + BoardFileList.Count );
                for i := BoardFileList.Count - 1 downto 0 do begin
                  BBSs[ l ]                             := TBBS.Create( BoardFileList[ i ] );
                  BBSs[ l ].Title       := ChangeFileExt( ExtractFileName( BoardFileList[ i ] ), '' );
@@ -2832,11 +2631,26 @@ begin
                BoardFileList.Free;
          end;
        end;
-end;
-(*************************************************************************
- *\8b@\94\\96¼\81@\81@\81F\83{\81[\83h\83t\83@\83C\83\8b\93Ç\82Ý\8d\9e\82Ý
- *\89Â\8e\8b\81@\81@\81@\81FPublic
- *************************************************************************)
+
+    // \93Á\8eê\97p\93rBBS\90\90¬
+    // \8aù\82É\91\8dÝ\82·\82é\8fê\8d\87\82Í\8dí\8f\9c\82·\82é
+    DestorySpecialBBS(BoardGroup.SpecialBBS);
+    SpecialBBS := TBBS.Create('');
+    SpecialBBS.Title := '\93Á\8eê\97p\93r(\94ñ\95\\8e¦)';
+    sCategory := TCategory.Create;
+    sCategory.No := 1;
+    sCategory.Title := '\93Á\8eê\97p\93r(\94ñ\95\\8e¦)';
+    SpecialBBS.Add(sCategory);
+    BoardGroup.SpecialBoard := TSpecialBoard.Create(nil, 'http://localhost/gikonavi/special/index.html');
+    BoardGroup.SpecialBoard.Title := '\83^\83u\88ê\97\97';
+    BoardGroup.SpecialBoard.IsThreadDatRead := True;
+    sCategory.Add(BoardGroup.SpecialBoard);
+end;
+
+{!
+\brief \83{\81[\83h\83t\83@\83C\83\8b\93Ç\82Ý\8d\9e\82Ý
+\param bbs \83{\81[\83h\83t\83@\83C\83\8b\82ð\93Ç\82Ý\8d\9e\82Þ BBS
+}
 procedure TGikoSys.ReadBoardFile( bbs : TBBS );
 var
 //     idx                                             : Integer;
@@ -2975,6 +2789,10 @@ begin
 
 end;
 
+{!
+\brief \96¼\8fÌ\82ª\95s\96¾\82È\83J\83e\83S\83\8a\82Ì\90\90¬
+\return \90\90¬\82³\82ê\82½\83J\83e\83S\83\8a
+}
 function       TGikoSys.GetUnknownCategory : TCategory;
 const
        UNKNOWN_CATEGORY = '(\96¼\8fÌ\95s\96¾)';
@@ -2994,6 +2812,10 @@ begin
 
 end;
 
+{!
+\brief \96¼\8fÌ\82ª\95s\96¾\82È BBS \82Ì\90\90¬
+\return \90\90¬\82³\82ê\82½ BBS
+}
 function       TGikoSys.GetUnknownBoard( inPlugIn : TBoardPlugIn; inURL : string ) : TBoard;
 var
        category : TCategory;
@@ -3014,60 +2836,77 @@ begin
        end;
 
 end;
+
+//! Samba.ini
 function TGikoSys.GetSambaFileName : string;
 begin
        Result := Setting.GetSambaFileName;
 end;
-procedure TGikoSys.SambaFileExists();
-var
-       sambaTmp: string;
-       sambaStrList: TStringList;
-begin
-       if not FileExists(GikoSys.GetSambaFileName) then begin
-               sambaTmp := ChangeFileExt(GikoSys.GetSambaFileName, '.default');
-               sambaStrList := TStringList.Create;
-               try
-                       if FileExists(sambaTmp) then begin
-                               sambaStrList.LoadFromFile(sambaTmp);
-                               sambaStrList.SaveToFile(GikoSys.GetSambaFileName);
-                       end;
-               finally
-                       sambaStrList.Free;
-               end;
-       end;
-end;
-function TGikoSys.GetSameIDResAnchor(const AID : string; ThreadItem: TThreadItem; limited: boolean):string;
+{!
+\brief \97ñ\8b\93\82³\82ê\82½\83\8c\83X\94Ô\8d\86\82Ö\82Ì\83A\83\93\83J\81[\97pHTML\8dì\90¬
+\param Numbers    \97ñ\8b\93\82³\82ê\82½\83\8c\83X\94Ô\8d\86
+\param ThreadItem \97ñ\8b\93\82·\82é\83X\83\8c\83b\83h
+\param limited    \97ñ\8b\93\82·\82é\90\94\82ð\90§\8cÀ\82·\82é\82È\82ç1\88È\8fã
+\return           \97ñ\8b\93\82³\82ê\82½\83\8c\83X\83A\83\93\83J\81[
+}
+function TGikoSys.CreateResAnchor(
+    var Numbers: TStringList; ThreadItem: TThreadItem;
+    limited: Integer):string;
 var
        i: integer;
-       body: TStringList;
+    Res: TResRec;
+    ResLink : TResLinkRec;
 begin
-    Result := '';
-    if (not IsNoValidID(AID)) and
-       (ThreadItem <> nil) and (ThreadItem.IsLogFile) then begin
-        body := TStringList.Create;
-        try
-            GetSameIDRes(AID, ThreadItem, body);
-            if (limited) and (body.Count > 20) then begin
-                for i := body.Count - 20 to body.Count - 1 do begin
-                    Result := Result + '&gt;' + body[i] + ' ';
-                end;
-            end else begin
-                for i := 0 to body.Count - 1 do begin
-                    Result := Result + '&gt;' + body[i] + ' ';
-                end;
+    // body\88È\8aO\82Í\8eg\97p\82µ\82È\82¢\82Ì\82Å\8f\89\8aú\89»\82µ\82È\82¢
+    Res.FBody := '';
+    Res.FType := glt2chNew;
+
+       Result := '';
+       if (Numbers <> nil) and (Numbers.Count > 0) then begin
+        if (limited > 0) and (Numbers.Count > limited) then begin
+            for i := Numbers.Count - limited to Numbers.Count - 1 do begin
+                Res.FBody := Res.FBody + '&gt;' + Numbers[i] + ' ';
+            end;
+        end else begin
+            for i := 0 to Numbers.Count - 1 do begin
+                Res.FBody := Res.FBody + '&gt;' + Numbers[i] + ' ';
             end;
-        finally
-            body.Free;
         end;
-               Result := HTMLCreater.ConvRes(Result, ThreadItem.ParentBoard.BBSID, ChangeFileExt(ThreadItem.FileName, ''), 'bbs', 'key', 'st', 'to', 'nofirst', 'true', false);
+        ResLink.FBbs := ThreadItem.ParentBoard.BBSID;
+        ResLink.FKey := ChangeFileExt(ThreadItem.FileName, '');
+        HTMLCreater.ConvRes(@Res, @ResLink, false);
+        Result := Res.FBody;
     end;
 end;
+
+{!
+\brief \93¯\82\93\8a\8de ID \82ð\8e\9d\82Â\83\8c\83X\82ð\97ñ\8b\93
+\param AID        \8cÂ\90l\82ð\93Á\92è\82·\82é\93\8a\8de ID
+\param ThreadItem \97ñ\8b\93\82·\82é\83X\83\8c\83b\83h
+\param body       OUT:\97ñ\8b\93\82³\82ê\82½\83\8c\83X\94Ô\8d\86\82ª\95Ô\82é
+}
 procedure TGikoSys.GetSameIDRes(const AID : string; ThreadItem: TThreadItem;var body: TStringList);
 var
        i: integer;
        ReadList: TStringList;
        Res: TResRec;
        boardPlugIn : TBoardPlugIn;
+
+    procedure CheckSameID(const AID:String; const Target: String; no: Integer);
+    var
+        pos: Integer;
+    begin
+        pos := AnsiPos('id:', LowerCase(Target));
+        if (pos > 0) then begin
+            if(AnsiPos(AID, Copy(Target, pos-1, Length(Target))) > 0) then begin
+                body.Add(IntToStr(no));
+            end;
+        end else begin
+            if(AnsiPos(AID, Target) > 0) then begin
+                body.Add(IntToStr(no));
+            end;
+        end;
+    end;
 begin
        if (not IsNoValidID(AID)) and
        (ThreadItem <> nil) and (ThreadItem.IsLogFile) then begin
@@ -3079,20 +2918,16 @@ begin
 
                        for i := 0 to threadItem.Count - 1 do begin
                                // \83\8c\83X
-                               Res := DivideStrLine(boardPlugIn.GetDat(DWORD( threadItem ), i + 1));
-                               if(AnsiPos(AID, Res.FDateTime) > 0) then begin
-                                       body.Add(IntToStr(i+1));
-                               end;
+                               THTMLCreate.DivideStrLine(boardPlugIn.GetDat(DWORD( threadItem ), i + 1), @Res);
+                CheckSameID(AID, Res.FDateTime, i+1);
                        end;
                end else begin
                        ReadList := TStringList.Create;
                        try
                                ReadList.LoadFromFile(ThreadItem.GetThreadFileName);
                                for i := 0 to ReadList.Count - 1 do begin
-                                       Res := DivideStrLine(ReadList[i]);
-                                       if AnsiPos(AID, Res.FDateTime) > 0 then begin
-                                               body.Add(IntToStr(i+1));
-                                       end;
+                                       THTMLCreate.DivideStrLine(ReadList[i], @Res);
+                    CheckSameID(AID, Res.FDateTime, i+1);
                                end;
                        finally
                                ReadList.Free;
@@ -3100,40 +2935,34 @@ begin
                end;
        end;
 end;
-function TGikoSys.GetSameIDResAnchor(AIDNum : Integer; ThreadItem: TThreadItem; limited: boolean):string;
+
+{!
+\brief \93¯\82\93\8a\8de ID \82ð\8e\9d\82Â\83\8c\83X\82ð\97ñ\8b\93
+\param AIDNum     \8cÂ\90l\82ð\93Á\92è\82·\82é\93\8a\8de ID
+\param ThreadItem \97ñ\8b\93\82·\82é\83X\83\8c\83b\83h
+\param body       OUT:\97ñ\8b\93\82³\82ê\82½\83\8c\83X\94Ô\8d\86\82ª\95Ô\82é
+}
+procedure TGikoSys.GetSameIDRes(AIDNum : Integer; ThreadItem: TThreadItem;var body: TStringList);
 var
-       i: integer;
-       body: TStringList;
+       AID : String;
 begin
-       Result := '';
-       if (ThreadItem <> nil) and (ThreadItem.IsLogFile) then begin
-               body := TStringList.Create;
-               try
-                       GetSameIDRes(AIDNum, ThreadItem, body);
-            if (limited) and (body.Count > 20) then begin
-                       for i := body.Count - 20 to body.Count - 1 do begin
-                               Result := Result + '&gt;' + body[i] + ' ';
-                       end;
-            end else begin
-                       for i := 0 to body.Count - 1 do begin
-                               Result := Result + '&gt;' + body[i] + ' ';
-                       end;
-            end;
-               finally
-                       body.Free;
-               end;
-               Result := HTMLCreater.ConvRes(Result, ThreadItem.ParentBoard.BBSID, ChangeFileExt(ThreadItem.FileName, ''), 'bbs', 'key', 'st', 'to', 'nofirst', 'true', false);
+    AID := GetResID(AIDNum, ThreadItem);
+    if not IsNoValidID(AID) then begin
+           GetSameIDRes(AID, ThreadItem, body);
        end;
 end;
-
-procedure TGikoSys.GetSameIDRes(AIDNum : Integer; ThreadItem: TThreadItem;var body: TStringList);
+{!
+\brief \93\8a\8de ID \8eæ\93¾
+\param AIDNum     \93\8a\8d\83\8c\83X\94Ô\8d\86
+\param ThreadItem \93\8a\8de\83X\83\8c\83b\83h
+\param body       OUT:\93\8a\8deID
+}
+function TGikoSys.GetResID(AIDNum: Integer; ThreadItem: TThreadItem): String;
 var
        Res: TResRec;
        boardPlugIn : TBoardPlugIn;
-       AID : String;
-       stList: TStringList;
-       i : Integer;
 begin
+    Result := '';
        if (ThreadItem <> nil) and (ThreadItem.IsLogFile)
                and (AIDNum > 0) and (AIDNum <= ThreadItem.Count) then begin
                //if ThreadItem.IsBoardPlugInAvailable then begin
@@ -3141,85 +2970,51 @@ begin
                        //===== \83v\83\89\83O\83C\83\93\82É\82æ\82é\95\\8e¦
                        //boardPlugIn           := ThreadItem.BoardPlugIn;
             boardPlugIn                := ThreadItem.ParentBoard.BoardPlugIn;
-                       Res := DivideStrLine(boardPlugIn.GetDat(DWORD( threadItem ), AIDNum));
+                       THTMLCreate.DivideStrLine(boardPlugIn.GetDat(DWORD( threadItem ), AIDNum), @Res);
                end else begin
-                       Res := DivideStrLine( ReadThreadFile(ThreadItem.GetThreadFileName, AIDNum));
-               end;
-               AID := Res.FDateTime;
-               if AnsiPos('id', AnsiLowerCase(AID)) > 0 then begin
-                       AID := Copy(AID, AnsiPos('id', AnsiLowerCase(AID)) - 1, 11);
-            if AnsiPos(' be:', AnsiLowerCase(AID)) > 0 then begin
-               AID := Copy(AID, 1, AnsiPos(' BE:', AnsiLowerCase(AID)) - 1)
-            end;
-               end else begin
-                       stlist := TStringList.Create;
-                       try
-                               stList.DelimitedText := AID;
-                AID := '';
-                               for i := 0 to stList.Count - 1 do
-                                       if Length(WideString(stList[i])) = 8 then begin
-                                               if NotDateorTimeString(stList[i]) then begin
-                                                       AID := stList[i];
-                                                       break;
-                                               end;
-                                       end;
-                       finally
-                               stList.Free;
-                       end;
+                       THTMLCreate.DivideStrLine( ReadThreadFile(ThreadItem.GetThreadFileName, AIDNum), @Res);
                end;
-        if not IsNoValidID(AID) then
-                       GetSameIDRes(AID, ThreadItem, body);
+               Result := ExtructResID(Res.FDateTime);
        end;
 end;
-function TGikoSys.GetSameIDResCount(const AID : string; ThreadItem: TThreadItem):Integer;
+{!
+\brief \83\8c\83X\82Ì\8e\9e\8d\8f\95\94\82©\82çID\82ð\92\8a\8fo\82·\82é
+\param ADateStr \8e\9e\8d\8f\95\94\82Ì\95\8e\9a\97ñ
+\return     ID(ID\82Æ\82Ý\82È\82¹\82é\95\94\95ª\82ª\82È\82¢\82Æ\82«\82Í\8bó\95\8e\9a\97ñ)
+}
+function TGikoSys.ExtructResID(ADateStr: String): String;
 var
-       body: TStringList;
+    stlist : TStringList;
 begin
-    Result := 0;
-       if (not IsNoValidID(AID))
-     and (ThreadItem <> nil) and (ThreadItem.IsLogFile) then begin
-               body := TStringList.Create;
-               try
-                       GetSameIDRes(AID, ThreadItem, body);
-                       Result := body.Count;
-               finally
-                       body.Free;
-               end;
-       end;
-
-end;
-function TGikoSys.GetSameIDResCount(AIDNum : Integer; ThreadItem: TThreadItem):Integer;
-var
-       body: TStringList;
-begin
-       Result := 0;
-       if (ThreadItem <> nil) and (ThreadItem.IsLogFile) then begin
-               body := TStringList.Create;
-               try
-                       GetSameIDRes(AIDNum, ThreadItem, body);
-            Result := body.Count;
-               finally
-                       body.Free;
-               end;
-       end;
-end;
-
-function TGikoSys.NotDateorTimeString(const AStr : string): boolean;
-begin
-       Result := false;
-       try
-               StrToDate(AStr);
-       except
-               try
-                       StrToTime(AStr);
-                       Result := false;
-               except
-                       Result := true;
-               end;
-       end;
-
+    Result := '';
+    if AnsiPos('id', AnsiLowerCase(ADateStr)) > 0 then begin
+        Result := Copy(ADateStr, AnsiPos('id', AnsiLowerCase(ADateStr)), Length(ADateStr));
+        if AnsiPos(' ', Result) > 0 then begin
+            Result := Copy(Result, 1, AnsiPos(' ', Result) - 1);
+        end;
+        Result := ' ' + Result;
+    end else begin
+        stlist := TStringList.Create;
+        try
+            stList.Delimiter := ' ';
+            stList.DelimitedText := ADateStr;
+            // \93ú\95\8e\9e\8d\8f ID \91¼\81@\82Æ\8cÅ\92è\82Å\8dl\82¦\82é
+            if (stList.Count >= 3) then begin
+                if Length(stList[3 - 1]) >= 7 then begin
+                    Result := stList[3 - 1];
+                end;
+            end;
+        finally
+            stList.Free;
+        end;
+    end;
 end;
 
+{!
+\brief \83X\83p\83\80:\8cê\90\94\82ð\83J\83E\83\93\83g
+\param text      \8c³\82É\82È\82é\95\8fÍ
+\param wordCount OUT:\83J\83E\83\93\83g\82³\82ê\82½\92P\8cê\82Ì\88ê\97\97\82ª\95Ô\82é
+}
 procedure TGikoSys.SpamCountWord( const text : string; wordCount : TWordCount );
 begin
 
@@ -3228,6 +3023,20 @@ begin
 
 end;
 
+{!
+\brief \83X\83p\83\80:\8aw\8fK\8c\8b\89Ê\82ð\95ú\8aü
+\param wordCount \95ú\8aü\82·\82é\92P\8cê\82Ì\88ê\97\97
+\param isSpam    wordCount \82ª\83X\83p\83\80\82Æ\82µ\82Ä\8aw\8fK\82³\82ê\82Ä\82¢\82½\82È\82ç True
+\warning       \8aw\8fK\8dÏ\82Ý\82Ì\95\8fÍ\82©\82Ç\82¤\82©\82Í\8am\94F\8fo\97\88\82Ü\82¹\82ñ\81B\n
+                                       Learn \82µ\82Ä\82¢\82È\82¢\95\8fÍ\82â isSpam \82ð\8aÔ\88á\82¦\82Ä\8ew\92è\82·\82é\82Æ
+                                       \83f\81[\83^\83x\81[\83X\82ª\94j\91¹\82µ\82Ü\82·\81B\n
+                                       \8aw\8fK\8dÏ\82Ý\82©\82Ç\82¤\82©\82Í\93Æ\8e©\82É\8aÇ\97\9d\82µ\82Ä\82­\82¾\82³\82¢\81B
+
+\91S\82Ä\82Ì\8aw\8fK\8c\8b\89Ê\82ð\83N\83\8a\83A\82·\82é\82í\82¯\82Å\82Í\82 \82è\82Ü\82¹\82ñ\81B\n
+wordCount \82ð\93¾\82½\95\8fÍ\82Ì\8aw\8fK\8c\8b\89Ê\82Ì\82Ý\83N\83\8a\83A\82µ\82Ü\82·\81B
+
+\8eå\82É\83X\83p\83\80\82Æ\83n\83\80\82ð\90Ø\82è\91Ö\82¦\82é\82½\82ß\82É Forget -> Learn \82Ì\8f\87\82Å\8eg\97p\82µ\82Ü\82·\81B
+}
 procedure TGikoSys.SpamForget( wordCount : TWordCount; isSpam : Boolean );
 begin
 
@@ -3236,6 +3045,11 @@ begin
 
 end;
 
+{!
+\brief \83X\83p\83\80:\8aw\8fK
+\param wordCount \8aw\8fK\82·\82é\92P\8cê\82Ì\88ê\97\97
+\param isSpam    \83X\83p\83\80\82Æ\82µ\82Ä\8aw\8fK\82·\82é\82È\82ç True
+}
 procedure TGikoSys.SpamLearn( wordCount : TWordCount; isSpam : Boolean );
 begin
 
@@ -3244,6 +3058,12 @@ begin
 
 end;
 
+{!
+\brief \83X\83p\83\80:\95\8fÍ\82ð\89ð\90Í\82µ\81A\83X\83p\83\80\93x\90\94\82ð\93¾\82é
+\param text      \8c³\82É\82È\82é\95\8fÍ
+\param wordCount OUT:\83J\83E\83\93\83g\82³\82ê\82½\92P\8cê\82Ì\88ê\97\97\82ª\95Ô\82é(SpamCountWord \82Æ\93¯\93\99)
+\return          0\81`1 \82Ì\83X\83p\83\80\93x\90\94
+}
 function TGikoSys.SpamParse( const text : string; wordCount : TWordCount ) : Extended;
 begin
 
@@ -3256,9 +3076,17 @@ begin
        end;
 
 end;
+
+{!
+\brief \83\86\81[\83U\90Ý\92è\82Ì CSS \82ð\90\90¬
+\return \90\90¬\82³\82ê\82½ CSS
+
+[\83c\81[\83\8b]\83\81\83j\83\85\81[-[\83I\83v\83V\83\87\83\93]-[CSS \82Æ\83X\83L\83\93]\83^\83u\82Ì
+[\83t\83H\83\93\83g\82ð\8ew\92è], [\94w\8ci\90F\82ð\8ew\92è] \82É\89\88\82Á\82½ CSS \82ð\90\90¬\82µ\82Ü\82·\81B
+}
 function TGikoSys.SetUserOptionalStyle(): string;
 begin
-    Result := '';
+               Result := '';
        if Length( GikoSys.Setting.BrowserFontName ) > 0 then
                Result := 'font-family:"' + GikoSys.Setting.BrowserFontName + '";';
        if GikoSys.Setting.BrowserFontSize <> 0 then
@@ -3276,7 +3104,14 @@ begin
                1:  Result := Result + 'font-style:italic;';
        end;
 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
+
+{!
+\brief Be \83v\83\8d\83t\83@\83C\83\8b\82Ö\82Ì\83A\83\93\83J\81[\83^\83O\82ð\90\90¬
+\param AID  \91Î\8fÛ\82Æ\82È\82é\93ú\95tID\95\8e\9a\97ñ
+\param ANum \83\8c\83X\94Ô
+\param AURL \82»\82Ì\83X\83\8c\83b\83h\82ÌURL
+\return     \90\90¬\82³\82ê\82½\83A\83\93\83J\81[\83^\83O
+}
 function TGikoSys.AddBeProfileLink(AID : string; ANum: Integer):string ;
 var
        p : integer;
@@ -3297,7 +3132,12 @@ begin
        end else
                Result := AID;
 end;
-// \83o\81[\83W\83\87\83\93\8fî\95ñ\82ð\8eæ\93¾
+
+{!
+\brief \83o\81[\83W\83\87\83\93\8fî\95ñ\82ð\8eæ\93¾
+\param KeyWord \8eæ\93¾\82·\82é\8d\80\96Ú
+\return        \83o\81[\83W\83\87\83\93\95\8e\9a\97ñ
+}
 function TGikoSys.GetVersionInfo(KeyWord: TVerResourceKey): string;
 const
        Translation = '\VarFileInfo\Translation';
@@ -3341,9 +3181,11 @@ begin
                end;
        end;
 end;
-//Plugin\82Ì\8fî\95ñ\82Ì\8eæ\93¾
-//Load\82³\82ê\82½\91S\82Ä\82Ì\83v\83\89\83O\83C\83\93\82Ì\83o\81[\83W\83\87\83\93\8fî\95ñ\82ð\95Ô\82·
-//1\8ds1plugin
+
+{!
+\brief Load \82³\82ê\82Ä\82¢\82é\83v\83\89\83O\83C\83\93\82Ì\83o\81[\83W\83\87\83\93\82ð\97ñ\8b\93
+\return 1\8ds1plugin
+}
 function TGikoSys.GetPluginsInfo(): String;
 var
        i : Integer;
@@ -3369,7 +3211,7 @@ begin
 end;
 
 
-//IE\82Ì\83o\81[\83W\83\87\83\93\82ð\8eæ\93¾\82·\82é
+//IE\82Ì\83o\81[\83W\83\87\83\93\82ð\8eæ\93¾\82·\82é
 function TGikoSys.GetIEVersion: string;
 var
        R: TRegistry;
@@ -3390,14 +3232,327 @@ begin
                R.Free;
        end;
 end;
+//! main\83t\83H\81[\83\80\82Ì\83V\83\87\81[\83g\83J\83b\83g\83L\81[\82ÌIni\83t\83@\83C\83\8b\96¼
+function TGikoSys.GetMainKeyFileName : String;
+begin
+       Result := Setting.GetMainKeyFileName;
+end;
+//! Editor\83t\83H\81[\83\80\82Ì\83V\83\87\81[\83g\83J\83b\83g\83L\81[\82ÌIni\83t\83@\83C\83\8b\96¼
+function TGikoSys.GetEditorKeyFileName: String;
+begin
+       Result := Setting.GetEditorKeyFileName;
+end;
+//! \93ü\97Í\83A\83V\83X\83g\82Ì\90Ý\92è\83t\83@\83C\83\8b\96¼
+function TGikoSys.GetInputAssistFileName: String;
+begin
+       Result := Setting.GetInputAssistFileName;
+end;
+//! \83M\83R\83i\83r\82Ì\83\81\83b\83Z\81[\83W\82ð\90Ý\92è\82·\82é
+procedure TGikoSys.SetGikoMessage;
+begin
+       if FGikoMessage = nil then begin
+               FGikoMessage := TGikoMessage.Create;
+       end else begin
+               FGikoMessage.Clear;
+       end;
+
+       if (Setting.GengoSupport) then begin
+               try
+                       if (FileExists(Setting.GetLanguageFileName)) then begin
+                               FGikoMessage.LoadFromFile(Setting.GetLanguageFileName);
+                       end;
+               except
+                       FGikoMessage.Clear;
+               end;
+       end;
+end;
+//! \83M\83R\83i\83r\82Ì\83\81\83b\83Z\81[\83W\82ð\8eæ\93¾\82·\82é
+function TGikoSys.GetGikoMessage(MesType: TGikoMessageListType): String;
+begin
+    Result := '';
+       if FGikoMessage <> nil then begin
+               Result := FGikoMessage.GetMessage(MesType);
+       end;
+end;
+
+//Tue, 17 Dec 2002 12:18:07 GMT \81¨ TDateTime\82Ö
+//MonaUtils\82©\82ç\88Ú\93®
+function  TGikoSys.DateStrToDateTime(const DateStr: string): TDateTime;
+       function  StrMonthToMonth(const s: string): integer;
+       const
+               m: array[1..12] of string = ('Jan','Feb','Mar','Apr','May','Jun', 'Jul','Aug','Sep','Oct','Nov','Dec');
+       var
+               i: integer;
+       begin
+               Result  :=  -1;
+               for i :=  Low(m)  to  High(m) do  begin
+                       if  (SameText(s, m[i]))  then  begin
+                               Result  :=  i;
+                               Break;
+                       end;
+               end;
+       end;
+var
+       wDay, wMonth, wYear: word;
+       wHour, wMinute, wSecond: word;
+       sTime: string;
+       d: TDateTime;
+begin
+       wDay    :=  StrToIntDef(ChooseString(DateStr, ' ', 1), 0);
+       wMonth  :=  StrMonthToMonth(ChooseString(DateStr, ' ', 2));
+       wYear   :=  StrToIntDef(ChooseString(DateStr, ' ', 3), 0);
+       sTime   :=  ChooseString(DateStr, ' ', 4);
+       wHour   :=  StrToIntDef(ChooseString(sTime, ':', 0), 0);
+       wMinute :=  StrToIntDef(ChooseString(sTime, ':', 1), 0);
+       wSecond :=  StrToIntDef(ChooseString(sTime, ':', 2), 0);
+       d :=  EncodeDateTime(wYear, wMonth, wDay, wHour, wMinute, wSecond, 0);
+       Result  :=  d;
+end;
+//MonaUtils\82©\82ç\88Ú\93®
+//! \82 \82é\83Z\83p\83\8c\81[\83^\82Å\8bæ\90Ø\82ç\82ê\82½\95\8e\9a\97ñ\82©\82ç\82\8e\94Ô\96Ú\82Ì\95\8e\9a\97ñ\82ð\8eæ\82è\8fo\82·
+function TGikoSys.ChooseString(const Text, Separator: string; Index: integer): string;
+var
+       S : string;
+       i, p : integer;
+begin
+       S :=  Text;
+       for i :=  0 to  Index - 1 do  begin
+               if  (AnsiPos(Separator, S) = 0) then  S :=  ''
+               else  S :=  Copy(S, AnsiPos(Separator, S) + Length(Separator), Length(S));
+       end;
+       p :=  AnsiPos(Separator, S);
+       if  (p > 0) then  Result  :=  Copy(S, 1, p - 1) else Result :=  S;
+end;
+//! \88ê\8e\9e\83t\83@\83C\83\8b\82©\82ç\82Ì\95\9c\8b\8c
+procedure TGikoSys.RestoreThreadData(Board : TBoard);
+const
+    SECTION = 'Setting';
+var
+    TmpFileList : TStringList;
+    i : Integer;
+    ini : TMemIniFile;
+    ThreadItem : TThreadItem;
+    Boardpath, tmpStr : string;
+begin
+    Boardpath := ExtractFilePath(Board.GetFolderIndexFileName);
+
+       TmpFileList := TStringList.Create;
+       TmpFileList.Sorted := True;
+       TmpFileList.BeginUpdate;
+    try
+       //\91O\89ñ\88Ù\8fí\8fI\97¹\8e\9e\97pTmp\83t\83@\83C\83\8b\83\8a\83X\83g
+           GetFileList(Boardpath, '*.tmp', TmpFileList, False);
+           TmpFileList.EndUpdate;
+               //\91O\89ñ\88Ù\8fí\8fI\97¹\8e\9e\83`\83F\83b\83N
+               for i := TmpFileList.Count - 1 downto 0 do begin
+                       ThreadItem := Board.FindThreadFromFileName(ChangeFileExt(TmpFileList[i], '.dat'));
+                       if ThreadItem <> nil then begin
+                               ini := TMemIniFile.Create(Boardpath + TmpFileList[i]);
+                               try
+                                       tmpStr := ini.ReadString(SECTION, 'RoundDate', DateTimeToStr(ZERO_DATE));
+                                       ThreadItem.RoundDate := ConvertDateTimeString(tmpStr);
+
+                                       tmpStr := ini.ReadString(SECTION, 'LastModified', DateTimeToStr(ZERO_DATE));
+                                       ThreadItem.LastModified := ConvertDateTimeString(tmpStr);
+                                       ThreadItem.Count := ini.ReadInteger(SECTION, 'Count', 0);
+                                       ThreadItem.NewReceive := ini.ReadInteger(SECTION, 'NewReceive', 0);
 
+                                       ThreadItem.Size := ini.ReadInteger(SECTION, 'Size', 0);
+                    ThreadItem.IsLogFile := FileExists(ThreadItem.GetThreadFileName);
+                                       if(ThreadItem.Size = 0) and (ThreadItem.IsLogFile) then begin
+                                               try
+                                                       ThreadItem.Size := GetFileSize(ThreadItem.GetThreadFileName) - ThreadItem.Count;
+                                               except
+                                               end;
+                                       end;
+
+                    //\8f\84\89ñ\82Ì\90Ý\92è\82ÍRoundData\82Ì\95û\82ª\82â\82é\82©\82ç\8f\9f\8eè\82É\90Ý\92è\82µ\82Ä\82Í\83_\83\81\81I\81@by \82à\82\82ã
+                                       //ThreadItem.Round := ini.ReadBool('Setting', 'Round', False);
+                                       //ThreadItem.RoundName := ini.ReadString('Setting', 'RoundName', ThreadItem.RoundName);
+                                       ThreadItem.UnRead := False;//ini.ReadBool('Setting', 'UnRead', False);
+                                       ThreadItem.ScrollTop := ini.ReadInteger(SECTION, 'ScrollTop', 0);
+                                       ThreadItem.AllResCount := ini.ReadInteger(SECTION, 'AllResCount', ThreadItem.Count);
+                                       ThreadItem.NewResCount := ini.ReadInteger(SECTION, 'NewResCount', 0);
+                                       ThreadItem.AgeSage := TGikoAgeSage(ini.ReadInteger(SECTION, 'AgeSage', Ord(gasNone)));
+                               finally
+                                       ini.Free;
+                               end;
+                               DeleteFile(Boardpath + TmpFileList[i]);
+                       end;
+               end;
+    finally
+        TmpFileList.Clear;
+        TmpFileList.Free;
+    end;
+end;
+{
+\brief User32.dll\82ª\97\98\97p\82Å\82«\82é\82©
+\return Boolean \97\98\97p\82Å\82«\82é\8fê\8d\87\82ÍTrue
+}
+function TGikoSys.CanUser32DLL: Boolean;
+var
+    hUser32 : HINST;
+begin
+    Result := False;
+       hUser32 := 0;
+       try
+               try
+                       hUser32 := LoadLibrary('User32.dll');
+                       if hUser32 <> 0 then begin
+                               Result := True;
+            end;
+               except
+               Result := false;
+               end;
+       finally
+               FreeLibrary(hUser32);
+       end;
+end;
+{
+\brief  OE\88ø\97p\95\84\8eæ\93¾
+\return OE\82Ì\88ø\97p\95\84\81i\90Ý\92è\82³\82ê\82Ä\82¢\82È\82¢\8fê\8d\87\82Í'>')
+}
+function TGikoSys.GetOEIndentChar : string;
+var
+       regKey                  : TRegistry;
+       Identities      : string;
+       IndentChar      : DWORD;
+const
+       DEFAULT_CHAR    = '> ';
+       OE_MAIL_PATH    = '\Software\Microsoft\Outlook Express\5.0\Mail';
+       INDENT_CHAR             = 'Indent Char';
+begin
+
+       Result  := DEFAULT_CHAR;
+       regKey  := TRegistry.Create;
+       try
+               try
+                       regKey.RootKey  := HKEY_CURRENT_USER;
+                       if not regKey.OpenKey( 'Identities', False ) then
+                               Exit;
+                       Identities                      := regKey.ReadString( 'Default User ID' );
+                       if Identities = '' then
+                               Exit;
+                       if not regKey.OpenKey( Identities + OE_MAIL_PATH, False ) then
+                               Exit;
+                       IndentChar := regKey.ReadInteger( INDENT_CHAR );
+                       Result := Char( IndentChar ) + ' ';
+               except
+               end;
+       finally
+               regKey.Free;
+       end;
+
+end;
+//! \92u\8a·\90Ý\92è\83t\83@\83C\83\8b\8eæ\93¾
+function TGikoSys.GetReplaceFileName: String;
+begin
+    Result := Setting.GetReplaceFileName;
+end;
+//! \83v\83\8c\83r\83\85\81[\8ag\92£\82Ì\90Ý\92è\83t\83@\83C\83\8b\8eæ\93¾
+function TGikoSys.GetExtpreviewFileName: String;
+begin
+    Result := Setting.GetExtprevieFileName;
+end;
+
+//! \83t\83@\83C\83\8b\96¼\82©\82ç\82Ì\83X\83\8c\83b\83h\8dì\90¬\93ú\82Ì\8eæ\93¾
+function TGikoSys.GetCreateDateFromName(FileName: String): TDateTime;
+var
+    tmp : String;
+    unixtime: Int64;  
+begin
+    // \83\8d\83O\83t\83@\83C\83\8b\82Ì\8ag\92£\8eq\82ð\82Í\82¸\82µ\82½\82à\82Ì\82ª\83X\83\8c\8dì\90¬\93ú\8e\9e
+    tmp := ChangeFileExt(FileName, '');
+    if AnsiPos('_', tmp) <> 0 then
+        if AnsiPos('_', tmp) > 9 then
+            tmp := Copy(tmp, 1, AnsiPos('_', tmp)-1)
+        else
+            Delete(tmp, AnsiPos('_', tmp), 1);
+
+    if ( Length(tmp) = 9) and ( tmp[1] = '0' ) then
+        Insert('1', tmp, 1);
+
+    unixtime := StrToInt64Def(tmp, ZERO_DATE);
+    Result := UnixToDateTime(unixtime) + OffsetFromUTC;
+end;
+
+procedure TGikoSys.ShowRefCount(msg: String; unk: IUnknown);
+{$IFDEF DEBUG}
+var
+    count : integer;
+{$ENDIF}
+begin
+    if not Assigned(unk) then
+        Exit;
+
+{$IFDEF DEBUG}
+    try
+        unk._AddRef;
+        count := unk._Release;
+
+               Writeln(msg + ' RefCount=' + IntToStr(count));
+    except
+               Writeln(msg + ' RefCount=exception!!');
+       end;
+{$ENDIF}
+end;
+function TGikoSys.GetBoukenCookie(AURL: String): String;
+var
+       Protocol, Host, Path, Document, Port,Bookmark : String;
+begin
+    Result := '';
+    GikoSys.ParseURI(AURL, Protocol, Host, Path, Document, Port,Bookmark);
+    if ( Length(Host) > 0 ) then begin
+        Result := Setting.GetBoukenCookie(Host);
+    end;
+end;
+procedure TGikoSys.SetBoukenCookie(ACookieValue, ADomain: String);
+begin
+    if ( Length(ADomain) > 0 ) then begin
+        Setting.SetBoukenCookie(ACookieValue, ADomain);
+    end;
+end;
+//! \96`\8c¯\82Ì\8f\91Domain\88ê\97\97\8eæ\93¾
+procedure TGikoSys.GetBoukenDomain(var ADomain: TStringList);
+var
+    i : Integer;
+begin
+    ADomain.Clear;
+    for i := 0 to Setting.BoukenCookieList.Count - 1 do begin
+        ADomain.Add( Setting.BoukenCookieList.Names[i] );
+    end;
+end;
+//! \96`\8c¯\82Ì\8f\91Cookie\8dí\8f\9c
+procedure TGikoSys.DelBoukenCookie(ADomain: String);
+var
+    i : Integer;
+begin
+    for i := 0 to Setting.BoukenCookieList.Count - 1 do begin
+        if ( Setting.BoukenCookieList.Names[i] = ADomain ) then begin
+            Setting.BoukenCookieList.Delete(i);
+            Break;
+        end;
+    end;
+end;
+function TGikoSys.GetBouken(AURL: String; var Domain: String): String;
+var
+       Protocol, Host, Path, Document, Port,Bookmark : String;
+    Cookie : String;
+begin
+    Domain := '';
+    Cookie := '';
+    GikoSys.ParseURI(AURL, Protocol, Host, Path, Document, Port,Bookmark);
+    if ( Length(Host) > 0 ) then begin
+        Setting.GetBouken(Host, Domain, Cookie);
+        Result := Cookie;
+    end;
+end;
 
 initialization
        GikoSys := TGikoSys.Create;
 
 finalization
        if GikoSys <> nil then begin
-               GikoSys.Free;
-               GikoSys := nil;
+               FreeAndNil(GikoSys);
        end;
 end.