• R/O
  • SSH
  • HTTPS

ttssh2: Commit


Commit MetaInfo

Revision9035 (tree)
Time2020-11-22 00:12:27
Authorzmatsuo

Log Message

64bitビルド時にttxsshのホスト名エディットボックスで CTRL+k の動作がおかしかったので修正

- 関数名 SetEditboxSubclass() を SetEditboxEmacsKeybind() に変更した
- C-b/C-f(カーソルを1文字前/後ろ)でサロゲートペアに対応
- エディットボックスかコンボボックスかを自動で判別するようにした
- ttxssh のログイン履歴を Unicode 対応とした

- teraterm.ini が Unicode で保存していあるとき有効

Change Summary

Incremental Difference

--- trunk/teraterm/common/dlglib.c (revision 9034)
+++ trunk/teraterm/common/dlglib.c (revision 9035)
@@ -40,6 +40,7 @@
4040 #endif
4141 #include <stdlib.h>
4242 #include <crtdbg.h>
43+#include <wchar.h>
4344 #include "ttlib.h" // for get_lang_font()
4445 #include "layer_for_unicode.h"
4546 #include "codeconv.h"
@@ -90,7 +91,7 @@
9091 }
9192 HControl = GetDlgItem(HDlg, FirstId + R - 1);
9293 SendMessage(HControl, BM_SETCHECK, 1, 0);
93- Style = GetClassLongPtr(HControl, GCL_STYLE);
94+ Style = (DWORD)GetClassLongPtr(HControl, GCL_STYLE);
9495 SetClassLongPtr(HControl, GCL_STYLE, Style | WS_TABSTOP);
9596 }
9697
@@ -232,24 +233,26 @@
232233 typedef struct {
233234 WNDPROC OrigProc; // Original window procedure
234235 LONG_PTR OrigUser; // DWLP_USER
235- BOOL ComboBox;
236+ BOOL IsComboBox;
236237 } EditSubclassData;
237238
238-// C-n/C-p のためにサブクラス化 (2007.9.4 maya)
239-// C-p/C-n/C-b/C-f/C-a/C-e をサポート (2007.9.5 maya)
240-// C-d/C-k をサポート (2007.10.3 yutaka)
241-// ドロップダウンの中のエディットコントロールを
242-// サブクラス化するためのウインドウプロシージャ
243-// TODO サロゲートペア文字の場合の処理
239+/**
240+ * サポートするキー
241+ * C-n/C-p コンボボックスのとき1つ上/下を選択
242+ * C-b/C-f カーソルを1文字前/後ろ
243+ * C-a/C-e カーソルを行頭/行末
244+ * C-d カーソル配下の1文字削除
245+ * C-k カーソルから行末まで削除
246+ * C-u カーソルより行頭まで削除
247+ */
244248 static LRESULT CALLBACK HostnameEditProc(HWND dlg, UINT msg,
245249 WPARAM wParam, LPARAM lParam)
246250 {
247251 EditSubclassData *data = (EditSubclassData *)GetWindowLongPtr(dlg, GWLP_USERDATA);
248252 LRESULT Result;
249- LRESULT select;
250- LRESULT max;
251- int len;
252- char *str, *orgstr;
253+ DWORD select;
254+ DWORD max;
255+ DWORD len;
253256
254257 switch (msg) {
255258 // キーが押されたのを検知する
@@ -257,64 +260,105 @@
257260 if (GetKeyState(VK_CONTROL) < 0) {
258261 switch (wParam) {
259262 case 0x50: // Ctrl+p ... up
260- if (data->ComboBox) {
263+ if (data->IsComboBox) {
261264 HWND parent = GetParent(dlg);
262- select = SendMessage(parent, CB_GETCURSEL, 0, 0);
263- if (select > 0) {
264- PostMessage(parent, CB_SETCURSEL, select - 1, 0);
265+ select = (DWORD)_SendMessageW(parent, CB_GETCURSEL, 0, 0);
266+ if (select == CB_ERR) {
267+ max = (DWORD)_SendMessageW(parent, CB_GETCOUNT, 0, 0);
268+ PostMessageW(parent, CB_SETCURSEL, max - 1, 0);
265269 }
270+ else if (select > 0) {
271+ PostMessageW(parent, CB_SETCURSEL, select - 1, 0);
272+ }
266273 return 0;
267274 }
268275 break;
269276 case 0x4e: // Ctrl+n ... down
270- if (data->ComboBox) {
277+ if (data->IsComboBox) {
271278 HWND parent = GetParent(dlg);
272- max = SendMessage(parent, CB_GETCOUNT, 0, 0);
273- select = SendMessage(parent, CB_GETCURSEL, 0, 0);
274- if (select < max - 1) {
275- PostMessage(parent, CB_SETCURSEL, select + 1, 0);
279+ max = (DWORD)_SendMessageW(parent, CB_GETCOUNT, 0, 0);
280+ select = (DWORD)_SendMessageW(parent, CB_GETCURSEL, 0, 0);
281+ if (select == CB_ERR) {
282+ PostMessageW(parent, CB_SETCURSEL, 0, 0);
283+ } else if (select < max - 1) {
284+ PostMessageW(parent, CB_SETCURSEL, select + 1, 0);
276285 }
277286 return 0;
278287 }
279288 break;
280- case 0x42: // Ctrl+b ... left
281- SendMessage(dlg, EM_GETSEL, 0, (LPARAM)&select);
282- PostMessage(dlg, EM_SETSEL, select-1, select-1);
289+ case 0x42: {
290+ // Ctrl+b ... left
291+ _SendMessageW(dlg, EM_GETSEL, 0, (LPARAM)&select);
292+ if (select > 0) {
293+ wchar_t *str;
294+ max = _GetWindowTextLengthW(dlg);
295+ max++; // '\0'
296+ str = (wchar_t *)malloc(sizeof(wchar_t) * max);
297+ if (str == NULL) {
298+ return 0;
299+ }
300+ _GetWindowTextW(dlg, str, (int)max);
301+ select = select - 1;
302+ if (IsLowSurrogate(str[select])) {
303+ select = select - 1;
304+ }
305+ PostMessageW(dlg, EM_SETSEL, select, select);
306+ free(str);
307+ }
283308 return 0;
284- case 0x46: // Ctrl+f ... right
285- SendMessage(dlg, EM_GETSEL, 0, (LPARAM)&select);
286- max = GetWindowTextLength(dlg) ;
287- PostMessage(dlg, EM_SETSEL, select+1, select+1);
309+ }
310+ case 0x46: {
311+ // Ctrl+f ... right
312+ _SendMessageW(dlg, EM_GETSEL, 0, (LPARAM)&select);
313+ max = _GetWindowTextLengthW(dlg);
314+ if (select < max) {
315+ wchar_t *str;
316+ max++; // '\0'
317+ str = (wchar_t *)malloc(sizeof(wchar_t) * max);
318+ if (str == NULL) {
319+ return 0;
320+ }
321+ _GetWindowTextW(dlg, str, (int)max);
322+ select = select + 1;
323+ if (IsLowSurrogate(str[select])) {
324+ select = select + 1;
325+ }
326+ PostMessageW(dlg, EM_SETSEL, select, select);
327+ free(str);
328+ }
288329 return 0;
330+ }
289331 case 0x41: // Ctrl+a ... home
290- PostMessage(dlg, EM_SETSEL, 0, 0);
332+ PostMessageW(dlg, EM_SETSEL, 0, 0);
291333 return 0;
292334 case 0x45: // Ctrl+e ... end
293- max = GetWindowTextLength(dlg) ;
294- PostMessage(dlg, EM_SETSEL, max, max);
335+ max = _GetWindowTextLengthW(dlg) ;
336+ PostMessageW(dlg, EM_SETSEL, max, max);
295337 return 0;
296338
297339 case 0x44: // Ctrl+d
298340 case 0x4b: // Ctrl+k
299- case 0x55: // Ctrl+u
300- SendMessage(dlg, EM_GETSEL, 0, (LPARAM)&select);
301- max = GetWindowTextLength(dlg);
341+ case 0x55: {
342+ // Ctrl+u
343+ wchar_t *str, *orgstr;
344+ _SendMessageW(dlg, EM_GETSEL, 0, (LPARAM)&select);
345+ max = _GetWindowTextLengthW(dlg);
302346 max++; // '\0'
303- orgstr = str = (char *)malloc(max);
347+ orgstr = str = (wchar_t *)malloc(sizeof(wchar_t) * max);
304348 if (str != NULL) {
305- len = GetWindowTextA(dlg, str, (int)max);
306- if (select >= 0 && select < len) {
307- if (wParam == 0x44) { // カーソル配下の文字のみを削除する
308- memmove(&str[select], &str[select + 1], len - select - 1);
349+ len = _GetWindowTextW(dlg, str, (int)max);
350+ if (select < len) {
351+ if (wParam == 0x44) { // Ctrl+d カーソル配下の文字のみを削除する
352+ wmemmove(&str[select], &str[select + 1], len - select - 1);
309353 str[len - 1] = '\0';
310354
311- } else if (wParam == 0x4b) { // カーソルから行末まで削除する
355+ } else if (wParam == 0x4b) { // Ctrl+k カーソルから行末まで削除する
312356 str[select] = '\0';
313357
314358 }
315359 }
316360
317- if (wParam == 0x55) { // カーソルより左側をすべて消す
361+ if (wParam == 0x55) { // Ctrl+uカーソルより左側をすべて消す
318362 if (select >= len) {
319363 str[0] = '\0';
320364 } else {
@@ -323,12 +367,15 @@
323367 select = 0;
324368 }
325369
326- SetWindowTextA(dlg, str);
327- SendMessage(dlg, EM_SETSEL, select, select);
370+ _SetWindowTextW(dlg, str);
371+ _SendMessageW(dlg, EM_SETSEL, select, select);
328372 free(orgstr);
329373 return 0;
330374 }
331375 break;
376+ }
377+ default:
378+ break;
332379 }
333380 }
334381 break;
@@ -374,19 +421,22 @@
374421 * C-n/C-p のためにサブクラス化
375422 * @praram hDlg ダイアログ
376423 * @praram nID emacs風にするエディットボックス または コンボボックス
377- * @param comboBox TRUE = nIDがコンボボックス
378424 */
379-void SetEditboxSubclass(HWND hDlg, int nID, BOOL ComboBox)
425+void SetEditboxEmacsKeybind(HWND hDlg, int nID)
380426 {
381427 EditSubclassData *data;
382428 HWND hWndEdit = GetDlgItem(hDlg, nID);
383- if (ComboBox) {
429+ BOOL IsCombobox = FALSE;
430+ char ClassName[32];
431+ GetClassNameA(hWndEdit, ClassName, _countof(ClassName));
432+ if (strcmp(ClassName, "ComboBox") == 0) {
384433 hWndEdit = GetWindow(hWndEdit, GW_CHILD);
434+ IsCombobox = TRUE;
385435 }
386436 data = (EditSubclassData *)malloc(sizeof(EditSubclassData));
387437 data->OrigProc = (WNDPROC)GetWindowLongPtrW(hWndEdit, GWLP_WNDPROC);
388438 data->OrigUser = (LONG_PTR)GetWindowLongPtr(hWndEdit, GWLP_USERDATA);
389- data->ComboBox = ComboBox;
439+ data->IsComboBox = IsCombobox;
390440 _SetWindowLongPtrW(hWndEdit, GWLP_WNDPROC, (LONG_PTR)HostnameEditProc);
391441 SetWindowLongPtr(hWndEdit, GWLP_USERDATA, (LONG_PTR)data);
392442 }
--- trunk/teraterm/common/dlglib.h (revision 9034)
+++ trunk/teraterm/common/dlglib.h (revision 9035)
@@ -49,7 +49,7 @@
4949 void SetDropDownListW(HWND HDlg, int Id_Item, const wchar_t *List[], int nsel);
5050 LONG GetCurSel(HWND HDlg, int Id_Item);
5151 void InitDlgProgress(HWND HDlg, int id_Progress, int *CurProgStat);
52-void SetEditboxSubclass(HWND hDlg, int nID, BOOL ComboBox);
52+void SetEditboxEmacsKeybind(HWND hDlg, int nID);
5353
5454 #if defined(_UNICODE)
5555 #define SetDropDownListT(p1, p2, p3, p4) SetDropDownListW(p1, p2, p3, p4)
--- trunk/teraterm/common/layer_for_unicode.cpp (revision 9034)
+++ trunk/teraterm/common/layer_for_unicode.cpp (revision 9035)
@@ -538,7 +538,7 @@
538538 if (pSetWindowLongPtrW != NULL) {
539539 return pSetWindowLongPtrW(hWnd, nIndex, dwNewLong);
540540 }
541- return SetWindowLongPtr(hWnd, nIndex, dwNewLong);
541+ return SetWindowLongPtrA(hWnd, nIndex, dwNewLong);
542542 #else
543543 return _SetWindowLongW(hWnd, nIndex, dwNewLong);
544544 #endif
--- trunk/teraterm/teraterm/dnddlg.cpp (revision 9034)
+++ trunk/teraterm/teraterm/dnddlg.cpp (revision 9035)
@@ -1,5 +1,5 @@
11 /*
2- * (C) 2005-2019 TeraTerm Project
2+ * (C) 2005-2020 TeraTerm Project
33 * All rights reserved.
44 *
55 * Redistribution and use in source and binary forms, with or without
@@ -111,7 +111,7 @@
111111 EnableWindow(GetDlgItem(hDlgWnd, IDC_SCP_PATH), FALSE);
112112 EnableWindow(GetDlgItem(hDlgWnd, IDC_SCP_PATH_NOTE), FALSE);
113113 }
114- SetEditboxSubclass(hDlgWnd, IDC_SCP_PATH, FALSE);
114+ SetEditboxEmacsKeybind(hDlgWnd, IDC_SCP_PATH);
115115
116116 // Send File
117117 if (Param->DropType == DROP_TYPE_SEND_FILE_BINARY) {
--- trunk/teraterm/ttpdlg/ttdlg.c (revision 9034)
+++ trunk/teraterm/ttpdlg/ttdlg.c (revision 9035)
@@ -1902,7 +1902,7 @@
19021902
19031903 SendDlgItemMessage(Dialog, IDC_HOSTNAME, CB_SETCURSEL,0,0);
19041904
1905- SetEditboxSubclass(Dialog, IDC_HOSTNAME, TRUE);
1905+ SetEditboxEmacsKeybind(Dialog, IDC_HOSTNAME);
19061906
19071907 SetRB(Dialog,GetHNRec->Telnet,IDC_HOSTTELNET,IDC_HOSTTELNET);
19081908 SendDlgItemMessage(Dialog, IDC_HOSTTCPPORT, EM_LIMITTEXT,5,0);
--- trunk/ttssh2/ttxssh/ttxssh.c (revision 9034)
+++ trunk/ttssh2/ttxssh/ttxssh.c (revision 9035)
@@ -1207,7 +1207,6 @@
12071207 static char *ProtocolFamilyList[] = { "AUTO", "IPv6", "IPv4", NULL };
12081208 PGetHNRec GetHNRec;
12091209 char EntName[128];
1210- char TempHost[HostNameMaxLength + 1];
12111210 WORD i, j, w;
12121211 WORD ComPortTable[MAXCOMPORT];
12131212 static char *ComPortDesc[MAXCOMPORT];
@@ -1235,26 +1234,30 @@
12351234 )
12361235 GetHNRec->PortType = IdTCPIP;
12371236
1238- strncpy_s(EntName, sizeof(EntName), "Host", _TRUNCATE);
1237+ {
1238+ wchar_t *SetupFnW = ToWcharA(GetHNRec->SetupFN);
1239+ i = 1;
1240+ do {
1241+ wchar_t EntNameW[128];
1242+ wchar_t TempHostW[HostNameMaxLength + 1];
1243+ _snwprintf_s(EntNameW, _countof(EntNameW), _TRUNCATE, L"host%d", i);
1244+ GetPrivateProfileStringW(L"Hosts", EntNameW, L"",
1245+ TempHostW, _countof(TempHostW),
1246+ SetupFnW);
1247+ if (TempHostW[0] != 0)
1248+ SendDlgItemMessageW(dlg, IDC_HOSTNAME, CB_ADDSTRING,
1249+ 0, (LPARAM) TempHostW);
1250+ i++;
1251+ } while (i <= MAXHOSTLIST);
1252+ free(SetupFnW);
1253+ }
12391254
1240- i = 1;
1241- do {
1242- _snprintf_s(&EntName[4], sizeof(EntName)-4, _TRUNCATE, "%d", i);
1243- GetPrivateProfileString("Hosts", EntName, "",
1244- TempHost, sizeof(TempHost),
1245- GetHNRec->SetupFN);
1246- if (strlen(TempHost) > 0)
1247- SendDlgItemMessage(dlg, IDC_HOSTNAME, CB_ADDSTRING,
1248- 0, (LPARAM) TempHost);
1249- i++;
1250- } while (i <= MAXHOSTLIST);
1251-
12521255 SendDlgItemMessage(dlg, IDC_HOSTNAME, EM_LIMITTEXT,
12531256 HostNameMaxLength - 1, 0);
12541257
12551258 SendDlgItemMessage(dlg, IDC_HOSTNAME, CB_SETCURSEL, 0, 0);
12561259
1257- SetEditboxSubclass(dlg, IDC_HOSTNAME, TRUE);
1260+ SetEditboxEmacsKeybind(dlg, IDC_HOSTNAME);
12581261
12591262 CheckRadioButton(dlg, IDC_HOSTTELNET, IDC_HOSTOTHER,
12601263 pvar->settings.Enabled ? IDC_HOSTSSH : GetHNRec->
Show on old repository browser