Home > Latest topics

Latest topics > ルーラーバーで折り返された行のカーソル位置を正しく表示できるようになったよ

宣伝。日経LinuxにてLinuxの基礎?を紹介する漫画「シス管系女子」を連載させていただいています。 以下の特設サイトにて、単行本まんがでわかるLinux シス管系女子の試し読みが可能! シス管系女子って何!? - 「シス管系女子」特設サイト

ルーラーバーで折り返された行のカーソル位置を正しく表示できるようになったよ - Oct 11, 2008

ルーラバーだとやっぱり行ったことのある場所に行くあの呪文しか思い浮かばないという声があったので、日本語名をルーラーバーに変えた。

そのルーラーバーなんだけど、Rulerrrrrでもあった「折り返された次の行の先頭にカーソルがある時や行末にカーソルがある時にルーラー上の現在位置表示がおかしくなる(カーソル位置の計算に失敗する)問題」に真面目に取り組んで、0.2.2008101101でだいぶ改善した。

背景

ルーラーバーもRulerrrrrも、現在のカーソルの位置を計算するのには選択範囲を使っている。FirefoxやThunderbirdではカーソル位置をJavaScriptから直接取得することはできないんだけど、現在カーソルがある位置は長さ0の選択範囲として取得できるので、選択範囲が含まれているノードとか選択範囲の開始・終了位置などからどうにかこうにかして「カーソルより前に何文字あるか」を数えて、カーソル位置を割り出している。

行末にカーソルがある時

行末にカーソルがある時にカーソル位置が0(行頭)と判定されてしまっていたのは、この選択範囲から選択範囲が含まれているノードを取得できないせい。どういう事かというと、行末にカーソルがある状態というのは「テキストノード」「改行のBR要素」「テキストノード」という順番にノードが並んでいてBR要素の直前に長さ0のRangeがあるという状態で、「選択範囲が含まれているノード」は前後の要素やテキストノードではなくいきなりBODY要素になってしまう、ということでカーソル位置の求めようがなくなっていた。

そこで、TreeWalkerを使って各行のテキストノードやBR要素を走査し、compareBoundaryPoints()でそのノードがカーソルに隣接しているかどうかを調べる、という風な処理を入れてみた。これにより、行末にカーソルがある時でもカーソルより前にある文字を数えられるようになった。

折り返された行の行頭・行末判別

折り返された行の処理はもうちょっと厄介だった。普通に考えたら、「カーソル位置より前の文字数÷折り返し文字数 の余り」でカーソルの現在位置が分かるはずなんだけど、実際にはこれだけじゃダメだった。FirefoxやThunderbirdのエディタ機能では、折り返された行の行末にカーソルがある時に右キーを押すと、次の文字(折り返された次の行の先頭文字)の後の位置にカーソルが移動するのではなく、次の文字の前・仮想的な改行文字の後にカーソルが移動してしまう。折り返された後の行頭で左キーを押した時も同様。なので、いくら文字数ベースで計算しても、今「折り返された行の折り返し直前にカーソルがある」のか「折り返された後の行の先頭にカーソルがある」のかは分からない。

幸い、選択範囲の変更(=カーソルの移動)を監視する時にはその選択範囲の変更が発生したユーザの操作の種類がある程度分かる。なので、マウス操作でのカーソル移動については、行の左の方でのクリックでカーソルが移動した時は行頭、そうでなければ行末と判定するようにした。また、キー操作でのカーソル移動については、「直前にいた位置が行頭・行の中程・行末のどれだったか」と「どのキーが押されたか」の組み合わせを元に、今カーソルがどの位置にあるかを推測するようにした。

英単語等があるせいで予定の文字数より前で折り返しが発生した時や、HTMLでプロポーショナルフォントが使用されている時、画像がある時などについてはもう完全にお手上げです。カーソルの位置をピクセル単位で取れるようなAPIが付いてくれないことには、もうどうにもなりません。

分類:Mozilla > 拡張機能 > rulerbar, , , , , , , 時刻:21:51 | Comments/Trackbacks (2) | Edit

Comments/Trackbacks

カーソルの位置をピクセル単位で取れる

> カーソルの位置をピクセル単位で取れるようなAPIが付いてくれないことには、もうどうにもなりません。

その位置に一時的に空のspan要素を挿入してそのノードのoffsetLeftを取得するのではだめですか?

Commented by takeshi at 2008/10/12 (Sun) 02:34:51

no title

最初はその方法も考えていて、XUL/Migemoで検索にヒットした位置を画面の真ん中の方に持ってくる処理で実際に同じ事をやったという実績?もあるんですけど、テキストノードが分割されると選択範囲が消失するのでその復帰やら何やらで色々面倒なことになる、という問題とか、それが頻繁に起こるとパフォーマンスが低下するんじゃないかという心配(文字書きという、少しの遅延が大きなストレスを生みかねない部分でのことですから、なおさら)だったとか、なるべくなら元の文書構造には手を入れたくないという個人的な思い入れ+技術的チャレンジとか、それだけ苦労して対応してもだいたい自分はHTMLメール使ってないからそれほど困ってないとか(ぉぃ)、いくつかの理由でこうした次第です。

Commented by Piro at 2008/10/12 (Sun) 03:17:06

TrackBack ping me at


の末尾に2020年11月30日時点の日本の首相のファミリーネーム(ローマ字で回答)を繋げて下さい。例えば「noda」なら、「2008-10-11_wrapped.trackbacknoda」です。これは機械的なトラックバックスパムを防止するための措置です。

Post a comment

writeback message: Ready to post a comment.

2020年11月30日時点の日本の首相のファミリーネーム(ひらがなで回答)

Powered by blosxom 2.0 + starter kit
Home

カテゴリ一覧

過去の記事

1999.2~2005.8

最近のコメント

最近のつぶやき