From 32920988ed16940a45f774a9c6283abdc0408a6a Mon Sep 17 00:00:00 2001 From: Aldrik Ramaekers Date: Sat, 22 Feb 2020 19:56:12 +0100 Subject: licensing --- src/licensing.c | 110 +- src/licensing.h | 40 +- src/linux/platform.c | 12 +- src/platform.h | 447 ++++---- src/windows/platform.c | 2680 ++++++++++++++++++++++++------------------------ 5 files changed, 1690 insertions(+), 1599 deletions(-) (limited to 'src') diff --git a/src/licensing.c b/src/licensing.c index 834313f..f619970 100644 --- a/src/licensing.c +++ b/src/licensing.c @@ -1,36 +1,74 @@ -/* -* BSD 2-Clause “Simplified” License -* Copyright (c) 2019, Aldrik Ramaekers, aldrik.ramaekers@protonmail.com -* All rights reserved. -*/ - -#include "external/cJSON.h" - -static void* validate_license_thread(void *arg) -{ - char params[50]; - sprintf(params, "can_run?ti=%s", license_key); - - char response[MAX_INPUT_LENGTH]; - if (platform_send_http_request("api.aldrik.org", params, response)) - { - cJSON *result = cJSON_Parse(response); - if (!result) return false; - cJSON *canRun = cJSON_GetObjectItem(result, "canRun"); - license_is_valid = canRun->valueint; - } - - return 0; -} - -void validate_license() -{ - license_is_valid = true; - -#ifdef MODE_DEVELOPER - return; -#endif - - thread license_thread = thread_start(validate_license_thread, NULL); - thread_detach(&license_thread); -} +/* +* BSD 2-Clause “Simplified” License +* Copyright (c) 2019, Aldrik Ramaekers, aldrik.ramaekers@protonmail.com +* All rights reserved. +*/ + +#include "external/cJSON.h" + +static void* validate_license_thread(void *arg) +{ + char *mac_address = arg; + + char params[80]; + sprintf(params, "can_run?ti=%s&addr=%s", license_key, mac_address); + + char response[MAX_INPUT_LENGTH]; + while (main_window->is_open) + { + // send activity ping + if (platform_send_http_request("api.aldrik.org", params, response)) + { + cJSON *result = cJSON_Parse(response); + if (!result) return false; + cJSON *response = cJSON_GetObjectItem(result, "response"); + + if (response) + global_license_status = response->valueint; + } + + thread_sleep(5*1000*1000); // 5s + } + + mem_free(mac_address); + return 0; +} + +void validate_license() +{ + char *mac_address_buffer = mem_alloc(30); + platform_get_mac_address(mac_address_buffer, 30); + +#ifdef MODE_DEVELOPER + return; +#endif + + thread license_thread = thread_start(validate_license_thread, mac_address_buffer); + thread_detach(&license_thread); +} + +bool license_check_status() +{ + if (global_license_status == LICENSE_STATUS_VALID) + { + return true; + } + else if (global_license_status == LICENSE_STATUS_INVALID) + { + char message[200]; + sprintf(message, localize("invalid_license"), license_key); + platform_show_message(main_window, message, localize("license_error")); + main_window->is_open = false; + return false; + } + else if (global_license_status == LICENSE_STATUS_TOO_MANY_USERS) + { + char message[200]; + sprintf(message, localize("too_many_users_using_license"), license_key); + platform_show_message(main_window, message, localize("license_error")); + main_window->is_open = false; + return false; + } + + return true; +} \ No newline at end of file diff --git a/src/licensing.h b/src/licensing.h index 5255ffd..471dcd9 100644 --- a/src/licensing.h +++ b/src/licensing.h @@ -1,17 +1,25 @@ -/* -* BSD 2-Clause “Simplified” License -* Copyright (c) 2019, Aldrik Ramaekers, aldrik.ramaekers@protonmail.com -* All rights reserved. -*/ - -#ifndef INCLUDE_LICENSING -#define INCLUDE_LICENSING - -// NOTE DO NOT TOUCH THIS! -char license_key[18] = { "[LICENSELOCATION]" }; -// NOTE DO NOT TOUCH THIS! - -bool license_is_valid = true; -void validate_license(); - +/* +* BSD 2-Clause “Simplified” License +* Copyright (c) 2019, Aldrik Ramaekers, aldrik.ramaekers@protonmail.com +* All rights reserved. +*/ + +#ifndef INCLUDE_LICENSING +#define INCLUDE_LICENSING + +typedef enum t_license_status +{ + LICENSE_STATUS_VALID = 1, + LICENSE_STATUS_INVALID = 2, + LICENSE_STATUS_TOO_MANY_USERS = 3, +} license_status; + +// NOTE DO NOT TOUCH THIS! +char license_key[18] = { "[LICENSELOCATION]" }; +// NOTE DO NOT TOUCH THIS! + +license_status global_license_status = LICENSE_STATUS_VALID; +void validate_license(); +bool license_check_status(); + #endif \ No newline at end of file diff --git a/src/linux/platform.c b/src/linux/platform.c index 8e8f01d..4915138 100644 --- a/src/linux/platform.c +++ b/src/linux/platform.c @@ -615,9 +615,9 @@ inline void platform_init(int argc, char **argv) char buf[MAX_INPUT_LENGTH]; get_directory_from_path(buf, binary_path); string_copyn(binary_path, buf, MAX_INPUT_LENGTH); - + curl = curl_easy_init(); - + assets_create(); } @@ -1613,7 +1613,7 @@ uint write_cb(char *in, uint size, uint nmemb, char *buffer) bool platform_send_http_request(char *url, char *params, char *response_buffer) { string_copyn(response_buffer, "", MAX_INPUT_LENGTH); - + char fullurl[200]; sprintf(fullurl, "https://%s/%s", url, params); curl_easy_setopt(curl, CURLOPT_URL,fullurl); @@ -1625,6 +1625,12 @@ bool platform_send_http_request(char *url, char *params, char *response_buffer) curl_easy_setopt(curl, CURLOPT_WRITEDATA, response_buffer); CURLcode res = curl_easy_perform(curl); if (res != CURLE_OK) return false; + + return true; +} +bool platform_get_mac_address(char *buffer, s32 buf_size) +{ + string_copyn(buffer, "", buf_size); return true; } \ No newline at end of file diff --git a/src/platform.h b/src/platform.h index 5575dcf..35ec81b 100644 --- a/src/platform.h +++ b/src/platform.h @@ -1,224 +1,225 @@ -/* -* BSD 2-Clause “Simplified” License -* Copyright (c) 2019, Aldrik Ramaekers, aldrik.ramaekers@protonmail.com -* All rights reserved. -*/ - -#ifndef INCLUDE_PLATFORM -#define INCLUDE_PLATFORM - -typedef struct t_platform_window platform_window; - -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// - -typedef struct t_found_file -{ - char *matched_filter; - char *path; -} found_file; - -typedef struct t_file_match -{ - found_file file; - s16 file_error; - s32 file_size; - - u32 line_nr; - s32 word_match_offset; - s32 word_match_length; - s32 word_match_offset_x; // highlight render offset - s32 word_match_width; // highlight render width - char *line_info; // will be null when no match is found -} file_match; - -typedef struct t_search_result -{ - array work_queue; - array files; - array matches; - u64 find_duration_us; - array errors; - bool show_error_message; // error occured - bool found_file_matches; // found/finding file matches - s32 files_searched; - s32 files_matched; - s32 search_result_source_dir_len; - bool match_found; // found text match - mutex mutex; - bool walking_file_system; - bool cancel_search; - bool done_finding_matches; - s32 search_id; - u64 start_time; - bool done_finding_files; - memory_bucket mem_bucket; - bool is_command_line_search; - bool threads_closed; - - char *export_path; - char *file_filter; - char *directory_to_search; - char *text_to_find; - s32 max_thread_count; - s32 max_file_size; - bool is_recursive; -} search_result; - -typedef struct t_find_text_args -{ - file_match file; - search_result *search_result_buffer; -} find_text_args; - -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// - -typedef struct t_file_content -{ - s64 content_length; - void *content; - s16 file_error; -} file_content; - -typedef enum t_time_type -{ - TIME_FULL, // realtime - TIME_THREAD, // run time for calling thread - TIME_PROCESS, // run time for calling process -} time_type; - -typedef enum t_time_precision -{ - TIME_NS, // nanoseconds - TIME_US, // microseconds - TIME_MILI_S, // miliseconds - TIME_S, // seconds -} time_precision; - -typedef struct t_cpu_info -{ - s32 model; - char model_name[255]; - float32 frequency; - u32 cache_size; - u32 cache_alignment; -} cpu_info; - -typedef enum t_file_dialog_type -{ - OPEN_FILE, - OPEN_DIRECTORY, - SAVE_FILE, -} file_dialog_type; - -typedef enum t_file_open_error -{ - FILE_ERROR_TOO_MANY_OPEN_FILES_PROCESS = 1, - FILE_ERROR_TOO_MANY_OPEN_FILES_SYSTEM = 2, - FILE_ERROR_NO_ACCESS = 3, - FILE_ERROR_NOT_FOUND = 4, - FILE_ERROR_CONNECTION_ABORTED = 5, - FILE_ERROR_CONNECTION_REFUSED = 6, - FILE_ERROR_NETWORK_DOWN = 7, - FILE_ERROR_REMOTE_IO_ERROR = 8, - FILE_ERROR_STALE = 9, // NFS server file is removed/renamed - FILE_ERROR_GENERIC = 10, -} file_open_error; - -struct open_dialog_args -{ - char *buffer; - char *file_filter; - char *start_path; - char *default_save_file_extension; - file_dialog_type type; -}; - -typedef struct t_list_file_args -{ - array *list; - char *start_dir; - char *pattern; - bool recursive; - bool include_directories; - bool *state; - bool *is_cancelled; - memory_bucket *bucket; -} list_file_args; - -typedef enum t_cursor_type -{ - CURSOR_DEFAULT, - CURSOR_POINTER, -} cursor_type; - -typedef struct t_vec2 -{ - s32 x; - s32 y; -} vec2; - -platform_window *main_window = 0; -platform_window *settings_window = 0; - -bool platform_window_is_valid(platform_window *window); -platform_window platform_open_window(char *name, u16 width, u16 height, u16 max_w, u16 max_h, u16 min_w, u16 min_h); -void platform_get_focus(platform_window *window); -bool platform_set_clipboard(platform_window *window, char *buffer); -bool platform_get_clipboard(platform_window *window, char *buffer); -void platform_window_set_size(platform_window *window, u16 width, u16 height); -void platform_window_set_position(platform_window *window, u16 x, u16 y); -void platform_destroy_window(platform_window *window); -void platform_handle_events(platform_window *window, mouse_input *mouse, keyboard_input *keyboard); -void platform_window_swap_buffers(platform_window *window); -void platform_set_cursor(platform_window *window, cursor_type type); -void platform_window_set_title(platform_window *window, char *name); -file_content platform_read_file_content(char *path, const char *mode); -bool platform_write_file_content(char *path, const char *mode, char *buffer, s32 len); -void platform_destroy_file_content(file_content *content); -bool get_active_directory(char *buffer); -bool set_active_directory(char *path); -void platform_show_message(platform_window *window, char *message, char *title); -array get_filters(char *filter); -void platform_list_files_block(array *list, char *start_dir, array filters, bool recursive, memory_bucket *bucket, bool include_directories, bool *is_cancelled); -void platform_list_files(array *list, char *start_dir, char *filter, bool recursive, memory_bucket *bucket, bool *is_cancelled, bool *state); -void platform_open_file_dialog(file_dialog_type type, char *buffer, char *file_filter, char *start_path); -bool is_platform_in_darkmode(); -void *platform_open_file_dialog_block(void *arg); -char *platform_get_full_path(char *file); -void platform_open_url(char *command); -bool platform_send_http_request(char *url, char *params, char *response_buffer); -void platform_run_command(char *command); -void platform_window_make_current(platform_window *window); -void platform_init(int argc, char **argv); -void platform_destroy(); -void platform_set_icon(platform_window *window, image *img); -void platform_autocomplete_path(char *buffer, bool want_dir); -bool platform_directory_exists(char *path); -void platform_create_directory(char *path); -bool platform_file_exists(char *path); -void platform_show_alert(char *title, char *message); -char *get_config_save_location(char *buffer); -char *get_file_extension(char *path); -void get_name_from_path(char *buffer, char *path); -void get_directory_from_path(char *buffer, char *path); -vec2 platform_get_window_size(platform_window *window); -s32 filter_matches(array *filters, char *string, char **matched_filter); -void platform_delete_file(char *path); - -u64 platform_get_time(time_type time_type, time_precision precision); -s32 platform_get_memory_size(); -s32 platform_get_cpu_count(); - -u64 string_to_u64(char *str); -u32 string_to_u32(char *str); -u16 string_to_u16(char *str); -u8 string_to_u8(char *str); - -s64 string_to_s64(char *str); -s32 string_to_s32(char *str); -s16 string_to_s16(char *str); -s8 string_to_s8(char *str); - +/* +* BSD 2-Clause “Simplified” License +* Copyright (c) 2019, Aldrik Ramaekers, aldrik.ramaekers@protonmail.com +* All rights reserved. +*/ + +#ifndef INCLUDE_PLATFORM +#define INCLUDE_PLATFORM + +typedef struct t_platform_window platform_window; + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +typedef struct t_found_file +{ + char *matched_filter; + char *path; +} found_file; + +typedef struct t_file_match +{ + found_file file; + s16 file_error; + s32 file_size; + + u32 line_nr; + s32 word_match_offset; + s32 word_match_length; + s32 word_match_offset_x; // highlight render offset + s32 word_match_width; // highlight render width + char *line_info; // will be null when no match is found +} file_match; + +typedef struct t_search_result +{ + array work_queue; + array files; + array matches; + u64 find_duration_us; + array errors; + bool show_error_message; // error occured + bool found_file_matches; // found/finding file matches + s32 files_searched; + s32 files_matched; + s32 search_result_source_dir_len; + bool match_found; // found text match + mutex mutex; + bool walking_file_system; + bool cancel_search; + bool done_finding_matches; + s32 search_id; + u64 start_time; + bool done_finding_files; + memory_bucket mem_bucket; + bool is_command_line_search; + bool threads_closed; + + char *export_path; + char *file_filter; + char *directory_to_search; + char *text_to_find; + s32 max_thread_count; + s32 max_file_size; + bool is_recursive; +} search_result; + +typedef struct t_find_text_args +{ + file_match file; + search_result *search_result_buffer; +} find_text_args; + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +typedef struct t_file_content +{ + s64 content_length; + void *content; + s16 file_error; +} file_content; + +typedef enum t_time_type +{ + TIME_FULL, // realtime + TIME_THREAD, // run time for calling thread + TIME_PROCESS, // run time for calling process +} time_type; + +typedef enum t_time_precision +{ + TIME_NS, // nanoseconds + TIME_US, // microseconds + TIME_MILI_S, // miliseconds + TIME_S, // seconds +} time_precision; + +typedef struct t_cpu_info +{ + s32 model; + char model_name[255]; + float32 frequency; + u32 cache_size; + u32 cache_alignment; +} cpu_info; + +typedef enum t_file_dialog_type +{ + OPEN_FILE, + OPEN_DIRECTORY, + SAVE_FILE, +} file_dialog_type; + +typedef enum t_file_open_error +{ + FILE_ERROR_TOO_MANY_OPEN_FILES_PROCESS = 1, + FILE_ERROR_TOO_MANY_OPEN_FILES_SYSTEM = 2, + FILE_ERROR_NO_ACCESS = 3, + FILE_ERROR_NOT_FOUND = 4, + FILE_ERROR_CONNECTION_ABORTED = 5, + FILE_ERROR_CONNECTION_REFUSED = 6, + FILE_ERROR_NETWORK_DOWN = 7, + FILE_ERROR_REMOTE_IO_ERROR = 8, + FILE_ERROR_STALE = 9, // NFS server file is removed/renamed + FILE_ERROR_GENERIC = 10, +} file_open_error; + +struct open_dialog_args +{ + char *buffer; + char *file_filter; + char *start_path; + char *default_save_file_extension; + file_dialog_type type; +}; + +typedef struct t_list_file_args +{ + array *list; + char *start_dir; + char *pattern; + bool recursive; + bool include_directories; + bool *state; + bool *is_cancelled; + memory_bucket *bucket; +} list_file_args; + +typedef enum t_cursor_type +{ + CURSOR_DEFAULT, + CURSOR_POINTER, +} cursor_type; + +typedef struct t_vec2 +{ + s32 x; + s32 y; +} vec2; + +platform_window *main_window = 0; +platform_window *settings_window = 0; + +bool platform_window_is_valid(platform_window *window); +platform_window platform_open_window(char *name, u16 width, u16 height, u16 max_w, u16 max_h, u16 min_w, u16 min_h); +void platform_get_focus(platform_window *window); +bool platform_set_clipboard(platform_window *window, char *buffer); +bool platform_get_clipboard(platform_window *window, char *buffer); +void platform_window_set_size(platform_window *window, u16 width, u16 height); +void platform_window_set_position(platform_window *window, u16 x, u16 y); +void platform_destroy_window(platform_window *window); +void platform_handle_events(platform_window *window, mouse_input *mouse, keyboard_input *keyboard); +void platform_window_swap_buffers(platform_window *window); +void platform_set_cursor(platform_window *window, cursor_type type); +void platform_window_set_title(platform_window *window, char *name); +file_content platform_read_file_content(char *path, const char *mode); +bool platform_write_file_content(char *path, const char *mode, char *buffer, s32 len); +void platform_destroy_file_content(file_content *content); +bool get_active_directory(char *buffer); +bool set_active_directory(char *path); +void platform_show_message(platform_window *window, char *message, char *title); +array get_filters(char *filter); +void platform_list_files_block(array *list, char *start_dir, array filters, bool recursive, memory_bucket *bucket, bool include_directories, bool *is_cancelled); +void platform_list_files(array *list, char *start_dir, char *filter, bool recursive, memory_bucket *bucket, bool *is_cancelled, bool *state); +void platform_open_file_dialog(file_dialog_type type, char *buffer, char *file_filter, char *start_path); +bool platform_get_mac_address(char *buffer, s32 buf_size); +bool is_platform_in_darkmode(); +void *platform_open_file_dialog_block(void *arg); +char *platform_get_full_path(char *file); +void platform_open_url(char *command); +bool platform_send_http_request(char *url, char *params, char *response_buffer); +void platform_run_command(char *command); +void platform_window_make_current(platform_window *window); +void platform_init(int argc, char **argv); +void platform_destroy(); +void platform_set_icon(platform_window *window, image *img); +void platform_autocomplete_path(char *buffer, bool want_dir); +bool platform_directory_exists(char *path); +void platform_create_directory(char *path); +bool platform_file_exists(char *path); +void platform_show_alert(char *title, char *message); +char *get_config_save_location(char *buffer); +char *get_file_extension(char *path); +void get_name_from_path(char *buffer, char *path); +void get_directory_from_path(char *buffer, char *path); +vec2 platform_get_window_size(platform_window *window); +s32 filter_matches(array *filters, char *string, char **matched_filter); +void platform_delete_file(char *path); + +u64 platform_get_time(time_type time_type, time_precision precision); +s32 platform_get_memory_size(); +s32 platform_get_cpu_count(); + +u64 string_to_u64(char *str); +u32 string_to_u32(char *str); +u16 string_to_u16(char *str); +u8 string_to_u8(char *str); + +s64 string_to_s64(char *str); +s32 string_to_s32(char *str); +s16 string_to_s16(char *str); +s8 string_to_s8(char *str); + #endif \ No newline at end of file diff --git a/src/windows/platform.c b/src/windows/platform.c index 2172fd5..246e50d 100644 --- a/src/windows/platform.c +++ b/src/windows/platform.c @@ -1,1322 +1,1360 @@ -/* -* BSD 2-Clause “Simplified” License -* Copyright (c) 2019, Aldrik Ramaekers, aldrik.ramaekers@protonmail.com -* All rights reserved. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../external/LooplessSizeMove.c" - -struct t_platform_window -{ - HWND window_handle; - HDC hdc; - HGLRC gl_context; - WNDCLASS window_class; - - s32 min_width; - s32 min_height; - s32 max_width; - s32 max_height; - - // shared window properties - s32 width; - s32 height; - bool is_open; - bool has_focus; - cursor_type curr_cursor_type; - cursor_type next_cursor_type; -}; - -extern BOOL GetPhysicallyInstalledSystemMemory(PULONGLONG TotalMemoryInKilobytes); - -LARGE_INTEGER perf_frequency; -static HINSTANCE instance; -platform_window *current_window_to_handle; -keyboard_input *current_keyboard_to_handle; -mouse_input *current_mouse_to_handle; - -int cmd_show; - -bool platform_get_clipboard(platform_window *window, char *buffer) -{ - if (!OpenClipboard(NULL)) - return false; - - if (!IsClipboardFormatAvailable(CF_UNICODETEXT)) - { - CloseClipboard(); - return false; - } - - wchar_t* clip_str = GetClipboardData(CF_UNICODETEXT); - if (!clip_str) - { - CloseClipboard(); - return false; - } - - WideCharToMultiByte(CP_UTF8, 0, clip_str, -1, buffer, MAX_INPUT_LENGTH ,0,0); - - CloseClipboard(); - return true; -} - -bool platform_set_clipboard(platform_window *window, char *buffer) -{ - HANDLE clipboard_data; - - int char_num = MultiByteToWideChar(CP_UTF8, 0, buffer, -1, 0, 0); - wchar_t *convstr = mem_alloc(char_num*2); - int result = MultiByteToWideChar(CP_UTF8, 0, buffer, -1, convstr, char_num); - - size_t len = result; - size_t size = (len+1) * sizeof(wchar_t); - LPSTR dst; - - if (!OpenClipboard(NULL)) - return false; - - clipboard_data = GlobalAlloc(GMEM_MOVEABLE, size); - if (clipboard_data) - { - dst = GlobalLock(clipboard_data); - memmove(dst, convstr, size); - dst[len*2] = 0; - GlobalUnlock(clipboard_data); - - SetClipboardData(CF_UNICODETEXT, clipboard_data); - } - else - { - CloseClipboard(); - return false; - } - - CloseClipboard(); - return true; -} - -inline void platform_show_alert(char *title, char *message) -{ - // not implemented -} - -inline void platform_destroy() -{ - assets_destroy(); - -#if defined(MODE_DEVELOPER) - memory_print_leaks(); -#endif -} - -bool is_platform_in_darkmode() -{ - char *key = "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize\\"; - - HKEY result; - LSTATUS o = RegOpenKeyExA(HKEY_CURRENT_USER, key, 0, KEY_READ, &result); - - if (o == 0) - { - BYTE data; - DWORD len = 4; - RegQueryValueExA(result, "AppsUseLightTheme", NULL, NULL, &data, &len); - - if (data == 1) return true; - } - - return false; -} - -inline void platform_set_cursor(platform_window *window, cursor_type type) -{ - if (window->next_cursor_type != type) - { - window->next_cursor_type = type; - } -} - -bool platform_directory_exists(char *path) -{ - return PathFileExistsA(path) == TRUE; -} - -static void create_key_tables() -{ - keycode_map[0x30] = KEY_0; - keycode_map[0x31] = KEY_1; - keycode_map[0x32] = KEY_2; - keycode_map[0x33] = KEY_3; - keycode_map[0x34] = KEY_4; - keycode_map[0x35] = KEY_5; - keycode_map[0x36] = KEY_6; - keycode_map[0x37] = KEY_7; - keycode_map[0x38] = KEY_8; - keycode_map[0x39] = KEY_9; - keycode_map[0x41] = KEY_A; - keycode_map[0x42] = KEY_B; - keycode_map[0x43] = KEY_C; - keycode_map[0x44] = KEY_D; - keycode_map[0x45] = KEY_E; - keycode_map[0x46] = KEY_F; - keycode_map[0x47] = KEY_G; - keycode_map[0x48] = KEY_H; - keycode_map[0x49] = KEY_I; - keycode_map[0x4A] = KEY_J; - keycode_map[0x4B] = KEY_K; - keycode_map[0x4C] = KEY_L; - keycode_map[0x4D] = KEY_M; - keycode_map[0x4E] = KEY_N; - keycode_map[0x4F] = KEY_O; - keycode_map[0x50] = KEY_P; - keycode_map[0x51] = KEY_Q; - keycode_map[0x52] = KEY_R; - keycode_map[0x53] = KEY_S; - keycode_map[0x54] = KEY_T; - keycode_map[0x55] = KEY_U; - keycode_map[0x56] = KEY_V; - keycode_map[0x57] = KEY_W; - keycode_map[0x58] = KEY_X; - keycode_map[0x59] = KEY_Y; - keycode_map[0x5A] = KEY_Z; - - keycode_map[VK_OEM_7] = KEY_APOSTROPHE; - keycode_map[VK_OEM_102] = KEY_BACKSLASH; - keycode_map[VK_OEM_COMMA] = KEY_COMMA; - keycode_map[VK_OEM_3] = KEY_GRAVE_ACCENT; - keycode_map[VK_OEM_4] = KEY_LEFT_BRACKET; - keycode_map[VK_OEM_MINUS] = KEY_MINUS; - keycode_map[VK_OEM_PERIOD] = KEY_PERIOD; - - keycode_map[VK_BACK] = KEY_BACKSPACE; - keycode_map[VK_DELETE] = KEY_DELETE; - keycode_map[VK_END] = KEY_END; - keycode_map[VK_RETURN] = KEY_ENTER; - keycode_map[VK_ESCAPE] = KEY_ESCAPE; - keycode_map[VK_HOME] = KEY_HOME; - keycode_map[VK_INSERT] = KEY_INSERT; - keycode_map[VK_MENU] = KEY_MENU; - keycode_map[VK_NEXT] = KEY_PAGE_DOWN; - keycode_map[VK_PRIOR] = KEY_PAGE_UP; - keycode_map[VK_PAUSE] = KEY_PAUSE; - keycode_map[VK_TAB] = KEY_TAB; - keycode_map[VK_CAPITAL] = KEY_CAPS_LOCK; - keycode_map[VK_NUMLOCK] = KEY_NUM_LOCK; - keycode_map[VK_SCROLL] = KEY_SCROLL_LOCK; - keycode_map[0x70] = KEY_F1; - keycode_map[0x71] = KEY_F2; - keycode_map[0x72] = KEY_F3; - keycode_map[0x73] = KEY_F4; - keycode_map[0x74] = KEY_F5; - keycode_map[0x75] = KEY_F6; - keycode_map[0x76] = KEY_F7; - keycode_map[0x77] = KEY_F8; - keycode_map[0x78] = KEY_F9; - keycode_map[0x79] = KEY_F10; - keycode_map[0x7A] = KEY_F11; - keycode_map[0x7B] = KEY_F12; - keycode_map[0x7C] = KEY_F13; - keycode_map[0x7D] = KEY_F14; - keycode_map[0x7E] = KEY_F15; - keycode_map[0x7F] = KEY_F16; - keycode_map[0x80] = KEY_F17; - keycode_map[0x81] = KEY_F18; - keycode_map[0x82] = KEY_F19; - keycode_map[0x83] = KEY_F20; - keycode_map[0x84] = KEY_F21; - keycode_map[0x85] = KEY_F22; - keycode_map[0x86] = KEY_F23; - keycode_map[0x87] = KEY_F24; - keycode_map[0x88] = KEY_LEFT_ALT; - keycode_map[VK_CONTROL] = KEY_LEFT_CONTROL; - keycode_map[VK_LCONTROL] = KEY_LEFT_CONTROL; - keycode_map[VK_LSHIFT] = KEY_LEFT_SHIFT; - keycode_map[VK_LWIN] = KEY_LEFT_SUPER; - keycode_map[VK_SNAPSHOT] = KEY_PRINT_SCREEN; - keycode_map[VK_RMENU] = KEY_RIGHT_ALT; - keycode_map[VK_RCONTROL] = KEY_RIGHT_CONTROL; - keycode_map[VK_RSHIFT] = KEY_RIGHT_SHIFT; - keycode_map[VK_RWIN] = KEY_RIGHT_SUPER; - keycode_map[VK_DOWN] = KEY_DOWN; - keycode_map[VK_LEFT] = KEY_LEFT; - keycode_map[VK_RIGHT] = KEY_RIGHT; - keycode_map[VK_UP] = KEY_UP; - - keycode_map[VK_NUMPAD0] = KEY_KP_0; - keycode_map[VK_NUMPAD1] = KEY_KP_1; - keycode_map[VK_NUMPAD2] = KEY_KP_2; - keycode_map[VK_NUMPAD3] = KEY_KP_3; - keycode_map[VK_NUMPAD4] = KEY_KP_4; - keycode_map[VK_NUMPAD5] = KEY_KP_5; - keycode_map[VK_NUMPAD6] = KEY_KP_6; - keycode_map[VK_NUMPAD7] = KEY_KP_7; - keycode_map[VK_NUMPAD8] = KEY_KP_8; - keycode_map[VK_NUMPAD9] = KEY_KP_9; - keycode_map[VK_ADD] = KEY_KP_ADD; - keycode_map[VK_DECIMAL] = KEY_KP_DECIMAL; - keycode_map[VK_DIVIDE] = KEY_KP_DIVIDE; - keycode_map[VK_MULTIPLY] = KEY_KP_MULTIPLY; - keycode_map[VK_SUBTRACT] = KEY_KP_SUBTRACT; -} - -bool platform_file_exists(char *path) -{ - DWORD dwAttrib = GetFileAttributes(path); - - return (dwAttrib != INVALID_FILE_ATTRIBUTES && - !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); -} - -void platform_create_config_directory() -{ - char tmp[PATH_MAX]; - if(SUCCEEDED(SHGetFolderPathA(0, CSIDL_LOCAL_APPDATA|CSIDL_FLAG_CREATE, NULL, 0, tmp))) - { - string_appendn(tmp, CONFIG_DIRECTORY, PATH_MAX); - } - - - if (!platform_directory_exists(tmp)) - { - CreateDirectoryA(tmp, NULL); - } -} - -char* get_config_save_location(char *buffer) -{ - if(SUCCEEDED(SHGetFolderPathA(0, CSIDL_LOCAL_APPDATA|CSIDL_FLAG_CREATE, NULL, 0, buffer))) - { - string_appendn(buffer, CONFIG_DIRECTORY"\\config.txt", MAX_INPUT_LENGTH); - return buffer; - } - - return 0; -} - -void platform_show_message(platform_window *window, char *message, char *title) -{ - HWND handle = window ? window->window_handle : NULL; - MessageBox(handle, message, title, MB_ICONINFORMATION | MB_OK); -} - -LRESULT CALLBACK main_window_callback(HWND window, UINT message, WPARAM wparam, LPARAM lparam) -{ - LRESULT result = 0; - - if (message == WM_SIZE) - { - u32 width = lparam&0xFFFF; - u32 height = lparam>>16; - - current_window_to_handle->width = width; - current_window_to_handle->height = height; - } - else if (message == WM_CHAR) - { - if (current_keyboard_to_handle->take_input) - { - char buf[5]; - memset(buf, 0, 5); - char *ch = 0; - - wchar_t codep = wparam; - - WideCharToMultiByte(CP_UTF8, 0, &codep, 1, buf, 5 ,0,0); - - if (utf8len(buf) == 1) - { - char val = buf[0]; - - if (current_keyboard_to_handle->input_mode == INPUT_NUMERIC) - { - if (!(val >= 48 && val <= 57)) - { - ch = 0; - } - else - { - snprintf(buf, 2, "%c", val); - ch = buf; - } - } - else if (val >= 32 && val <= 126) - { - snprintf(buf, 5, "%c", val); - ch = buf; - } - } - - if (ch != 0) - keyboard_handle_input_string(current_window_to_handle, current_keyboard_to_handle, ch); - } - } - else if (message == WM_MOUSELEAVE) - { - //current_mouse_to_handle->x = MOUSE_OFFSCREEN; - //current_mouse_to_handle->y = MOUSE_OFFSCREEN; - } - else if (message == WM_KILLFOCUS) - { - current_mouse_to_handle->x = MOUSE_OFFSCREEN; - current_mouse_to_handle->y = MOUSE_OFFSCREEN; - - current_window_to_handle->has_focus = false; - memset(current_keyboard_to_handle->keys, 0, MAX_KEYCODE); - } - else if (message == WM_SETFOCUS) - { - current_window_to_handle->has_focus = true; - } - else if (message == WM_KEYDOWN) - { - s32 key = wparam; - - current_keyboard_to_handle->keys[keycode_map[key]] = true; - current_keyboard_to_handle->input_keys[keycode_map[key]] = true; - - if (current_keyboard_to_handle->take_input) - keyboard_handle_input_string(current_window_to_handle, - current_keyboard_to_handle, 0); - } - else if (message == WM_KEYUP) - { - s32 key = wparam; - current_keyboard_to_handle->keys[keycode_map[key]] = false; - current_keyboard_to_handle->input_keys[keycode_map[key]] = false; - } - else if (message == WM_LBUTTONDOWN || - message == WM_RBUTTONDOWN || - message == WM_MBUTTONDOWN || - message == WM_MOUSEWHEEL) - { - bool is_left_down = wparam & MK_LBUTTON; - bool is_right_down = wparam & MK_RBUTTON; - bool is_middle_down = wparam & MK_MBUTTON; - - u64 ev_time = platform_get_time(TIME_FULL, TIME_MILI_S); - static u64 last_ev_time = 0; - - if (message == WM_MOUSEWHEEL) - { - s16 scroll_val = wparam>>16; - - if (scroll_val < 0) - current_mouse_to_handle->scroll_state = SCROLL_DOWN; - else - current_mouse_to_handle->scroll_state = SCROLL_UP; - } - - if (is_left_down) - { - if (ev_time - last_ev_time < 200) - { - current_mouse_to_handle->left_state |= MOUSE_DOUBLE_CLICK; - } - - current_mouse_to_handle->left_state |= MOUSE_DOWN; - current_mouse_to_handle->left_state |= MOUSE_CLICK; - - current_mouse_to_handle->total_move_x = 0; - current_mouse_to_handle->total_move_y = 0; - last_ev_time = ev_time; - } - if (is_right_down) - { - current_mouse_to_handle->right_state |= MOUSE_DOWN; - current_mouse_to_handle->right_state |= MOUSE_CLICK; - } - } - else if (message == WM_LBUTTONUP || - message == WM_RBUTTONUP || - message == WM_MBUTTONUP) - { - bool is_left_up = message == WM_LBUTTONUP; - bool is_right_up = message == WM_RBUTTONUP; - bool is_middle_up = message == WM_MBUTTONUP; - - if (is_left_up) - { - current_mouse_to_handle->left_state = MOUSE_RELEASE; - } - if (is_right_up) - { - current_mouse_to_handle->right_state = MOUSE_RELEASE; - } - } - else if (message == WM_MOUSEMOVE) - { - current_window_to_handle->curr_cursor_type = -999; - -#if 0 - s32 x = lparam&0xFFFF; - s32 y = lparam>>16; - - current_mouse_to_handle->x = x; - current_mouse_to_handle->y = y; -#endif - - TRACKMOUSEEVENT track; - track.cbSize = sizeof(track); - track.dwFlags = TME_LEAVE; - track.hwndTrack = current_window_to_handle->window_handle; - TrackMouseEvent(&track); - } - else if (message == WM_GETMINMAXINFO) - { - MINMAXINFO *info = (MINMAXINFO*)lparam; - - info->ptMinTrackSize.x = current_window_to_handle->min_width; - info->ptMinTrackSize.y = current_window_to_handle->min_height; - - if (current_window_to_handle->max_width) - info->ptMaxTrackSize.x = current_window_to_handle->max_width; - if (current_window_to_handle->max_height) - info->ptMaxTrackSize.y = current_window_to_handle->max_height; - } - else if (message == WM_DESTROY) - { - current_window_to_handle->is_open = false; - } - else if (message == WM_CLOSE) - { - current_window_to_handle->is_open = false; - } - else - { - result = LSMProc(window, message, wparam, lparam); - } - - return result; -} - -void platform_window_set_title(platform_window *window, char *name) -{ - SetWindowText(window->window_handle, name); -} - -vec2 platform_get_window_size(platform_window *window) -{ - RECT rec; - GetWindowRect(window->window_handle, &rec); - vec2 res; - res.x = rec.right - rec.left; - res.y = rec.bottom - rec.top; - return res; -} - -void platform_get_focus(platform_window *window) -{ - SetFocus(window->window_handle); -} - -platform_window platform_open_window(char *name, u16 width, u16 height, u16 max_w, u16 max_h, u16 min_w, u16 min_h) -{ -#if !defined(MODE_GDBDEBUG) && !defined(MODE_DEVELOPER) - ShowWindow(GetConsoleWindow(), SW_HIDE); -#endif - - platform_window window; - window.has_focus = true; - window.window_handle = 0; - window.hdc = 0; - window.width = width; - window.height = height; - window.min_width = min_w; - window.min_height = min_h; - window.max_width = max_w; - window.max_height = max_h; - window.curr_cursor_type = -1; - window.next_cursor_type = CURSOR_DEFAULT; - - current_window_to_handle = &window; - - memset(&window.window_class, 0, sizeof(WNDCLASS)); - window.window_class.style = CS_OWNDC; - window.window_class.lpfnWndProc = main_window_callback; - window.window_class.hInstance = instance; - window.window_class.lpszClassName = name; - window.window_class.hIcon = LoadIcon(NULL, IDI_WINLOGO); - //window.window_class.hCursor = LoadCursor(NULL, IDC_ARROW); - - if (RegisterClass(&window.window_class)) - { - int style = WS_VISIBLE|WS_SYSMENU|WS_CAPTION|WS_MINIMIZEBOX; - - if (min_w != max_w && min_h != max_h) - style |= WS_SIZEBOX; - else - style |= WS_THICKFRAME; - - window.window_handle = CreateWindowEx(0, - window.window_class.lpszClassName, - name, - style, - CW_USEDEFAULT, - CW_USEDEFAULT, - width, - height, - 0, - 0, - instance, - 0); - - if (window.window_handle) - { - window.hdc = GetDC(window.window_handle); - - PIXELFORMATDESCRIPTOR format; - memset(&format, 0, sizeof(PIXELFORMATDESCRIPTOR)); - format.nSize = sizeof(PIXELFORMATDESCRIPTOR); - format.nVersion = 1; - format.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER; - format.cColorBits = 24; - format.cAlphaBits = 8; - format.iLayerType = PFD_MAIN_PLANE; // PFD_TYPE_RGBA - s32 suggested_format_index = ChoosePixelFormat(window.hdc, &format); - - PIXELFORMATDESCRIPTOR actual_format; - DescribePixelFormat(window.hdc, suggested_format_index, sizeof(actual_format), &actual_format); - SetPixelFormat(window.hdc, suggested_format_index, &actual_format); - - window.gl_context = wglCreateContext(window.hdc); - - static HGLRC share_list = 0; - if (share_list == 0) - { - share_list = window.gl_context; - } - else - { - wglShareLists(share_list, window.gl_context); - } - - wglMakeCurrent(window.hdc, window.gl_context); - - ShowWindow(window.window_handle, cmd_show); - - // blending - glEnable(GL_DEPTH_TEST); - //glDepthMask(true); - //glClearDepth(50); - glDepthFunc(GL_LEQUAL); - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - // setup multisampling -#if 0 - glEnable(GL_ALPHA_TEST); - glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE); - glEnable(GL_SAMPLE_ALPHA_TO_ONE); - glEnable(GL_MULTISAMPLE); - glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST); -#endif - - // https://stackoverflow.com/questions/5627229/sub-pixel-drawing-with-opengl - //glHint(GL_POINT_SMOOTH, GL_NICEST); - //glHint(GL_LINE_SMOOTH, GL_NICEST); - //glHint(GL_POLYGON_SMOOTH, GL_NICEST); - - //glEnable(GL_SMOOTH); - //glEnable(GL_POINT_SMOOTH); - //glEnable(GL_LINE_SMOOTH); - //glEnable(GL_POLYGON_SMOOTH); - ////////////////// - - window.is_open = true; - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, width, height, 0, -1, 1); - - //GLint m_viewport[4]; - //glGetIntegerv( GL_VIEWPORT, m_viewport ); - //printf("%d %d %d %d\n", m_viewport[0], m_viewport[1], m_viewport[2], m_viewport[3]); - - glMatrixMode(GL_MODELVIEW); - - TRACKMOUSEEVENT track; - track.cbSize = sizeof(track); - track.dwFlags = TME_LEAVE; - track.hwndTrack = window.window_handle; - TrackMouseEvent(&track); - } - else - { - platform_show_message(0, "An error occured within Windows, please restart the program.", "Error"); - abort(); - } - } - else - { - platform_show_message(0, "An error occured within Windows, please restart the program.", "Error"); - abort(); - } - - platform_get_focus(&window); - - return window; -} - -void platform_window_set_size(platform_window *window, u16 width, u16 height) -{ - s32 style = GetWindowLong(window->window_handle, GWL_STYLE); - BOOL menu = FALSE; - - RECT rec; - rec.left = 0; - rec.top = 0; - rec.right = width; - rec.bottom = height; - AdjustWindowRectEx(&rec, style, menu, 0); - SetWindowPos(window->window_handle,NULL,rec.left,rec.top,rec.right,rec.bottom,SWP_NOMOVE|SWP_NOZORDER); -} - -void platform_window_set_position(platform_window *window, u16 x, u16 y) -{ - RECT rec; - GetWindowRect(window->window_handle, &rec); - MoveWindow(window->window_handle, x, y, rec.right-rec.left, rec.bottom-rec.top, FALSE); -} - -bool platform_window_is_valid(platform_window *window) -{ - return window->hdc && window->window_handle; -} - -void platform_destroy_window(platform_window *window) -{ - wglMakeCurrent(NULL, NULL); - wglDeleteContext(window->gl_context); - - ReleaseDC(window->window_handle, window->hdc); - CloseWindow(window->window_handle); - DestroyWindow(window->window_handle); - UnregisterClassA(window->window_class.lpszClassName, instance); - window->hdc = 0; - window->window_handle = 0; -} - -void platform_handle_events(platform_window *window, mouse_input *mouse, keyboard_input *keyboard) -{ - current_window_to_handle = window; - current_keyboard_to_handle = keyboard; - current_mouse_to_handle = mouse; - - mouse->left_state &= ~MOUSE_CLICK; - mouse->right_state &= ~MOUSE_CLICK; - mouse->left_state &= ~MOUSE_DOUBLE_CLICK; - mouse->right_state &= ~MOUSE_DOUBLE_CLICK; - mouse->left_state &= ~MOUSE_RELEASE; - mouse->right_state &= ~MOUSE_RELEASE; - memset(keyboard->input_keys, 0, MAX_KEYCODE); - mouse->move_x = 0; - mouse->move_y = 0; - mouse->scroll_state = 0; - keyboard->text_changed = false; - - // mouse position (including outside of window) - current_window_to_handle->has_focus = GetFocus() == current_window_to_handle->window_handle; - - if (current_window_to_handle->has_focus) - { - if((GetKeyState(VK_LBUTTON) & 0x100) == 0) - { - current_mouse_to_handle->left_state = MOUSE_RELEASE; - } - - RECT rec; - GetWindowRect(window->window_handle, &rec); - POINT p; - GetCursorPos(&p); - mouse->x = p.x - rec.left - GetSystemMetrics(SM_CYSIZEFRAME); - mouse->y = p.y - rec.top - GetSystemMetrics(SM_CYSIZE) - GetSystemMetrics(SM_CYFRAME); - //printf("%d %d\n",GetSystemMetrics(SM_CYSIZE), GetSystemMetrics(SM_CYFRAME)); - } - - MSG message; - while(PeekMessageA(&message, window->window_handle, 0, 0, TRUE)) - { - TranslateMessage(&message); - SizingCheck(&message); - DispatchMessage(&message); - } - - glViewport(0, 0, window->width, window->height); -} - -void platform_window_swap_buffers(platform_window *window) -{ - // set cursor if changed - if (window->curr_cursor_type != window->next_cursor_type) - { - char *cursor_shape = 0; - switch(window->next_cursor_type) - { - case CURSOR_DEFAULT: cursor_shape = IDC_ARROW; break; - case CURSOR_POINTER: cursor_shape = IDC_HAND; break; - } - - HCURSOR cursor = LoadCursorA(NULL, cursor_shape); - - window->curr_cursor_type = window->next_cursor_type; - SetCursor(cursor); - } - - SwapBuffers(window->hdc); -} - -file_content platform_read_file_content(char *path, const char *mode) -{ - file_content result; - result.content = 0; - result.content_length = 0; - result.file_error = 0; - - FILE *file = fopen(path, mode); - if (!file) - { - if (errno == EMFILE) - result.file_error = FILE_ERROR_TOO_MANY_OPEN_FILES_PROCESS; - else if (errno == ENFILE) - result.file_error = FILE_ERROR_TOO_MANY_OPEN_FILES_SYSTEM; - else if (errno == EACCES) - result.file_error = FILE_ERROR_NO_ACCESS; - else if (errno == EPERM) - result.file_error = FILE_ERROR_NO_ACCESS; - else if (errno == ENOENT) - result.file_error = FILE_ERROR_NOT_FOUND; - else if (errno == ECONNABORTED) - result.file_error = FILE_ERROR_CONNECTION_ABORTED; - else if (errno == ECONNREFUSED) - result.file_error = FILE_ERROR_CONNECTION_REFUSED; - else if (errno == ENETDOWN) - result.file_error = FILE_ERROR_NETWORK_DOWN; - else - { - result.file_error = FILE_ERROR_GENERIC; - printf("ERROR: %d\n", errno); - } - - goto done_failure; - } - - fseek(file, 0 , SEEK_END); - int length = ftell(file); - fseek(file, 0, SEEK_SET); - - s32 length_to_alloc = length+1; - - result.content = mem_alloc(length_to_alloc); - if (!result.content) goto done; - - memset(result.content, 0, length); - s32 read_result = fread(result.content, 1, length, file); - if (read_result == 0 && length != 0) - { - mem_free(result.content); - result.content = 0; - return result; - } - - result.content_length = read_result; - - ((char*)result.content)[length] = 0; - - done: - fclose(file); - done_failure: - return result; -} - -void platform_delete_file(char *path) -{ - remove(path); -} - -bool platform_write_file_content(char *path, const char *mode, char *buffer, s32 len) -{ - bool result = false; - - FILE *file = fopen(path, mode); - - if (!file) - { - goto done_failure; - } - else - { - fwrite(buffer, 1, len, file); - //fprintf(file, buffer); - } - - //done: - fclose(file); - done_failure: - return result; -} - -void platform_destroy_file_content(file_content *content) -{ - assert(content); - mem_free(content->content); -} - -bool get_active_directory(char *buffer) -{ - return GetCurrentDirectory(MAX_INPUT_LENGTH, buffer); -} - -bool set_active_directory(char *path) -{ - return SetCurrentDirectory(path); -} - -void platform_list_files_block(array *list, char *start_dir, array filters, bool recursive, memory_bucket *bucket, bool include_directories, bool *is_cancelled) -{ - assert(list); - s32 len = 0; - char *matched_filter = 0; - - char *subdirname_buf; - if (bucket) - subdirname_buf = memory_bucket_reserve(bucket, MAX_INPUT_LENGTH); - else - subdirname_buf = mem_alloc(MAX_INPUT_LENGTH); - - char *start_dir_fix; - if (bucket) - start_dir_fix = memory_bucket_reserve(bucket, MAX_INPUT_LENGTH); - else - start_dir_fix = mem_alloc(MAX_INPUT_LENGTH); - snprintf(start_dir_fix, MAX_INPUT_LENGTH, "%s*", start_dir); - - char *start_dir_clean; - if (bucket) - start_dir_clean = memory_bucket_reserve(bucket, MAX_INPUT_LENGTH); - else - start_dir_clean = mem_alloc(MAX_INPUT_LENGTH); - string_copyn(start_dir_clean, start_dir, MAX_INPUT_LENGTH); - - WIN32_FIND_DATAA file_info; - HWND handle = FindFirstFileA(start_dir_fix, &file_info); - - if (!bucket) - mem_free(start_dir_fix); - - if (handle == INVALID_HANDLE_VALUE) - { - return; - } - - do - { - if (*is_cancelled) break; - char *name = file_info.cFileName; - - // symbolic link is not allowed.. - if ((file_info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) - continue; - - - if ((file_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) - { - if ((strcmp(name, ".") == 0) || (strcmp(name, "..") == 0)) - continue; - - if (include_directories) - { - if ((len = filter_matches(&filters, name, - &matched_filter)) && len != -1) - { - // is file - char *buf; - if (bucket) - buf = memory_bucket_reserve(bucket, MAX_INPUT_LENGTH); - else - buf = mem_alloc(MAX_INPUT_LENGTH); - snprintf(buf, MAX_INPUT_LENGTH, "%s%s",start_dir, name); - - found_file f; - f.path = buf; - - if (bucket) - f.matched_filter= memory_bucket_reserve(bucket, len+1); - else - f.matched_filter= mem_alloc(len+1); - - string_copyn(f.matched_filter, matched_filter, len+1); - - mutex_lock(&list->mutex); - array_push_size(list, &f, sizeof(found_file)); - mutex_unlock(&list->mutex); - } - } - - if (recursive) - { - string_copyn(subdirname_buf, start_dir_clean, MAX_INPUT_LENGTH); - string_appendn(subdirname_buf, name, MAX_INPUT_LENGTH); - string_appendn(subdirname_buf, "\\", MAX_INPUT_LENGTH); - - // is directory - platform_list_files_block(list, subdirname_buf, filters, recursive, bucket, include_directories, is_cancelled); - } - } - else if ((file_info.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) || - (file_info.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) || - (file_info.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) || - (file_info.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) || - (file_info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) || - (file_info.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE)) - { - if ((len = filter_matches(&filters, name, - &matched_filter)) && len != -1) - { - // is file - char *buf; - if (bucket) - buf = memory_bucket_reserve(bucket, MAX_INPUT_LENGTH); - else - buf = mem_alloc(MAX_INPUT_LENGTH); - - snprintf(buf, MAX_INPUT_LENGTH, "%s%s",start_dir, name); - - found_file f; - f.path = buf; - - if (bucket) - f.matched_filter = memory_bucket_reserve(bucket, len+1); - else - f.matched_filter = mem_alloc(len+1); - - string_copyn(f.matched_filter, matched_filter, len+1); - - mutex_lock(&list->mutex); - array_push_size(list, &f, sizeof(found_file)); - mutex_unlock(&list->mutex); - } - } - } - while (FindNextFile(handle, &file_info) != 0); - - if (!bucket) - mem_free(start_dir_clean); - - FindClose(handle); -} - -static void* platform_open_file_dialog_implementation(void *data) -{ - struct open_dialog_args *args = data; - - OPENFILENAME info; - info.lStructSize = sizeof(OPENFILENAME); - info.hwndOwner = NULL; - info.hInstance = NULL; - - char filter[MAX_INPUT_LENGTH]; - memset(filter, 0, MAX_INPUT_LENGTH); - - if (args->file_filter) - { - string_copyn(filter, args->file_filter, MAX_INPUT_LENGTH); - filter[strlen(filter)] = 0; - filter[strlen(filter)+1] = 0; - info.lpstrFilter = filter; - } - else - { - info.lpstrFilter = NULL; - } - - char szFile[MAX_INPUT_LENGTH]; - memset(szFile, 0, MAX_INPUT_LENGTH); - - info.lpstrCustomFilter = NULL; - info.nMaxCustFilter = MAX_INPUT_LENGTH; - info.nFilterIndex = 0; - info.lpstrFile = (char*)szFile; - info.nMaxFile = MAX_INPUT_LENGTH; - - info.lpstrDefExt = args->default_save_file_extension; - - info.lpstrFileTitle = NULL; - info.lpstrInitialDir = args->start_path; - info.lpstrTitle = NULL; - - if (args->type == SAVE_FILE) - { - info.Flags = OFN_EXTENSIONDIFFERENT | OFN_OVERWRITEPROMPT; - GetSaveFileNameA(&info); - string_copyn(args->buffer, info.lpstrFile, MAX_INPUT_LENGTH); - } - else if (args->type == OPEN_DIRECTORY) - { - BROWSEINFOA inf; - PIDLIST_ABSOLUTE result = SHBrowseForFolderA(&inf); - if (!result) return 0; - - SHGetPathFromIDListA(result, args->buffer); - } - else if (args->type == OPEN_FILE) - { - info.Flags = OFN_FILEMUSTEXIST; - GetOpenFileNameA(&info); - string_copyn(args->buffer, info.lpstrFile, MAX_INPUT_LENGTH); - } - - return 0; -} - -void *platform_open_file_dialog_block(void *arg) -{ - platform_open_file_dialog_implementation(arg); - mem_free(arg); - return 0; -} - -char *platform_get_full_path(char *file) -{ - char *buf = mem_alloc(MAX_INPUT_LENGTH); - if (!GetFullPathNameA(file, MAX_INPUT_LENGTH, buf, NULL)) - { - buf[0] = 0; - } - - return buf; -} - -void platform_open_url(char *command) -{ - platform_run_command(command); -} - -void platform_run_command(char *command) -{ - // might be start instead of open - ShellExecuteA(NULL, "open", command, NULL, NULL, SW_SHOWDEFAULT); -} - -void platform_window_make_current(platform_window *window) -{ - wglMakeCurrent(window->hdc, window->gl_context); -} - -void platform_init(int argc, char **argv) -{ - setlocale(LC_ALL, "en_US.UTF-8"); - - QueryPerformanceFrequency(&perf_frequency); - CoInitialize(NULL); - create_key_tables(); - - instance = GetModuleHandle(NULL); - cmd_show = argc; - - // get fullpath of the directory the exe is residing in - binary_path = platform_get_full_path(argv[0]); - - platform_create_config_directory(); - - char buf[MAX_INPUT_LENGTH]; - get_directory_from_path(buf, binary_path); - string_copyn(binary_path, buf, MAX_INPUT_LENGTH); - - assets_create(); -} - -void platform_set_icon(platform_window *window, image *img) -{ - BYTE *bmp; - s32 data_len = img->width * img->height * 4; - s32 total_len = data_len + 40 * 4; - - bmp = mem_alloc(total_len); - - struct { - int32_t header_size, width, geight; - int16_t color_plane, bits_per_pixel; - int32_t compression_mode, img_length, obsolete[4]; - } bmp_header = {40, img->width, img->height * 2, 1, 32, BI_RGB, data_len, {0,0,0,0} }; - - memcpy(bmp, &bmp_header, 40); - - s32 index = 0; - for (s32 y = img->height-1; y >= 0; y--) - { - for (s32 x = 0; x < img->width; x++) - { - s32 img_pixel = *(((s32*)img->data+(x+(y*img->width)))); - - // 0xAABBGGRR - s32 a = (img_pixel>>24) & 0x000000FF; - s32 b = (img_pixel>>16) & 0x000000FF; - s32 g = (img_pixel>> 8) & 0x000000FF; - s32 r = (img_pixel>> 0) & 0x000000FF; - - //s32 c = (r << 24) | (g << 16) | (b << 8) | (a << 0); - s32 c = (a << 24) | (r << 16) | (g << 8) | (b << 0); - memcpy(bmp+40+(index*4), &c, 4); - - ++index; - } - } - - HICON icon = CreateIconFromResourceEx(bmp, total_len, TRUE, 0x00030000, img->width, img->height, LR_DEFAULTCOLOR); - - SendMessage(window->window_handle, WM_SETICON, ICON_SMALL, (LPARAM)icon); - SendMessage(window->window_handle, WM_SETICON, ICON_BIG, (LPARAM)icon); - - mem_free(bmp); - - if (!icon) - printf("Failed to load icon, error code: %ld.\n", GetLastError()); -} - -u64 platform_get_time(time_type time_type, time_precision precision) -{ - LARGE_INTEGER counter; - QueryPerformanceCounter(&counter); - - double sec = counter.QuadPart / (double)(perf_frequency.QuadPart); - - //printf("%I64d %I64d %f\n", counter.QuadPart, perf_frequency.QuadPart, sec); - - double val = sec; - - if (precision == TIME_NS) - { - return val*1000000000; - } - if (precision == TIME_US) - { - return val*1000000; - } - if (precision == TIME_MILI_S) - { - return val*1000; - } - if (precision == TIME_S) - { - return val; - } - return val; -} - -s32 platform_get_memory_size() -{ - u64 result; - GetPhysicallyInstalledSystemMemory(&result); - return result; -} - -s32 platform_get_cpu_count() -{ - SYSTEM_INFO info; - GetSystemInfo(&info); - - return info.dwNumberOfProcessors; -} - -u64 string_to_u64(char *str) -{ - return (u64)strtoull(str, 0, 10); -} - -u32 string_to_u32(char *str) -{ - return (u32)strtoul(str, 0, 10); -} - -u16 string_to_u16(char *str) -{ - return (u16)strtoul(str, 0, 10); -} - -u8 string_to_u8(char *str) -{ - return (u8)strtoul(str, 0, 10); -} - -s64 string_to_s64(char *str) -{ - return (s64)strtoull(str, 0, 10); -} - -s32 string_to_s32(char *str) -{ - return (s32)strtoul(str, 0, 10); -} - -s16 string_to_s16(char *str) -{ - return (s16)strtoul(str, 0, 10); -} - -s8 string_to_s8(char *str) -{ - return (s8)strtoul(str, 0, 10); -} - -bool platform_send_http_request(char *url, char *params, char *response_buffer) -{ - // https://www.unix.com/programming/187337-c-http-get-request-using-sockets.html - - bool response = true; - HINTERNET hIntSession = 0; - HINTERNET hHttpSession = 0; - HINTERNET hHttpRequest = 0; - - hIntSession = InternetOpen("Text-Search", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0); - if (!hIntSession) goto failure; - - hHttpSession = InternetConnect(hIntSession, url, 80, 0, 0, INTERNET_SERVICE_HTTP, 0, 0); - if (!hHttpSession) goto failure; - - hHttpRequest = HttpOpenRequest( - hHttpSession, - "GET", - params, - 0, 0, 0, INTERNET_FLAG_RELOAD, 0); - - - char* szHeaders = "Content-Type: application/json"; - char szReq[1024] = ""; - if(!HttpSendRequest(hHttpRequest, szHeaders, strlen(szHeaders), szReq, strlen(szReq))) { - goto failure; - } - - DWORD dwRead=0; - while(InternetReadFile(hHttpRequest, response_buffer, MAX_INPUT_LENGTH-1, &dwRead) && dwRead) { - response_buffer[dwRead] = 0; - dwRead=0; - } - - goto done; - - failure: - printf("failure"); - response = false; - - done: - InternetCloseHandle(hHttpRequest); - InternetCloseHandle(hHttpSession); - InternetCloseHandle(hIntSession); - - return response; +/* +* BSD 2-Clause “Simplified” License +* Copyright (c) 2019, Aldrik Ramaekers, aldrik.ramaekers@protonmail.com +* All rights reserved. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../external/LooplessSizeMove.c" + +struct t_platform_window +{ + HWND window_handle; + HDC hdc; + HGLRC gl_context; + WNDCLASS window_class; + + s32 min_width; + s32 min_height; + s32 max_width; + s32 max_height; + + // shared window properties + s32 width; + s32 height; + bool is_open; + bool has_focus; + cursor_type curr_cursor_type; + cursor_type next_cursor_type; +}; + +extern BOOL GetPhysicallyInstalledSystemMemory(PULONGLONG TotalMemoryInKilobytes); + +LARGE_INTEGER perf_frequency; +static HINSTANCE instance; +platform_window *current_window_to_handle; +keyboard_input *current_keyboard_to_handle; +mouse_input *current_mouse_to_handle; + +int cmd_show; + +bool platform_get_clipboard(platform_window *window, char *buffer) +{ + if (!OpenClipboard(NULL)) + return false; + + if (!IsClipboardFormatAvailable(CF_UNICODETEXT)) + { + CloseClipboard(); + return false; + } + + wchar_t* clip_str = GetClipboardData(CF_UNICODETEXT); + if (!clip_str) + { + CloseClipboard(); + return false; + } + + WideCharToMultiByte(CP_UTF8, 0, clip_str, -1, buffer, MAX_INPUT_LENGTH ,0,0); + + CloseClipboard(); + return true; +} + +bool platform_set_clipboard(platform_window *window, char *buffer) +{ + HANDLE clipboard_data; + + int char_num = MultiByteToWideChar(CP_UTF8, 0, buffer, -1, 0, 0); + wchar_t *convstr = mem_alloc(char_num*2); + int result = MultiByteToWideChar(CP_UTF8, 0, buffer, -1, convstr, char_num); + + size_t len = result; + size_t size = (len+1) * sizeof(wchar_t); + LPSTR dst; + + if (!OpenClipboard(NULL)) + return false; + + clipboard_data = GlobalAlloc(GMEM_MOVEABLE, size); + if (clipboard_data) + { + dst = GlobalLock(clipboard_data); + memmove(dst, convstr, size); + dst[len*2] = 0; + GlobalUnlock(clipboard_data); + + SetClipboardData(CF_UNICODETEXT, clipboard_data); + } + else + { + CloseClipboard(); + return false; + } + + CloseClipboard(); + return true; +} + +inline void platform_show_alert(char *title, char *message) +{ + // not implemented +} + +inline void platform_destroy() +{ + assets_destroy(); + +#if defined(MODE_DEVELOPER) + memory_print_leaks(); +#endif +} + +bool is_platform_in_darkmode() +{ + char *key = "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize\\"; + + HKEY result; + LSTATUS o = RegOpenKeyExA(HKEY_CURRENT_USER, key, 0, KEY_READ, &result); + + if (o == 0) + { + BYTE data; + DWORD len = 4; + RegQueryValueExA(result, "AppsUseLightTheme", NULL, NULL, &data, &len); + + if (data == 1) return true; + } + + return false; +} + +inline void platform_set_cursor(platform_window *window, cursor_type type) +{ + if (window->next_cursor_type != type) + { + window->next_cursor_type = type; + } +} + +bool platform_directory_exists(char *path) +{ + return PathFileExistsA(path) == TRUE; +} + +static void create_key_tables() +{ + keycode_map[0x30] = KEY_0; + keycode_map[0x31] = KEY_1; + keycode_map[0x32] = KEY_2; + keycode_map[0x33] = KEY_3; + keycode_map[0x34] = KEY_4; + keycode_map[0x35] = KEY_5; + keycode_map[0x36] = KEY_6; + keycode_map[0x37] = KEY_7; + keycode_map[0x38] = KEY_8; + keycode_map[0x39] = KEY_9; + keycode_map[0x41] = KEY_A; + keycode_map[0x42] = KEY_B; + keycode_map[0x43] = KEY_C; + keycode_map[0x44] = KEY_D; + keycode_map[0x45] = KEY_E; + keycode_map[0x46] = KEY_F; + keycode_map[0x47] = KEY_G; + keycode_map[0x48] = KEY_H; + keycode_map[0x49] = KEY_I; + keycode_map[0x4A] = KEY_J; + keycode_map[0x4B] = KEY_K; + keycode_map[0x4C] = KEY_L; + keycode_map[0x4D] = KEY_M; + keycode_map[0x4E] = KEY_N; + keycode_map[0x4F] = KEY_O; + keycode_map[0x50] = KEY_P; + keycode_map[0x51] = KEY_Q; + keycode_map[0x52] = KEY_R; + keycode_map[0x53] = KEY_S; + keycode_map[0x54] = KEY_T; + keycode_map[0x55] = KEY_U; + keycode_map[0x56] = KEY_V; + keycode_map[0x57] = KEY_W; + keycode_map[0x58] = KEY_X; + keycode_map[0x59] = KEY_Y; + keycode_map[0x5A] = KEY_Z; + + keycode_map[VK_OEM_7] = KEY_APOSTROPHE; + keycode_map[VK_OEM_102] = KEY_BACKSLASH; + keycode_map[VK_OEM_COMMA] = KEY_COMMA; + keycode_map[VK_OEM_3] = KEY_GRAVE_ACCENT; + keycode_map[VK_OEM_4] = KEY_LEFT_BRACKET; + keycode_map[VK_OEM_MINUS] = KEY_MINUS; + keycode_map[VK_OEM_PERIOD] = KEY_PERIOD; + + keycode_map[VK_BACK] = KEY_BACKSPACE; + keycode_map[VK_DELETE] = KEY_DELETE; + keycode_map[VK_END] = KEY_END; + keycode_map[VK_RETURN] = KEY_ENTER; + keycode_map[VK_ESCAPE] = KEY_ESCAPE; + keycode_map[VK_HOME] = KEY_HOME; + keycode_map[VK_INSERT] = KEY_INSERT; + keycode_map[VK_MENU] = KEY_MENU; + keycode_map[VK_NEXT] = KEY_PAGE_DOWN; + keycode_map[VK_PRIOR] = KEY_PAGE_UP; + keycode_map[VK_PAUSE] = KEY_PAUSE; + keycode_map[VK_TAB] = KEY_TAB; + keycode_map[VK_CAPITAL] = KEY_CAPS_LOCK; + keycode_map[VK_NUMLOCK] = KEY_NUM_LOCK; + keycode_map[VK_SCROLL] = KEY_SCROLL_LOCK; + keycode_map[0x70] = KEY_F1; + keycode_map[0x71] = KEY_F2; + keycode_map[0x72] = KEY_F3; + keycode_map[0x73] = KEY_F4; + keycode_map[0x74] = KEY_F5; + keycode_map[0x75] = KEY_F6; + keycode_map[0x76] = KEY_F7; + keycode_map[0x77] = KEY_F8; + keycode_map[0x78] = KEY_F9; + keycode_map[0x79] = KEY_F10; + keycode_map[0x7A] = KEY_F11; + keycode_map[0x7B] = KEY_F12; + keycode_map[0x7C] = KEY_F13; + keycode_map[0x7D] = KEY_F14; + keycode_map[0x7E] = KEY_F15; + keycode_map[0x7F] = KEY_F16; + keycode_map[0x80] = KEY_F17; + keycode_map[0x81] = KEY_F18; + keycode_map[0x82] = KEY_F19; + keycode_map[0x83] = KEY_F20; + keycode_map[0x84] = KEY_F21; + keycode_map[0x85] = KEY_F22; + keycode_map[0x86] = KEY_F23; + keycode_map[0x87] = KEY_F24; + keycode_map[0x88] = KEY_LEFT_ALT; + keycode_map[VK_CONTROL] = KEY_LEFT_CONTROL; + keycode_map[VK_LCONTROL] = KEY_LEFT_CONTROL; + keycode_map[VK_LSHIFT] = KEY_LEFT_SHIFT; + keycode_map[VK_LWIN] = KEY_LEFT_SUPER; + keycode_map[VK_SNAPSHOT] = KEY_PRINT_SCREEN; + keycode_map[VK_RMENU] = KEY_RIGHT_ALT; + keycode_map[VK_RCONTROL] = KEY_RIGHT_CONTROL; + keycode_map[VK_RSHIFT] = KEY_RIGHT_SHIFT; + keycode_map[VK_RWIN] = KEY_RIGHT_SUPER; + keycode_map[VK_DOWN] = KEY_DOWN; + keycode_map[VK_LEFT] = KEY_LEFT; + keycode_map[VK_RIGHT] = KEY_RIGHT; + keycode_map[VK_UP] = KEY_UP; + + keycode_map[VK_NUMPAD0] = KEY_KP_0; + keycode_map[VK_NUMPAD1] = KEY_KP_1; + keycode_map[VK_NUMPAD2] = KEY_KP_2; + keycode_map[VK_NUMPAD3] = KEY_KP_3; + keycode_map[VK_NUMPAD4] = KEY_KP_4; + keycode_map[VK_NUMPAD5] = KEY_KP_5; + keycode_map[VK_NUMPAD6] = KEY_KP_6; + keycode_map[VK_NUMPAD7] = KEY_KP_7; + keycode_map[VK_NUMPAD8] = KEY_KP_8; + keycode_map[VK_NUMPAD9] = KEY_KP_9; + keycode_map[VK_ADD] = KEY_KP_ADD; + keycode_map[VK_DECIMAL] = KEY_KP_DECIMAL; + keycode_map[VK_DIVIDE] = KEY_KP_DIVIDE; + keycode_map[VK_MULTIPLY] = KEY_KP_MULTIPLY; + keycode_map[VK_SUBTRACT] = KEY_KP_SUBTRACT; +} + +bool platform_file_exists(char *path) +{ + DWORD dwAttrib = GetFileAttributes(path); + + return (dwAttrib != INVALID_FILE_ATTRIBUTES && + !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); +} + +void platform_create_config_directory() +{ + char tmp[PATH_MAX]; + if(SUCCEEDED(SHGetFolderPathA(0, CSIDL_LOCAL_APPDATA|CSIDL_FLAG_CREATE, NULL, 0, tmp))) + { + string_appendn(tmp, CONFIG_DIRECTORY, PATH_MAX); + } + + + if (!platform_directory_exists(tmp)) + { + CreateDirectoryA(tmp, NULL); + } +} + +char* get_config_save_location(char *buffer) +{ + if(SUCCEEDED(SHGetFolderPathA(0, CSIDL_LOCAL_APPDATA|CSIDL_FLAG_CREATE, NULL, 0, buffer))) + { + string_appendn(buffer, CONFIG_DIRECTORY"\\config.txt", MAX_INPUT_LENGTH); + return buffer; + } + + return 0; +} + +void platform_show_message(platform_window *window, char *message, char *title) +{ + HWND handle = window ? window->window_handle : NULL; + MessageBox(handle, message, title, MB_ICONINFORMATION | MB_OK); +} + +LRESULT CALLBACK main_window_callback(HWND window, UINT message, WPARAM wparam, LPARAM lparam) +{ + LRESULT result = 0; + + if (message == WM_SIZE) + { + u32 width = lparam&0xFFFF; + u32 height = lparam>>16; + + current_window_to_handle->width = width; + current_window_to_handle->height = height; + } + else if (message == WM_CHAR) + { + if (current_keyboard_to_handle->take_input) + { + char buf[5]; + memset(buf, 0, 5); + char *ch = 0; + + wchar_t codep = wparam; + + WideCharToMultiByte(CP_UTF8, 0, &codep, 1, buf, 5 ,0,0); + + if (utf8len(buf) == 1) + { + char val = buf[0]; + + if (current_keyboard_to_handle->input_mode == INPUT_NUMERIC) + { + if (!(val >= 48 && val <= 57)) + { + ch = 0; + } + else + { + snprintf(buf, 2, "%c", val); + ch = buf; + } + } + else if (val >= 32 && val <= 126) + { + snprintf(buf, 5, "%c", val); + ch = buf; + } + } + + if (ch != 0) + keyboard_handle_input_string(current_window_to_handle, current_keyboard_to_handle, ch); + } + } + else if (message == WM_MOUSELEAVE) + { + //current_mouse_to_handle->x = MOUSE_OFFSCREEN; + //current_mouse_to_handle->y = MOUSE_OFFSCREEN; + } + else if (message == WM_KILLFOCUS) + { + current_mouse_to_handle->x = MOUSE_OFFSCREEN; + current_mouse_to_handle->y = MOUSE_OFFSCREEN; + + current_window_to_handle->has_focus = false; + memset(current_keyboard_to_handle->keys, 0, MAX_KEYCODE); + } + else if (message == WM_SETFOCUS) + { + current_window_to_handle->has_focus = true; + } + else if (message == WM_KEYDOWN) + { + s32 key = wparam; + + current_keyboard_to_handle->keys[keycode_map[key]] = true; + current_keyboard_to_handle->input_keys[keycode_map[key]] = true; + + if (current_keyboard_to_handle->take_input) + keyboard_handle_input_string(current_window_to_handle, + current_keyboard_to_handle, 0); + } + else if (message == WM_KEYUP) + { + s32 key = wparam; + current_keyboard_to_handle->keys[keycode_map[key]] = false; + current_keyboard_to_handle->input_keys[keycode_map[key]] = false; + } + else if (message == WM_LBUTTONDOWN || + message == WM_RBUTTONDOWN || + message == WM_MBUTTONDOWN || + message == WM_MOUSEWHEEL) + { + bool is_left_down = wparam & MK_LBUTTON; + bool is_right_down = wparam & MK_RBUTTON; + bool is_middle_down = wparam & MK_MBUTTON; + + u64 ev_time = platform_get_time(TIME_FULL, TIME_MILI_S); + static u64 last_ev_time = 0; + + if (message == WM_MOUSEWHEEL) + { + s16 scroll_val = wparam>>16; + + if (scroll_val < 0) + current_mouse_to_handle->scroll_state = SCROLL_DOWN; + else + current_mouse_to_handle->scroll_state = SCROLL_UP; + } + + if (is_left_down) + { + if (ev_time - last_ev_time < 200) + { + current_mouse_to_handle->left_state |= MOUSE_DOUBLE_CLICK; + } + + current_mouse_to_handle->left_state |= MOUSE_DOWN; + current_mouse_to_handle->left_state |= MOUSE_CLICK; + + current_mouse_to_handle->total_move_x = 0; + current_mouse_to_handle->total_move_y = 0; + last_ev_time = ev_time; + } + if (is_right_down) + { + current_mouse_to_handle->right_state |= MOUSE_DOWN; + current_mouse_to_handle->right_state |= MOUSE_CLICK; + } + } + else if (message == WM_LBUTTONUP || + message == WM_RBUTTONUP || + message == WM_MBUTTONUP) + { + bool is_left_up = message == WM_LBUTTONUP; + bool is_right_up = message == WM_RBUTTONUP; + bool is_middle_up = message == WM_MBUTTONUP; + + if (is_left_up) + { + current_mouse_to_handle->left_state = MOUSE_RELEASE; + } + if (is_right_up) + { + current_mouse_to_handle->right_state = MOUSE_RELEASE; + } + } + else if (message == WM_MOUSEMOVE) + { + current_window_to_handle->curr_cursor_type = -999; + +#if 0 + s32 x = lparam&0xFFFF; + s32 y = lparam>>16; + + current_mouse_to_handle->x = x; + current_mouse_to_handle->y = y; +#endif + + TRACKMOUSEEVENT track; + track.cbSize = sizeof(track); + track.dwFlags = TME_LEAVE; + track.hwndTrack = current_window_to_handle->window_handle; + TrackMouseEvent(&track); + } + else if (message == WM_GETMINMAXINFO) + { + MINMAXINFO *info = (MINMAXINFO*)lparam; + + info->ptMinTrackSize.x = current_window_to_handle->min_width; + info->ptMinTrackSize.y = current_window_to_handle->min_height; + + if (current_window_to_handle->max_width) + info->ptMaxTrackSize.x = current_window_to_handle->max_width; + if (current_window_to_handle->max_height) + info->ptMaxTrackSize.y = current_window_to_handle->max_height; + } + else if (message == WM_DESTROY) + { + current_window_to_handle->is_open = false; + } + else if (message == WM_CLOSE) + { + current_window_to_handle->is_open = false; + } + else + { + result = LSMProc(window, message, wparam, lparam); + } + + return result; +} + +void platform_window_set_title(platform_window *window, char *name) +{ + SetWindowText(window->window_handle, name); +} + +vec2 platform_get_window_size(platform_window *window) +{ + RECT rec; + GetWindowRect(window->window_handle, &rec); + vec2 res; + res.x = rec.right - rec.left; + res.y = rec.bottom - rec.top; + return res; +} + +void platform_get_focus(platform_window *window) +{ + SetFocus(window->window_handle); +} + +platform_window platform_open_window(char *name, u16 width, u16 height, u16 max_w, u16 max_h, u16 min_w, u16 min_h) +{ +#if !defined(MODE_GDBDEBUG) && !defined(MODE_DEVELOPER) + ShowWindow(GetConsoleWindow(), SW_HIDE); +#endif + + platform_window window; + window.has_focus = true; + window.window_handle = 0; + window.hdc = 0; + window.width = width; + window.height = height; + window.min_width = min_w; + window.min_height = min_h; + window.max_width = max_w; + window.max_height = max_h; + window.curr_cursor_type = -1; + window.next_cursor_type = CURSOR_DEFAULT; + + current_window_to_handle = &window; + + memset(&window.window_class, 0, sizeof(WNDCLASS)); + window.window_class.style = CS_OWNDC; + window.window_class.lpfnWndProc = main_window_callback; + window.window_class.hInstance = instance; + window.window_class.lpszClassName = name; + window.window_class.hIcon = LoadIcon(NULL, IDI_WINLOGO); + //window.window_class.hCursor = LoadCursor(NULL, IDC_ARROW); + + if (RegisterClass(&window.window_class)) + { + int style = WS_VISIBLE|WS_SYSMENU|WS_CAPTION|WS_MINIMIZEBOX; + + if (min_w != max_w && min_h != max_h) + style |= WS_SIZEBOX; + else + style |= WS_THICKFRAME; + + window.window_handle = CreateWindowEx(0, + window.window_class.lpszClassName, + name, + style, + CW_USEDEFAULT, + CW_USEDEFAULT, + width, + height, + 0, + 0, + instance, + 0); + + if (window.window_handle) + { + window.hdc = GetDC(window.window_handle); + + PIXELFORMATDESCRIPTOR format; + memset(&format, 0, sizeof(PIXELFORMATDESCRIPTOR)); + format.nSize = sizeof(PIXELFORMATDESCRIPTOR); + format.nVersion = 1; + format.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER; + format.cColorBits = 24; + format.cAlphaBits = 8; + format.iLayerType = PFD_MAIN_PLANE; // PFD_TYPE_RGBA + s32 suggested_format_index = ChoosePixelFormat(window.hdc, &format); + + PIXELFORMATDESCRIPTOR actual_format; + DescribePixelFormat(window.hdc, suggested_format_index, sizeof(actual_format), &actual_format); + SetPixelFormat(window.hdc, suggested_format_index, &actual_format); + + window.gl_context = wglCreateContext(window.hdc); + + static HGLRC share_list = 0; + if (share_list == 0) + { + share_list = window.gl_context; + } + else + { + wglShareLists(share_list, window.gl_context); + } + + wglMakeCurrent(window.hdc, window.gl_context); + + ShowWindow(window.window_handle, cmd_show); + + // blending + glEnable(GL_DEPTH_TEST); + //glDepthMask(true); + //glClearDepth(50); + glDepthFunc(GL_LEQUAL); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + // setup multisampling +#if 0 + glEnable(GL_ALPHA_TEST); + glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE); + glEnable(GL_SAMPLE_ALPHA_TO_ONE); + glEnable(GL_MULTISAMPLE); + glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST); +#endif + + // https://stackoverflow.com/questions/5627229/sub-pixel-drawing-with-opengl + //glHint(GL_POINT_SMOOTH, GL_NICEST); + //glHint(GL_LINE_SMOOTH, GL_NICEST); + //glHint(GL_POLYGON_SMOOTH, GL_NICEST); + + //glEnable(GL_SMOOTH); + //glEnable(GL_POINT_SMOOTH); + //glEnable(GL_LINE_SMOOTH); + //glEnable(GL_POLYGON_SMOOTH); + ////////////////// + + window.is_open = true; + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, width, height, 0, -1, 1); + + //GLint m_viewport[4]; + //glGetIntegerv( GL_VIEWPORT, m_viewport ); + //printf("%d %d %d %d\n", m_viewport[0], m_viewport[1], m_viewport[2], m_viewport[3]); + + glMatrixMode(GL_MODELVIEW); + + TRACKMOUSEEVENT track; + track.cbSize = sizeof(track); + track.dwFlags = TME_LEAVE; + track.hwndTrack = window.window_handle; + TrackMouseEvent(&track); + } + else + { + platform_show_message(0, "An error occured within Windows, please restart the program.", "Error"); + abort(); + } + } + else + { + platform_show_message(0, "An error occured within Windows, please restart the program.", "Error"); + abort(); + } + + platform_get_focus(&window); + + return window; +} + +void platform_window_set_size(platform_window *window, u16 width, u16 height) +{ + s32 style = GetWindowLong(window->window_handle, GWL_STYLE); + BOOL menu = FALSE; + + RECT rec; + rec.left = 0; + rec.top = 0; + rec.right = width; + rec.bottom = height; + AdjustWindowRectEx(&rec, style, menu, 0); + SetWindowPos(window->window_handle,NULL,rec.left,rec.top,rec.right,rec.bottom,SWP_NOMOVE|SWP_NOZORDER); +} + +void platform_window_set_position(platform_window *window, u16 x, u16 y) +{ + RECT rec; + GetWindowRect(window->window_handle, &rec); + MoveWindow(window->window_handle, x, y, rec.right-rec.left, rec.bottom-rec.top, FALSE); +} + +bool platform_window_is_valid(platform_window *window) +{ + return window->hdc && window->window_handle; +} + +void platform_destroy_window(platform_window *window) +{ + wglMakeCurrent(NULL, NULL); + wglDeleteContext(window->gl_context); + + ReleaseDC(window->window_handle, window->hdc); + CloseWindow(window->window_handle); + DestroyWindow(window->window_handle); + UnregisterClassA(window->window_class.lpszClassName, instance); + window->hdc = 0; + window->window_handle = 0; +} + +void platform_handle_events(platform_window *window, mouse_input *mouse, keyboard_input *keyboard) +{ + current_window_to_handle = window; + current_keyboard_to_handle = keyboard; + current_mouse_to_handle = mouse; + + mouse->left_state &= ~MOUSE_CLICK; + mouse->right_state &= ~MOUSE_CLICK; + mouse->left_state &= ~MOUSE_DOUBLE_CLICK; + mouse->right_state &= ~MOUSE_DOUBLE_CLICK; + mouse->left_state &= ~MOUSE_RELEASE; + mouse->right_state &= ~MOUSE_RELEASE; + memset(keyboard->input_keys, 0, MAX_KEYCODE); + mouse->move_x = 0; + mouse->move_y = 0; + mouse->scroll_state = 0; + keyboard->text_changed = false; + + // mouse position (including outside of window) + current_window_to_handle->has_focus = GetFocus() == current_window_to_handle->window_handle; + + if (current_window_to_handle->has_focus) + { + if((GetKeyState(VK_LBUTTON) & 0x100) == 0) + { + current_mouse_to_handle->left_state = MOUSE_RELEASE; + } + + RECT rec; + GetWindowRect(window->window_handle, &rec); + POINT p; + GetCursorPos(&p); + mouse->x = p.x - rec.left - GetSystemMetrics(SM_CYSIZEFRAME); + mouse->y = p.y - rec.top - GetSystemMetrics(SM_CYSIZE) - GetSystemMetrics(SM_CYFRAME); + //printf("%d %d\n",GetSystemMetrics(SM_CYSIZE), GetSystemMetrics(SM_CYFRAME)); + } + + MSG message; + while(PeekMessageA(&message, window->window_handle, 0, 0, TRUE)) + { + TranslateMessage(&message); + SizingCheck(&message); + DispatchMessage(&message); + } + + glViewport(0, 0, window->width, window->height); +} + +void platform_window_swap_buffers(platform_window *window) +{ + // set cursor if changed + if (window->curr_cursor_type != window->next_cursor_type) + { + char *cursor_shape = 0; + switch(window->next_cursor_type) + { + case CURSOR_DEFAULT: cursor_shape = IDC_ARROW; break; + case CURSOR_POINTER: cursor_shape = IDC_HAND; break; + } + + HCURSOR cursor = LoadCursorA(NULL, cursor_shape); + + window->curr_cursor_type = window->next_cursor_type; + SetCursor(cursor); + } + + SwapBuffers(window->hdc); +} + +file_content platform_read_file_content(char *path, const char *mode) +{ + file_content result; + result.content = 0; + result.content_length = 0; + result.file_error = 0; + + FILE *file = fopen(path, mode); + if (!file) + { + if (errno == EMFILE) + result.file_error = FILE_ERROR_TOO_MANY_OPEN_FILES_PROCESS; + else if (errno == ENFILE) + result.file_error = FILE_ERROR_TOO_MANY_OPEN_FILES_SYSTEM; + else if (errno == EACCES) + result.file_error = FILE_ERROR_NO_ACCESS; + else if (errno == EPERM) + result.file_error = FILE_ERROR_NO_ACCESS; + else if (errno == ENOENT) + result.file_error = FILE_ERROR_NOT_FOUND; + else if (errno == ECONNABORTED) + result.file_error = FILE_ERROR_CONNECTION_ABORTED; + else if (errno == ECONNREFUSED) + result.file_error = FILE_ERROR_CONNECTION_REFUSED; + else if (errno == ENETDOWN) + result.file_error = FILE_ERROR_NETWORK_DOWN; + else + { + result.file_error = FILE_ERROR_GENERIC; + printf("ERROR: %d\n", errno); + } + + goto done_failure; + } + + fseek(file, 0 , SEEK_END); + int length = ftell(file); + fseek(file, 0, SEEK_SET); + + s32 length_to_alloc = length+1; + + result.content = mem_alloc(length_to_alloc); + if (!result.content) goto done; + + memset(result.content, 0, length); + s32 read_result = fread(result.content, 1, length, file); + if (read_result == 0 && length != 0) + { + mem_free(result.content); + result.content = 0; + return result; + } + + result.content_length = read_result; + + ((char*)result.content)[length] = 0; + + done: + fclose(file); + done_failure: + return result; +} + +void platform_delete_file(char *path) +{ + remove(path); +} + +bool platform_write_file_content(char *path, const char *mode, char *buffer, s32 len) +{ + bool result = false; + + FILE *file = fopen(path, mode); + + if (!file) + { + goto done_failure; + } + else + { + fwrite(buffer, 1, len, file); + //fprintf(file, buffer); + } + + //done: + fclose(file); + done_failure: + return result; +} + +void platform_destroy_file_content(file_content *content) +{ + assert(content); + mem_free(content->content); +} + +bool get_active_directory(char *buffer) +{ + return GetCurrentDirectory(MAX_INPUT_LENGTH, buffer); +} + +bool set_active_directory(char *path) +{ + return SetCurrentDirectory(path); +} + +void platform_list_files_block(array *list, char *start_dir, array filters, bool recursive, memory_bucket *bucket, bool include_directories, bool *is_cancelled) +{ + assert(list); + s32 len = 0; + char *matched_filter = 0; + + char *subdirname_buf; + if (bucket) + subdirname_buf = memory_bucket_reserve(bucket, MAX_INPUT_LENGTH); + else + subdirname_buf = mem_alloc(MAX_INPUT_LENGTH); + + char *start_dir_fix; + if (bucket) + start_dir_fix = memory_bucket_reserve(bucket, MAX_INPUT_LENGTH); + else + start_dir_fix = mem_alloc(MAX_INPUT_LENGTH); + snprintf(start_dir_fix, MAX_INPUT_LENGTH, "%s*", start_dir); + + char *start_dir_clean; + if (bucket) + start_dir_clean = memory_bucket_reserve(bucket, MAX_INPUT_LENGTH); + else + start_dir_clean = mem_alloc(MAX_INPUT_LENGTH); + string_copyn(start_dir_clean, start_dir, MAX_INPUT_LENGTH); + + WIN32_FIND_DATAA file_info; + HWND handle = FindFirstFileA(start_dir_fix, &file_info); + + if (!bucket) + mem_free(start_dir_fix); + + if (handle == INVALID_HANDLE_VALUE) + { + return; + } + + do + { + if (*is_cancelled) break; + char *name = file_info.cFileName; + + // symbolic link is not allowed.. + if ((file_info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) + continue; + + + if ((file_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + { + if ((strcmp(name, ".") == 0) || (strcmp(name, "..") == 0)) + continue; + + if (include_directories) + { + if ((len = filter_matches(&filters, name, + &matched_filter)) && len != -1) + { + // is file + char *buf; + if (bucket) + buf = memory_bucket_reserve(bucket, MAX_INPUT_LENGTH); + else + buf = mem_alloc(MAX_INPUT_LENGTH); + snprintf(buf, MAX_INPUT_LENGTH, "%s%s",start_dir, name); + + found_file f; + f.path = buf; + + if (bucket) + f.matched_filter= memory_bucket_reserve(bucket, len+1); + else + f.matched_filter= mem_alloc(len+1); + + string_copyn(f.matched_filter, matched_filter, len+1); + + mutex_lock(&list->mutex); + array_push_size(list, &f, sizeof(found_file)); + mutex_unlock(&list->mutex); + } + } + + if (recursive) + { + string_copyn(subdirname_buf, start_dir_clean, MAX_INPUT_LENGTH); + string_appendn(subdirname_buf, name, MAX_INPUT_LENGTH); + string_appendn(subdirname_buf, "\\", MAX_INPUT_LENGTH); + + // is directory + platform_list_files_block(list, subdirname_buf, filters, recursive, bucket, include_directories, is_cancelled); + } + } + else if ((file_info.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) || + (file_info.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) || + (file_info.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) || + (file_info.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) || + (file_info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) || + (file_info.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE)) + { + if ((len = filter_matches(&filters, name, + &matched_filter)) && len != -1) + { + // is file + char *buf; + if (bucket) + buf = memory_bucket_reserve(bucket, MAX_INPUT_LENGTH); + else + buf = mem_alloc(MAX_INPUT_LENGTH); + + snprintf(buf, MAX_INPUT_LENGTH, "%s%s",start_dir, name); + + found_file f; + f.path = buf; + + if (bucket) + f.matched_filter = memory_bucket_reserve(bucket, len+1); + else + f.matched_filter = mem_alloc(len+1); + + string_copyn(f.matched_filter, matched_filter, len+1); + + mutex_lock(&list->mutex); + array_push_size(list, &f, sizeof(found_file)); + mutex_unlock(&list->mutex); + } + } + } + while (FindNextFile(handle, &file_info) != 0); + + if (!bucket) + mem_free(start_dir_clean); + + FindClose(handle); +} + +static void* platform_open_file_dialog_implementation(void *data) +{ + struct open_dialog_args *args = data; + + OPENFILENAME info; + info.lStructSize = sizeof(OPENFILENAME); + info.hwndOwner = NULL; + info.hInstance = NULL; + + char filter[MAX_INPUT_LENGTH]; + memset(filter, 0, MAX_INPUT_LENGTH); + + if (args->file_filter) + { + string_copyn(filter, args->file_filter, MAX_INPUT_LENGTH); + filter[strlen(filter)] = 0; + filter[strlen(filter)+1] = 0; + info.lpstrFilter = filter; + } + else + { + info.lpstrFilter = NULL; + } + + char szFile[MAX_INPUT_LENGTH]; + memset(szFile, 0, MAX_INPUT_LENGTH); + + info.lpstrCustomFilter = NULL; + info.nMaxCustFilter = MAX_INPUT_LENGTH; + info.nFilterIndex = 0; + info.lpstrFile = (char*)szFile; + info.nMaxFile = MAX_INPUT_LENGTH; + + info.lpstrDefExt = args->default_save_file_extension; + + info.lpstrFileTitle = NULL; + info.lpstrInitialDir = args->start_path; + info.lpstrTitle = NULL; + + if (args->type == SAVE_FILE) + { + info.Flags = OFN_EXTENSIONDIFFERENT | OFN_OVERWRITEPROMPT; + GetSaveFileNameA(&info); + string_copyn(args->buffer, info.lpstrFile, MAX_INPUT_LENGTH); + } + else if (args->type == OPEN_DIRECTORY) + { + BROWSEINFOA inf; + PIDLIST_ABSOLUTE result = SHBrowseForFolderA(&inf); + if (!result) return 0; + + SHGetPathFromIDListA(result, args->buffer); + } + else if (args->type == OPEN_FILE) + { + info.Flags = OFN_FILEMUSTEXIST; + GetOpenFileNameA(&info); + string_copyn(args->buffer, info.lpstrFile, MAX_INPUT_LENGTH); + } + + return 0; +} + +void *platform_open_file_dialog_block(void *arg) +{ + platform_open_file_dialog_implementation(arg); + mem_free(arg); + return 0; +} + +char *platform_get_full_path(char *file) +{ + char *buf = mem_alloc(MAX_INPUT_LENGTH); + if (!GetFullPathNameA(file, MAX_INPUT_LENGTH, buf, NULL)) + { + buf[0] = 0; + } + + return buf; +} + +void platform_open_url(char *command) +{ + platform_run_command(command); +} + +void platform_run_command(char *command) +{ + // might be start instead of open + ShellExecuteA(NULL, "open", command, NULL, NULL, SW_SHOWDEFAULT); +} + +void platform_window_make_current(platform_window *window) +{ + wglMakeCurrent(window->hdc, window->gl_context); +} + +void platform_init(int argc, char **argv) +{ + setlocale(LC_ALL, "en_US.UTF-8"); + + QueryPerformanceFrequency(&perf_frequency); + CoInitialize(NULL); + create_key_tables(); + + instance = GetModuleHandle(NULL); + cmd_show = argc; + + // get fullpath of the directory the exe is residing in + binary_path = platform_get_full_path(argv[0]); + + platform_create_config_directory(); + + char buf[MAX_INPUT_LENGTH]; + get_directory_from_path(buf, binary_path); + string_copyn(binary_path, buf, MAX_INPUT_LENGTH); + + assets_create(); +} + +void platform_set_icon(platform_window *window, image *img) +{ + BYTE *bmp; + s32 data_len = img->width * img->height * 4; + s32 total_len = data_len + 40 * 4; + + bmp = mem_alloc(total_len); + + struct { + int32_t header_size, width, geight; + int16_t color_plane, bits_per_pixel; + int32_t compression_mode, img_length, obsolete[4]; + } bmp_header = {40, img->width, img->height * 2, 1, 32, BI_RGB, data_len, {0,0,0,0} }; + + memcpy(bmp, &bmp_header, 40); + + s32 index = 0; + for (s32 y = img->height-1; y >= 0; y--) + { + for (s32 x = 0; x < img->width; x++) + { + s32 img_pixel = *(((s32*)img->data+(x+(y*img->width)))); + + // 0xAABBGGRR + s32 a = (img_pixel>>24) & 0x000000FF; + s32 b = (img_pixel>>16) & 0x000000FF; + s32 g = (img_pixel>> 8) & 0x000000FF; + s32 r = (img_pixel>> 0) & 0x000000FF; + + //s32 c = (r << 24) | (g << 16) | (b << 8) | (a << 0); + s32 c = (a << 24) | (r << 16) | (g << 8) | (b << 0); + memcpy(bmp+40+(index*4), &c, 4); + + ++index; + } + } + + HICON icon = CreateIconFromResourceEx(bmp, total_len, TRUE, 0x00030000, img->width, img->height, LR_DEFAULTCOLOR); + + SendMessage(window->window_handle, WM_SETICON, ICON_SMALL, (LPARAM)icon); + SendMessage(window->window_handle, WM_SETICON, ICON_BIG, (LPARAM)icon); + + mem_free(bmp); + + if (!icon) + printf("Failed to load icon, error code: %ld.\n", GetLastError()); +} + +u64 platform_get_time(time_type time_type, time_precision precision) +{ + LARGE_INTEGER counter; + QueryPerformanceCounter(&counter); + + double sec = counter.QuadPart / (double)(perf_frequency.QuadPart); + + //printf("%I64d %I64d %f\n", counter.QuadPart, perf_frequency.QuadPart, sec); + + double val = sec; + + if (precision == TIME_NS) + { + return val*1000000000; + } + if (precision == TIME_US) + { + return val*1000000; + } + if (precision == TIME_MILI_S) + { + return val*1000; + } + if (precision == TIME_S) + { + return val; + } + return val; +} + +s32 platform_get_memory_size() +{ + u64 result; + GetPhysicallyInstalledSystemMemory(&result); + return result; +} + +s32 platform_get_cpu_count() +{ + SYSTEM_INFO info; + GetSystemInfo(&info); + + return info.dwNumberOfProcessors; +} + +u64 string_to_u64(char *str) +{ + return (u64)strtoull(str, 0, 10); +} + +u32 string_to_u32(char *str) +{ + return (u32)strtoul(str, 0, 10); +} + +u16 string_to_u16(char *str) +{ + return (u16)strtoul(str, 0, 10); +} + +u8 string_to_u8(char *str) +{ + return (u8)strtoul(str, 0, 10); +} + +s64 string_to_s64(char *str) +{ + return (s64)strtoull(str, 0, 10); +} + +s32 string_to_s32(char *str) +{ + return (s32)strtoul(str, 0, 10); +} + +s16 string_to_s16(char *str) +{ + return (s16)strtoul(str, 0, 10); +} + +s8 string_to_s8(char *str) +{ + return (s8)strtoul(str, 0, 10); +} + +bool platform_send_http_request(char *url, char *params, char *response_buffer) +{ + // https://www.unix.com/programming/187337-c-http-get-request-using-sockets.html + + bool response = true; + HINTERNET hIntSession = 0; + HINTERNET hHttpSession = 0; + HINTERNET hHttpRequest = 0; + + hIntSession = InternetOpen("Text-Search", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0); + if (!hIntSession) goto failure; + + hHttpSession = InternetConnect(hIntSession, url, 80, 0, 0, INTERNET_SERVICE_HTTP, 0, 0); + if (!hHttpSession) goto failure; + + hHttpRequest = HttpOpenRequest( + hHttpSession, + "GET", + params, + 0, 0, 0, INTERNET_FLAG_RELOAD, 0); + + + char* szHeaders = "Content-Type: application/json"; + char szReq[1024] = ""; + if(!HttpSendRequest(hHttpRequest, szHeaders, strlen(szHeaders), szReq, strlen(szReq))) { + goto failure; + } + + DWORD dwRead=0; + while(InternetReadFile(hHttpRequest, response_buffer, MAX_INPUT_LENGTH-1, &dwRead) && dwRead) { + response_buffer[dwRead] = 0; + dwRead=0; + } + + goto done; + + failure: + printf("failure"); + response = false; + + done: + InternetCloseHandle(hHttpRequest); + InternetCloseHandle(hHttpSession); + InternetCloseHandle(hIntSession); + + return response; +} + +bool platform_get_mac_address(char *buffer, s32 buf_size) +{ + PIP_ADAPTER_INFO pAdapterInfo; + PIP_ADAPTER_INFO pAdapter = NULL; + DWORD dwRetVal = 0; + UINT i; + + ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO); + pAdapterInfo = mem_alloc(sizeof(IP_ADAPTER_INFO)); + + if (!pAdapterInfo) return false; + + if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) { + mem_free(pAdapterInfo); + pAdapterInfo = mem_alloc(ulOutBufLen); + if (!pAdapterInfo) return false; + } + + if ((dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR) { + pAdapter = pAdapterInfo; + + if (pAdapter) { + for (i = 0; i < pAdapter->AddressLength; i++) { + if (i == (pAdapter->AddressLength - 1)) + buffer += sprintf(buffer, "%.2X", (int)pAdapter->Address[i]); + else + buffer += sprintf(buffer, "%.2X-", (int)pAdapter->Address[i]); + } + + if (pAdapterInfo) mem_free(pAdapterInfo); + return true; + } + } + + return false; } \ No newline at end of file -- cgit v1.2.3-70-g09d2