Notepad++ should work now.
This commit is contained in:
1 parent
cbce83581a
commit
df7879acb5
12 files changed
+523
-18
No files matched your search
@@ -0,0 +1,140 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
// Drive an actual Notepad++ instance in the runner's disposable Wine prefix.
|
||||
#include <windows.h>
|
||||
#include "../scintilla_messages.h"
|
||||
|
||||
static DWORD editorPid;
|
||||
static HWND editor, owner;
|
||||
|
||||
static BOOL CALLBACK find_editor(HWND window, LPARAM unused) {
|
||||
(void)unused;
|
||||
WCHAR name[64];
|
||||
if (IsWindowVisible(window) && GetClassNameW(window, name, 64) &&
|
||||
!lstrcmpW(name, L"Scintilla")) {
|
||||
editor = window;
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL CALLBACK find_owner(HWND window, LPARAM unused) {
|
||||
(void)unused;
|
||||
DWORD pid;
|
||||
GetWindowThreadProcessId(window, &pid);
|
||||
if (pid == editorPid && IsWindowVisible(window)) {
|
||||
EnumChildWindows(window, find_editor, 0);
|
||||
if (editor) { owner = 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);
|
||||
}
|
||||
|
||||
static void move_to(ptrdiff_t position) {
|
||||
SendMessageW(editor, SCI_SETSEL, position, position);
|
||||
Sleep(100);
|
||||
}
|
||||
|
||||
int WINAPI WinMain(HINSTANCE instance, HINSTANCE previous, LPSTR args, int show) {
|
||||
(void)instance; (void)previous; (void)args; (void)show;
|
||||
WCHAR executable[2048], document[2048], command[4600];
|
||||
if (!GetEnvironmentVariableW(L"WINE_ACCESS_NOTEPADPP_EXE", executable, 2048) ||
|
||||
!GetEnvironmentVariableW(L"WINE_ACCESS_SCINTILLA_DOCUMENT", document, 2048)) return 2;
|
||||
wsprintfW(command, L"\"%s\" -multiInst -nosession -noPlugin \"%s\"", executable, document);
|
||||
STARTUPINFOW startup = {0};
|
||||
PROCESS_INFORMATION process = {0};
|
||||
startup.cb = sizeof(startup);
|
||||
if (!CreateProcessW(NULL, command, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &process)) return 2;
|
||||
editorPid = process.dwProcessId;
|
||||
for (int i = 0; i < 100 && !editor; ++i) { EnumWindows(find_owner, 0); Sleep(50); }
|
||||
if (!editor || SendMessageW(editor, SCI_GETLENGTH, 0, 0) < 40) return 2;
|
||||
ptrdiff_t originalLength = SendMessageW(editor, SCI_GETLENGTH, 0, 0);
|
||||
SetForegroundWindow(owner);
|
||||
key(VK_HOME, TRUE, FALSE);
|
||||
WCHAR ready[1024];
|
||||
if (GetEnvironmentVariableW(L"WINE_ACCESS_FIXTURE_READY", ready, 1024)) {
|
||||
HANDLE file = CreateFileW(ready, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
|
||||
if (file == INVALID_HANDLE_VALUE) return 2;
|
||||
CloseHandle(file);
|
||||
}
|
||||
Sleep(1500);
|
||||
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_LEFT, TRUE, FALSE); // hello plus trailing space
|
||||
key(VK_RIGHT, TRUE, FALSE);
|
||||
key(VK_DOWN, FALSE, FALSE); // Scintilla second line
|
||||
key(VK_UP, FALSE, FALSE); // hello beta
|
||||
key(VK_DOWN, FALSE, FALSE);
|
||||
key(VK_HOME, FALSE, FALSE);
|
||||
key(VK_RIGHT, FALSE, TRUE); // S selected
|
||||
key(VK_RIGHT, FALSE, TRUE); // c selected
|
||||
key(VK_LEFT, FALSE, TRUE); // c unselected
|
||||
key(VK_LEFT, FALSE, FALSE); // S unselected
|
||||
key(VK_DELETE, FALSE, FALSE);// S deleted
|
||||
key(VK_RIGHT, FALSE, FALSE);
|
||||
key(VK_BACK, FALSE, FALSE); // c (without deleted suffix)
|
||||
key(VK_MENU, FALSE, FALSE);
|
||||
key(VK_ESCAPE, FALSE, FALSE);
|
||||
key(VK_ESCAPE, FALSE, FALSE);// return at "intilla second line"
|
||||
key('Z', TRUE, FALSE); // undo c
|
||||
key('Z', TRUE, FALSE); // undo S
|
||||
key(VK_HOME, FALSE, FALSE);
|
||||
key(VK_RIGHT, FALSE, FALSE);// c from restored document
|
||||
SendMessageW(editor, SCI_SETSEL, 12, 21); // Scintilla selected
|
||||
Sleep(100);
|
||||
key('X', TRUE, FALSE); // Scintilla deleted
|
||||
key('Z', TRUE, FALSE);
|
||||
key(VK_HOME, FALSE, FALSE);
|
||||
key(VK_DOWN, FALSE, FALSE); // café 😀 tail
|
||||
ptrdiff_t lineStart = SendMessageW(editor, SCI_POSITIONFROMLINE, 2, 0);
|
||||
move_to(lineStart + 2);
|
||||
key(VK_RIGHT, FALSE, FALSE);// é (two UTF-8 bytes)
|
||||
move_to(lineStart + 6);
|
||||
key(VK_LEFT, FALSE, FALSE); // space
|
||||
key(VK_RIGHT, FALSE, FALSE);// 😀 (four UTF-8 bytes)
|
||||
key(VK_RIGHT, FALSE, TRUE); // 😀 selected
|
||||
key(VK_LEFT, FALSE, TRUE); // 😀 unselected
|
||||
key(VK_DELETE, FALSE, FALSE);// 😀 deleted
|
||||
key('Z', TRUE, FALSE);
|
||||
move_to(lineStart + 10);
|
||||
key(VK_BACK, FALSE, FALSE); // 😀
|
||||
key('Z', TRUE, FALSE);
|
||||
SendMessageW(editor, 2171 /* SCI_SETREADONLY */, TRUE, 0);
|
||||
SendMessageW(editor, RegisterWindowMessageW(L"CthulhuWineEditFocus"), 0, 0);
|
||||
key(VK_DELETE, FALSE, FALSE);// read-only: must leave document unchanged
|
||||
if (SendMessageW(editor, SCI_GETLENGTH, 0, 0) != originalLength) return 4;
|
||||
SendMessageW(editor, 2171 /* SCI_SETREADONLY */, FALSE, 0);
|
||||
move_to(SendMessageW(editor, SCI_POSITIONFROMLINE, 3, 0));
|
||||
key(VK_END, TRUE, FALSE); // truncate before a surrogate pair in the last line
|
||||
key(VK_UP, FALSE, FALSE);// very large document line, bounded range read
|
||||
move_to(0);
|
||||
LRESULT codePage = SendMessageW(editor, SCI_GETCODEPAGE, 0, 0);
|
||||
SendMessageW(editor, 2037 /* SCI_SETCODEPAGE */, 0, 0);
|
||||
SendMessageW(editor, 2066 /* SCI_STYLESETCHARACTERSET */, 32, DEFAULT_CHARSET);
|
||||
SendMessageW(editor, RegisterWindowMessageW(L"CthulhuWineEditFocus"), 0, 0);
|
||||
Sleep(100);
|
||||
SendMessageW(editor, 2066 /* SCI_STYLESETCHARACTERSET */, 32, ANSI_CHARSET);
|
||||
SendMessageW(editor, RegisterWindowMessageW(L"CthulhuWineEditFocus"), 0, 0);
|
||||
Sleep(100);
|
||||
SendMessageW(editor, 2037 /* SCI_SETCODEPAGE */, codePage, 0);
|
||||
// Mark this disposable document clean to close without a save prompt.
|
||||
SendMessageW(editor, 2014 /* SCI_SETSAVEPOINT */, 0, 0);
|
||||
PostMessageW(owner, WM_CLOSE, 0, 0);
|
||||
int result = WaitForSingleObject(process.hProcess, 3000) == WAIT_OBJECT_0 ? 0 : 2;
|
||||
CloseHandle(process.hThread); CloseHandle(process.hProcess);
|
||||
return result;
|
||||
}
|
||||
Reference in new issue
Block a user