Files
wine-access/tests/notepad_fixture.c

119 lines
4.3 KiB
C

// SPDX-License-Identifier: LGPL-2.1-or-later
// Drive Wine's actual Notepad; the standard-control fixture covers edge cases.
#include <windows.h>
#include <stdio.h>
static DWORD notepad_pid;
static HWND notepad;
static HWND saveDialog;
static BOOL CALLBACK find_save_dialog(HWND window, LPARAM unused) {
(void)unused;
DWORD pid;
GetWindowThreadProcessId(window, &pid);
if (pid == notepad_pid && IsWindowVisible(window) &&
GetDlgItem(window, IDYES) && GetDlgItem(window, IDNO) &&
GetDlgItem(window, IDCANCEL)) {
saveDialog = window;
return FALSE;
}
return TRUE;
}
static BOOL CALLBACK find_notepad(HWND window, LPARAM unused) {
(void)unused;
DWORD pid;
GetWindowThreadProcessId(window, &pid);
if (pid == notepad_pid && IsWindowVisible(window) &&
FindWindowExW(window, NULL, L"Edit", NULL)) {
notepad = window;
return FALSE;
}
return TRUE;
}
static void key(WORD vk, BOOL control, BOOL shift) {
INPUT input[6] = {0};
UINT count = 0;
if (control) { input[count].ki.wVk = VK_CONTROL; ++count; }
if (shift) { input[count].ki.wVk = VK_SHIFT; ++count; }
input[count].ki.wVk = vk; ++count;
input[count].ki.wVk = vk; input[count].ki.dwFlags = KEYEVENTF_KEYUP; ++count;
if (shift) { input[count].ki.wVk = VK_SHIFT; input[count].ki.dwFlags = KEYEVENTF_KEYUP; ++count; }
if (control) { input[count].ki.wVk = VK_CONTROL; input[count].ki.dwFlags = KEYEVENTF_KEYUP; ++count; }
for (UINT i = 0; i < count; ++i) input[i].type = INPUT_KEYBOARD;
if (SendInput(count, input, sizeof(INPUT)) != count) ExitProcess(3);
Sleep(200);
}
int WINAPI WinMain(HINSTANCE instance, HINSTANCE previous, LPSTR args, int show) {
(void)instance; (void)previous; (void)args; (void)show;
STARTUPINFOW startup = {0};
PROCESS_INFORMATION process = {0};
startup.cb = sizeof(startup);
WCHAR command[] = L"notepad.exe";
if (!CreateProcessW(NULL, command, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &process)) return 2;
notepad_pid = process.dwProcessId;
for (int i = 0; i < 100 && !notepad; ++i) {
EnumWindows(find_notepad, 0);
Sleep(50);
}
int result = 2;
if (notepad) {
HWND edit = FindWindowExW(notepad, NULL, L"Edit", NULL);
SetForegroundWindow(notepad);
Sleep(400);
key('Z', FALSE, FALSE);
key('Z', FALSE, FALSE);
key(VK_SPACE, FALSE, FALSE);
key(VK_RETURN, FALSE, FALSE);
WCHAR typed[16] = {0};
SendMessageW(edit, WM_GETTEXT, 16, (LPARAM)typed);
if (lstrcmpW(typed, L"zz \r\n")) {
fprintf(stderr, "Notepad typing did not reach its edit: units=%d first=%04x foreground=%p expected=%p\n",
lstrlenW(typed), (unsigned)typed[0], (void *)GetForegroundWindow(), (void *)notepad);
ExitProcess(2);
}
SendMessageW(edit, WM_SETTEXT, 0, (LPARAM)L"hello beta\r\nNotepad second line");
SendMessageW(edit, EM_SETSEL, 0, 0);
Sleep(400);
key(VK_RIGHT, FALSE, FALSE); // e
key(VK_RIGHT, FALSE, FALSE); // l
key(VK_RIGHT, FALSE, FALSE); // l
key(VK_RIGHT, TRUE, FALSE); // beta
key(VK_DOWN, FALSE, FALSE); // second line
key(VK_HOME, FALSE, FALSE);
key(VK_RIGHT, FALSE, TRUE); // N selected
key(VK_LEFT, FALSE, TRUE); // N unselected
key(VK_DELETE, FALSE, FALSE);// N deleted
key(VK_MENU, FALSE, FALSE);
key(VK_ESCAPE, FALSE, FALSE);
key(VK_ESCAPE, FALSE, FALSE);
WCHAR text[80] = {0};
SendMessageW(edit, WM_GETTEXT, 80, (LPARAM)text);
if (!lstrcmpW(text, L"hello beta\r\notepad second line")) result = 0;
else fprintf(stderr, "Notepad final document mismatch: units=%d\n", lstrlenW(text));
PostMessageW(notepad, WM_CLOSE, 0, 0);
for (int i = 0; i < 100 && !saveDialog; ++i) {
EnumWindows(find_save_dialog, 0);
Sleep(50);
}
if (!saveDialog) { fprintf(stderr, "Notepad save dialog missing\n"); result = 2; }
else {
SetForegroundWindow(saveDialog);
Sleep(400);
key(VK_TAB, FALSE, FALSE); // Yes -> No
key(VK_TAB, FALSE, FALSE); // No -> Cancel
key(VK_TAB, FALSE, TRUE); // Cancel -> No
key(VK_ESCAPE, FALSE, FALSE);
}
// Suppress the save prompt only in this test-owned, unsaved document.
SendMessageW(edit, EM_SETMODIFY, FALSE, 0);
PostMessageW(notepad, WM_CLOSE, 0, 0);
if (WaitForSingleObject(process.hProcess, 3000) != WAIT_OBJECT_0) result = 2;
}
CloseHandle(process.hThread);
CloseHandle(process.hProcess);
return result;
}