| 2004/04 | ||||||
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | ||||
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | |
| 2004/05 | ||||||
|---|---|---|---|---|---|---|
| 1 | ||||||
| 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| 9 | 10 | 11 | 12 | 13 | 14 | 15 |
| 16 | 17 | 18 | 19 | 20 | 21 | 22 |
| 23 | 24 | 25 | 26 | 27 | 28 | 29 |
| 30 | 31 | |||||
| 2004/06 | ||||||
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | ||
| 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 13 | 14 | 15 | 16 | 17 | 18 | 19 |
| 20 | 21 | 22 | 23 | 24 | 25 | 26 |
| 27 | 28 | 29 | 30 | |||
top > かいはつにっき 2004 Q2
Q2 もいよいよ締めですよー。半年分に見合った成果を出しているのかは、微妙なところかも。。。
あまり意味もありませんが、ソースとバイナリを BSD License にしてみました。
タブを切り替えたとき、1 行バッファがちらついていたのを修正。キャレット位置のガイドラインがちらついていたのを修正。カレント以外のビューを削除するアクションのキャプションがわかりにくかったので「他のビューをすべて削除する」に修正。
実装の度合いから COM コンポーネント云々を削除しました。そのほか、いろいろ現状に合わせて修正。
昨日ののうち、更新していないバッファがアクティブなときに。。。というやつですが。「開く」ダイアログで複数のファイルを選択できるのですが、その場合はどうするか。選択したファイルの最初のものに限って、新規バッファとの置き換えを(必要なら)して、それ以降はバッファリストの末尾に追加?
なんか変なので、「開く」ダイアログで複数のファイルを選択した場合は、常にバッファリストの末尾に追加するようにします。そいで、
あるとき、アクティブなバッファを選択したファイルで置き換えます。
妖精現実 フェアリアルには、たまに Unicode に関するトピックが掲載されるのでためになるなあ。
コマンドラインのリファレンスを追加。なんか酔っ払いながら書いたので間違ってるかもしれません。
サーバスレッドからの呼び出しでファイルを開いた場合、エンコーディング選択とかのダイアログがわけのわからないところに表示されるのを修正。できればコモンダイアログも、アクティブなフォームの中心を基準にして表示してあげたいところなのですが。。。TNT 自体が VCL ネイティブなダイアログを巧妙にいじっているので、どこに手を入れたものかよくわからないよう。
たぶん TNT なダイアログをさらにサブクラス化して CDN_INITDONE あたりでつじつまを合わせればよいのではないか。。。と妄想。
まずタブをどんどん閉じていって、最後の 1 つを閉じた場合、それをアプリケーションの終了とみなしていますが、ええと言われてみるとなんでこういう仕様にしたのか覚えてないなあ。。。WZ で、ctrl+w で終了するのに慣れてるからかな?
ということで、最後のバッファを閉じたら、その代わりに新規バッファで置き換えるようにしてみます。それから、更新していない新規バッファがアクティブなときにファイルを開くと、先に新規バッファを閉じるというのが一般的な仕様っぽいので、今更ながら合わせてみます。
それから、起動したとき前回開いていたバッファをタブに再現しますが、プロパティで切り替えられるようにしてみますね。
Visual Studio .NET に Express 版が出るそうですが、コンパイラが最適化してくれないとかいう落ちだったりしないんですかね。。。?
複数起動防止の続き。やっぱりちゃんとやります。
とりあえず CreateMutex() で mutex を生成/取得します。それからメモリマップトファイルと、イベントオブジェクトも取得します。mutex を生成できれば自分が最初のプロセスなので、サーバスレッドを生成して、通常の起動処理へ。mutex が既存のものであれば自分が 2 番め以降のプロセスなので、メモリマップトファイルにコマンドラインを書き込み(この処理は mutex で排他的に行う)、イベントオブジェクトをシグナル状態にして、終了。
サーバスレッドは生成されると、WaitForSingleObject() でイベントオブジェクトからのシグナルを待ちます。そいで、シグナルを受けたらメモリマップトファイルを見て(ここも mutex で排他的に行う)、メインスレッドで個々のファイルを読み込んでもらったりウィンドウを前面に表示したりします。そして、またシグナルを待つと。
mutex とイベントを使用することで、ほぼ同時にプロセスを複数起動した場合なんかでも正しく動作するようになると思いますが、ふつうに使ってて、そんな状況があるのかな? というとない気もします。まあいいや。
バッファの短いエンコーディング名称を取得しようとして、ぬるぽになっているところ(バッファリストの表示、ini ファイルの更新)をガッしました。Windows2000 以降の NT 系 OS 以外で実行したときメッセージボックスを出すようにしました(とりあえず現状では 9x 系では動かないので)。ini ファイルオブジェクトを二重に生成していたのを修正しました。
コマンドラインスイッチのテストはめどい。
どうでもいいのですがこのページ、3 ヶ月フルに書き込んでいくとだんだん重くなってきますねー。1 ヶ月ごとに分けようかな。
( ◔ิД◔ิ)
こういう風にしてみました。
まず、複数段落を選択しているときは再変換不可で、メッセージを表示して終了します。範囲選択されていない、あるいは字選択以外のモードで選択されているときは、キャレット位置の単語を字選択モードで選択します。
次に、キャレットを選択範囲の左端に移動して、再変換を開始します。
そして再変換が確定した場合、基本的には普通の入力処理へ流れるのですが、
場合、バッファへの送出は行わず、キャレットを選択範囲の右端に移動して、選択を解除します。ただ、これ(再変換をキャンセルしても文字列が入力される)、明らかにおかしな動作なのに手持ちのエディタがすべてそういう風に動作するのは、もしかしたらわたしのマシンがおかしいだけなのかもしれないです。
あと、Caret.Reconvert() というのを追加したので、普通のキーバインドでも再変換を呼び出せるようになります。とりあえず ctrl+D にしてみました。
ところで、これ、ATOK だとどうなるんでしょうか。これをちらっと見る限り、WM_IME_REQUEST でそれなりの処理をしていればそのままだいじょうぶな気がしますが。。。
さて次ですが。。。「検索/置換」「色分け」「Undo/Redo」とすごく面倒なのが残っています。とりあえずこれ以外の、それほど実装に手間のかからないものから優先的に片付けようかな。
コマンドラインスイッチを考えます。CUI だと大量にスイッチを組み込むところなのですが、GUI だと、極端にはファイル名が指定できればそれでよいと思いますが、それでも必要そうなものを考えてみると:
-i --internal-binding-p --ignore-serialized-properties-b --ignore-serialized-buffers-r --readonly-m --moveto row[,col]-f --find string-e --encoding name-c --class nameとこんな感じかな?
あと、同時に考える必要があるのが複数起動のチェックです。萌ディタは複数起動をしません(壁紙とスクリプトエンジンとで、1 つのプロセス自体がけっこうメモリを消費するので。。。)。
で、2 回目以降に起動された exe(クライアント)はとりあえず mutex をチェックしたあと、共有メモリにコマンドラインをコピーしたり最初に起動された exe(サーバ)にイベントを投げたりするので、サーバ側ではそれを受け取るスレッドを裏で走らせておく必要があります。。。が、めんどうだなー。お手軽に FindWindow + WM_COPYDATA にしちゃおうかな。。。
とりあえず分割しようとしているビューのサイズが小さすぎるときは分割させないようにしました。
ビュー上のコンテキストメニューを調整。一応マーク関連とビュー関連を追加しましたが。。。あまりメニューの項目が多いのも、見た目にごちゃごちゃしすぎだし、項目を選ぶためにマウスの移動距離が長くなるので微妙なところです。
再変換を作ってみます。
なんか web を探してみても、いまいち情報がないです。。。MSDN を見てもよくわからないなあ。
とりあえず WM_IME_REQUEST に応答すればいいんですね。で、lParam が null なら RECONVERTSTRING 構造体のサイズ + 変換対象の文字列のサイズを返して、入ってればそれは RECONVERTSTRING を指しているので、ImmSetCompositionString とかで適当に中身をいじってあげればよいと。。。
よくよく考えると、うちには英語のキーボードしかないので WM_IME_REQUEST を出せない(「変換」キーがない)なあ。とりあえず IME のキー設定を出してみると、なんか F13 も再変換に割り当てられているみたいですが、F13 ってなに??
とりあえず選択範囲に対して再変換できるようになりましたが。
など。
ビューの分割のバグを片付けます。
ぎょぎょ。タブの並べ替えじゃなくて位置交換にしちゃっていました。
タブ上のホイールクリックでタブを閉じる機能を実装。ただし、アクティブではないタブの場合はアクティブにするだけです。
メモバッファみたいなのを入れようかなあ。仕様としては、
でもよく考えるとこれ、いわゆる *scratch* の亜種ですね。。。
そいで、ビュー分割のバグですが。これは、原因は、分割したときのサイズが 0 以上であるような assert に引っかかってしまっています。分割後のサイズは、分割前のサイズからスプリッタのサイズを引いて 2 で割って出すのですが、分割前のビューのサイズがもともと小さいと分割後のサイズが負になってしまうわけです。
で、どうするか。むずかしいのは、分割後のサイズが不正になるかどうかは、分割時のウィンドウサイズに依存するということです。なので、あるとき分割したらエラーになるけど、ウィンドウを最大化したら分割できるようになったりするのですが、それも変な話です。分割サイズが負なら 0 に補正すればとりあえず常にエラーにはなりませんが、そうすると見えないビューを多量に生成できてしまう(分割数自体に制限はないので)。うーむずかしいなあ。どこかで制限する必要があるのですが、何をよりどころにして制限するか?
昨日考えた通り、タブのドラッグ&ドロップには 2 種類のパターンがあることになります。そして、ドラッグ中の表示の仕方も微妙に異なってくる。1 つは、ビューでテキストのドラッグを開始し、他のバッファに切り替えてペーストする場合。これは、ドロップの対象がタブ(に対応するバッファ)になるので、ドラッグ中もカーソルの下にあるタブをハイライト表示すればわかりやすいと思います。そいで、ハイライトした状態でちょっと待つとそのタブがアクティブになる。

これに対して、もう 1 つはタブの中でドラッグを開始するタブの並べ替えで、これはドロップの対象がタブとタブの間になるので、タブそのもののではなく、タブの間を強調表示するようにしなければなりません。

というわけでこうなったのですが。せっかくなのでこの他にもタブへのドラッグ&ドロップを活用できないものかな? たとえばエクスプローラからファイルをドラッグするとき、ビューへのドロップは常にバッファリストの末尾に追加する形になりますが、タブへ位置を指定してドロップできるようにするとか。
自分用メモ。-maxdepth 2 を付け足すこともあります。なんかこれで数えたら 40000 行くらいだったなあ。delphi 上で再構築したときに出る 60000 行というのはなんなんだろう。。。
wc -l `find . \( -name "[^$]*.pas" -or -name "[^$]*.dpr" \) -print`
ルーラ上のコンテキストメニューを実装。一応「折り返しなし」というのも実装してみましたが、実は折り返し幅を 32768 にしているだけというのはここだけの秘密ですよ。
マークを用いて、折り返ししなおしてもキャレットの位置を保持するよう修正。
タブのドラッグ&ドロップ(タブの並べ替え)なんかを考えてみます。ええと、タブ型のテキストエディタは多いのですが、ドラッグ&ドロップで並べ替えのできるものはそれほど多くないように思えます。たぶん「エディタなのにマウス操作に凝る必要はない」という潔い割り切りか、「あると便利だけど、ドラッグ&ドロップを組むのがめどい」という位置付けなんじゃないかと(タブ上のメニューからタブを移動できたりするエディタはあるので)。。。
それでも delphi の場合は、基底のコンポーネントにドラッグ&ドロップ用のしくみがすでに用意されていて、単にメソッドをオーバーライドするだけで済むのでまだ簡単なほうだと思います。ただ、それは VCL 内で完結するドラッグ&ドロップであって、OLE ドラッグ&ドロップではないところがミソ。
タブに対して OLE ドラッグ&ドロップができると何がうれしいのかというと、タブの並べ替えに加えて、ドラッグ&ドロップを用いてあるバッファから異なるバッファへのカット/コピーが行えるようになるということです。実はこれは、わたしが思いついたわけではなくてマイナーテキストエディタ愛好会での要望なのですが、確かに便利そうなので作ってみようと思います。
で、ビューで文字列をドラッグして、それをタブにもってくるとカーソルの下のバッファに切り替わってくれればいいのですが、
というところが気になります。1. は、カーソルがタブの上に一定時間位置していた場合に切り替えるという風にすればいいかな? 2. は、タブ用のスクロールボタンがあるのを利用して、ボタンの上に一定時間位置してたらその機能を呼び出し、とかにしてみます。
あと気になるのは、タブを切り替えるためにカーソルをビューの外に持っていって、ビューがスクロールしてしまうのがやだなあという点でしょうか。うーん。ちょっと苦しいですが、Alt を押しているときはスクロールしないという風にすればいいかな?
ええと、最後の nightly build から増えた機能のまとめ。部分的にまだ実装しきれていない(矩形形式の段落単位の貼り付けとか)ところもありますが。。。
スクリプトファイル std.javascript.txt もキーバインドの追加に併せて更新しています。まだこのファイルをいじっているひとはいないと思いますが、念のため気をつけてくださいね。いじっていなければ、単純に上書きでかまいません。
ふと気づいたのですが、異なるエディタ間で矩形の選択範囲をドラッグ&ドロップってできないものなのかも? とりあえず矩形を MSDEVColumnSelect で認識するエディタ同士(例えば、サクラエディタと cannia とか)ならだいじょうぶかなーと思ったのですが。。。ドロップ時は MSDEVColumnSelect をみてくれるわけではないのかな。
あ。ビューを分割して同じバッファを見ているとき、一方で範囲選択し、他方で挿入とか削除しても範囲が追従しないですね。
せっかくマークの仕組みを作ったので、選択範囲もマークの一種にしてしまえばとりあえず解決策の 1 つにはなるのですが。。。そもそも、異なるビューの間で選択範囲の端点は共有したほうがいいのか、独立させたほうがいいのか。
これはむずかしいです。共有させるとすると、キャレットの位置は当然ビューごとに独立しているので、選択範囲とキャレット位置が離れてしまうことがありえます。かといって、独立させたとしても、それで何かメリットがあるのかなというと、あまりない気もする。
これはきっと、1 つのバッファの選択範囲を操作する複数の窓口が存在してしまったり(選択範囲の共有の場合)、同時に異なる選択範囲を作ったり(独立した選択範囲の場合)のどちらも不自然なんだと思います。選択範囲はビュー(群)につき 1 つだけに限ったほうがよいのではないか。
ということで、それを実現するのですが。例えば 1 つの案としては、ビューを切り替えたときに範囲選択を解除するようにするとか。でもそれはそれで不親切のような。。。というか間違えてビューを切り替えたときに勝手に範囲選択が解除されたらむかつきそうです。さらに、別のバッファを指しているビューへの切り替えであれば、選択範囲をそのままにしても別に問題ないのです。
ということで、ない知恵を絞って考えましたが。。。「選択範囲はビュー(群)につき 1 つだけに限る」というのは、「アクティブでないビューに選択範囲が設定してあることを許さない」と同じではないのです。で、とりあえずバッファとそれを見ているビューの間には双方向のリンクがある(バッファ側が、自分を見ているビューのリストを持っている)のでそれを利用してビューの間で調停することにします。そいで、
という前提のときに、アクティブなビューで選択を開始しようとしたタイミングで、
という動作にしようかと思います。
なんか矩形選択を作る過程で直接にはあまり関係ない部分をいろいろいじってるので、矩形選択そのものの処理を忘れてしまいました。。。とりあえず IDropTarget.Drop() をちょっと修正。
矩形選択が片付いたらまた公開かな? 時期的には。
マークが動き始めてきました。とりあえず設定項目に表示色を追加。
あと考えているのは、ユーザが設定できるマークとしては 1 〜 9 の 9 種類なのですが、0 番のマークというのもあります。これはアプリケーションが暗黙的に使用したらどうかなーと。例えば検索とか、指定の行へ移動とかで大きくキャレットがジャンプするとき、元のキャレット位置を自動的にマーク 0 へ登録しておくとか。
それから、マークの一覧のような専用のウィンドウとかが必要かなあ。いらない気もしますが。
メニューにも組み込み。「次のマークへ移動」「前のマークへ移動」「マークをすべてクリア」実装。
ということで、矩形選択に戻ります。
マークの続き。マークを設定した文字を削除する場合について。
マークを設定した文字を|削除する場合について。 ↑この字を削除
「削」の字にマークをつけてあり、キャレットがその前にあります。そして、「削」の字を削除した場合、マークはどうなるか。
これは、キャレットと同様、マークの指すものが厳密には文字ではなく文字と文字の間の空間ということを考えると、どちらかというと 2 かなーと。たぶん。
逆に、
マークを設定した文字を|削除する場合について。 ↑この字を削除
「を」の字にマークをつけてあり、キャレットがその後ろにあります。そして、「を」の字を削除した場合もマークが消えるわけではないです。
一般化すると、削除される範囲内にあるマークは、範囲の左端に移動するということかな。あと、萌ディタの仕様上は、同じ位置に複数のマークを設定することはない(表示上の問題からですが。。。)ので、複数のマークが左端にまとめられた場合は、最後に移動したマークだけが生きるというのがポイント。
ほかのエディタの挙動も参考にしたいところですが、字単位で、かつテキスト中の位置を保持するタイプのマークづけというと、unix 由来のエディタとかはともかく、Windows 発のものとなるとあまり知らないです。たいていは、行単位だったり、テキスト中の絶対的な位置を保持するつくりだったりという感じでしょうか。
というかそれで十分な気もしますが、もしかして字単位のマークづけってオーバースペックぎみなんでしょうか??
まあ便利といえば便利そうなので、気にせず作ってみます。
ということで、こんな感じに。
キーバインドは、とりあえず Delphi みたいに ctrl+ 1〜9 でそのマークへ移動、shift+ctrl+ 1〜9 でキャレット位置にマークを設定/解除という感じをデフォルトにしてみます。マーク表示がテキストの中に割り込むというエディタはあまりなかったと思うのですが、はたして使いやすいのかどうか? 表示するかどうかは設定で変えられるようにしたほうがいいのかな?
ちょっと使ってみたらキャレットがマークの幅の分だけジャンプするのがとても使いにくいような。ということで、こんな感じにしてみました。これはこれで、あまり小さくするとマークのインデックスが見えないし、大きくすると文字が隠れるので痛し痒し。。。
なんか動き始めてきました。ドラッグ&ドロップはまだ。
「力ずく」でした。はずかしー。
矩形のドラッグ&ドロップを実装しようとしたら、字/行単位用の選択範囲の移動処理はそのままでは流用できないようです。このへんは、6/5 に書いたようなマークの仕組みがあると楽なのですが。。。先に作っちゃおうかな。
クリップボードにあるテキストを取り出すとき、U+0000 が終端になっている前提にしているので、文字列の間にも U+0000 が入っていると途中までしか貼り付けられません。常にメモリにある分だけ取り出すようにしてもいいのですが、コピーするテキストの長さよりも多めにメモリを確保するエディタもあるようなので(Dana とか)、どちらがいいともいえません。
なので、「形式を指定して貼り付け」で、メモリにある分だけ貼り付けるかどうか選べるようにしてみました。。。のですが、いまいち簡潔な説明が思い浮かばなかったので、とりあえず「力ずくでも貼り付ける」にしたらよけい意味不明になってしまった。
例えば折り返し幅 80 カウントの設定のテキストで矩形選択した文字列を、折り返し幅 40 の設定のテキストに貼り付けたらどうなるのかなあ? とか。
クリップボード上のデータに、コピーした文字列が文字単位なのか行単位なのか矩形単位なのかの情報、および文字列の長さを置くようにしてみました。
昨日のあれなのですが。。。とりあえず、基本的には WZEditor / Cannia / PeggyPad / xyzzy などのやり方に合わせてみようかなと。そいで、Office のように「形式を指定して貼り付け...」みたいなのを実装するので、Dana/otbedit のように貼り付けるときはそこで選択してもらうみたいなかたち。EmEditor / TEditor のような貼り付け方は、あまり実用的ではない感じがするので、とりあえず実装しないです。
ハンドルネームうらないをやってみたら、吉だった。「653◆kNifeLBwa2半額処分」にすると大吉らしいです。。。がっかり。
ソースをちょっと整理。選択範囲を操作するメソッドがビュークラスとキャレットクラスに散在しているので、選択範囲クラスとして独立させて、選択モードの更新時にファクトリメソッドから取得するようにした。選択範囲を操作するメソッドは必ず選択モードでの分岐をしているので、選択範囲クラスを親に持つ字単位・行単位・矩形単位クラスを作って、多態で処理するようにした。
なんかクラスの役割分担が、まんま MVC になってしまいました。
とりあえず MSDEVColumnSelect でコピーするようにしてみました。MSDEVColumnSelect でやりとりする他のエディタへ貼り付けられることを確認。TEditor Box Type は、ちょっと保留。
コピーは何も難しくはないのですが。。。切り取りと貼り付けが問題。
1|□□□■□□□□□□□□□□□ |□□□■□□□□□□□□□□□ |□□□■□□□□□□□□□□□ |□□□■□□□□□□□□□□□ |□□□■□□□□□□□□□□□
ええと、折り返して表示されている上のような段落があったとします。そいで、「■」の場所に矩形形式で貼り付けたとすると、
1|□□□■▲▲▲□□□□□□□□ |□□□□□□■▲▲▲□□□□□ |□□□□□□□□□■▲▲▲□□ |□□□□□□□□□□□□■▲▲ |▲□□□□□□□□□□□□□□ |■▲▲▲□□□□□□□□□□□
こんな感じになってしまいます。
上の例は、貼り付ける文字列の各行が挿入されるインデックスを、貼り付ける前の状態の文字列に対して決定した場合です。いいかえると、矩形を意識するのが、貼り付け先の文字列だということです。これを、1行挿入して折り返すごとにインデックスを算出しなおすようにすれば、
1|□□□■▲▲▲□□□□□□□□ |□□□□▲▲▲□□■□□□□□ |□□□□▲▲▲□□□□□■□□ |□□□□▲▲▲□□□□□□□□ |■□□□▲▲▲□□□□□□□□ |□□□■□□□□□□□□□□□
こんな感じになって、少なくとも見た目上は矩形で貼り付けたようになりますが。。。こちらは、矩形を意識するのが貼り付け元ということです。ちなみに、EmEditor は 1 番めの動作、WZEditor は 2 番めの動作をするようです。そのほか、
ふーむむむ。試したエディタの中では少数派ですが、Dana、otbedit もあなどれません。例えば、90 字幅を想定したテキストを、80字幅の環境で開くと
1|□□□□□□□□□□□□□□□ |□□
みたいに、ちょっとだけはみ出す感じになりますが、この段落に対して矩形貼り付けしたとき、多くの場合
1|□□□□□▲▲▲□□□□□□□ |□□ ▲▲▲
こうなるよりは
1|□□□□□▲▲▲□□□□□□□ |□□ 2| ▲▲▲
こうなったほうが自然だと思います。常にそうか、といわれると自信がありませんが。
つまり、どれが正しいのかよくわからない。。。
6/10 で出た矩形選択のポイントの 2. がとてもめどいです。
前提として、まず萌ディタを含むフリーキャレットを認めないタイプのエディタの場合、キャレットが文字列の長さを超えて位置することがありません。超えるようなことがある場合は、自動的に補正されます。
[フリーキャレット禁止] [フリーキャレット許可] あああああ|ああ あああああ|ああ あああ あああ ↓ ↓ あああああああ あああああああ あああ| あああ |
次に、キーボードで選択範囲を指定する場合、範囲の端点はキャレット位置になります。
で、この 2 点を同時に実装すると、キーボードで矩形範囲を指定する場合、キャレット位置によって範囲が大きく縮んだり元に戻ったりして(別にバグとかそういうわけではない)、とても見難いです。


WZEditor やサクラエディタのように、矩形範囲の指定時のみフリーキャレット状態にしてもいいのですが、それはそれでめどいし、統一性があまりなくなるので、単純に「キャレット位置に文字が存在しない場合、選択範囲の大きさを更新しない」というルールにしてみます。
それから、範囲をマウスで指定する場合もけっこう面倒です。素直に書くと、カーソル位置からキャレット位置を出して、キャレット位置から選択範囲を出して更新すればいいのですが、前述のようにフリーキャレット禁止の場合はキャレット位置が補正されてしまうので、6/10 で例を挙げたように狙った矩形を選択できないことがある。
これは、矩形選択の場合はマウスのカーソル位置を直接選択範囲の端点に変換することにしてみました。
ということで、やっと選択周りの基礎的な部分ができたので、次のステップへ進むのですが。。。ここからがまためどい。
たとえば F7 で行単位の選択、とかにしてて、F7 を押した瞬間から選択を開始するようになっていますが、このあたりのしくみをちょっと変えようかと思います。
具体的に言うと、「規定の選択モード」を設けます。これは、スクリプトからは Caret.DefaultSelectMode で参照・変更することができます。で、キーボードから Shift 併用でキャレット移動を行った場合、従来は固定的に字選択モードにしていたのを、この規定の選択モードに移行するようになります。逆に、F7 とかによる選択モードの切り替えは、この「規定の選択モード」を変更するだけになるので、実際に範囲選択を始めるには、字選択の場合と同じように Shift 併用のキー操作をするようになります。
これが何がよくなるのかというと、あまり変わらないのですが、
というあたりです。
なんとなくできてきましたが、もしかして折り返しとプロポーショナルフォントと矩形選択ってとても相性が悪いのでは。。。などなどさらに考えなければならないことは多そうです。

ナビゲータの画像はKK'sWS さん作成のカウンタから作ってみました。
なんか IME Wathcer でキャレット位置に変換モードを出すようにしていると、なぜかダブルクリックの直後にくる WM_MOUSEMOVE がいつもより多いみたいです。マウスが動いてないのにくる。萌ディタの場合、WM_MOUSEMOVE がきても実際にマウスが動いていなければ何もしないようにしているのが功を奏しているということかな?
折り返し位置補正ができた感じ。実は UAX#14 に載っているサンプルコードをそのままポートしただけだったりしますが、とりあえずちゃんと動いているみたい。またひとつ、普通のエディタに近づいた(ただ、すべての文字種の組み合わせについて厳密にテストしたわけではない)。
どうしようかな。きっちりテストするか、次へ進むか。次は矩形選択を片付けようかと思っています。
とりあえず nightly build 出してみます。
矩形選択について妄想だけしてみます。考える必要があるのは、
あたりだと思います。それぞれについて考えます。まず 1。普通のテキストは、クリップボード上では CF_TEXT とか CF_UNICODETEXT とかのフォーマットとして扱われます。これは標準のフォーマットなので、あるプログラム上で生成したデータが普通に他のプログラムでも利用できます。
が、矩形形式のテキストというのは標準では存在しないので、独自のフォーマットを定義することになります。そうすると、他のプログラムが矩形形式と認識しなくなってしまいます。そこで、次善の策として、デファクトスタンダードになっている矩形形式フォーマットに合わせるというやりかたが考えられます。ところで、矩形形式のデファクトスタンダードなフォーマットってなんだろ。手持ちのエディタでちょっと調べてみます。
| alpha | MSDEVColumnSelect |
|---|---|
| cannia | SAKURAClip, MSDEVColumnSelect |
| Dana | フォーマットに区別なし(貼り付けコマンドで分ける?) |
| Delphi 6 | Borland IDE Block Type |
| EmEditor | EmSoftBoxSelectW |
| otbedit | OGAWA_EditCtrl_CF_IS_BOX |
| PeggyaPad | MSVCColumnSelect |
| SpaceEditor | フォーマットに区別なし(貼り付けコマンドで分ける?) |
| TEditor系 | TEditor Box Type |
| Visual Studio 6 | MSDEVColumnSelect |
| WZEditor | WZ4_CF_TEXTWZ |
| xyzzy | フォーマットに区別なし(貼り付けコマンドで分ける?) |
| サクラエディタ | SAKURAClip, MSDEVColumnSelect |
| 秀丸エディタ | CF_DSPTEXT で区別? |
MSDEVColumnSelect が多いといえば多いかなあ。あと、TEditor の形式に対応するとそれなりに多くのエディタに対応、と謳うことができるかも。関係ないのですが、cannia をみたときなぜかサクラエディタに似てるなあと思ったのですが、クリップボード形式も同じなんですね。サクラエディタのソースから派生しているのかな?
次、2。萌ディタの場合、フリーカーソルさせないようにしているのですが、矩形の指定のときはそれが不便かもしれないです。というのは、矩形の一方の端はキャレットなので、フリーカーソルを禁止していると

のように、意図した矩形を選択できないことがあり得るからです。というわけで、矩形選択のときだけ特別扱いしますが、これは意外に面倒そうな気もします。
最後に 3 ですが。当たり前ですが、プロポーショナルフォントを使っていると桁位置は揃わないので、それぞれの行について矩形の範囲にはいるかどうか、個別に判定しなければいけません。
あたりが考えられますが、どうしたものか?
微妙に禁則やワードラップが動き始めてきた感じ。
それで、細かいところを詰めてみます。まず、これらの行を分割する位置を補正する処理は、Unicode のそれぞれの字が持っている属性をもとにしています。それらの情報は exe の中にテーブルの形で持っています。
ということは、日本語のテキストエディタによく見られる、行頭禁則文字・行末禁則文字の指定が不要になるということです。これは、面倒な設定項目がなくなるということで良いことでもありますが、ユーザからカスタマイズの機会を奪うという意味では悪いことともいえます。これをどうしたものか? エディタの禁則文字設定をカスタマイズするような方がどれくらいいるか次第なのですが。
それから、5/11 では、禁則に対して追い出し文字数を設定できるようにする云々を書いていますが、やめます。というか、もともと折り返し幅の n% 以上後ろに戻ったら、その行に対しては禁則しないという動作を想定してたのを思い出した。
例をあげます。折り返しの幅以上、「a」がずらーっと並ぶ行があるとします。
backtrack-limit
┌───────┐
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
└────────────────────────┘
wrap-count (1)
とりあえず、折り返し幅いっぱいの位置 (1) が決定して、それに対して位置補正します。連続するアルファベットの間では分離しないルールなので、分割位置の候補は 1 文字ずつ前にさかのぼり、行頭に達してしまいます。で、行全体が次の行に送られるという変な現象が起きてしまう。
それを防ぐため、プロパティ 'backtrack-limit' にたとえば 0.25 とか設定しておきます。そいで、分割位置の候補をさかのぼった幅が折り返し幅(のピクセル数)× backtrack-limit を超えてしまった場合、さかのぼるのをやめる(折り返し位置は最初に出した (1) を採用する)、という動きになります。
あとプロパティですが、UAX#14 を元にすると、ワードラップも禁則も同じルーチンで判定することになるのでまとめます。用語も、まとめて「折り返し位置補正」と呼ぶことにします。
UAX#14 のペアテーブルを作ってみたり。
萌エディタを発見。ほほう。
背景を固定するとやっぱり重いのでやめました。
ドラッグ中の横スクロールが変なのをちょっと修正。横スクロールさせたときタブを含んだ行が正しく描画されないバグを修正。空行で改行したときエラーになることがあるのを修正。
TEditor 系のエディタでダブルクリックすると、単語全体ではなく単語の先頭からカーソル位置まで選択される(一瞬単語全体が選択されたあと、カーソル位置まで縮むのが見える)ようなのですが、なんだろう。バグにしては、TEditor 系のエディタすべてに共通する動作っぽいので、何か意図があるのかなあ。
UAX#14 を読んでいるところですが、めどい。
正規表現での検索を実装するとして、Delphi から利用できる既存のライブラリとしては、
などがいま知っているものです。ふむ。でも Unicode に特化したエンジンとなると JCL くらい?
あとは普通の検索ですが。BM 法とかにしたとしても別に難しくはないので、これは自前で書いちゃおうかなと。。。
以下は妄想なので読み飛ばし推奨です。
今出ているバグ
のうち、2. について考えます。
このバグは、直接の原因は、フォントを変えて折り返ししなおすことでキャレットの位置が無効になってしまった場合に起こるようです。図解してみると、
あれ? 声が 遅れて 聞こえるよ?|
縦線がキャレットだとします。ここで、フォントを小さくして、折り返ししなくても1行に入るようになると、
あれ? 声が 遅れて 聞こえるよ? |
と、存在しない行にキャレットが位置することになって、エラーになる。なので、フォント変更、再折り返しの直後にキャレットを正しい位置に更新してやれば解決することになります。
で、どう更新するかというと。行位置・桁位置を見るだけでいいなら簡単なのですが、そうすると更新後キャレットが指す文字はフォント変更前とはぜんぜん違う場所を指すことがあり得ます。これはよくない。折り返しの前後も、同じ段落・文字に位置していたほうが親切そうです。そのためには、折り返しの行、桁位置に依存せずに、キャレットがテキストのどこにあるかという情報をもたせなければなりません。
そこまで面倒なことする必要あるのかな? という気もしますが、実は字単位のブックマークをあとで実装するとき、そのしくみと絡んでくるので必要なのです。
そいで、ブックマークの位置を折り返しに依存しないようにするためには、その情報は段落側にもたせることになります。萌ディタでは、段落単位の双方向リスト、折り返し行単位の双方向リストでテキストを管理しています。
このしくみにおいては、折り返しするというのは、ある段落リストのノードに結びついた文字列を頭から走査して、折り返し幅に収まる単位で開始インデックスと長さを出して、生成した折り返し行のノードに保持しておく処理ということです。
さて、ブックマークの位置を保持するために、段落リストのどこにそれを潜り込ませるかというと、ノード自体のサイズはできれば増やしたくないので、特殊な段落ノードの 1 つにしようかなと思います。そのほうが同じ段落に複数のブックマークをいくらでも登録できるし。つまり、

というふうに。リストのノードの 1 つなのですが、実体は段落ではなくブックマーククラスのインスタンス O を指しているわけです。そして、そのブックマークは直前の段落に対応しています。そいで、折り返しの途中でブックマークに対応する文字の行・桁位置が更新されたら、O のメソッドを呼んで、それが保持する行・桁位置を同期させる、というような感じ。もちろん、ブックマークの対象行より若い段落が追加・削除された場合も更新しなければいけませんが。
そんな感じでブックマークのしくみを作ると、フォント変更の場合は、折り返し前にキャレット位置にブックマークを入れておいて、折り返し後にブックマークの行位置・桁位置にキャレットを動かせばそれでおしまい。
それから、ブックマークがどこにあるかを表示できるとよいのですが、こんな感じかなあ。

どうもキー入力周りが、あちらを直せばこちらが。。。になってしまう。まずい傾向だなあ。それとも、もしかして XP ってメッセージの流れてくる順番が微妙に違うのかな?? またいじってみましたが、今度はどうでしょうか。
ダブルクリック&ドラッグは結構便利と指摘があったので、ためしに実装してみたのですが、意外にめどかった。。。というのは、単語/段落を選択したあと、カーソルが単語/段落の範囲内に入ったときに、最初に選択した範囲より縮小してしまうとあまり意味がないということです。
ということで、ダブルクリック/トリプルクリックで単語/段落を選択した後のドラッグは最初に選択した範囲を保持するようにしてみました。
それから、空白をダブルクリックしたときの挙動がおかしかったのも修正。ついに goto を使ってしまいました。
結論だけ読んでもらってもよいです。以下の文章は長い上につまらないので。。。
トリプルクリックとかについて。ダブルクリックで単語選択というのは、割と普通に見られる仕様だと思いますが、トリプルクリックとなるとすべてのエディタが実装しているわけではないようです。ちなみにトリプルクリックだと、段落、もしくは折り返し行 1 行をまとめて選択というのが一般的です。
この調子でいくと、クワドラプルクリック(っていうの?)でテキスト全体を選択、とかになるんでしょうか。ここまでいくと手持ちのエディタではかなり限られて、WZEditor と xyzzy が対応しています。やっぱりこの 2 つはすごいなあ。WZEditor は、トリプルで段落を、クワドラプルでテキスト全体を選択します。xyzzy は、トリプルで折り返し 1 行を、クワドラプルで空行に挟まれた部分を、クインタプルクリック(っていうの??)でテキスト全体を選択します。
ただ、多ければいいのかというとそうともいえないと思います。ダブルクリックの判定は、クリックという同一の操作を、クリックの時間的な間隔だけをもとに振り分けることになるので、必ずしもユーザの意思を正しく反映できるか? というところに弱い部分があると思うからです。
それから、原則的には、範囲選択をしている場合キャレットは必ず選択範囲のどちらかの端点に位置することになるのですが、それを忠実に守ると、テキスト全体とかを選択した場合勝手にスクロールしてしまうことがあり得ます。これは、あまり親切ではなさそうです。こういった部分のフールプルーフとしてダブルクリックまでしか対応しない、というのもある意味では正しいのかもしれません。
その辺をうまく処理しているのは WZEditor で、ダブルクリック以上の操作ではキャレットはあくまでクリックした位置を保持する仕様になってたり、ダブルクリック+ドラッグ(2 回クリックして、2回めはボタンを離さずドラッグに移る)の場合は単語単位で範囲選択できるようになってたりします。同様に段落単位の範囲選択も可能。目立たないところがきっちり作ってあるあたりはさすがにプロが作った製品という感じがします。
そいで、萌ディタでダブルクリックとかをどうするかですが。こんな感じにしてみます。
今日の nightly build はこの辺り。
眼鏡を買ってみました。見えすぎ。
キャレット位置算出のバグを修正。Backspace や Delete 押下でエラーになることがあるのを修正。ascii 以外の文字を含むファイル名が ini ファイルに正しく保持されないバグを修正。
折り返し時の禁則やワードラップも Unicode の中の人が考えたロジックに準拠しようかなー。それにしても多国語のための Unicode なのに、サイトが英語だけというのはなんというか。。。
キーボードレイアウトを変えたとき、右 Alt 併用の特殊な入力ができないバグを修正したつもり。実は Windows にそういう機能があること自体を知らなかった(すみません。。。)。
こういうのって何を押したら何が出るっていう一覧がどこかにないのかな?? と思ったらスクリーンキーボードを出せばいいんですね。へぇ〜。ためになるなあ。とりあえず通常の入力、アクサンと組み合わせる入力、右 Alt 併用の入力と、メモ帳と比べて同じ入力ができることを確認。
右 Alt + テンキーでの入力(入力ロケールとシステム OEM ロケールの 2 種類)もだいじょうぶだと思いますが、実はうちのマシンにはテンキーがないので、スクリーンキーボードだけでしか見てないです。
指摘していただいたフランス語、オランダ語ではだいたい動いているみたいですが、どんなもんでしょうか。
キャレット位置算出のバグはちょっと根が深そう。
それにしても、XP で動かしているところを初めて見ました。
nightly build を更新。てか、時間的に daily build ですね。。。
しばらくバグつぶしに重点をおこうかな。
なんか delphi の起動時に、ハードディスクそのものに原因がありそうなエラー「ドライブにディスクがありません。ディスクをドライブ \Device\Harddisk2\DR4 に挿入してください」とか、起動した後も突然落ちたりとか、マシンが大変不安定になってきました。でもハードウェアってぜんぜんわかんないんですよね。。。新調したいなあー。
とりあえず単純に、最新バージョンを nightly build として出すことにしてみます。バグ修正の場合も、機能追加の場合もあります(top に書いておきます)。怖いもの知らずの方はどうぞ。。。
あ、今週も皆勤だ!
なんかいろいろ勘違いしているので書き直し。やっぱり ALetter には漢字を含まなかった。。。PropList.txt の取得にバグがあって Ideograph とみなしてなかったー。24、26日のにっきもこっそり修正。
ところでふと思ったのですが、漢字の列を単語として扱うのは、中国語の文章の場合使いやすいのかなあ? 句読点で単語境界とみなされるので、実質的には単語じゃなく文単位の移動になってしまうと思います。
HangulSyllableType.txt も組み込んで、UAX#29 の Grapheme Cluster Boundaries をそのまま実装してみました。まだサイズ的には焼身自殺には至らないのですが。。。今のところあまり使う機会がないなあ。
とりあえずキャレットの左右移動を、単純な桁位置の加減算ではなく Grapheme Cluster 境界単位で行うよう修正。
けっこうバグが見つかるので修正するのですが、新しい機能の追加とこれまでに書いたコードの修正は分けたほうが楽かも? リリースバージョンへの修正と、nightly build みたいな感じで。
OSたん保管庫にわたしの描いたのが載ってておどろいた。
ALetter の間の MidNumLet は単語境界とするように修正。例えばアルファベットに囲まれた FULL STOP(ピリオド)は境界となり、数値に囲まれた場合は全体が単語になります。
(1) |object|.|member| (2) |123.456|
昨日作ったのは、空白とひらがなの特別扱いをしているため、「単語境界」ではなく正確には「擬似文節境界」になっていると思います。範囲選択を考えると、この 2 つは区別する必要があるかもしれません。特に空白が当てはまります。昨日のロジックのまま
Numeric と Numeric の間では分離しない
というテキストで、「Numeric」を ctrl+shift+→で選択しようとすると、「Numeric 」が選択されてしまいます(後ろの空白も選択されるということです)。この場合は「Numeric」だけ選択してくれたほうがよいのではないか?
とても微妙なので、引数で指定できるようにしてみます。Caret オブジェクトに単語単位移動のメソッドを加えるので、その引数で後続する空白を単語の一部とみなすかを指定するようにしてみます。
また単語境界。以下の文章は UAX#29 を読まないと、何のことやら。。。かもしれないです。
まず書いてあるとおりに組んでみました。以下の縦線のところが単語境界とみなされます。
|以|下|の|縦|線|の|と|こ|ろ|が|単|語|境|界|と|
やっぱり漢字やひらがなで分離するのはあまり使いやすそうではないので(もしかしたら実装が悪くて、UAX#29 はこのように意図していないのかもしれませんが)、
というふうにしてみます。すると、
|以下の|縦線のところが|単語境界と|
となります。「縦線の」「ところが」と分かれないのがいまいちですが、文字の属性だけみているのでしょうがないところです。
ついでに、空白(White_Space)も特別扱いしてみます。現状では、
|まず| |UAX|#|29| |のとおりに|
となりますが、空白以外の文字と空白の間を分離禁止にしてみます。すると
|まず |UAX|#|29 |のとおりに|
となります。だいたいこんな感じなら恥ずかしくないかな。。。
動かして様子を見てみたら MidNumLet がプログラムのソースと相性がよくない気がする(FULL STOP の前後で分離しない、つまり object.member が 1 単語とみなされる)のでこれはオミットしようかな?
きのうの続きです。文字のプロパティについて、テーブル持ちたくないとはいえコードポイントの数が数なので、テーブルにせざるを得ないところもあります。とりあえずのところは、ここの UnicodeData.txt の一般カテゴリと、Scripts.txt と、LineBreak.txt の内容くらいがあれば(単語境界と折り返しについては)なんとかなりそうなので、これに絞ってテーブルがどれくらいのサイズになるかを考えてみます。
まず UnicodeData.txt。15100 文字について定義してあります。意外と少ないですが、漢字とかは最初と最後だけになってたり、定義済みコードポイントしか書いてない(あたりまえ)のでこの数で収まっています。でも、そのままだとべたなテーブル(コードポイントをそのままテーブルへの添え字にできるような)になりません。かといって、べたなテーブルに展開すると当然 0x110000 のエントリができて、カテゴリをバイトで持つとしても 1M 強です。これは却下。
なので、なんとか詰めてみます。つらつらと眺めてみると、同じ一般カテゴリが連続しているところがけっこう多そうです。では、例えばこんな構造体を用意して:
TUnicodeCategoryItem = record StartCodePoint : dword; EndCodePoint : dword; Category : byte; end;
そして、テーブルはこの構造体の配列という形にします。つまり、
| StartCodePoint | EndCodePoint | Category | |
|---|---|---|---|
| エントリ 0 | U+0000 | U+001f | Cc |
| エントリ 1 | U+0020 | U+0020 | Zs |
| エントリ 2 | 以下続く | ||
こんな感じです。この形式で U+10FFFF まで入れてみて、全体としてはどれくらいのサイズになるか? ちょっと試してみたら、1793 エントリですみそうです。で、上記の構造体は 9 バイトになるので、16KB くらい。9 バイトは中途半端なので 8 バイトにすれば(コードポイントのどっちかを 3 バイトにしちゃう)、14KB くらい。割といいサイズかも?
テーブルを引くときは、StartCodePoint順にエントリがソート済みの前提で 2 分探索して、見つかったら EndCodePoint と比較して、対象となるコードポイントが範囲内ならカテゴリが決定、という感じになると思います。
ちなみに 2 分探索なので、最悪で11回テーブルをうろうろすることになるのかな。速いとはいえなさそうです。まあ、いっか。
同じ構造で、Scripts.txt も見てみると、こちらは 503 エントリ、4KB くらい。LineBreak.txt は 1024 エントリ、8KB。すべて合計してもいまのところ、まだ小さいです。これくらいなら、まあ、いいかなあ。
PropList.txt も 505 エントリですむのでこれも組み込んでみました。
0.3 です。新たに実装した個所は、
前のバージョンからは上書きでかまいません。
単語境界とか。とりあえず、Unicode のえらい人が考えた UAX#29 に準拠すればいいのですが。。。なんかそのとおりに組んでも、あまり実用的ではなさそうな?? 漢字やひらがなの間も分離できるし。。。
まあそれは、CJK IDEOGRAPH(と、Compatible や Extension A、B?)の間で分離しないなどのルールを加えればそれでいいような気もしますが、各文字のプロパティをどうやって得たものか。05/12のライブラリでプロパティテーブルをリソースで持つようにはなるのだけど、どうも 2001 年以降更新されていないっぽいのと、あまり exe の中に巨大なテーブルは持ちたくないというのがあって微妙なところです(ライブラリを組み込むだけで 100KB くらい増える)。
一度テーブルを自前で持ち始めたら、BMP 以降の文字がさらに拡充されるごとにテーブルを増やさなければならない足かせができてしまいます。テーブルを持つこと自体にはやぶさかではありませんが、そのサイズが問題です。テーブルのせいで exe のサイズがどかどか増えていったとしたら、Unicode 対応をあきらめるか、ギャーと叫んで焼身自殺するしかありません。
いろいろドキュメントを整理。
バージョンは何になるのかな? トップページに書いた未実装リストからは、だいたい 45% くらいが実装済みということになるのですが、漏れやバグ込みの分を差し引いて、順当に 0.3αにしてみます。
なんかアクセスカウンタが信じられない(ペースがはやすぎ?)のですが、よく考えると自分でアクセスした分もけっこうありそうなので、ローカルで html をいじるときはカウンタを出さないようにしてみました。。。ぜんぜん増えなくなったらそれはそれでショック。
地道にバグとり。
見えたり見えなかったりするアクセスカウンタを設置してみました。
終了時に ini ファイルの更新に失敗しても無視するようにしました。
ルーラの表示も折り返し幅に正しく連動するよう修正。このルーラコンポーネントって Delphi を買って、初めて書いた部分なのでちょっと使いづらい。。。
ここのところ、エディタとしての編集機能よりも、アプリケーションとしてのこまごました機能に重点を置いて実装してきたのですが、おかげでなんとなく普通のアプリっぽくなってきました。そんなわけで、ぼちぼち編集機能に重きをおくところなのですが、今の状態でまた公開しちゃいましょうかねー。0.2 から 1ヶ月たった頃だし。
折り返しをウィンドウ幅(正確には、ビューの幅)に合わせた場合の動作の不明点をクリアしたので、実装を進めてみます。
そいで、折り返ししなおすタイミングなんですけども。WM_SIZE がきたときでもいいんですけども、画面のプロパティで「ドラッグ中にウィンドウの内容を表示する」設定にしているとドラッグでサイズの変更中、ものすごい勢いで WM_SIZE がきます。その都度折り返ししなおすとちょっと負荷が高すぎなので(とくに、大きいファイルを開いている場合)、WM_EXITSIZEMOVE のタイミングで折り返ししなおすようにしてみます。つまり、ドラッグが完了した時点で折り返しなおすということです。リアルタイムでウィンドウ幅に追従、に比べると少し遅延する感じなのですが、どんなもんでしょうか。ちなみに、EmEditor とかも同じような動作をするようです。
折り返しの挙動を制御するプロパティとして、現状はこんな感じになっています:
これは、n 文字で折り返し、というほかに n ピクセルで折り返しという指定ができるようにするためにこうなっているのですが、自分で考えておいてなんですが、すごく判りにくい。n ピクセルで折り返しというのも、もしかしたら年に 2、3 回くらいは「こりゃー便利だ!」と思えることがあるかもしれませんが、別になくても困らなさそうです。
なので、簡単にします。
ちなみに、「折り返しなし」というのは特にないのですが、とりあえず WrapCount にやたら大きい値(折り返し1行の最大文字数は WORD なので 65535 とかその辺)を入れればいいと思います。
いろいろいじったらなんか不安定になってしまったよ。。。
ファイル名の Unicode 対応から漏れているところを修正。ファイル名に Unicode を使用してもよい部分は、
です。というか、ファイルにかかわる部分のほとんどが対応済みなのですが、まだ微妙に漏れてるところもあるんですよね。。。バレたら直します。
3/11 の時点で 25000 行くらいだったらしいのですが、今日カウントしてみたら 60000 行くらいだった。ふむ。
「拡張子クラス」の名前は変と指摘を受けたので、ちょっと考えてみます。確かに、拡張子も含めた設定のかたまりのことを指すのに、「拡張子」だけが表に出るのは変。。。かな? 実際、拡張子で分けられるからいいような気も。。。「設定のかたまり」ということで、configuration cluster というのを考えましたが、なんだかよくわかりません。
ドキュメントタイプとか文書型も微妙に違う気がするしなあ。。。そうすると代替として出してもらった「設定クラス」が一番無難? 英語だと configure class。
設定ダイアログのうち積み残していた、起動時に読み込むスクリプトと、使用するエンコーディング DLL の編集を実装。
けっこう深刻な問題。
1. はどういうことかというと、たとえばルーラ上のスライダをいじって行番号の表示幅を変更するとします。表示幅も拡張子クラスごとに設定するプロパティの1つなのですが、このとき変更対象となる拡張子クラス(a)には表示幅が定義されておらず、親(b)の表示幅を継承している場合、実際に変更されるべき拡張子クラスは a か b か、ということです。これは、基本的には親を変更するので、子供を変更したい場合は、設定ダイアログで拡張子クラスを明示して設定してね、というスタンスにしようと思います。この辺は、プロパティの裏に継承のしくみがあるのが却って判りにくいですね。。。
2. はどうしよう。単純にスクリプトと ini ファイルのタイプスタンプで新しいほうを正としてもいいのですが、ini ファイルに設定した情報がばっさり消えてしまうのもちょっと大胆すぎます。どうしたものか、これだけ未決。
3. は、xyzzy の動作が参考になりそうな感じなので見てみると、勘ですが1個のバッファを見ている複数のビューのうち、最も幅の広いものを折り返し幅としているような感じです。とりあえずそれにあわせてみます(ただ、逆に最も幅の狭いものにあわせたほうが、横スクロールする必要のあるビューが出ないのでいいような気もします)。
ビューの右下に、キャレット位置のコードポイントを表示しているわけですが、U+ なんとかと出ているように、Unicode におけるコードポイントです。それはそれでいいのですが、時には、ファイル上のエンコーディングで表示したほうが便利な場合もあると思います。ということで、切り替えられるようにしてみます。
してみたんですが、ファイル保存のための、エンコーディング DLL の関数を流用してみたら ISO-2022-JP のように状態をもつエンコーディングで、対象となる文字の前後にエスケープシーケンスが勝手に付いてしまうなあ。1 文字専用の変換関数が必要?
今週はがんばったなあ。。。
「萌ディタ」というのは、マイナーテキストエディタ愛好会で付けてもらったのですが、なかなかインパクトのある名前です。しかも、ただ「萌え萌え〜」とか言っているわけじゃなくて、Multi Opinion Editor の略称なのだそうです。萌ディタスレで出るいろいろな意見が参考になっているので、確かにそうだと思います。だからインパクトといっても、バカパクじゃなくインパク知なのです。
「利用できるツールバー ボタン(V)」のアイコンが変なのは、気のせいです(全部描くの大変だなあ)。

試しに複数項目選択を許可して、そのままドラッグ&ドロップできるようにしてみました。意外と使いやすいかも?
例の正規表現エンジンは後方参照前方参照が(まだ)できない予感。。。うむむ。
ステータスバーを隠した場合、メッセージをどこに表示したものでしょうか。こういうのは面白そうだけど、実際に使ってみたら邪魔なんだろうなあ。

拡張子クラスとエンコードを選択するフォームを実装。
何の気なしに「拡張子クラス」とか萌ディタにローカルな用語をけっこう出しているので一応説明してみます。一言でいうと拡張子で区別されるグループのことを拡張子クラスといいます。例えば、.txt に対応する拡張子クラスがあって、それに対してフォントは MS UI Gothic だよ、とか設定しておくと、ほげほげ.txt を開いたときその設定で表示されるわけです。
拡張子ごとに個別に設定を行えるというのはテキストエディタにおいては割と一般的な仕様だと思いますが、萌ディタにおいてはおのおのの拡張子クラスが独立した存在ではなくて、継承関係を持っているというのがミソです。
例を挙げます。C のソースファイル、pascal のソースファイル、java のソースファイルに対応する拡張子クラスがあるとします。で、「やっぱりソースは背景黒じゃないと落ち着かないよっ」と思って設定を変えようとします。拡張子ごとの設定がおのおの独立していると、拡張子のグループごとに同じような設定をしなければならないので、めどいです。
そういう場合、萌ディタではこうします。まずプログラムソースに共通する拡張子クラスを定義します('programsource' とでもします)。それに対して、背景色を設定します(App.Prop('programsource', 'background-color') = 'black' とかする)。
次に、'programsource' を継承した 'c-source'、'pascal-source'、'java-source' を定義して、それぞれに固有の設定だけ行います。
このとき、子供の拡張子クラスには背景色を設定しません。その状態で、App.Prop('c-source', 'background-color') を参照すると、それぞれの拡張子クラスは、自分に設定されていないプロパティについては継承元の親のプロパティを返すようになっています。つまり、いずれの拡張子クラスも背景色は黒だよ、と返してくれる。
逆に 'programsource' の背景色を設定すれば、子供の背景色も自動的に変わります(それぞれの子供が背景色を上書き定義していなければ)。そういう感じで、まず共通の設定を行い、それぞれの拡張子クラスに固有のものだけを差分として設定していくのが萌ディタで環境を構築する流れになると思います。
それから、キー押下に反応するスクリプト側のイベントハンドラも拡張子クラスに対して設定するわけですが、こちらも同じように、定義しなければ自動的に親のイベントハンドラを呼ぶようになっています(定義しつつ、親のハンドラを呼ぶこともできる)。
とまあこんな感じなんですが。
ためしにここのライブラリを組み込んでみたり。Unicode の文字のプロパティを参照できるようになったりします。Unicode Tuned Boyer-Moore 検索エンジンやら正規表現エンジンも付いているのがちょっとおいしいなあ。BMP 以降もつかえるのかな?
特に意味はないのですが、スタイルシートをいろいろいじってみました。あらためて自分の書いた文章を読んでみると、「とりあえず」と「面倒」がやたら多いなあ。
禁則とか折り返しとかワードラップとかそのへん。禁則とは何かというとテキストのレンダリングにおいて、見にくい部分を回避する処理なわけです。まず禁則の対象となる文字群があって、それぞれ「行頭禁則文字」「行末禁則文字」と呼ばれます。
行頭禁則文字は、行頭に来た場合見にくい字。例えば「。」とか「?」とか。これらは直前の文章の終端を示すわけで、それが行頭にくるのはおかしいよという理屈です。それから行末禁則は逆に、行末に来た場合見にくい字。例えば「(」とか「[」とか。これらはここから文章が始まることを示すわけで、それが行末にくるのはおかしいよという理屈。
それで、そのおかしい点を修正するのですがだいたい3種類あって、
理想的には、どの禁則処理を使うのかをユーザが選択できることなのですが、追い込み禁則はちょっと(かなり)面倒なので却下して。。。実装の楽そうな追い出し禁則かぶら下げ禁則を選択しようとしています。ちなみにエディタによっては、句読点のみぶら下げるというルールにして追い出し禁則と両立させているものも多いです。うーんどうしようかな。
とりあえず追い出し禁則だけに絞って組んでみます。で、追い出し禁則について再度まとめると、行頭禁則は
□□□□□□□□□□□□□□□□□■ )□□□□□□□□□□□□□□□□□
とこうなってしまった場合に1行目の最後の文字を追い出して、
□□□□□□□□□□□□□□□□□ ■)□□□□□□□□□□□□□□□□
こうする処理。行末禁則は
□□□□□□□□□□□□□□□□□( □□□□□□□□□□□□□□□□□□
とこうなってしまった場合に1行目の最後の文字を追い出して、
□□□□□□□□□□□□□□□□□ (□□□□□□□□□□□□□□□□□
こうする処理です。
さて、これですべてが片付くのならいいのですが、
□□□□□□□□□□□□□□□□□) 。□□□□□□□□□□□□□□□□□
これを
□□□□□□□□□□□□□□□□□ )。□□□□□□□□□□□□□□□□
こうしたのでは禁則の解決になっていません。そのため、追い出し字数を設定できるようにして、その字数までならさらに後ろに戻れるようにします。つまりこの場合、追い出し字数 = 2 とかにすれば、最大2文字まで追い出せるようになって、
□□□□□□□□□□□□□□□□ □)。□□□□□□□□□□□□□□□
こうなるわけです。
次にワードラップについて。アルファベットの列が折り返し幅をまたぐ場合、何もしないと列が2つに分離してしまうわけですが、分離しないように列の直前のスペースまで遡ってそこで折り返しましょという考え方です。
で、よく分からないのは
というあたりで、とりあえずワードラップ対象は折り返し基準幅をまたぐ Alphabetic = true の文字列、代替となる折り返し位置は Whitespace = true になっている文字という扱いにすればいいかな。
いろいろなエンコーディングでの読み書きができるようになりました。以下のエンコーディングに対応します。
いやー、対応文字セットについては、やっと普通のエディタっぽくなってきました。
と思ったら EBCDIC は CR+LF が 0x0d 0x25 だったりして、まだ細かいところをいろいろ直さなくちゃいけなかったりします。。。
「Delphiコンポーネント設計&開発完全解説」が引越しの荷物から見つかりません。。。
しょうがないので、エンコーディングの名称について。ビュー下部に拡張子クラス、エンコーディング名称、改行タイプを常に表示するわけですが、「JIS (ISO-2022-JP, Kana Extended)」とかだと長すぎて困るので、短縮した名称で表示するようにしてみました。。。

割とどうでもいいことなのですが、Windows の UI って、何らかの文字入力をしているときの IME が on かどうかの状態ってわかりにくいと思うのですがどんなもんなんでしょうか。タスクバーなり、IME のツールバーなりを見ればいいのですが、ここで大きな視線移動を強いられるのがよくないわけで、単純に考えるとキャレット付近に何か情報を表示してもらえればよいと思うのです。
が、ところがそこが素人の浅はかさで、たとえば IME のツールバーをキャレット付近に置くと(あたりまえといえばあたりまえなのだが)邪魔でしょうがないです。
ので、何かないかと探してみたら、例えば IME Watcher reduce というのがあったりします。これは便利です。
で、エディタの話になるのですが、xyzzy の場合だと、IME の状態をキャレットの色で表すことができてこれもよいと思います。色付きキャレットってどうするんだろ。自前で反転させているのかなあ? ちょっと面倒そうなので、代わりに IME が OFF のときはキャレット幅を 2pixel、on のときは 1pixel になるようにしてみたのですが。。。フォントサイズが小さいととても分かりにくかった。ほかに、幅は 2pixel のままメッシュ状にするとか、音を出すとか、点滅間隔を変えるとか(さすがにまずい?)、いろいろ試行錯誤してみたのですがどれもいまいち。。。
なにかステキなアイデアがないもんですかねえ。
また割とどうでもよいのですが、今時のアプリは Explorer や IE を始めとして、メニューやツールバーが CoolBar とか ReBar と呼ばれるものの中に入っているものが多いと思いますが、萌ディタは今のところそうしていません。というのは大して CoolBar の中に入れるネタもないというのと、CoolBar を VCL がラップしている部分がけっこう容量があって、組み込むだけで 100KB ほど増えるのが物悲しいためです。
ちなみに組み込むとこうなるのですが、微妙にさびしいですね。。。
次。JIS コードの読み書きにも対応させてみます。正確には、ISO-2022-JP のエンコーディングです。
といっても ISO-2022-JP にもいろいろあって、エスケープシーケンスで切り替えられる文字セットで区別されるのですが、まとめると
| ISO-2022-JP | ・ASCII: ESC ( B ・JIS X 0201 (左): ESC ( J ・JIS C 6226-1978: ESC $ @ ・JIS X 0208-1983: ESC $ B |
ISO-2022-JP-2 | ISO-2022-JPに加え、 ・GB2312-80: ESC $ A ・JIS X 0212-1990: ESC $ ( D ・KS X 1001:1992: ESC $ ( C ・ISO 8859-1:1998 (右): ESC . A ・ISO 8859-7:1998 (右): ESC . F |
ISO-2022-JP-1 | ISO-2022-JPに加え、 ・JIS X 0212-1990: ESC $ ( D |
|---|
だそうです。このほかにも ISO-2022-JP-3 や(これはよくわからない)、ESC ( I で半角カナを使えるようにした拡張もあるそうです。とりあえず、ISO-2022-JP に対応させてみます(ほかのは Shift_JIS を経由する単純なロジックでは実装が面倒なので)。
そいで、ISO-2022-JP ですが。あいまいなのは、
というところでしょうか。1. については、常に先頭を ESC ( B で始めてもいいかもしれません。BOM のようにエンコーディングの自動判定の助けにもなる。2. は、「¥」と「‾」については JIS X 0201 とすればいいかなあ。3. も同様なのですが、まあとりあえず 83JIS だけでいいかなあと。UTF-16 でもちつつ、この 2 つを区別するのはとても面倒そうだし。4. は難しい。というか RFC で「使えない」と書かれている以上呼べないのでしょう。つまり、純粋な ISO-2022-JP と、ISO-2022-JP のそっくりさんを区別する必要がある。
といいつつ、なんとも自信が持てないので、例によって JIS エンコーディングに対応しているエディタはどういう動作をするか見てみます。テキストは
日本語ですよ。 (J\JIS ローマ字の円マークですよ。 ハンカクカナデスヨ。
のような感じで、打ち込んだものを保存してバイナリエディタで覗いてみます。円マークについては、再度読み込み後再保存し、またバイナリエディタで見たときに、ESC ( J が残っていれば ASCII と JIS ローマンを区別しているとみなします。2行めの先頭は、エスケープコード(0x1b)そのものです。結果は以下のとおりでした。
| Alpha 0.7.5.3α | (うまく保存できませんでした) | ||
|---|---|---|---|
| Dana 1.14.01 | ASCII と前提? | ASCII とみなす | 全角カタカナに変換する |
| EmEditor 4.01 | ASCII と前提? | ASCII とみなす | エンコーディング選択時、「日本語 (JIS) (50220, iso-2022-jp)」と「日本語 (JIS 1 バイト カタカナ可) (50221, csISO2022-jp)」を選択。前者は全角カタカナへ変換 |
| FirstPad 0.21β | ASCII と前提? | ASCII とみなす | ESC ( I を使用する |
| GreenPad 0.1.0.4 | ESC ( B が入る | ASCII とみなす | ESC ( I を使用する |
| Jesty 0.34 | ASCII と前提? | (直接打ったエスケープコードが保存されません) | 全角カタカナに変換する |
| JmEditor 2.0.8 | ASCII と前提? | ASCII とみなす | 全角カタカナに変換する |
| K2Editor r.1.4.21 Build 484 | ASCII と前提? | ASCII とみなす | 全角カタカナに変換する |
| 「JIS(ROMAN)」の場合、ESC ( J、「JIS(ASCII)」の場合、ESC ( B を使用する | |||
| MKEditor 3.7.8-J | ASCII と前提? | ASCII とみなす | 全角カタカナに変換する |
| otbedit 3.0.4.1 | JIS ローマ字と前提? 行末でも ESC ( J を使用 | JIS ローマ字とみなす | SO/SI?(SI は書かれていない) |
| Peggy Pad 4.14 | ASCII と前提? | ASCII とみなす | ESC ( I を使用する |
| サクラエディタ 1.4.6.0 | ASCII と前提? | ASCII とみなす | ESC ( I を使用する |
| Space editor 2.44 | ASCII と前提? | ASCII とみなす | ESC ( I を使用する(ただし、7ビットに変換されずに書かれる) |
| TeraPad 0.83 | ASCII と前提? | ASCII とみなす | ESC ( I を使用する |
| VxEditor 0.3.6.0 | JIS ローマ字と前提? | JIS ローマ字とみなす | 全角カナに変換する |
| WZEditor 4.00F | JIS ローマ字と前提? | JIS ローマ字とみなす | 全角カナに変換する |
| xyzzy 0.2.2.229 | ASCII と前提? | ASCII とみなす | ESC ( I を使用する |
| 秀丸エディタ 4.10 β14 | ASCII と前提? | ASCII とみなす | 全角カナに変換する |
気になるのは有無を言わさず半角カナを ESC ( I でくくってしまうのはいいの? という点ですね。。。あと細かいことを言えば、ファイル末尾に ASCII なり JIS ローマンに戻していないものもいくつかあります(もしかしたら、省いていいのかもしれません)。
ということで、これらを踏まえて、萌ディタにおける JIS エンコーディングは以下のような感じにしてみます。
JIS (ISO-2022-JP)
JIS (ISO-2022-JP + 半角カナ)
EUC-JP について。ええと、Windows がサポートするコードページの中には 51932 (EUC - Japanese) という形で存在するのですが、どの環境でも使用できるわけではなさそうなので、とりあえず自前で変換することにします。
そいで、どう変換するかというと、とりあえず中間的に Shift_JIS に変換して、それを MultiByteToWideChar() に渡せばいちばん簡単そうなのですが、そうすると Shift_JIS では表せない 8F XX XX のシーケンス(JIS 0212 の補助漢字)を変換できないことになってしまいます。
メモリ上でテキストを Shift_JIS で持つエディタであれば、「補助漢字使えません」でもいいと思いますが、Unicode は補助漢字を取り込んでいるので使えなくなるのは困る(といっても困るのは EUC-JP との入出力時だけなのですが)。どうしようかな? 自前で変換テーブルを持つのはやだなあ。。。テーブル自体はこれを元に作るだけなのですが。
と思ったら Alpha や EmEditor とかも補助漢字を含んだ EUC-JP エンコーディングのファイルは、補助漢字をうまく変換できないようだなあ。これは、補助漢字を切ってよいという悪魔の囁き??
というわけで、とりあえず EUC-JP での読み書きができるようになりました。補助漢字は、無視の方向で。。。
「文字コード【超】研究」が引越しの荷物から見つかりません。。。
しょうがないので、ツールバーとビューに挟まれた部分について。これは検索文字列/置換文字列の入力、直接実行するスクリプトの入力に使おうとしているわけですが、それぞれについて考えてみます。
とりあえず最初はスクリプトの入力ですが、もともとの案では、これもひとつのテキストバッファ扱いにするつもりでした。で、例えば F5 を押すと、バッファ全体かもしくは選択した範囲が実行対象のスクリプトになるような(SQL Server のクエリアナライザのような感じです)。もちろん普通のバッファなので複数行入ります。そのためビューとの間にスプリッタを設けて高さが可変になるようにします。
さてそれはそれでいいと思うのですが、同じ場所を検索・置換のための入力にも使おうとすると、よくよく考えると無理があるような気もするので(標準的なインターフェースを犠牲にするほどスクリプトの直接実行の頻度が高いか、というとそうでもないように思えるし)、複数行云々は却下して、いずれも単一行のコンボボックスにしてみます。
そんなわけで、とりあえずコンボボックス横のボタンでこんなメニューが出て
それぞれ

こんな風になります。当然、スクリプトからも切り替えられる。
それから、検索、置換で細かいオプションを指定したい場合は一般的なダイアログを使用することになると思います。
Intellisense のような補完機能について。実現する手順がどうなるかなと考えてみるに(すぐ実装するわけではない)、
という感じでしょうか。プログラム側から見ると、補完文字列のリスト作成よりは補完ウィンドウの作りこみのほうが面倒そうです(リストの作成にもエディタ側で構文解析とかのロジックを提供することになるとしたらそうでもない)。
ということで、とりあえず補完ウィンドウもどきを作ってみたのですが、なんかちょちょいっとはいかないです。。。ポイントとしては
くらいで、1番めは CreateWindow() のときに操作するだけだし、2 番めは WM_NCACTIVATE でつじつまを合わせるだけでいいのですが、3番めが面倒です。どうしたものかしら。ちなみに Visual Studio や Visual Basic、あと Delphi の補完ウィンドウを見てみると、
あたりが特徴だと思います。なるほどねえ。けっこう言語仕様に依存している部分もあるので、テキストエディタに落としこむときにどう一般化するかはむずかしそうです。
とりあえず基本的なところだけできた。ウィンドウの破棄のタイミングは、メッセージループで真っ先に WM_LBOTTONDOWN、WM_LCLBUTTONDOWN を(対象のウィンドウハンドルにかかわりなく)見るようにしてみた。

補完まわりはまだ作るわけではないのですが、代わりにスクリプト側から任意のポップアップメニューを出せるようにしてみました。
switch (App.PopupMenu(
'' //近接する対象。'mouse'、'caret'、'f1'〜'f12'。
// デフォルトは mouse
'', //近接対象との位置関係。
// デフォルトは 'left top'
'項目1(&A)\n' + //項目は '\n' で繋いだ文字列です。
'項目2(&B)\n' + // '-' は仕切り線です
'項目3(&C)\n' +
'-\n' +
'キャンセル')) {
case 0: //戻り値として選択した項目の
break; // インデックスを返すので、
case 1: // 振り分けて処理
break;
case 2:
break;
default: //何も選ばれなかった
break;
}
のような感じで使います。分かりにくいサンプルですね。。。

ファンクションキーに近接させるとこんな感じです。
とりあえず、ini ファイルのエンコーディングを UTF-8 にしてみました。設定ダイアログで使うテキストファイル(config.txt)も同様。ただコマンドライン周りはまだいじってないんですよね。。。(というかどんなスイッチを組み込むか考えていない)
エディタの操作系に関して、あらゆる側面から考察を行った大掛かりなドキュメントを書いてみたのですが、まとめきれなくなったので捨ててしまいました。。。
一言でいえば、「ホームポジションのまま操作できれば(・∀・)イイ!!」ということです。
なんか風邪を引いたような。。。
ファイル名の Unicode 対応の続き。エディタの設定を ini ファイルとやり取りしていますが、今のところ Unicode 特有の文字を表現できません。これをどうしようかなと。
と、とりあえずはこれくらいしか思い浮かびません。1. は、UTF-8 エンコーディングの ini ファイルなんてあっていいの? という気もしますが、Opera などは普通に使っているようなので気にしないことにします。
2. は割と少ない修正ですみそうですが、ini ファイルを直接編集するときに「むきー」となるかもしれません。
3. は今の状態でさえ起動が速いとはいえないのに、それに加えて XML のパーサ生成、パース……となるとさすがにためらわれるところです。DTD 自体はぜんぜん複雑ではないと思うので、SAX 専用の軽いパーサを利用するとかで工夫の余地はあるとは思いますが。
どうしようかな。
桁位置を表示するルーラがあるのですが、よく考えてみると微妙な存在です。まず、プロポーショナルフォントを使用している場合は目盛りにあまり意味がありません。これは、他のエディタについても同様で、プロポーショナルフォントを指定でき、かつルーラを持つ EmEditor、秀丸エディタ、WZEditor なども同じ問題を持っています。

中でも EmEditor と秀丸エディタの場合、ルーラ上に表示する桁位置は、行頭から何文字目かということを表しており、キャレットの表示上の位置とは関係がなく、見た目上ずれてしまいます(WZEditor の場合は、キャレットの表示上の位置に追従するのでずれない)。
「ルーラ上に表示する桁位置は、行頭から何文字目かということを表している」ということを知っていれば、この動作で納得できるのですが、知らないとちょっと不自然だと思います。
萌ディタの場合、桁位置を知りたければビュー下部のラインを見ればいいということで、ルーラ上に特に桁位置の表示はしていないのですが、そのかわり行番号の表示幅と折り返し位置をドラッグで指定できるようにしています。それでもいまいちルーラの存在は微妙なままですね。。。何か便利な使い道があればいいのですが。
秀丸エディタのルーラを見ていて気づいたのですが、開始が 0 からなんですね。でも桁・行番号表示は 1 からなので混乱しそうなのですが、いいんでしょうか。10、20……の目盛りも、実際は 11 桁め、21 桁めのはずです。目盛りの表示位置を 1桁左にずらすか、表示する数値を +1 してあげないと、つじつまが合わないような気がするのですが。。。と思ったら TEditor も同じような感じですね。うーんこれで正しいのかな。わたしは、何か勘違いをしているのでしょうか??
とりあえず萌ディタでは、10 単位の目盛りの最後のブロックのところに 10、20……と表示するようにしていますが。。。
まあ、ぶっちゃけ、どうでもいいことなのかもしれません。
Unicode にしかない文字をファイル名に含んでも開けるようにいろいろいじってみたら、いろいろなところをなおさなくちゃいけなくて、めどいです。。。
といいつつ、ファイル名の Unicode 対応をちくちくしています。

前に書いた、行番号表示・桁番号表示の切り替えも実装してみました。拡張子クラスのプロパティ
で指定します。

line-disp-style = 'by-paragraph'、col-disp-style = 'whole-paragraph' の状態

line-disp-style = 'by-line'、col-disp-style = 'each-line' の状態
0.20 です。お待たせしてすみません。新たに実装した個所は、
ファイル I/O まわりはまだ不完全です。いまのところ読み書きとも Shift_JIS、UTF-8、UTF-8N のみ対応しています。アーカイブのディレクトリ構成が多少変化しているので、前のバージョンからは上書きではなく、いったん削除後の展開をお願いします。あとは細かいことですが、設定ファイルのうち 'plaintext.javascript.txt' は 'std.javascript.txt' としました('.javascript.txt' という拡張子はどうなの? という気もしないではありませんが。。。)。
ん?
なんとか仕事が終わりました。開発を再開します。
とりあえず今週いっぱいで仕事が片付く予定です。。。はやく開発に戻りたいよう。
最近は web サイトをデザインする人になっています。。。