VZ.DEFやVZFL.DEFのような基本設定マクロに既に記述されているイベントマクロを発効させないようにするためには,別の内容を持つイベントマクロをコマンドラインでインクルードして起動させます。イベントマクロもマクロキーと同様に後優先になりますので,より後から読み込まれたイベントマクロが優先して実行されます。起動後に別のイベントマクロを読み込んでも同様です。
変数mx(入力待ち(&p
)でのマクロ実行・イベントマクロの実行禁止)によって制御することができます。
例えば,#O
などのファイルオープン系で特定のファイルを開こうとするとき,なにも指定しなければmxは無効ですから,!Openイベントが呼ばれます。もちろん,!Openイベントに含まれる拡張子別の編集設定を有効にする必要があるなら別ですが,単なる作業ファイルを開くときなどは無駄な過程ですから,mxを有効にするとよいでしょう。
1 ^\ "" ?.
mx+,
#O "nul" #m (s)?'y'
mx-,
mxはマクロの実行が中断されるとリセットされるという安全設計になっています。したがって敢えて値を保存・復帰していません。行儀作法が気になる人は,mx[+,
… mx],
としておきましょう。
なお,いくら中断・終了でリセットされるからと言っても,mx+
のまま終了させるのはやめておいた方が無難でしょう。
前項と同様に,変数mx(入力待ち(&p
)でのマクロ実行・イベントマクロの実行禁止)によって制御することができます。
mx+, &g("title",20) mx-,
!Openなどのイベントマクロは通常必要があって呼ばれるわけですから,#O
などのファイルオープン系コマンドではmxを無効のままにしておくという選択が当然ありえます。しかし,マクロ中で使われる&g()
の入力窓では一定の決まりに従った入力が期待されているわけですから,このようなケースでは常にmxを有効にしてマクロキーを押しても実行できないようにしておくべきでしょう。
何故に「べき」などと妙に強調するのかと言うと,&g()
の入力窓でマクロを実行した場合,引数が関数から分離されるような現象が起こって「&g
」の次の「(引数)」が独立したコードのように扱われてしまうからです。この場合,&g()
の窓に初期文字列が二重に出力されたり,後の命令が二重に実行されてしまうという現象が起こります。
もしも必要があって&g()
窓内でのマクロ実行を許容するのであれば,次の例のように初期文字列の先頭アドレスを変数rに格納するようにしてカーソル位置への出力を抑止し,さらに&g()
窓の表示中にもかかわらず後続する命令が実行されないように,特殊関数&Cr
(編集モードになるまで次の命令を実行しない)を関所にしておきましょう。
&g("title",20,r"str") &Cr
!Openイベントを利用して,ファイルを開くと同時に拡張子に応じた設定を適用することができます。まずはサンプルとして製品版の!Openを見てみましょう。
1 "!Open" (ne=='DE')? ts="*=", (ne=='NI')? ts="\x ^\0/\0", ; (ne=='TX')?{ we=40, td=1, } ; (ne=='C'||ne=='H'||ne=='CP')?{ ts="/", qk="{}", } ; (ks&1)? &#_(0)
変数neは編集テキストの拡張子の最初の2文字が格納されています。なぜ2文字かというと2バイトの数値として扱っているからです。neは編集テキスト変数で,wa..109
を参照しています。ここが2バイトです。したがってneを指定するときは文字列("AB"
)ではなく数値('AB'
)として記述する必要があります。また「'ABC'
」のように指定することはできません。もしもこのように記述した場合は'BC'
と同じ値をとるので,期待したようには動作しません。
もしも拡張子の最初の2文字が同じで3文字目が異なるファイル(例えば.BASと.BAT)を識別するのであれば,次の例のようにできるでしょう。これらの例のほかにもおそらく手はあると思われます。
(ne=='BA')?{ ;.BA?
ht8, ;.BAT .BAK など
; &Sy(wa+$92) (cx.3&95=='S')?ht4, ;.BAS(1)
; &Sy(wa+$92) (cx.3|32=='s')?ht4, ;.BAS(2)
&So(wa+$92,".BAS") (r)?ht4, ;.BAS(3)
}
イベントマクロ自体は他のマクロと同様にマクロバッファに読み込まれていますが,イベントが発生したとき即座に起動されなければ全体のパフォーマンスが著しく落ちてしまいます。これを回避するために,イベントマクロがマクロバッファに読み込まれると pv+63
から始まる16バイトのテーブルに先頭アドレスを記録しておいて,イベントが発生したときはマクロバッファ全体を走査することなく高速に該当のイベントマクロが起動できるようになっています。
参考までにpv+63
からのイベントテーブルに記録されるイベントの順序を書いておきます。イベントテーブルは2バイトデータの引出が8個で,合計16バイトの領域です。
アドレス | イベント名 | イベントのタイミング | イベント種別 |
---|---|---|---|
pv+63 | !Abort | 動作中にエラーが発生した時 | キー入力 |
pv+65 | !Start | 最初の起動時 | 呼出し |
pv+67 | !Open | ファイルオープン時 | 呼出し |
pv+69 | !Close | ファイルクローズ時 | 呼出し |
pv+71 | !Edit | 編集中に特定の文字キーが入力された時 | キー入力 |
pv+73 | !View | ビューモードのファイルに対して編集操作を行なった時 | キー入力 |
pv+75 | !Timer | 編集中に一定時間キー入力がない時 | キー入力 |
pv+77 | !Filer | ファイラー上で文字キーが入力された時 | 呼出し |
なお,イベントマクロが存在しない場合は,アドレスの代わりにヌルが入っています。
任意のイベントマクロをオン・オフするマクロを上村郁夫氏が作成しています。(nifty:FGALDC/MES/15/3880 1997/01/08 00:55)
======== Xevent.def ======== by I.Kamimura #if 0 【イベントマクロON/OFF】 ●マクロを起動すると、現在のイベントマクロの状況がメニューに表示されま す。カーソルを合わせてリターンキーで選択すると、イベントマクロをON /OFFできます。 ※マクロバッファ内部を一時的に操作する ('!'と '?'とを置換する)だけ ですので、VZを再起動すると元の状態に戻ります。 ※元々存在しないイベントマクロをONにすることはできません。(当然) ※ON/OFFを実行すると、内部処理の都合上、外部マクロはクリアされ ます。 #endif * M 89 ^\ "Xevent" &01 af[=aw, !01 af], (r<0)?. (pm.8=='N')? { &03 (0)} ? &04 i[, (i=128){ &Zd(i--) } i], ; 外部マクロ一括削除 >^ 1: ;--- check event --- &09 i[=r.4, &08 pm=r, :A &Sn(pm) pm+=r+1, (pm..0) &02 ? { &Sc(pm+7,"ON ") (0)} ? { &Sc(pm+7,"OFF") } (i--)? >A i], 2: ;--- search word of title --- ; INPUT mg..0 = char ; OUTPUT r = address, 0:not found r=mg..0, p[=mh, :A (p.0==0)? >Z p++, (p..2-r)? { p+=p..0+2, >A } (p+4) :Z p], 3: ;--- ON --> OFF --- (pm..0) &02 ??. r.0='?', >^ 4: ;--- OFF --> ON --- (pm.1<<8+'?') &02 ??. r.0='!', >^ 8: ;--- menu title address --- &> (r+7+(r.4+1)*2) 9: (2+$) * P 1 "<Event>",12,7 "!Open ..." ; Don't touch! "!Close ..." ; Don't touch! "!Edit ..." ; Don't touch! "!Timer ..." ; Don't touch! "!View ..." ; Don't touch! "!Abort ..." ; Don't touch! "!Filer ..." ; Don't touch! * ======== End of Xevent.def ========