diff --git a/internal/c/parts/gui/tinyfiledialogs.c b/internal/c/parts/gui/tinyfiledialogs.c index f713e8b98..df5456ea2 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*/ @@ -1043,51 +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; -} - - -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 */ @@ -1100,9 +980,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; @@ -1190,13 +1067,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 +1094,7 @@ static void setupNotifyHandles() if (!RegisterClassEx(&wndclass)) return; - notifyWindow = CreateWindowEx( + hiddenWindow = CreateWindowEx( 0, "notifyIconClass", "title", @@ -1232,7 +1109,7 @@ static void setupNotifyHandles() 0 ); - if (!notifyWindow) + if (!hiddenWindow) return; // Attempt to load 32x32 image @@ -1254,7 +1131,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 +1146,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; @@ -1296,17 +1173,12 @@ 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; } - setupNotifyHandles(); + setupHiddenWindowHandles(); // Can't send notification if the handles aren't setup - if (!notifyWindow || !notifyIcon) + if (!hiddenWindow || !notifyIcon) return 0; createWinNotificationEntry(); @@ -1315,6 +1187,176 @@ 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) +{ + 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); + EndDialog(hwndDlg, 0); + return TRUE; + + case IDCANCEL: + memset(dialogContents, 0, sizeof(dialogContents)); + EndDialog(hwndDlg, 0); + 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; + + if (wcslen(defaultText) == 0) + lpdit->style |= ES_PASSWORD; + + 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"" */ @@ -1322,275 +1364,22 @@ 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; } - 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\ -\n"); - - wcscat(lDialogString, aMessage ? aMessage : L""); - - wcscat(lDialogString, L"\n\ - | \n\ -\n\
- | \n\
-
\n\
- \n\ - | \n\
-