訂正:hmjre.dll FindRegular についてNo.08529
yamashita さん 17/07/24 16:07
 
すいません、先ほど「hmjre.dll FindRegular について」を投稿した
のですが、一部に文字化けが発生し、回避策が見つかったので再投稿します。

掲示板を汚してしまって失礼しました。


ご無沙汰しております。山下です。
秀丸 version 8.73 の hmjre.dll を使ったマクロにおいて、
期待と異なる動作がありましたので、報告します。
Windows7 Prof. SP1 です。

(1)strstr() における、期待通りの動作
以下の test1.mac を作成し、実行します。

test1.mac ここから >>>>
$line = "abc" + unichar(0x00A9) + "123";

#pos = strstr($line, "abc");
message(str(#pos)); // 0 ok

#pos = strstr($line, "123");
message(str(#pos)); // 4 ok
<<<< test1.mac ここまで

test1.mac は、期待通り動作しました。


(2)hmjre.dll FindRegular における、期待と異なる動作
test1.mac と似たことを行う
以下のマクロ test2.mac を作成し、実行します。

test2.mac ここから >>>>
loaddll "hmjre.dll";

$line = "abc" + unichar(0x00A9) + "123";

#pos = dllfunc("FindRegular", "abc", $line, 0);
message(str(#pos)); // 0 ok

#pos = dllfunc("FindRegular", "123", $line, 0);
message(str(#pos)); // 7 (4 になるはずでは?)

freedll;
<<<< test2.mac ここまで

test2.mac では dllfunc を2回実行しています。
1回目の dllfunc は期待通り 0 が返ってきます。
2回目の dllfunc は、私としては 4 が返ってきて欲しいのですが、
7 が返ってきます。


(3)その他
なお、unichar(0x00A9) の代わりに半角カタカナ カ (utf-16 0xFF76)
でやってみたところ、全て期待通りの結果が返ってきました。

もし、(2)が秀丸として意図せぬ動作だった場合、関連する論点として

・hmjre.dll の FindRegular 以外の、同様の関数での問題
・utf-16 0x0049 以外の、似た構造を持つ文字での問題

があると思われますが、これらは調べていません。

よろしくお願いします。

[ ]
RE:08529 訂正:hmjre.dll FindRegular にNo.08530
colder さん 17/07/24 19:00
 
山下さん、こんにちは。colderです。

これはhmjre.dllの仕様です。
FindRegularを使用する前にSetUnicodeIndexAutoConvertを呼び出すことで解決でき
ます。
#n = dllfunc("SetUnicodeIndexAutoConvert", 1);
詳しくは以下のヘルプの下の方の「ユニコード文字を扱う時の注意、および、SetUni
codeIndexAutoConvert関数」を見てください。
http://hidemaruo.mydns.jp:81/helpsite/hmjre/html/0008_API_MACRO.html

[ ]
RE:08530 ありがとうございました。No.08531
yamashita さん 17/07/24 19:28
 
colder さん、ありがとうございました。

ご指摘のページのうち、SetUnicodeIndexAutoConvert を使う方しか
試していませんが、期待通りの結果になりました。

HmJre.dll の help はそれなりに見たつもりだったんですが、
SetUnicodeIndexAutoConvert を見つけられませんでした。

次からはこの辺をよく見るようにします。

[ ]
RE:08531 ありがとうございました。No.08532
秀まるお2 さん 17/07/24 22:38
 
 今さらのお返事ですみませんが、仕様としてはcolderさんの話の通りでして、
ユニコード文字1文字が内部的に4バイトとしてカウントされる仕組みがあって、
そういうややこしいことになってしまってました。

 ややこしくてすみませんが、とりあえずそういう仕様ということでお願いしま
す。

[ ]
RE:08529 訂正:hmjre.dll FindRegular にNo.08533
でるもんたいいじま さん 17/07/25 00:45
 
でるもんた・いいじま@秀丸愛用者です。

解決されたとのことですが、ちょっと補足します。

> すいません、先ほど「hmjre.dll FindRegular について」を投稿したの
> ですが、一部に文字化けが発生し、回避策が見つかったので再投稿します。
...
> test1.mac ここから >>>>
> $line = "abc" + unichar(0x00A9) + "123";

この部分ですが、次の2通りの方法で、"..." の中に直接Unicode文字を
記入することができます。

$line = "abc\u00A9123";
$line = "abc\U000000A9123";

\uXXXX は UTF-16 でのコードを16進数4桁で指定します。
\Uxxxxxxxx は UTF-32 でのコードを16進数8桁で指定します。

この方法は、マクロファイルの文字コードがShift_JISでも使用可能ですし、
マクロ自体がUTF-16であっても、目に見えない制御文字や合成文字などを
明記する目的には有用です。

さらに、\uXXXX のほうは何と、サロゲートペアのコードも指定可能です。
なのでたとえば、

message "I \U0001F497 YOU";
message "I \uD83D\uDC97 YOU";

の2つは同じ意味になります。

[ ]
RE:08532 了解です。/ありがとうございまNo.08534
yamashita さん 17/07/25 14:11
 
まるおさん、お忙しいところ恐縮です。
SetUnicodeIndexAutoConvert 関連の件、諸事情あっての仕様かと思いますので、
了解です。

ただ、この件に起因する意図せぬ動作は、処理対象が特定の文字の場合でしか
発生しないため、発見が遅れがちです。

ついては、hmjre.dll のヘルプの該当関数付近に
「ユニコード文字を扱う時の注意」のリンクを張って頂き、
該当箇所に飛べるようにするというのはどうでしょうか。
この件を知らない人ばかりでなく、知ってる人にも便利なのではないかと
思います。


でるもんたいいじま様
ご指摘ありがとうございます。

[ ]
RE:08532 ありがとうございました。No.08535
colder さん 17/07/25 14:20
 
colderです
マクロを少し改変したら、おかしな動作を見つけてしまいました。
newfile;
setencode 8;
loaddll "hmjre.dll";

$line = "abc" + unichar(0x00A9) + "123";

#pos = dllfunc("FindRegular", "[\\u00A9]", $line, 0);
message(str(#pos)); // -1 なぜかヒットしない
#pos = dllfunc("FindRegular", "[\\uFF69]", $line, 0);
message(str(#pos)); // 3 なぜかヒットする

freedll;

[ ]
RE:08534 了解です。/ありがとうございまNo.08536
秀まるお2 さん 17/07/25 14:46
 
 「マクロからのdllfunc呼び出し」の先頭の文面を、

 HmJre.dllには、秀丸マクロからloaddllしてdllfuncで呼び出せる関数があります。
 ユニコード文字(Shift-JIS範囲外の時)を扱う場合に少々問題が発生します。詳
しくは

    ユニコード文字を扱う時の注意

 を参照ください。

 に直すこととさせていただます。次のバージョンからの添付となります。その
点ご了承ください。

[ ]
RE:08535 ありがとうございました。No.08537
秀まるお2 さん 17/07/25 15:29
 
 テストしてみたら再現できまして、もっと調べてみたら、FindRegularとかの
処理での、いわゆる「コードページ」が、日本語932固定になってました。

 そもそも的に、FindRegularとかに渡す文字列について、コードページという
か、文字コードというか、エンコードというか、それを指定する仕組みがそもそ
も無いというか、外国語の検索のことをまったく考えてませんでした。

 秀丸エディタ側の、マクロキーワードの「encode」の値をHmJre.dllに渡して
もらう必要があると思うので、例えば

    loaddll "tkinfo.dll";
    #n = dllfunc(""NotifyEncode", encode);

 みたいな感じでエンコードの値をHmJre.dll側に通知してくれるって仕組みを
追加すれば対応できるのですが、それでいいでしょうか。

 またヘルプに追加しないといけないですけども。

[ ]
RE:08537 新たな呪文?No.08538
yamashita さん 17/07/25 17:25
 
全部理解できてませんが、要するに FindRegular などを使う際、
SetUnicodeIndexAutoConvert

NotifyEncode

場合によっては唱える必要のある呪文になる、ということでしょうか?

[ ]
RE:08538 新たな呪文?No.08539
秀まるお2 さん 17/07/25 18:01
 
 とりあえず、SetUnicodeIndexAutoConvertだけ必要でして、将来的には
NotifyEncodeも呼んでもらわないとダメになりそう、という状況です。

 NotifyEncodeが必要になりそうなケースは、「ファイル・エンコードの種類」
の中の「欧文」とか「簡体字中国語」とか選択してるケースに限るので、普通に
日本語(またはユニコード)のファイルを扱う分には呼ばなくても大丈夫です。

 とりあえず、SetUnicodeIndexAutoConvertだけ呼ぶようにマクロ側の修正お願
いします。

[ ]
RE:08537 ありがとうございました。No.08540
colder さん 17/07/25 21:19
 
> 秀丸エディタ側の、マクロキーワードの「encode」の値をHmJre.dllに渡して
>もらう必要があると思うので、例えば
>
>    loaddll "tkinfo.dll";
>    #n = dllfunc(""NotifyEncode", encode);
>
> みたいな感じでエンコードの値をHmJre.dll側に通知してくれるって仕組みを
>追加すれば対応できるのですが、それでいいでしょうか。

対応方法は秀まるおさんにお任せします。

[ ]
RE:08540 ありがとうございました。No.08541
秀まるお2 さん 17/07/26 15:11
 
 NotifyEncode関数の追加ということで対応すると、古いHmJre.dllの場合に
dllfunc呼び出しがエラーになるって問題があるのですが、他にいい案が無いで
す。

 とりあえず、NotifyEncode関数追加で対応させていただくしか無いかなぁと思
います。

 HmJre.dllのVersion 5.01として、次の秀丸エディタおよび秀丸メールから添
付とさせていただきます。

[ ]
RE:08540 ありがとうございました。No.08542
秀まるお2 さん 17/07/26 15:13
 
 dllfuncw/dllfuncstrwで呼び出す用の関数を追加したら万事解決のような気が
しました。

 一回Version 5.01として出した次に対応しようかなぁと思います。

[ ]
RE:08542 ありがとうございました。No.08544
でるもんたいいじま さん 17/07/26 19:18
 
でるもんた・いいじま@秀丸愛用者です。

> loaddll "tkinfo.dll";
> #n = dllfunc(""NotifyEncode", encode);
> みたいな感じでエンコードの値をHmJre.dll側に

えっと、最初のloaddllの引数は "hmjre.dll" ですよね。
#手元で試そうとしたら、loaddllに失敗しました。

あと、dllfuncの引数に ""NotifyEncode" とあるのも、" がひとつ余計ですね。

☆ ☆ ☆

> NotifyEncode関数の追加ということで対応すると、古いHmJre.dllの
> 場合にdllfunc呼び出しがエラーになるって問題があるのですが、
> 他にいい案が無いです。

ちょっと試してみました。

loaddll "hmjre.dll";
#n = dllfunc("NoSuchFunction", 0);
message sprintf("NoSuchFunction(0) returned %d. result=%d.", #n, result);
endmacro;

dllfunc() の呼び出しに失敗したら result に0が返ってきてくれないかな…と
期待したのですが、マクロがエラー終了してしまいました。

次に、
#hJRE = loaddll("hmjre.dll");
#jreVersion = dllfunc(#hJRE, "JreGetVersion") & 0xFFFF;
message sprintf("JreGetVersion() = 0x%04X", #jreVersion);
としたら 0x0500 と出ました。

なので、こんなコードで回避することも考えられます。

#hJRE = loaddll("hmjre.dll");
#jreVersion = dllfunc(#hJRE, "JreGetVersion") & 0xFFFF;
if ( #jreVersion>=0x0501 ) #n = dllfunc(#hJRE, "NotifyEncode", encode);
// ここに、DLLを呼び出す各種処理を書く
freedll #hJRE;

☆ ☆ ☆

あるいは、秀丸側に dllfuncexist() といった関数を作っていただければ、

loaddll "hmjre.dll";
if ( dllfuncexist("NotifyEncode") )
    #n = dllfunc(#hJRE, "NotifyEncode", encode);

とか、

#hJRE = loaddll("hmjre.dll");
if ( dllfuncexist(#hJRE,"NotifyEncode") )
    #n = dllfunc(#hJRE, "NotifyEncode", encode);

とか書けると思います。

あるいは、事前にフラグを立てて置いた場合にはdllfunc系での呼び出しに
失敗した場合でもマクロを無条件でエラー終了とはせず、resultにfalseを
返す仕組みを作る、ということも考えられます。loaddll文・loaddll関数に
第二パラメータをつけられるようにする、というのがスマートでしょうか。

ただ、どちらも秀丸本体に手を入れる必要がありますし、古いバージョンの
秀丸でそのマクロを実行したらエラーになるという問題もありますし、
hmjre.dll だけ先行してのバージョンアップもできたほうがいいと思うので、
GetJreVersion() で確認してもらうのが確実なように思います。

☆ ☆ ☆

> dllfuncw/dllfuncstrwで呼び出す用の関数を追加したら万事解決の
> ような気がしました。

そうですね。将来的にはこちらのほうが確実かもしれません。

[ ]
RE:08541 ありがとうございました。No.08545
colder さん 17/07/26 21:06
 
> NotifyEncode関数の追加ということで対応すると、古いHmJre.dllの場合に
>dllfunc呼び出しがエラーになるって問題があるのですが、他にいい案が無いで
>す。
loaddll時にdllからHidemaru_EvalMacroを使って、自動的にNotifyEncode関数を呼ぶ
ってむちゃですかね。

[ ]
RE:08545 ありがとうございました。No.08546
でるもんたいいじま さん 17/07/26 22:42
 
でるもんた・いいじま@秀丸愛用者です。

> > NotifyEncode関数の追加ということで対応すると、古いHmJre.dllの
> > 場合にdllfunc呼び出しがエラーになるって問題があるのですが、
> > 他にいい案が無いです。
> loaddll時にdllからHidemaru_EvalMacroを使って、
> 自動的にNotifyEncode関数を呼ぶってむちゃですかね。

マクロ→DLL→Hidemaru_EvalMacroでマクロへ→またDLLへ、っていう
循環操作ってできたんでしたっけ?
…と思ってヘルプを読んでみた限りでは、できないとは書いてないですね。

で、Hidemaru_GetDllFuncCalledType() のヘルプを読んでいたら、
> 例えばdllfunc関数内でHidemaru_EvalMacroで
> さらにdllfuncを呼び出す場合
とはっきり「できる」と書いてあります。

そうすると、hmjre.dll側ではまず Hidemaru_GetDllFuncCalledType(-1) で
自身のハンドルを取得してから、Hidemaru_EvalMacroで
  if ( dllfunc(0x12345678, "NotifyEncode", encode) ) {}
なんていうマクロを実行すればいいことになりますね。

ただ、この場合はトリッキーな古いマクロとの互換性が問題になりそうです。
つまり、日本語以外の言語で呼び出されることを想定してこんなworkaroundを
書いたマクロが動かなくなります。

loaddll "hmjre.dll";
disabledraw;
#orig_encode = encode;
setencode 1, 1; // テキストの文字コードをShift_JISにする
  (ここでFindRegular等を呼び出す)
freedll;
setencode #orig_encode, 1;
enabledraw;

なので、
  From: "でるもんたいいじま" <xxxxxxxxxxxxxxxxxxx@maruo.co.jp>
  Subject: hidesoft.4:08544| RE 08542 ありがとうございました。
で書いたように、ランタイムエラーにしたくなければマクロ側から
JreGetVersion() を明示的に呼び出してもらうのがいいように思います。


---以下の内容はコミュニテックス会議室システムにより付加されました。
本文中のメールアドレスは伏せ字に変換されました。伏せ字にしたくない場合
はメールアドレスを""で囲んで書き込んでください。

[ ]
RE:08545 ありがとうございました。No.08547
vscode-life さん 17/07/27 10:48
 
>> NotifyEncode関数の追加ということで対応すると、古いHmJre.dllの場合に
>>dllfunc呼び出しがエラーになるって問題があるのですが、他にいい案が無いで
>>す。
>loaddll時にdllからHidemaru_EvalMacroを使って、自動的にNotifyEncode関数を呼
>ぶってむちゃですかね。

というか、encodeの値は、秀丸が提供する値なのですから、

"NotifyEncode", encode という規定の値の伝達で良いなら、
わざわざEvalという100倍以上遅い手段で、
サイトー企画が把握しているプログラム内部同士で
伝達するなど何の意味もなくないですか?

EvalMacroはあくまでも、内部プログラムにさわるべきでない各ユーザーが
自身のdll内の環境空間とマクロスクリプト環境空間の値や処理を
やりとりするために「開発者側のユーザーへのカプセル化」を考え、
やむなくやってる行為なわけで…


ここからはどうでもいい話ですが、
loaddllのタイミングでは正しくEvalMacroから自身のdllを呼ぶのは
無理では…
第1は、loaddll呼び出しの結果として、HMODULEの値なわけではない、
束縛変数ハンドルとでも称すべき小さな整数値を決めてるというのも
ありますし、
第2は、その束縛変数自体が、Hidemaru_GetDllFuncCalledType(-1)は、dllfunc系呼
び出しの
呼び出された関数内になって、やっと補足可能となる値であることです。

[ ]
RE:08547 ありがとうございました。No.08549
秀まるお2 さん 17/07/27 13:34
 
 たしかにHidemaru_EvalMacroが最近追加されたので、これを使う手もあります
が、encodeの値は後で変化するかもしれないとかって可能性まで考えると、やは
りマクロから通知してもらわないとダメな気もします。

 とりあえずはNotifyEncodeを呼び出してもらうことにしつつ、将来的に
dllfuncw/dllfuncstrwを使う作戦に持って行こうかなぁと思います。

 あと、でるもんたいいじまさんから提案のあったdllfuncexistとかもあったら
いいかと思ったんですが、この「dllfuncexist」を追加したとしても、秀丸
エディタのバージョンが古いとどっちみちエラーになるので、とりあえずは
バージョン番号を見てもらうしか無いかなぁと思います。

[ ]
RE:08544 ありがとうございました。No.08550
秀丸担当 さん 17/07/27 13:45
 

dllfuncexistという関数を追加して調べることは、HmJreに限らず一般的な用途
としてもあったらいいと思います。
追加を検討したいと思います。

[ ]
RE:08547 ありがとうございました。No.08551
colder さん 17/07/27 14:22
 
>"NotifyEncode", encode という規定の値の伝達で良いなら、
>わざわざEvalという100倍以上遅い手段で、
>サイトー企画が把握しているプログラム内部同士で
>伝達するなど何の意味もなくないですか?

サイトー企画製のプログラム間だけなら、そうでしょうね。
ユーザーが作ったdllでもdllfunc/dllfuncstrで渡される文字列の文字コードが編集
中のファイルの文字コードで変わるので…
これが問題になるようなマクロを書く人は、あまりいないからいいけど。

ところで、秀丸リーダーは大丈夫なんだろうか?

[ ]
RE:08541 ありがとうございました。No.08554
でるもんたいいじま さん 17/07/31 20:40
 
でるもんた・いいじまです。

もう決着済みの話題ですが、与太話。

> とりあえず、NotifyEncode関数追加で対応させていただくしか
> 無いかなぁと思います。
> HmJre.dllのVersion 5.01として、次の秀丸エディタおよび
> 秀丸メールから添付とさせていただきます。

HmJre.dllのヘルプを読んでいたら、「実は既に同等の機能があるには
あるけど、秀丸のマクロからは呼び出せない」ということを発見して
しまいました。

HmJre.dllのヘルプ中、「JRE32.DLL互換API」のページに、こんな記述が
あります。

> extern "C" BOOL WINAPI Jre2SetCodePage( LPJRE2 pJre, UINT cp );
>
> 検索文字列および検索対象文字列のコードページを指定します。
> コードページにはCP_UTF8は指定できません。
>
> 文字コードの違う文字列について検索を実行する時は、Jre2Open関数を
> 呼び出した次にこの関数を呼んでください。この関数を呼んでから
> Jre2Compile/Jre2GetMatchInfo等を呼び出してください。

まず、この関数宣言にはWINAPIというキーワードがついています。
秀丸のマクロから32bitのDLLを呼び出すためには、呼び出し規約が
WINAPI(__stdcall)ではなくWINAPIV(__cdecl)になっている必要が
あるので、この関数は秀丸からは呼び出せない、ということになります。

もし、64bit版のHmJre.dllにも互換性のためにこの関数が残っている
のであれば、物理的にこれを呼び出すこと自体は可能なはずです。
64bitのDLLでは、WINAPIと宣言してもWINAPIVと宣言しても同じ
コードになるはずですので。

ただ、仮にこれが呼び出せたとしても、この関数はあくまでJRE32.DLL
との互換性のために残されているだけですし、しかも第一引数は構造体
へのポインタなので、マクロで扱うには相当な困難が伴うはずです。

それに、FindRegular() 等をいきなり呼び出す今の方式とは処理の
順序が全く違うので、苦労して呼び出しても実際に機能するかどうかは
かなり怪しいと思います。

[ ]
RE:08551 ありがとうございました。No.08555
秀まるお2 さん 17/08/01 11:24
 
> ところで、秀丸リーダーは大丈夫なんだろうか?

 たぶん外国語ファイル上ではうまく動作しないと思います。テストもしたこと
無いし。

[ ]