Vz Resources
Commands
2018-09-09T22:52:06+09:00

コマンド拡張で学ぶVZマクロ入門 #15

番号記号初期キー機能
#15#g^G [DEL]1文字削除

s==0(編集モード)

戻り値 r:0=成功,-1=失敗(ファイルの終端)

削除した文字は(通常のux無効の状態であれば)削除バッファに格納され,(mg..-3).-3 に存在(2バイト文字なら(mg..-3).-4)する。なお,mg..-3 は削除バッファの終端で,次に削除された文字はこの位置から格納される。

格納された文字の次に2バイトのサイズ情報があり,最上位の1ビットが削除方向を示すフラグになっている。削除方向とは[DEL]系の操作か[BS]系の操作かで異なり,#u(削除文字(列)の復活)実行時の出力後カーソル位置に反映される。[DEL]系の削除で格納された場合は8000hがサイズ情報に加算される(先頭1ビットが1になりフラグが立つ)。[BS]系の削除ではフラグが立たない。

削除バッファに関する特殊な動作
改行コード(0A0Dh)を削除したとき,削除バッファには0Ahのみ格納され,出力時に0Dhが補充される。したがって,0Ahを削除したのち#u(削除文字列の復活)を実行すると,0A0Dhが出力される。単独の0Dhはそのまま格納・復活される。

削除バッファのイメージ

削除バッファは一種の「スタック」である。削除された文字列は一定の大きさをもつバッファの範囲で「積まれ」ていき,空きがなくなると古い文字列は押し出されて捨てられてしまう。スタックのイメージは次の図のようになる。(上位アドレスを上に書くのが普通だが,右に向かって書いている。)aやbは1バイトの文字,01や 80は十六進数である。

 |←─────── 削除バッファ (サイズはbc)────────→|
─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─────────────┬──
  │a│01│80│b│01│80│c│01│80│                          │
─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─────────────┴──
  ↑削除バッファの先頭            ↑削除文字列終端 mg..-3   ↑puの先頭
  pq..131 (pu-bc)

削除バッファはスタックセグメント内にあり,pq..131のポインタが指すアドレスにある。マクロバッファの先(上位アドレス)に各種ヒストリーバッファ,システムメニューバッファがあり,その先にある。pu(マクロ用配列領域)の手前にあるので,削除バッファのサイズであるbcpuから引くpu-bcという式でも先頭アドレスを算出することができる。削除文字列の終端はmg..-3のポインタが指すアドレスで,新たに削除された文字列はこの位置から追加されてゆく。

削除した文字の上位2バイトはサイズ情報を示す数値である。ただし2バイトをまるまるサイズ情報として使っているわけではなく,サイズ情報の構造をビット単位で示すと,次の図のようになっている。

   ←上位ビット                   下位ビット→  
  ┏━┯━┯━┯━┯━┯━┯━┯━┳━┯━┯━┯━┯━┯━┯━┯━┓
  ┃★│      上位バイト          ┃          下位バイト          ┃
  ┗━┷━┷━┷━┷━┷━┷━┷━┻━┷━┷━┷━┷━┷━┷━┷━┛

★で示した最上位の1ビットが,削除方向を示している。

つまり,サイズ情報は15ビットで表わせる(7FFFh==32767)文字分が確保してある。サイズ情報としては十分で,むしろ過多なくらいである。

#15(#g)で1文字削除した。

─┬─┬─┬─┬────────────────
  │a│01│80│
─┴─┴─┴─┴────────────────

#15(#g)でもう1文字削除した。

─┬─┬─┬─┬─┬─┬─┬──────────
  │a│01│80│b│01│80│
─┴─┴─┴─┴─┴─┴─┴──────────

#15(#g)でさらに1文字削除した。

─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬────
  │a│01│80│b│01│80│c│01│80│
─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴────

削除バッファの中身はこのようになっている。

s==1(文字列入力モード)

編集モードと同じ

s==2(コマンドラインモード)

編集モードと同じ

s==3(ファイラーモード)

無効

なお,初期設定キー[DEL]#-(マークの解除)に使用されている。

s==4(メニュー)

戻り値rの内容

s==4(1文字入力モード)

無効

マクロによる拡張例

40 ^G ""        ;Del Indent     Ikuo
        (ct>1) #g ?. (ct==2)?#t

論理行末で実行(改行コードの削除)すると,次の論理行の行頭空白類を削除して行を接続する。上村郁夫氏の名作小物のひとつ。


コマンド拡張で学ぶVZマクロ入門 #15
The VZ resources, valid XHTML 1.0 Strict. ©2006 by mezala.