Win32: define UNICODE so unsuffixed calls cannot fall back to the A functions, and share the UTF-8 conversion #186

Open
opened 2026-10-31 17:22:47 +00:00 by jorijnvdgraaf · 0 comments

Summary

claude/win32-title makes the Win32 window a Unicode one by calling the W functions by name (RegisterClassW, CreateWindowExW, DefWindowProcW, PeekMessageW, DispatchMessageW, SetWindowTextW). UNICODE and _UNICODE stay undefined: project.cpp:73 (at 852ae8a) defines only CRAFTER_GRAPHICS_WINDOW_WIN32. So every unsuffixed Win32 name in the library and the tests still means the A function, and nothing stops one from coming back. A new message loop written the usual way, with PeekMessage and DispatchMessage, would hand WM_CHAR over in the code page again, turning 日 and emoji into ?. TextWin32 catches that in StartSync's loop, not in a loop anywhere else.

The same branch adds a file-static Utf16FromUtf8 to Window.cpp, while Clipboard::SetText does the same two-call MultiByteToWideChar inline (implementations/Crafter.Graphics-Clipboard.cpp:274-288) with a different failure check. Its if (wlen < 0) (:276) can't fire, since the function returns 0 on failure.

Suggested fix

  • Define UNICODE and _UNICODE beside CRAFTER_GRAPHICS_WINDOW_WIN32. They reach every library unit, GamepadWin32.c and the tests, since LibraryTest copies cfg.defines. The two MessageBox calls with char strings then need L"" or MessageBoxA.
  • One non-exported Win32 helper each way between UTF-8 and UTF-16, for Window (SetTitle, WM_CHAR) and Clipboard (SetText, GetText).
## Summary `claude/win32-title` makes the Win32 window a Unicode one by calling the W functions by name (`RegisterClassW`, `CreateWindowExW`, `DefWindowProcW`, `PeekMessageW`, `DispatchMessageW`, `SetWindowTextW`). `UNICODE` and `_UNICODE` stay undefined: `project.cpp:73` (at `852ae8a`) defines only `CRAFTER_GRAPHICS_WINDOW_WIN32`. So every unsuffixed Win32 name in the library and the tests still means the A function, and nothing stops one from coming back. A new message loop written the usual way, with `PeekMessage` and `DispatchMessage`, would hand `WM_CHAR` over in the code page again, turning 日 and emoji into `?`. `TextWin32` catches that in `StartSync`'s loop, not in a loop anywhere else. The same branch adds a file-static `Utf16FromUtf8` to `Window.cpp`, while `Clipboard::SetText` does the same two-call `MultiByteToWideChar` inline (`implementations/Crafter.Graphics-Clipboard.cpp:274-288`) with a different failure check. Its `if (wlen < 0)` (`:276`) can't fire, since the function returns 0 on failure. ## Suggested fix - Define `UNICODE` and `_UNICODE` beside `CRAFTER_GRAPHICS_WINDOW_WIN32`. They reach every library unit, `GamepadWin32.c` and the tests, since `LibraryTest` copies `cfg.defines`. The two `MessageBox` calls with `char` strings then need `L""` or `MessageBoxA`. - One non-exported Win32 helper each way between UTF-8 and UTF-16, for `Window` (`SetTitle`, `WM_CHAR`) and `Clipboard` (`SetText`, `GetText`).
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Catcrafts/Crafter.Graphics#186
No description provided.