From 0115029e5e14e12f895e910d4e9fd48129308c3e Mon Sep 17 00:00:00 2001 From: Matthew Kilgore Date: Mon, 7 Nov 2022 00:54:00 -0500 Subject: [PATCH 1/6] Implement InputBox using DialogBoxIndirect This removes the VBS based InputBox for Windows and replaces it with a version that uses DialogBoxIndirect to create the dialog. While it is a bit more complicated in some respects, it removes any concerns about the contents of the strings as they're no longer being inserted into the generated script. It also has the advantage that it doesn't spawn another process (which then shows up in the task bar in some situations). With this changes quote characters are allowed in all of the parameters. --- internal/c/parts/gui/tinyfiledialogs.c | 449 ++++++++++--------------- 1 file changed, 186 insertions(+), 263 deletions(-) diff --git a/internal/c/parts/gui/tinyfiledialogs.c b/internal/c/parts/gui/tinyfiledialogs.c index f713e8b98..55f1043fc 100644 --- a/internal/c/parts/gui/tinyfiledialogs.c +++ b/internal/c/parts/gui/tinyfiledialogs.c @@ -1190,13 +1190,13 @@ static LRESULT CALLBACK hiddenNotifyWindowProc(HWND hwnd, UINT message, WPARAM w return 0; } -static HWND notifyWindow = NULL; +static HWND hiddenWindow = NULL; static HICON notifyIcon = NULL; // Creates a hidden window to tie the Notifications too -static void setupNotifyHandles() +static void setupHiddenWindowHandles() { - if (notifyWindow || notifyIcon) + if (hiddenWindow || notifyIcon) return; WNDCLASSEX wndclass = { @@ -1217,7 +1217,7 @@ static void setupNotifyHandles() if (!RegisterClassEx(&wndclass)) return; - notifyWindow = CreateWindowEx( + hiddenWindow = CreateWindowEx( 0, "notifyIconClass", "title", @@ -1232,7 +1232,7 @@ static void setupNotifyHandles() 0 ); - if (!notifyWindow) + if (!hiddenWindow) return; // Attempt to load 32x32 image @@ -1254,7 +1254,7 @@ static void createWinNotificationEntry() memset(¬ificationData, 0, sizeof(notificationData)); notificationData.cbSize = sizeof(notificationData); - notificationData.hWnd = notifyWindow; + notificationData.hWnd = hiddenWindow; notificationData.uID = 0; notificationData.hIcon = notifyIcon; @@ -1269,7 +1269,7 @@ static void sendWinNotification(const wchar_t *title, const wchar_t *message, co NOTIFYICONDATAW notificationData; memset(¬ificationData, 0, sizeof(notificationData)); notificationData.cbSize = sizeof(notificationData); - notificationData.hWnd = notifyWindow; + notificationData.hWnd = hiddenWindow; notificationData.uID = 0; notificationData.hIcon = notifyIcon; @@ -1303,10 +1303,10 @@ int tinyfd_notifyPopupW( if (aTitle && !wcscmp(aTitle, L"tinyfd_query")) { strcpy(tinyfd_response, "windows_wchar"); return 1; } - setupNotifyHandles(); + setupHiddenWindowHandles(); // Can't send notification if the handles aren't setup - if (!notifyWindow || !notifyIcon) + if (!hiddenWindow || !notifyIcon) return 0; createWinNotificationEntry(); @@ -1315,6 +1315,175 @@ int tinyfd_notifyPopupW( return 1; } +#define ID_TEXT 200 + +static LPWORD lpwAlignDWORD(LPWORD lpIn) +{ + uintptr_t ul; + + ul = (uintptr_t)lpIn; + ul += 3; + ul >>= 2; + ul <<= 2; + return (LPWORD)ul; +} + +static char dialogContents[MAX_PATH_OR_CMD] = { 0 }; + +static BOOL CALLBACK dialogBoxCallback(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + BOOL fError; + + switch (message) + { + case WM_INITDIALOG: + // Allow a max of MAX_PATH_OR_CMD characters in the edit box + SendDlgItemMessage(hwndDlg, ID_TEXT, EM_LIMITTEXT, MAX_PATH_OR_CMD, 0); + return TRUE; + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDOK: + GetDlgItemText(hwndDlg, ID_TEXT, dialogContents, MAX_PATH_OR_CMD); + DestroyWindow(hwndDlg); + return TRUE; + + case IDCANCEL: + memset(dialogContents, 0, sizeof(dialogContents)); + DestroyWindow(hwndDlg); + return TRUE; + } + } + return FALSE; +} + +static LRESULT DisplayMyMessage(HINSTANCE hinst, HWND hwndOwner, const wchar_t *title, const wchar_t *lpszMessage, const wchar_t *defaultText) +{ + HGLOBAL hgbl; + LPDLGTEMPLATE lpdt; + LPDLGITEMTEMPLATE lpdit; + LPWORD lpw; + LPWSTR lpwsz; + LRESULT ret; + int nchar; + + // The extra 500 accounts for the default button text, alignment padding, and a few other small things + hgbl = GlobalAlloc(GMEM_ZEROINIT, sizeof(DLGTEMPLATE) + + sizeof(DLGITEMTEMPLATE) * 4 + + (wcslen(lpszMessage) + 1) * sizeof(wchar_t) + + (wcslen(title) + 1) * sizeof(wchar_t) + + (wcslen(defaultText) + 1) * sizeof(wchar_t) + + 500); + if (!hgbl) + return -1; + + lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl); + + // Define a dialog box. + + lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU | DS_MODALFRAME | WS_CAPTION | DS_SETFONT; + lpdt->cdit = 4; // Number of controls + lpdt->x = 0; lpdt->y = 0; + lpdt->cx = 200; lpdt->cy = 70; + + lpw = (LPWORD)(lpdt + 1); + *lpw++ = 0; // No menu + *lpw++ = 0; // Predefined dialog box class (by default) + + for (lpwsz = (LPWSTR)lpw; *lpwsz++ = *title++;); + lpw = (LPWORD)lpwsz; + + // Add font information + const wchar_t *font = L"Arial"; + + *lpw++ = 9; // Point size + for (lpwsz = (LPWSTR)lpw; *lpwsz++ = *font++;); // Font name + lpw = (LPWORD)lpwsz; + + //----------------------- + // Define an OK button. + //----------------------- + lpw = lpwAlignDWORD(lpw); // Align DLGITEMTEMPLATE on DWORD boundary + lpdit = (LPDLGITEMTEMPLATE)lpw; + lpdit->x = 160; lpdit->y = 6; + lpdit->cx = 35; lpdit->cy = 12; + lpdit->id = IDOK; // OK button identifier + lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON; + + lpw = (LPWORD)(lpdit + 1); + *lpw++ = 0xFFFF; + *lpw++ = 0x0080; // Button class + + lpwsz = (LPWSTR)lpw; + nchar = 1 + MultiByteToWideChar(CP_ACP, 0, "OK", -1, lpwsz, 50); + lpw += nchar; + *lpw++ = 0; // No creation data + + //----------------------- + // Define a Cancel button. + //----------------------- + lpw = lpwAlignDWORD(lpw); // Align DLGITEMTEMPLATE on DWORD boundary + lpdit = (LPDLGITEMTEMPLATE)lpw; + lpdit->x = 160; lpdit->y = 21; + lpdit->cx = 35; lpdit->cy = 12; + lpdit->id = IDCANCEL; // Cancel button identifier + lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON; + + lpw = (LPWORD)(lpdit + 1); + *lpw++ = 0xFFFF; + *lpw++ = 0x0080; // Button class atom + + lpwsz = (LPWSTR)lpw; + nchar = 1 + MultiByteToWideChar(CP_ACP, 0, "Cancel", -1, lpwsz, 50); + lpw += nchar; + *lpw++ = 0; // No creation data + + //----------------------- + // Define a edit text control. + //----------------------- + lpw = lpwAlignDWORD(lpw); // Align DLGITEMTEMPLATE on DWORD boundary + lpdit = (LPDLGITEMTEMPLATE)lpw; + lpdit->x = 5; lpdit->y = 53; + lpdit->cx = 190; lpdit->cy = 12; + lpdit->id = ID_TEXT; // Text identifier + lpdit->style = WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL | ES_LEFT; + + lpw = (LPWORD)(lpdit + 1); + *lpw++ = 0xFFFF; + *lpw++ = 0x0081; // Edit class + + for (lpwsz = (LPWSTR)lpw; *lpwsz++ = *defaultText++;); + lpw = (LPWORD)lpwsz; + *lpw++ = 0; // No creation data + + //----------------------- + // Define a static text control. + //----------------------- + lpw = lpwAlignDWORD(lpw); // Align DLGITEMTEMPLATE on DWORD boundary + lpdit = (LPDLGITEMTEMPLATE)lpw; + lpdit->x = 5; lpdit->y = 5; + lpdit->cx = 150; lpdit->cy = 40; + lpdit->id = ID_TEXT; // Text identifier + lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT; + + lpw = (LPWORD)(lpdit + 1); + *lpw++ = 0xFFFF; + *lpw++ = 0x0082; // Static class + + for (lpwsz = (LPWSTR)lpw; *lpwsz++ = *lpszMessage++;); + lpw = (LPWORD)lpwsz; + *lpw++ = 0; // No creation data + + // Display the dialog + GlobalUnlock(hgbl); + ret = DialogBoxIndirect(hinst, + (LPDLGTEMPLATE)hgbl, + hwndOwner, + (DLGPROC)dialogBoxCallback); + GlobalFree(hgbl); + return ret; +} wchar_t * tinyfd_inputBoxW( wchar_t const * aTitle, /* NULL or L"" */ @@ -1332,265 +1501,19 @@ wchar_t * tinyfd_inputBoxW( if (aTitle&&!wcscmp(aTitle, L"tinyfd_query")){ strcpy(tinyfd_response, "windows_wchar"); return (wchar_t *)1; } - if (quoteDetectedW(aTitle)) return tinyfd_inputBoxW(L"INVALID TITLE WITH QUOTES", aMessage, aDefaultInput); - if (quoteDetectedW(aMessage)) return tinyfd_inputBoxW(aTitle, L"INVALID MESSAGE WITH QUOTES", aDefaultInput); - if (quoteDetectedW(aDefaultInput)) return tinyfd_inputBoxW(aTitle, aMessage, L"INVALID DEFAULT_INPUT WITH QUOTES"); + memset(dialogContents, 0, sizeof(dialogContents)); - lTitleLen = aTitle ? wcslen(aTitle) : 0 ; - lMessageLen = aMessage ? wcslen(aMessage) : 0 ; - lDialogStringLen = 3 * MAX_PATH_OR_CMD + lTitleLen + lMessageLen; - lDialogString = (wchar_t *)malloc(2 * lDialogStringLen); + aTitle = aTitle? aTitle: L""; + aMessage = aMessage? aMessage: L""; + aDefaultInput = aDefaultInput? aDefaultInput: L""; - if (aDefaultInput) - { - swprintf(lDialogString, -#if !defined(__BORLANDC__) && !defined(__TINYC__) && !(defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)) - lDialogStringLen, -#endif - L"%ls\\tinyfd.vbs", _wgetenv(L"TEMP")); - } - else - { - swprintf(lDialogString, -#if !defined(__BORLANDC__) && !defined(__TINYC__) && !(defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)) - lDialogStringLen, -#endif - L"%ls\\tinyfd.hta", _wgetenv(L"TEMP")); - } - lIn = _wfopen(lDialogString, L"w"); - if (!lIn) - { - free(lDialogString); - return NULL; - } + setupHiddenWindowHandles(); + DisplayMyMessage(GetModuleHandle(NULL), hiddenWindow, aTitle, aMessage, aDefaultInput); - if ( aDefaultInput ) - { - wcscpy(lDialogString, L"Dim result:result=InputBox(\""); - if (aMessage && wcslen(aMessage)) - { - wcscpy(lBuff, aMessage); - replaceWchar(lBuff, L'\n', L' '); - wcscat(lDialogString, lBuff); - } - wcscat(lDialogString, L"\",\"tinyfiledialogsTopWindow\",\""); - if (aDefaultInput && wcslen(aDefaultInput)) - { - wcscpy(lBuff, aDefaultInput); - replaceWchar(lBuff, L'\n', L' '); - wcscat(lDialogString, lBuff); - } - wcscat(lDialogString, L"\"):If IsEmpty(result) then:WScript.Echo 0"); - wcscat(lDialogString, L":Else: WScript.Echo \"1\" & result : End If"); - } - else - { - wcscpy(lDialogString, L"\n\ -\n\ -\n\ -"); - - wcscat(lDialogString, L"tinyfiledialogsTopWindow"); - wcscat(lDialogString, L"\n\ -\n\ -\n\ -\n\ -\n\ -\n\ -\n\ -\n\ -\n\ -\n\ -\n\ -
\n"); - - wcscat(lDialogString, aMessage ? aMessage : L""); - - wcscat(lDialogString, L"\n\ -\n\ -\n\ -\n\ -
\n\ -

\n\ -\n\ -
\n\ -
\n"); - - wcscat(lDialogString, L"\n\ -\n\ -\n\ -\n\ -
\n\ -
\n\ -
\n\ -\n\ -\n\ -" ) ; - } - fputws(lDialogString, lIn); - fclose(lIn); - - if (aDefaultInput) - { - swprintf(lDialogString, -#if !defined(__BORLANDC__) && !defined(__TINYC__) && !(defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)) - lDialogStringLen, -#endif - L"%ls\\tinyfd.txt",_wgetenv(L"TEMP")); - -#ifdef TINYFD_NOCCSUNICODE - lFile = _wfopen(lDialogString, L"w"); - fputc(0xFF, lFile); - fputc(0xFE, lFile); -#else - lFile = _wfopen(lDialogString, L"wt, ccs=UNICODE"); /*or ccs=UTF-16LE*/ -#endif - fclose(lFile); - - wcscpy(lDialogString, L"cmd.exe /c cscript.exe //U //Nologo "); - wcscat(lDialogString, L"\"%TEMP%\\tinyfd.vbs\" "); - wcscat(lDialogString, L">> \"%TEMP%\\tinyfd.txt\""); - } - else - { - wcscpy(lDialogString, - L"cmd.exe /c mshta.exe \"%TEMP%\\tinyfd.hta\""); - } - - /* wprintf ( "lDialogString: %ls\n" , lDialogString ) ; */ - - hiddenConsoleW(lDialogString, aTitle, 1); - - swprintf(lDialogString, -#if !defined(__BORLANDC__) && !defined(__TINYC__) && !(defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)) - lDialogStringLen, -#endif - L"%ls\\tinyfd.txt", _wgetenv(L"TEMP")); - /* wprintf(L"lDialogString: %ls\n", lDialogString); */ -#ifdef TINYFD_NOCCSUNICODE - if (!(lIn = _wfopen(lDialogString, L"r"))) -#else - if (!(lIn = _wfopen(lDialogString, L"rt, ccs=UNICODE"))) /*or ccs=UTF-16LE*/ -#endif - { - _wremove(lDialogString); - free(lDialogString); - return NULL; - } - - memset(lBuff, 0, MAX_PATH_OR_CMD * sizeof(wchar_t) ); - -#ifdef TINYFD_NOCCSUNICODE - fgets((char *)lBuff, 2*MAX_PATH_OR_CMD, lIn); -#else - fgetws(lBuff, MAX_PATH_OR_CMD, lIn); -#endif - fclose(lIn); - wipefileW(lDialogString); - _wremove(lDialogString); - - if (aDefaultInput) - { - swprintf(lDialogString, -#if !defined(__BORLANDC__) && !defined(__TINYC__) && !(defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)) - lDialogStringLen, -#endif - L"%ls\\tinyfd.vbs", _wgetenv(L"TEMP")); - } - else - { - swprintf(lDialogString, -#if !defined(__BORLANDC__) && !defined(__TINYC__) && !(defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)) - lDialogStringLen, -#endif - L"%ls\\tinyfd.hta", _wgetenv(L"TEMP")); - } - _wremove(lDialogString); - free(lDialogString); - /* wprintf( L"lBuff: %ls\n" , lBuff ) ; */ -#ifdef TINYFD_NOCCSUNICODE - lResult = !wcsncmp(lBuff+1, L"1", 1); -#else - lResult = !wcsncmp(lBuff, L"1", 1); -#endif - - /* printf( "lResult: %d \n" , lResult ) ; */ - if (!lResult) - { - return NULL ; - } - - /* wprintf( "lBuff+1: %ls\n" , lBuff+1 ) ; */ - -#ifdef TINYFD_NOCCSUNICODE - if (aDefaultInput) - { - lDialogStringLen = wcslen(lBuff) ; - lBuff[lDialogStringLen - 1] = L'\0'; - lBuff[lDialogStringLen - 2] = L'\0'; - } - return lBuff + 2; -#else - if (aDefaultInput) lBuff[wcslen(lBuff) - 1] = L'\0'; - return lBuff + 1; -#endif + mbstowcs(lBuff, dialogContents, MAX_PATH_OR_CMD); + return lBuff; } - wchar_t * tinyfd_saveFileDialogW( wchar_t const * aTitle, /* NULL or "" */ wchar_t const * aDefaultPathAndFile, /* NULL or "" */ From ec0ec106524df572fd6d391b6fc0738daa5f1622 Mon Sep 17 00:00:00 2001 From: Matthew Kilgore Date: Mon, 7 Nov 2022 00:57:53 -0500 Subject: [PATCH 2/6] Add missing static to char array in tinyfd_openFileDialog Fairly simple, lBuff is used to return the resulting filename and has to be static so that it's still valid when the function exits. --- internal/c/parts/gui/tinyfiledialogs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/c/parts/gui/tinyfiledialogs.c b/internal/c/parts/gui/tinyfiledialogs.c index 55f1043fc..d3a8d5b10 100644 --- a/internal/c/parts/gui/tinyfiledialogs.c +++ b/internal/c/parts/gui/tinyfiledialogs.c @@ -3078,8 +3078,8 @@ char * tinyfd_openFileDialog( char const * aSingleFilterDescription, /* NULL or "image files" */ int aAllowMultipleSelects ) /* 0 or 1 */ { + static char lBuff[MAX_PATH_OR_CMD]; char lString[MAX_PATH_OR_CMD]; - char lBuff[MAX_PATH_OR_CMD]; char * p; char * lPointerInputBox; int i; From ee9f8e4404325c0325aa42dc8b24b457b57b9946 Mon Sep 17 00:00:00 2001 From: Matthew Kilgore Date: Mon, 7 Nov 2022 01:04:36 -0500 Subject: [PATCH 3/6] Remove quote checks on Windows These are the last of the quote checks, these don't require any associated changes as the underlying Win32 functions already allow quotes. They were simply added to keep parity with the functionality on other platforms, that that has since been fixed. --- internal/c/parts/gui/tinyfiledialogs.c | 55 -------------------------- 1 file changed, 55 deletions(-) diff --git a/internal/c/parts/gui/tinyfiledialogs.c b/internal/c/parts/gui/tinyfiledialogs.c index d3a8d5b10..5c90a310a 100644 --- a/internal/c/parts/gui/tinyfiledialogs.c +++ b/internal/c/parts/gui/tinyfiledialogs.c @@ -1100,9 +1100,6 @@ int tinyfd_messageBoxW( if (aTitle&&!wcscmp(aTitle, L"tinyfd_query")){ strcpy(tinyfd_response, "windows_wchar"); return 1; } - if (quoteDetectedW(aTitle)) return tinyfd_messageBoxW(L"INVALID TITLE WITH QUOTES", aMessage, aDialogType, aIconType, aDefaultButton); - if (quoteDetectedW(aMessage)) return tinyfd_messageBoxW(aTitle, L"INVALID MESSAGE WITH QUOTES", aDialogType, aIconType, aDefaultButton); - if (aIconType && !wcscmp(L"warning", aIconType)) { aCode = MB_ICONWARNING; @@ -1534,14 +1531,6 @@ wchar_t * tinyfd_saveFileDialogW( if (aTitle&&!wcscmp(aTitle, L"tinyfd_query")){ strcpy(tinyfd_response, "windows_wchar"); return (wchar_t *)1; } - if (quoteDetectedW(aTitle)) return tinyfd_saveFileDialogW(L"INVALID TITLE WITH QUOTES", aDefaultPathAndFile, aNumOfFilterPatterns, aFilterPatterns, aSingleFilterDescription); - if (quoteDetectedW(aDefaultPathAndFile)) return tinyfd_saveFileDialogW(aTitle, L"INVALID DEFAULT_PATH WITH QUOTES", aNumOfFilterPatterns, aFilterPatterns, aSingleFilterDescription); - if (quoteDetectedW(aSingleFilterDescription)) return tinyfd_saveFileDialogW(aTitle, aDefaultPathAndFile, aNumOfFilterPatterns, aFilterPatterns, L"INVALID FILTER_DESCRIPTION WITH QUOTES"); - for (i = 0; i < aNumOfFilterPatterns; i++) - { - if (quoteDetectedW(aFilterPatterns[i])) return tinyfd_saveFileDialogW(L"INVALID FILTER_PATTERN WITH QUOTES", aDefaultPathAndFile, 0, NULL, NULL); - } - lHResult = CoInitializeEx(NULL, 0); getPathWithoutFinalSlashW(lDirname, aDefaultPathAndFile); @@ -1643,14 +1632,6 @@ wchar_t * tinyfd_openFileDialogW( if (aTitle&&!wcscmp(aTitle, L"tinyfd_query")){ strcpy(tinyfd_response, "windows_wchar"); return (wchar_t *)1; } - if (quoteDetectedW(aTitle)) return tinyfd_openFileDialogW(L"INVALID TITLE WITH QUOTES", aDefaultPathAndFile, aNumOfFilterPatterns, aFilterPatterns, aSingleFilterDescription, aAllowMultipleSelects); - if (quoteDetectedW(aDefaultPathAndFile)) return tinyfd_openFileDialogW(aTitle, L"INVALID DEFAULT_PATH WITH QUOTES", aNumOfFilterPatterns, aFilterPatterns, aSingleFilterDescription, aAllowMultipleSelects); - if (quoteDetectedW(aSingleFilterDescription)) return tinyfd_openFileDialogW(aTitle, aDefaultPathAndFile, aNumOfFilterPatterns, aFilterPatterns, L"INVALID FILTER_DESCRIPTION WITH QUOTES", aAllowMultipleSelects); - for (i = 0; i < aNumOfFilterPatterns; i++) - { - if (quoteDetectedW(aFilterPatterns[i])) return tinyfd_openFileDialogW(L"INVALID FILTER_PATTERN WITH QUOTES", aDefaultPathAndFile, 0, NULL, NULL, aAllowMultipleSelects); - } - if (aAllowMultipleSelects) { lFullBuffLen = MAX_MULTIPLE_FILES * MAX_PATH_OR_CMD + 1; @@ -1820,9 +1801,6 @@ wchar_t * tinyfd_selectFolderDialogW( if (aTitle&&!wcscmp(aTitle, L"tinyfd_query")){ strcpy(tinyfd_response, "windows_wchar"); return (wchar_t *)1; } - if (quoteDetectedW(aTitle)) return tinyfd_selectFolderDialogW(L"INVALID TITLE WITH QUOTES", aDefaultPath); - if (quoteDetectedW(aDefaultPath)) return tinyfd_selectFolderDialogW(aTitle, L"INVALID DEFAULT_PATH WITH QUOTES"); - lHResult = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); bInfo.hwndOwner = GetForegroundWindow(); @@ -1872,9 +1850,6 @@ wchar_t * tinyfd_colorChooserW( if (aTitle&&!wcscmp(aTitle, L"tinyfd_query")){ strcpy(tinyfd_response, "windows_wchar"); return (wchar_t *)1; } - if (quoteDetectedW(aTitle)) return tinyfd_colorChooserW(L"INVALID TITLE WITH QUOTES", aDefaultHexRGB, aDefaultRGB, aoResultRGB); - if (quoteDetectedW(aDefaultHexRGB)) return tinyfd_colorChooserW(aTitle, L"INVALID DEFAULT_HEX_RGB WITH QUOTES", aDefaultRGB, aoResultRGB); - lHResult = CoInitializeEx(NULL, 0); if ( aDefaultHexRGB ) @@ -2734,9 +2709,6 @@ int tinyfd_messageBox( UINT lOriginalCP = 0; UINT lOriginalOutputCP = 0; - if (tfd_quoteDetected(aTitle)) return tinyfd_messageBox("INVALID TITLE WITH QUOTES", aMessage, aDialogType, aIconType, aDefaultButton); - if (tfd_quoteDetected(aMessage)) return tinyfd_messageBox(aTitle, "INVALID MESSAGE WITH QUOTES", aDialogType, aIconType, aDefaultButton); - if ((!tinyfd_forceConsole || !(GetConsoleWindow() || dialogPresent())) && (!getenv("SSH_CLIENT") || getenvDISPLAY())) { @@ -2884,10 +2856,6 @@ char * tinyfd_inputBox( if (!aTitle && !aMessage && !aDefaultInput) return lBuff; /* now I can fill lBuff from outside */ - if (tfd_quoteDetected(aTitle)) return tinyfd_inputBox("INVALID TITLE WITH QUOTES", aMessage, aDefaultInput); - if (tfd_quoteDetected(aMessage)) return tinyfd_inputBox(aTitle, "INVALID MESSAGE WITH QUOTES", aDefaultInput); - if (tfd_quoteDetected(aDefaultInput)) return tinyfd_inputBox(aTitle, aMessage, "INVALID DEFAULT_INPUT WITH QUOTES"); - mode = 0; hStdin = GetStdHandle(STD_INPUT_HANDLE); @@ -3016,15 +2984,6 @@ char * tinyfd_saveFileDialog( lBuff[0]='\0'; - if (tfd_quoteDetected(aTitle)) return tinyfd_saveFileDialog("INVALID TITLE WITH QUOTES", aDefaultPathAndFile, aNumOfFilterPatterns, aFilterPatterns, aSingleFilterDescription); - if (tfd_quoteDetected(aDefaultPathAndFile)) return tinyfd_saveFileDialog(aTitle, "INVALID DEFAULT_PATH WITH QUOTES", aNumOfFilterPatterns, aFilterPatterns, aSingleFilterDescription); - if (tfd_quoteDetected(aSingleFilterDescription)) return tinyfd_saveFileDialog(aTitle, aDefaultPathAndFile, aNumOfFilterPatterns, aFilterPatterns, "INVALID FILTER_DESCRIPTION WITH QUOTES"); - for (i = 0; i < aNumOfFilterPatterns; i++) - { - if (tfd_quoteDetected(aFilterPatterns[i])) return tinyfd_saveFileDialog("INVALID FILTER_PATTERN WITH QUOTES", aDefaultPathAndFile, 0, NULL, NULL); - } - - if ( ( !tinyfd_forceConsole || !( GetConsoleWindow() || dialogPresent() ) ) && (!getenv("SSH_CLIENT") || getenvDISPLAY())) { @@ -3084,14 +3043,6 @@ char * tinyfd_openFileDialog( char * lPointerInputBox; int i; - if (tfd_quoteDetected(aTitle)) return tinyfd_openFileDialog("INVALID TITLE WITH QUOTES", aDefaultPathAndFile, aNumOfFilterPatterns, aFilterPatterns, aSingleFilterDescription, aAllowMultipleSelects); - if (tfd_quoteDetected(aDefaultPathAndFile)) return tinyfd_openFileDialog(aTitle, "INVALID DEFAULT_PATH WITH QUOTES", aNumOfFilterPatterns, aFilterPatterns, aSingleFilterDescription, aAllowMultipleSelects); - if (tfd_quoteDetected(aSingleFilterDescription)) return tinyfd_openFileDialog(aTitle, aDefaultPathAndFile, aNumOfFilterPatterns, aFilterPatterns, "INVALID FILTER_DESCRIPTION WITH QUOTES", aAllowMultipleSelects); - for (i = 0; i < aNumOfFilterPatterns; i++) - { - if (tfd_quoteDetected(aFilterPatterns[i])) return tinyfd_openFileDialog("INVALID FILTER_PATTERN WITH QUOTES", aDefaultPathAndFile, 0, NULL, NULL, aAllowMultipleSelects); - } - if ( ( !tinyfd_forceConsole || !( GetConsoleWindow() || dialogPresent() ) ) && (!getenv("SSH_CLIENT") || getenvDISPLAY())) { @@ -3143,9 +3094,6 @@ char * tinyfd_selectFolderDialog( char * lPointerInputBox; char lString[MAX_PATH_OR_CMD]; - if (tfd_quoteDetected(aTitle)) return tinyfd_selectFolderDialog("INVALID TITLE WITH QUOTES", aDefaultPath); - if (tfd_quoteDetected(aDefaultPath)) return tinyfd_selectFolderDialog(aTitle, "INVALID DEFAULT_PATH WITH QUOTES"); - if ( ( !tinyfd_forceConsole || !( GetConsoleWindow() || dialogPresent() ) ) && (!getenv("SSH_CLIENT") || getenvDISPLAY())) { @@ -3197,9 +3145,6 @@ char * tinyfd_colorChooser( lDefaultHexRGB[0] = '\0'; - if (tfd_quoteDetected(aTitle)) return tinyfd_colorChooser("INVALID TITLE WITH QUOTES", aDefaultHexRGB, aDefaultRGB, aoResultRGB); - if (tfd_quoteDetected(aDefaultHexRGB)) return tinyfd_colorChooser(aTitle, "INVALID DEFAULT_HEX_RGB WITH QUOTES", aDefaultRGB, aoResultRGB); - if ( (!tinyfd_forceConsole || !( GetConsoleWindow() || dialogPresent()) ) && (!getenv("SSH_CLIENT") || getenvDISPLAY())) { From 7bf68383d52ea4d0fe8567da402d758a2e270e7f Mon Sep 17 00:00:00 2001 From: Matthew Kilgore Date: Mon, 7 Nov 2022 01:12:49 -0500 Subject: [PATCH 4/6] Fix warnings, remove unused code in tinyfiledialogs.c --- internal/c/parts/gui/tinyfiledialogs.c | 131 +------------------------ 1 file changed, 4 insertions(+), 127 deletions(-) diff --git a/internal/c/parts/gui/tinyfiledialogs.c b/internal/c/parts/gui/tinyfiledialogs.c index 5c90a310a..e04642b9c 100644 --- a/internal/c/parts/gui/tinyfiledialogs.c +++ b/internal/c/parts/gui/tinyfiledialogs.c @@ -712,31 +712,6 @@ void tinyfd_beep(void) else MessageBeep(MB_OK); } - -static void wipefileW(wchar_t const * aFilename) -{ - int i; - FILE * lIn; -#if defined(__MINGW32_MAJOR_VERSION) && !defined(__MINGW64__) && (__MINGW32_MAJOR_VERSION <= 3) - struct _stat st; - if (_wstat(aFilename, &st) == 0) -#else - struct __stat64 st; - if (_wstat64(aFilename, &st) == 0) -#endif - { - if ((lIn = _wfopen(aFilename, L"w"))) - { - for (i = 0; i < st.st_size; i++) - { - fputc('A', lIn); - } - fclose(lIn); - } - } -} - - static wchar_t * getPathWithoutFinalSlashW( wchar_t * aoDestination, /* make sure it is allocated, use _MAX_PATH */ wchar_t const * aSource) /* aoDestination and aSource can be the same */ @@ -943,56 +918,6 @@ static int fileExists(char const * aFilePathAndName) } } -static void replaceWchar(wchar_t * aString, - wchar_t aOldChr, - wchar_t aNewChr) -{ - wchar_t * p; - - if (!aString) - { - return ; - } - - if (aOldChr == aNewChr) - { - return ; - } - - p = aString; - while ((p = wcsrchr(p, aOldChr))) - { - *p = aNewChr; -#ifdef TINYFD_NOCCSUNICODE - p++; -#endif - p++; - } - return ; -} - - -static int quoteDetectedW(wchar_t const * aString) -{ - wchar_t const * p; - - if (!aString) return 0; - - p = aString; - while ((p = wcsrchr(p, L'\''))) - { - return 1; - } - - p = aString; - while ((p = wcsrchr(p, L'\"'))) - { - return 1; - } - - return 0; -} - #endif /* _WIN32 */ /* source and destination can be the same or ovelap*/ @@ -1056,38 +981,6 @@ static int __stdcall EnumThreadWndProc(HWND hwnd, LPARAM lParam) return 1; } - -static void hiddenConsoleW(wchar_t const * aString, wchar_t const * aDialogTitle, int aInFront) -{ - STARTUPINFOW StartupInfo; - PROCESS_INFORMATION ProcessInfo; - - if (!aString || !wcslen(aString) ) return; - - memset(&StartupInfo, 0, sizeof(StartupInfo)); - StartupInfo.cb = sizeof(STARTUPINFOW); - StartupInfo.dwFlags = STARTF_USESHOWWINDOW; - StartupInfo.wShowWindow = SW_HIDE; - - if (!CreateProcessW(NULL, (LPWSTR)aString, NULL, NULL, FALSE, - CREATE_NEW_CONSOLE, NULL, NULL, - &StartupInfo, &ProcessInfo)) - { - return; /* GetLastError(); */ - } - - WaitForInputIdle(ProcessInfo.hProcess, INFINITE); - if (aInFront) - { - while (EnumWindows(EnumThreadWndProc, (LPARAM)NULL)) {} - SetWindowTextW(GetForegroundWindow(), aDialogTitle); - } - WaitForSingleObject(ProcessInfo.hProcess, INFINITE); - CloseHandle(ProcessInfo.hThread); - CloseHandle(ProcessInfo.hProcess); -} - - int tinyfd_messageBoxW( wchar_t const * aTitle, /* NULL or "" */ wchar_t const * aMessage, /* NULL or "" may contain \n and \t */ @@ -1293,11 +1186,6 @@ int tinyfd_notifyPopupW( wchar_t const * aMessage, /* NULL or L"" may contain \n \t */ wchar_t const * aIconType) /* L"info" L"warning" L"error" */ { - wchar_t * lDialogString; - size_t lTitleLen; - size_t lMessageLen; - size_t lDialogStringLen; - if (aTitle && !wcscmp(aTitle, L"tinyfd_query")) { strcpy(tinyfd_response, "windows_wchar"); return 1; } setupHiddenWindowHandles(); @@ -1329,8 +1217,6 @@ static char dialogContents[MAX_PATH_OR_CMD] = { 0 }; static BOOL CALLBACK dialogBoxCallback(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam) { - BOOL fError; - switch (message) { case WM_INITDIALOG: @@ -1388,14 +1274,14 @@ static LRESULT DisplayMyMessage(HINSTANCE hinst, HWND hwndOwner, const wchar_t * *lpw++ = 0; // No menu *lpw++ = 0; // Predefined dialog box class (by default) - for (lpwsz = (LPWSTR)lpw; *lpwsz++ = *title++;); + for (lpwsz = (LPWSTR)lpw; (*lpwsz++) = *title++;); lpw = (LPWORD)lpwsz; // Add font information const wchar_t *font = L"Arial"; *lpw++ = 9; // Point size - for (lpwsz = (LPWSTR)lpw; *lpwsz++ = *font++;); // Font name + for (lpwsz = (LPWSTR)lpw; (*lpwsz++) = *font++;); // Font name lpw = (LPWORD)lpwsz; //----------------------- @@ -1450,7 +1336,7 @@ static LRESULT DisplayMyMessage(HINSTANCE hinst, HWND hwndOwner, const wchar_t * *lpw++ = 0xFFFF; *lpw++ = 0x0081; // Edit class - for (lpwsz = (LPWSTR)lpw; *lpwsz++ = *defaultText++;); + for (lpwsz = (LPWSTR)lpw; (*lpwsz++) = *defaultText++;); lpw = (LPWORD)lpwsz; *lpw++ = 0; // No creation data @@ -1468,7 +1354,7 @@ static LRESULT DisplayMyMessage(HINSTANCE hinst, HWND hwndOwner, const wchar_t * *lpw++ = 0xFFFF; *lpw++ = 0x0082; // Static class - for (lpwsz = (LPWSTR)lpw; *lpwsz++ = *lpszMessage++;); + for (lpwsz = (LPWSTR)lpw; (*lpwsz++) = *lpszMessage++;); lpw = (LPWORD)lpwsz; *lpw++ = 0; // No creation data @@ -1488,13 +1374,6 @@ wchar_t * tinyfd_inputBoxW( wchar_t const * aDefaultInput) /* L"" , if NULL it's a passwordBox */ { static wchar_t lBuff[MAX_PATH_OR_CMD]; - wchar_t * lDialogString; - FILE * lIn; - FILE * lFile; - int lResult; - size_t lTitleLen; - size_t lMessageLen; - size_t lDialogStringLen; if (aTitle&&!wcscmp(aTitle, L"tinyfd_query")){ strcpy(tinyfd_response, "windows_wchar"); return (wchar_t *)1; } @@ -2980,7 +2859,6 @@ char * tinyfd_saveFileDialog( char lString[MAX_PATH_OR_CMD] ; char * p ; char * lPointerInputBox; - int i; lBuff[0]='\0'; @@ -3041,7 +2919,6 @@ char * tinyfd_openFileDialog( char lString[MAX_PATH_OR_CMD]; char * p; char * lPointerInputBox; - int i; if ( ( !tinyfd_forceConsole || !( GetConsoleWindow() || dialogPresent() ) ) && (!getenv("SSH_CLIENT") || getenvDISPLAY())) From 5b238467a9ef5da5e752686fa7d3cbc4d2d855db Mon Sep 17 00:00:00 2001 From: Matthew Kilgore Date: Mon, 7 Nov 2022 20:58:58 -0500 Subject: [PATCH 5/6] Use hidden input if defaultText is blank Fairly simple, this sets the ES_PASSWORD flag when the default text is blank. Additionally I fixed the dialog callback to correctly call EndDialog() rather than DestroyWindow(). --- internal/c/parts/gui/tinyfiledialogs.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/internal/c/parts/gui/tinyfiledialogs.c b/internal/c/parts/gui/tinyfiledialogs.c index e04642b9c..183aed5df 100644 --- a/internal/c/parts/gui/tinyfiledialogs.c +++ b/internal/c/parts/gui/tinyfiledialogs.c @@ -1229,12 +1229,12 @@ static BOOL CALLBACK dialogBoxCallback(HWND hwndDlg, UINT message, WPARAM wParam { case IDOK: GetDlgItemText(hwndDlg, ID_TEXT, dialogContents, MAX_PATH_OR_CMD); - DestroyWindow(hwndDlg); + EndDialog(hwndDlg, 0); return TRUE; case IDCANCEL: memset(dialogContents, 0, sizeof(dialogContents)); - DestroyWindow(hwndDlg); + EndDialog(hwndDlg, 0); return TRUE; } } @@ -1332,6 +1332,9 @@ static LRESULT DisplayMyMessage(HINSTANCE hinst, HWND hwndOwner, const wchar_t * lpdit->id = ID_TEXT; // Text identifier lpdit->style = WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL | ES_LEFT; + if (wcslen(defaultText) == 0) + lpdit->style |= ES_PASSWORD; + lpw = (LPWORD)(lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0081; // Edit class From 90b3bd2662b2465096702b0f48a522e5f6026d97 Mon Sep 17 00:00:00 2001 From: Matthew Kilgore Date: Mon, 7 Nov 2022 21:52:45 -0500 Subject: [PATCH 6/6] Address build warnings on tinyfiledialogs.c A function was made unnecessary but wasn't removed, triggering a warning. Additionally gcc likes parenthesis around `=` assignments used for conditions. --- internal/c/parts/gui/tinyfiledialogs.c | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/internal/c/parts/gui/tinyfiledialogs.c b/internal/c/parts/gui/tinyfiledialogs.c index 183aed5df..df5456ea2 100644 --- a/internal/c/parts/gui/tinyfiledialogs.c +++ b/internal/c/parts/gui/tinyfiledialogs.c @@ -968,19 +968,6 @@ static char * ensureFilesExist(char * aDestination, #ifdef _WIN32 -static int __stdcall EnumThreadWndProc(HWND hwnd, LPARAM lParam) -{ - wchar_t lTitleName[MAX_PATH]; - GetWindowTextW(hwnd, lTitleName, MAX_PATH); - /* wprintf(L"lTitleName %ls \n", lTitleName); */ - if (wcscmp(L"tinyfiledialogsTopWindow", lTitleName) == 0) - { - SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); - return 0; - } - return 1; -} - int tinyfd_messageBoxW( wchar_t const * aTitle, /* NULL or "" */ wchar_t const * aMessage, /* NULL or "" may contain \n and \t */ @@ -1274,14 +1261,14 @@ static LRESULT DisplayMyMessage(HINSTANCE hinst, HWND hwndOwner, const wchar_t * *lpw++ = 0; // No menu *lpw++ = 0; // Predefined dialog box class (by default) - for (lpwsz = (LPWSTR)lpw; (*lpwsz++) = *title++;); + for (lpwsz = (LPWSTR)lpw; ((*lpwsz++) = *title++);); lpw = (LPWORD)lpwsz; // Add font information const wchar_t *font = L"Arial"; *lpw++ = 9; // Point size - for (lpwsz = (LPWSTR)lpw; (*lpwsz++) = *font++;); // Font name + for (lpwsz = (LPWSTR)lpw; ((*lpwsz++) = *font++);); // Font name lpw = (LPWORD)lpwsz; //----------------------- @@ -1339,7 +1326,7 @@ static LRESULT DisplayMyMessage(HINSTANCE hinst, HWND hwndOwner, const wchar_t * *lpw++ = 0xFFFF; *lpw++ = 0x0081; // Edit class - for (lpwsz = (LPWSTR)lpw; (*lpwsz++) = *defaultText++;); + for (lpwsz = (LPWSTR)lpw; ((*lpwsz++) = *defaultText++);); lpw = (LPWORD)lpwsz; *lpw++ = 0; // No creation data @@ -1357,7 +1344,7 @@ static LRESULT DisplayMyMessage(HINSTANCE hinst, HWND hwndOwner, const wchar_t * *lpw++ = 0xFFFF; *lpw++ = 0x0082; // Static class - for (lpwsz = (LPWSTR)lpw; (*lpwsz++) = *lpszMessage++;); + for (lpwsz = (LPWSTR)lpw; ((*lpwsz++) = *lpszMessage++);); lpw = (LPWORD)lpwsz; *lpw++ = 0; // No creation data