履歴レイヤ (HistoryLayer) を拡張する [ExtHistoryLayer] プラグイン はじめに: ExtHistoryLayerは、KAGデフォルトのHistoryLayerと似て非なる履歴 レイヤ実装で、HistoryLayerに以下の機能を追加する。  ・横書き・縦書き両対応  ・スクロールバーで履歴移動(横書き時は右、縦書き時は上に配置)  ・スクロールボタン画像指定(指定しなくてもよい)  ・履歴背景画像指定(指定しなくてもよい)  ・履歴中フォント色の動的変更  ・履歴中フォントサイズの動的変更(ただし最大で一行幅までに自動補正)  ・履歴中の太文字フォント  ・履歴上のルビ  ・履歴上にボタンを設置可能(押すと音声を流すなどの用途に)  ・スライダの上下空白部分を押すとpageが変わる  ・スライダ上でクリックした場合にその位置を覚えてスクロール  ・メッセージ画面の[font][ruby]などをそのまま履歴に反映可能  ・メッセージ画面のみ、ヒストリ画面のみの変更タグを用意  ・拙作eruby.ksがあれば読み込んで拡張  ・erubyに従い、履歴中ではルビ割付も、均等割り・左寄せ・右寄せが可能  ・履歴画面表示時にメッセージ画面を消去可能  ・履歴画面の文字間に画像を配置可能  ・表示・消去時にフェード(def=200ms)可能  (以下1.99からの新機能)  ・履歴中で文字に影をつけたり、袋文字にすることが可能  ・対象文字列が改行するとルビも改行される  ・縦書き時、縦中横([hch]タグ)に対応  ・[graph]タグをそのまま履歴に反映  ・Home/Endで最初・最後のページを表示 使い方: ExtHistoryLayer.ks を用意して、first.ks の最初で、以下を実行。 [call storage=ExtHistoryLayer.ks] これで、履歴レイヤ専用の KAG タグ(後述)が有効になり、また、メッセージ 画面のフォント設定・ルビがそのまま履歴に反映されるようになる。 eruby.ks(追加でRenameKAGTag.ksが必要)もあれば、追加で勝手に読み込む。 設定: system/Config.tjs の末尾、HistoryLayer_config() 内の 「[start-historylayer-additionals]と[end-historylayer-additionals]で 囲まれた部分」に、以下の設定を追加することをお勧めする。追加しなければ デフォルト値(下で設定している値)が使用される。それ以外の値は、 HistoryLayer_config() 内で定義されているものに従う。 ※Config.tjsのデフォルト設定だと、lineHeight=26、fontHeight=24なので、  rubyHeight=10、rubyOffset=-2では一行を超えてしまう。少なくとも  lineHeight=32以上に変更する必要がある。  if(typeof(.ExtHistoryLayer) != 'undefined' && this instanceof "HistoryMessageLayer") { historyColor = 0xffffff; // 履歴フォント色 hbColor = 0x808080; // 履歴ボタン色 hbCaptionColor = 0xffffff; // 履歴ボタンキャプション色 rubyName = "MS P明朝"; // ルビフォント名 rubyBold = true; // ルビ太字細字 rubyHeight = 10; // ルビサイズ rubyOffset = -2; // -の値で本文に近づく marginL = 12; // 左マージン marginR = 12; // 右マージン marginT = 12; // 上マージン marginB = 12; // 下マージン // 文字の影設定(ルビも含む) // 袋文字にするならオフセット=0、幅=3、Level=1024とかにする // 影をつけるなら、履歴のlineHeightをrubyHeight+fontHeightより // 大きくしないと、履歴中で次の行がかかって見栄えが悪くなる shadowLevel = 0; // 影レベル shadowColor = 0x000000; // 影の色(0xRRGGBBで指定)   shadowWidth = 0; // 影の幅 shadowOffsetX = 0; // 影の横方向オフセット shadowOffsetY = 0; // 影の縦方向オフセット  } 更に、ExtHistoryLayer 本体の設定は、Config.tjsの末尾に ExtHistoryLayer_config() という関数を追加して、その中で設定する(任意)。 設定項目は以下の通り。以下の設定値がデフォルト。 function ExtHistoryLayer_config() { // 履歴中メッセージレイヤを隠すかどうか(def=false(隠さない)) hidemessage = false; // 背景画像ファイル名(""で指定なし) bggraphic = ""; // 背景色(背景画像bggraphicを指定すると無効) bgColor = 0xc8000000; // 履歴メッセージウィンドウの座標(Infinityでdefault値を表す) messageTop = Infinity; // def = scrollbarHeight messageLeft = Infinity; // def = 0 // 履歴メッセージウィンドウの大きさ(Infinityでdefault値を表す) messageWidth = Infinity; // def = kag.scWidth - scrollbarHeight messageHeight = Infinity; // def = kag.scHeight // クローズボタンの画像ファイル名(""で指定なし) closegraphic = ""; // クローズボタンの座標(Infinityでdefault値を表す) closeButtonTop = Infinity; // def = 0 closeButtonLeft = Infinity; // def = kag.scWidth-closeButton.width; // prevボタンの画像ファイル名(""で指定なし) prevgraphic = ""; // nextボタンの画像ファイル名(""で指定なし) nextgraphic = ""; // スクロールバーのスライダー画像ファイル名(""で指定なし) slgraphic = ""; // Scrollbarのボタン色(メッセージレイヤの履歴ボタンなども含む) buttonColor = 0x808080; // Scrollbarのボタンキャプション色(ボタン画像を指定すると意味なくなる) buttonCaptionColor = 0xffffff; // スクロールバー幅(sbbggraphicが指定されていると無視される) scrollbarHeight = 16; // スクロールバー背景色(画像btnなら画像に合わせるので未使用) scrollbarBack = 0x80404040; // スクロールバー背景画像ファイル名 sbbggraphic = ""; // フェードイン・アウトする時間(ms) fadetime = 200; } KAGタグリファレンス: [history output= enabled= historytag= bggraphic= closegraphic= prevgraphic= nextgraphic= slgraphic= sbbggraphic= fadetime= clear=] 機能: [history]タグを拡張し、色々パラメータを追加。「色々 パラメータ」には、HistoryLayer(ExtHistoryLayer含む)の プロパティが全て指定可能(ただし、KAGParserの制限で全小 文字のプロパティに限る)。指定してあると何も考えずに上書き するので注意。 引数: output= デフォルトと同じ enabled=デフォルトと同じ。ただし、[font]などでサイズ変更中に 状態を変更すると、その部分の履歴フォントが正しく設定 されないので注意。 hidemessage=true|false(def) 履歴画面表示時、メッセージ画面を消去するかどうか。 そういう要望が多かったので…。 historytag=true(def)|false [font]や[ruby]などのメッセージ画面への記述変化を、 履歴画面にも反映するかどうか。起動直後は true(反映する) 反映する場合、メッセージ画面に対して例えば [font] を 使うと、ヒストリ画面には同時に自動的に [hfont] が 指定されたこととして扱う。このパラメータが true の場合 [hfont][hruby]などを指定する必要はない。 bggraphic= 履歴画面の背景画像。デフォルトは黒の半透明。 ""を指定することでデフォルトに戻せる。 Config.tjsで指定してあれば改めて指定する必要なし。 closegraphic= 右上のcloseボタン画像指定。デフォルトはcaption"×"。 横書きの時は横幅がスクロールバー幅に、縦書きの時は 縦幅がスクロールバー幅に設定される。 Config.tjsで指定してあれば改めて指定する必要なし。 prevgraphic= スクロールバーに付属の「前へ」ボタン画像指定。 デフォルトはcaption">>"or"▲" Config.tjsで指定してあれば改めて指定する必要なし。 nextgraphic= スクロールバーに付属の「次へ」ボタン画像指定。 デフォルトはchaption"<<"or"▼" Config.tjsで指定してあれば改めて指定する必要なし。 slgraphic= スクロールバーのスライダーの画像指定。デフォルトは 画像なしのボタン。 スライダー画像は、縦書きなら「上+中1dot+下」のボタン 画像であり、内部的には「中」部分を適宜自動コピーする ことでスライダー長を自動調整している。横書きなら 「左+中1dot+右」のボタン画像。 Config.tjsで指定してあれば改めて指定する必要なし。 sbbggraphic= スクロールバーの背景画像指定。デフォルトは黒の半透明。 指定されているとスクロールバーの大きさが変わってしまう ので、指定する時はスクロールバーの大きさに合わせること。 ちなみに、スクロールバーは「前へボタン」+「スライダー」 +「次へボタン」であり、この背景はこれら全てのボタンの 背景であることに注意(スライダーだけの背景ではない) Config.tjsで指定してあれば改めて指定する必要なし。 fadetime= 履歴をフェードイン・アウトする時の時間(ms)。def=200(ms) clear=true 履歴をクリアする [hfont color= size= bold= face= align=] 機能: ヒストリのフォント属性を変更する。メッセージ画面には影響を 与えない。[history historytag=true] の場合、あえてこれを 指定しなくとも、メッセージ画面での[font]設定にあわせて 属性は自動的に変更される。 [cm][ct][er]などで[resethfont]が自動実行されて[hfont]の 属性はリセットされることに注意。 引数: color= 色コード(ex. "0xff0000" = 赤) size= フォントサイズ(dot)。一行幅より大きいフォントが指定 されると、自動的に行幅までの大きさに補正される。 ただし、フォントサイズが大きくてルビがあって一行を ハミ出してしまった場合、スクロールさせた時にmargin 部分にゴミが残ることがある…。仕方ないんだよぅ。 bold= 太字にするかどうか(true/false)。 face= フォント名。"MS ゴシック" とか。 align= ルビの割付アラインを指定。 c=center 中央割付(デフォルト) l=left 左寄せ(縦書きの時は上寄せ) r=right 右寄せ(縦書きの時は下寄せ) e=expand 均等割付 ; 1.45 で [endhfont] を廃止 ; [endhfont] ; 機能: [hfont]で変更したフォント属性をひとつ前に戻す。メッセージ ; 画面には影響を与えない。[hfont]と対応する数設定する必要あり。 引数: なし [resethfont] 機能: [hfont]で変更したフォント属性をデフォルトに戻す。メッセージ 画面には影響を与えない。[hfont]の数と対応する必要なし。 [cm][ct][er]で自動的に挿入される。 引数: なし [hbutton exp=TJSスクリプト graphic=ボタン画像 hint=ボタンヒント idx=] 機能: 履歴上にボタンを表示する。メッセージ画面には影響を与えない。 引数: exp= ボタンがクリックされた時に実行する TJS スクリプト graphic=ボタングラフィック。省略すると caption="▲" が デフォルトになる。なお、ボタンもフォントと同じように、 横書き=下ぞろえ、縦書き=中央揃えになっている。 hint= ボタンヒント idx= ボタン相対位置。デフォルトでは、縦書きなら文字位置に 中央揃え、横書きなら文字位置に下ぞろえで表示されるが、 idx=を指定することで縦書きなら横位置を、横書きなら 縦位置を微調整することができる。単位=ドット。 注意: 現在のところ、一行サイズに収まる大きさでないと、画面最上段・ 最下段にスクロールさせた後戻した時におかしくなる。表示され なかったり、二重に表示されたり。 [hruby text=ルビ文字列 str=ルビ対象文字列] 機能: 履歴上にルビを振る。デフォルトではMS 明朝 10 point。 [history historytag=true] の場合、あえてこれを指定しなくとも、 メッセージ画面での[ruby]や[eruby]にあわせて自動的に描画される。 メッセージ画面には影響を与えない。 引数: text= ルビ文字列。 str= ルビ対象文字列。省略すると「次の一文字」が対象となる。 width= ルビ対象文字列の幅(縦書きの時は長さ)。内部的に使うだけ。 制限: ・文字サイズを大きく変更した文字列にルビを振ると、履歴上の  ルビ表示が切れることがある ・3行以上に亘る長いルビを振ると暴走する。途中で分割すること。 ・ルビ対象文字列は中間では改行されず、改行が必要な場合は  その前で改行される。 ・ルビ振り対象文字列は、ルビ振り開始から終了までフォント  属性の変更はできない(できちゃうけどおかしくなるはず)。 [hlocate pos= ipos=] 機能: 履歴レイヤ上の同一メッセージライン上で次の描画位置を指定する。 引数: pos= 行先頭からの絶対位置(dot数) ipos= 現在位置からの相対位置(dot数) 備考: ・同一行中でしか指定できない(次の行・前の行には移動できない) ・マイナス方向も指定できる あと、[hact][endhact]はデフォルトと同じ。 この他、KAGの[font]、[resetfont]、[ruby]タグに、以下の引数が追加される nohistory=true|false 履歴画面にこのタグ効果を出力するかどうか。 先で述べた [history historytag=true] の場合でも、この引数 nohistoryがfalseであれば、履歴画面に変更を反映しない。 [font nohistory=true]と指定した場合、対応する[resetfont]にも [resetfont nohistory=true]と指定しなければならないことに注意。 [himage grahpic=画像 idx=] 機能: 履歴上に画像を表示する。メッセージ画面には影響を与えない。 引数: graphic=画像ファイル。省略不能。画像もフォントと同じように、 横書き=下ぞろえ、縦書き=中央揃えになっている。 idx= 画像相対位置。デフォルトでは、縦書きなら文字位置に 中央揃え、横書きなら文字位置に下ぞろえで表示されるが、 idx=を指定することで縦書きなら横位置を、横書きなら 縦位置を微調整することができる。単位=ドット。 注意: 現在のところ、一行サイズに収まる大きさでないと、画面最上段・ 最下段にスクロールさせた後戻した時におかしくなる。 描画位置関係: 横書きの時は、履歴描画領域は、以下で表される。 描画横幅 = 画面横幅 - marginR - marginL - スクロールバー横幅 描画縦幅 = 画面横幅 - marginT - marginB 描画縦幅がlineHeightの倍数でない場合はmarginBが自動補正される 縦書きの時は以下の通り。 描画横幅 = 画面横幅 - marginR - marginL 描画縦幅 = 画面横幅 - marginT - marginB - スクロールバー縦幅 描画横幅がlineHeightの倍数でない場合はmarginLが自動補正される フォントの描画は、横書きの時は以下の通り。横書きでは、大きさの違う フォントは下ぞろえにされ、一行(rubyHeight+fontHeight)を超える大きさの 文字は補正される。 一行幅 = lineHeight 配置は、上から lineHeight = rubyHeight+fontHeight+余り(>=0) 縦書きの場合は、大きさの違うフォントは中央揃えにされる。 一行幅 = lineHeight 配置は、右から lineHeight = 余り/2+rubyHeight+fontHeight+余り/2 大きなフォントを使用する場合、影や袋抜きを指定する場合は、「余り」を 大きめに取るために、lineHeight を大きくすること。そうしないと、履歴を スクロールさせた場合に文字が切れることがある。 フォントが一行幅に近づいた場合、ルビを振ると一行幅からはみ出る場合が あるため、lineHeightを適当に調整すること。 また、強禁則文字(。、℃など)は行末を無視して描画し、改行しないため、 margin[RB]を大きくとる必要があるかもしれない。 内部的なこと: 履歴は行単位で管理され、タグの配列として格納されている。テキストは [htext text=xxx]の形に変換される。 タグは履歴一行ごとに独立するように中で自動調整される。以下のような 複数行にわたる [hact]があった時、 [hact exp="tf.pushed=1"]ある行から[r]次の行にわたる[endhact]とき これは、以下のように変更されて履歴レイヤに蓄積される。 [hact exp="tf.pushed=1"][htext text=ある行から][endhact] [hact exp="tf.pushed=1"][htext text=次の行にわたる][endhact]とき ルビは更に捻ってあって、内部的にはstr=が必ず指定されるようになって いる。すなわち、 [hruby text=るび]▲を振ります は、以下のように自動的に変更され、蓄積される。 [hruby text=るび str=▲][htext text=を振ります] 速度的な話: 当然ながら、デフォルトのHistoryLayerよりは遅い。どのくらい遅いか、 CoreDuo U2500(1.2GHz)にて、maxLines=2000の時に本文を表示したりセーブ したりしてみた結果が以下の通り。 Default 1460(ms)/履歴2000行セーブx1000回。本文1381行表示/10秒 1.99c 5208(ms)/履歴2000行セーブx1000回。本文1253行表示/10秒 加えて、栞から読み込む時に、このCPUだと1.99cで2秒ちょっと(Default では1秒ちょっと)固まることがあった。やっぱり重い。その覚悟は必要。 あと、maxLines=2000、maxHistoryOfStore=5 だと、1.99ではkrkr.exeが 100MBくらい余計にメモリを食うことがある。これは仕組み上防げない…。 そもそも data/system/Config.tjsのmaxLinesは1000か、できれば500 くらいで十分だと思うんだがどうか?そうすれば早くなるし、セーブ データも小さくなるし。 四方山: そろそろ行単位の履歴でやれることは尽きてきた気がする…。履歴表示の 時に履歴画面全部描画して一部だけ表示する、のようにすれば色々便利 (行をまたぐボタンとかイメージとかを配置できる)なんだけど、そうすると 重くなるしねぇ…。2000行表示で一行ごとにボタンがあったらレイヤが 2000個同時表示になっちゃうし…。何かいいアイディアないかしら。 変更履歴: 2014/11/06 1.99k・改行直後に[hruby]が続いた時にルビ振りに失敗していた  のを修正 2014/10/30 1.99j・maxLinesのデフォルト値を1000に変更。2000だと重い… ・起動直後も履歴が見れるように、ExtHistoryLayerFadeの  startFadein()でowner.visibleもチェックするよう修正 2014/03/29 1.99i・テキストボタン経由でkag.close()した際に、ヒストリを  フェードアウトで非表示にしようとしてエラーとなって  いたのを修正 2014/02/22 1.99h・config.tjsでeverypage=trueのときに正しくページ  ごとに履歴が作成されていなかったのを修正 2014/01/25 1.99g・[graph][himage]の横幅が0になっていたのを修正 2013/09/24 1.99f・[history historytag=true/false]がエラーになっていた  のを修正 2012/10/08 1.99e・[showhistory]タグで表示できていなかったのを修正 2012/09/30 1.99d・ページ表示(everypage=true)時にprev/nextボタン押しで  エラーとなっていたのを修正 ・drawPage()/drawLinesInThePage()でclearBack()と  parent.updateButtonState()を実行するよう修正 ・setOptions()中で実行していた無駄なdispLines/magineL  の計算を削除 ・lastPage()/firstPage()を新設、Home/Endボタンで最初・  最後のページを表示するようにした ・dispInit()からlastPage()を呼ぶようにした ・dispPage()の引数にdispStartを渡せるようにした 2012/09/10 1.99c・セーブを高速化 ・履歴のスクロール速度を高速化(画面毎のスクロールを  可能に) 2012/09/06 1.99 ・新機能のために内部構造を大きく変更 ・履歴中で文字に影をつけたり、袋文字にすることが可能 ・対象文字列が改行するとルビも改行される ・縦書き時、縦中横に対応 ・[graph]タグで表示した画像を履歴にも表示するように修正 2012/08/20 1.51 ・"[["が入力された時にエラーとなっていたのに対応 ・[history clear]が動いていなかったのを修正 2012/07/28 1.50 ・NameWindowPluginと一緒に使うと「メンバ "er" が見つかり  ません」とエラーになっていたのを修正 ・eruby.ksを読み込む時以外はRenameKAGTag.ksを不要とした 2012/06/28 1.48 ・フェードで表示・消去できるようにした 2012/06/27 1.47 ・KAG TAGに空白が使えるように変更。font="MS ゴシック"  などの空白に対応した。 2012/05/03 1.46 ・maxLinesが-1判定されていたのを修正 2011/09/22 1.45 ・なぜか[macro name=font]中に[endif]が多かったので削除 2011/08/19 1.44 ・createBack()中でヒストリイメージをpop()していな  かったのを修正 ・[endhfont]廃止、[resethfont]に統一 ・履歴行末は[endhfont]でなく[resethfont]に統一 ・[history]タグに履歴をクリアする引数clear=trueを追加 2011/07/27 1.43 ・storeTag()で引数をmpにしたらグローバルpropertyと  被ったので、mp → tagmp に変更 2011/05/30 1.42 ・RepeatButtonLayer/CommonScrollBarのfinalized()に  timer.enabled = false を追加 2011/05/06 1.40 ・[iscript]中の行頭の * を回避 2011/03/14 1.30 ・スクロールバーの画像を指定可能に変更 ・履歴表示中はメッセージ画面を消去できるように変更 ・画像[himage]追加 ・[hbutton]と[himage]に idx パラメータ追加 ・isInMessageArea() の判定を間違っていたので修正 2011/03/03 1.25 ・ReplaceKAGTag.ks → RenameKAGTag.ks の名前変更対応 2010/12/21 1.24 ・SliderLayerのfinalizeで不要なsetOptions(elm)が  あったので削除。 2010/11/15 1.23 ・縦書き履歴のデフォルト設定で、ScrollbarとClose  ボタンが重なるようになっていたのを修正 2010/08/10 1.22 ・Config.tjs の storeState=true でも履歴がセーブされ  ていなかったのを修正 2010/07/04 1.21 ・kag.historyLayer.clear() でヒストリデータをクリア  していなかったので修正 ・ボタン色を、スクロールバーと履歴ボタンとで分割  ※buttonColor/buttonCaptionColor と   hbColor/hbCaptionColor に分割 ・ExtHistoryLayerで拡張したメンバの値を設定する時は  ExtHistoryLayerが定義されているかを確認するよう  Config.tjs内の記述を変更(プログラムは変更なし) ・強禁則文字の禁則処理ができてなかったのを修正。  これに伴い、強禁則文字が続く場合は行末をはみ  出して描画されるようになった。marginR/Bを大きく  する必要があるかもしれない 2010/07/02 1.20 ・ExtHistoryLayer_config() があれば読み込むように変更  + 履歴クローズボタンの位置変更パラメータ新設  + 履歴メッセージウィンドウの位置変更パラメータ新設  + などなど ・スクロールバーを履歴メッセージの上・右に付属化。これ  に伴い、closeボタン位置が独立した ・[hact]がちょうど次の行から始まる場合にエラーになって  いたのを修正 2010/06/29 1.12 ・デストラクタ中でtimerの invalidate を先頭に移動。  finalize中に timer が動くのを防ぐため。 2010/06/22 1.11 ・稀に dispInit() 中で setMode() に失敗してエラーに  なるのを修正。直前に enabled = true を入れて。 2010/06/20 1.10 ・履歴中のキー入力で履歴上下しなかったのを修正 ・縦書きの時、PageUp/Downでライン移動だったのでページ  移動に変更 ・背景画像が表示されず透明になることがあったのを修正。  実は吉里吉里の深いところに関係してて、大改修となった 2010/06/20 1.02 ・f.transhistorytagが未定義なら、trueと判定するよう変更 2010/06/20 1.01 ・[resethfont]新設 ・[resetfont]の対応を[endhfont]から[resethfont]に変更 ・[cm][ct][er]でもフォント設定をリセットするようにした お願い: ご意見・ご要望・バグ報告歓迎。mixi にメッセージ頂くか、掲示板 http://www.geocities.jp/keep_creating/bbspre.htm に連絡頂くか、 s_naray[at]yahoo[dot]co[dot]jp にメール下さい。