Visual Basic 6 アプリケーションの複数行エディットで改行位置が正しく認識されない
追加ですが、英語の(マルチバイト文字を含まない)テキストの場合は、行末位置のずれは起こっていません。
まだあまりちゃんと調査していませんが source/NVDAObjects/window/edit.py で使われている EM_LINELENGTH が "For ANSI text, this is the number of bytes" を返す仕様になっていることと関係があるような気がします。
本家版 2014.1rc1 で再現できたので、本家にチケットを書きました。
jteh さんからコメントをもらいました:
it's quite tricky to detect the encoding for an ANSI control. We'd probably have to go in-process (in-thread actually) and call GetThreadLocale.
どうやら Python 部分だけの修正では直せないようです。
後述のデバッグコードで検証してみました。
エディットの内容:
ああああ hello
パッチ(ブランチ ti33260):
diff --git a/source/NVDAObjects/window/edit.py b/source/NVDAObjects/window/edit.py
index 362fe1b..4325254 100644
--- a/source/NVDAObjects/window/edit.py
+++ b/source/NVDAObjects/window/edit.py
@@ -422,6 +422,10 @@ class EditTextInfo(textInfos.offsets.OffsetsTextInfo):
lineNum=self._getLineNumFromOffset(offset)
start=watchdog.cancellableSendMessage(self.obj.windowHandle,EM_LINEINDEX,lineNum,0)
length=watchdog.cancellableSendMessage(self.obj.windowHandle,EM_LINELENGTH,offset,0)
+ if not self.obj.isWindowUnicode:
+ import tones
+ tones.beep(880,10)
+ log.info("lineNum %d, start %d, length %d" % (lineNum,start, length))
end=start+length
#If we just seem to get invalid line info, calculate manually
if start<=0 and end<=0 and lineNum<=0 and self._getLineCount()<=0 and self._getStoryLength()>0:
カーソルの上下の移動のログ:
INFO - NVDAObjects.window.edit.EditTextInfo._getLineOffsets (15:01:15): lineNum 0, start 0, length 8 INFO - NVDAObjects.window.edit.EditTextInfo._getLineOffsets (15:01:16): lineNum 1, start 10, length 5
ということで、isWindowUnicode が False になっていること、start と length が全角1文字を2バイトで数えている、改行の CR/LF を2バイトで数えている、などの可能性が高いです。
本家チケットではなぜ isWindowUnicode で判定できないのか聞いてみたのですが「ANSI であったとしてもロケールがシステムデフォルト(いわゆる Shift JIS) とは限らないため、プロセスにフックして GetThreadLocale する必要がある」とのことでした。
日本で開発された非 Unicode のアプリケーションで Shift JIS 以外を考慮する必要はないと思いますが、ユニバーサルに対応するなら彼らの言うとおりでしょうね。。
状況としては、いつ本家が着手するか不明です。
ちょっとだけ調べてみた Visual Basic 6.0 の国際化に関する資料:
http://msdn.microsoft.com/en-us/library/aa261360%28v=vs.60%29.aspx
Unicode でない場合は mbcs で決め打ちするという前提で対策を実装してみました。
[ti33260 c4c0031] work around _getLineOffsets 1 file changed, 11 insertions(+), 4 deletions(-)
ただし、下記のような内容で行の区切りは正しくなったのですが、行のインデックスが正しく認識されていないので、EM_LINEFROMCHAR もどうやら対策が必要らしいです。。
1ぎょうめ 2ぎょうめ あああ Text1
INFO - NVDAObjects.window.edit.EditTextInfo._getLineOffsets (22:34:46): offset 0 lineNum 0 start 0 end 10 buf 1ぎょうめ start_new 0 end_new 5 INFO - NVDAObjects.window.edit.EditTextInfo._getLineOffsets (22:34:52): offset 7 lineNum 0 start 0 end 10 buf 1ぎょうめ start_new 0 end_new 5 INFO - NVDAObjects.window.edit.EditTextInfo._getLineOffsets (22:34:55): offset 14 lineNum 1 start 12 end 22 buf 2ぎょうめ start_new 7 end_new 12 INFO - NVDAObjects.window.edit.EditTextInfo._getLineOffsets (22:34:56): offset 19 lineNum 1 start 12 end 22 buf 2ぎょうめ start_new 7 end_new 12 INFO - NVDAObjects.window.edit.EditTextInfo._getLineOffsets (22:34:58): offset 26 lineNum 2 start 24 end 30 buf あああ start_new 14 end_new 17 INFO - NVDAObjects.window.edit.EditTextInfo._getLineOffsets (22:34:59):
いちおう EM_LINEFROMCHAR も含めて対策してみました。
[ti33260 888b82e] work around ti33260 1 file changed, 21 insertions(+), 8 deletions(-)
NVDA 日本語テスト版 jpbeta140302 https://dl.dropboxusercontent.com/u/62564469/nvda_jpbeta140302.exe
特定の開発ツールやAPIで作られたアプリケーションが、 複数行エディットでカーソル位置や改行位置が不正確になる、 というご指摘を他にもいただいていたので、 この修正が有効かどうかご検討いただけると助かります。
NVDA 日本語テスト版 jpbeta140303 https://dl.dropboxusercontent.com/u/62564469/nvda_jpbeta140303.exe
VoicePopper のフリーズ対策、ANSI アプリケーションの改行位置対策が、このビルドには含まれています。
これらの変更によって新たな副作用が起きているかどうかを確認することが、このビルドの目的です。
もし新しい副作用があるなら #33037 と #33260 は 2014.2jp に延期します。
いままでと同じ状況(存在するその他の不具合の状況に変化がない)ならば、影響なしとみなして、2014.1jp への採用とさせていただきます。
スケジュールとしては、本家の 2014.1 が正式にリリースされたら、日本語版については、電子署名付きのリリース候補版を作りたいと思っています。
補足説明:
ブランチ jp2014.1 と ti33037v2 と ti33260 を jpnext にマージしました。
この jpnext ブランチから jpbeta140303 をビルドしました。
点訳エンジンの修正は jp2014.1 ブランチに反映されています。
比較のために ti33037v2 と ti33260 をマージしていないビルドも作りました。
NVDA 日本語テスト版 jpbeta140303s https://dl.dropboxusercontent.com/u/62564469/nvda_jpbeta140303s.exe
本件の対策を含むブランチ jpnext を jp2014.1 にマージします。
Visual Basic 6 で開発されたアプリケーションのフォームに複数行エディット(ThunderRT6TextBox)が使われていると、そのコントロールの中のテキストの改行位置が正しく認識されないという現象を確認しました。
テスト環境は Windows 8.1(64ビット)+ NVDA 日本語テスト版 jpbeta140223 です。
テスト用の VB6 アプリケーションはお問い合わせをされたかたから提供していただきました。
例えば、以下のようにエディットにテキストを貼り付けて、 上下の矢印キーで移動すると、見えている行頭とは違う場所が行頭として認識されています。
また、レビューカーソルを先頭から1文字ずつ右に移動すると、2行目の「オペレーティング」の長音で「みぎ」と通知され、この文字が行末として認識されていることがわかります。