论坛: 公开讨论 (Thread #32907)

クリップボードにコピーした文字列の文字化け (2012-10-09 10:02 by comutt #65800)

当方 Windows 7 Professional 日本語版の環境なのですが、
Tera Term 4.75 でターミナル上の日本語文字列をクリップボードにコピーすると、
他のアプリにペーストしたときに、文字化けが発生します。

いつからかこうなったのか、(最近Windows7にしたので)Windows7 を使い始めた当初からなのか、
わからないのですが、同様の現象の方はいらっしゃらないでしょうか?

4.69 あたりまでまき戻してみて(TERATERM.INIも削除してみて)も同様の現象です。
(なので、当方の環境が何かおかしいのかもしれません。。。)

ソースを追ったりしたわけではありませんが、
なんとなく、ログイン先のロケール(UTF-8)文字列でクリップボードにコピーされているのかしら?
と邪推しています。(が、他のロケールを試したわけではないので、ぜんぜん違うかもしれません)

何かご存知の方いらしたら、教えていただけると幸いです。

RE: クリップボードにコピーした文字列の文字化け (2012-10-09 12:08 by (del#1144) #65802)

端末設定で確認できる「受信文字コード」「ロケール」「コードページ」はどうなっていますか?
回复到 #65800

RE: クリップボードにコピーした文字列の文字化け (2012-10-09 14:09 by comutt #65804)

[メッセージ#65802 へのフォロー]

> 端末設定で確認できる「受信文字コード」「ロケール」「コードページ」はどうなっていますか?

受信文字コード: UTF-8
ロケール: japanese
コードページ: 932

となっています。

ちなみに、 TeraTerm のターミナル -> (同一、違うを問わず) TeraTerm のターミナル
のコピー&ペーストは日本語を含んでいても正常です。


回复到 #65802

RE: クリップボードにコピーした文字列の文字化け (2012-10-12 21:06 by doda #65841)

適当な日本語文字列をコピーして、メモ帳に貼り付けるとどのように文字化けしますか?
コピーした文字列と貼り付けられた文字列を教えてください。
可能でしたら、メモ帳に貼り付けられた内容をファイルに保存し、
適当なチケットを作成してファイルを添付してください。
回复到 #65800

RE: クリップボードにコピーした文字列の文字化け (2012-10-14 15:04 by comutt #65852)

再現条件がなにかしらあることがわかったのですが、都合によりまだ試せておりません。
再現できたら、ご報告させていただきます。
# 初回のログインが、端末経由か、RDP経由か、で(私の環境の場合は)変わってくるのではないか?と思ってます
# キーボードを US-ASCII 配列で認識させてるので、最初はキーボードロケールが US-ASCII になります。
# その辺が、何か関係しているのではないかと。
回复到 #65841

RE: クリップボードにコピーした文字列の文字化け (2012-11-05 07:25 by comutt #66122)

#どこにくっつけようか迷いましたが、ここにします。

すみません、時間がたってしまいましたが、原因調査をしてみました。

RDP云々は関係なくて、やはり、キーボードロケールが単純に影響しておりました。

キーボードロケールがUSの状態でコピーすると、漏れなく文字化けする状態でした。

PuTTYなど、他のアプリケーションでは発生しないため、
PuTTYのコピー処理を拝見したところ、以下のようになっていました(抜粋)

len2 = WideCharToMultiByte(CP_ACP, 0, data, len, 0, 0, NULL, NULL);

clipdata = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE,
len * sizeof(wchar_t));
clipdata2 = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, len2);

/* 省略 */

if (OpenClipboard(hwnd)) {
EmptyClipboard();
SetClipboardData(CF_UNICODETEXT, clipdata);
SetClipboardData(CF_TEXT, clipdata2);
if (clipdata3)
SetClipboardData(RegisterClipboardFormat(CF_RTF), clipdata3);
CloseClipboard();
} else {
GlobalFree(clipdata);
GlobalFree(clipdata2);
}

つまり、CF_TEXTとCF_UNICODETEXTを両方設定していました。

TeraTerm は WCHAR を使っていないので、
MultiByteToWideChar するように(PuTTYとは逆)、以下のパッチを書いてみいました(rev5057に対して)

なにぶん、C言語開発に疎いので、おかしな処理をしていたらすみません。
受け入れ可能な形で修正していただいて、取り込んでいただけたら幸いです。
VS2010でのDebugビルドでしか確認しておりませんが、
Windows 7 Professional (日本語版) で問題なく動くことを確認しております。


Index: trunk/teraterm/teraterm/clipboar.c
===================================================================
--- trunk/teraterm/teraterm/clipboar.c (revision 5057)
+++ trunk/teraterm/teraterm/clipboar.c (working copy)
@@ -67,6 +67,10 @@
void CBClose()
{
BOOL Empty;
+ HGLOBAL CBCopyWideHandle = NULL;
+ LPWSTR CBCopyWidePtr = NULL;
+ int WideCharLength;
+
if (CBCopyHandle==NULL) {
return;
}
@@ -76,6 +80,14 @@
Empty = (CBCopyPtr[0]==0);
}

+ WideCharLength = MultiByteToWideChar(CP_ACP, 0, CBCopyPtr, -1, NULL, 0);
+ CBCopyWideHandle = GlobalAlloc(GMEM_MOVEABLE, sizeof(WCHAR) * WideCharLength);
+ if (CBCopyWideHandle) {
+ CBCopyWidePtr = (LPWSTR)GlobalLock(CBCopyWideHandle);
+ MultiByteToWideChar(CP_ACP, 0, CBCopyPtr, -1, CBCopyWidePtr, WideCharLength);
+ GlobalUnlock(CBCopyWideHandle);
+ }
+
GlobalUnlock(CBCopyHandle);
CBCopyPtr = NULL;

@@ -83,10 +95,17 @@
EmptyClipboard();
if (! Empty) {
SetClipboardData(CF_TEXT, CBCopyHandle);
+ if (CBCopyWidePtr) {
+ SetClipboardData(CF_UNICODETEXT, CBCopyWideHandle);
+ }
}
CloseClipboard();
}
CBCopyHandle = NULL;
+
+ if (CBCopyWideHandle) {
+ GlobalFree(CBCopyWideHandle);
+ }
}

void CBStartPaste(HWND HWin, BOOL AddCR, BOOL Bracketed,
回复到 #65800

RE: クリップボードにコピーした文字列の文字化け (2012-11-05 07:32 by comutt #66123)

パッチが大変見づらくなってしまったので、 gist にも貼りました。
よろしければこちらをご参照ください。

https://gist.github.com/4014064
回复到 #66122

RE: クリップボードにコピーした文字列の文字化け (2012-11-05 12:46 by comutt #66129)

チケットにまとめさせていただきました。

http://sourceforge.jp/ticket/browse.php?group_id=1412&tid=30015
回复到 #66123