scmno****@osdn*****
scmno****@osdn*****
2018年 6月 11日 (月) 23:34:12 JST
Revision: 7130 http://sourceforge.jp/projects/ttssh2/scm/svn/commits/7130 Author: zmatsuo Date: 2018-06-11 23:34:12 +0900 (Mon, 11 Jun 2018) Log Message: ----------- drag and dropの改良 - ダイアログにファイル名ペーストなどを追加 - 複数ファイルのドロップに対応 Modified Paths: -------------- branches/drag_and_drop/teraterm/common/tt_res.h branches/drag_and_drop/teraterm/common/tttypes.h branches/drag_and_drop/teraterm/teraterm/ttermpro.rc branches/drag_and_drop/teraterm/teraterm/vtwin.cpp branches/drag_and_drop/teraterm/teraterm/vtwin.h -------------- next part -------------- Modified: branches/drag_and_drop/teraterm/common/tt_res.h =================================================================== --- branches/drag_and_drop/teraterm/common/tt_res.h 2018-06-11 14:22:14 UTC (rev 7129) +++ branches/drag_and_drop/teraterm/common/tt_res.h 2018-06-11 14:34:12 UTC (rev 7130) @@ -164,7 +164,6 @@ #define IDC_PROT_ELAPSED 2525 #define IDC_DAD_STATIC 2525 #define IDC_PROTOELAPSEDTIME 2526 -#define IDC_DAD_SENDFILE 2526 #define IDC_TRANS_ELAPSED 2527 #define IDC_BGIMG_LABEL 2527 #define IDC_TRANS_ETIME 2528 @@ -218,7 +217,16 @@ #define IDC_NORMALIZE_LINEBREAK 2565 #define IDC_CLIPBOARD_NOTIFY 2566 #define IDC_LIST_HIDDEN_FONTS 2567 - +#define IDC_BINARY_CHECK 2568 +#define IDC_ADAPT_SAME_CHECK 2569 +#define IDC_FILENAME_EDIT 2570 +#define IDC_SCP_RADIO 2571 +#define IDC_SENDFILE_RADIO 2572 +#define IDC_PASTE_RADIO 2573 +#define IDC_ESCAPE_CHECK 2574 +#define IDC_DEFAULT_CHECK 2575 +#define IDC_SCP_PATH_LABEL 2576 +#define IDC_SCP_PATH_NOTE 2577 #define ID_ACC_SENDBREAK 50001 #define ID_ACC_COPY 50002 #define ID_ACC_NEWCONNECTION 50003 @@ -316,7 +324,7 @@ #define _APS_NO_MFC 1 #define _APS_NEXT_RESOURCE_VALUE 126 #define _APS_NEXT_COMMAND_VALUE 52031 -#define _APS_NEXT_CONTROL_VALUE 2568 +#define _APS_NEXT_CONTROL_VALUE 2578 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif Modified: branches/drag_and_drop/teraterm/common/tttypes.h =================================================================== --- branches/drag_and_drop/teraterm/common/tttypes.h 2018-06-11 14:22:14 UTC (rev 7129) +++ branches/drag_and_drop/teraterm/common/tttypes.h 2018-06-11 14:34:12 UTC (rev 7130) @@ -1,6 +1,6 @@ /* * Copyright (C) 1994-1998 T. Teranishi - * (C) 2004-2017 TeraTerm Project + * (C) 2004-2018 TeraTerm Project * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -173,6 +173,7 @@ #define WM_USER_GETSERIALNO WM_USER+13 #define WM_USER_CHANGETITLE WM_USER+14 #define WM_USER_NOTIFYICON WM_USER+15 +#define WM_USER_DROPNOTIFY WM_USER+16 #define WM_USER_DDEREADY WM_USER+21 #define WM_USER_DDECMNDEND WM_USER+22 Modified: branches/drag_and_drop/teraterm/teraterm/ttermpro.rc =================================================================== --- branches/drag_and_drop/teraterm/teraterm/ttermpro.rc 2018-06-11 14:22:14 UTC (rev 7129) +++ branches/drag_and_drop/teraterm/teraterm/ttermpro.rc 2018-06-11 14:34:12 UTC (rev 7130) @@ -26,17 +26,28 @@ // Dialog // -IDD_DAD_DIALOG DIALOGEX 0, 0, 186, 74 +IDD_DAD_DIALOG DIALOGEX 0, 0, 187, 207 STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Tera Term: File Drag and Drop" FONT 8, "Tahoma", 400, 0, 0x0 BEGIN - LTEXT "Are you sure that you want to send the file content?",IDC_DAD_STATIC,7,9,172,8 - LTEXT "SCP:",IDC_STATIC,15,27,16,8 - EDITTEXT IDC_SCP_PATH,31,25,122,14,ES_AUTOHSCROLL - PUSHBUTTON "Send file",IDOK,7,45,50,14 - DEFPUSHBUTTON "SCP",IDC_DAD_SENDFILE,69,45,50,14 - PUSHBUTTON "Cancel",IDCANCEL,129,45,50,14 + EDITTEXT IDC_FILENAME_EDIT,7,6,172,14,ES_AUTOHSCROLL | ES_READONLY | NOT WS_TABSTOP + LTEXT "Are you sure that you want to send the file content?",IDC_DAD_STATIC,7,25,173,8 + CONTROL "&SCP",IDC_SCP_RADIO,"Button",BS_AUTORADIOBUTTON | BS_NOTIFY,7,36,29,10 + CONTROL "S&end File (Paste content of file)",IDC_SENDFILE_RADIO, + "Button",BS_AUTORADIOBUTTON | BS_NOTIFY,7,77,172,10 + CONTROL "&Paste Filename",IDC_PASTE_RADIO,"Button",BS_AUTORADIOBUTTON | BS_NOTIFY,7,109,172,10 + LTEXT "SCP des&t:",IDC_SCP_PATH_LABEL,19,50,36,8 + EDITTEXT IDC_SCP_PATH,57,47,122,14,ES_AUTOHSCROLL + LTEXT "dest is home directory if empty",IDC_SCP_PATH_NOTE,50,64,120,8 + CONTROL "Bina&ry",IDC_BINARY_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,19,92,151,10 + CONTROL "Es&cape",IDC_ESCAPE_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,19,125,151,10 + CONTROL "&Adapt same process to remaing %d files",IDC_ADAPT_SAME_CHECK, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,144,172,10 + CONTROL "&Default process from next drop\n(Drop with CTRL, this dialog is dispalyed)",IDC_DEFAULT_CHECK, + "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,7,160,172,18 + DEFPUSHBUTTON "OK",IDOK,69,185,50,14 + PUSHBUTTON "Cancel",IDCANCEL,130,185,50,14 END IDD_COMMENT_DIALOG DIALOGEX 0, 0, 239, 19 Modified: branches/drag_and_drop/teraterm/teraterm/vtwin.cpp =================================================================== --- branches/drag_and_drop/teraterm/teraterm/vtwin.cpp 2018-06-11 14:22:14 UTC (rev 7129) +++ branches/drag_and_drop/teraterm/teraterm/vtwin.cpp 2018-06-11 14:34:12 UTC (rev 7130) @@ -1,6 +1,6 @@ /* * Copyright (C) 1994-1998 T. Teranishi - * (C) 2004-2017 TeraTerm Project + * (C) 2004-2018 TeraTerm Project * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -254,6 +254,7 @@ ON_COMMAND(ID_WINDOW_UNDO, OnWindowUndo) ON_COMMAND(ID_HELP_INDEX2, OnHelpIndex) ON_COMMAND(ID_HELP_ABOUT, OnHelpAbout) + ON_MESSAGE(WM_USER_DROPNOTIFY, OnDropNotify) //}}AFX_MSG_MAP END_MESSAGE_MAP() @@ -918,6 +919,9 @@ // Tera Term\x82̋N\x93\xAE\x8E\x9E\x81AVirtual Store\x82\xAA\x93\xAD\x82\xAD\x82\xA9\x82ǂ\xA4\x82\xA9\x82\xF0\x8Ao\x82\xA6\x82Ă\xA8\x82\xAD\x81B // (2015.11.14 yutaka) cv.VirtualStoreEnabled = GetVirtualStoreEnvironment(); + + DropLists = NULL; + DropListCount = 0; } ///////////////////////////////////////////////////////////////////////////// @@ -1986,6 +1990,7 @@ /* Disable drag-drop */ ::DragAcceptFiles(HVTWin,FALSE); + DropListFree(); EndDDE(); @@ -2019,57 +2024,135 @@ DeleteNotifyIcon(&cv); } +static void SetDlgFonts(HWND hDlg, const int nIDDlgItems[], int nIDDlgItemCount, HFONT hFont) +{ + for (int i = 0 ; i < nIDDlgItemCount ; i++) { + const int nIDDlgItem = nIDDlgItems[i]; + SendDlgItemMessage(hDlg, nIDDlgItem, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE,0)); + } +} + +enum drop_type { + DROP_TYPE_CANCEL, + DROP_TYPE_SCP, + DROP_TYPE_SEND_FILE, // past contents of file + DROP_TYPE_SEND_FILE_BINARY, + DROP_TYPE_PASTE_FILENAME, + DROP_TYPE_PASTE_FILENAME_WITH_ESCAPE, +}; + +struct DrapDropDlgParam { + const char *TargetFilename; + enum drop_type DropType; + bool ScpEnable; + char *ScpSendDirPtr; + int ScpSendDirSize; + bool SendfileEnable; + int RemaingFileCount; + bool AdaptSameProcess; + bool DefaultProcess; +}; + +struct DrapDropDlgData { + HFONT DlgDragDropFont; + struct DrapDropDlgParam *Param; +}; + static LRESULT CALLBACK OnDragDropDlgProc(HWND hDlgWnd, UINT msg, WPARAM wp, LPARAM lp) { - static HFONT DlgDragDropFont = NULL; - char uimsg[MAX_UIMSG]; - LOGFONT logfont; - HFONT font; + struct DrapDropDlgData *DlgData = (struct DrapDropDlgData *)GetWindowLongPtr(hDlgWnd, GWLP_USERDATA); switch (msg) { case WM_INITDIALOG: + { + char uimsg[MAX_UIMSG]; + LOGFONT logfont; + HFONT font; + HFONT DlgDragDropFont = NULL; + DlgData = (struct DrapDropDlgData *)malloc(sizeof(struct DrapDropDlgData)); + SetWindowLongPtr(hDlgWnd, GWLP_USERDATA, (LONG_PTR)DlgData); + struct DrapDropDlgParam *Param = (struct DrapDropDlgParam *)lp; + DlgData->Param = Param; font = (HFONT)SendMessage(hDlgWnd, WM_GETFONT, 0, 0); GetObject(font, sizeof(LOGFONT), &logfont); if (get_lang_font("DLG_TAHOMA_FONT", hDlgWnd, &logfont, &DlgDragDropFont, ts.UILanguageFile)) { - SendDlgItemMessage(hDlgWnd, IDC_SCP_PATH, WM_SETFONT, (WPARAM)DlgDragDropFont, MAKELPARAM(TRUE,0)); - SendDlgItemMessage(hDlgWnd, IDOK, WM_SETFONT, (WPARAM)DlgDragDropFont, MAKELPARAM(TRUE,0)); - SendDlgItemMessage(hDlgWnd, IDCANCEL, WM_SETFONT, (WPARAM)DlgDragDropFont, MAKELPARAM(TRUE,0)); - SendDlgItemMessage(hDlgWnd, IDC_DAD_STATIC, WM_SETFONT, (WPARAM)DlgDragDropFont, MAKELPARAM(TRUE,0)); - SendDlgItemMessage(hDlgWnd, IDC_DAD_SENDFILE, WM_SETFONT, (WPARAM)DlgDragDropFont, MAKELPARAM(TRUE,0)); + const static int IDs[] = { + IDC_FILENAME_EDIT, + IDC_DAD_STATIC, + IDC_SCP_RADIO, IDC_SENDFILE_RADIO, IDC_PASTE_RADIO, + IDC_SCP_PATH_LABEL, IDC_SCP_PATH, IDC_SCP_PATH_NOTE, + IDC_BINARY_CHECK, IDC_ESCAPE_CHECK, + IDC_ADAPT_SAME_CHECK, IDC_DEFAULT_CHECK, + IDOK, IDCANCEL, + }; + SetDlgFonts(hDlgWnd, IDs, _countof(IDs), DlgDragDropFont); } else { DlgDragDropFont = NULL; } + DlgData->DlgDragDropFont = DlgDragDropFont; GetWindowText(hDlgWnd, uimsg, sizeof(uimsg)); get_lang_msg("MSG_DANDD_CONF_TITLE", ts.UIMsg, sizeof(ts.UIMsg), uimsg, ts.UILanguageFile); SetWindowText(hDlgWnd, ts.UIMsg); + SetDlgItemText(hDlgWnd, IDC_FILENAME_EDIT, Param->TargetFilename); + get_lang_msg("MSG_DANDD_CONF", ts.UIMsg, sizeof(ts.UIMsg), "Are you sure that you want to send the file content?", ts.UILanguageFile); SetDlgItemText(hDlgWnd, IDC_DAD_STATIC, ts.UIMsg); + + // checkbox + CheckRadioButton(hDlgWnd, IDC_SCP_RADIO, IDC_PASTE_RADIO, + (Param->DropType == DROP_TYPE_SEND_FILE || + Param->DropType == DROP_TYPE_SEND_FILE_BINARY) ? IDC_SENDFILE_RADIO : + (Param->DropType == DROP_TYPE_PASTE_FILENAME || + Param->DropType == DROP_TYPE_PASTE_FILENAME_WITH_ESCAPE) ? IDC_PASTE_RADIO : + IDC_SCP_RADIO); - get_lang_msg("FILEDLG_TRANS_TITLE_SENDFILE", ts.UIMsg, sizeof(ts.UIMsg), - "Send file", ts.UILanguageFile); - SetDlgItemText(hDlgWnd, IDOK, ts.UIMsg); + // SCP + SendMessage(GetDlgItem(hDlgWnd, IDC_SCP_PATH), WM_SETTEXT, 0, (LPARAM)Param->ScpSendDirPtr); + if (!Param->ScpEnable) { + // \x96\xB3\x8C\xF8\x89\xBB + EnableWindow(GetDlgItem(hDlgWnd, IDC_SCP_RADIO), FALSE); + EnableWindow(GetDlgItem(hDlgWnd, IDC_SCP_PATH_LABEL), FALSE); + EnableWindow(GetDlgItem(hDlgWnd, IDC_SCP_PATH), FALSE); + EnableWindow(GetDlgItem(hDlgWnd, IDC_SCP_PATH_NOTE), FALSE); + } - SendMessage(GetDlgItem(hDlgWnd, IDC_SCP_PATH), WM_SETTEXT, 0, (LPARAM)ts.ScpSendDir); + // Send File + if (Param->DropType == DROP_TYPE_SEND_FILE_BINARY) { + SendMessage(GetDlgItem(hDlgWnd, IDC_BINARY_CHECK), BM_SETCHECK, BST_CHECKED, 0); + } + if (!Param->SendfileEnable) { + // \x96\xB3\x8C\xF8\x89\xBB + EnableWindow(GetDlgItem(hDlgWnd, IDC_SENDFILE_RADIO), FALSE); + EnableWindow(GetDlgItem(hDlgWnd, IDC_BINARY_CHECK), FALSE); + } - // SSH2 \x90ڑ\xB1\x82ł͂Ȃ\xA2\x8Fꍇ\x82ɂ\xCD "SCP" \x82\x{27B0B7}\x82\xE9\x81B - if (cv.isSSH != 2) { - EnableWindow(GetDlgItem(hDlgWnd, IDC_DAD_SENDFILE), FALSE); - EnableWindow(GetDlgItem(hDlgWnd, IDC_SCP_PATH), FALSE); - EnableWindow(GetDlgItem(hDlgWnd, IDC_STATIC), FALSE); + // Paste Filename + if (Param->DropType != DROP_TYPE_PASTE_FILENAME) { + SendMessage(GetDlgItem(hDlgWnd, IDC_ESCAPE_CHECK), BM_SETCHECK, BST_CHECKED, 0); + } - // \x83t\x83H\x81[\x83J\x83X\x82̏\x89\x8A\xFA\x8F\xF3\x91Ԃ\xF0 Cancel \x82ɂ\xB7\x82\xE9\x88ׁA\x82\xB1\x82̎\x9E\x93_\x82ł\xCD Send File (IDOK)\x82\xC9 + // Adapt same process + GetDlgItemText(hDlgWnd, IDC_ADAPT_SAME_CHECK, uimsg, sizeof(uimsg)); + char b[MAX_UIMSG]; + _snprintf_s(b, sizeof(b), _TRUNCATE, uimsg, Param->RemaingFileCount); + SetDlgItemText(hDlgWnd, IDC_ADAPT_SAME_CHECK, b); + if (Param->RemaingFileCount < 2) { + EnableWindow(GetDlgItem(hDlgWnd, IDC_ADAPT_SAME_CHECK), FALSE); + } + + // focus to "SCP dest textbox" or "Cancel" + if (Param->ScpEnable) { + // "SCP" \x97L\x8C\xF8\x8E\x9E\x82\xCD Cancel \x82Ƀt\x83H\x81[\x83J\x83X\x82āA\x8DŏI\x93I\x82\xC9 SCP PATH \x82Ƀt\x83H\x81[\x83J\x83X\x82\xAA + // \x93\x96\x82\xBD\x82\xE9\x82悤\x82ɂ\xB7\x82\xE9\x81B + SetFocus(GetDlgItem(hDlgWnd, IDC_SCP_RADIO)); + } else { + // \x83t\x83H\x81[\x83J\x83X\x82̏\x89\x8A\xFA\x8F\xF3\x91Ԃ\xF0 Cancel \x82ɂ\xB7\x82\xE9\x88ׁA\x82\xB1\x82̎\x9E\x93_\x82ł\xCD IDOK \x82\xC9 // \x83t\x83H\x81[\x83J\x83X\x82Ă\xE9\x81B\x8C\xE3\x82\xC5 WM_NEXTDLGCTL \x82Ńt\x83H\x81[\x83J\x83X\x82\xAA\x8E\x9F\x82̃{\x83^\x83\x93\x82ɂȂ\xE9\x81B SetFocus(GetDlgItem(hDlgWnd, IDOK)); } - else { - // SSH2 \x90ڑ\xB1\x8E\x9E\x82\xCD Cancel \x82Ƀt\x83H\x81[\x83J\x83X\x82āA\x8DŏI\x93I\x82\xC9 SCP PATH \x82Ƀt\x83H\x81[\x83J\x83X\x82\xAA - // \x93\x96\x82\xBD\x82\xE9\x82悤\x82ɂ\xB7\x82\xE9\x81B - SetFocus(GetDlgItem(hDlgWnd, IDCANCEL)); - } - // \x83t\x83H\x81[\x83J\x83X\x82\xF0\x8E\x9F\x82̃{\x83^\x83\x93\x82Ɉڂ\xB7 // SetFocus() \x82Œ\xBC\x90ڃt\x83H\x81[\x83J\x83X\x82Ă\xE9\x82ƃ^\x83u\x83L\x81[\x82̓\xAE\x8D쓙\x82ɖ\xE2\x91肪\x8Fo\x82邽\x82߁A // \x82\xB1\x82̃\x81\x83b\x83Z\x81[\x83W\x82p\x82\xB7\x82\xE9 @@ -2077,34 +2160,55 @@ // TRUE\x82ɂ\xB7\x82\xE9\x82ƃ{\x83^\x83\x93\x82Ƀt\x83H\x81[\x83J\x83X\x82\xAA\x93\x96\x82\xBD\x82\xE7\x82Ȃ\xA2\x81B return FALSE; + } case WM_COMMAND: - switch (LOWORD(wp)) { - case IDC_DAD_SENDFILE: - SendMessage(GetDlgItem(hDlgWnd, IDC_SCP_PATH), WM_GETTEXT, sizeof(ts.ScpSendDir), (LPARAM)ts.ScpSendDir); - if (DlgDragDropFont != NULL) { - DeleteObject(DlgDragDropFont); - } - EndDialog(hDlgWnd, IDC_DAD_SENDFILE); - break; - - case IDOK: - if (DlgDragDropFont != NULL) { - DeleteObject(DlgDragDropFont); - } - EndDialog(hDlgWnd, IDOK); - break; - - case IDCANCEL: - if (DlgDragDropFont != NULL) { - DeleteObject(DlgDragDropFont); - } - EndDialog(hDlgWnd, IDCANCEL); - break; - - default: - return FALSE; + { + WORD wID = GET_WM_COMMAND_ID(wp, lp); + const WORD wCMD = GET_WM_COMMAND_CMD(wp, lp); + if (wCMD == BN_DBLCLK && + (wID == IDC_SCP_RADIO || wID == IDC_SENDFILE_RADIO || wID == IDC_PASTE_RADIO)) + { // radio buttons double click + wID = IDOK; } + if (wID == IDOK) { + if (IsDlgButtonChecked(hDlgWnd, IDC_SCP_RADIO) == BST_CHECKED) { + // SCP + DlgData->Param->DropType = DROP_TYPE_SCP; + SendMessage(GetDlgItem(hDlgWnd, IDC_SCP_PATH), WM_GETTEXT, + (WPARAM)DlgData->Param->ScpSendDirSize, + (LPARAM)DlgData->Param->ScpSendDirPtr); + } else if (IsDlgButtonChecked(hDlgWnd, IDC_SENDFILE_RADIO) == BST_CHECKED) { + // Send File + DlgData->Param->DropType = + (IsDlgButtonChecked(hDlgWnd, IDC_BINARY_CHECK) == BST_CHECKED) ? + DROP_TYPE_SEND_FILE_BINARY : DROP_TYPE_SEND_FILE; + } else /* if (IsDlgButtonChecked(hDlgWnd, IDC_PASTE_RADIO) == BST_CHECKED) */ { + // Paste Filename + DlgData->Param->DropType = + (IsDlgButtonChecked(hDlgWnd, IDC_ESCAPE_CHECK) == BST_CHECKED) ? + DROP_TYPE_PASTE_FILENAME_WITH_ESCAPE : DROP_TYPE_PASTE_FILENAME; + } + DlgData->Param->AdaptSameProcess = + (IsDlgButtonChecked(hDlgWnd, IDC_ADAPT_SAME_CHECK) == BST_CHECKED) ? + true : false; + DlgData->Param->DefaultProcess = + (IsDlgButtonChecked(hDlgWnd, IDC_DEFAULT_CHECK) == BST_CHECKED) ? + true : false; + } + if (wID == IDCANCEL) { + DlgData->Param->DropType = DROP_TYPE_CANCEL; + } + if (wID == IDOK || wID == IDCANCEL) { + if (DlgData->DlgDragDropFont != NULL) { + DeleteObject(DlgData->DlgDragDropFont); + } + EndDialog(hDlgWnd, wID); + free(DlgData); + break; + } + return FALSE; + } default: return FALSE; @@ -2112,118 +2216,312 @@ return TRUE; } -void CVTWindow::OnDropFiles(HDROP hDropInfo) +static enum drop_type ShowDropDialogBox( + HINSTANCE hInstance, HWND hWndParent, + const char *TargetFilename, + enum drop_type DefaultDropType, + int RemaingFileCount, + bool EnableSCP, + bool EnableSendFile, + bool *AdaptSameProcess, + bool *DefaultProcess) { - ::SetForegroundWindow(HVTWin); - if (cv.Ready && (SendVar==NULL) && NewFileVar(&SendVar)) - { - if (DragQueryFile(hDropInfo,0,SendVar->FullName, - sizeof(SendVar->FullName))>0) - { - DWORD attr; - char *ptr, *q; - char tmpbuf[_MAX_PATH * 2]; + struct DrapDropDlgParam Param; + Param.TargetFilename = TargetFilename; + Param.DropType = DefaultDropType; + Param.ScpEnable = EnableSCP; + Param.ScpSendDirPtr = ts.ScpSendDir; + Param.ScpSendDirSize = sizeof(ts.ScpSendDir); + Param.SendfileEnable = EnableSendFile; + Param.RemaingFileCount = RemaingFileCount; + int ret = DialogBoxParam( + hInstance, MAKEINTRESOURCE(IDD_DAD_DIALOG), + hWndParent, (DLGPROC)OnDragDropDlgProc, + (LPARAM)&Param); + if (ret != IDOK) { + return DROP_TYPE_CANCEL; + } + *AdaptSameProcess = Param.AdaptSameProcess; + *DefaultProcess = Param.DefaultProcess; + return Param.DropType; +} - // \x83f\x83B\x83\x8C\x83N\x83g\x83\x8A\x82̏ꍇ\x82̓t\x83\x8B\x83p\x83X\x96\xBC\x82\xF0\x93\\x82\xE8\x95t\x82\xAF\x82\xE9 (2004.11.3 yutaka) - attr = GetFileAttributes(SendVar->FullName); - if (attr != -1 && (attr & FILE_ATTRIBUTE_DIRECTORY)) { - ptr = SendVar->FullName; - // \x83p\x83X\x82̋\xE6\x90\xE8\x82\xF0 \ -> / \x82\xD6 - setlocale(LC_ALL, ts.Locale); - while (*ptr) { - if (isleadbyte(*ptr)) { // multi-byte - ptr += 2; - continue; - } - if (*ptr == '\\') - *ptr = '/'; - ptr++; - } +static void EscapeFilename(const char *src, char *dest) +{ +#define ESCAPE_CHARS " ;&()$!`'[]{}#^~" + setlocale(LC_ALL, ts.Locale); + const char *s = src; + char *d = dest; + while (*s) { + if (isleadbyte(*s)) { // multi-byte + *d++ = *s++; + *d++ = *s++; + continue; + } + char c = *s++; + if (c == '\\') { + // \x83p\x83X\x82̋\xE6\x90\xE8\x82\xF0 \ -> / \x82\xD6 + *d = '/'; + } else if (strchr(ESCAPE_CHARS, c) != NULL) { + // \x83G\x83X\x83P\x81[\x83v\x82\xAA\x95K\x97v\x82ȕ\xB6\x8E\x9A + *d++ = '\\'; + *d = c; + } else { + *d = c; + } + d++; + } + *d = '\0'; // null-terminate +} - // \x83p\x83X\x82ɋ\xAA\x82\xA0\x82\xEA\x82G\x83X\x83P\x81[\x83v\x82\xB7\x82\xE9 - q = tmpbuf; - ptr = SendVar->FullName; - while (*ptr) { - if (*ptr == ' ') - *q++ = '\\'; - *q++ = *ptr; - ptr++; - } - *q = '\0'; // null-terminate +static void PasteString(PComVar cv, const char *str, bool escape) +{ + PCHAR ptr = (PCHAR)str; + char *tmpbuf = NULL; + if (escape) { + size_t len = strlen(str) * 2; + tmpbuf = (char *)malloc(len); + EscapeFilename(str, tmpbuf); + ptr = tmpbuf; + } - ptr = tmpbuf; + // console\x82֑\x97\x90M + while (*ptr) { + CommTextOut(cv, ptr, 1); + if (ts.LocalEcho > 0) { + CommTextEcho(cv, ptr, 1); + } + ptr++; + } - // console\x82֑\x97\x90M - while (*ptr) { - CommTextOut(&cv, ptr, 1); - if (ts.LocalEcho > 0) { - CommTextEcho(&cv, ptr, 1); - } - ptr++; - } - FreeFileVar(&SendVar); // \x89\xF0\x95\xFA\x82\xF0\x96Y\x82ꂸ\x82\xC9 + if (tmpbuf != NULL) free(tmpbuf); +} - } else { - // Confirm send a file when drag and drop (2007.12.28 maya) - if (ts.ConfirmFileDragAndDrop) { - // \x82\xA2\x82\xAB\x82Ȃ\xE8\x83t\x83@\x83C\x83\x8B\x82̓\xE0\x97e\x82𑗂荞\x82ޑO\x82ɁA\x83\x86\x81[\x83U\x82ɖ₢\x8D\x87\x82킹\x82\xF0\x8Ds\x82\xA4\x81B(2006.1.21 yutaka) - // MessageBox\x82\xC5SCP\x82\xE0\x91I\x91\xF0\x82ł\xAB\x82\xE9\x82悤\x82ɂ\xB7\x82\xE9\x81B(2008.1.25 yutaka) - // SCP\x83p\x83X\x82\xF0\x8Ew\x92\xE8\x82ł\xAB\x82\xE9\x82悤\x82Ƀ_\x83C\x83A\x83\x8D\x83O\x82ɕύX\x82\xB5\x82\xBD\x81B(2012.4.11 yutaka) - int ret; +/* \x93\xFC\x97͂̓t\x83@\x83C\x83\x8B\x82̂\xDD(\x83t\x83H\x83\x8B\x83_\x82͊܂܂\xEA\x82Ȃ\xA2) */ +static bool SendScp(char *Filenames[], int FileCount, const char *SendDir) +{ + typedef int (CALLBACK *PSSH_start_scp)(char *, char *); + static PSSH_start_scp func = NULL; + static HMODULE h = NULL; + char msg[128]; - ret = DialogBox(hInst, MAKEINTRESOURCE(IDD_DAD_DIALOG), - HVTWin, (DLGPROC)OnDragDropDlgProc); + if (h == NULL) { + if ( ((h = GetModuleHandle("ttxssh.dll")) == NULL) ) { + _snprintf_s(msg, sizeof(msg), _TRUNCATE, "GetModuleHandle(\"ttxssh.dll\")) %d", GetLastError()); + scp_send_error: + ::MessageBox(NULL, msg, "Tera Term: scpsend command error", MB_OK | MB_ICONERROR); + return false; + } + } + if (func == NULL) { + func = (PSSH_start_scp)GetProcAddress(h, "TTXScpSendfile"); + if (func == NULL) { + _snprintf_s(msg, sizeof(msg), _TRUNCATE, "GetProcAddress(\"TTXScpSendfile\")) %d", GetLastError()); + goto scp_send_error; + } + } - if (ret == IDOK) { // sendfile - HelpId = HlpFileSend; - SendVar->DirLen = 0; - ts.TransBin = 0; - FileSendStart(); + for (int i = 0; i < FileCount; i++) { + const char *FileName = Filenames[i]; + func((char *)FileName, ts.ScpSendDir); + } + return true; +} - } else if (ret == IDC_DAD_SENDFILE) { // SCP - typedef int (CALLBACK *PSSH_start_scp)(char *, char *); - static PSSH_start_scp func = NULL; - static HMODULE h = NULL; - char msg[128]; +void CVTWindow::DropListFree() +{ + if (DropListCount > 0) { + for (int i = 0; i < DropListCount; i++) { + free(DropLists[i]); + DropLists[i] = NULL; + } + free(DropLists); + DropLists = NULL; + DropListCount = 0; + } +} - if (func == NULL) { - if ( ((h = GetModuleHandle("ttxssh.dll")) == NULL) ) { - _snprintf_s(msg, sizeof(msg), _TRUNCATE, "GetModuleHandle(\"ttxssh.dll\")) %d", GetLastError()); - goto scp_send_error; - } - func = (PSSH_start_scp)GetProcAddress(h, "TTXScpSendfile"); - if (func == NULL) { - _snprintf_s(msg, sizeof(msg), _TRUNCATE, "GetProcAddress(\"TTXScpSendfile\")) %d", GetLastError()); - goto scp_send_error; - } - } +LONG CVTWindow::OnDropNotify(UINT ShowDialog, LONG lParam) +{ + static enum drop_type DefaultDropType = DROP_TYPE_CANCEL; - if (func != NULL) { - func(SendVar->FullName, ts.ScpSendDir); - goto send_success; - } + (void)lParam; + int FileCount = 0; + int DirectoryCount = 0; + for (int i = 0; i < DropListCount; i++) { + const char *FileName = DropLists[i]; + const DWORD attr = GetFileAttributes(FileName); + if (attr == -1 ) { + goto finish; + } + if (attr & FILE_ATTRIBUTE_DIRECTORY) { + DirectoryCount++; + } else { + FileCount++; + } + } -scp_send_error: - ::MessageBox(NULL, msg, "Tera Term: scpsend command error", MB_OK | MB_ICONERROR); -send_success: - FreeFileVar(&SendVar); // \x89\xF0\x95\xFA\x82\xF0\x96Y\x82ꂸ\x82\xC9 - + bool AdapatSameProcess = false; + const bool isSSH = (cv.isSSH == 2); + enum drop_type DropType; + if (DefaultDropType == DROP_TYPE_CANCEL) { + // default is not set + if (!ShowDialog) { + if (FileCount == 1 && DirectoryCount == 0) { + if (ts.ConfirmFileDragAndDrop) { + if (isSSH) { + DropType = DROP_TYPE_SCP; } else { - FreeFileVar(&SendVar); - + DropType = DROP_TYPE_SEND_FILE; } + AdapatSameProcess = false; + } else { + DropType = DROP_TYPE_SEND_FILE; + AdapatSameProcess = true; } - else { - SendVar->DirLen = 0; - ts.TransBin = 0; - FileSendStart(); + } else if (FileCount == 0 && DirectoryCount == 1) { + DropType = DROP_TYPE_PASTE_FILENAME_WITH_ESCAPE; + AdapatSameProcess = true; + } else if (FileCount > 0 && DirectoryCount > 0) { + DropType = DROP_TYPE_PASTE_FILENAME_WITH_ESCAPE; + AdapatSameProcess = false; + } else if (FileCount > 0 && DirectoryCount == 0) { + // filename only + if (isSSH) { + DropType = DROP_TYPE_SCP; + } else { + DropType = DROP_TYPE_SEND_FILE; + } + AdapatSameProcess = false; + } else { + // directory only + DropType = DROP_TYPE_PASTE_FILENAME_WITH_ESCAPE; + AdapatSameProcess = ts.ConfirmFileDragAndDrop ? false : true; + } + } else { + // show dialog + if (DirectoryCount > 0) { + DropType = DROP_TYPE_PASTE_FILENAME_WITH_ESCAPE; + } else { + if (isSSH) { + DropType = DROP_TYPE_SCP; + } else { + DropType = DROP_TYPE_SEND_FILE; + } + } + AdapatSameProcess = false; + } + } else { + if (DirectoryCount > 0 && + (DefaultDropType == DROP_TYPE_SEND_FILE || + DefaultDropType == DROP_TYPE_SEND_FILE_BINARY || + DefaultDropType == DROP_TYPE_SCP)) + { // \x83f\x83t\x83H\x83\x8B\x83g\x82̂܂܂ł͏\x88\x97\x9D\x82ł\xAB\x82Ȃ\xA2\x91g\x82ݍ\x87\x82킹 + DropType = DROP_TYPE_PASTE_FILENAME_WITH_ESCAPE; + AdapatSameProcess = false; + } else { + DropType = DefaultDropType; + AdapatSameProcess = ShowDialog ? false : true; + } + } + for (int i = 0; i < DropListCount; i++) { + const char *FileName = DropLists[i]; + + if (!AdapatSameProcess) { + bool DefaultProcess; + DropType = + ShowDropDialogBox(hInst, HVTWin, + FileName, DropType, + DropListCount - i, + (DirectoryCount == 0 && isSSH) ? true : false, + DirectoryCount == 0 ? true : false, + &AdapatSameProcess, &DefaultProcess); + if (DropType == DROP_TYPE_CANCEL) { + goto finish; + } + if (DefaultProcess) { + DefaultDropType = DropType; + } + } + + switch (DropType) { + case DROP_TYPE_CANCEL: + default: + // cancel + break; + case DROP_TYPE_SEND_FILE: + case DROP_TYPE_SEND_FILE_BINARY: + if (SendVar==NULL && NewFileVar(&SendVar)) { + HelpId = HlpFileSend; + strncpy_s(SendVar->FullName, sizeof(SendVar->FullName), FileName, _TRUNCATE); + SendVar->DirLen = 0; + ts.TransBin = DropType == DROP_TYPE_SEND_FILE ? 0 : 1; + FileSendStart(); +#if 0 + goto finish; // send file\x82͘A\x91\xB1\x82\xB5\x82Ăł\xAB\x82Ȃ\xA2 +#else + { + LONG lCount = 0; + CWinApp *app = AfxGetApp(); + while(1) { + if (SendVar == NULL) { + break; + } + app->OnIdle(lCount++); + } } +#endif } + break; + case DROP_TYPE_PASTE_FILENAME: + case DROP_TYPE_PASTE_FILENAME_WITH_ESCAPE: + { + const bool escape = DropType == DROP_TYPE_PASTE_FILENAME ? false : true; + PasteString(&cv, FileName, escape); + if (DropListCount > 1) { + PasteString(&cv, "\n", false); + } + break; } - else - FreeFileVar(&SendVar); + case DROP_TYPE_SCP: + { + // send by scp + char **FileNames = &DropLists[i]; + int FileCount = AdapatSameProcess ? DropListCount - i : 1; + if (!SendScp(FileNames, FileCount, ts.ScpSendDir)) { + goto finish; + } + i += FileCount - 1; + break; + } + } } + +finish: + DropListFree(); + return 0; +} + +void CVTWindow::OnDropFiles(HDROP hDropInfo) +{ + ::SetForegroundWindow(HVTWin); + if (cv.Ready && SendVar==NULL) + { + const UINT ShowDialog = + ((GetAsyncKeyState(VK_CONTROL) & 0x8000) != 0) ? 1 : 0; + DropListCount = DragQueryFile(hDropInfo, -1, NULL, 0); + DropLists = (char **)malloc(sizeof(char *) * DropListCount); + + for (int i = 0; i < DropListCount; i++) { + const UINT cch = DragQueryFile(hDropInfo, i, NULL, 0) + 1; + char *FileName = (char *)malloc(cch); + DropLists[i] = FileName; + DragQueryFile(hDropInfo,i,FileName,cch); + } + + ::PostMessage(HVTWin, WM_USER_DROPNOTIFY, ShowDialog, 0); + } DragFinish(hDropInfo); } Modified: branches/drag_and_drop/teraterm/teraterm/vtwin.h =================================================================== --- branches/drag_and_drop/teraterm/teraterm/vtwin.h 2018-06-11 14:22:14 UTC (rev 7129) +++ branches/drag_and_drop/teraterm/teraterm/vtwin.h 2018-06-11 14:34:12 UTC (rev 7130) @@ -1,6 +1,6 @@ /* * Copyright (C) 1994-1998 T. Teranishi - * (C) 2004-2017 TeraTerm Project + * (C) 2004-2018 TeraTerm Project * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -50,6 +50,13 @@ HMENU MainMenu, FileMenu, TransMenu, EditMenu, SetupMenu, ControlMenu, WinMenu, HelpMenu; + // drag and drop handle + char **DropLists; + int DropListCount; + void DropListFree(); + bool DropWithLeftbutton; + bool DropWithRightbutton; + protected: public: @@ -214,6 +221,7 @@ afx_msg void OnHelpIndex(); afx_msg void OnHelpUsing(); afx_msg void OnHelpAbout(); + afx_msg LONG OnDropNotify(UINT ShowMenu, LONG lParam); //}}AFX_MSG DECLARE_MESSAGE_MAP(); void Disconnect(BOOL confirm);