unicode support in win32 layer
This commit is contained in:
parent
db16c4b067
commit
9a8b712f98
@ -514,15 +514,6 @@ INLINE i64 clamp_i64(i64 v, i64 min, i64 max) { return v < min ? min : v > max ?
|
|||||||
INLINE f32 clamp_f32(f32 v, f32 min, f32 max) { return v < min ? min : v > max ? max : v; }
|
INLINE f32 clamp_f32(f32 v, f32 min, f32 max) { return v < min ? min : v > max ? max : v; }
|
||||||
INLINE f64 clamp_f64(f64 v, f64 min, f64 max) { return v < min ? min : v > max ? max : v; }
|
INLINE f64 clamp_f64(f64 v, f64 min, f64 max) { return v < min ? min : v > max ? max : v; }
|
||||||
|
|
||||||
INLINE u64 cstr_len(char *cstr)
|
|
||||||
{
|
|
||||||
u64 len = 0;
|
|
||||||
for (char *c = cstr; *c != 0; ++c) {
|
|
||||||
++len;
|
|
||||||
}
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Profiling
|
* Profiling
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|||||||
@ -186,7 +186,7 @@ struct asset *font_load_asset(struct string path, f32 point_size, b32 help)
|
|||||||
STR("Font path \"%F\" too long!"),
|
STR("Font path \"%F\" too long!"),
|
||||||
FMT_STR(path)));
|
FMT_STR(path)));
|
||||||
}
|
}
|
||||||
string_to_cstr_buff(path, BUFFER_FROM_ARRAY(params->path_cstr));
|
cstr_buff_from_string(BUFFER_FROM_ARRAY(params->path_cstr), path);
|
||||||
params->path_len = path.len;
|
params->path_len = path.len;
|
||||||
params->asset = asset;
|
params->asset = asset;
|
||||||
params->point_size = point_size;
|
params->point_size = point_size;
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
struct resource {
|
struct resource {
|
||||||
struct buffer bytes;
|
struct buffer bytes;
|
||||||
|
|
||||||
|
/* Internal */
|
||||||
#if !RESOURCES_EMBEDDED
|
#if !RESOURCES_EMBEDDED
|
||||||
struct sys_file file;
|
struct sys_file file;
|
||||||
struct sys_file_map file_map;
|
struct sys_file_map file_map;
|
||||||
|
|||||||
@ -236,7 +236,7 @@ struct asset *sheet_load_asset(struct string path, b32 help)
|
|||||||
STR("Sheet path \"%F\" too long!"),
|
STR("Sheet path \"%F\" too long!"),
|
||||||
FMT_STR(path)));
|
FMT_STR(path)));
|
||||||
}
|
}
|
||||||
string_to_cstr_buff(path, BUFFER_FROM_ARRAY(params->path_cstr));
|
cstr_buff_from_string(BUFFER_FROM_ARRAY(params->path_cstr), path);
|
||||||
params->path_len = path.len;
|
params->path_len = path.len;
|
||||||
params->asset = asset;
|
params->asset = asset;
|
||||||
|
|
||||||
|
|||||||
@ -191,7 +191,7 @@ struct asset *sound_load_asset(struct string path, u32 flags, b32 help)
|
|||||||
STR("Sound path \"%F\" too long!"),
|
STR("Sound path \"%F\" too long!"),
|
||||||
FMT_STR(path)));
|
FMT_STR(path)));
|
||||||
}
|
}
|
||||||
string_to_cstr_buff(path, BUFFER_FROM_ARRAY(params->path_cstr));
|
cstr_buff_from_string(BUFFER_FROM_ARRAY(params->path_cstr), path);
|
||||||
params->path_len = path.len;
|
params->path_len = path.len;
|
||||||
params->asset = asset;
|
params->asset = asset;
|
||||||
params->flags = flags;
|
params->flags = flags;
|
||||||
|
|||||||
231
src/string.c
231
src/string.c
@ -160,54 +160,17 @@ struct string string_copy(struct arena *arena, struct string src)
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct string string_copy_buff(struct buffer buff, struct string src)
|
struct string string_copy_buff(struct buffer dest_buff, struct string src)
|
||||||
{
|
{
|
||||||
u64 len = min_u64(buff.size, src.len);
|
u64 len = min_u64(dest_buff.size, src.len);
|
||||||
struct string str = {
|
struct string str = {
|
||||||
.len = len,
|
.len = len,
|
||||||
.text = buff.data
|
.text = dest_buff.data
|
||||||
};
|
};
|
||||||
MEMCPY(str.text, src.text, src.len);
|
MEMCPY(str.text, src.text, src.len);
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: Benchmark performance of appending each character while calculating size here */
|
|
||||||
// //struct string string_copy_cstr(struct arena *arena, char *cstr)
|
|
||||||
// //{
|
|
||||||
// // u8 *final_text = arena_next(arena);
|
|
||||||
// // char *c = cstr;
|
|
||||||
// // for (; *c != 0; ++c) {
|
|
||||||
// // u8 *new_char = arena_push(arena, 1);
|
|
||||||
// // *new_char = *c;
|
|
||||||
// // }
|
|
||||||
// // return (struct string) {
|
|
||||||
// // .len = c - cstr,
|
|
||||||
// // .text = final_text
|
|
||||||
// // };
|
|
||||||
// //}
|
|
||||||
|
|
||||||
struct string string_from_cstr(char *cstr)
|
|
||||||
{
|
|
||||||
struct string str = { 0 };
|
|
||||||
if (cstr) {
|
|
||||||
char *c = cstr;
|
|
||||||
while (*c != 0) {
|
|
||||||
++c;
|
|
||||||
}
|
|
||||||
str.len = c - cstr;
|
|
||||||
str.text = (u8 *)cstr;
|
|
||||||
}
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct string string_from_cstr_len(char *cstr, u64 len)
|
|
||||||
{
|
|
||||||
return (struct string) {
|
|
||||||
.text = (u8 *)cstr,
|
|
||||||
.len = len
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
struct string string_repeat(struct arena *arena, struct string src, u64 count)
|
struct string string_repeat(struct arena *arena, struct string src, u64 count)
|
||||||
{
|
{
|
||||||
u64 final_len = src.len * count;
|
u64 final_len = src.len * count;
|
||||||
@ -365,54 +328,6 @@ b32 string_ends_with(struct string str, struct string substring)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* NOTE: This is a LOSSY conversion.
|
|
||||||
* `wstr` must be null-terminated.
|
|
||||||
*/
|
|
||||||
struct string string_from_wstr(struct arena *arena, u16 *wstr)
|
|
||||||
{
|
|
||||||
u8 *final_text = arena_next(arena);
|
|
||||||
u16 *wchar = wstr;
|
|
||||||
for (; *wchar != 0; ++wchar) {
|
|
||||||
u8 *c = arena_push(arena, 1);
|
|
||||||
*c = (u8)(*wchar & 0xFF);
|
|
||||||
}
|
|
||||||
return (struct string) {
|
|
||||||
.len = wchar - wstr,
|
|
||||||
.text = final_text
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
char *string_to_cstr(struct arena *arena, struct string str)
|
|
||||||
{
|
|
||||||
u8 *text = arena_push_array(arena, u8, str.len + 1);
|
|
||||||
MEMCPY(text, str.text, str.len);
|
|
||||||
text[str.len] = '\0';
|
|
||||||
return (char *)text;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *string_to_cstr_buff(struct string str, struct buffer buff)
|
|
||||||
{
|
|
||||||
if (buff.size > 0) {
|
|
||||||
u64 len = min_u64(str.len, buff.size - 1);
|
|
||||||
MEMCPY(buff.data, str.text, len);
|
|
||||||
buff.data[len] = '\0';
|
|
||||||
}
|
|
||||||
return (char *)buff.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
wchar_t *string_to_wstr(struct arena *arena, struct string str)
|
|
||||||
{
|
|
||||||
/* FIXME: Do proper encoding. */
|
|
||||||
u16 *text = arena_push_array(arena, u16, str.len + 1);
|
|
||||||
for (u64 i = 0; i < str.len; ++i) {
|
|
||||||
text[i] = (u16)str.text[i];
|
|
||||||
}
|
|
||||||
text[str.len] = '\0';
|
|
||||||
return (wchar_t *)text;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Format
|
* Format
|
||||||
* ========================== */
|
* ========================== */
|
||||||
@ -549,7 +464,7 @@ struct string _string_format(struct arena *arena, struct string fmt, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Unicode transformation
|
* Unicode
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
/* utf8 <- utf16 */
|
/* utf8 <- utf16 */
|
||||||
@ -576,6 +491,30 @@ struct string string_from_string16(struct arena *arena, struct string16 str16)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* utf8 <- utf32 */
|
||||||
|
struct string string_from_string32(struct arena *arena, struct string32 str32)
|
||||||
|
{
|
||||||
|
struct string res = {
|
||||||
|
.len = 0,
|
||||||
|
.text = arena_dry_push(arena, u8)
|
||||||
|
};
|
||||||
|
|
||||||
|
u64 pos32 = 0;
|
||||||
|
while (pos32 < str32.len) {
|
||||||
|
struct string32 str32_remaining = { .len = (str32.len - pos32), .text = str32.text + pos32 };
|
||||||
|
struct utf32_decode_result decoded = utf32_decode(str32_remaining);
|
||||||
|
struct utf8_encode_result encoded = utf8_encode(decoded.codepoint);
|
||||||
|
|
||||||
|
u8 *dest = arena_push_array(arena, u8, encoded.count8);
|
||||||
|
MEMCPY(dest, &encoded.chars8, encoded.count8);
|
||||||
|
|
||||||
|
pos32 += 1;
|
||||||
|
res.len += encoded.count8;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
/* utf16 <- utf8 */
|
/* utf16 <- utf8 */
|
||||||
struct string16 string16_from_string(struct arena *arena, struct string str8)
|
struct string16 string16_from_string(struct arena *arena, struct string str8)
|
||||||
{
|
{
|
||||||
@ -600,30 +539,6 @@ struct string16 string16_from_string(struct arena *arena, struct string str8)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* utf8 <- utf32 */
|
|
||||||
struct string string_from_string32(struct arena *arena, struct string32 str32)
|
|
||||||
{
|
|
||||||
struct string res = {
|
|
||||||
.len = 0,
|
|
||||||
.text = arena_dry_push(arena, u8)
|
|
||||||
};
|
|
||||||
|
|
||||||
u64 pos32 = 0;
|
|
||||||
while (pos32 < str32.len) {
|
|
||||||
struct string32 str32_remaining = { .len = (str32.len - pos32), .text = str32.text + pos32 };
|
|
||||||
struct utf32_decode_result decoded = utf32_decode(str32_remaining);
|
|
||||||
struct utf8_encode_result encoded = utf8_encode(decoded.codepoint);
|
|
||||||
|
|
||||||
u8 *dest = arena_push_array(arena, u8, encoded.count8);
|
|
||||||
MEMCPY(dest, &encoded.chars8, encoded.count8);
|
|
||||||
|
|
||||||
pos32 += 1;
|
|
||||||
res.len += encoded.count8;
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* utf32 <- utf8 */
|
/* utf32 <- utf8 */
|
||||||
struct string32 string32_from_string(struct arena *arena, struct string str8)
|
struct string32 string32_from_string(struct arena *arena, struct string str8)
|
||||||
{
|
{
|
||||||
@ -647,3 +562,93 @@ struct string32 string32_from_string(struct arena *arena, struct string str8)
|
|||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ========================== *
|
||||||
|
* Legacy strings
|
||||||
|
* ========================== */
|
||||||
|
|
||||||
|
/* C narrow strings */
|
||||||
|
|
||||||
|
u64 cstr_len(char *cstr)
|
||||||
|
{
|
||||||
|
char *end = cstr;
|
||||||
|
while (*end) {
|
||||||
|
++end;
|
||||||
|
}
|
||||||
|
return end - cstr;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *cstr_from_string(struct arena *arena, struct string src)
|
||||||
|
{
|
||||||
|
u8 *text = arena_push_array(arena, u8, src.len + 1);
|
||||||
|
MEMCPY(text, src.text, src.len);
|
||||||
|
text[src.len] = 0;
|
||||||
|
return (char *)text;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *cstr_buff_from_string(struct buffer dest_buff, struct string src)
|
||||||
|
{
|
||||||
|
if (dest_buff.size > 0) {
|
||||||
|
u64 len = min_u64(src.len, dest_buff.size - 1);
|
||||||
|
MEMCPY(dest_buff.data, src.text, len);
|
||||||
|
dest_buff.data[len] = 0;
|
||||||
|
}
|
||||||
|
return (char *)dest_buff.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct string string_from_cstr(char *cstr)
|
||||||
|
{
|
||||||
|
u64 len = cstr_len(cstr);
|
||||||
|
return (struct string) {
|
||||||
|
.len = len,
|
||||||
|
.text = (u8 *)cstr
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
struct string string_from_cstr_len(char *cstr, u64 len)
|
||||||
|
{
|
||||||
|
return (struct string) {
|
||||||
|
.text = (u8 *)cstr,
|
||||||
|
.len = len
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/* C wide strings */
|
||||||
|
|
||||||
|
u64 wstr_len(wchar_t *wstr)
|
||||||
|
{
|
||||||
|
wchar_t *end = wstr;
|
||||||
|
while (*end) {
|
||||||
|
++end;
|
||||||
|
}
|
||||||
|
return end - wstr;
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t *wstr_from_string(struct arena *arena, struct string src)
|
||||||
|
{
|
||||||
|
struct string16 str16 = string16_from_string(arena, src);
|
||||||
|
*arena_push(arena, u16) = 0;
|
||||||
|
return (wchar_t *)str16.text;
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t *wstr_from_string16(struct arena *arena, struct string16 src)
|
||||||
|
{
|
||||||
|
u16 *text = arena_push_array(arena, u16, src.len + 1);
|
||||||
|
text[src.len] = 0;
|
||||||
|
return (wchar_t *)text;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct string string_from_wstr(struct arena *arena, wchar_t *wstr)
|
||||||
|
{
|
||||||
|
struct string16 str16 = string16_from_wstr(wstr);
|
||||||
|
return string_from_string16(arena, str16);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct string16 string16_from_wstr(wchar_t *wstr)
|
||||||
|
{
|
||||||
|
u64 len = wstr_len(wstr);
|
||||||
|
return (struct string16) {
|
||||||
|
.len = len,
|
||||||
|
.text = (u16 *)wstr
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
27
src/string.h
27
src/string.h
@ -21,9 +21,7 @@ struct string string_from_float(struct arena *arena, f64 f, u32 precision);
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct string string_copy(struct arena *arena, struct string src);
|
struct string string_copy(struct arena *arena, struct string src);
|
||||||
struct string string_copy_buff(struct buffer buff, struct string src);
|
struct string string_copy_buff(struct buffer dest_buff, struct string src);
|
||||||
struct string string_from_cstr(char *cstr);
|
|
||||||
struct string string_from_cstr_len(char *cstr, u64 len);
|
|
||||||
struct string string_repeat(struct arena *arena, struct string src, u64 count);
|
struct string string_repeat(struct arena *arena, struct string src, u64 count);
|
||||||
struct string string_cat(struct arena *arena, struct string str1, struct string str2);
|
struct string string_cat(struct arena *arena, struct string str1, struct string str2);
|
||||||
struct string_array string_split(struct arena *arena, struct string str, struct string delim);
|
struct string_array string_split(struct arena *arena, struct string str, struct string delim);
|
||||||
@ -32,9 +30,6 @@ b32 string_eq(struct string str1, struct string str2);
|
|||||||
b32 string_contains(struct string str, struct string substring);
|
b32 string_contains(struct string str, struct string substring);
|
||||||
b32 string_starts_with(struct string str, struct string substring);
|
b32 string_starts_with(struct string str, struct string substring);
|
||||||
b32 string_ends_with(struct string str, struct string substring);
|
b32 string_ends_with(struct string str, struct string substring);
|
||||||
char *string_to_cstr(struct arena *arena, struct string str);
|
|
||||||
char *string_to_cstr_buff(struct string str, struct buffer buff);
|
|
||||||
wchar_t *string_to_wstr(struct arena *arena, struct string str);
|
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Format
|
* Format
|
||||||
@ -86,12 +81,28 @@ struct string _string_format(struct arena *arena, struct string fmt, ...);
|
|||||||
struct string string_formatv(struct arena *arena, struct string fmt, va_list args);
|
struct string string_formatv(struct arena *arena, struct string fmt, va_list args);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Unicode transformation
|
* Unicode
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct string string_from_string16(struct arena *arena, struct string16 str16);
|
struct string string_from_string16(struct arena *arena, struct string16 str16);
|
||||||
struct string16 string16_from_string(struct arena *arena, struct string str8);
|
|
||||||
struct string string_from_string32(struct arena *arena, struct string32 str32);
|
struct string string_from_string32(struct arena *arena, struct string32 str32);
|
||||||
|
struct string16 string16_from_string(struct arena *arena, struct string str8);
|
||||||
struct string32 string32_from_string(struct arena *arena, struct string str8);
|
struct string32 string32_from_string(struct arena *arena, struct string str8);
|
||||||
|
|
||||||
|
/* ========================== *
|
||||||
|
* Legacy strings
|
||||||
|
* ========================== */
|
||||||
|
|
||||||
|
u64 cstr_len(char *cstr);
|
||||||
|
char *cstr_from_string(struct arena *arena, struct string src);
|
||||||
|
char *cstr_buff_from_string(struct buffer dest_buff, struct string src);
|
||||||
|
struct string string_from_cstr(char *cstr);
|
||||||
|
struct string string_from_cstr_len(char *cstr, u64 len);
|
||||||
|
|
||||||
|
u64 wstr_len(wchar_t *wstr);
|
||||||
|
wchar_t *wstr_from_string(struct arena *arena, struct string src);
|
||||||
|
wchar_t *wstr_from_string16(struct arena *arena, struct string16 src);
|
||||||
|
struct string string_from_wstr(struct arena *arena, wchar_t *wstr);
|
||||||
|
struct string16 string16_from_wstr(wchar_t *wstr);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
20
src/sys.h
20
src/sys.h
@ -195,8 +195,8 @@ u64 sys_file_size(struct sys_file file);
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct sys_file_map {
|
struct sys_file_map {
|
||||||
u64 handle;
|
|
||||||
struct buffer mapped_memory;
|
struct buffer mapped_memory;
|
||||||
|
u64 handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sys_file_map sys_file_map_open_read(struct sys_file file);
|
struct sys_file_map sys_file_map_open_read(struct sys_file file);
|
||||||
@ -207,18 +207,20 @@ struct buffer sys_file_map_data(struct sys_file_map map);
|
|||||||
* Dir iter
|
* Dir iter
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
/* Opaque */
|
struct sys_file_filter_result {
|
||||||
struct sys_dir_iter;
|
struct string filename;
|
||||||
|
|
||||||
struct sys_dir_iter_info {
|
|
||||||
struct string file_name;
|
|
||||||
b32 is_dir;
|
b32 is_dir;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct sys_file_filter {
|
||||||
|
struct sys_file_filter_result info;
|
||||||
|
u64 handle;
|
||||||
|
};
|
||||||
|
|
||||||
/* Iterate all files in a directory */
|
/* Iterate all files in a directory */
|
||||||
struct sys_dir_iter *sys_dir_iter_begin(struct arena *arena, struct string dir_name);
|
struct sys_file_filter sys_file_filter_begin(struct arena *arena, struct string pattern);
|
||||||
struct sys_dir_iter_info *sys_dir_iter_next(struct arena *arena, struct sys_dir_iter *iter);
|
b32 sys_file_filter_next(struct arena *arena, struct sys_file_filter *iter);
|
||||||
void sys_dir_iter_end(struct sys_dir_iter *iter);
|
void sys_file_filter_end(struct sys_file_filter *iter);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Window
|
* Window
|
||||||
|
|||||||
278
src/sys_win32.c
278
src/sys_win32.c
@ -10,6 +10,7 @@
|
|||||||
#include "math.h"
|
#include "math.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "tls.h"
|
#include "tls.h"
|
||||||
|
#include "utf.h"
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <windowsx.h>
|
#include <windowsx.h>
|
||||||
@ -27,6 +28,7 @@
|
|||||||
#pragma comment(lib, "dwmapi")
|
#pragma comment(lib, "dwmapi")
|
||||||
|
|
||||||
#define SYS_WINDOW_EVENT_LISTENERS_MAX 512
|
#define SYS_WINDOW_EVENT_LISTENERS_MAX 512
|
||||||
|
#define WINDOW_CLASS_NAME L"power_play_window_class"
|
||||||
|
|
||||||
struct win32_thread_params {
|
struct win32_thread_params {
|
||||||
sys_thread_func *thread_func;
|
sys_thread_func *thread_func;
|
||||||
@ -107,7 +109,7 @@ GLOBAL struct {
|
|||||||
struct win32_thread_params *first_free_thread_params;
|
struct win32_thread_params *first_free_thread_params;
|
||||||
|
|
||||||
/* Windows */
|
/* Windows */
|
||||||
WNDCLASSEX window_class;
|
WNDCLASSEXW window_class;
|
||||||
struct sys_mutex windows_mutex;
|
struct sys_mutex windows_mutex;
|
||||||
struct arena windows_arena;
|
struct arena windows_arena;
|
||||||
struct win32_window *first_free_window;
|
struct win32_window *first_free_window;
|
||||||
@ -187,39 +189,39 @@ void sys_memory_decommit(void *address, u64 size)
|
|||||||
VirtualFree(address, size, MEM_DECOMMIT);
|
VirtualFree(address, size, MEM_DECOMMIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
|
||||||
* Wchar
|
|
||||||
*
|
|
||||||
* TODO: Move wide char ops to string.c and actually do proper decoding
|
|
||||||
* ========================== */
|
|
||||||
|
|
||||||
INTERNAL struct string wchar_path_to_string(struct arena *arena, wchar_t *src)
|
|
||||||
{
|
|
||||||
struct string str = { 0, arena_dry_push(arena, u8) };
|
|
||||||
while (1) {
|
|
||||||
wchar_t wchar = src[str.len];
|
|
||||||
if (wchar != 0) {
|
|
||||||
if (wchar == '\\') {
|
|
||||||
wchar = '/';
|
|
||||||
}
|
|
||||||
u8 *c = arena_push(arena, u8);
|
|
||||||
/* FIXME: We're ignoring the high byte here */
|
|
||||||
*c = (u8)(wchar & 0xFF);
|
|
||||||
++str.len;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* File system
|
* File system
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
|
INTERNAL struct string string_from_win32_path(struct arena *arena, wchar_t *src)
|
||||||
|
{
|
||||||
|
struct string res = {
|
||||||
|
.len = 0,
|
||||||
|
.text = arena_dry_push(arena, u8)
|
||||||
|
};
|
||||||
|
|
||||||
|
while (*src) {
|
||||||
|
struct string16 decode_str = { .len = *(src + 1) ? 2 : 1, .text = src };
|
||||||
|
struct utf16_decode_result decoded = utf16_decode(decode_str);
|
||||||
|
struct utf8_encode_result encoded = utf8_encode(decoded.codepoint);
|
||||||
|
u8 *dest = arena_push_array(arena, u8, encoded.count8);
|
||||||
|
for (u32 i = 0; i < encoded.count8; ++i) {
|
||||||
|
u8 byte = encoded.chars8[i];
|
||||||
|
if (byte == '\\') {
|
||||||
|
byte = '/';
|
||||||
|
}
|
||||||
|
dest[i] = byte;
|
||||||
|
}
|
||||||
|
res.len += encoded.count8;
|
||||||
|
src += decoded.advance16;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
struct string sys_get_write_path(struct arena *arena)
|
struct string sys_get_write_path(struct arena *arena)
|
||||||
{
|
{
|
||||||
wchar_t *p = NULL;
|
u16 *p = NULL;
|
||||||
/* TODO: cache this? */
|
/* TODO: cache this? */
|
||||||
HRESULT res = SHGetKnownFolderPath(
|
HRESULT res = SHGetKnownFolderPath(
|
||||||
&FOLDERID_LocalAppData,
|
&FOLDERID_LocalAppData,
|
||||||
@ -229,7 +231,7 @@ struct string sys_get_write_path(struct arena *arena)
|
|||||||
);
|
);
|
||||||
struct string path = { 0 };
|
struct string path = { 0 };
|
||||||
if (res == S_OK) {
|
if (res == S_OK) {
|
||||||
path = wchar_path_to_string(arena, p);
|
path = string_from_win32_path(arena, p);
|
||||||
}
|
}
|
||||||
CoTaskMemFree(p);
|
CoTaskMemFree(p);
|
||||||
return path;
|
return path;
|
||||||
@ -239,8 +241,8 @@ b32 sys_is_file(struct string path)
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct temp_arena scratch = scratch_begin_no_conflict();
|
struct temp_arena scratch = scratch_begin_no_conflict();
|
||||||
const char *path_cstr = string_to_cstr(scratch.arena, path);
|
wchar_t *path_wstr = wstr_from_string(scratch.arena, path);
|
||||||
DWORD attributes = GetFileAttributes(path_cstr);
|
DWORD attributes = GetFileAttributesW(path_wstr);
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
return attributes != INVALID_FILE_ATTRIBUTES && !(attributes & FILE_ATTRIBUTE_DIRECTORY);
|
return attributes != INVALID_FILE_ATTRIBUTES && !(attributes & FILE_ATTRIBUTE_DIRECTORY);
|
||||||
}
|
}
|
||||||
@ -248,8 +250,8 @@ b32 sys_is_file(struct string path)
|
|||||||
b32 sys_is_dir(struct string path)
|
b32 sys_is_dir(struct string path)
|
||||||
{
|
{
|
||||||
struct temp_arena scratch = scratch_begin_no_conflict();
|
struct temp_arena scratch = scratch_begin_no_conflict();
|
||||||
const char *path_cstr = string_to_cstr(scratch.arena, path);
|
wchar_t *path_wstr = wstr_from_string(scratch.arena, path);
|
||||||
DWORD attributes = GetFileAttributes(path_cstr);
|
DWORD attributes = GetFileAttributesW(path_wstr);
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
return attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY);
|
return attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY);
|
||||||
}
|
}
|
||||||
@ -258,10 +260,35 @@ void sys_mkdir(struct string path)
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct temp_arena scratch = scratch_begin_no_conflict();
|
struct temp_arena scratch = scratch_begin_no_conflict();
|
||||||
const char *path_cstr = string_to_cstr(scratch.arena, path);
|
wchar_t *path_wstr = wstr_from_string(scratch.arena, path);
|
||||||
b32 success = SHCreateDirectoryExA(NULL, path_cstr, NULL) == ERROR_SUCCESS;
|
int err_code = SHCreateDirectory(NULL, path_wstr);
|
||||||
(UNUSED)success;
|
struct string err = { 0 };
|
||||||
ASSERT(success);
|
switch (err_code) {
|
||||||
|
case ERROR_BAD_PATHNAME: {
|
||||||
|
err = STR("Bad path name");
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case ERROR_FILENAME_EXCED_RANGE: {
|
||||||
|
err = STR("Path name too long");
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case ERROR_FILE_EXISTS: {
|
||||||
|
err = STR("A file already exists at this location");
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case ERROR_CANCELLED: {
|
||||||
|
err = STR("User canceled the operation");
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
if (err.len > 0) {
|
||||||
|
struct string msg = string_format(scratch.arena,
|
||||||
|
STR("Failed to create directory \"%F\": %F"),
|
||||||
|
FMT_STR(path),
|
||||||
|
FMT_STR(err));
|
||||||
|
sys_panic(msg);
|
||||||
|
}
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -269,11 +296,11 @@ struct sys_file sys_file_open_read(struct string path)
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct temp_arena scratch = scratch_begin_no_conflict();
|
struct temp_arena scratch = scratch_begin_no_conflict();
|
||||||
const char *path_cstr = string_to_cstr(scratch.arena, path);
|
wchar_t *path_wstr = wstr_from_string(scratch.arena, path);
|
||||||
|
|
||||||
/* TODO: Handle errors / non-existing file (handle == INVALID_HANDLE_VALUE) */
|
/* TODO: Handle errors / non-existing file (handle == INVALID_HANDLE_VALUE) */
|
||||||
HANDLE handle = CreateFileA(
|
HANDLE handle = CreateFileW(
|
||||||
path_cstr,
|
path_wstr,
|
||||||
GENERIC_READ,
|
GENERIC_READ,
|
||||||
FILE_SHARE_READ,
|
FILE_SHARE_READ,
|
||||||
NULL,
|
NULL,
|
||||||
@ -290,9 +317,9 @@ struct sys_file sys_file_open_write(struct string path)
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct temp_arena scratch = scratch_begin_no_conflict();
|
struct temp_arena scratch = scratch_begin_no_conflict();
|
||||||
const char *path_cstr = string_to_cstr(scratch.arena, path);
|
wchar_t *path_wstr = wstr_from_string(scratch.arena, path);
|
||||||
HANDLE handle = CreateFileA(
|
HANDLE handle = CreateFileW(
|
||||||
path_cstr,
|
path_wstr,
|
||||||
GENERIC_WRITE,
|
GENERIC_WRITE,
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
@ -310,9 +337,9 @@ struct sys_file sys_file_open_append(struct string path)
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct temp_arena scratch = scratch_begin_no_conflict();
|
struct temp_arena scratch = scratch_begin_no_conflict();
|
||||||
const char *path_cstr = string_to_cstr(scratch.arena, path);
|
wchar_t *path_wstr = wstr_from_string(scratch.arena, path);
|
||||||
HANDLE handle = CreateFileA(
|
HANDLE handle = CreateFileW(
|
||||||
path_cstr,
|
path_wstr,
|
||||||
FILE_APPEND_DATA,
|
FILE_APPEND_DATA,
|
||||||
FILE_SHARE_READ,
|
FILE_SHARE_READ,
|
||||||
NULL,
|
NULL,
|
||||||
@ -395,7 +422,7 @@ u64 sys_file_size(struct sys_file file)
|
|||||||
|
|
||||||
struct sys_file_map sys_file_map_open_read(struct sys_file file)
|
struct sys_file_map sys_file_map_open_read(struct sys_file file)
|
||||||
{
|
{
|
||||||
HANDLE map_handle = CreateFileMappingA(
|
HANDLE map_handle = CreateFileMappingW(
|
||||||
(HANDLE)file.handle,
|
(HANDLE)file.handle,
|
||||||
NULL,
|
NULL,
|
||||||
PAGE_READONLY,
|
PAGE_READONLY,
|
||||||
@ -451,60 +478,57 @@ struct buffer sys_file_map_data(struct sys_file_map map)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Dir iter
|
* File iter
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct sys_dir_iter {
|
struct win32_file_filter {
|
||||||
HANDLE handle;
|
HANDLE find_handle;
|
||||||
char *dir_path_cstr;
|
wchar_t *filter_wstr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sys_dir_iter *sys_dir_iter_begin(struct arena *arena, struct string dir_name)
|
struct sys_file_filter sys_file_filter_begin(struct arena *arena, struct string pattern)
|
||||||
{
|
{
|
||||||
struct temp_arena scratch = scratch_begin(arena);
|
struct sys_file_filter filter = { 0 };
|
||||||
struct sys_dir_iter *iter = arena_push_zero(arena, struct sys_dir_iter);
|
struct win32_file_filter *filter_internal = arena_push_zero(arena, struct win32_file_filter);
|
||||||
if (dir_name.len >= 1 && dir_name.text[dir_name.len - 1] == '/') {
|
filter_internal->filter_wstr = wstr_from_string(arena, pattern);
|
||||||
struct string dir_path_w_asterisk = string_cat(scratch.arena, dir_name, STR("*"));
|
filter.handle = (u64)filter_internal;
|
||||||
iter->dir_path_cstr = string_to_cstr(arena, dir_path_w_asterisk);
|
return filter;
|
||||||
} else {
|
|
||||||
/* Invalid directory path supplied */
|
|
||||||
ASSERT(false);
|
|
||||||
}
|
|
||||||
scratch_end(scratch);
|
|
||||||
return iter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sys_dir_iter_info *sys_dir_iter_next(struct arena *arena, struct sys_dir_iter *iter)
|
b32 sys_file_filter_next(struct arena *arena, struct sys_file_filter *filter)
|
||||||
{
|
{
|
||||||
WIN32_FIND_DATA find_file_data = { 0 };
|
struct win32_file_filter *filter_internal = (struct win32_file_filter *)filter->handle;
|
||||||
|
|
||||||
|
WIN32_FIND_DATAW find_file_data = { 0 };
|
||||||
b32 found = false;
|
b32 found = false;
|
||||||
|
|
||||||
if (iter->handle) {
|
if (filter_internal->find_handle) {
|
||||||
found = FindNextFileA(iter->handle, &find_file_data);
|
found = FindNextFileW(filter_internal->find_handle, &find_file_data);
|
||||||
} else if (iter->dir_path_cstr) {
|
} else {
|
||||||
iter->handle = FindFirstFileExA(iter->dir_path_cstr, FindExInfoStandard, &find_file_data, FindExSearchNameMatch, NULL, FIND_FIRST_EX_LARGE_FETCH);
|
filter_internal->find_handle = FindFirstFileExW(filter_internal->filter_wstr, FindExInfoStandard, &find_file_data, FindExSearchNameMatch, NULL, FIND_FIRST_EX_CASE_SENSITIVE | FIND_FIRST_EX_LARGE_FETCH);
|
||||||
found = iter->handle != INVALID_HANDLE_VALUE;
|
found = filter_internal->find_handle != INVALID_HANDLE_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sys_dir_iter_info *info = NULL;
|
|
||||||
if (found) {
|
if (found) {
|
||||||
struct string file_name = string_from_cstr(find_file_data.cFileName);
|
struct string file_name = string_from_wstr(arena, find_file_data.cFileName);
|
||||||
if (string_eq(file_name, STR(".")) || string_eq(file_name, STR(".."))) {
|
if (string_eq(file_name, STR(".")) || string_eq(file_name, STR(".."))) {
|
||||||
/* Skip initial '.' and '..' matches */
|
/* Skip initial '.' and '..' matches */
|
||||||
info = sys_dir_iter_next(arena, iter);
|
found = sys_file_filter_next(arena, filter);
|
||||||
} else {
|
} else {
|
||||||
info = arena_push_zero(arena, struct sys_dir_iter_info);
|
filter->info.is_dir = find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
|
||||||
info->is_dir = find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
|
filter->info.filename = string_copy(arena, file_name);
|
||||||
info->file_name = string_copy(arena, file_name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return info;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sys_dir_iter_end(struct sys_dir_iter *iter)
|
void sys_file_filter_end(struct sys_file_filter *filter)
|
||||||
{
|
{
|
||||||
FindClose(iter->handle);
|
struct win32_file_filter *filter_internal = (struct win32_file_filter *)filter->handle;
|
||||||
|
if (filter_internal->find_handle) {
|
||||||
|
FindClose(filter_internal->find_handle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
@ -536,10 +560,10 @@ INTERNAL HWND win32_create_window(struct win32_window *window)
|
|||||||
DWORD exstyle = WS_EX_APPWINDOW | WS_EX_NOREDIRECTIONBITMAP;
|
DWORD exstyle = WS_EX_APPWINDOW | WS_EX_NOREDIRECTIONBITMAP;
|
||||||
|
|
||||||
/* TODO: Check for hwnd success */
|
/* TODO: Check for hwnd success */
|
||||||
HWND hwnd = CreateWindowExA(
|
HWND hwnd = CreateWindowExW(
|
||||||
exstyle,
|
exstyle,
|
||||||
L.window_class.lpszClassName,
|
L.window_class.lpszClassName,
|
||||||
"",
|
L"",
|
||||||
WS_OVERLAPPEDWINDOW,
|
WS_OVERLAPPEDWINDOW,
|
||||||
CW_USEDEFAULT,
|
CW_USEDEFAULT,
|
||||||
CW_USEDEFAULT,
|
CW_USEDEFAULT,
|
||||||
@ -556,7 +580,7 @@ INTERNAL HWND win32_create_window(struct win32_window *window)
|
|||||||
DwmSetWindowAttribute(hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, (LPCVOID)&dark_mode, sizeof(dark_mode));
|
DwmSetWindowAttribute(hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, (LPCVOID)&dark_mode, sizeof(dark_mode));
|
||||||
|
|
||||||
/* Set window as userdata */
|
/* Set window as userdata */
|
||||||
SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)window);
|
SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR)window);
|
||||||
|
|
||||||
return hwnd;
|
return hwnd;
|
||||||
}
|
}
|
||||||
@ -779,7 +803,7 @@ INTERNAL void win32_update_window_from_settings(struct win32_window *window, str
|
|||||||
if (fullscreen) {
|
if (fullscreen) {
|
||||||
if (!old_fullscreen) {
|
if (!old_fullscreen) {
|
||||||
/* Entering fullscreen */
|
/* Entering fullscreen */
|
||||||
SetWindowLongPtrA(hwnd, GWL_STYLE, WS_POPUP);
|
SetWindowLongPtrW(hwnd, GWL_STYLE, WS_POPUP);
|
||||||
}
|
}
|
||||||
rect = (RECT) {
|
rect = (RECT) {
|
||||||
.left = 0,
|
.left = 0,
|
||||||
@ -790,7 +814,7 @@ INTERNAL void win32_update_window_from_settings(struct win32_window *window, str
|
|||||||
} else {
|
} else {
|
||||||
if (old_fullscreen) {
|
if (old_fullscreen) {
|
||||||
/* Leaving fullscreen */
|
/* Leaving fullscreen */
|
||||||
SetWindowLongPtrA(hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW);
|
SetWindowLongPtrW(hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW);
|
||||||
}
|
}
|
||||||
rect = (RECT) {
|
rect = (RECT) {
|
||||||
.left = settings->floating_x,
|
.left = settings->floating_x,
|
||||||
@ -808,21 +832,26 @@ INTERNAL void win32_update_window_from_settings(struct win32_window *window, str
|
|||||||
};
|
};
|
||||||
SetWindowPlacement(hwnd, &wp);
|
SetWindowPlacement(hwnd, &wp);
|
||||||
|
|
||||||
SetWindowTextA(hwnd, settings->title);
|
{
|
||||||
|
struct temp_arena scratch = scratch_begin_no_conflict();
|
||||||
|
wchar_t *title_wstr = wstr_from_string(scratch.arena, string_from_cstr(settings->title));
|
||||||
|
SetWindowTextW(hwnd, title_wstr);
|
||||||
|
scratch_end(scratch);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL void win32_window_wake(struct win32_window *window)
|
INTERNAL void win32_window_wake(struct win32_window *window)
|
||||||
{
|
{
|
||||||
/* Post a blank message to the window's thread message queue to wake it. */
|
/* Post a blank message to the window's thread message queue to wake it. */
|
||||||
PostMessageA(window->hwnd, WM_NULL, 0, 0);
|
PostMessageW(window->hwnd, WM_NULL, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL LRESULT CALLBACK win32_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
|
INTERNAL LRESULT CALLBACK win32_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
|
||||||
{
|
{
|
||||||
struct win32_window *window = (struct win32_window *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
|
struct win32_window *window = (struct win32_window *)GetWindowLongPtrW(hwnd, GWLP_USERDATA);
|
||||||
|
|
||||||
if (!window) {
|
if (!window) {
|
||||||
return DefWindowProcA(hwnd, msg, wparam, lparam);
|
return DefWindowProcW(hwnd, msg, wparam, lparam);
|
||||||
}
|
}
|
||||||
|
|
||||||
LRESULT result = 0;
|
LRESULT result = 0;
|
||||||
@ -834,7 +863,7 @@ INTERNAL LRESULT CALLBACK win32_window_proc(HWND hwnd, UINT msg, WPARAM wparam,
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case WM_PAINT: {
|
case WM_PAINT: {
|
||||||
result = DefWindowProcA(hwnd, msg, wparam, lparam);
|
result = DefWindowProcW(hwnd, msg, wparam, lparam);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case WM_MOVE:
|
case WM_MOVE:
|
||||||
@ -842,13 +871,13 @@ INTERNAL LRESULT CALLBACK win32_window_proc(HWND hwnd, UINT msg, WPARAM wparam,
|
|||||||
case WM_SIZE:
|
case WM_SIZE:
|
||||||
case WM_SIZING: {
|
case WM_SIZING: {
|
||||||
win32_update_window_from_system(window);
|
win32_update_window_from_system(window);
|
||||||
result = DefWindowProcA(hwnd, msg, wparam, lparam);
|
result = DefWindowProcW(hwnd, msg, wparam, lparam);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
/* Keyboard buttons */
|
/* Keyboard buttons */
|
||||||
case WM_SYSKEYUP:
|
case WM_SYSKEYUP:
|
||||||
case WM_SYSKEYDOWN: {
|
case WM_SYSKEYDOWN: {
|
||||||
result = DefWindowProcA(hwnd, msg, wparam, lparam);
|
result = DefWindowProcW(hwnd, msg, wparam, lparam);
|
||||||
} FALLTHROUGH;
|
} FALLTHROUGH;
|
||||||
case WM_KEYUP:
|
case WM_KEYUP:
|
||||||
case WM_KEYDOWN: {
|
case WM_KEYDOWN: {
|
||||||
@ -997,7 +1026,7 @@ INTERNAL LRESULT CALLBACK win32_window_proc(HWND hwnd, UINT msg, WPARAM wparam,
|
|||||||
|
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
result = DefWindowProcA(hwnd, msg, wparam, lparam);
|
result = DefWindowProcW(hwnd, msg, wparam, lparam);
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1476,7 +1505,7 @@ INTERNAL DWORD WINAPI win32_thread_proc(LPVOID params)
|
|||||||
struct string thread_name = string_from_cstr(thread_params.thread_name_cstr);
|
struct string thread_name = string_from_cstr(thread_params.thread_name_cstr);
|
||||||
if (thread_name.len > 0) {
|
if (thread_name.len > 0) {
|
||||||
struct temp_arena scratch = scratch_begin_no_conflict();
|
struct temp_arena scratch = scratch_begin_no_conflict();
|
||||||
wchar_t *wc_thread_name = string_to_wstr(scratch.arena, thread_name);
|
wchar_t *wc_thread_name = wstr_from_string(scratch.arena, thread_name);
|
||||||
SetThreadDescription(GetCurrentThread(), wc_thread_name);
|
SetThreadDescription(GetCurrentThread(), wc_thread_name);
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
}
|
}
|
||||||
@ -1509,7 +1538,7 @@ struct sys_thread sys_thread_init(sys_thread_func *thread_func, void *thread_dat
|
|||||||
tp->thread_data = thread_data;
|
tp->thread_data = thread_data;
|
||||||
|
|
||||||
/* Copy thread name to params */
|
/* Copy thread name to params */
|
||||||
string_to_cstr_buff(thread_name, BUFFER_FROM_ARRAY(tp->thread_name_cstr));
|
cstr_buff_from_string(BUFFER_FROM_ARRAY(tp->thread_name_cstr), thread_name);
|
||||||
|
|
||||||
HANDLE handle = CreateThread(
|
HANDLE handle = CreateThread(
|
||||||
NULL,
|
NULL,
|
||||||
@ -1558,10 +1587,10 @@ void sys_thread_assert(u32 tid)
|
|||||||
|
|
||||||
void sys_message_box(enum sys_message_box_kind kind, struct string message)
|
void sys_message_box(enum sys_message_box_kind kind, struct string message)
|
||||||
{
|
{
|
||||||
char message_buff[4096] = { 0 };
|
struct temp_arena scratch = scratch_begin_no_conflict();
|
||||||
char *message_cstr = string_to_cstr_buff(message, BUFFER_FROM_ARRAY(message_buff));
|
wchar_t *message_wstr = wstr_from_string(scratch.arena, message);
|
||||||
|
|
||||||
const char *title = "";
|
const wchar_t *title = L"";
|
||||||
UINT mbox_type = 0;
|
UINT mbox_type = 0;
|
||||||
|
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
@ -1570,22 +1599,24 @@ void sys_message_box(enum sys_message_box_kind kind, struct string message)
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case SYS_MESSAGE_BOX_KIND_WARNING: {
|
case SYS_MESSAGE_BOX_KIND_WARNING: {
|
||||||
title = "Warning";
|
title = L"Warning";
|
||||||
mbox_type = MB_ICONWARNING;
|
mbox_type = MB_ICONWARNING;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case SYS_MESSAGE_BOX_KIND_ERROR: {
|
case SYS_MESSAGE_BOX_KIND_ERROR: {
|
||||||
title = "Error";
|
title = L"Error";
|
||||||
mbox_type = MB_ICONERROR;
|
mbox_type = MB_ICONERROR;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case SYS_MESSAGE_BOX_KIND_FATAL: {
|
case SYS_MESSAGE_BOX_KIND_FATAL: {
|
||||||
title = "Fatal error";
|
title = L"Fatal error";
|
||||||
mbox_type = MB_ICONSTOP;
|
mbox_type = MB_ICONSTOP;
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageBoxExA(NULL, message_cstr, title, mbox_type, 0);
|
MessageBoxExW(NULL, message_wstr, title, mbox_type, 0);
|
||||||
|
|
||||||
|
scratch_end(scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
@ -1650,21 +1681,30 @@ u32 sys_rand_u32(void)
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sys_panic_raw(char *msg_cstr)
|
INTERNAL void panic_exit(void)
|
||||||
{
|
{
|
||||||
/* FIXME: Exit other threads before showing message box */
|
|
||||||
MessageBoxExA(NULL, msg_cstr, "Fatal error", MB_ICONSTOP, 0);
|
|
||||||
ASSERT(false);
|
ASSERT(false);
|
||||||
sys_exit();
|
sys_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sys_panic_raw(char *msg_cstr)
|
||||||
|
{
|
||||||
|
/* FIXME: Exit other threads before showing message box */
|
||||||
|
MessageBoxExA(NULL, msg_cstr, "Fatal error", MB_ICONSTOP, 0);
|
||||||
|
panic_exit();
|
||||||
|
}
|
||||||
|
|
||||||
void sys_panic(struct string msg)
|
void sys_panic(struct string msg)
|
||||||
{
|
{
|
||||||
struct temp_arena scratch = scratch_begin_no_conflict();
|
/* FIXME: Exit other threads before showing message box */
|
||||||
logf_critical("Panicking: %F", FMT_STR(msg));
|
logf_critical("Panicking: %F", FMT_STR(msg));
|
||||||
struct string prepend = STR("A fatal error has occured and the application needs to exit:\n\n");
|
struct temp_arena scratch = scratch_begin_no_conflict();
|
||||||
msg = string_cat(scratch.arena, prepend, msg);
|
msg = string_cat(scratch.arena,
|
||||||
sys_panic_raw(string_to_cstr(scratch.arena, msg));
|
STR("A fatal error has occured and the application needs to exit:\n\n"),
|
||||||
|
msg);
|
||||||
|
wchar_t *msg_wstr = wstr_from_string(scratch.arena, msg);
|
||||||
|
MessageBoxExW(NULL, msg_wstr, L"Fatal error", MB_ICONSTOP, 0);
|
||||||
|
panic_exit();
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1782,14 +1822,14 @@ INTERNAL SYS_THREAD_FUNC_DEF(app_thread_entry_point, arg)
|
|||||||
app_entry_point();
|
app_entry_point();
|
||||||
}
|
}
|
||||||
|
|
||||||
int CALLBACK WinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev_instance, _In_ LPSTR command_line, _In_ int show_code)
|
int CALLBACK wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev_instance, _In_ LPWSTR command_line, _In_ int show_code)
|
||||||
{
|
{
|
||||||
(UNUSED)instance;
|
(UNUSED)instance;
|
||||||
(UNUSED)prev_instance;
|
(UNUSED)prev_instance;
|
||||||
(UNUSED)command_line;
|
(UNUSED)command_line;
|
||||||
(UNUSED)show_code;
|
(UNUSED)show_code;
|
||||||
|
|
||||||
const char *error_msg = NULL;
|
const wchar_t *error_msg = NULL;
|
||||||
|
|
||||||
SetThreadDescription(GetCurrentThread(), L"Main thread");
|
SetThreadDescription(GetCurrentThread(), L"Main thread");
|
||||||
|
|
||||||
@ -1816,7 +1856,7 @@ int CALLBACK WinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev_instance,
|
|||||||
L.thread_tls_index = TlsAlloc();
|
L.thread_tls_index = TlsAlloc();
|
||||||
if (L.thread_tls_index == TLS_OUT_OF_INDEXES) {
|
if (L.thread_tls_index == TLS_OUT_OF_INDEXES) {
|
||||||
/* TODO: GetLastError */
|
/* TODO: GetLastError */
|
||||||
error_msg = "Platform initialization error: TLS_OUT_OF_INDEXES";
|
error_msg = L"Platform initialization error: TLS_OUT_OF_INDEXES";
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1840,9 +1880,9 @@ int CALLBACK WinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev_instance,
|
|||||||
/* Create window class */
|
/* Create window class */
|
||||||
{
|
{
|
||||||
/* Register the window class */
|
/* Register the window class */
|
||||||
WNDCLASSEX *wc = &L.window_class;
|
WNDCLASSEXW *wc = &L.window_class;
|
||||||
wc->cbSize = sizeof(WNDCLASSEX);
|
wc->cbSize = sizeof(WNDCLASSEX);
|
||||||
wc->lpszClassName = "power_play_window_class";
|
wc->lpszClassName = WINDOW_CLASS_NAME;
|
||||||
wc->hCursor = LoadCursor(NULL, IDC_ARROW);
|
wc->hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||||
wc->style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
|
wc->style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
|
||||||
//wc->hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
|
//wc->hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
|
||||||
@ -1854,9 +1894,9 @@ int CALLBACK WinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev_instance,
|
|||||||
GetModuleFileName(instance, path, MAX_PATH);
|
GetModuleFileName(instance, path, MAX_PATH);
|
||||||
ExtractIconEx(path, 0, &wc->hIcon, &wc->hIconSm, 1);
|
ExtractIconEx(path, 0, &wc->hIcon, &wc->hIconSm, 1);
|
||||||
|
|
||||||
if (!RegisterClassExA(wc)) {
|
if (!RegisterClassExW(wc)) {
|
||||||
/* TODO: GetLastError */
|
/* TODO: GetLastError */
|
||||||
error_msg = "Failed to register window class";
|
error_msg = L"Failed to register window class";
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1871,14 +1911,14 @@ int CALLBACK WinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev_instance,
|
|||||||
|
|
||||||
if (!RegisterRawInputDevices(&rid, 1, sizeof(rid))) {
|
if (!RegisterRawInputDevices(&rid, 1, sizeof(rid))) {
|
||||||
/* TODO: GetLastError */
|
/* TODO: GetLastError */
|
||||||
error_msg = "Failed to register raw input device";
|
error_msg = L"Failed to register raw input device";
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
error:
|
error:
|
||||||
if (error_msg) {
|
if (error_msg) {
|
||||||
MessageBoxExA(NULL, error_msg, "Fatal initialization error", MB_ICONSTOP, 0);
|
MessageBoxExW(NULL, error_msg, L"Fatal initialization error", MB_ICONSTOP, 0);
|
||||||
ASSERT(false);
|
ASSERT(false);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -1910,9 +1950,9 @@ __attribute((used))
|
|||||||
int _fltused;
|
int _fltused;
|
||||||
|
|
||||||
__attribute((used))
|
__attribute((used))
|
||||||
void __stdcall WinMainCRTStartup(void)
|
void __stdcall wWinMainCRTStartup(void)
|
||||||
{
|
{
|
||||||
int result = WinMain(GetModuleHandle(0), 0, GetCommandLineA(), 0);
|
int result = wWinMain(GetModuleHandle(0), 0, GetCommandLineW(), 0);
|
||||||
ExitProcess(result);
|
ExitProcess(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -247,7 +247,7 @@ struct asset *texture_load_asset(struct string path, b32 help)
|
|||||||
STR("Texture path \"%F\" too long!"),
|
STR("Texture path \"%F\" too long!"),
|
||||||
FMT_STR(path)));
|
FMT_STR(path)));
|
||||||
}
|
}
|
||||||
string_to_cstr_buff(path, BUFFER_FROM_ARRAY(params->path_cstr));
|
cstr_buff_from_string(BUFFER_FROM_ARRAY(params->path_cstr), path);
|
||||||
params->path_len = path.len;
|
params->path_len = path.len;
|
||||||
params->asset = asset;
|
params->asset = asset;
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user