diff --git a/src/86box.c b/src/86box.c index cf992df4c..0f72ddef1 100644 --- a/src/86box.c +++ b/src/86box.c @@ -1870,6 +1870,27 @@ update_mouse_msg(void) (mouse_get_buttons() > 2) ? plat_get_string(STRING_MOUSE_RELEASE) : plat_get_string(STRING_MOUSE_RELEASE_MMB)); swprintf(mouse_msg[2], sizeof_w(mouse_msg[2]), L"%ls v%ls - %%i%%%% - %ls - %ls/%ls", EMU_NAME_W, EMU_VERSION_FULL_W, wmachine, wcpufamily, wcpu); +#else +#ifdef __APPLE__ + /* + * On macOS, BSD swprintf fails (returns -1) when the format string + * or a %ls argument contains non-ASCII wide characters (e.g. the + * native key symbols ⌘ U+2318, ⌫ U+232B) and the C locale is + * active. Store just the message suffixes here; the title update + * path in pc_render_monitor_dispatch() builds the full string + * without swprintf. + */ + wcsncpy(mouse_msg[0], plat_get_string(STRING_MOUSE_CAPTURE), sizeof_w(mouse_msg[0]) - 1); + mouse_msg[0][sizeof_w(mouse_msg[0]) - 1] = L'\0'; + + { + wchar_t *rel = (mouse_get_buttons() > 2) ? plat_get_string(STRING_MOUSE_RELEASE) + : plat_get_string(STRING_MOUSE_RELEASE_MMB); + wcsncpy(mouse_msg[1], rel, sizeof_w(mouse_msg[1]) - 1); + mouse_msg[1][sizeof_w(mouse_msg[1]) - 1] = L'\0'; + } + + mouse_msg[2][0] = L'\0'; #else swprintf(mouse_msg[0], sizeof_w(mouse_msg[0]), L"%%i%%%% - %ls", plat_get_string(STRING_MOUSE_CAPTURE)); @@ -1877,6 +1898,7 @@ update_mouse_msg(void) (mouse_get_buttons() > 2) ? plat_get_string(STRING_MOUSE_RELEASE) : plat_get_string(STRING_MOUSE_RELEASE_MMB)); wcsncpy(mouse_msg[2], L"%i%%", sizeof_w(mouse_msg[2])); #endif +#endif } void @@ -2009,11 +2031,20 @@ pc_run(void) else fps = ((fps + 20) / 50) * 50; #endif - swprintf(temp, sizeof_w(temp), mouse_msg[mouse_msg_idx], fps / (force_10ms ? 1 : 10)); #ifdef __APPLE__ + /* + * mouse_msg[] stores suffixes only on macOS (see update_mouse_msg). + * Build the title without passing non-ASCII chars through swprintf. + */ + swprintf(temp, sizeof_w(temp), L"%i%%", fps / (force_10ms ? 1 : 10)); + if (mouse_msg[mouse_msg_idx][0]) { + wcsncat(temp, L" - ", sizeof_w(temp) - wcslen(temp) - 1); + wcsncat(temp, mouse_msg[mouse_msg_idx], sizeof_w(temp) - wcslen(temp) - 1); + } /* Needed due to modifying the UI on the non-main thread is a big no-no. */ dispatch_async_f(dispatch_get_main_queue(), wcsdup((const wchar_t *) temp), _ui_window_title); #else + swprintf(temp, sizeof_w(temp), mouse_msg[mouse_msg_idx], fps / (force_10ms ? 1 : 10)); ui_window_title(temp); #endif title_update = 0;