Revision: 10400 https://osdn.net/projects/ttssh2/scm/svn/commits/10400 Author: zmatsuo Date: 2022-12-11 21:07:36 +0900 (Sun, 11 Dec 2022) Log Message: ----------- 複数ファイルのDrag&Dropで複数のファイルが送信できない - sendmemにAPI追加 - 送信完了コールバック追加 - ファイルの送信完了ごとに次の送信を行えるよう修正 ticket #46070 Ticket Links: ------------ https://osdn.net/projects/ttssh2/tracker/detail/46070 Modified Paths: -------------- trunk/teraterm/teraterm/sendmem.cpp trunk/teraterm/teraterm/sendmem.h trunk/teraterm/teraterm/vtwin.cpp -------------- next part -------------- Modified: trunk/teraterm/teraterm/sendmem.cpp =================================================================== --- trunk/teraterm/teraterm/sendmem.cpp 2022-12-11 12:07:26 UTC (rev 10399) +++ trunk/teraterm/teraterm/sendmem.cpp 2022-12-11 12:07:36 UTC (rev 10400) @@ -76,6 +76,8 @@ char *UILanguageFile; wchar_t *dialog_caption; wchar_t *filename; + void (*callback)(void *data); + void *callback_data; // size_t send_left; size_t send_index; @@ -142,6 +144,12 @@ static void EndPaste() { sendmem_work_t *p = sendmem_work; + + if (p->callback != NULL) { + p->callback(p->callback_data); + p->callback = NULL; + } + free((void *)p->send_ptr); p->send_ptr = NULL; @@ -584,6 +592,15 @@ sm->delay_tick = delay_tick; } +/** + * \x91\x97\x90M\x8A\xAE\x97\xB9\x82ŃR\x81[\x83\x8B\x83o\x83b\x83N + */ +void SendMemInitSetCallback(SendMem *sm, void (*callback)(void *data), void *callback_data) +{ + sm->callback = callback; + sm->callback_data = callback_data; +} + // \x83Z\x83b\x83g\x82\xB7\x82\xE9\x82ƃ_\x83C\x83A\x83\x8D\x83O\x82\xAA\x8Fo\x82\xE9 void SendMemInitDialog(SendMem *sm, HINSTANCE hInstance, HWND hWndParent, const char *UILanguageFile) { @@ -646,7 +663,7 @@ return r; } #else -BOOL SendMemSendFile(const wchar_t *filename, BOOL binary, SendMemDelayType delay_type, DWORD delay_tick, size_t send_max) +SendMem *SendMemSendFileCom(const wchar_t *filename, BOOL binary, SendMemDelayType delay_type, DWORD delay_tick, size_t send_max) { SendMem *sm; if (!binary) { @@ -654,7 +671,7 @@ wchar_t *str_ptr = LoadFileWW(filename, &str_len); assert(str_ptr != NULL); if (str_ptr == NULL) { - return FALSE; + return NULL; } // \x89\xFC\x8Ds\x82\xF0 CR \x82݂̂ɐ\xB3\x8BK\x89\xBB @@ -669,7 +686,7 @@ unsigned char *data_ptr = LoadFileBinary(filename, &data_len); assert(data_ptr != NULL); if (data_ptr == NULL) { - return FALSE; + return NULL; } sm = SendMemBinary(data_ptr, data_len); } @@ -678,10 +695,27 @@ SendMemInitDialogFilename(sm, filename); SendMemInitDelay(sm, delay_type, delay_tick, send_max); SendMemStart(sm); - return TRUE; + return sm; } #endif +BOOL SendMemSendFile(const wchar_t *filename, BOOL binary, SendMemDelayType delay_type, DWORD delay_tick, size_t send_max) +{ + SendMem *sm = SendMemSendFileCom(filename, binary, delay_type, delay_tick, send_max); + return (sm != NULL) ? TRUE : FALSE; +} + +BOOL SendMemSendFile2(const wchar_t *filename, BOOL binary, SendMemDelayType delay_type, DWORD delay_tick, size_t send_max, void (*callback)(void *data), void *callback_data) +{ + SendMem *sm = SendMemSendFileCom(filename, binary, delay_type, delay_tick, send_max); + if (sm == NULL) { + return FALSE; + } + + SendMemInitSetCallback(sm, callback, callback_data); + return TRUE; +} + /** * \x92Z\x82\xA2\x95\xB6\x8E\x9A\x97\xF1\x82𑗐M\x82\xB7\x82\xE9 * @param[in] str malloc\x82\xB3\x82ꂽ\x97̈\xE6\x82̕\xB6\x8E\x9A\x97\xF1 Modified: trunk/teraterm/teraterm/sendmem.h =================================================================== --- trunk/teraterm/teraterm/sendmem.h 2022-12-11 12:07:26 UTC (rev 10399) +++ trunk/teraterm/teraterm/sendmem.h 2022-12-11 12:07:36 UTC (rev 10400) @@ -46,6 +46,7 @@ SendMem *SendMemBinary(void *ptr, size_t len); void SendMemInitEcho(SendMem *sm, BOOL echo); void SendMemInitSend(SendMem *sm, BOOL echo_only); +void SendMemInitSetCallback(SendMem *sm, void (*callback)(void *data), void *callback_data); void SendMemInitDelay(SendMem *sm, SendMemDelayType delay_type, DWORD delay_tick, size_t send_max); void SendMemInitDialog(SendMem *sm, HINSTANCE hInstance, HWND hWndParent, const char *UILanguageFile); void SendMemInitDialogCaption(SendMem *sm, const wchar_t *caption); @@ -59,6 +60,7 @@ // convenient function BOOL SendMemPasteString(wchar_t *str); BOOL SendMemSendFile(const wchar_t *filename, BOOL binary, SendMemDelayType delay_type, DWORD delay_tick, size_t send_max); +BOOL SendMemSendFile2(const wchar_t *filename, BOOL binary, SendMemDelayType delay_type, DWORD delay_tick, size_t send_max, void (*callback)(void *data), void *callback_data); #ifdef __cplusplus } Modified: trunk/teraterm/teraterm/vtwin.cpp =================================================================== --- trunk/teraterm/teraterm/vtwin.cpp 2022-12-11 12:07:26 UTC (rev 10399) +++ trunk/teraterm/teraterm/vtwin.cpp 2022-12-11 12:07:36 UTC (rev 10400) @@ -1595,149 +1595,210 @@ } } +typedef struct DropData_tag { + // ini\x82ɕۑ\xB6\x82\xB3\x82\xEA\x82Ȃ\xA2\x81A\x8D\xA1\x8E\xC0\x8Ds\x82\xB5\x82Ă\xA2\x82\xE9Tera Term\x82ł̂ݗL\x8C\xF8\x82Ȑݒ\xE8 + enum drop_type DefaultDropType; + unsigned char DefaultDropTypePaste; + bool DefaultShowDialog; + bool TransBin; + bool DoSameProcess; + enum drop_type DropType; + unsigned char DropTypePaste; + + HWND vtwin; + + int FileCount; + int DirectoryCount; + int SendIndex; +} DropData_t; + +static DropData_t *DropData; + /** - * \x83t\x83@\x83C\x83\x8B\x82\xAA\x83h\x83\x8D\x83b\x83v\x82\xB3\x82ꂽ + * \x8F\x89\x8A\xFA\x89\xBB + */ +static DropData_t *DropInit() +{ + DropData_t *data =(DropData_t *)calloc(sizeof(*data), 1); + data->DefaultDropType = DROP_TYPE_CANCEL; + data->DefaultDropTypePaste = DROP_TYPE_PASTE_ESCAPE; + data->DefaultShowDialog = ts.ConfirmFileDragAndDrop ? true : false; + data->vtwin = HVTWin; + return data; +} + +/** + * \x91\x97\x90M\x8A\xAE\x97\xB9\x83R\x81[\x83\x8B\x83o\x83b\x83N + */ +static void DropSendCallback(void *callback_data) +{ + DropData_t *data = (DropData_t *)callback_data; + // \x8E\x9F\x82̑\x97\x90M\x82\xF0\x8Ds\x82\xA4 + ::PostMessage(data->vtwin, WM_USER_DROPNOTIFY, 0, 1); +} + +/** + * \x83t\x83@\x83C\x83\x8B\x82\xAA\x83h\x83\x8D\x83b\x83v\x92ʒm + * @param lparam 0 \x83t\x83@\x83C\x83\x8B\x82\xAA\x83h\x83\x8D\x83b\x83v\x82\xB3\x82ꂽ + * ShowDialog\x82\xAA\x8EQ\x8FƂ\xB3\x82\xEA\x82\xE9 + * 1 \x83t\x83@\x83C\x83\x8B\x82̓]\x91\x97\x82\xAA\x8A\xAE\x97\xB9\x82\xB5\x82\xBD * @param ShowDialog 0 \x95\\x8E\xA6\x82\xB5\x82Ă\xE0\x95\\x8E\xA6\x82\xB5\x82Ȃ\xAD\x82Ă\xE0\x97ǂ\xA2 * 1 \x95K\x82\xB8\x95\\x8E\xA6\x82\xB7\x82\xE9 */ -LRESULT CVTWindow::OnDropNotify(WPARAM ShowDialog, LPARAM) +LRESULT CVTWindow::OnDropNotify(WPARAM ShowDialog, LPARAM lparam) { - // ini\x82ɕۑ\xB6\x82\xB3\x82\xEA\x82Ȃ\xA2\x81A\x8D\xA1\x8E\xC0\x8Ds\x82\xB5\x82Ă\xA2\x82\xE9Tera Term\x82ł̂ݗL\x8C\xF8\x82Ȑݒ\xE8 - static enum drop_type DefaultDropType = DROP_TYPE_CANCEL; - static unsigned char DefaultDropTypePaste = DROP_TYPE_PASTE_ESCAPE; - static bool DefaultShowDialog = ts.ConfirmFileDragAndDrop ? true : false; - static bool TransBin; + DropData_t *data = DropData; + if (data == NULL) { + // \x8F\x89\x82߂ăt\x83@\x83C\x83\x8B\x82̃h\x83\x8D\x83b\x83v\x82\xAA\x94\xAD\x90\xB6\x82\xB5\x82\xBD + assert(lparam == 0); + data = DropInit(); + DropData = data; + } - int FileCount = 0; - int DirectoryCount = 0; - for (int i = 0; i < DropListCount; i++) { - const wchar_t *FileName = DropLists[i]; - const DWORD attr = GetFileAttributesW(FileName); - if (attr == INVALID_FILE_ATTRIBUTES) { - FileCount++; - } else if (attr & FILE_ATTRIBUTE_DIRECTORY) { - DirectoryCount++; - } else { - FileCount++; + switch (lparam) { + case 0: { + data->FileCount = 0; + data->DirectoryCount = 0; + for (int i = 0; i < DropListCount; i++) { + const wchar_t *FileName = DropLists[i]; + const DWORD attr = GetFileAttributesW(FileName); + if (attr == INVALID_FILE_ATTRIBUTES) { + data->FileCount++; + } else if (attr & FILE_ATTRIBUTE_DIRECTORY) { + data->DirectoryCount++; + } else { + data->FileCount++; + } } - } - bool DoSameProcess = false; - const bool isSSH = (cv.isSSH == 2); - enum drop_type DropType; - unsigned char DropTypePaste = DROP_TYPE_PASTE_ESCAPE; - if (DefaultDropType == DROP_TYPE_CANCEL) { - // default is not set - TransBin = ts.TransBin == 0 ? false : true; - if (!ShowDialog) { - if (FileCount == 1 && DirectoryCount == 0) { - if (ts.ConfirmFileDragAndDrop) { + data->DoSameProcess = false; + const bool isSSH = (cv.isSSH == 2); + data->DropTypePaste = DROP_TYPE_PASTE_ESCAPE; + if (data->DefaultDropType == DROP_TYPE_CANCEL) { + // default is not set + data->TransBin = ts.TransBin == 0 ? false : true; + if (!ShowDialog) { + if (data->FileCount == 1 && data->DirectoryCount == 0) { + if (ts.ConfirmFileDragAndDrop) { + if (isSSH) { + data->DropType = DROP_TYPE_SCP; + } else { + data->DropType = DROP_TYPE_SEND_FILE; + } + data->DoSameProcess = false; + } else { + data->DropType = DROP_TYPE_SEND_FILE; + data->DoSameProcess = data->DefaultShowDialog ? false : true; + } + } + else if (data->FileCount == 0 && data->DirectoryCount == 1) { + data->DropType = DROP_TYPE_PASTE_FILENAME; + data->DoSameProcess = data->DefaultShowDialog ? false : true; + } + else if (data->FileCount > 0 && data->DirectoryCount > 0) { + data->DropType = DROP_TYPE_PASTE_FILENAME; + data->DoSameProcess = false; + } + else if (data->FileCount > 0 && data->DirectoryCount == 0) { + // filename only if (isSSH) { - DropType = DROP_TYPE_SCP; + data->DropType = DROP_TYPE_SCP; } else { - DropType = DROP_TYPE_SEND_FILE; + data->DropType = DROP_TYPE_SEND_FILE; } - DoSameProcess = false; + data->DoSameProcess = false; } else { - DropType = DROP_TYPE_SEND_FILE; - DoSameProcess = DefaultShowDialog ? false : true; + // directory only + data->DropType = DROP_TYPE_PASTE_FILENAME; + data->DoSameProcess = ts.ConfirmFileDragAndDrop ? false : true; } - } else if (FileCount == 0 && DirectoryCount == 1) { - DropType = DROP_TYPE_PASTE_FILENAME; - DoSameProcess = DefaultShowDialog ? false : true; - } else if (FileCount > 0 && DirectoryCount > 0) { - DropType = DROP_TYPE_PASTE_FILENAME; - DoSameProcess = false; - } else if (FileCount > 0 && DirectoryCount == 0) { - // filename only - if (isSSH) { - DropType = DROP_TYPE_SCP; + } else { + // show dialog + if (data->DirectoryCount > 0) { + data->DropType = DROP_TYPE_PASTE_FILENAME; } else { - DropType = DROP_TYPE_SEND_FILE; + if (isSSH) { + data->DropType = DROP_TYPE_SCP; + } else { + data->DropType = DROP_TYPE_SEND_FILE; + } } - DoSameProcess = false; - } else { - // directory only - DropType = DROP_TYPE_PASTE_FILENAME; - DoSameProcess = ts.ConfirmFileDragAndDrop ? false : true; + data->DoSameProcess = false; } } else { - // show dialog - if (DirectoryCount > 0) { - DropType = DROP_TYPE_PASTE_FILENAME; + if (data->DirectoryCount > 0 && + (data->DefaultDropType == DROP_TYPE_SEND_FILE || + data->DefaultDropType == DROP_TYPE_SCP)) + { // \x83f\x83t\x83H\x83\x8B\x83g\x82̂܂܂ł͏\x88\x97\x9D\x82ł\xAB\x82Ȃ\xA2\x91g\x82ݍ\x87\x82킹 + data->DropType = DROP_TYPE_PASTE_FILENAME; + data->DropTypePaste = data->DefaultDropTypePaste; + data->DoSameProcess = false; } else { - if (isSSH) { - DropType = DROP_TYPE_SCP; - } else { - DropType = DROP_TYPE_SEND_FILE; - } + data->DropType = data->DefaultDropType; + data->DropTypePaste = data->DefaultDropTypePaste; + data->DoSameProcess = (ShowDialog || data->DefaultShowDialog) ? false : true; } - DoSameProcess = false; } - } else { - if (DirectoryCount > 0 && - (DefaultDropType == DROP_TYPE_SEND_FILE || - 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; - DropTypePaste = DefaultDropTypePaste; - DoSameProcess = false; - } else { - DropType = DefaultDropType; - DropTypePaste = DefaultDropTypePaste; - DoSameProcess = (ShowDialog || DefaultShowDialog) ? false : true; + + data->SendIndex = 0; + // break; + // FALLTHROUGH + } + case 1: + next_file: { + if (data->SendIndex == DropListCount) { + // \x82\xB7\x82ׂđ\x97\x90M\x8A\xAE\x97\xB9 + goto finish; } - } - - for (int i = 0; i < DropListCount; i++) { + int i = data->SendIndex; + data->SendIndex++; const wchar_t *FileName = DropLists[i]; - if (!DoSameProcess) { + if (!data->DoSameProcess) { + const bool isSSH = (cv.isSSH == 2); bool DoSameProcessNextDrop; - bool DoNotShowDialog = !DefaultShowDialog; + bool DoNotShowDialog = !data->DefaultShowDialog; SetDialogFont(ts.DialogFontNameW, ts.DialogFontPoint, ts.DialogFontCharSet, ts.UILanguageFileW, "Tera Term", "DLG_SYSTEM_FONT"); - DropType = - ShowDropDialogBox(m_hInst, HVTWin, - FileName, DropType, + data->DropType = + ShowDropDialogBox(m_hInst, HVTWin, FileName, data->DropType, DropListCount - i, - (DirectoryCount == 0 && isSSH) ? true : false, - DirectoryCount == 0 ? true : false, - &TransBin, + (data->DirectoryCount == 0 && isSSH) ? true : false, data->DirectoryCount == 0 ? true : false, + &data->TransBin, &ts, - &DropTypePaste, - &DoSameProcess, + &data->DropTypePaste, &data->DoSameProcess, &DoSameProcessNextDrop, &DoNotShowDialog); - if (DropType == DROP_TYPE_CANCEL) { + if (data->DropType == DROP_TYPE_CANCEL) { goto finish; } if (DoSameProcessNextDrop) { - DefaultDropType = DropType; + data->DefaultDropType = data->DropType; } if (!ts.ConfirmFileDragAndDrop) { - DefaultShowDialog = !DoNotShowDialog; + data->DefaultShowDialog = !DoNotShowDialog; } } - switch (DropType) { + switch (data->DropType) { case DROP_TYPE_CANCEL: default: // cancel break; - case DROP_TYPE_SEND_FILE: - if (!TransBin) { - SendMemSendFile(FileName, FALSE, SENDMEM_DELAYTYPE_NO_DELAY, 0, 0); + case DROP_TYPE_SEND_FILE: { + if (!data->TransBin) { + SendMemSendFile2(FileName, FALSE, SENDMEM_DELAYTYPE_NO_DELAY, 0, 0, DropSendCallback, data); } else { - SendMemSendFile(FileName, TRUE, SENDMEM_DELAYTYPE_NO_DELAY, 0, 0); + SendMemSendFile2(FileName, TRUE, SENDMEM_DELAYTYPE_NO_DELAY, 0, 0, DropSendCallback, data); } break; + } case DROP_TYPE_PASTE_FILENAME: { - const bool escape = (DropTypePaste & DROP_TYPE_PASTE_ESCAPE) ? true : false; + const bool escape = (data->DropTypePaste & DROP_TYPE_PASTE_ESCAPE) ? true : false; - DefaultDropTypePaste = DropTypePaste; + data->DefaultDropTypePaste = data->DropTypePaste; TermSendStartBracket(); @@ -1745,7 +1806,7 @@ TermPasteStringNoBracket(str, wcslen(str)); free(str); if (DropListCount > 1 && i < DropListCount - 1) { - if (DropTypePaste & DROP_TYPE_PASTE_NEWLINE) { + if (data->DropTypePaste & DROP_TYPE_PASTE_NEWLINE) { TermPasteStringNoBracket(L"\x0d", 1); // \x89\xFC\x8Ds(CR,0x0d) } else { @@ -1755,7 +1816,8 @@ TermSendEndBracket(); - break; + // \x8E\x9F\x82̃t\x83@\x83C\x83\x8B\x82̏\x88\x97\x9D\x82\xD6 + goto next_file; } case DROP_TYPE_SCP: { @@ -1767,7 +1829,7 @@ else { // \x88ꊇ\x91\x97\x90M\x82̏ꍇ\x82̓^\x83C\x83}\x81[\x8F\x88\x97\x9D\x82\xF0\x8Ds\x82\xA4\x82\xB1\x82ƂŁA\x98A\x91\xB1\x91\x97\x90M\x82ɂ\xE6\x82\xE9 // \x83G\x83\x89\x81[\x82\xAA\x8BN\x82\xB1\x82\xE7\x82Ȃ\xA2\x82悤\x82ɂ\xB7\x82\xE9\x81B - if (DoSameProcess) { + if (data->DoSameProcess) { int j; DropListCountSendScp = DropListCount - i; @@ -1788,8 +1850,9 @@ if (!SendScp(FileNames, FileCount, ts.ScpSendDir)) { goto finish; } - i += FileCount - 1; - break; + + // \x8E\x9F\x82̃t\x83@\x83C\x83\x8B\x82̏\x88\x97\x9D\x82\xD6 + goto next_file; } } @@ -1796,9 +1859,15 @@ } } } + break; + case 2: + default: + finish: + // \x8FI\x97\xB9\x8F\x88\x97\x9D + DropListFree(); + break; + } -finish: - DropListFree(); return 0; }