From 0858ae202488437f1634b8afef9fe70efd694483 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 30 Aug 2018 10:59:46 +0100 Subject: [PATCH] Add `utf8_to_ucs2` for package win32 so that the wide procedures can used by default --- core/os/os.odin | 4 +-- core/os/os_windows.odin | 15 +++------ core/sync/sync_windows.odin | 4 +-- core/sys/win32/windows.odin | 66 ++++++++++++++++++++++++++++++++++++- 4 files changed, 73 insertions(+), 16 deletions(-) diff --git a/core/os/os.odin b/core/os/os.odin index 39e21a19e..aa669644e 100644 --- a/core/os/os.odin +++ b/core/os/os.odin @@ -67,8 +67,8 @@ read_ptr :: proc(fd: Handle, data: rawptr, len: int) -> (int, Errno) { heap_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode, - size, alignment: int, - old_memory: rawptr, old_size: int, flags: u64 = 0, loc := #caller_location) -> rawptr { + size, alignment: int, + old_memory: rawptr, old_size: int, flags: u64 = 0, loc := #caller_location) -> rawptr { using mem.Allocator_Mode; switch mode { diff --git a/core/os/os_windows.odin b/core/os/os_windows.odin index 4c39bb59d..1ffb2206a 100644 --- a/core/os/os_windows.odin +++ b/core/os/os_windows.odin @@ -98,11 +98,8 @@ open :: proc(path: string, mode: int = O_RDONLY, perm: u32 = 0) -> (Handle, Errn case: create_mode = win32.OPEN_EXISTING; } - - buf: [300]byte; - copy(buf[:], cast([]byte)path); - - handle := Handle(win32.create_file_a(cstring(&buf[0]), access, share_mode, sa, create_mode, win32.FILE_ATTRIBUTE_NORMAL, nil)); + wide_path := win32.utf8_to_wstring(path); + handle := Handle(win32.create_file_w(wide_path, access, share_mode, sa, create_mode, win32.FILE_ATTRIBUTE_NORMAL, nil)); if handle != INVALID_HANDLE do return handle, ERROR_NONE; err := Errno(win32.get_last_error()); @@ -217,13 +214,9 @@ last_write_time :: proc(fd: Handle) -> File_Time { last_write_time_by_name :: proc(name: string) -> File_Time { last_write_time: win32.Filetime; data: win32.File_Attribute_Data; - buf: [1024]byte; - assert(len(buf) > len(name)); - - copy(buf[:], cast([]byte)name); - - if win32.get_file_attributes_ex_a(cstring(&buf[0]), win32.GetFileExInfoStandard, &data) { + wide_path := win32.utf8_to_wstring(name); + if win32.get_file_attributes_ex_w(wide_path, win32.GetFileExInfoStandard, &data) { last_write_time = data.last_write_time; } diff --git a/core/sync/sync_windows.odin b/core/sync/sync_windows.odin index e07b66ce5..d50d9046e 100644 --- a/core/sync/sync_windows.odin +++ b/core/sync/sync_windows.odin @@ -20,7 +20,7 @@ current_thread_id :: proc() -> i32 { } semaphore_init :: proc(s: ^Semaphore) { - s._handle = win32.create_semaphore_a(nil, 0, 1<<31-1, nil); + s._handle = win32.create_semaphore_w(nil, 0, 1<<31-1, nil); } semaphore_destroy :: proc(s: ^Semaphore) { @@ -63,7 +63,7 @@ mutex_unlock :: proc(m: ^Mutex) { condition_init :: proc(using c: ^Condition) { - event = win32.create_event_a(nil, false, false, nil); + event = win32.create_event_w(nil, false, false, nil); assert(event != nil); } diff --git a/core/sys/win32/windows.odin b/core/sys/win32/windows.odin index 49e289159..2e7f8a70b 100644 --- a/core/sys/win32/windows.odin +++ b/core/sys/win32/windows.odin @@ -550,6 +550,64 @@ CP_SYMBOL :: 42; // SYMBOL translations CP_UTF7 :: 65000; // UTF-7 translation CP_UTF8 :: 65001; // UTF-8 translation + +MB_ERR_INVALID_CHARS :: 8; +WC_ERR_INVALID_CHARS :: 128; + +utf8_to_ucs2 :: proc(s: string, allocator := context.temp_allocator) -> []u16 { + if len(s) < 1 { + return nil; + } + + n := multi_byte_to_wide_char(CP_UTF8, MB_ERR_INVALID_CHARS, cstring(&s[0]), i32(len(s)), nil, 0); + if n == 0 { + return nil; + } + + text := make([]u16, n+1, allocator); + + n1 := multi_byte_to_wide_char(CP_UTF8, MB_ERR_INVALID_CHARS, cstring(&s[0]), i32(len(s)), &text[0], i32(n)); + if n1 == 0 { + delete(text, allocator); + return nil; + } + + text[n] = 0; + + return text[:len(text)-1]; +} +utf8_to_wstring :: proc(s: string, allocator := context.temp_allocator) -> Wstring { + if res := utf8_to_ucs2(s, allocator); res != nil { + return &res[0]; + } + return nil; +} + +ucs2_to_utf8 :: proc(s: []u16, allocator := context.temp_allocator) -> string { + if len(s) < 1 { + return ""; + } + + n := wide_char_to_multi_byte(CP_UTF8, WC_ERR_INVALID_CHARS, &s[0], i32(len(s)), nil, 0, nil, nil); + if n == 0 { + return ""; + } + + text := make([]byte, n+1, allocator); + + n1 := wide_char_to_multi_byte(CP_UTF8, WC_ERR_INVALID_CHARS, &s[0], i32(len(s)), cstring(&text[0]), n, nil, nil); + if n1 == 0 { + delete(text, allocator); + return ""; + } + + text[n] = 0; + + return string(text[:len(text)-1]); +} + + + @(default_calling_convention = "std") foreign kernel32 { @(link_name="GetLastError") get_last_error :: proc() -> i32 ---; @@ -603,6 +661,7 @@ foreign kernel32 { @(link_name="GetFileAttributesA") get_file_attributes_a :: proc(filename: cstring) -> u32 ---; @(link_name="GetFileAttributesW") get_file_attributes_w :: proc(filename: Wstring) -> u32 ---; @(link_name="GetFileAttributesExA") get_file_attributes_ex_a :: proc(filename: cstring, info_level_id: GET_FILEEX_INFO_LEVELS, file_info: rawptr) -> Bool ---; + @(link_name="GetFileAttributesExW") get_file_attributes_ex_w :: proc(filename: Wstring, info_level_id: GET_FILEEX_INFO_LEVELS, file_info: rawptr) -> Bool ---; @(link_name="GetFileInformationByHandle") get_file_information_by_handle :: proc(file_handle: Handle, file_info: ^By_Handle_File_Information) -> Bool ---; @(link_name="CreateDirectoryA") create_directory_a :: proc(path: cstring, security_attributes: ^Security_Attributes) -> Bool ---; @@ -657,6 +716,7 @@ foreign kernel32 { wc_str: Wstring, wc: i32) -> i32 ---; @(link_name="CreateSemaphoreA") create_semaphore_a :: proc(attributes: ^Security_Attributes, initial_count, maximum_count: i32, name: cstring) -> Handle ---; + @(link_name="CreateSemaphoreW") create_semaphore_w :: proc(attributes: ^Security_Attributes, initial_count, maximum_count: i32, name: cstring) -> Handle ---; @(link_name="ReleaseSemaphore") release_semaphore :: proc(semaphore: Handle, release_count: i32, previous_count: ^i32) -> Bool ---; @(link_name="WaitForSingleObject") wait_for_single_object :: proc(handle: Handle, milliseconds: u32) -> u32 ---; } @@ -701,6 +761,7 @@ foreign kernel32 { @(link_name="LeaveCriticalSection") leave_critical_section :: proc(critical_section: ^Critical_Section) ---; @(link_name="CreateEventA") create_event_a :: proc(event_attributes: ^Security_Attributes, manual_reset, initial_state: Bool, name: cstring) -> Handle ---; + @(link_name="CreateEventW") create_event_w :: proc(event_attributes: ^Security_Attributes, manual_reset, initial_state: Bool, name: Wstring) -> Handle ---; @(link_name="PulseEvent") pulse_event :: proc(event: Handle) -> Bool ---; @(link_name="SetEvent") set_event :: proc(event: Handle) -> Bool ---; @(link_name="ResetEvent") reset_event :: proc(event: Handle) -> Bool ---; @@ -722,6 +783,7 @@ foreign user32 { @(link_name="ClientToScreen") client_to_screen :: proc(h: Hwnd, p: ^Point) -> Bool ---; @(link_name="PostQuitMessage") post_quit_message :: proc(exit_code: i32) ---; @(link_name="SetWindowTextA") set_window_text_a :: proc(hwnd: Hwnd, c_string: cstring) -> Bool ---; + @(link_name="SetWindowTextW") set_window_text_w :: proc(hwnd: Hwnd, c_string: Wstring) -> Bool ---; @(link_name="RegisterClassExA") register_class_ex_a :: proc(wc: ^Wnd_Class_Ex_A) -> i16 ---; @(link_name="RegisterClassExW") register_class_ex_w :: proc(wc: ^Wnd_Class_Ex_W) -> i16 ---; @@ -753,9 +815,11 @@ foreign user32 { @(link_name="PeekMessageW") peek_message_w :: proc(msg: ^Msg, hwnd: Hwnd, msg_filter_min, msg_filter_max, remove_msg: u32) -> Bool ---; - @(link_name="PostMessageA") post_message :: proc(hwnd: Hwnd, msg, wparam, lparam: u32) -> Bool ---; + @(link_name="PostMessageA") post_message_a :: proc(hwnd: Hwnd, msg, wparam, lparam: u32) -> Bool ---; + @(link_name="PostMessageW") post_message_w :: proc(hwnd: Hwnd, msg, wparam, lparam: u32) -> Bool ---; @(link_name="DefWindowProcA") def_window_proc_a :: proc(hwnd: Hwnd, msg: u32, wparam: Wparam, lparam: Lparam) -> Lresult ---; + @(link_name="DefWindowProcW") def_window_proc_w :: proc(hwnd: Hwnd, msg: u32, wparam: Wparam, lparam: Lparam) -> Lresult ---; @(link_name="AdjustWindowRect") adjust_window_rect :: proc(rect: ^Rect, style: u32, menu: Bool) -> Bool ---; @(link_name="GetActiveWindow") get_active_window :: proc() -> Hwnd ---;