• R/O
  • SSH
  • HTTPS

ttssh2: Commit


Commit MetaInfo

Revision7484 (tree)
Time2019-03-15 00:53:55
Authorzmatsuo

Log Message

GetConvString()#ttime.cの戻り値をconst wchar_t *に変更
前後参照変換の処理を ttime.c に移動
CommTextOutW(), CommTextEchoW() を ttcmn.c に追加
imm32.lib をリンクから外した

Change Summary

Incremental Difference

--- trunk/teraterm/common/ttcommon.h (revision 7483)
+++ trunk/teraterm/common/ttcommon.h (revision 7484)
@@ -76,8 +76,10 @@
7676 int PASCAL CommBinaryOut(PComVar cv, PCHAR B, int C);
7777 int PASCAL CommBinaryBuffOut(PComVar cv, PCHAR B, int C);
7878 int PASCAL CommTextOut(PComVar cv, PCHAR B, int C);
79+int PASCAL CommTextOutW(PComVar cv, const wchar_t *B, int C);
7980 int PASCAL CommBinaryEcho(PComVar cv, PCHAR B, int C);
8081 int PASCAL CommTextEcho(PComVar cv, PCHAR B, int C);
82+int PASCAL CommTextEchoW(PComVar cv, const wchar_t *B, int C);
8183
8284 void PASCAL CreateNotifyIcon(PComVar cv);
8385 void PASCAL DeleteNotifyIcon(PComVar cv);
--- trunk/teraterm/teraterm/CMakeLists.txt (revision 7483)
+++ trunk/teraterm/teraterm/CMakeLists.txt (revision 7484)
@@ -164,7 +164,6 @@
164164 gdi32
165165 comctl32
166166 ws2_32
167- imm32
168167 imagehlp
169168 delayimp
170169 uuid
--- trunk/teraterm/teraterm/ttime.c (revision 7483)
+++ trunk/teraterm/teraterm/ttime.c (revision 7484)
@@ -1,6 +1,6 @@
11 /*
22 * Copyright (C) 1994-1998 T. Teranishi
3- * (C) 2007-2017 TeraTerm Project
3+ * (C) 2007-2019 TeraTerm Project
44 * All rights reserved.
55 *
66 * Redistribution and use in source and binary forms, with or without
@@ -29,18 +29,25 @@
2929 /* Tera Term */
3030 /* TERATERM.EXE, IME interface */
3131
32-#include "teraterm.h"
33-#include "tttypes.h"
32+#undef UNICODE
33+#undef _UNICODE
34+
35+#include <windows.h>
3436 #include <stdlib.h>
3537 #include <string.h>
3638 #include <imm.h>
3739
40+#include "ttime.h"
41+#include "ttlib.h"
42+
43+#if 1
44+#include "teraterm.h"
45+#include "tttypes.h"
3846 #include "ttwinman.h"
3947 #include "ttcommon.h"
48+#include "buffer.h" // for BuffGetCurrentLineData()
49+#endif
4050
41-#include "ttime.h"
42-#include "ttlib.h"
43-
4451 #ifndef _IMM_
4552 #define _IMM_
4653
@@ -55,8 +62,8 @@
5562
5663 #define GCS_RESULTSTR 0x0800
5764
58-typedef LONG (WINAPI *TImmGetCompositionString)
59- (HIMC, DWORD, LPVOID, DWORD);
65+typedef LONG (WINAPI *TImmGetCompositionStringA)(HIMC, DWORD, LPVOID, DWORD);
66+typedef LONG (WINAPI *TImmGetCompositionStringW)(HIMC, DWORD, LPVOID, DWORD);
6067 typedef HIMC (WINAPI *TImmGetContext)(HWND);
6168 typedef BOOL (WINAPI *TImmReleaseContext)(HWND, HIMC);
6269 typedef BOOL (WINAPI *TImmSetCompositionFont)(HIMC, LPLOGFONTA);
@@ -64,7 +71,8 @@
6471 typedef BOOL (WINAPI *TImmGetOpenStatus)(HIMC);
6572 typedef BOOL (WINAPI *TImmSetOpenStatus)(HIMC, BOOL);
6673
67-static TImmGetCompositionString PImmGetCompositionString;
74+static TImmGetCompositionStringW PImmGetCompositionStringW;
75+static TImmGetCompositionStringA PImmGetCompositionStringA;
6876 static TImmGetContext PImmGetContext;
6977 static TImmReleaseContext PImmReleaseContext;
7078 static TImmSetCompositionFont PImmSetCompositionFont;
@@ -74,8 +82,29 @@
7482
7583
7684 static HANDLE HIMEDLL = NULL;
77-static LOGFONT lfIME;
85+static LOGFONTA lfIME;
7886
87+#if 1
88+static void show_message()
89+{
90+ char uimsg[MAX_UIMSG];
91+ get_lang_msg("MSG_TT_ERROR", uimsg, sizeof(uimsg), "Tera Term: Error", ts.UILanguageFile);
92+ get_lang_msg("MSG_USE_IME_ERROR", ts.UIMsg, sizeof(ts.UIMsg), "Can't use IME", ts.UILanguageFile);
93+ MessageBoxA(0,ts.UIMsg,uimsg,MB_ICONEXCLAMATION);
94+ WritePrivateProfileStringA("Tera Term","IME","off",ts.SetupFName);
95+ ts.UseIME = 0;
96+#if 0
97+ tempts = (PTTSet)malloc(sizeof(TTTSet));
98+ if (tempts!=NULL)
99+ {
100+ GetDefaultSet(tempts);
101+ tempts->UseIME = 0;
102+ ChangeDefaultSet(tempts,NULL);
103+ free(tempts);
104+ }
105+#endif
106+}
107+#endif
79108
80109 BOOL LoadIME()
81110 {
@@ -83,38 +112,27 @@
83112 #if 0
84113 PTTSet tempts;
85114 #endif
86- char uimsg[MAX_UIMSG];
87115 char imm32_dll[MAX_PATH];
88116
89117 if (HIMEDLL != NULL) return TRUE;
90- GetSystemDirectory(imm32_dll, sizeof(imm32_dll));
118+ GetSystemDirectoryA(imm32_dll, sizeof(imm32_dll));
91119 strncat_s(imm32_dll, sizeof(imm32_dll), "\\imm32.dll", _TRUNCATE);
92- HIMEDLL = LoadLibrary(imm32_dll);
120+ HIMEDLL = LoadLibraryA(imm32_dll);
93121 if (HIMEDLL == NULL)
94122 {
95- get_lang_msg("MSG_TT_ERROR", uimsg, sizeof(uimsg), "Tera Term: Error", ts.UILanguageFile);
96- get_lang_msg("MSG_USE_IME_ERROR", ts.UIMsg, sizeof(ts.UIMsg), "Can't use IME", ts.UILanguageFile);
97- MessageBox(0,ts.UIMsg,uimsg,MB_ICONEXCLAMATION);
98- WritePrivateProfileString("Tera Term","IME","off",ts.SetupFName);
99- ts.UseIME = 0;
100-#if 0
101- tempts = (PTTSet)malloc(sizeof(TTTSet));
102- if (tempts!=NULL)
103- {
104- GetDefaultSet(tempts);
105- tempts->UseIME = 0;
106- ChangeDefaultSet(tempts,NULL);
107- free(tempts);
108- }
109-#endif
123+ show_message();
110124 return FALSE;
111125 }
112126
113127 Err = FALSE;
114128
115- PImmGetCompositionString = (TImmGetCompositionString)GetProcAddress(
129+ PImmGetCompositionStringW = (TImmGetCompositionStringW)GetProcAddress(
130+ HIMEDLL, "ImmGetCompositionStringW");
131+ if (PImmGetCompositionStringW==NULL) Err = TRUE;
132+
133+ PImmGetCompositionStringA = (TImmGetCompositionStringA)GetProcAddress(
116134 HIMEDLL, "ImmGetCompositionStringA");
117- if (PImmGetCompositionString==NULL) Err = TRUE;
135+ if (PImmGetCompositionStringA==NULL) Err = TRUE;
118136
119137 PImmGetContext = (TImmGetContext)GetProcAddress(
120138 HIMEDLL, "ImmGetContext");
@@ -202,50 +220,53 @@
202220 (*PImmReleaseContext)(HVTWin,hIMC);
203221 }
204222
205-HGLOBAL GetConvString(UINT wParam, LPARAM lParam)
223+/*
224+ * @param[in,out] *len wchar_t文字数
225+ * @reterun 変換wchar_t文字列へのポインタ
226+ * NULLの場合変換確定していない(またはエラー)
227+ * 文字列は使用後free()すること
228+ */
229+const wchar_t *GetConvString(HWND hWnd, UINT wParam, LPARAM lParam, size_t *len)
206230 {
207- HIMC hIMC;
208- HGLOBAL hstr = NULL;
209- //LPSTR lpstr;
210231 wchar_t *lpstr;
211- DWORD dwSize;
212232
233+ *len = 0;
213234 if (HIMEDLL==NULL) return NULL;
214- hIMC = (*PImmGetContext)(HVTWin);
215- if (hIMC==0) return NULL;
216235
217- if ((lParam & GCS_RESULTSTR)==0)
218- goto skip;
236+ if ((lParam & GCS_RESULTSTR) != 0) {
237+ HIMC hIMC;
238+ LONG size;
219239
220- // Get the size of the result string.
221- //dwSize = (*PImmGetCompositionString)(hIMC, GCS_RESULTSTR, NULL, 0);
222- dwSize = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, NULL, 0);
223- dwSize += sizeof(WCHAR);
224- hstr = GlobalAlloc(GHND,dwSize);
225- if (hstr != NULL)
226- {
227-// lpstr = (LPSTR)GlobalLock(hstr);
228- lpstr = GlobalLock(hstr);
229- if (lpstr != NULL)
230- {
231-#if 0
232- // Get the result strings that is generated by IME into lpstr.
233- (*PImmGetCompositionString)
234- (hIMC, GCS_RESULTSTR, lpstr, dwSize);
235-#else
236- ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, lpstr, dwSize);
237-#endif
238- GlobalUnlock(hstr);
240+ hIMC = (*PImmGetContext)(hWnd);
241+ if (hIMC==0) return NULL;
242+
243+ // Get the size of the result string.
244+ // 注意 ImmGetCompositionStringW() の戻り値は byte 数
245+ size = PImmGetCompositionStringW(hIMC, GCS_RESULTSTR, NULL, 0);
246+ if (size <= 0) {
247+ lpstr = NULL; // エラー
248+ } else {
249+ lpstr = malloc(size + sizeof(WCHAR));
250+ if (lpstr != NULL)
251+ {
252+ size = PImmGetCompositionStringW(hIMC, GCS_RESULTSTR, lpstr, size);
253+ if (size <= 0) {
254+ free(lpstr);
255+ lpstr = NULL;
256+ } else {
257+ *len = size/2;
258+ lpstr[(size/2)] = 0; // ターミネートする
259+ }
260+ }
239261 }
240- else {
241- GlobalFree(hstr);
242- hstr = NULL;
243- }
262+
263+ (*PImmReleaseContext)(hWnd, hIMC);
264+
265+ } else {
266+ lpstr = NULL;
244267 }
245268
246-skip:
247- (*PImmReleaseContext)(HVTWin, hIMC);
248- return hstr;
269+ return lpstr;
249270 }
250271
251272 BOOL GetIMEOpenStatus()
@@ -270,3 +291,67 @@
270291 (*PImmSetOpenStatus)(hIMC, stat);
271292 (*PImmReleaseContext)(HVTWin, hIMC);
272293 }
294+
295+// IMEの前後参照変換機能への対応
296+// MSからちゃんと仕様が提示されていないので、アドホックにやるしかないらしい。
297+// cf. http://d.hatena.ne.jp/topiyama/20070703
298+// http://ice.hotmint.com/putty/#DOWNLOAD
299+// http://27213143.at.webry.info/201202/article_2.html
300+// http://webcache.googleusercontent.com/search?q=cache:WzlX3ouMscIJ:anago.2ch.net/test/read.cgi/software/1325573999/82+IMR_DOCUMENTFEED&cd=13&hl=ja&ct=clnk&gl=jp
301+// (2012.5.9 yutaka)
302+LRESULT ReplyIMERequestDocumentfeed(LPARAM lParam, int NumOfColumns)
303+{
304+ static int complen, newsize;
305+ static char comp[512];
306+ int size, ret;
307+ char buf[512], newbuf[1024];
308+ HIMC hIMC;
309+
310+ // "IME=off"の場合は、何もしない。
311+ size = NumOfColumns + 1; // カーソルがある行の長さ+null
312+
313+ if (lParam == 0) { // 1回目の呼び出し
314+ // バッファのサイズを返すのみ。
315+ // ATOK2012では常に complen=0 となる。
316+ complen = 0;
317+ memset(comp, 0, sizeof(comp));
318+ hIMC = PImmGetContext(HVTWin);
319+ if (hIMC) {
320+ ret = PImmGetCompositionStringA(hIMC, GCS_COMPSTR, comp, sizeof(comp));
321+ if (ret == IMM_ERROR_NODATA || ret == IMM_ERROR_GENERAL) {
322+ memset(comp, 0, sizeof(comp));
323+ }
324+ complen = strlen(comp); // w/o null
325+ PImmReleaseContext(HVTWin, hIMC);
326+ }
327+ newsize = size + complen; // 変換文字も含めた全体の長さ(including null)
328+
329+ } else { // 2回目の呼び出し
330+ //lParam を RECONVERTSTRING と 文字列格納バッファに使用する
331+ RECONVERTSTRING *pReconv = (RECONVERTSTRING*)lParam;
332+ char* pszParagraph = (char*)pReconv + sizeof(RECONVERTSTRING);
333+ int cx;
334+
335+ cx = BuffGetCurrentLineData(buf, sizeof(buf));
336+
337+ // カーソル位置に変換文字列を挿入する。
338+ memset(newbuf, 0, sizeof(newbuf));
339+ memcpy(newbuf, buf, cx);
340+ memcpy(newbuf + cx, comp, complen);
341+ memcpy(newbuf + cx + complen, buf + cx, size - cx);
342+ newsize = size + complen; // 変換文字も含めた全体の長さ(including null)
343+
344+ pReconv->dwSize = sizeof(RECONVERTSTRING);
345+ pReconv->dwVersion = 0;
346+ pReconv->dwStrLen = newsize - 1;
347+ pReconv->dwStrOffset = sizeof(RECONVERTSTRING);
348+ pReconv->dwCompStrLen = complen;
349+ pReconv->dwCompStrOffset = cx;
350+ pReconv->dwTargetStrLen = complen;
351+ pReconv->dwTargetStrOffset = cx;
352+
353+ memcpy(pszParagraph, newbuf, newsize);
354+ //OutputDebugPrintf("cx %d buf [%d:%s] -> [%d:%s]\n", cx, size, buf, newsize, newbuf);
355+ }
356+ return (sizeof(RECONVERTSTRING) + newsize);
357+}
--- trunk/teraterm/teraterm/ttime.h (revision 7483)
+++ trunk/teraterm/teraterm/ttime.h (revision 7484)
@@ -1,6 +1,6 @@
11 /*
22 * Copyright (C) 1994-1998 T. Teranishi
3- * (C) 2007-2017 TeraTerm Project
3+ * (C) 2007-2019 TeraTerm Project
44 * All rights reserved.
55 *
66 * Redistribution and use in source and binary forms, with or without
@@ -38,11 +38,12 @@
3838 void FreeIME();
3939 BOOL CanUseIME();
4040 void SetConversionWindow(HWND HWin, int X, int Y);
41-void SetConversionLogFont(HWND HWin, PLOGFONT lf);
41+void SetConversionLogFont(HWND HWin, PLOGFONTA lf);
4242 BOOL GetIMEOpenStatus(void);
4343 void SetIMEOpenStatus(BOOL stat);
4444
45-HGLOBAL GetConvString(UINT wParam, LPARAM lParam);
45+const wchar_t *GetConvString(HWND hWnd, UINT wParam, LPARAM lParam, size_t *len);
46+LRESULT ReplyIMERequestDocumentfeed(LPARAM lParam, int NumOfColumns);
4647
4748 #ifndef WM_IME_COMPOSITION
4849 #define WM_IME_COMPOSITION 0x010F
--- trunk/teraterm/teraterm/vtwin.cpp (revision 7483)
+++ trunk/teraterm/teraterm/vtwin.cpp (revision 7484)
@@ -3218,63 +3218,34 @@
32183218
32193219 LRESULT CVTWindow::OnIMEComposition(WPARAM wParam, LPARAM lParam)
32203220 {
3221- HGLOBAL hstr;
3222- //LPSTR lpstr;
3223- wchar_t *lpstr;
3224- int Len;
3225- char *mbstr;
3226- int mlen;
3227-
32283221 if (CanUseIME()) {
3229- hstr = GetConvString(wParam, lParam);
3230- }
3231- else {
3232- hstr = NULL;
3233- }
3234-
3235- if (hstr!=NULL) {
3236- //lpstr = (LPSTR)GlobalLock(hstr);
3237- lpstr = (wchar_t *)GlobalLock(hstr);
3238- if (lpstr!=NULL) {
3239- mlen = wcstombs(NULL, lpstr, 0);
3240- mbstr = (char *)malloc(sizeof(char) * (mlen + 1));
3241- if (mbstr == NULL) {
3242- goto skip;
3243- }
3244- Len = wcstombs(mbstr, lpstr, mlen + 1);
3245-
3246- // add this string into text buffer of application
3247- Len = strlen(mbstr);
3248- if (Len==1) {
3249- switch (mbstr[0]) {
3222+ size_t len;
3223+ const wchar_t *lpstr = GetConvString(HVTWin, wParam, lParam, &len);
3224+ if (lpstr != NULL) {
3225+ if (len == 1 && ControlKey()) {
3226+ const static wchar_t code_ctrl_space = 0;
3227+ const static wchar_t code_ctrl_backslash = 0x1c;
3228+ switch(*lpstr) {
32503229 case 0x20:
3251- if (ControlKey()) {
3252- mbstr[0] = 0; /* Ctrl-Space */
3253- }
3230+ lpstr = &code_ctrl_space;
32543231 break;
32553232 case 0x5c: // Ctrl-\ support for NEC-PC98
3256- if (ControlKey()) {
3257- mbstr[0] = 0x1c;
3258- }
3233+ lpstr = &code_ctrl_backslash;
32593234 break;
32603235 }
32613236 }
32623237 if (ts.LocalEcho>0) {
3263- CommTextEcho(&cv,mbstr,Len);
3238+ CommTextEchoW(&cv,lpstr,len);
32643239 }
3265- CommTextOut(&cv,mbstr,Len);
3266-
3267- free(mbstr);
3268- GlobalUnlock(hstr);
3240+ CommTextOutW(&cv,lpstr,len);
3241+ free((void *)lpstr);
3242+ return 0;
32693243 }
3270-skip:
3271- GlobalFree(hstr);
3272- return 0;
32733244 }
32743245 return CFrameWnd::DefWindowProc(WM_IME_COMPOSITION,wParam,lParam);
32753246 }
32763247
3277-LONG CVTWindow::OnIMEInputChange(UINT wParam, LONG lParam)
3248+LRESULT CVTWindow::OnIMEInputChange(WPARAM wParam, LPARAM lParam)
32783249 {
32793250 ChangeCaret();
32803251
@@ -3281,7 +3252,7 @@
32813252 return CFrameWnd::DefWindowProc(WM_INPUTLANGCHANGE,wParam,lParam);
32823253 }
32833254
3284-LONG CVTWindow::OnIMENotify(UINT wParam, LONG lParam)
3255+LRESULT CVTWindow::OnIMENotify(WPARAM wParam, LPARAM lParam)
32853256 {
32863257 switch (wParam) {
32873258 case IMN_SETOPENSTATUS: {
@@ -3326,72 +3297,17 @@
33263297 return CFrameWnd::DefWindowProc(WM_IME_NOTIFY,wParam,lParam);
33273298 }
33283299
3329-// IMEの前後参照変換機能への対応
3330-// MSからちゃんと仕様が提示されていないので、アドホックにやるしかないらしい。
3331-// cf. http://d.hatena.ne.jp/topiyama/20070703
3332-// http://ice.hotmint.com/putty/#DOWNLOAD
3333-// http://27213143.at.webry.info/201202/article_2.html
3334-// http://webcache.googleusercontent.com/search?q=cache:WzlX3ouMscIJ:anago.2ch.net/test/read.cgi/software/1325573999/82+IMR_DOCUMENTFEED&cd=13&hl=ja&ct=clnk&gl=jp
3335-// (2012.5.9 yutaka)
3336-LONG CVTWindow::OnIMERequest(UINT wParam, LONG lParam)
3300+LRESULT CVTWindow::OnIMERequest(WPARAM wParam, LPARAM lParam)
33373301 {
3338- static int complen, newsize;
3339- static char comp[512];
3340- int size, ret;
3341- char buf[512], newbuf[1024];
3342- HIMC hIMC;
3343-
33443302 // "IME=off"の場合は、何もしない。
3345- if (ts.UseIME > 0 &&
3346- wParam == IMR_DOCUMENTFEED) {
3347- size = NumOfColumns + 1; // カーソルがある行の長さ+null
3348-
3349- if (lParam == 0) { // 1回目の呼び出し
3350- // バッファのサイズを返すのみ。
3351- // ATOK2012では常に complen=0 となる。
3352- complen = 0;
3353- memset(comp, 0, sizeof(comp));
3354- hIMC = ImmGetContext(HVTWin);
3355- if (hIMC) {
3356- ret = ImmGetCompositionString(hIMC, GCS_COMPSTR, comp, sizeof(comp));
3357- if (ret == IMM_ERROR_NODATA || ret == IMM_ERROR_GENERAL) {
3358- memset(comp, 0, sizeof(comp));
3359- }
3360- complen = strlen(comp); // w/o null
3361- ImmReleaseContext(HVTWin, hIMC);
3362- }
3363- newsize = size + complen; // 変換文字も含めた全体の長さ(including null)
3364-
3365- } else { // 2回目の呼び出し
3366- //lParam を RECONVERTSTRING と 文字列格納バッファに使用する
3367- RECONVERTSTRING *pReconv = (RECONVERTSTRING*)lParam;
3368- char* pszParagraph = (char*)pReconv + sizeof(RECONVERTSTRING);
3369- int cx;
3370-
3371- cx = BuffGetCurrentLineData(buf, sizeof(buf));
3372-
3373- // カーソル位置に変換文字列を挿入する。
3374- memset(newbuf, 0, sizeof(newbuf));
3375- memcpy(newbuf, buf, cx);
3376- memcpy(newbuf + cx, comp, complen);
3377- memcpy(newbuf + cx + complen, buf + cx, size - cx);
3378- newsize = size + complen; // 変換文字も含めた全体の長さ(including null)
3379-
3380- pReconv->dwSize = sizeof(RECONVERTSTRING);
3381- pReconv->dwVersion = 0;
3382- pReconv->dwStrLen = newsize - 1;
3383- pReconv->dwStrOffset = sizeof(RECONVERTSTRING);
3384- pReconv->dwCompStrLen = complen;
3385- pReconv->dwCompStrOffset = cx;
3386- pReconv->dwTargetStrLen = complen;
3387- pReconv->dwTargetStrOffset = cx;
3388-
3389- memcpy(pszParagraph, newbuf, newsize);
3390- //OutputDebugPrintf("cx %d buf [%d:%s] -> [%d:%s]\n", cx, size, buf, newsize, newbuf);
3303+ if (ts.UseIME > 0) {
3304+ switch(wParam) {
3305+ case IMR_DOCUMENTFEED:
3306+ return ReplyIMERequestDocumentfeed(lParam, NumOfColumns);
3307+ default:
3308+ break;
33913309 }
3392- return (sizeof(RECONVERTSTRING) + newsize);
33933310 }
3394-
33953311 return CFrameWnd::DefWindowProc(WM_IME_REQUEST,wParam,lParam);
33963312 }
33973313
--- trunk/teraterm/ttpcmn/ttcmn.c (revision 7483)
+++ trunk/teraterm/ttpcmn/ttcmn.c (revision 7484)
@@ -48,6 +48,7 @@
4848
4949 #include "compat_w95.h"
5050 #include "tt_res.h"
51+#include "ttcommon.h"
5152 #include "codeconv.h"
5253
5354 // TMap を格納するファイルマッピングオブジェクト(共有メモリ)の名前
@@ -1918,6 +1919,38 @@
19181919 return i;
19191920 }
19201921
1922+// TODO: UTF-16から直接変換して出力する
1923+int WINAPI CommTextOutW(PComVar cv, const wchar_t *B, int C)
1924+{
1925+ int CodePage = *cv->CodePage;
1926+ size_t mb_len;
1927+ int r;
1928+ char *mb_str = _WideCharToMultiByte(B, C, CodePage, &mb_len);
1929+ if (mb_str == NULL) {
1930+ r = 0;
1931+ } else {
1932+ r = CommTextOut(cv, mb_str, mb_len);
1933+ free(mb_str);
1934+ }
1935+ return r;
1936+}
1937+
1938+// TODO: UTF-16から直接変換して出力する
1939+int WINAPI CommTextEchoW(PComVar cv, const wchar_t *B, int C)
1940+{
1941+ int CodePage = *cv->CodePage;
1942+ size_t mb_len;
1943+ int r;
1944+ char *mb_str = _WideCharToMultiByte(B, C, CodePage, &mb_len);
1945+ if (mb_str == NULL) {
1946+ r = 0;
1947+ } else {
1948+ r = CommTextEcho(cv, mb_str, mb_len);
1949+ free(mb_str);
1950+ }
1951+ return r;
1952+}
1953+
19211954 int WINAPI CommBinaryEcho(PComVar cv, PCHAR B, int C)
19221955 {
19231956 int a, i, Len;
Show on old repository browser