• R/O
  • SSH
  • HTTPS

ttssh2: コミット


コミットメタ情報

リビジョン7130 (tree)
日時2018-06-11 23:34:12
作者zmatsuo

ログメッセージ

drag and dropの改良
- ダイアログにファイル名ペーストなどを追加
- 複数ファイルのドロップに対応

変更サマリ

差分

--- branches/drag_and_drop/teraterm/teraterm/vtwin.cpp (revision 7129)
+++ branches/drag_and_drop/teraterm/teraterm/vtwin.cpp (revision 7130)
@@ -1,6 +1,6 @@
11 /*
22 * Copyright (C) 1994-1998 T. Teranishi
3- * (C) 2004-2017 TeraTerm Project
3+ * (C) 2004-2018 TeraTerm Project
44 * All rights reserved.
55 *
66 * Redistribution and use in source and binary forms, with or without
@@ -254,6 +254,7 @@
254254 ON_COMMAND(ID_WINDOW_UNDO, OnWindowUndo)
255255 ON_COMMAND(ID_HELP_INDEX2, OnHelpIndex)
256256 ON_COMMAND(ID_HELP_ABOUT, OnHelpAbout)
257+ ON_MESSAGE(WM_USER_DROPNOTIFY, OnDropNotify)
257258 //}}AFX_MSG_MAP
258259 END_MESSAGE_MAP()
259260
@@ -918,6 +919,9 @@
918919 // Tera Termの起動時、Virtual Storeが働くかどうかを覚えておく。
919920 // (2015.11.14 yutaka)
920921 cv.VirtualStoreEnabled = GetVirtualStoreEnvironment();
922+
923+ DropLists = NULL;
924+ DropListCount = 0;
921925 }
922926
923927 /////////////////////////////////////////////////////////////////////////////
@@ -1986,6 +1990,7 @@
19861990
19871991 /* Disable drag-drop */
19881992 ::DragAcceptFiles(HVTWin,FALSE);
1993+ DropListFree();
19891994
19901995 EndDDE();
19911996
@@ -2019,57 +2024,135 @@
20192024 DeleteNotifyIcon(&cv);
20202025 }
20212026
2027+static void SetDlgFonts(HWND hDlg, const int nIDDlgItems[], int nIDDlgItemCount, HFONT hFont)
2028+{
2029+ for (int i = 0 ; i < nIDDlgItemCount ; i++) {
2030+ const int nIDDlgItem = nIDDlgItems[i];
2031+ SendDlgItemMessage(hDlg, nIDDlgItem, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE,0));
2032+ }
2033+}
2034+
2035+enum drop_type {
2036+ DROP_TYPE_CANCEL,
2037+ DROP_TYPE_SCP,
2038+ DROP_TYPE_SEND_FILE, // past contents of file
2039+ DROP_TYPE_SEND_FILE_BINARY,
2040+ DROP_TYPE_PASTE_FILENAME,
2041+ DROP_TYPE_PASTE_FILENAME_WITH_ESCAPE,
2042+};
2043+
2044+struct DrapDropDlgParam {
2045+ const char *TargetFilename;
2046+ enum drop_type DropType;
2047+ bool ScpEnable;
2048+ char *ScpSendDirPtr;
2049+ int ScpSendDirSize;
2050+ bool SendfileEnable;
2051+ int RemaingFileCount;
2052+ bool AdaptSameProcess;
2053+ bool DefaultProcess;
2054+};
2055+
2056+struct DrapDropDlgData {
2057+ HFONT DlgDragDropFont;
2058+ struct DrapDropDlgParam *Param;
2059+};
2060+
20222061 static LRESULT CALLBACK OnDragDropDlgProc(HWND hDlgWnd, UINT msg, WPARAM wp, LPARAM lp)
20232062 {
2024- static HFONT DlgDragDropFont = NULL;
2025- char uimsg[MAX_UIMSG];
2026- LOGFONT logfont;
2027- HFONT font;
2063+ struct DrapDropDlgData *DlgData = (struct DrapDropDlgData *)GetWindowLongPtr(hDlgWnd, GWLP_USERDATA);
20282064
20292065 switch (msg) {
20302066 case WM_INITDIALOG:
2067+ {
2068+ char uimsg[MAX_UIMSG];
2069+ LOGFONT logfont;
2070+ HFONT font;
2071+ HFONT DlgDragDropFont = NULL;
2072+ DlgData = (struct DrapDropDlgData *)malloc(sizeof(struct DrapDropDlgData));
2073+ SetWindowLongPtr(hDlgWnd, GWLP_USERDATA, (LONG_PTR)DlgData);
2074+ struct DrapDropDlgParam *Param = (struct DrapDropDlgParam *)lp;
2075+ DlgData->Param = Param;
20312076 font = (HFONT)SendMessage(hDlgWnd, WM_GETFONT, 0, 0);
20322077 GetObject(font, sizeof(LOGFONT), &logfont);
20332078 if (get_lang_font("DLG_TAHOMA_FONT", hDlgWnd, &logfont, &DlgDragDropFont, ts.UILanguageFile)) {
2034- SendDlgItemMessage(hDlgWnd, IDC_SCP_PATH, WM_SETFONT, (WPARAM)DlgDragDropFont, MAKELPARAM(TRUE,0));
2035- SendDlgItemMessage(hDlgWnd, IDOK, WM_SETFONT, (WPARAM)DlgDragDropFont, MAKELPARAM(TRUE,0));
2036- SendDlgItemMessage(hDlgWnd, IDCANCEL, WM_SETFONT, (WPARAM)DlgDragDropFont, MAKELPARAM(TRUE,0));
2037- SendDlgItemMessage(hDlgWnd, IDC_DAD_STATIC, WM_SETFONT, (WPARAM)DlgDragDropFont, MAKELPARAM(TRUE,0));
2038- SendDlgItemMessage(hDlgWnd, IDC_DAD_SENDFILE, WM_SETFONT, (WPARAM)DlgDragDropFont, MAKELPARAM(TRUE,0));
2079+ const static int IDs[] = {
2080+ IDC_FILENAME_EDIT,
2081+ IDC_DAD_STATIC,
2082+ IDC_SCP_RADIO, IDC_SENDFILE_RADIO, IDC_PASTE_RADIO,
2083+ IDC_SCP_PATH_LABEL, IDC_SCP_PATH, IDC_SCP_PATH_NOTE,
2084+ IDC_BINARY_CHECK, IDC_ESCAPE_CHECK,
2085+ IDC_ADAPT_SAME_CHECK, IDC_DEFAULT_CHECK,
2086+ IDOK, IDCANCEL,
2087+ };
2088+ SetDlgFonts(hDlgWnd, IDs, _countof(IDs), DlgDragDropFont);
20392089 } else {
20402090 DlgDragDropFont = NULL;
20412091 }
2092+ DlgData->DlgDragDropFont = DlgDragDropFont;
20422093
20432094 GetWindowText(hDlgWnd, uimsg, sizeof(uimsg));
20442095 get_lang_msg("MSG_DANDD_CONF_TITLE", ts.UIMsg, sizeof(ts.UIMsg), uimsg, ts.UILanguageFile);
20452096 SetWindowText(hDlgWnd, ts.UIMsg);
20462097
2098+ SetDlgItemText(hDlgWnd, IDC_FILENAME_EDIT, Param->TargetFilename);
2099+
20472100 get_lang_msg("MSG_DANDD_CONF", ts.UIMsg, sizeof(ts.UIMsg),
20482101 "Are you sure that you want to send the file content?", ts.UILanguageFile);
20492102 SetDlgItemText(hDlgWnd, IDC_DAD_STATIC, ts.UIMsg);
2103+
2104+ // checkbox
2105+ CheckRadioButton(hDlgWnd, IDC_SCP_RADIO, IDC_PASTE_RADIO,
2106+ (Param->DropType == DROP_TYPE_SEND_FILE ||
2107+ Param->DropType == DROP_TYPE_SEND_FILE_BINARY) ? IDC_SENDFILE_RADIO :
2108+ (Param->DropType == DROP_TYPE_PASTE_FILENAME ||
2109+ Param->DropType == DROP_TYPE_PASTE_FILENAME_WITH_ESCAPE) ? IDC_PASTE_RADIO :
2110+ IDC_SCP_RADIO);
20502111
2051- get_lang_msg("FILEDLG_TRANS_TITLE_SENDFILE", ts.UIMsg, sizeof(ts.UIMsg),
2052- "Send file", ts.UILanguageFile);
2053- SetDlgItemText(hDlgWnd, IDOK, ts.UIMsg);
2112+ // SCP
2113+ SendMessage(GetDlgItem(hDlgWnd, IDC_SCP_PATH), WM_SETTEXT, 0, (LPARAM)Param->ScpSendDirPtr);
2114+ if (!Param->ScpEnable) {
2115+ // 無効化
2116+ EnableWindow(GetDlgItem(hDlgWnd, IDC_SCP_RADIO), FALSE);
2117+ EnableWindow(GetDlgItem(hDlgWnd, IDC_SCP_PATH_LABEL), FALSE);
2118+ EnableWindow(GetDlgItem(hDlgWnd, IDC_SCP_PATH), FALSE);
2119+ EnableWindow(GetDlgItem(hDlgWnd, IDC_SCP_PATH_NOTE), FALSE);
2120+ }
20542121
2055- SendMessage(GetDlgItem(hDlgWnd, IDC_SCP_PATH), WM_SETTEXT, 0, (LPARAM)ts.ScpSendDir);
2122+ // Send File
2123+ if (Param->DropType == DROP_TYPE_SEND_FILE_BINARY) {
2124+ SendMessage(GetDlgItem(hDlgWnd, IDC_BINARY_CHECK), BM_SETCHECK, BST_CHECKED, 0);
2125+ }
2126+ if (!Param->SendfileEnable) {
2127+ // 無効化
2128+ EnableWindow(GetDlgItem(hDlgWnd, IDC_SENDFILE_RADIO), FALSE);
2129+ EnableWindow(GetDlgItem(hDlgWnd, IDC_BINARY_CHECK), FALSE);
2130+ }
20562131
2057- // SSH2 接続ではない場合には "SCP" を無効化する。
2058- if (cv.isSSH != 2) {
2059- EnableWindow(GetDlgItem(hDlgWnd, IDC_DAD_SENDFILE), FALSE);
2060- EnableWindow(GetDlgItem(hDlgWnd, IDC_SCP_PATH), FALSE);
2061- EnableWindow(GetDlgItem(hDlgWnd, IDC_STATIC), FALSE);
2132+ // Paste Filename
2133+ if (Param->DropType != DROP_TYPE_PASTE_FILENAME) {
2134+ SendMessage(GetDlgItem(hDlgWnd, IDC_ESCAPE_CHECK), BM_SETCHECK, BST_CHECKED, 0);
2135+ }
20622136
2063- // フォーカスの初期状態を Cancel にする為、この時点では Send File (IDOK)に
2137+ // Adapt same process
2138+ GetDlgItemText(hDlgWnd, IDC_ADAPT_SAME_CHECK, uimsg, sizeof(uimsg));
2139+ char b[MAX_UIMSG];
2140+ _snprintf_s(b, sizeof(b), _TRUNCATE, uimsg, Param->RemaingFileCount);
2141+ SetDlgItemText(hDlgWnd, IDC_ADAPT_SAME_CHECK, b);
2142+ if (Param->RemaingFileCount < 2) {
2143+ EnableWindow(GetDlgItem(hDlgWnd, IDC_ADAPT_SAME_CHECK), FALSE);
2144+ }
2145+
2146+ // focus to "SCP dest textbox" or "Cancel"
2147+ if (Param->ScpEnable) {
2148+ // "SCP" 有効時は Cancel にフォーカスを当て、最終的に SCP PATH にフォーカスが
2149+ // 当たるようにする。
2150+ SetFocus(GetDlgItem(hDlgWnd, IDC_SCP_RADIO));
2151+ } else {
2152+ // フォーカスの初期状態を Cancel にする為、この時点では IDOK に
20642153 // フォーカスを当てる。後で WM_NEXTDLGCTL でフォーカスが次のボタンになる。
20652154 SetFocus(GetDlgItem(hDlgWnd, IDOK));
20662155 }
2067- else {
2068- // SSH2 接続時は Cancel にフォーカスを当て、最終的に SCP PATH にフォーカスが
2069- // 当たるようにする。
2070- SetFocus(GetDlgItem(hDlgWnd, IDCANCEL));
2071- }
2072-
20732156 // フォーカスを次のボタンに移す
20742157 // SetFocus() で直接フォーカスを当てるとタブキーの動作等に問題が出るため、
20752158 // このメッセージを併用する
@@ -2077,34 +2160,55 @@
20772160
20782161 // TRUEにするとボタンにフォーカスが当たらない。
20792162 return FALSE;
2163+ }
20802164
20812165 case WM_COMMAND:
2082- switch (LOWORD(wp)) {
2083- case IDC_DAD_SENDFILE:
2084- SendMessage(GetDlgItem(hDlgWnd, IDC_SCP_PATH), WM_GETTEXT, sizeof(ts.ScpSendDir), (LPARAM)ts.ScpSendDir);
2085- if (DlgDragDropFont != NULL) {
2086- DeleteObject(DlgDragDropFont);
2087- }
2088- EndDialog(hDlgWnd, IDC_DAD_SENDFILE);
2089- break;
2090-
2091- case IDOK:
2092- if (DlgDragDropFont != NULL) {
2093- DeleteObject(DlgDragDropFont);
2094- }
2095- EndDialog(hDlgWnd, IDOK);
2096- break;
2097-
2098- case IDCANCEL:
2099- if (DlgDragDropFont != NULL) {
2100- DeleteObject(DlgDragDropFont);
2101- }
2102- EndDialog(hDlgWnd, IDCANCEL);
2103- break;
2104-
2105- default:
2106- return FALSE;
2166+ {
2167+ WORD wID = GET_WM_COMMAND_ID(wp, lp);
2168+ const WORD wCMD = GET_WM_COMMAND_CMD(wp, lp);
2169+ if (wCMD == BN_DBLCLK &&
2170+ (wID == IDC_SCP_RADIO || wID == IDC_SENDFILE_RADIO || wID == IDC_PASTE_RADIO))
2171+ { // radio buttons double click
2172+ wID = IDOK;
21072173 }
2174+ if (wID == IDOK) {
2175+ if (IsDlgButtonChecked(hDlgWnd, IDC_SCP_RADIO) == BST_CHECKED) {
2176+ // SCP
2177+ DlgData->Param->DropType = DROP_TYPE_SCP;
2178+ SendMessage(GetDlgItem(hDlgWnd, IDC_SCP_PATH), WM_GETTEXT,
2179+ (WPARAM)DlgData->Param->ScpSendDirSize,
2180+ (LPARAM)DlgData->Param->ScpSendDirPtr);
2181+ } else if (IsDlgButtonChecked(hDlgWnd, IDC_SENDFILE_RADIO) == BST_CHECKED) {
2182+ // Send File
2183+ DlgData->Param->DropType =
2184+ (IsDlgButtonChecked(hDlgWnd, IDC_BINARY_CHECK) == BST_CHECKED) ?
2185+ DROP_TYPE_SEND_FILE_BINARY : DROP_TYPE_SEND_FILE;
2186+ } else /* if (IsDlgButtonChecked(hDlgWnd, IDC_PASTE_RADIO) == BST_CHECKED) */ {
2187+ // Paste Filename
2188+ DlgData->Param->DropType =
2189+ (IsDlgButtonChecked(hDlgWnd, IDC_ESCAPE_CHECK) == BST_CHECKED) ?
2190+ DROP_TYPE_PASTE_FILENAME_WITH_ESCAPE : DROP_TYPE_PASTE_FILENAME;
2191+ }
2192+ DlgData->Param->AdaptSameProcess =
2193+ (IsDlgButtonChecked(hDlgWnd, IDC_ADAPT_SAME_CHECK) == BST_CHECKED) ?
2194+ true : false;
2195+ DlgData->Param->DefaultProcess =
2196+ (IsDlgButtonChecked(hDlgWnd, IDC_DEFAULT_CHECK) == BST_CHECKED) ?
2197+ true : false;
2198+ }
2199+ if (wID == IDCANCEL) {
2200+ DlgData->Param->DropType = DROP_TYPE_CANCEL;
2201+ }
2202+ if (wID == IDOK || wID == IDCANCEL) {
2203+ if (DlgData->DlgDragDropFont != NULL) {
2204+ DeleteObject(DlgData->DlgDragDropFont);
2205+ }
2206+ EndDialog(hDlgWnd, wID);
2207+ free(DlgData);
2208+ break;
2209+ }
2210+ return FALSE;
2211+ }
21082212
21092213 default:
21102214 return FALSE;
@@ -2112,118 +2216,312 @@
21122216 return TRUE;
21132217 }
21142218
2115-void CVTWindow::OnDropFiles(HDROP hDropInfo)
2219+static enum drop_type ShowDropDialogBox(
2220+ HINSTANCE hInstance, HWND hWndParent,
2221+ const char *TargetFilename,
2222+ enum drop_type DefaultDropType,
2223+ int RemaingFileCount,
2224+ bool EnableSCP,
2225+ bool EnableSendFile,
2226+ bool *AdaptSameProcess,
2227+ bool *DefaultProcess)
21162228 {
2117- ::SetForegroundWindow(HVTWin);
2118- if (cv.Ready && (SendVar==NULL) && NewFileVar(&SendVar))
2119- {
2120- if (DragQueryFile(hDropInfo,0,SendVar->FullName,
2121- sizeof(SendVar->FullName))>0)
2122- {
2123- DWORD attr;
2124- char *ptr, *q;
2125- char tmpbuf[_MAX_PATH * 2];
2229+ struct DrapDropDlgParam Param;
2230+ Param.TargetFilename = TargetFilename;
2231+ Param.DropType = DefaultDropType;
2232+ Param.ScpEnable = EnableSCP;
2233+ Param.ScpSendDirPtr = ts.ScpSendDir;
2234+ Param.ScpSendDirSize = sizeof(ts.ScpSendDir);
2235+ Param.SendfileEnable = EnableSendFile;
2236+ Param.RemaingFileCount = RemaingFileCount;
2237+ int ret = DialogBoxParam(
2238+ hInstance, MAKEINTRESOURCE(IDD_DAD_DIALOG),
2239+ hWndParent, (DLGPROC)OnDragDropDlgProc,
2240+ (LPARAM)&Param);
2241+ if (ret != IDOK) {
2242+ return DROP_TYPE_CANCEL;
2243+ }
2244+ *AdaptSameProcess = Param.AdaptSameProcess;
2245+ *DefaultProcess = Param.DefaultProcess;
2246+ return Param.DropType;
2247+}
21262248
2127- // ディレクトリの場合はフルパス名を貼り付ける (2004.11.3 yutaka)
2128- attr = GetFileAttributes(SendVar->FullName);
2129- if (attr != -1 && (attr & FILE_ATTRIBUTE_DIRECTORY)) {
2130- ptr = SendVar->FullName;
2131- // パスの区切りを \ -> / へ
2132- setlocale(LC_ALL, ts.Locale);
2133- while (*ptr) {
2134- if (isleadbyte(*ptr)) { // multi-byte
2135- ptr += 2;
2136- continue;
2137- }
2138- if (*ptr == '\\')
2139- *ptr = '/';
2140- ptr++;
2141- }
2249+static void EscapeFilename(const char *src, char *dest)
2250+{
2251+#define ESCAPE_CHARS " ;&()$!`'[]{}#^~"
2252+ setlocale(LC_ALL, ts.Locale);
2253+ const char *s = src;
2254+ char *d = dest;
2255+ while (*s) {
2256+ if (isleadbyte(*s)) { // multi-byte
2257+ *d++ = *s++;
2258+ *d++ = *s++;
2259+ continue;
2260+ }
2261+ char c = *s++;
2262+ if (c == '\\') {
2263+ // パスの区切りを \ -> / へ
2264+ *d = '/';
2265+ } else if (strchr(ESCAPE_CHARS, c) != NULL) {
2266+ // エスケープが必要な文字
2267+ *d++ = '\\';
2268+ *d = c;
2269+ } else {
2270+ *d = c;
2271+ }
2272+ d++;
2273+ }
2274+ *d = '\0'; // null-terminate
2275+}
21422276
2143- // パスに空白があればエスケープする
2144- q = tmpbuf;
2145- ptr = SendVar->FullName;
2146- while (*ptr) {
2147- if (*ptr == ' ')
2148- *q++ = '\\';
2149- *q++ = *ptr;
2150- ptr++;
2151- }
2152- *q = '\0'; // null-terminate
2277+static void PasteString(PComVar cv, const char *str, bool escape)
2278+{
2279+ PCHAR ptr = (PCHAR)str;
2280+ char *tmpbuf = NULL;
2281+ if (escape) {
2282+ size_t len = strlen(str) * 2;
2283+ tmpbuf = (char *)malloc(len);
2284+ EscapeFilename(str, tmpbuf);
2285+ ptr = tmpbuf;
2286+ }
21532287
2154- ptr = tmpbuf;
2288+ // consoleへ送信
2289+ while (*ptr) {
2290+ CommTextOut(cv, ptr, 1);
2291+ if (ts.LocalEcho > 0) {
2292+ CommTextEcho(cv, ptr, 1);
2293+ }
2294+ ptr++;
2295+ }
21552296
2156- // consoleへ送信
2157- while (*ptr) {
2158- CommTextOut(&cv, ptr, 1);
2159- if (ts.LocalEcho > 0) {
2160- CommTextEcho(&cv, ptr, 1);
2161- }
2162- ptr++;
2163- }
2164- FreeFileVar(&SendVar); // 解放を忘れずに
2297+ if (tmpbuf != NULL) free(tmpbuf);
2298+}
21652299
2166- } else {
2167- // Confirm send a file when drag and drop (2007.12.28 maya)
2168- if (ts.ConfirmFileDragAndDrop) {
2169- // いきなりファイルの内容を送り込む前に、ユーザに問い合わせを行う。(2006.1.21 yutaka)
2170- // MessageBoxでSCPも選択できるようにする。(2008.1.25 yutaka)
2171- // SCPパスを指定できるようにダイアログに変更した。(2012.4.11 yutaka)
2172- int ret;
2300+/* 入力はファイルのみ(フォルダは含まれない) */
2301+static bool SendScp(char *Filenames[], int FileCount, const char *SendDir)
2302+{
2303+ typedef int (CALLBACK *PSSH_start_scp)(char *, char *);
2304+ static PSSH_start_scp func = NULL;
2305+ static HMODULE h = NULL;
2306+ char msg[128];
21732307
2174- ret = DialogBox(hInst, MAKEINTRESOURCE(IDD_DAD_DIALOG),
2175- HVTWin, (DLGPROC)OnDragDropDlgProc);
2308+ if (h == NULL) {
2309+ if ( ((h = GetModuleHandle("ttxssh.dll")) == NULL) ) {
2310+ _snprintf_s(msg, sizeof(msg), _TRUNCATE, "GetModuleHandle(\"ttxssh.dll\")) %d", GetLastError());
2311+ scp_send_error:
2312+ ::MessageBox(NULL, msg, "Tera Term: scpsend command error", MB_OK | MB_ICONERROR);
2313+ return false;
2314+ }
2315+ }
2316+ if (func == NULL) {
2317+ func = (PSSH_start_scp)GetProcAddress(h, "TTXScpSendfile");
2318+ if (func == NULL) {
2319+ _snprintf_s(msg, sizeof(msg), _TRUNCATE, "GetProcAddress(\"TTXScpSendfile\")) %d", GetLastError());
2320+ goto scp_send_error;
2321+ }
2322+ }
21762323
2177- if (ret == IDOK) { // sendfile
2178- HelpId = HlpFileSend;
2179- SendVar->DirLen = 0;
2180- ts.TransBin = 0;
2181- FileSendStart();
2324+ for (int i = 0; i < FileCount; i++) {
2325+ const char *FileName = Filenames[i];
2326+ func((char *)FileName, ts.ScpSendDir);
2327+ }
2328+ return true;
2329+}
21822330
2183- } else if (ret == IDC_DAD_SENDFILE) { // SCP
2184- typedef int (CALLBACK *PSSH_start_scp)(char *, char *);
2185- static PSSH_start_scp func = NULL;
2186- static HMODULE h = NULL;
2187- char msg[128];
2331+void CVTWindow::DropListFree()
2332+{
2333+ if (DropListCount > 0) {
2334+ for (int i = 0; i < DropListCount; i++) {
2335+ free(DropLists[i]);
2336+ DropLists[i] = NULL;
2337+ }
2338+ free(DropLists);
2339+ DropLists = NULL;
2340+ DropListCount = 0;
2341+ }
2342+}
21882343
2189- if (func == NULL) {
2190- if ( ((h = GetModuleHandle("ttxssh.dll")) == NULL) ) {
2191- _snprintf_s(msg, sizeof(msg), _TRUNCATE, "GetModuleHandle(\"ttxssh.dll\")) %d", GetLastError());
2192- goto scp_send_error;
2193- }
2194- func = (PSSH_start_scp)GetProcAddress(h, "TTXScpSendfile");
2195- if (func == NULL) {
2196- _snprintf_s(msg, sizeof(msg), _TRUNCATE, "GetProcAddress(\"TTXScpSendfile\")) %d", GetLastError());
2197- goto scp_send_error;
2198- }
2199- }
2344+LONG CVTWindow::OnDropNotify(UINT ShowDialog, LONG lParam)
2345+{
2346+ static enum drop_type DefaultDropType = DROP_TYPE_CANCEL;
22002347
2201- if (func != NULL) {
2202- func(SendVar->FullName, ts.ScpSendDir);
2203- goto send_success;
2204- }
2348+ (void)lParam;
2349+ int FileCount = 0;
2350+ int DirectoryCount = 0;
2351+ for (int i = 0; i < DropListCount; i++) {
2352+ const char *FileName = DropLists[i];
2353+ const DWORD attr = GetFileAttributes(FileName);
2354+ if (attr == -1 ) {
2355+ goto finish;
2356+ }
2357+ if (attr & FILE_ATTRIBUTE_DIRECTORY) {
2358+ DirectoryCount++;
2359+ } else {
2360+ FileCount++;
2361+ }
2362+ }
22052363
2206-scp_send_error:
2207- ::MessageBox(NULL, msg, "Tera Term: scpsend command error", MB_OK | MB_ICONERROR);
2208-send_success:
2209- FreeFileVar(&SendVar); // 解放を忘れずに
2210-
2364+ bool AdapatSameProcess = false;
2365+ const bool isSSH = (cv.isSSH == 2);
2366+ enum drop_type DropType;
2367+ if (DefaultDropType == DROP_TYPE_CANCEL) {
2368+ // default is not set
2369+ if (!ShowDialog) {
2370+ if (FileCount == 1 && DirectoryCount == 0) {
2371+ if (ts.ConfirmFileDragAndDrop) {
2372+ if (isSSH) {
2373+ DropType = DROP_TYPE_SCP;
22112374 } else {
2212- FreeFileVar(&SendVar);
2213-
2375+ DropType = DROP_TYPE_SEND_FILE;
22142376 }
2377+ AdapatSameProcess = false;
2378+ } else {
2379+ DropType = DROP_TYPE_SEND_FILE;
2380+ AdapatSameProcess = true;
22152381 }
2216- else {
2217- SendVar->DirLen = 0;
2218- ts.TransBin = 0;
2219- FileSendStart();
2382+ } else if (FileCount == 0 && DirectoryCount == 1) {
2383+ DropType = DROP_TYPE_PASTE_FILENAME_WITH_ESCAPE;
2384+ AdapatSameProcess = true;
2385+ } else if (FileCount > 0 && DirectoryCount > 0) {
2386+ DropType = DROP_TYPE_PASTE_FILENAME_WITH_ESCAPE;
2387+ AdapatSameProcess = false;
2388+ } else if (FileCount > 0 && DirectoryCount == 0) {
2389+ // filename only
2390+ if (isSSH) {
2391+ DropType = DROP_TYPE_SCP;
2392+ } else {
2393+ DropType = DROP_TYPE_SEND_FILE;
2394+ }
2395+ AdapatSameProcess = false;
2396+ } else {
2397+ // directory only
2398+ DropType = DROP_TYPE_PASTE_FILENAME_WITH_ESCAPE;
2399+ AdapatSameProcess = ts.ConfirmFileDragAndDrop ? false : true;
2400+ }
2401+ } else {
2402+ // show dialog
2403+ if (DirectoryCount > 0) {
2404+ DropType = DROP_TYPE_PASTE_FILENAME_WITH_ESCAPE;
2405+ } else {
2406+ if (isSSH) {
2407+ DropType = DROP_TYPE_SCP;
2408+ } else {
2409+ DropType = DROP_TYPE_SEND_FILE;
2410+ }
2411+ }
2412+ AdapatSameProcess = false;
2413+ }
2414+ } else {
2415+ if (DirectoryCount > 0 &&
2416+ (DefaultDropType == DROP_TYPE_SEND_FILE ||
2417+ DefaultDropType == DROP_TYPE_SEND_FILE_BINARY ||
2418+ DefaultDropType == DROP_TYPE_SCP))
2419+ { // デフォルトのままでは処理できない組み合わせ
2420+ DropType = DROP_TYPE_PASTE_FILENAME_WITH_ESCAPE;
2421+ AdapatSameProcess = false;
2422+ } else {
2423+ DropType = DefaultDropType;
2424+ AdapatSameProcess = ShowDialog ? false : true;
2425+ }
2426+ }
22202427
2428+ for (int i = 0; i < DropListCount; i++) {
2429+ const char *FileName = DropLists[i];
2430+
2431+ if (!AdapatSameProcess) {
2432+ bool DefaultProcess;
2433+ DropType =
2434+ ShowDropDialogBox(hInst, HVTWin,
2435+ FileName, DropType,
2436+ DropListCount - i,
2437+ (DirectoryCount == 0 && isSSH) ? true : false,
2438+ DirectoryCount == 0 ? true : false,
2439+ &AdapatSameProcess, &DefaultProcess);
2440+ if (DropType == DROP_TYPE_CANCEL) {
2441+ goto finish;
2442+ }
2443+ if (DefaultProcess) {
2444+ DefaultDropType = DropType;
2445+ }
2446+ }
2447+
2448+ switch (DropType) {
2449+ case DROP_TYPE_CANCEL:
2450+ default:
2451+ // cancel
2452+ break;
2453+ case DROP_TYPE_SEND_FILE:
2454+ case DROP_TYPE_SEND_FILE_BINARY:
2455+ if (SendVar==NULL && NewFileVar(&SendVar)) {
2456+ HelpId = HlpFileSend;
2457+ strncpy_s(SendVar->FullName, sizeof(SendVar->FullName), FileName, _TRUNCATE);
2458+ SendVar->DirLen = 0;
2459+ ts.TransBin = DropType == DROP_TYPE_SEND_FILE ? 0 : 1;
2460+ FileSendStart();
2461+#if 0
2462+ goto finish; // send fileは連続してできない
2463+#else
2464+ {
2465+ LONG lCount = 0;
2466+ CWinApp *app = AfxGetApp();
2467+ while(1) {
2468+ if (SendVar == NULL) {
2469+ break;
2470+ }
2471+ app->OnIdle(lCount++);
2472+ }
22212473 }
2474+#endif
22222475 }
2476+ break;
2477+ case DROP_TYPE_PASTE_FILENAME:
2478+ case DROP_TYPE_PASTE_FILENAME_WITH_ESCAPE:
2479+ {
2480+ const bool escape = DropType == DROP_TYPE_PASTE_FILENAME ? false : true;
2481+ PasteString(&cv, FileName, escape);
2482+ if (DropListCount > 1) {
2483+ PasteString(&cv, "\n", false);
2484+ }
2485+ break;
22232486 }
2224- else
2225- FreeFileVar(&SendVar);
2487+ case DROP_TYPE_SCP:
2488+ {
2489+ // send by scp
2490+ char **FileNames = &DropLists[i];
2491+ int FileCount = AdapatSameProcess ? DropListCount - i : 1;
2492+ if (!SendScp(FileNames, FileCount, ts.ScpSendDir)) {
2493+ goto finish;
2494+ }
2495+ i += FileCount - 1;
2496+ break;
2497+ }
2498+ }
22262499 }
2500+
2501+finish:
2502+ DropListFree();
2503+ return 0;
2504+}
2505+
2506+void CVTWindow::OnDropFiles(HDROP hDropInfo)
2507+{
2508+ ::SetForegroundWindow(HVTWin);
2509+ if (cv.Ready && SendVar==NULL)
2510+ {
2511+ const UINT ShowDialog =
2512+ ((GetAsyncKeyState(VK_CONTROL) & 0x8000) != 0) ? 1 : 0;
2513+ DropListCount = DragQueryFile(hDropInfo, -1, NULL, 0);
2514+ DropLists = (char **)malloc(sizeof(char *) * DropListCount);
2515+
2516+ for (int i = 0; i < DropListCount; i++) {
2517+ const UINT cch = DragQueryFile(hDropInfo, i, NULL, 0) + 1;
2518+ char *FileName = (char *)malloc(cch);
2519+ DropLists[i] = FileName;
2520+ DragQueryFile(hDropInfo,i,FileName,cch);
2521+ }
2522+
2523+ ::PostMessage(HVTWin, WM_USER_DROPNOTIFY, ShowDialog, 0);
2524+ }
22272525 DragFinish(hDropInfo);
22282526 }
22292527
--- branches/drag_and_drop/teraterm/teraterm/vtwin.h (revision 7129)
+++ branches/drag_and_drop/teraterm/teraterm/vtwin.h (revision 7130)
@@ -1,6 +1,6 @@
11 /*
22 * Copyright (C) 1994-1998 T. Teranishi
3- * (C) 2004-2017 TeraTerm Project
3+ * (C) 2004-2018 TeraTerm Project
44 * All rights reserved.
55 *
66 * Redistribution and use in source and binary forms, with or without
@@ -50,6 +50,13 @@
5050 HMENU MainMenu, FileMenu, TransMenu, EditMenu,
5151 SetupMenu, ControlMenu, WinMenu, HelpMenu;
5252
53+ // drag and drop handle
54+ char **DropLists;
55+ int DropListCount;
56+ void DropListFree();
57+ bool DropWithLeftbutton;
58+ bool DropWithRightbutton;
59+
5360 protected:
5461
5562 public:
@@ -214,6 +221,7 @@
214221 afx_msg void OnHelpIndex();
215222 afx_msg void OnHelpUsing();
216223 afx_msg void OnHelpAbout();
224+ afx_msg LONG OnDropNotify(UINT ShowMenu, LONG lParam);
217225 //}}AFX_MSG
218226 DECLARE_MESSAGE_MAP();
219227 void Disconnect(BOOL confirm);
--- branches/drag_and_drop/teraterm/common/tttypes.h (revision 7129)
+++ branches/drag_and_drop/teraterm/common/tttypes.h (revision 7130)
@@ -1,6 +1,6 @@
11 /*
22 * Copyright (C) 1994-1998 T. Teranishi
3- * (C) 2004-2017 TeraTerm Project
3+ * (C) 2004-2018 TeraTerm Project
44 * All rights reserved.
55 *
66 * Redistribution and use in source and binary forms, with or without
@@ -173,6 +173,7 @@
173173 #define WM_USER_GETSERIALNO WM_USER+13
174174 #define WM_USER_CHANGETITLE WM_USER+14
175175 #define WM_USER_NOTIFYICON WM_USER+15
176+#define WM_USER_DROPNOTIFY WM_USER+16
176177
177178 #define WM_USER_DDEREADY WM_USER+21
178179 #define WM_USER_DDECMNDEND WM_USER+22
--- branches/drag_and_drop/teraterm/common/tt_res.h (revision 7129)
+++ branches/drag_and_drop/teraterm/common/tt_res.h (revision 7130)
@@ -164,7 +164,6 @@
164164 #define IDC_PROT_ELAPSED 2525
165165 #define IDC_DAD_STATIC 2525
166166 #define IDC_PROTOELAPSEDTIME 2526
167-#define IDC_DAD_SENDFILE 2526
168167 #define IDC_TRANS_ELAPSED 2527
169168 #define IDC_BGIMG_LABEL 2527
170169 #define IDC_TRANS_ETIME 2528
@@ -218,7 +217,16 @@
218217 #define IDC_NORMALIZE_LINEBREAK 2565
219218 #define IDC_CLIPBOARD_NOTIFY 2566
220219 #define IDC_LIST_HIDDEN_FONTS 2567
221-
220+#define IDC_BINARY_CHECK 2568
221+#define IDC_ADAPT_SAME_CHECK 2569
222+#define IDC_FILENAME_EDIT 2570
223+#define IDC_SCP_RADIO 2571
224+#define IDC_SENDFILE_RADIO 2572
225+#define IDC_PASTE_RADIO 2573
226+#define IDC_ESCAPE_CHECK 2574
227+#define IDC_DEFAULT_CHECK 2575
228+#define IDC_SCP_PATH_LABEL 2576
229+#define IDC_SCP_PATH_NOTE 2577
222230 #define ID_ACC_SENDBREAK 50001
223231 #define ID_ACC_COPY 50002
224232 #define ID_ACC_NEWCONNECTION 50003
@@ -316,7 +324,7 @@
316324 #define _APS_NO_MFC 1
317325 #define _APS_NEXT_RESOURCE_VALUE 126
318326 #define _APS_NEXT_COMMAND_VALUE 52031
319-#define _APS_NEXT_CONTROL_VALUE 2568
327+#define _APS_NEXT_CONTROL_VALUE 2578
320328 #define _APS_NEXT_SYMED_VALUE 101
321329 #endif
322330 #endif
旧リポジトリブラウザで表示