diff --git a/examples/common/entry/entry_windows.cpp b/examples/common/entry/entry_windows.cpp index 06f88807a..3c1c164ef 100644 --- a/examples/common/entry/entry_windows.cpp +++ b/examples/common/entry/entry_windows.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -33,6 +34,16 @@ namespace entry { + typedef tinystl::vector WSTRING; + + inline WSTRING UTF8ToUTF16(const char *utf8_str) + { + int len = MultiByteToWideChar(CP_UTF8, 0, utf8_str, -1, NULL, 0); + WSTRING utf16(len); + MultiByteToWideChar(CP_UTF8, 0, utf8_str, -1, utf16.data(), len); + return utf16; + } + /// inline void winSetHwnd(::HWND _window) { @@ -359,6 +370,7 @@ namespace entry , m_init(false) , m_exit(false) { + m_surrogate = 0; bx::memSet(s_translateKey, 0, sizeof(s_translateKey) ); s_translateKey[VK_ESCAPE] = Key::Esc; s_translateKey[VK_RETURN] = Key::Return; @@ -450,29 +462,29 @@ namespace entry int32_t run(int _argc, const char* const* _argv) { - SetDllDirectoryA("."); + SetDllDirectoryW(L"."); s_xinput.init(); - HINSTANCE instance = (HINSTANCE)GetModuleHandle(NULL); + HINSTANCE instance = (HINSTANCE)GetModuleHandleW(NULL); - WNDCLASSEXA wnd; + WNDCLASSEXW wnd; bx::memSet(&wnd, 0, sizeof(wnd) ); wnd.cbSize = sizeof(wnd); wnd.style = CS_HREDRAW | CS_VREDRAW; wnd.lpfnWndProc = wndProc; wnd.hInstance = instance; - wnd.hIcon = LoadIcon(NULL, IDI_APPLICATION); - wnd.hCursor = LoadCursor(NULL, IDC_ARROW); - wnd.lpszClassName = "bgfx"; - wnd.hIconSm = LoadIcon(NULL, IDI_APPLICATION); - RegisterClassExA(&wnd); + wnd.hIcon = LoadIconW(NULL, (LPWSTR)IDI_APPLICATION); + wnd.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW); + wnd.lpszClassName = L"bgfx"; + wnd.hIconSm = LoadIconW(NULL, (LPWSTR)IDI_APPLICATION); + RegisterClassExW(&wnd); m_windowAlloc.alloc(); - m_hwnd[0] = CreateWindowExA( + m_hwnd[0] = CreateWindowExW( WS_EX_ACCEPTFILES - , "bgfx" - , "BGFX" + , L"bgfx" + , L"BGFX" , WS_OVERLAPPEDWINDOW|WS_VISIBLE , 0 , 0 @@ -521,10 +533,10 @@ namespace entry s_xinput.update(m_eventQueue); WaitForInputIdle(GetCurrentProcess(), 16); - while (0 != PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE) ) + while (0 != PeekMessageW(&msg, NULL, 0U, 0U, PM_REMOVE) ) { TranslateMessage(&msg); - DispatchMessage(&msg); + DispatchMessageW(&msg); } } @@ -548,8 +560,8 @@ namespace entry case WM_USER_WINDOW_CREATE: { Msg* msg = (Msg*)_lparam; - HWND hwnd = CreateWindowA("bgfx" - , msg->m_title.c_str() + HWND hwnd = CreateWindowW(L"bgfx" + , UTF8ToUTF16(msg->m_title.c_str()).data() , WS_OVERLAPPEDWINDOW|WS_VISIBLE , msg->m_x , msg->m_y @@ -557,7 +569,7 @@ namespace entry , msg->m_height , NULL , NULL - , (HINSTANCE)GetModuleHandle(NULL) + , (HINSTANCE)GetModuleHandleW(NULL) , 0 ); clear(hwnd); @@ -590,7 +602,7 @@ namespace entry case WM_USER_WINDOW_SET_TITLE: { Msg* msg = (Msg*)_lparam; - SetWindowTextA(m_hwnd[_wparam], msg->m_title.c_str() ); + SetWindowTextW(m_hwnd[_wparam], UTF8ToUTF16(msg->m_title.c_str()).data() ); delete msg; } break; @@ -743,7 +755,7 @@ namespace entry HWND parent = GetWindow(_hwnd, GW_OWNER); if (NULL != parent) { - PostMessage(parent, _id, _wparam, _lparam); + PostMessageW(parent, _id, _wparam, _lparam); } } } @@ -842,20 +854,36 @@ namespace entry case WM_CHAR: { + WCHAR utf16[2] = { (WCHAR)_wparam }; uint8_t utf8[4] = {}; - uint8_t len = (uint8_t)WideCharToMultiByte(CP_UTF8 - , 0 - , (LPCWSTR)&_wparam - , 1 - , (LPSTR)utf8 - , BX_COUNTOF(utf8) - , NULL - , NULL - ); - if (0 != len) - { - WindowHandle handle = findHandle(_hwnd); - m_eventQueue.postCharEvent(handle, len, utf8); + + if (utf16[0] >= 0xD800 && utf16[0] <= 0xDBFF) { + m_surrogate = utf16[0]; + } else { + int utf16_len; + if (utf16[0] >= 0xDC00 && utf16[0] <= 0xDFFF) { + utf16[1] = utf16[0]; + utf16[0] = m_surrogate; + m_surrogate = 0; + utf16_len = 2; + } else { + utf16_len = 1; + } + + uint8_t len = (uint8_t)WideCharToMultiByte(CP_UTF8 + , 0 + , utf16 + , utf16_len + , (LPSTR)utf8 + , BX_COUNTOF(utf8) + , NULL + , NULL + ); + if (0 != len) + { + WindowHandle handle = findHandle(_hwnd); + m_eventQueue.postCharEvent(handle, len, utf8); + } } } break; @@ -864,8 +892,10 @@ namespace entry { HDROP drop = (HDROP)_wparam; char tmp[bx::kMaxFilePath]; - uint32_t result = DragQueryFileA(drop, 0, tmp, sizeof(tmp) ); + WCHAR utf16[bx::kMaxFilePath]; + uint32_t result = DragQueryFileW(drop, 0, utf16, bx::kMaxFilePath); BX_UNUSED(result); + WideCharToMultiByte(CP_UTF8, 0, utf16, -1, tmp, bx::kMaxFilePath, NULL, NULL); WindowHandle handle = findHandle(_hwnd); m_eventQueue.postDropFileEvent(handle, tmp); } @@ -876,7 +906,7 @@ namespace entry } } - return DefWindowProc(_hwnd, _id, _wparam, _lparam); + return DefWindowProcW(_hwnd, _id, _wparam, _lparam); } WindowHandle findHandle(HWND _hwnd) @@ -921,7 +951,7 @@ namespace entry if (m_frame) { GetWindowRect(_hwnd, &m_rect); - m_style = GetWindowLong(_hwnd, GWL_STYLE); + m_style = GetWindowLongW(_hwnd, GWL_STYLE); } if (_windowFrame) @@ -934,13 +964,13 @@ namespace entry HMONITOR monitor = MonitorFromWindow(_hwnd, MONITOR_DEFAULTTONEAREST); MONITORINFO mi; mi.cbSize = sizeof(mi); - GetMonitorInfo(monitor, &mi); + GetMonitorInfoW(monitor, &mi); newrect = mi.rcMonitor; rect = mi.rcMonitor; m_aspectRatio = float(newrect.right - newrect.left)/float(newrect.bottom - newrect.top); } - SetWindowLong(_hwnd, GWL_STYLE, style); + SetWindowLongW(_hwnd, GWL_STYLE, style); uint32_t prewidth = newrect.right - newrect.left; uint32_t preheight = newrect.bottom - newrect.top; AdjustWindowRect(&newrect, style, FALSE); @@ -1015,6 +1045,7 @@ namespace entry static LRESULT CALLBACK wndProc(HWND _hwnd, UINT _id, WPARAM _wparam, LPARAM _lparam); EventQueue m_eventQueue; + WCHAR m_surrogate; bx::Mutex m_lock; bx::HandleAllocT m_windowAlloc; @@ -1078,7 +1109,7 @@ namespace entry msg->m_height = _height; msg->m_title = _title; msg->m_flags = _flags; - PostMessage(s_ctx.m_hwnd[0], WM_USER_WINDOW_CREATE, handle.idx, (LPARAM)msg); + PostMessageW(s_ctx.m_hwnd[0], WM_USER_WINDOW_CREATE, handle.idx, (LPARAM)msg); } return handle; @@ -1088,7 +1119,7 @@ namespace entry { if (UINT16_MAX != _handle.idx) { - PostMessage(s_ctx.m_hwnd[0], WM_USER_WINDOW_DESTROY, _handle.idx, 0); + PostMessageW(s_ctx.m_hwnd[0], WM_USER_WINDOW_DESTROY, _handle.idx, 0); bx::MutexScope scope(s_ctx.m_lock); s_ctx.m_windowAlloc.free(_handle.idx); @@ -1100,19 +1131,19 @@ namespace entry Msg* msg = new Msg; msg->m_x = _x; msg->m_y = _y; - PostMessage(s_ctx.m_hwnd[0], WM_USER_WINDOW_SET_POS, _handle.idx, (LPARAM)msg); + PostMessageW(s_ctx.m_hwnd[0], WM_USER_WINDOW_SET_POS, _handle.idx, (LPARAM)msg); } void setWindowSize(WindowHandle _handle, uint32_t _width, uint32_t _height) { - PostMessage(s_ctx.m_hwnd[0], WM_USER_WINDOW_SET_SIZE, _handle.idx, (_height<<16) | (_width&0xffff) ); + PostMessageW(s_ctx.m_hwnd[0], WM_USER_WINDOW_SET_SIZE, _handle.idx, (_height<<16) | (_width&0xffff) ); } void setWindowTitle(WindowHandle _handle, const char* _title) { Msg* msg = new Msg; msg->m_title = _title; - PostMessage(s_ctx.m_hwnd[0], WM_USER_WINDOW_SET_TITLE, _handle.idx, (LPARAM)msg); + PostMessageW(s_ctx.m_hwnd[0], WM_USER_WINDOW_SET_TITLE, _handle.idx, (LPARAM)msg); } void setWindowFlags(WindowHandle _handle, uint32_t _flags, bool _enabled) @@ -1120,24 +1151,24 @@ namespace entry Msg* msg = new Msg; msg->m_flags = _flags; msg->m_flagsEnabled = _enabled; - PostMessage(s_ctx.m_hwnd[0], WM_USER_WINDOW_SET_FLAGS, _handle.idx, (LPARAM)msg); + PostMessageW(s_ctx.m_hwnd[0], WM_USER_WINDOW_SET_FLAGS, _handle.idx, (LPARAM)msg); } void toggleFullscreen(WindowHandle _handle) { - PostMessage(s_ctx.m_hwnd[0], WM_USER_WINDOW_TOGGLE_FRAME, _handle.idx, 0); + PostMessageW(s_ctx.m_hwnd[0], WM_USER_WINDOW_TOGGLE_FRAME, _handle.idx, 0); } void setMouseLock(WindowHandle _handle, bool _lock) { - PostMessage(s_ctx.m_hwnd[0], WM_USER_WINDOW_MOUSE_LOCK, _handle.idx, _lock); + PostMessageW(s_ctx.m_hwnd[0], WM_USER_WINDOW_MOUSE_LOCK, _handle.idx, _lock); } int32_t MainThreadEntry::threadFunc(bx::Thread* /*_thread*/, void* _userData) { MainThreadEntry* self = (MainThreadEntry*)_userData; int32_t result = main(self->m_argc, self->m_argv); - PostMessage(s_ctx.m_hwnd[0], WM_QUIT, 0, 0); + PostMessageW(s_ctx.m_hwnd[0], WM_QUIT, 0, 0); return result; }