[cci]motionUpDown[/cci]。
テキストエディタはカーソルの行位置・桁位置を管理保持する。このとき桁位置に関して、メモ帳のようなシンプルなエディタ以外はたいてい、カーソルの本来の桁位置とは別に架空の桁位置を持っている。この架空の桁位置は、カーソルが水平移動した時にカーソルの本来の桁位置に同期する。カーソルが垂直移動した時は変更されず、かつカーソルの桁位置は架空の桁位置に最も近い位置に算出される。
これで何が良くなるのかというと:
aaaaaaaaaaa
bbbbbbbbbbb
なんてテキストの先頭行の最終桁にカーソルがあった時、最終行の最終桁近辺を編集したくなったとする。そこで、下矢印キーを 2 回押すわけだが。架空の桁位置がないと中間の行でカーソル位置が行頭に固定されてしまい、最終行に達した時にはわざわざ最終桁へ移動させる手間が増えてしまう。架空の桁位置の仕組みがあると、最終行にカーソルが移動した時その桁位置は架空の桁位置に最も近い位置に再生されて、無駄なカーソル移動をしなくて済むというわけだ。このとき、絶対に等幅のフォントでしか描画しない!というわけでなければ、架空の桁位置はピクセル単位で保持することになる。そういうわけで、「あるピクセル位置に最も近い、文字列上の桁位置」というのを算出する処理が必要になる。
処理の内容は、素朴に考えれば、文字列の先頭から1文字ずつ切り出すループを設け、その部分文字列の offsetWidth を出し、それが基準ピクセル位置を超えていたならば、超える直前の offsetWidth と比較して距離が近い方を採用し、それに対応するループカウンタが結果の桁位置になる……という感じになる。
しかしこのまま組むと結構遅い。offsetWidth というのはそんなに軽くないメソッドなので、100 文字あったら 100 回 offsetWidth を呼ぶというのは避けなければならない。
で、実は [cci]motionUpDown()[/cci] はすでにそうなっていて(offsetWidth の呼び出しが算出される桁位置の log2 〜 2log2 で収まるようになっている)、それを Unistring を使うように修正する必要があり、そうした。
この修正は、折り返し行単位でのカーソルの上下移動とも関わるのでこれで終わりではない。
* * *
そういうわけで、その辺の諸々を更新。