From 0aa1df3da05f872db05439cbd7e80e901a1cf8fb Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Wed, 6 Jan 2016 10:39:15 -0500 Subject: [PATCH] locales --- 4cpp_config.h => 4coder_config.h | 0 4coder_custom.cpp | 100 +- 4coder_custom.h | 32 +- 4coder_helper.h | 52 +- 4cpp_string.h => 4coder_string.h | 33 +- 4cpp_lexer.h | 2 +- 4cpp_preprocessor.cpp | 2741 ++++++++--------------------- 4cpp_types.h | 2 +- 4ed.cpp | 955 ++++++---- 4ed.h | 53 +- 4ed_app_target.cpp | 6 +- 4ed_color_view.cpp | 353 ++-- 4ed_command.cpp | 33 +- 4ed_debug_view.cpp | 62 +- 4ed_exchange.cpp | 217 +++ 4ed_file_view.cpp | 1244 ++++++------- 4ed_font_set.cpp | 232 +++ 4ed_interactive_view.cpp | 20 +- 4ed_keyboard.cpp | 70 +- 4ed_layout.cpp | 71 +- 4ed_mem.cpp | 64 +- 4ed_menu_view.cpp | 2 +- 4ed_meta.h | 8 +- 4ed_rendering.cpp | 449 ++--- 4ed_rendering.h | 88 +- 4ed_rendering_helper.cpp | 127 +- 4ed_rendering_old.cpp | 405 ----- 4ed_style.cpp | 83 +- 4ed_system.h | 134 +- 4ed_ttf.cpp | 360 ++++ 4ed_win32_keyboard.cpp | 73 +- buffer/4coder_buffer_abstract.cpp | 302 ++-- build.bat | 3 + buildsuper.bat | 17 + temp.cpp | 22 - test/experiment.cpp | 210 +-- vc120.pdb | Bin 0 -> 94208 bytes win32_4ed.cpp | 754 +++++--- 38 files changed, 4601 insertions(+), 4778 deletions(-) rename 4cpp_config.h => 4coder_config.h (100%) rename 4cpp_string.h => 4coder_string.h (93%) create mode 100644 4ed_exchange.cpp create mode 100644 4ed_font_set.cpp delete mode 100644 4ed_rendering_old.cpp create mode 100644 4ed_ttf.cpp create mode 100644 build.bat create mode 100644 buildsuper.bat delete mode 100644 temp.cpp create mode 100644 vc120.pdb diff --git a/4cpp_config.h b/4coder_config.h similarity index 100% rename from 4cpp_config.h rename to 4coder_config.h diff --git a/4coder_custom.cpp b/4coder_custom.cpp index 95faa706..be856f74 100644 --- a/4coder_custom.cpp +++ b/4coder_custom.cpp @@ -2,18 +2,20 @@ * Example use of customization API */ +#define FCPP_STRING_IMPLEMENTATION +#include "4coder_string.h" + #include "4coder_custom.h" #include "4coder_helper.h" -#define exec_command_keep_stack app.exec_command_keep_stack -#define clear_parameters app.clear_parameters -#define get_active_buffer app.get_active_buffer +#define exec_command_keep_stack app->exec_command_keep_stack +#define clear_parameters app->clear_parameters +#define get_active_buffer app->get_active_buffer #define exec_command(cmd_context, id) \ exec_command_keep_stack(cmd_context, id); \ clear_parameters(cmd_context) -#define push_parameter(cmd_context, ...) push_parameter_helper(cmd_context, app, __VA_ARGS__) -#define push_memory(cmd_context, len) app.push_memory(cmd_context, len) +#define push_memory(cmd_context, len) app->push_memory(cmd_context, len) #define literal(s) s, (sizeof(s)-1) @@ -21,6 +23,7 @@ // I recommend enumerating your own map ids as shown here. enum My_Maps{ my_code_map = mapid_user_custom, + my_html_map }; HOOK_SIG(my_start){ @@ -64,9 +67,9 @@ HOOK_SIG(my_file_settings){ else if (str_match(extension, extension_len, literal("hpp"))) treat_as_code = 1; } - push_parameter(cmd_context, par_lex_as_cpp_file, treat_as_code); - push_parameter(cmd_context, par_wrap_lines, !treat_as_code); - push_parameter(cmd_context, par_key_mapid, (treat_as_code)?(my_code_map):(mapid_file)); + push_parameter(app, cmd_context, par_lex_as_cpp_file, treat_as_code); + push_parameter(app, cmd_context, par_wrap_lines, !treat_as_code); + push_parameter(app, cmd_context, par_key_mapid, (treat_as_code)?(my_code_map):(mapid_file)); exec_command(cmd_context, cmdid_set_settings); } @@ -79,7 +82,7 @@ CUSTOM_COMMAND_SIG(open_my_files){ // NOTE(allen|a3.1): The command cmdid_interactive_open can now open // a file specified on the parameter stack. If the file does not // exist cmdid_interactive_open behaves as usual. - push_parameter(cmd_context, par_name, literal("w:/4ed/data/test/basic.cpp")); + push_parameter(app, cmd_context, par_name, literal("w:/4ed/data/test/basic.cpp")); exec_command(cmd_context, cmdid_interactive_open); exec_command(cmd_context, cmdid_change_active_panel); @@ -93,12 +96,82 @@ CUSTOM_COMMAND_SIG(open_my_files){ } // NOTE(allen|a3.1): null terminators are not needed for strings. - push_parameter(cmd_context, par_name, my_file, my_file_len); + push_parameter(app, cmd_context, par_name, my_file, my_file_len); exec_command(cmd_context, cmdid_interactive_open); exec_command(cmd_context, cmdid_change_active_panel); } +CUSTOM_COMMAND_SIG(build_at_launch_location){ + // NOTE(allen|a3.3): An example of calling build by setting all + // parameters directly. This only works if build.bat can be called + // from the starting directory + push_parameter(app, cmd_context, par_cli_overlap_with_conflict, 1); + push_parameter(app, cmd_context, par_target_buffer_name, literal("*compilation*")); + push_parameter(app, cmd_context, par_cli_path, literal(".")); + push_parameter(app, cmd_context, par_cli_command, literal("build")); + exec_command(cmd_context, cmdid_build); +} + +CUSTOM_COMMAND_SIG(build_search){ + // NOTE(allen|a3.3): An example of traversing the filesystem through parent + // directories looking for a file, in this case a batch file to execute. + // + // + // Step 1: push_directory returns a String containing the current "hot" directory + // (whatever directory you most recently visited in the 4coder file browsing interface) + // + // Step 2: app->directory_has_file queries the file system to see if "build.bat" exists + // If it does exist several parameters are pushed: + // - par_cli_overlap_with_conflict: whether to launch this process if an existing process + // is already being used for output on the same buffer + // + // - par_target_buffer_name: the name of the buffer to fill with the output from the process + // + // - par_cli_path: sets the path from which the command is executed + // + // - par_cli_command: sets the actual command to be executed, this can be almost any command + // that you could execute through a command line interface + // + // + // To set par_cli_path: push_parameter makes a copy of the dir string on the stack + // because the string allocated by push_directory is going to change again + // To set par_cli_command: app->push_parameter does not make a copy of the dir because + // dir isn't going to change again. + // + // Step 3: If the batch file did not exist try to move to the parent directory using + // app->directory_cd. The cd function can also be used to navigate to subdirectories. + // It returns true if it can actually move in the specified direction, and false otherwise. + + int keep_going = 1; + String dir = push_directory(app, cmd_context); + while (keep_going){ + if (app->directory_has_file(dir, "build.bat")){ + push_parameter(app, cmd_context, par_cli_overlap_with_conflict, 0); + push_parameter(app, cmd_context, par_target_buffer_name, literal("*compilation*")); + push_parameter(app, cmd_context, par_cli_path, dir.str, dir.size); + + if (append(&dir, "build")){ + app->push_parameter(cmd_context, + dynamic_int(par_cli_command), + dynamic_string(dir.str, dir.size)); + exec_command(cmd_context, cmdid_build); + } + else{ + clear_parameters(cmd_context); + } + + return; + } + + if (app->directory_cd(&dir, "..") == 0){ + keep_going = 0; + } + } + + // TODO(allen): feedback message - couldn't find build.bat +} + CUSTOM_COMMAND_SIG(write_and_auto_tab){ exec_command(cmd_context, cmdid_write_character); exec_command(cmd_context, cmdid_auto_tab_line_at_cursor); @@ -126,9 +199,12 @@ extern "C" GET_BINDING_DATA(get_bindings){ bind(context, 'c', MDFR_ALT, cmdid_open_color_tweaker); bind(context, 'x', MDFR_ALT, cmdid_open_menu); bind_me(context, 'o', MDFR_ALT, open_in_other); - // NOTE(allen|a3.1): Go look at open_my_files, that's the only point of this being here, - // it won't actually be useful for you. + + // NOTE(allen): These callbacks may not actually be useful to you, but + // go look at them and see what they do. bind_me(context, 'M', MDFR_ALT | MDFR_CTRL, open_my_files); + bind_me(context, 'M', MDFR_ALT, build_at_launch_location); + bind_me(context, 'm', MDFR_ALT, build_search); end_map(context); diff --git a/4coder_custom.h b/4coder_custom.h index e7abb8c3..b0a5c344 100644 --- a/4coder_custom.h +++ b/4coder_custom.h @@ -5,10 +5,7 @@ #define MDFR_SHIFT 4 #define MDFR_NUMPAD 8 -// NOTE(allen): These need not be used direct -#define MDFR_EXACT 128 - -typedef u16 Code; +typedef unsigned char Code; struct Key_Codes{ Code back; @@ -121,6 +118,7 @@ enum Command_ID{ cmdid_cursor_mark_swap, cmdid_open_menu, cmdid_set_settings, + cmdid_build, // cmdid_count }; @@ -130,6 +128,10 @@ enum Param_ID{ par_lex_as_cpp_file, par_wrap_lines, par_key_mapid, + par_target_buffer_name, + par_cli_path, + par_cli_command, + par_cli_overlap_with_conflict, // never below this par_type_count }; @@ -230,10 +232,19 @@ struct Buffer_Summary{ int map_id; }; +#ifndef FRED_STRING_STRUCT +#define FRED_STRING_STRUCT +struct String{ + char *str; + int size; + int memory_size; +}; +#endif + #define GET_BINDING_DATA(name) int name(void *data, int size, Key_Codes *codes) #define SET_EXTRA_FONT_SIG(name) void name(Extra_Font *font_out) -#define CUSTOM_COMMAND_SIG(name) void name(void *cmd_context, struct Application_Links app) -#define HOOK_SIG(name) void name(void *cmd_context, struct Application_Links app) +#define CUSTOM_COMMAND_SIG(name) void name(void *cmd_context, struct Application_Links *app) +#define HOOK_SIG(name) void name(void *cmd_context, struct Application_Links *app) extern "C"{ typedef CUSTOM_COMMAND_SIG(Custom_Command_Function); @@ -247,6 +258,9 @@ extern "C"{ #define EXECUTE_COMMAND_SIG(name) void name(void *cmd_context, int command_id) #define CLEAR_PARAMETERS_SIG(name) void name(void *cmd_context) #define GET_ACTIVE_BUFFER_SIG(name) Buffer_Summary name(void *cmd_context) +#define DIRECTORY_GET_HOT_SIG(name) int name(void *cmd_context, char *buffer, int max) +#define DIRECTORY_HAS_FILE_SIG(name) int name(String dir, char *filename) +#define DIRECTORY_CD_SIG(name) int name(String *dir, char *rel_path) extern "C"{ typedef EXECUTE_COMMAND_SIG(Exec_Command_Function); @@ -254,6 +268,9 @@ extern "C"{ typedef PUSH_MEMORY_SIG(Push_Memory_Function); typedef CLEAR_PARAMETERS_SIG(Clear_Parameters_Function); typedef GET_ACTIVE_BUFFER_SIG(Get_Active_Buffer_Function); + typedef DIRECTORY_GET_HOT_SIG(Directory_Get_Hot); + typedef DIRECTORY_HAS_FILE_SIG(Directory_Has_File); + typedef DIRECTORY_CD_SIG(Directory_CD); } struct Application_Links{ @@ -262,6 +279,9 @@ struct Application_Links{ Push_Memory_Function *push_memory; Clear_Parameters_Function *clear_parameters; Get_Active_Buffer_Function *get_active_buffer; + Directory_Get_Hot *directory_get_hot; + Directory_Has_File *directory_has_file; + Directory_CD *directory_cd; }; struct Config_API{ diff --git a/4coder_helper.h b/4coder_helper.h index 43639de9..85623ceb 100644 --- a/4coder_helper.h +++ b/4coder_helper.h @@ -97,14 +97,6 @@ struct Bind_Target{ unsigned char modifiers; }; -inline Bind_Target -ekey(short code, unsigned char modifiers){ - Bind_Target target; - target.code = code; - target.modifiers = modifiers | MDFR_EXACT; - return target; -} - inline Bind_Target tkey(short code, unsigned char modifiers){ Bind_Target target; @@ -144,14 +136,14 @@ bind_me(Bind_Helper *helper, Bind_Target target, Custom_Command_Function *func){ inline void bind(Bind_Helper *helper, short code, unsigned char modifiers, int cmdid){ Bind_Target target; - target.code = tkey(code, modifiers); + target = tkey(code, modifiers); bind(helper, target, cmdid); } inline void bind_me(Bind_Helper *helper, short code, unsigned char modifiers, Custom_Command_Function *func){ Bind_Target target; - target.code = tkey(code, modifiers); + target = tkey(code, modifiers); bind_me(helper, target, func); } @@ -207,30 +199,46 @@ end_bind_helper(Bind_Helper *helper){ // NOTE(allen): Useful functions and overloads on app links inline void -push_parameter_helper(void *cmd_context, Application_Links app, int param, int value){ - app.push_parameter(cmd_context, dynamic_int(param), dynamic_int(value)); +push_parameter(Application_Links *app, void *cmd_context, int param, int value){ + app->push_parameter(cmd_context, dynamic_int(param), dynamic_int(value)); } inline void -push_parameter_helper(void *cmd_context, Application_Links app, int param, const char *value, int value_len){ - char *value_copy = app.push_memory(cmd_context, value_len); +push_parameter(Application_Links *app, void *cmd_context, int param, const char *value, int value_len){ + char *value_copy = app->push_memory(cmd_context, value_len+1); copy(value_copy, value, value_len); - app.push_parameter(cmd_context, dynamic_int(param), dynamic_string(value_copy, value_len)); + value_copy[value_len] = 0; + app->push_parameter(cmd_context, dynamic_int(param), dynamic_string(value_copy, value_len)); } inline void -push_parameter_helper(void *cmd_context, Application_Links app, const char *param, int param_len, int value){ - char *param_copy = app.push_memory(cmd_context, param_len); +push_parameter(Application_Links *app, void *cmd_context, const char *param, int param_len, int value){ + char *param_copy = app->push_memory(cmd_context, param_len+1); copy(param_copy, param, param_len); - app.push_parameter(cmd_context, dynamic_string(param_copy, param_len), dynamic_int(value)); + param_copy[param_len] = 0; + app->push_parameter(cmd_context, dynamic_string(param_copy, param_len), dynamic_int(value)); } inline void -push_parameter_helper(void *cmd_context, Application_Links app, const char *param, int param_len, const char *value, int value_len){ - char *param_copy = app.push_memory(cmd_context, param_len); - char *value_copy = app.push_memory(cmd_context, value_len); +push_parameter(Application_Links *app, void *cmd_context, const char *param, int param_len, const char *value, int value_len){ + char *param_copy = app->push_memory(cmd_context, param_len+1); + char *value_copy = app->push_memory(cmd_context, value_len+1); copy(param_copy, param, param_len); copy(value_copy, value, value_len); - app.push_parameter(cmd_context, dynamic_string(param_copy, param_len), dynamic_string(value_copy, value_len)); + value_copy[value_len] = 0; + param_copy[param_len] = 0; + + app->push_parameter(cmd_context, dynamic_string(param_copy, param_len), dynamic_string(value_copy, value_len)); } +inline String +push_directory(Application_Links *app, void *cmd_context){ + String result; + result.memory_size = 512; + result.str = app->push_memory(cmd_context, result.memory_size); + result.size = app->directory_get_hot(cmd_context, result.str, result.memory_size); + return(result); +} + +#define dir_string(d) ((d).str), ((d).size) + diff --git a/4cpp_string.h b/4coder_string.h similarity index 93% rename from 4cpp_string.h rename to 4coder_string.h index 3ece385b..984f5f4a 100644 --- a/4cpp_string.h +++ b/4coder_string.h @@ -24,16 +24,19 @@ NOTES ON USE: // - memcpy / memmove replacements (different file for optimization options?) // -#include "4cpp_config.h" +#include "4coder_config.h" #ifndef FCPP_STRING_INC #define FCPP_STRING_INC +#ifndef FRED_STRING_STRUCT +#define FRED_STRING_STRUCT struct String{ char *str; int size; int memory_size; }; +#endif inline bool char_not_slash(char c) { return (c != '\\' && c != '/'); } inline bool char_is_slash(char c) { return (c == '\\' || c == '/'); } @@ -147,12 +150,14 @@ inline int compare(char *a, String b) { return -compare(b,a); } FCPP_LINK int compare(String a, String b); FCPP_LINK int reverse_seek_slash(String str); +FCPP_LINK int reverse_seek_slash(String str, int start_pos); inline bool get_front_of_directory(String *dest, String dir) { return append_checked(dest, substr(dir, reverse_seek_slash(dir) + 1)); } inline bool get_path_of_directory(String *dest, String dir) { return append_checked(dest, substr(dir, 0, reverse_seek_slash(dir) + 1)); } FCPP_LINK bool set_last_folder(String *dir, char *folder_name); FCPP_LINK bool set_last_folder(String *dir, String folder_name); FCPP_LINK String file_extension(String str); FCPP_LINK String file_extension_slowly(char *str); +FCPP_LINK bool remove_last_folder(String *str); inline String make_string(char *str, int size, int mem_size){ String result; @@ -834,14 +839,19 @@ compare(String a, String b){ } FCPP_LINK int -reverse_seek_slash(String str){ - int i = str.size - 1; +reverse_seek_slash(String str, int pos){ + int i = str.size - 1 - pos; while (i >= 0 && char_not_slash(str.str[i])){ --i; } return i; } +FCPP_LINK int +reverse_seek_slash(String str){ + return(reverse_seek_slash(str, 0)); +} + FCPP_LINK bool set_last_folder(String *dir, char *folder_name){ bool result = 0; @@ -886,7 +896,7 @@ file_extension(String str){ FCPP_LINK String file_extension_slowly(char *str){ - i32 s, i; + int s, i; for (s = 0; str[s]; ++s); for (i = s - 1; i >= 0; --i){ if (str[i] == '.') break; @@ -895,9 +905,24 @@ file_extension_slowly(char *str){ return make_string(str+i, s-i); } +FCPP_LINK bool +remove_last_folder(String *str){ + bool result = 0; + int end = reverse_seek_slash(*str, 1); + if (end >= 0){ + result = 1; + str->size = end + 1; + } + return(result); +} + // NOTE(allen): experimental section, things below here are // not promoted to public API level yet. +#ifndef ArrayCount +#define ArrayCount(a) ((sizeof(a))/sizeof(a)) +#endif + struct Absolutes{ String a[8]; int count; diff --git a/4cpp_lexer.h b/4cpp_lexer.h index 14d509fe..69f974a0 100644 --- a/4cpp_lexer.h +++ b/4cpp_lexer.h @@ -58,7 +58,7 @@ NOTES ON USE: // - lex in chunks // -#include "4cpp_config.h" +#include "4coder_config.h" #ifndef FCPP_LEXER_INC #define FCPP_LEXER_INC diff --git a/4cpp_preprocessor.cpp b/4cpp_preprocessor.cpp index cbbb685e..b3e6adb8 100644 --- a/4cpp_preprocessor.cpp +++ b/4cpp_preprocessor.cpp @@ -1,2057 +1,862 @@ +/* + * Mr. 4th Dimention - Allen Webster + * + * 30.11.2015 + * + * CPP preprocessor + * + */ // TOP -// TODO(allen): -// error check the body of macros as they are first read in -// (as in, check the thing after # is a parameter, and that ## is not on one of the ends) +#define byte unsigned char -#define _Assert Assert -#define _TentativeAssert TentativeAssert - -enum Cpp_Def_Type{ - CPP_DEFTYPE_ERROR, - CPP_DEFTYPE_FILE, - CPP_DEFTYPE_MACRO, - CPP_DEFTYPE_COUNT -}; - -struct Table_Entry{ - String name; - Cpp_Def_Type type; - fcpp_u32 hash; - int index; -}; - -struct Table{ - Table_Entry *table; - int size, max_size; -}; - -internal fcpp_u32 -get_hash(String name, Cpp_Def_Type type){ - fcpp_u32 x = 5381; - int i = 0; - char c; - while (i < name.size){ - c = name.str[i++]; - x = ((x << 5) + x) + c; - } - x += (fcpp_u32)(type)*13; - return x; -} - -internal bool -table_insert(Table *table, Table_Entry info){ - Table_Entry entry; - int index; - - info.hash = get_hash(info.name, info.type); - index = info.hash % table->max_size; - while ((entry = table->table[index]).name.str && entry.index != -1){ - if (entry.hash == info.hash && entry.type == info.type && match(entry.name, info.name)){ - return 1; - } - index = (index + 1) % table->max_size; - } - table->table[index] = info; - ++table->size; - return 0; -} - -internal bool -table_find_entry(Table *table, String name, Cpp_Def_Type type, int *index_out){ - fcpp_u32 hash = get_hash(name, type); - int index = hash % table->max_size; - Table_Entry entry; - while ((entry = table->table[index]).name.str){ - if (entry.index != -1 && entry.hash == hash && entry.type == type && match(entry.name, name)){ - *index_out = index; - return 1; - } - index = (index + 1) % table->max_size; - } - return 0; -} - -internal bool -table_find(Table *table, String name, Cpp_Def_Type type, int *index_out){ - bool result; - int entry_index; - result = table_find_entry(table, name, type, &entry_index); - if (result){ - *index_out = table->table[entry_index].index; - } - return result; -} - -internal bool -table_drop(Table *table, String name, Cpp_Def_Type type){ - bool result; - int entry_index; - result = table_find_entry(table, name, type, &entry_index); - if (result){ - table->table[entry_index].index = -1; - } - return result; -} - -internal void -table_copy(Table *table_src, Table *table_dst){ - Table_Entry entry; - int i; - for (i = 0; i < table_src->max_size; ++i){ - entry = table_src->table[i]; - if (entry.name.str){ - table_insert(table_dst, entry); - } - } -} - -struct Cpp_File_Data{ - Cpp_File file; - Cpp_Token_Stack tokens; - String filename; -}; - -struct Cpp_Macro_Data{ - int file_index; - int token_index; - int param_count; - int first_param_index; - int body_start_index; - int body_end_index; -}; - -union Cpp_Def_Slot{ - Cpp_File_Data file; - Cpp_Macro_Data macro; -}; - -struct Cpp_Loose_Token{ - int file_index; - int token_index; - int blocked; -}; - -struct Cpp_Loose_Token_Stack{ - Cpp_Loose_Token *tokens; - int count, max; -}; - -struct Cpp_Parse_Context{ - int preserve_chunk_size; -}; - -struct Cpp_Parse_Definitions{ - Table table; - Cpp_Def_Slot *slots; - int count, max; - - int string_file_index; - int string_write_pos; - - Cpp_Loose_Token eof_token; - Cpp_Loose_Token va_args_token; -}; - -struct Cpp_Visit{ - int file_index; - int token_index; - int blocked; -}; - -struct Cpp_Expansion{ - int position; - int end_position; - int file_index; - int macro_index; - int stack_base; - int stack_pop_pos; - int out_rule; - int out_type; - int param_info_base; - int invoking_file_index; - int invoking_token_index; - - bool pop_and_drop; - bool may_have_pp; - bool is_file_level; -}; - -struct Cpp_Macro_Reading_Vars{ - int name_index; - int first_param_index; - int param_count; - int body_start_index; -}; - -struct Cpp_Macro_Invoking_Vars{ - int file_index; - int token_index; - int invoking_file_index; - int invoking_token_index; - int macro_index; - int param_count; - int paren_level; - int stack_base; - int param_info_base; - int variadic; -}; - -struct Cpp_Token_Range{ - int start, end; -}; - -struct Cpp_Preproc_State{ - Cpp_Expansion expansions[256]; - Cpp_Token_Range param_info[192]; - int expansion_level; - int param_info_used; - - Cpp_Loose_Token_Stack tokens; - - int state; - - Cpp_Macro_Reading_Vars mac_read; - Cpp_Macro_Invoking_Vars mac_inv; - - char *spare_string; - int spare_string_write_pos; - int spare_string_size; - - bool resizing_slots; - bool finished; -}; - -enum Memory_Request_Purpse{ - MEMPURP_NONE, - MEMPURP_SPARE_STRING, - MEMPURP_PRESERVE_FILE, - MEMPURP_TOKEN_STACK, - MEMPURP_DEFINITION_SLOTS -}; - -struct Cpp_Preproc_Result{ - int file_index; - int token_index; - int blocked; - - int invoking_file_index; - int invoking_token_index; - +struct Cpp_PP_Step{ int error_code; - int memory_request; - Memory_Request_Purpse memory_purpose; - bool emit; - bool from_macro; - bool file_request; + int finished; + int early_out; + + int mem_size; + int mem_type; + + int emit; + int file_index; + int token_index; }; -struct Cpp_Memory_Request{ - Cpp_Preproc_State *state; - Cpp_Parse_Definitions *definitions; - int size; - Memory_Request_Purpse purpose; +enum Cpp_PP_Expansion_Type{ + PPExp_Normal, + // never below this + PPExp_Count +}; +struct Cpp_PP_Expansion_Header{ + int prev_frame; + int type; +}; +struct Cpp_PP_Expansion_Normal{ + int file_offset; + int current_token; + int end_token; + int file_level; }; -struct Cpp_File_Request{ - String filename; +struct Cpp_PP_State{ + byte *base; + int top, frame, max; + + int substep; + + struct{ + union{ + int name_index; + int param_count; + int macro_offset; + } define; + } vars; + + Debug(int did_advance); }; internal int -cpp_defs_add(Cpp_Parse_Definitions *defs, String name, Cpp_Def_Type type){ +cpp__push_expansion_normal(Cpp_PP_State *state, int file, int start, int end, int file_level){ + Cpp_PP_Expansion_Header *header; + Cpp_PP_Expansion_Normal *expansion; + int added_size; + int prev_frame; int result; - _Assert(defs->count < defs->max); - result = defs->count++; - defs->slots[result] = {}; + + added_size = sizeof(Cpp_PP_Expansion_Header) + sizeof(Cpp_PP_Expansion_Normal); + + if (state->top + added_size <= state->max){ + result = 1; + + prev_frame = state->frame; + state->frame = state->top; + state->top += added_size; + + header = (Cpp_PP_Expansion_Header*)(state->base + state->frame); + expansion = (Cpp_PP_Expansion_Normal*)(header + 1); + + header->prev_frame = prev_frame; + header->type = PPExp_Normal; + expansion->file_offset = file; + expansion->current_token = start; + expansion->end_token = end; + expansion->file_level = file_level; + } + else{ + result = 0; + } + + return(result); +} + +internal int +cpp__pop_expansion(Cpp_PP_State *state){ + Cpp_PP_Expansion_Header *header; + int result; + + if (state->top >= sizeof(Cpp_PP_Expansion_Header)){ + Assert(state->top - state->frame >= sizeof(Cpp_PP_Expansion_Header)); + result = 1; + + header = (Cpp_PP_Expansion_Header*)(state->base + state->frame); + state->top = state->frame; + state->frame = header->prev_frame; + } + else{ + result = 0; + } + + return(result); +} + +enum Cpp_PP_Memory_Type{ + PPMem_None, + PPMem_Definition_Items, + PPMem_Definition_Table, + PPMem_Spare_File_String, + PPMem_Spare_File_Tokens, + // never below this + PPMem_Count +}; + +internal void +cpp__pp_memory_request(Cpp_PP_Step *step, int amount, int type){ + Assert(!step->early_out); + step->early_out = 1; + step->mem_size = amount; + step->mem_type = type; +} + +enum Cpp_PP_Table_Entry_Type{ + PPItem_Unset, + PPItem_File, + PPItem_Macro, + // never below this + PPItem_Count +}; +struct Cpp_PP_Table_Entry{ + int name_start, name_size; + int type; + unsigned int hash; + int item_offset; +}; +struct Cpp_PP_Table{ + Cpp_PP_Table_Entry *entries; + unsigned int count, max; +}; + +struct Cpp_PP_File{ + Cpp_File file; + Cpp_Token_Stack tokens; +}; +struct Cpp_PP_Macro{ + int self_start; + int name_start; + int name_size; + int param_count; + int variadic; + int body_start; + int body_end; +}; + +struct Cpp_PP_Definitions{ + byte *items; + int pos, restore_pos, max; + Cpp_PP_File *spare_file; + int spare_pos; + + Cpp_PP_Table table; +}; + +internal unsigned int +cpp__hash(char *name, int size, int type){ + unsigned int x; + int i; - if (name.str != 0){ - _Assert(defs->table.size * 7 < defs->table.max_size * 8); - Table_Entry entry; - entry.name = name; - entry.type = type; - entry.index = result; - table_insert(&defs->table, entry); + x = 5381; + x = ((x << 5) + x) ^ ('A' + type); + for (i = 0; i < size; ++i, ++name){ + x = ((x << 5) + x) ^ *name; } - return result; + return(x); } -internal Cpp_Memory_Request -cpp_get_memory_request(Cpp_Preproc_State *state, Cpp_Parse_Definitions *definitions, - Cpp_Preproc_Result result){ - Cpp_Memory_Request request = {}; - request.state = state; - request.definitions = definitions; - request.size = result.memory_request; - request.purpose = result.memory_purpose; - return request; +internal unsigned int +cpp__hash(Cpp_PP_Definitions *definitions, int name_start, int name_size, int type){ + unsigned int x; + char *s; + s = definitions->spare_file->file.data + name_start; + x = cpp__hash(s, name_size, type); + return(x); } -internal Cpp_File_Data* -cpp_get_parse_file(Cpp_Parse_Definitions *definitions, int file_index){ - return &definitions->slots[file_index].file; +internal int +cpp__table_can_add(Cpp_PP_Table *table){ + int result; + result = 0; + if (table->count*8 < table->max*7) result = 1; + return(result); } internal void -cpp_set_parse_file(Cpp_Parse_Definitions *definitions, int file_index, Cpp_File_Data file){ - definitions->slots[file_index].file = file; -} +cpp__table_add_direct(Cpp_PP_Table *table, Cpp_PP_Table_Entry entry){ + unsigned int i, j; + i = entry.hash % table->max; + j = i - 1; + if (i <= 1) j += table->max; + + for (; i != j; ++i){ + if (i == table->max) i = 0; + if (table->entries[i].type == PPItem_Unset){ + table->entries[i] = entry; + break; + } + } -internal Cpp_Macro_Data* -cpp_get_macro_data(Cpp_Parse_Definitions *definitions, int macro_index){ - return &definitions->slots[macro_index].macro; + Assert(i != j); } internal void -cpp_set_macro_data(Cpp_Parse_Definitions *definitions, int macro_index, Cpp_Macro_Data macro){ - definitions->slots[macro_index].macro = macro; +cpp__table_add(Cpp_PP_Definitions *definitions, Cpp_PP_Table *table, + int name_start, int name_size, int type, int offset){ + Cpp_PP_Table_Entry entry; + unsigned int hash; + + Assert(cpp__table_can_add(table)); + + hash = cpp__hash(definitions, name_start, name_size, type); + entry.name_start = name_start; + entry.name_size = name_size; + entry.type = type; + entry.hash = hash; + entry.item_offset = offset; + + cpp__table_add_direct(table, entry); +} + +internal int +cpp__str_match(char *a, char *b, int size){ + char *e; + int result; + result = 0; + for(e = a + size; a < e && *a == *b; ++a, ++b); + if (a == e) result = 1; + return(result); +} + +internal int +cpp__table_find_hash_pos(Cpp_PP_Definitions *definitions, Cpp_PP_Table *table, + char *name, int name_size, int typ e, unsigned int *hash_index){ + Cpp_PP_Table_Entry *entry; + int result; + unsigned int hash; + unsigned int i, j; + + result = 0; + hash = cpp__hash(name, name_size, type); + i = hash % table->max; + j = i - 1; + if (i <= 1) j += table->max; + + for (; i != j; ++i){ + if (i == table->max) i = 0; + entry = table->entries + i; + if (entry->type == PPItem_Unset) break; + if (entry->hash == hash && entry->type == type && entry->name_size == name_size && + cpp__str_match(name, definitions->spare_file->file.data + entry->name_start, name_size)){ + result = 1; + *hash_index = i; + break; + } + } + + return(result); +} + +internal int +cpp__table_find(Cpp_PP_Definitions *definitions, Cpp_PP_Table *table, + char *name, int name_size, int type, int *offset){ + int result; + unsigned int hash_index; + + result = 0; + if (cpp__table_find_hash_pos(definitions, table, name, name_size, type, &hash_index)){ + result = 1; + *offset = table->entries[hash_index].item_offset; + } + + return(result); +} + +internal void +cpp__table_cpy(Cpp_PP_Table *dest, Cpp_PP_Table *src){ + Cpp_PP_Table_Entry *entry; + unsigned int i; + + Assert(dest->max >= src->max); + for (i = 0, entry = src->entries; i < src->max; ++i, ++entry){ + if (entry->type != PPItem_Unset){ + cpp__table_add_direct(dest, *entry); + } + } +} + +internal void +cpp__def_begin_uncertain(Cpp_PP_Definitions *definitions){ + definitions->restore_pos = definitions->pos; +} +internal void +cpp__def_success_uncertain(Cpp_PP_Definitions *definitions){ + definitions->restore_pos = 0; +} +internal void +cpp__def_fail_uncertain(Cpp_PP_Definitions *definitions){ + if (definitions->restore_pos != 0){ + definitions->pos = definitions->restore_pos; + } +} + +internal int +cpp__def_can_save_strings(Cpp_PP_Definitions *definitions, int total_size){ + int result; + Cpp_PP_File *file; + file = definitions->spare_file; + + if (definitions->spare_pos + total_size <= file->file.size) result = 1; + else result = 0; + + return(result); +} + +internal int +cpp__def_can_save_item(Cpp_PP_Definitions *definitions, int size){ + int result; + + if (definitions->pos + size <= definitions->max) result = 1; + else result = 0; + + return(result); +} + +internal int +cpp__def_save_string(Cpp_PP_Step *step, Cpp_PP_Definitions *definitions, + char *str, int size){ + int result; + Cpp_PP_File *file; + file = definitions->spare_file; + + Assert(definitions->spare_pos + size <= file->file.size); + memcpy(file->file.data + definitions->spare_pos, str, size); + result = definitions->spare_pos; + definitions->spare_pos += size; + + return(result); +} + +internal int +cpp__mem_up(int x){ + int xx; + xx = x / 1024; + if (xx*1024 < x){ + xx += 1; + } + xx = xx << 10; + return(xx); +} + +internal int +cpp__def_begin_macro(Cpp_PP_Step *step, Cpp_PP_Definitions *definitions, + char *str, int size){ + int result, str_pos; + Cpp_PP_Macro *macro_item; + + result = 0; + if (cpp__def_can_save_strings(definitions, size)){ + if (cpp__def_can_save_item(definitions, sizeof(Cpp_PP_Macro))){ + str_pos = cpp__def_save_string(step, definitions, str, size); + + Assert(definitions->pos + sizeof(Cpp_PP_Macro) <= definitions->max); + result = definitions->pos; + definitions->pos += sizeof(Cpp_PP_Macro); + + macro_item = (Cpp_PP_Macro*)(definitions->items + result); + *macro_item = {}; + macro_item->self_start = result; + macro_item->name_start = str_pos; + macro_item->name_size = size; + } + else{ + cpp__pp_memory_request(step, cpp__mem_up(definitions->max + 1), PPMem_Definition_Items); + } + } + else{ + cpp__pp_memory_request(step, cpp__mem_up(definitions->spare_file->file.size + size), + PPMem_Spare_File_String); + } + + return(result); +} + +internal void +cpp__def_set_macro_params(Cpp_PP_Definitions *definitions, int macro_offset, int param_count){ + Cpp_PP_Macro *macro_item; + macro_item = (Cpp_PP_Macro*)(definitions->items + macro_offset); + macro_item->param_count = param_count; +} + +internal void +cpp__def_set_macro_variadic(Cpp_PP_Definitions *definitions, int macro_offset, int variadic){ + Cpp_PP_Macro *macro_item; + macro_item = (Cpp_PP_Macro*)(definitions->items + macro_offset); + macro_item->variadic = variadic; +} + +internal void +cpp__def_set_macro_body_start(Cpp_PP_Definitions *definitions, int macro_offset, int body_start){ + Cpp_PP_Macro *macro_item; + macro_item = (Cpp_PP_Macro*)(definitions->items + macro_offset); + macro_item->body_start = body_start; +} + +internal void +cpp__def_set_macro_body_end(Cpp_PP_Definitions *definitions, int macro_offset, int body_end){ + Cpp_PP_Macro *macro_item; + macro_item = (Cpp_PP_Macro*)(definitions->items + macro_offset); + macro_item->body_end = body_end; +} + +internal void +cpp__def_end_macro(Cpp_PP_Step *step, Cpp_PP_Definitions *definitions){ + if (cpp__table_can_add(&definitions->table)){ + Cpp_PP_Macro *macro_item; + macro_item = (Cpp_PP_Macro*)(definitions->items + definitions->restore_pos); + + cpp__table_add(definitions, &definitions->table, + macro_item->name_start, macro_item->name_size, + PPItem_Macro, macro_item->self_start); + } + else{ + cpp__pp_memory_request(step, + cpp__mem_up(definitions->table.max*sizeof(Cpp_PP_Table_Entry)+1), + PPMem_Definition_Table); + } +} + +internal Cpp_PP_File* +cpp_preproc_get_pp_file(Cpp_PP_Definitions *definitions, int file_offset){ + Cpp_PP_File *result; + result = (Cpp_PP_File*)(definitions->items+file_offset); + return(result); +} + +internal Cpp_File* +cpp_preproc_get_file(Cpp_PP_Definitions *definitions, int file_offset){ + Cpp_PP_File *pp_file; + Cpp_File *result; + pp_file = cpp_preproc_get_pp_file(definitions, file_offset); + result = &pp_file->file; + return(result); +} + +internal Cpp_Token* +cpp_preproc_get_token(Cpp_PP_Definitions *definitions, int file_offset, int token_index){ + Cpp_PP_File *pp_file; + Cpp_Token *result; + pp_file = cpp_preproc_get_pp_file(definitions, file_offset); + result = &pp_file->tokens.tokens[token_index]; + return(result); +} + +internal int +cpp__define_file(Cpp_PP_Definitions *definitions, Cpp_File file, Cpp_Token_Stack tokens){ + int result; + Cpp_PP_File *file_item; + + Assert(definitions->pos + sizeof(Cpp_PP_File) <= definitions->max); + result = definitions->pos; + definitions->pos += sizeof(Cpp_PP_File); + + file_item = (Cpp_PP_File*)(definitions->items + result); + file_item->file = file; + file_item->tokens = tokens; + + return(result); +} + +internal void +cpp_preproc_set_spare_space(Cpp_PP_Definitions *definitions, + int str_size, void *str_mem, + int token_size, void *token_mem){ + Cpp_PP_File pp_file; + pp_file.file.size = str_size; + pp_file.file.data = (char*)str_mem; + pp_file.tokens.max_count = token_size; + pp_file.tokens.count = 0; + pp_file.tokens.tokens = (Cpp_Token*)token_mem; + + int pos = cpp__define_file(definitions, pp_file.file, pp_file.tokens); + Cpp_PP_File *spare_file = cpp_preproc_get_pp_file(definitions, pos); + definitions->spare_file = spare_file; + definitions->spare_pos = 0; +} + +internal void +cpp_preproc_target(Cpp_PP_State *state, Cpp_PP_Definitions *definitions, + Cpp_File file, Cpp_Token_Stack tokens){ + int file_index; + + Assert(state->top == 0); + + file_index = cpp__define_file(definitions, file, tokens); + cpp__push_expansion_normal(state, file_index, 0, tokens.count, 1); } internal void* -cpp_provide_memory(Cpp_Memory_Request request, void *memory){ - void *result = 0; - switch (request.purpose){ - case MEMPURP_SPARE_STRING: - { - Cpp_Preproc_State *state = request.state; - result = state->spare_string; - memcpy(memory, result, state->spare_string_size); - state->spare_string_size = request.size; - state->spare_string = (char*)memory; - }break; +cpp_preproc_provide_memory(Cpp_PP_State *state, Cpp_PP_Definitions *definitions, + int type, int size, void *memory){ + Cpp_PP_Table new_table; + Cpp_PP_File *spare; + void *result; + result = 0; - case MEMPURP_PRESERVE_FILE: - { - persist String string_filename = make_lit_string("~ string space"); - - Cpp_Parse_Definitions *definitions = request.definitions; - int size = request.size >> 1; - Cpp_File_Data new_file = {}; - new_file.tokens.tokens = (Cpp_Token*)memory; - new_file.tokens.max_count = size / sizeof(Cpp_Token); - new_file.file.data = ((char*)memory) + size; - new_file.file.size = size; - new_file.filename = string_filename; - - int string_index = cpp_defs_add(definitions, {}, CPP_DEFTYPE_FILE); - definitions->string_write_pos = 0; - definitions->string_file_index = string_index; - cpp_set_parse_file(definitions, string_index, new_file); - }break; - case MEMPURP_TOKEN_STACK: - { - Cpp_Preproc_State *state = request.state; - result = state->tokens.tokens; - memcpy(memory, result, sizeof(Cpp_Loose_Token)*state->tokens.count); - state->tokens.max = request.size / sizeof(Cpp_Loose_Token); - state->tokens.tokens = (Cpp_Loose_Token*)memory; - }break; - - case MEMPURP_DEFINITION_SLOTS: - { - Cpp_Preproc_State *state = request.state; - Cpp_Parse_Definitions *definitions = request.definitions; - if (state->resizing_slots){ - result = definitions->slots; - memcpy(memory, result, sizeof(Cpp_Def_Slot)*(definitions->count)); - definitions->slots = (Cpp_Def_Slot*)memory; - definitions->max = request.size / sizeof(Cpp_Def_Slot); - } - else{ - result = definitions->table.table; - Table new_table; - new_table.table = (Table_Entry*)memory; - new_table.size = 0; - new_table.max_size = request.size / sizeof(Table_Entry); - memset(new_table.table, 0, request.size); - table_copy(&definitions->table, &new_table); - definitions->table = new_table; - } - }break; - - default: - { - _Assert(!"unrecognized memory request"); - }break; - } - return result; -} - -internal Cpp_File_Request -cpp_get_file_request(Cpp_Preproc_State *state, Cpp_Preproc_Result result){ - Cpp_File_Request request = {}; - return request; -} - -internal bool -cpp_has_more_files(Cpp_File_Request *request){ - return 0; -} - -internal void -cpp_get_next_file(Cpp_File_Request *request){ -} - -internal bool -cpp_try_reuse_file(Cpp_File_Request *request){ - return 0; -} - -internal void -cpp_provide_file(Cpp_File_Request *request, Cpp_File new_file, Cpp_Token_Stack new_tokens){ -} - -enum Preproc_Error_Code{ - PPERR_NO_ERROR, - PPERR_UNFINISHED_DEFINE, - PPERR_DEFINE_EXPECTED_IDENTIFIER, - PPERR_MACRO_NONIDENTIFIER_ARG, - PPERR_MACRO_INCOMPLETE_PARAMS, - PPERR_MACRO_EXPECTED_COMMA, - PPERR_MACRO_MORE_AFTER_ELLIPSIS, - PPERR_MACROINV_TOO_FEW_PARAMS, - PPERR_MACROINV_TOO_MANY_PARAMS, - PPERR_EXPANSION_OVERRUN, - PPERR_INCOMPLETE_MACROINV -}; - -internal String -cpp_get_error(int error_code){ - String error = {}; - switch (error_code){ - case PPERR_NO_ERROR: - error = make_lit_string("no error"); break; - - case PPERR_UNFINISHED_DEFINE: - error = make_lit_string("define directive is unfinished"); break; - - case PPERR_DEFINE_EXPECTED_IDENTIFIER: - error = make_lit_string("define expected identifier for name"); break; - - case PPERR_MACRO_NONIDENTIFIER_ARG: - error = make_lit_string("macro argument must be an identifier"); break; - - case PPERR_MACRO_INCOMPLETE_PARAMS: - error = make_lit_string("macro incomplete parameters"); break; - - case PPERR_MACRO_EXPECTED_COMMA: - error = make_lit_string("macro expected comma between parameters"); break; - - case PPERR_MACRO_MORE_AFTER_ELLIPSIS: - error = make_lit_string("should not have more after the ellipsis"); break; - - case PPERR_EXPANSION_OVERRUN: - error = make_lit_string("nested expansion of files and macros ran too deep"); break; - - case PPERR_MACROINV_TOO_FEW_PARAMS: - error = make_lit_string("not enough arguments to macro invokation"); break; - - case PPERR_MACROINV_TOO_MANY_PARAMS: - error = make_lit_string("too many arguments to macro invokation"); break; - - case PPERR_INCOMPLETE_MACROINV: - error = make_lit_string("unexpected end of file in macro expansion"); break; - } - return error; -} - -internal bool -cpp_recommend_termination(int error_code){ - bool result = 0; - switch (error_code){ - case PPERR_EXPANSION_OVERRUN: - result = 1; - } - return result; -} - -struct Spare_String_Checkpoint{ - int write_pos_start; - int memory_overrun; -}; - -internal Spare_String_Checkpoint -cpp__checkpoint_spare_string(Cpp_Preproc_State *state){ - Spare_String_Checkpoint result = {}; - result.write_pos_start = state->spare_string_write_pos; - return result; -} - -internal void -cpp__spare_write(Spare_String_Checkpoint *check, Cpp_Preproc_State *state, char c){ - if (state->spare_string_write_pos < state->spare_string_size){ - state->spare_string[state->spare_string_write_pos++] = c; - } - else{ - ++check->memory_overrun; - } -} - -internal void -cpp__spare_write(Spare_String_Checkpoint *check, Cpp_Preproc_State *state, String str){ - if (state->spare_string_write_pos + str.size <= state->spare_string_size){ - memcpy(state->spare_string + state->spare_string_write_pos, str.str, str.size); - state->spare_string_write_pos += str.size; - } - else{ - check->memory_overrun += str.size; - } -} - -internal void -cpp__restore_spare_string(Cpp_Preproc_State *state, Spare_String_Checkpoint check){ - state->spare_string_write_pos = check.write_pos_start; -} - -struct Preserve_Checkpoint{ - int start_write_pos; - int start_token_count; - bool out_of_memory; -}; - -internal Preserve_Checkpoint -cpp__checkpoint_preserve_write(Cpp_Parse_Definitions *definitions){ - Cpp_File_Data *file = cpp_get_parse_file(definitions, definitions->string_file_index); - Preserve_Checkpoint check; - check.start_write_pos = definitions->string_write_pos; - check.start_token_count = file->tokens.count; - check.out_of_memory = 0; - return check; -} - -internal void -cpp__restore_preserve_write(Cpp_Parse_Definitions *definitions, Preserve_Checkpoint check){ - Cpp_File_Data *file = cpp_get_parse_file(definitions, definitions->string_file_index); - definitions->string_write_pos = check.start_write_pos; - file->tokens.count = check.start_token_count; -} - -internal void -cpp__preserve_string(Cpp_Parse_Definitions *definitions, String string){ - Cpp_File_Data *string_file = cpp_get_parse_file(definitions, definitions->string_file_index); - _Assert(string_file->file.size - definitions->string_write_pos >= string.size); - copy_fast_unsafe(string_file->file.data + definitions->string_write_pos, string); - definitions->string_write_pos += string.size; -} - -internal Cpp_Loose_Token -cpp__preserve_token(Cpp_Parse_Definitions *definitions, Cpp_Token token){ - Cpp_File_Data *string_file = cpp_get_parse_file(definitions, definitions->string_file_index); - _Assert(string_file->tokens.count < string_file->tokens.max_count); - Cpp_Loose_Token loose; - loose.file_index = definitions->string_file_index; - loose.token_index = string_file->tokens.count; - loose.blocked = 0; - string_file->tokens.tokens[string_file->tokens.count++] = token; - return loose; -} - -internal void -cpp__preserve_string(Preserve_Checkpoint *check, Cpp_Parse_Definitions *definitions, String string){ - if (!check->out_of_memory){ - Cpp_File_Data *string_file = cpp_get_parse_file(definitions, definitions->string_file_index); - if (string_file->file.size - definitions->string_write_pos >= string.size){ - copy_fast_unsafe(string_file->file.data + definitions->string_write_pos, string); - definitions->string_write_pos += string.size; - } - else{ - check->out_of_memory = 1; - } - } -} - -internal Cpp_Loose_Token -cpp__preserve_token(Preserve_Checkpoint *check, Cpp_Parse_Definitions *definitions, Cpp_Token token){ - Cpp_Loose_Token loose = {}; - if (!check->out_of_memory){ - Cpp_File_Data *string_file = cpp_get_parse_file(definitions, definitions->string_file_index); - if (string_file->tokens.count < string_file->tokens.max_count){ - loose.file_index = definitions->string_file_index; - loose.token_index = string_file->tokens.count; - loose.blocked = 0; - string_file->tokens.tokens[string_file->tokens.count++] = token; - } - else{ - check->out_of_memory = 1; - } - } - return loose; -} - -internal bool -cpp__can_push_loose_token(Cpp_Preproc_State *state, int count){ - return (state->tokens.count + count <= state->tokens.max); -} - -internal void -cpp__push_loose_token(Cpp_Preproc_State *state, int file_index, int token_index, int blocked){ - _Assert(state->tokens.count < state->tokens.max); - state->tokens.tokens[state->tokens.count++] = {file_index, token_index, blocked}; -} - -struct Token_Stack_Checkpoint{ - int start_count; - int memory_overrun; -}; - -internal Token_Stack_Checkpoint -cpp__checkpoint_token_stack(Cpp_Preproc_State *state){ - Token_Stack_Checkpoint result = {}; - result.start_count = state->tokens.count; - return result; -} - -internal void -cpp__restore_token_stack(Cpp_Preproc_State *state, Token_Stack_Checkpoint checkpoint){ - state->tokens.count = checkpoint.start_count; -} - -internal void -cpp__push_loose_token(Token_Stack_Checkpoint *checkpoint, Cpp_Preproc_State *state, - int file_index, int token_index, int blocked){ - if (state->tokens.count < state->tokens.max){ - cpp__push_loose_token(state, file_index, token_index, blocked); - } - else{ - ++checkpoint->memory_overrun; - } -} - -internal void -cpp__finish_macro(Cpp_Parse_Definitions *definitions, String name, - int file_index, int token_index, - int param_count, int first_param_index, - int body_start_index, int body_end_index){ - Cpp_Macro_Data macro; - macro.file_index = file_index; - macro.token_index = token_index; - macro.param_count = param_count; - macro.first_param_index = first_param_index; - macro.body_start_index = body_start_index; - macro.body_end_index = body_end_index; - - int macro_index = cpp_defs_add(definitions, name, CPP_DEFTYPE_MACRO); - cpp_set_macro_data(definitions, macro_index, macro); -} - -enum Cpp_Expansion_Type{ - EXPAN_FILE, - EXPAN_MACRO, - EXPAN_ARG, - EXPAN_PMACRO_BODY -}; - -enum Cpp_Expansion_Out_Type{ - EXPAN_NORMAL, - EXPAN_BIG_PROCESS_ARGS, - EXPAN_BIG_PROCESS_BODY, - EXPAN_BIG_DIRECT_OUT, - EXPAN_EOF_FLUSH, - EXPAN_STRFY -}; - -internal Cpp_Expansion* -cpp__push_expansion_raw(Cpp_Preproc_State *state, Cpp_Expansion *expansion){ - if (state->expansion_level == ArrayCount(state->expansions)){ - return 0; - } - - ++state->expansion_level; - Cpp_Expansion *result = state->expansions + state->expansion_level; - *result = *expansion; - return result; -} - -internal void -cpp__set_expansion(Cpp_Preproc_State *state, Cpp_Expansion *expansion, Cpp_Expansion_Type type, - int file_index, int start, int end, int out_rule, - int invoking_file_index, int invoking_token_index){ - expansion->position = start; - expansion->end_position = end; - expansion->file_index = file_index; - expansion->macro_index = 0; - expansion->out_rule = out_rule; - expansion->out_type = EXPAN_NORMAL; - expansion->invoking_file_index = invoking_file_index; - expansion->invoking_token_index = invoking_token_index; - if (state->expansion_level >= 1){ - expansion->stack_base = state->expansions[state->expansion_level-1].stack_base; - } - else{ - expansion->stack_base = 0; - } switch (type){ - case EXPAN_FILE: - expansion->may_have_pp = 1; - expansion->is_file_level = 1; - expansion->pop_and_drop = 0; + case PPMem_None: Assert(0); break; + + case PPMem_Definition_Items: + Assert(size > definitions->max); + memcpy(memory, definitions->items, definitions->pos); + result = definitions->items; + definitions->items = (byte*)memory; break; - case EXPAN_MACRO: - expansion->may_have_pp = 0; - expansion->is_file_level = 0; - expansion->pop_and_drop = 0; + case PPMem_Definition_Table: + Assert(size > definitions->table.max * sizeof(*new_table.entries)); + new_table.entries = (Cpp_PP_Table_Entry*)memory; + new_table.max = size/sizeof(*new_table.entries); + new_table.count = 0; + cpp__table_cpy(&new_table, &definitions->table); + result = definitions->table.entries; + definitions->table = new_table; break; - case EXPAN_ARG: - expansion->may_have_pp = 0; - expansion->is_file_level = 1; - expansion->pop_and_drop = 0; + case PPMem_Spare_File_String: + spare = definitions->spare_file; + Assert(size > spare->file.size); + memcpy(memory, spare->file.data, definitions->spare_pos); + result = spare->file.data; + spare->file.data = (char*)memory; break; - case EXPAN_PMACRO_BODY: - expansion->may_have_pp = 0; - expansion->is_file_level = 0; - expansion->pop_and_drop = 1; - expansion->stack_pop_pos = state->tokens.count; + case PPMem_Spare_File_Tokens: + spare = definitions->spare_file; + Assert(size > spare->tokens.count*sizeof(Cpp_Token)); + memcpy(memory, spare->tokens.tokens, spare->tokens.count*sizeof(Cpp_Token)); + result = spare->tokens.tokens; + spare->tokens.tokens = (Cpp_Token*)memory; break; + + default: Assert(0); break; } + + return(result); } -internal Cpp_Expansion* -cpp__push_expansion(Cpp_Preproc_State *state, Cpp_Expansion_Type type, - int file_index, int start, int end, int out_rule, - int invoking_file_index, int invoking_token_index){ - _Assert(start < end); - if (state->expansion_level == ArrayCount(state->expansions)){ - return 0; - } +enum Cpp_PP_Error{ + PPErr_None, + PPErr_Define_Identifier_Missing, + PPErr_Parameter_Identifier_Missing, + PPErr_Preprocessor_Directive_In_Expansion, + PPErr_Expected_Comma_Or_Parenthese, + PPErr_Unfinished_Parameters, + // never below this + PPErr_Count +}; + +internal char* +cpp_preproc_error_str(int error_code){ + char *result = 0; - ++state->expansion_level; - Cpp_Expansion *result = state->expansions + state->expansion_level; - cpp__set_expansion(state, result, type, file_index, start, end, out_rule, - invoking_file_index, invoking_token_index); - return result; -} + switch (error_code){ + case PPErr_None: + result = "no error"; break; -internal void -cpp__set_strfy_expansion(Cpp_Preproc_State *state, Cpp_Expansion *expansion, - int start, int end, int out_rule, - int invoking_file_index, int invoking_token_index){ - expansion->position = start; - expansion->end_position = end; - expansion->file_index = -1; - expansion->macro_index = 0; - expansion->out_rule = out_rule; - expansion->out_type = EXPAN_STRFY; - expansion->invoking_file_index = invoking_file_index; - expansion->invoking_token_index = invoking_token_index; - - expansion->may_have_pp = 0; - expansion->is_file_level = 0; - expansion->pop_and_drop = 0; - - if (state->expansion_level >= 1){ - expansion->stack_base = state->expansions[state->expansion_level-1].stack_base; - } - else{ - expansion->stack_base = 0; - } -} + case PPErr_Define_Identifier_Missing: + result = "define identifier missing"; break; -internal Cpp_Expansion* -cpp__push_strfy_expansion(Cpp_Preproc_State *state, int start, int end, int out_rule, - int invoking_file_index, int invoking_token_index){ - _Assert(start < end); - if (state->expansion_level == ArrayCount(state->expansions)){ - return 0; - } - - ++state->expansion_level; - Cpp_Expansion *result = state->expansions + state->expansion_level; - cpp__set_strfy_expansion(state, result, start, end, out_rule, - invoking_file_index, invoking_token_index); - return result; -} + case PPErr_Parameter_Identifier_Missing: + result = "parameter identifier missing"; break; + + case PPErr_Preprocessor_Directive_In_Expansion: + result = "preprocessor directive in expansion"; break; + + case PPErr_Expected_Comma_Or_Parenthese: + result = "expected comma or parenthese"; break; -internal void -cpp__set_big_expansion(Cpp_Expansion *expansion, int macro_index, int stack_base, - int param_info_base, int out_rule, - int invoking_file_index, int invoking_token_index){ - expansion->stack_base = stack_base; - expansion->file_index = macro_index; - expansion->macro_index = 0; - expansion->out_rule = out_rule; - expansion->out_type = EXPAN_BIG_PROCESS_ARGS; - expansion->param_info_base = param_info_base; - expansion->invoking_file_index = invoking_file_index; - expansion->invoking_token_index = invoking_token_index; - expansion->pop_and_drop = 0; - expansion->may_have_pp = 0; - expansion->is_file_level = 0; -} - -internal Cpp_Expansion* -cpp__push_big_expansion(Cpp_Preproc_State *state, int macro_index, int stack_base, int param_info_base, - int out_rule, int invoking_file_index, int invoking_token_index){ - if (state->expansion_level == ArrayCount(state->expansions)){ - return 0; + case PPErr_Unfinished_Parameters: + result = "unfinished parameter list"; break; + + default: + result = "unknown error code"; } - ++state->expansion_level; - Cpp_Expansion *result = state->expansions + state->expansion_level; - cpp__set_big_expansion(result, macro_index, stack_base, param_info_base, out_rule, - invoking_file_index, invoking_token_index); - return result; + + return(result); } internal int -cpp__alloc_param_table(Cpp_Preproc_State *state, int param_count){ - _Assert(state->param_info_used + param_count * 3 <= ArrayCount(state->param_info)); - int result = state->param_info_used; - state->param_info_used += param_count * 3; - memset(state->param_info + result, 0, sizeof(Cpp_Token_Range)*param_count*3); - return result; -} - -internal void -cpp__free_param_table(Cpp_Preproc_State *state, int param_count){ - _Assert(state->param_info_used >= param_count * 3); - state->param_info_used -= param_count * 3; -} - -enum Param_Info_Position{ - RAW_START, - RAW_END, - STRFY_START, - STRFY_END, - EXPANDED_START, - EXPANDED_END -}; - -enum Param_Info_Range_Position{ - RAW, - STRFY, - EXPANDED -}; - -internal Cpp_Token_Range -cpp__param_info_get(Cpp_Preproc_State *state, int base, int arg_index, Param_Info_Range_Position pos){ - Cpp_Token_Range *range = state->param_info + (base + arg_index*3); - range += pos; - return *range; -} - -internal void -cpp__param_info_set(Cpp_Preproc_State *state, int base, int arg_index, Param_Info_Position pos, int val){ - Cpp_Token_Range *range = state->param_info + (base + arg_index*3); - range += (pos >> 1); - *( ((int*)range) + (pos & 1) ) = val; -} - -internal void -cpp_set_target(Cpp_Preproc_State *state, Cpp_Parse_Definitions *definitions, - Cpp_File file, Cpp_Token_Stack tokens, String filename){ - int target_index; - target_index = cpp_defs_add(definitions, filename, CPP_DEFTYPE_FILE); - cpp_set_parse_file(definitions, target_index, {file, tokens, filename}); - state->expansion_level = -1; - cpp__push_expansion(state, EXPAN_FILE, target_index, 0, tokens.count, 0, -1, -1); -} - -internal void -cpp__preproc_pop_expansion(Cpp_Preproc_State *state, Cpp_Expansion *expansion){ - if (expansion->is_file_level){ - _Assert(expansion->out_type != EXPAN_EOF_FLUSH); - expansion->out_type = EXPAN_EOF_FLUSH; - } +cpp_preproc_recommend_termination(int error_code){ + int result = 0; + return(result); +} + +struct Cpp__PP_Visit{ + int file_offset; + int token_index; +}; + +internal void +cpp__pp_next_token(Cpp_PP_State *state, Cpp_PP_Expansion_Normal *expansion){ + ++expansion->current_token; + Debug(state->did_advance = 1); +} + +enum Cpp_PP_State_Step{ + PPState_None, + PPState_Define, + PPState_Name, + PPState_Define_Body, + PPState_Define_Parameter, + PPState_Define_Parameter_Comma, + PPState_Error_Recovery, + // never below this + PPState_Count +}; + +internal int +cpp__pp_require_identifier(Cpp_PP_State *state, Cpp_Token token){ + int result; + result = PPErr_None; + if ((token.flags & CPP_TFLAG_PP_BODY) == 0){ + result = PPErr_Define_Identifier_Missing; + state->substep = PPState_None; + Debug(state->did_advance = 1); + } + else if (token.type != CPP_TOKEN_IDENTIFIER && + (token.flags & CPP_TFLAG_IS_KEYWORD) == 0){ + result = PPErr_Define_Identifier_Missing; + state->substep = PPState_Error_Recovery; + Debug(state->did_advance = 1); + } + return(result); +} + +internal Cpp_PP_Step +cpp__pp_step_normal(Cpp_PP_State *state, Cpp_PP_Definitions *definitions, + Cpp_PP_Expansion_Normal *expansion){ + Cpp__PP_Visit visit; + Cpp_PP_Step result; + Cpp_Token token; + Cpp_PP_File pp_file; + int void_step; + + visit = {}; + result = {}; + void_step = 0; + + if (expansion->current_token < expansion->end_token){ + visit.file_offset = expansion->file_offset; + visit.token_index = expansion->current_token; + } else{ - if (expansion->pop_and_drop){ - Cpp_Loose_Token *tokens = state->tokens.tokens; - int count = state->tokens.count - expansion->stack_pop_pos; - memmove(tokens + expansion->stack_base, tokens + expansion->stack_pop_pos, - sizeof(Cpp_Loose_Token)*count); - state->tokens.count = expansion->stack_base + count; - state->mac_inv.stack_base -= (expansion->stack_pop_pos - expansion->stack_base); - } - - if (state->expansion_level == 0){ - state->finished = 1; - } - else{ - --state->expansion_level; - } + void_step = 1; + cpp__pop_expansion(state); } -} + + if (!void_step){ + pp_file = *cpp_preproc_get_pp_file(definitions, visit.file_offset); + Assert(visit.token_index >= 0 && visit.token_index < pp_file.tokens.count); + token = pp_file.tokens.tokens[visit.token_index]; -enum Preproc_State{ - PPS_DEFAULT, - PPS_MACRO_NAME, - PPS_MACRO_PARAM_OR_CLOSE, - PPS_MACRO_BODY, - PPS_MACRO_COMMA_OR_CLOSE, - PPS_MACRO_PARAM, - PPS_MACRO_CLOSE, - PPS_MACRO_BODY_OR_PARAM_OPEN, - PPS_MACRO_ERROR, - PPS_MACROINV_OPEN, - PPS_MACROINV_PARAMS -}; -internal Cpp_Preproc_Result -cpp__preproc_normal_step_nonalloc(Cpp_Preproc_State *state, Cpp_Parse_Definitions *definitions, - Cpp_Parse_Context *context){ - Cpp_Preproc_Result result = {}; - Cpp_Expansion to_push_later = {}; - int do_push_later = 0; - Cpp_Expansion *expansion = state->expansions + state->expansion_level; - - if (expansion->position == expansion->end_position && expansion->out_type == EXPAN_NORMAL){ - cpp__preproc_pop_expansion(state, expansion); - result = {}; - return result; - } - - if (!cpp__can_push_loose_token(state, 1)){ - result.memory_request = sizeof(Cpp_Loose_Token)*((state->tokens.count*2) + 1); - result.memory_purpose = MEMPURP_TOKEN_STACK; - return result; - } - - Cpp_Visit visit = {}; - Cpp_File_Data visit_file; - Cpp_Token visit_token; - - if (expansion->out_type == EXPAN_NORMAL){ - if (expansion->file_index >= 0){ - visit.file_index = expansion->file_index; - visit.token_index = expansion->position; - visit.blocked = 0; + + Debug(state->did_advance = 0); + if (token.type == CPP_TOKEN_COMMENT || token.type == CPP_TOKEN_JUNK){ + cpp__pp_next_token(state, expansion); } else{ - Cpp_Loose_Token loose_token = state->tokens.tokens[expansion->position]; - visit.file_index = loose_token.file_index; - visit.token_index = loose_token.token_index; - visit.blocked = loose_token.blocked; - } - } - else if (expansion->out_type == EXPAN_EOF_FLUSH){ - visit.file_index = definitions->eof_token.file_index; - visit.token_index = definitions->eof_token.token_index; - visit.blocked = 0; - } - - visit_file = *cpp_get_parse_file(definitions, visit.file_index); - visit_token = visit_file.tokens.tokens[visit.token_index]; - - result.file_index = visit.file_index; - result.token_index = visit.token_index; - result.blocked = visit.blocked; - result.invoking_file_index = expansion->invoking_file_index; - result.invoking_token_index = expansion->invoking_token_index; - result.from_macro = !expansion->is_file_level; - - bool step_forward = 1; - switch (state->state){ - case PPS_MACRO_NAME: - { - if (visit_token.flags & CPP_TFLAG_PP_BODY){ - switch (visit_token.type){ - case CPP_TOKEN_COMMENT: - case CPP_TOKEN_JUNK:break; - - case CPP_TOKEN_IDENTIFIER: + switch (state->substep){ + case PPState_None: { - state->mac_read.name_index = visit.token_index; - state->state = PPS_MACRO_BODY_OR_PARAM_OPEN; - }break; - - default: - { - result.error_code = PPERR_DEFINE_EXPECTED_IDENTIFIER; - state->state = PPS_MACRO_ERROR; - }break; - } - } - else{ - result.error_code = PPERR_UNFINISHED_DEFINE; - state->state = PPS_DEFAULT; - step_forward = 0; - } - }break; - - case PPS_MACRO_BODY_OR_PARAM_OPEN: - { - if (visit_token.flags & CPP_TFLAG_PP_BODY){ - switch (visit_token.type){ - case CPP_TOKEN_COMMENT: - case CPP_TOKEN_JUNK:break; - - case CPP_TOKEN_PARENTHESE_OPEN: - { - state->state = PPS_MACRO_PARAM_OR_CLOSE; - }break; - - default: - { - state->mac_read.param_count = -1; - state->mac_read.body_start_index = visit.token_index; - state->state = PPS_MACRO_BODY; - }break; - } - } - else{ - Cpp_Token token = visit_file.tokens.tokens[state->mac_read.name_index]; - String name = make_string(visit_file.file.data + token.start, token.size); - cpp__finish_macro(definitions, name, visit.file_index, state->mac_read.name_index, -1, 0, 0, 0); - state->state = PPS_DEFAULT; - step_forward = 0; - } - }break; - - case PPS_MACRO_BODY: - { - if (!(visit_token.flags & CPP_TFLAG_PP_BODY)){ - Cpp_Token token = visit_file.tokens.tokens[state->mac_read.name_index]; - String name = make_string(visit_file.file.data + token.start, token.size); - cpp__finish_macro(definitions, name, - visit.file_index, state->mac_read.name_index, - state->mac_read.param_count, state->mac_read.first_param_index, - state->mac_read.body_start_index, visit.token_index); - state->state = PPS_DEFAULT; - step_forward = 0; - } - }break; - - case PPS_MACRO_PARAM_OR_CLOSE: - { - if (visit_token.flags & CPP_TFLAG_PP_BODY){ - switch (visit_token.type){ - case CPP_TOKEN_COMMENT: - case CPP_TOKEN_JUNK:break; - - case CPP_TOKEN_PARENTHESE_CLOSE: - { - state->mac_read.body_start_index = visit.token_index + 1; - state->state = PPS_MACRO_BODY; - }break; - - case CPP_TOKEN_IDENTIFIER: - { - state->mac_read.first_param_index = visit.token_index; - ++state->mac_read.param_count; - state->state = PPS_MACRO_COMMA_OR_CLOSE; - }break; - - default: - { - result.error_code = PPERR_MACRO_NONIDENTIFIER_ARG; - state->state = PPS_MACRO_ERROR; - }break; - } - } - else{ - result.error_code = PPERR_MACRO_INCOMPLETE_PARAMS; - state->state = PPS_DEFAULT; - step_forward = 0; - } - }break; - - case PPS_MACRO_COMMA_OR_CLOSE: - { - if (visit_token.flags & CPP_TFLAG_PP_BODY){ - switch (visit_token.type){ - case CPP_TOKEN_COMMENT: - case CPP_TOKEN_JUNK:break; - - case CPP_TOKEN_PARENTHESE_CLOSE: - { - state->mac_read.body_start_index = visit.token_index + 1; - state->state = PPS_MACRO_BODY; - }break; - - case CPP_TOKEN_COMMA: - { - state->state = PPS_MACRO_PARAM; - }break; - - default: - { - result.error_code = PPERR_MACRO_EXPECTED_COMMA; - state->state = PPS_MACRO_ERROR; - }break; - } - } - else{ - result.error_code = PPERR_MACRO_INCOMPLETE_PARAMS; - state->state = PPS_DEFAULT; - step_forward = 0; - } - }break; - - case PPS_MACRO_PARAM: - { - if (visit_token.flags & CPP_TFLAG_PP_BODY){ - switch (visit_token.type){ - case CPP_TOKEN_COMMENT: - case CPP_TOKEN_JUNK:break; - - case CPP_TOKEN_IDENTIFIER: - { - ++state->mac_read.param_count; - state->state = PPS_MACRO_COMMA_OR_CLOSE; - }break; - - case CPP_TOKEN_ELLIPSIS: - { - ++state->mac_read.param_count; - state->state = PPS_MACRO_CLOSE; - }break; - - default: - { - result.error_code = PPERR_MACRO_NONIDENTIFIER_ARG; - state->state = PPS_MACRO_ERROR; - }break; - } - } - else{ - result.error_code = PPERR_MACRO_INCOMPLETE_PARAMS; - state->state = PPS_DEFAULT; - step_forward = 0; - } - }break; - - case PPS_MACRO_CLOSE: - { - if (visit_token.flags & CPP_TFLAG_PP_BODY){ - switch (visit_token.type){ - case CPP_TOKEN_COMMENT: - case CPP_TOKEN_JUNK:break; - - case CPP_TOKEN_PARENTHESE_CLOSE: - { - state->mac_read.body_start_index = visit.token_index + 1; - state->state = PPS_MACRO_BODY; - }break; - - default: - { - result.error_code = PPERR_MACRO_MORE_AFTER_ELLIPSIS; - state->state = PPS_MACRO_ERROR; - }break; - } - } - else{ - result.error_code = PPERR_MACRO_INCOMPLETE_PARAMS; - state->state = PPS_DEFAULT; - step_forward = 0; - } - }break; - - case PPS_MACRO_ERROR: - { - if (!(visit_token.flags & CPP_TFLAG_PP_BODY)){ - state->state = PPS_DEFAULT; - step_forward = 0; - } - }break; - - case PPS_MACROINV_OPEN: - { - switch (visit_token.type){ - case CPP_TOKEN_COMMENT: - case CPP_TOKEN_JUNK:break; - - case CPP_TOKEN_PARENTHESE_OPEN: - { - Cpp_Macro_Data *macro = cpp_get_macro_data(definitions, state->mac_inv.macro_index); - state->mac_inv.param_info_base = cpp__alloc_param_table(state, macro->param_count); - state->state = PPS_MACROINV_PARAMS; - }break; - - default: - { - state->tokens.count = state->mac_inv.stack_base; - - result.file_index = state->mac_inv.file_index; - result.token_index = state->mac_inv.token_index; - result.blocked = 0; - result.invoking_file_index = state->mac_inv.invoking_file_index; - result.invoking_token_index = state->mac_inv.invoking_token_index; - result.from_macro = (result.invoking_file_index != -1); - result.emit = 1; - - step_forward = 0; - - state->state = PPS_DEFAULT; - }break; - } - }break; - - case PPS_MACROINV_PARAMS: - { - enum Macroinv_Params_Action{ - MIA_NONE, - MIA_EXTEND_PARAM, - MIA_NEXT_PARAM, - MIA_FINISH, - MIA_CLEANUP - }; - - Macroinv_Params_Action action = MIA_NONE; - Cpp_Macro_Data macro = *cpp_get_macro_data(definitions, state->mac_inv.macro_index); - switch (visit_token.type){ - case CPP_TOKEN_COMMENT: - case CPP_TOKEN_JUNK:break; - - case CPP_TOKEN_PARENTHESE_OPEN: - { - action = MIA_EXTEND_PARAM; - ++state->mac_inv.paren_level; - }break; - - case CPP_TOKEN_PARENTHESE_CLOSE: - { - if (state->mac_inv.paren_level == 0){ - action = MIA_FINISH; - } - else{ - --state->mac_inv.paren_level; - action = MIA_EXTEND_PARAM; - } - }break; - - case CPP_TOKEN_COMMA: - { - if (state->mac_inv.paren_level != 0 || - (state->mac_inv.variadic && - (state->mac_inv.param_count == macro.param_count || - macro.param_count == 1))){ - action = MIA_EXTEND_PARAM; - } - else{ - action = MIA_NEXT_PARAM; - } - }break; - - case CPP_TOKEN_EOF: - { - action = MIA_CLEANUP; - result.error_code = PPERR_INCOMPLETE_MACROINV; - }break; - - default: - { - action = MIA_EXTEND_PARAM; - }break; - } - - switch (action){ - case MIA_EXTEND_PARAM: - { - if (state->mac_inv.param_count == 0){ - state->mac_inv.param_count = 1; - cpp__param_info_set(state, state->mac_inv.param_info_base, - 0, RAW_START, state->tokens.count); - } - // NOTE(allen): this function gaurantees at the head end that there is - // room for at least one token - cpp__push_loose_token(state, visit.file_index, visit.token_index, 0); - }break; - - case MIA_NEXT_PARAM: - { - if (state->mac_inv.param_count == 0){ - state->mac_inv.param_count = 1; - cpp__param_info_set(state, state->mac_inv.param_info_base, - 0, RAW_START, state->tokens.count); - } - - if (state->mac_inv.param_count <= macro.param_count){ - cpp__param_info_set(state, state->mac_inv.param_info_base, - state->mac_inv.param_count - 1, RAW_END, state->tokens.count); - ++state->mac_inv.param_count; - cpp__param_info_set(state, state->mac_inv.param_info_base, - state->mac_inv.param_count - 1, RAW_START, state->tokens.count); - } - else{ - ++state->mac_inv.param_count; - } - }break; - - case MIA_FINISH: - { - if (state->mac_inv.param_count != 0 && state->mac_inv.param_count <= macro.param_count){ - cpp__param_info_set(state, state->mac_inv.param_info_base, - state->mac_inv.param_count - 1, RAW_END, state->tokens.count); - } - if (state->mac_inv.param_count != macro.param_count){ - if (state->mac_inv.param_count < macro.param_count){ - result.error_code = PPERR_MACROINV_TOO_FEW_PARAMS; + if (expansion->file_level == 0 && (token.flags & CPP_TFLAG_PP_DIRECTIVE)){ + result.error_code = PPErr_Preprocessor_Directive_In_Expansion; + cpp__pp_next_token(state, expansion); } else{ - result.error_code = PPERR_MACROINV_TOO_MANY_PARAMS; - } - } - state->state = PPS_DEFAULT; + switch (token.type){ + case CPP_PP_DEFINE: + { + state->substep = PPState_Define; + state->vars = {}; + cpp__pp_next_token(state, expansion); + }break; - do_push_later = 2; - cpp__set_big_expansion(&to_push_later, state->mac_inv.macro_index, - state->mac_inv.stack_base, state->mac_inv.param_info_base, - expansion->out_rule, visit.file_index, visit.token_index); - }break; - - case MIA_CLEANUP: - { - state->tokens.count = state->mac_inv.stack_base; - cpp__free_param_table(state, state->mac_inv.param_count); - }break; - } - }break; - - case PPS_DEFAULT: - { - switch (visit_token.type){ - case CPP_TOKEN_COMMENT: - case CPP_TOKEN_JUNK: - case CPP_TOKEN_EOF:break; + default: + { + result.emit = 1; + result.file_index = visit.file_offset; + result.token_index = visit.token_index; + cpp__pp_next_token(state, expansion); + }break; - case CPP_PP_DEFINE: - { - state->mac_read = {}; - state->state = PPS_MACRO_NAME; - }break; - - case CPP_TOKEN_IDENTIFIER: - { - String name = make_string(visit_file.file.data + visit_token.start, visit_token.size); - int macro_index; - if (table_find(&definitions->table, name, CPP_DEFTYPE_MACRO, ¯o_index)){ - bool blocked = (visit.blocked != 0); - if (!blocked){ - for (int i = state->expansion_level; i >= 0; --i){ - if (macro_index == state->expansions[i].macro_index){ - blocked = 1; - break; - } } } - - if (!blocked){ - Cpp_Macro_Data *macro = cpp_get_macro_data(definitions, macro_index); - if (macro->param_count == -1){ - if (macro->body_start_index < macro->body_end_index){ - do_push_later = 1; - cpp__set_expansion(state, &to_push_later, EXPAN_MACRO, macro->file_index, - macro->body_start_index, macro->body_end_index, - expansion->out_rule, visit.file_index, visit.token_index); - to_push_later.macro_index = macro_index; - } + }break; + + case PPState_Define: + { + result.error_code = cpp__pp_require_identifier(state, token); + if (result.error_code == PPErr_None){ + + cpp__def_begin_uncertain(definitions); + state->vars.define.macro_offset = + cpp__def_begin_macro(&result, definitions, + pp_file.file.data + token.start, + token.size); + if (result.early_out) goto cpp__pp_step_early_out; + + state->substep = PPState_Name; + state->vars.define.name_index = visit.token_index; + cpp__pp_next_token(state, expansion); + } + }break; + + case PPState_Name: + { + if ((token.flags & CPP_TFLAG_PP_BODY) == 0){ + cpp__def_end_macro(&result, definitions); + if (result.early_out) goto cpp__pp_step_early_out; + cpp__def_success_uncertain(definitions); + state->substep = PPState_None; + Debug(state->did_advance = 1); + } + else if (token.type == CPP_TOKEN_PARENTHESE_OPEN){ + state->substep = PPState_Define_Parameter; + cpp__pp_next_token(state, expansion); + } + else{ + state->substep = PPState_Define_Body; + } + }break; + + case PPState_Define_Parameter: + { + if (token.type == CPP_TOKEN_PARENTHESE_CLOSE && + (token.flags & CPP_TFLAG_PP_BODY) && + state->vars.define.param_count == 0){ + state->substep = PPState_Define_Body; + cpp__pp_next_token(state, expansion); + } + else{ + result.error_code = cpp__pp_require_identifier(state, token); + if (result.error_code == PPErr_None){ + state->substep = PPState_Define_Parameter_Comma; + cpp__pp_next_token(state, expansion); + ++state->vars.define.param_count; } - else{ - int stack_start = state->tokens.count; - // NOTE(allen): luckily the number of tokens about to be pushed is known - // up front in this case. No states have been changed yet so it's okay - // allowing a memory request to be issued from here. - if (cpp__can_push_loose_token(state, macro->param_count)){ - bool variadic = 0; - if (macro->param_count != 0){ - int macro_file_index = macro->file_index; - Cpp_File_Data file = *cpp_get_parse_file(definitions, macro_file_index); - int i = macro->first_param_index; - Cpp_Token token = file.tokens.tokens[i]; - for (;;){ - if (token.type == CPP_TOKEN_IDENTIFIER){ - cpp__push_loose_token(state, macro_file_index, i, 0); - } - if (token.type == CPP_TOKEN_ELLIPSIS){ - Cpp_Loose_Token va_args = definitions->va_args_token; - cpp__push_loose_token(state, va_args.file_index, - va_args.token_index, 0); - variadic = 1; - } - - ++i; - if (i >= file.tokens.count){ - break; - } - token = file.tokens.tokens[i]; - if (token.type == CPP_TOKEN_PARENTHESE_CLOSE){ - break; - } - } - _Assert(state->tokens.count - stack_start == macro->param_count); - } - - state->mac_inv.file_index = visit.file_index; - state->mac_inv.token_index = visit.token_index; - - state->mac_inv.invoking_file_index = result.invoking_file_index; - state->mac_inv.invoking_token_index = result.invoking_token_index; - - state->mac_inv.macro_index = macro_index; - state->mac_inv.param_count = 0; - state->mac_inv.paren_level = 0; - state->mac_inv.stack_base = stack_start; - state->mac_inv.variadic = variadic; - - state->state = PPS_MACROINV_OPEN; - } - else{ - result.memory_request = sizeof(Cpp_Loose_Token)* - ((state->tokens.max*2) + macro->param_count); - result.memory_purpose = MEMPURP_TOKEN_STACK; - step_forward = 0; - } - } - } - else{ - result.emit = 1; - result.blocked = 1; - } - } - else{ - result.emit = 1; - } - }break; - - default: - { - result.emit = 1; - }break; - } - }break; - - default: - { - _Assert(!"bad state->state"); - }break; - } - - if (expansion->out_rule != 0 && result.emit){ - cpp__push_loose_token(state, result.file_index, result.token_index, result.blocked); - result.emit = 0; - if (expansion->out_rule > 0){ - if (state->param_info[expansion->out_rule].start == 0){ - state->param_info[expansion->out_rule].start = state->tokens.count - 1; - } - state->param_info[expansion->out_rule].end = state->tokens.count; - } - } - - if (expansion->out_type == EXPAN_NORMAL){ - if (step_forward){ - ++expansion->position; - if (expansion->position == expansion->end_position && do_push_later == 0){ - cpp__preproc_pop_expansion(state, expansion); - } - } - } - else{ - if (state->expansion_level == 0){ - state->finished = 1; - } - else{ - --state->expansion_level; - } - } - - if (do_push_later){ - cpp__push_expansion_raw(state, &to_push_later); - } - - return result; -} - -internal int -cpp__get_parameter_i(Cpp_Preproc_State *state, Cpp_Parse_Definitions * definitions, - Cpp_File_Data *macro_file, Cpp_Token token, int param_start, int param_count){ - int param_i = -1; - if (token.type == CPP_TOKEN_IDENTIFIER){ - String token_str = make_string(macro_file->file.data + token.start, token.size); - for (int j = 0; j < param_count; ++j){ - Cpp_Loose_Token param_loose = state->tokens.tokens[j + param_start]; - Cpp_File_Data *file = cpp_get_parse_file(definitions, param_loose.file_index); - Cpp_Token param_token = file->tokens.tokens[param_loose.token_index]; - String param_str = make_string(file->file.data + param_token.start, param_token.size); - if (match(token_str, param_str)){ - param_i = j; - break; - } - } - } - return param_i; -} - -internal Cpp_Preproc_Result -cpp__preproc_big_step_nonalloc(Cpp_Preproc_State *state, Cpp_Parse_Definitions *definitions, - Cpp_Parse_Context *context){ - Cpp_Preproc_Result result = {}; - Cpp_Expansion *expansion = state->expansions + state->expansion_level; - - Cpp_Macro_Data macro = *cpp_get_macro_data(definitions, expansion->file_index); - Cpp_File_Data *macro_file = cpp_get_parse_file(definitions, macro.file_index); - switch (expansion->out_type){ - case EXPAN_BIG_PROCESS_ARGS: - { - bool expand_arg[64]; - bool strfy_arg[64]; - _Assert(macro.param_count < 64); - memset(expand_arg, 0, macro.param_count); - memset(strfy_arg, 0, macro.param_count); - - bool prev_was_paste = 0; - bool next_is_paste = 0; - bool prev_was_strfy = 0; - Cpp_Token token; - int param_i; - for (int i = macro.body_start_index; i < macro.body_end_index; ++i){ - token = macro_file->tokens.tokens[i]; - param_i = cpp__get_parameter_i(state, definitions, macro_file, token, - expansion->stack_base, macro.param_count); - - next_is_paste = (i+1 < macro.body_end_index && - macro_file->tokens.tokens[i+1].type == CPP_PP_CONCAT); - - if (param_i != -1){ - if (prev_was_strfy){ - strfy_arg[param_i] = 1; - } - else if (!prev_was_paste && !next_is_paste){ - expand_arg[param_i] = 1; - } - } - - prev_was_strfy = (token.type == CPP_PP_STRINGIFY); - prev_was_paste = (token.type == CPP_PP_CONCAT && i != macro.body_start_index); - } - - int param_info_base = expansion->param_info_base; - for (int i = 0; i < macro.param_count; ++i){ - Cpp_Token_Range range = cpp__param_info_get(state, param_info_base, i, RAW); - - if (strfy_arg[i]){ - Cpp_Expansion *new_expansion = - cpp__push_strfy_expansion(state, range.start, range.end, - param_info_base + i*3 + 1, - expansion->invoking_file_index, - expansion->invoking_token_index); - if (new_expansion == 0){ - result.error_code = PPERR_EXPANSION_OVERRUN; - break; - } - } - - if (expand_arg[i]){ - if (range.start < range.end){ - Cpp_Expansion *new_expansion = - cpp__push_expansion(state, EXPAN_ARG, -1, range.start, range.end, - param_info_base + i*3 + 2, - expansion->invoking_file_index, - expansion->invoking_token_index); - if (new_expansion == 0){ - result.error_code = PPERR_EXPANSION_OVERRUN; - break; - } - } - } - } - expansion->out_type = EXPAN_BIG_PROCESS_BODY; - }break; - - case EXPAN_BIG_PROCESS_BODY: - { - int start_pos = state->tokens.count; - - // TODO(allen): because it is possible that this be used more than once, it is possible that - // all of this code happens any number of times before it finally runs through with enough - // memory. Perhaps loft this checkpoint out and try the whole thing in one big checkpoint? - // Some sort of way of determining the max size needed in spare string? - Spare_String_Checkpoint str_checkpoint = {}; - Preserve_Checkpoint pres_checkpoint = cpp__checkpoint_preserve_write(definitions); - Token_Stack_Checkpoint checkpoint = cpp__checkpoint_token_stack(state); - bool next_is_paste = 0; - for (int i = macro.body_start_index; i < macro.body_end_index; ++i){ - Cpp_Token token = macro_file->tokens.tokens[i]; - - next_is_paste = (i+1 < macro.body_end_index && - macro_file->tokens.tokens[i+1].type == CPP_PP_CONCAT); - - enum Body_Builder_Action{ - BBA_NONE, - BBA_NORMAL, - BBA_STRFY, - BBA_PASTE - }; - - int action = BBA_NONE; - int param_i = -1; - int i2 = -1; - - if (token.type == CPP_PP_STRINGIFY){ - i += 1; - if (i < macro.body_end_index){ - action = BBA_STRFY; - } - else{ - i -= 1; - action = BBA_NONE; - } - } - else if (next_is_paste){ - i2 = i + 2; - if (i2 < macro.body_end_index){ - action = BBA_PASTE; - } - else{ - action = BBA_NORMAL; - } - } - else if (token.type == CPP_PP_CONCAT){ - action = BBA_NONE; - } - else{ - action = BBA_NORMAL; - } - - // NOTE(allen): loose token pushes here are managed by checkpoint - switch (action){ - case BBA_NONE:break; - - case BBA_NORMAL: - { - param_i = cpp__get_parameter_i(state, definitions, macro_file, token, - expansion->stack_base, macro.param_count); - if (param_i != -1){ - Cpp_Token_Range range = cpp__param_info_get(state, expansion->param_info_base, param_i, EXPANDED); - for (int j = range.start; j < range.end; ++j){ - Cpp_Loose_Token loose = state->tokens.tokens[j]; - cpp__push_loose_token(&checkpoint, state, loose.file_index, loose.token_index, loose.blocked); - } - } - else{ - cpp__push_loose_token(&checkpoint, state, macro.file_index, i, 0); - } - }break; - - case BBA_STRFY: - { - token = macro_file->tokens.tokens[i]; - param_i = cpp__get_parameter_i(state, definitions, macro_file, token, - expansion->stack_base, macro.param_count); - if (param_i != -1){ - Cpp_Token_Range range = cpp__param_info_get(state, expansion->param_info_base, param_i, STRFY); - Cpp_Loose_Token loose = state->tokens.tokens[range.start]; - cpp__push_loose_token(&checkpoint, state, loose.file_index, loose.token_index, loose.blocked); - } - else{ - cpp__push_loose_token(&checkpoint, state, macro.file_index, i, 0); - } - }break; - - case BBA_PASTE: - { - Cpp_Token token2; - int param_i2; - - param_i = cpp__get_parameter_i(state, definitions, macro_file, token, - expansion->stack_base, macro.param_count); - token2 = macro_file->tokens.tokens[i2]; - param_i2 = cpp__get_parameter_i(state, definitions, macro_file, token2, - expansion->stack_base, macro.param_count); - - str_checkpoint = cpp__checkpoint_spare_string(state); - if (param_i != -1){ - Cpp_Token_Range range = cpp__param_info_get(state, expansion->param_info_base, param_i, RAW); - range.end -= 1; - if (range.start <= range.end){ - int j; - for (j = range.start; j < range.end; ++j){ - Cpp_Loose_Token loose = state->tokens.tokens[j]; - cpp__push_loose_token(&checkpoint, state, loose.file_index, loose.token_index, loose.blocked); - } - Cpp_Loose_Token loose = state->tokens.tokens[j]; - Cpp_File_Data *end_file = cpp_get_parse_file(definitions, loose.file_index); - Cpp_Token end_token = end_file->tokens.tokens[loose.token_index]; - String end_string = make_string(end_file->file.data + end_token.start, end_token.size); - cpp__spare_write(&str_checkpoint, state, end_string); - } - } - else{ - String end_string = make_string(macro_file->file.data + token.start, token.size); - cpp__spare_write(&str_checkpoint, state, end_string); - } - - if (param_i2 != -1){ - Cpp_Token_Range range = cpp__param_info_get(state, expansion->param_info_base, param_i2, RAW); - if (range.start < range.end){ - int j = range.start; - Cpp_Loose_Token loose = state->tokens.tokens[j]; - Cpp_File_Data *start_file = cpp_get_parse_file(definitions, loose.file_index); - Cpp_Token start_token = start_file->tokens.tokens[loose.token_index]; - String start_string = make_string(start_file->file.data + start_token.start, start_token.size); - cpp__spare_write(&str_checkpoint, state, start_string); - } - } - else{ - String start_string = make_string(macro_file->file.data + token2.start, token2.size); - cpp__spare_write(&str_checkpoint, state, start_string); - } - - if (!str_checkpoint.memory_overrun){ - Cpp_Token _tokens[3]; - Cpp_Token_Stack tokens; - tokens.tokens = _tokens; - tokens.max_count = ArrayCount(_tokens); - tokens.count = 0; - - Cpp_File paste_file; - paste_file.data = state->spare_string; - paste_file.size = state->spare_string_write_pos; - - cpp_lex_file_nonalloc(paste_file, &tokens); - _Assert(tokens.count <= 2); - - // TODO(allen): protect these preserves - String paste_string = make_string(state->spare_string, state->spare_string_write_pos); - cpp__preserve_string(&pres_checkpoint, definitions, paste_string); - int start_pos = definitions->string_write_pos - paste_string.size; - for (int k = 0; k < tokens.count; ++k){ - tokens.tokens[k].start += start_pos; - } - for (int k = 0; k < tokens.count; ++k){ - Cpp_Loose_Token loose = cpp__preserve_token(&pres_checkpoint, definitions, tokens.tokens[k]); - cpp__push_loose_token(&checkpoint, state, loose.file_index, loose.token_index, loose.blocked); - } - - i = i2; - } - else{ - i = macro.body_end_index; - } - - state->spare_string_write_pos = 0; - - if (param_i2 != -1){ - Cpp_Token_Range range = cpp__param_info_get(state, expansion->param_info_base, param_i2, RAW); - range.start += 1; - for (int j = range.start; j < range.end; ++j){ - Cpp_Loose_Token loose = state->tokens.tokens[j]; - cpp__push_loose_token(&checkpoint, state, loose.file_index, loose.token_index, loose.blocked); + result.error_code = PPErr_Parameter_Identifier_Missing; + // NOTE(allen): Here I do not do the work I normally do when + // setting an error, because that work was done earlier, this is + // just translating the error code. } } }break; - default: + case PPState_Define_Parameter_Comma: { - _Assert(!"unknown action"); + if ((token.flags & CPP_TFLAG_PP_BODY) == 0){ + result.error_code = PPErr_Unfinished_Parameters; + state->substep = PPState_None; + Debug(state->did_advance = 1); + } + else{ + if (token.type == CPP_TOKEN_COMMA){ + state->substep = PPState_Define_Parameter; + cpp__pp_next_token(state, expansion); + } + else if (token.type == CPP_TOKEN_PARENTHESE_CLOSE){ + state->substep = PPState_Define_Body; + cpp__pp_next_token(state, expansion); + } + else{ + state->substep = PPState_Error_Recovery; + result.error_code = PPErr_Expected_Comma_Or_Parenthese; + Debug(state->did_advance = 1); + } + } }break; + + case PPState_Define_Body: + { + if ((token.flags & CPP_TFLAG_PP_BODY) == 0){ + // TODO(allen): define macro + state->substep = PPState_None; + Debug(state->did_advance = 1); + } + else{ + cpp__pp_next_token(state, expansion); + } + }break; + + case PPState_Error_Recovery: + { + if ((token.flags & CPP_TFLAG_PP_BODY) == 0){ + state->substep = PPState_None; + Debug(state->did_advance = 1); + } + else{ + cpp__pp_next_token(state, expansion); + } + }break; + } } - if (pres_checkpoint.out_of_memory){ - cpp__restore_token_stack(state, checkpoint); - cpp__restore_preserve_write(definitions, pres_checkpoint); - result.memory_request = context->preserve_chunk_size; - result.memory_purpose = MEMPURP_PRESERVE_FILE; - } - else if (str_checkpoint.memory_overrun){ - cpp__restore_token_stack(state, checkpoint); - cpp__restore_preserve_write(definitions, pres_checkpoint); - result.memory_request = (state->spare_string_size * 2) + str_checkpoint.memory_overrun; - result.memory_purpose = MEMPURP_SPARE_STRING; - } - else if (checkpoint.memory_overrun){ - cpp__restore_token_stack(state, checkpoint); - cpp__restore_preserve_write(definitions, pres_checkpoint); - result.memory_request = sizeof(Cpp_Loose_Token)*((state->tokens.max*2) + checkpoint.memory_overrun); - result.memory_purpose = MEMPURP_TOKEN_STACK; - } - else{ - expansion->position = expansion->stack_base; - expansion->out_type = EXPAN_BIG_DIRECT_OUT; - - if (start_pos < state->tokens.count){ - Cpp_Expansion *new_expansion = - cpp__push_expansion(state, EXPAN_PMACRO_BODY, -1, start_pos, state->tokens.count, - -1, expansion->invoking_file_index, - expansion->invoking_token_index); - new_expansion->macro_index = expansion->file_index; - if (new_expansion == 0){ - result.error_code = PPERR_EXPANSION_OVERRUN; - } - } - } - }break; - - case EXPAN_BIG_DIRECT_OUT: - { - if (expansion->out_rule == -1){ - --state->expansion_level; - _Assert(state->expansion_level != -1); - cpp__free_param_table(state, macro.param_count); - } - else if (expansion->out_rule != 0){ - if (state->param_info[expansion->out_rule].start == 0){ - state->param_info[expansion->out_rule].start = expansion->position; - } - state->param_info[expansion->out_rule].end = state->tokens.count; - --state->expansion_level; - _Assert(state->expansion_level != -1); - cpp__free_param_table(state, macro.param_count); - } - else{ - Cpp_Visit visit; - Cpp_Loose_Token loose_token = state->tokens.tokens[expansion->position]; - visit.file_index = loose_token.file_index; - visit.token_index = loose_token.token_index; - - result.file_index = visit.file_index; - result.token_index = visit.token_index; - result.invoking_file_index = expansion->invoking_file_index; - result.invoking_token_index = expansion->invoking_token_index; - result.from_macro = 1; - result.emit = 1; - - ++expansion->position; - if (expansion->position == state->tokens.count){ - state->mac_inv.stack_base -= (state->tokens.count - expansion->stack_base); - state->tokens.count = expansion->stack_base; - --state->expansion_level; - _Assert(state->expansion_level != -1); - cpp__free_param_table(state, macro.param_count); - } - } - }break; - - default: - _Assert(!"only meant to be used with one of the big expan types"); + Assert(state->did_advance == 1); } - - return result; + +cpp__pp_step_early_out: + return(result); } -internal Cpp_Preproc_Result -cpp__preproc_strfy_step_nonalloc(Cpp_Preproc_State *state, Cpp_Parse_Definitions *definitions, - Cpp_Parse_Context *context){ - Cpp_Preproc_Result result = {}; - Cpp_Expansion *expansion = state->expansions + state->expansion_level; - - if (!cpp__can_push_loose_token(state, 1)){ - result.memory_request = sizeof(Cpp_Loose_Token)*((state->tokens.max*2) + 1); - result.memory_purpose = MEMPURP_TOKEN_STACK; - return result; - } - - Cpp_Visit visit = {}; +internal Cpp_PP_Step +cpp_preproc_step_nonalloc(Cpp_PP_State *state, Cpp_PP_Definitions *definitions){ + Cpp_PP_Step result; + Cpp_PP_Expansion_Header *header; - bool do_body = 1; - if (expansion->position == expansion->end_position + 1){ - do_body = 0; - --expansion->position; - } - else if (expansion->position == expansion->end_position){ - visit.file_index = definitions->eof_token.file_index; - visit.token_index = definitions->eof_token.token_index; - } - else{ - _Assert(expansion->file_index == -1); - Cpp_Loose_Token loose = state->tokens.tokens[expansion->position]; - visit.file_index = loose.file_index; - visit.token_index = loose.token_index; - } - - Spare_String_Checkpoint checkpoint = cpp__checkpoint_spare_string(state); - - if (do_body){ - Cpp_File_Data visit_file; - Cpp_Token visit_token; - - visit_file = *cpp_get_parse_file(definitions, visit.file_index); - visit_token = visit_file.tokens.tokens[visit.token_index]; - - result.file_index = visit.file_index; - result.token_index = visit.token_index; - result.invoking_file_index = expansion->invoking_file_index; - result.invoking_token_index = expansion->invoking_token_index; - result.from_macro = 1; - result.emit = 0; - - if (state->spare_string_write_pos == 0){ - cpp__spare_write(&checkpoint, state, '"'); - expansion->param_info_base = visit_token.start + visit_token.size; - } - - switch (visit_token.type){ - case CPP_TOKEN_COMMENT: - case CPP_TOKEN_JUNK:break; - - case CPP_TOKEN_EOF: - { - cpp__spare_write(&checkpoint, state, '"'); - }break; - - case CPP_TOKEN_STRING_CONSTANT: - { - if (visit_token.start > expansion->param_info_base){ - cpp__spare_write(&checkpoint, state, ' '); - } - - int i = visit_token.start; - char c = visit_file.file.data[i]; - while (c != '"'){ - cpp__spare_write(&checkpoint, state, c); - ++i; - c = visit_file.file.data[i]; - } - - cpp__spare_write(&checkpoint, state, '\\'); - cpp__spare_write(&checkpoint, state, '"'); - ++i; - - int end_pos = visit_token.start + visit_token.size - 1; - for (; i < end_pos; ++i){ - c = visit_file.file.data[i]; - switch (c){ - case '\\': - cpp__spare_write(&checkpoint, state, '\\'); - - default: - cpp__spare_write(&checkpoint, state, c); - } - } - - cpp__spare_write(&checkpoint, state, '\\'); - cpp__spare_write(&checkpoint, state, '"'); - - expansion->param_info_base = visit_token.start + visit_token.size; - }break; - - case CPP_TOKEN_CHARACTER_CONSTANT: - { - if (visit_token.start > expansion->param_info_base){ - cpp__spare_write(&checkpoint, state, ' '); - } - - int i = visit_token.start; - char c = visit_file.file.data[i]; - while (c != '\''){ - cpp__spare_write(&checkpoint, state, c); - ++i; - c = visit_file.file.data[i]; - } - - int end_pos = visit_token.start + visit_token.size; - for (; i < end_pos; ++i){ - c = visit_file.file.data[i]; - switch (c){ - case '\\': - cpp__spare_write(&checkpoint, state, '\\'); - - default: - cpp__spare_write(&checkpoint, state, c); - } - } - - expansion->param_info_base = visit_token.start + visit_token.size; - }break; - - default: - { - if (visit_token.start > expansion->param_info_base){ - cpp__spare_write(&checkpoint, state, ' '); - } - - int end_pos = visit_token.start + visit_token.size; - for (int i = visit_token.start; i < end_pos; ++i){ - char c = visit_file.file.data[i]; - cpp__spare_write(&checkpoint, state, c); - } - - expansion->param_info_base = visit_token.start + visit_token.size; - }break; - } - } - - if (checkpoint.memory_overrun){ - cpp__restore_spare_string(state, checkpoint); - result.memory_request = (state->spare_string_size*2) + checkpoint.memory_overrun; - result.memory_purpose = MEMPURP_SPARE_STRING; - } - else{ - if (expansion->position == expansion->end_position){ - Preserve_Checkpoint preserve_checkpoint = cpp__checkpoint_preserve_write(definitions); - - String string = make_string(state->spare_string, state->spare_string_write_pos); - Cpp_Token token = {}; - token.type = CPP_TOKEN_STRING_CONSTANT; - token.start = definitions->string_write_pos; - token.size = string.size; - - cpp__preserve_string(&preserve_checkpoint, definitions, string); - Cpp_Loose_Token loose = cpp__preserve_token(&preserve_checkpoint, definitions, token); - - if (preserve_checkpoint.out_of_memory){ - cpp__restore_preserve_write(definitions, preserve_checkpoint); - result.memory_request = context->preserve_chunk_size; - result.memory_purpose = MEMPURP_PRESERVE_FILE; - } - else{ - _Assert(expansion->out_rule > 0); - // NOTE(allen): this function gaurantees there is at least room - // for one token at the head end - cpp__push_loose_token(state, loose.file_index, loose.token_index, loose.blocked); - state->param_info[expansion->out_rule].start = state->tokens.count - 1; - state->param_info[expansion->out_rule].end = state->tokens.count; - --state->expansion_level; - state->spare_string_write_pos = 0; - } - } - ++expansion->position; - } - - return result; -} + Assert(state->top >= sizeof(Cpp_PP_Expansion_Header)); -internal Cpp_Preproc_Result -cpp_preproc_step_nonalloc(Cpp_Preproc_State *state, Cpp_Parse_Definitions *definitions, - Cpp_Parse_Context *context){ - Cpp_Preproc_Result result; - - if (state->resizing_slots){ - result = {}; - result.memory_request = sizeof(Table_Entry)*(definitions->table.max_size*2); - result.memory_purpose = MEMPURP_DEFINITION_SLOTS; - state->resizing_slots = 0; - return result; - } - if (definitions->count * 8 >= definitions->max * 7){ - result = {}; - result.memory_request = sizeof(Cpp_Def_Slot)*(definitions->max*2); - result.memory_purpose = MEMPURP_DEFINITION_SLOTS; - state->resizing_slots = 1; - return result; - } - - Cpp_Expansion *expansion = state->expansions + state->expansion_level; - switch (expansion->out_type){ - case EXPAN_NORMAL: - case EXPAN_EOF_FLUSH: - result = cpp__preproc_normal_step_nonalloc(state, definitions, context); + result = {}; + header = (Cpp_PP_Expansion_Header*)(state->base + state->frame); + switch (header->type){ + case PPExp_Normal: + result = cpp__pp_step_normal(state, definitions, + (Cpp_PP_Expansion_Normal*)(header + 1)); break; - - case EXPAN_BIG_PROCESS_ARGS: - case EXPAN_BIG_PROCESS_BODY: - case EXPAN_BIG_DIRECT_OUT: - result = cpp__preproc_big_step_nonalloc(state, definitions, context); - break; - - case EXPAN_STRFY: - result = cpp__preproc_strfy_step_nonalloc(state, definitions, context); - break; - - default: - result = {}; - _Assert(!"unknown expansion->out_type"); + default: Assert(0); } - return result; + if (state->top == 0) result.finished = 1; + + return(result); } +#undef byte + // BOTTOM diff --git a/4cpp_types.h b/4cpp_types.h index b0f067f7..9b51de1f 100644 --- a/4cpp_types.h +++ b/4cpp_types.h @@ -9,7 +9,7 @@ NOTES ON USE: // TODO(allen): // - create non stdint.h version in case someone wants to exclude that header -#include "4cpp_config.h" +#include "4coder_config.h" #ifndef FCPP_TYPES #define FCPP_TYPES diff --git a/4ed.cpp b/4ed.cpp index fc258873..71366e04 100644 --- a/4ed.cpp +++ b/4ed.cpp @@ -33,6 +33,11 @@ struct CLI_List{ i32 count, max; }; +struct Sys_App_Binding{ + i32 sys_id; + i32 app_id; +}; + struct App_Vars{ Mem_Options mem; Command_Map map_top; @@ -45,9 +50,12 @@ struct App_Vars{ i32 *map_id_table; i32 user_map_count; + Sys_App_Binding *sys_app_bindings; + i32 sys_app_count, sys_app_max; + Custom_Command_Function *hooks[hook_type_count]; - Font_Set fonts; + Font_Set *font_set; Style style; Style_Library styles; @@ -59,7 +67,6 @@ struct App_Vars{ Working_Set working_set; char hot_dir_base_[256]; - String hot_dir_base; Hot_Directory hot_directory; CLI_List cli_processes; @@ -131,12 +138,15 @@ globalvar Application_Links app_links; #define USE_STYLE(n) Style *n = command->style #define USE_DELAY(n) Delay *n = command->delay #define USE_VARS(n) App_Vars *n = command->vars +#define USE_EXCHANGE(n) Exchange *n = command->exchange +#define USE_FONT_SET(n) Font_Set *n = command->vars->font_set; #define REQ_VIEW(n) View *n = command->view; if (!n) return #define REQ_FILE_VIEW(n) File_View *n = view_to_file_view(command->view); if (!n) return #define REQ_OPEN_FILE_VIEW(n) File_View *n = view_to_file_view(command->view); if (!n || n->locked) return -#define REQ_FILE_HISTORY(n,v) Editing_File *n = (v)->file; if (!n || !buffer_good(&n->buffer) || n->is_dummy || !n->undo.undo.edits) return -#define REQ_FILE(n,v) Editing_File *n = (v)->file; if (!n || !buffer_good(&n->buffer) || n->is_dummy) return +#define REQ_FILE_HISTORY(n,v) Editing_File *n = (v)->file; if (!n || !buffer_good(&n->state.buffer) || n->state.is_dummy || !n->state.undo.undo.edits) return +#define REQ_FILE_LOADING(n,v) Editing_File *n = (v)->file; if (!n || n->state.is_dummy) return +#define REQ_FILE(n,v) Editing_File *n = (v)->file; if (!n || !buffer_good(&n->state.buffer) || n->state.is_dummy) return #define REQ_COLOR_VIEW(n) Color_View *n = view_to_color_view(command->view); if (!n) return #define REQ_DBG_VIEW(n) Debug_View *n = view_to_debug_view(command->view); if (!n) return @@ -153,6 +163,7 @@ struct Command_Data{ Style *style; Delay *delay; App_Vars *vars; + Exchange *exchange; i32 screen_width, screen_height; Key_Single key; @@ -224,8 +235,7 @@ COMMAND_DECL(write_character){ i32 next_cursor_pos = view->cursor.pos + string.size; view_replace_range(system, mem, view, layout, pos, pos, (u8*)string.str, string.size, next_cursor_pos); view_cursor_move(view, next_cursor_pos); - if (view->mark >= pos) view->mark += string.size; - file->cursor_pos = view->cursor.pos; + file->state.cursor_pos = view->cursor.pos; } COMMAND_DECL(seek_whitespace_right){ @@ -234,7 +244,7 @@ COMMAND_DECL(seek_whitespace_right){ REQ_FILE_VIEW(view); REQ_FILE(file, view); - i32 pos = buffer_seek_whitespace_right(&file->buffer, view->cursor.pos); + i32 pos = buffer_seek_whitespace_right(&file->state.buffer, view->cursor.pos); view_cursor_move(view, pos); #endif } @@ -245,7 +255,7 @@ COMMAND_DECL(seek_whitespace_left){ REQ_FILE_VIEW(view); REQ_FILE(file, view); - i32 pos = buffer_seek_whitespace_left(&file->buffer, view->cursor.pos); + i32 pos = buffer_seek_whitespace_left(&file->state.buffer, view->cursor.pos); view_cursor_move(view, pos); #endif } @@ -256,7 +266,7 @@ COMMAND_DECL(seek_whitespace_up){ REQ_FILE_VIEW(view); REQ_FILE(file, view); - i32 pos = buffer_seek_whitespace_up(&file->buffer, view->cursor.pos); + i32 pos = buffer_seek_whitespace_up(&file->state.buffer, view->cursor.pos); view_cursor_move(view, pos); #endif } @@ -267,7 +277,7 @@ COMMAND_DECL(seek_whitespace_down){ REQ_FILE_VIEW(view); REQ_FILE(file, view); - i32 pos = buffer_seek_whitespace_down(&file->buffer, view->cursor.pos); + i32 pos = buffer_seek_whitespace_down(&file->state.buffer, view->cursor.pos); view_cursor_move(view, pos); #endif } @@ -306,8 +316,8 @@ COMMAND_DECL(seek_token_left){ REQ_FILE_VIEW(view); REQ_FILE(file, view); - if (file->tokens_complete){ - i32 pos = seek_token_left(&file->token_stack, view->cursor.pos); + if (file->state.tokens_complete){ + i32 pos = seek_token_left(&file->state.token_stack, view->cursor.pos); view_cursor_move(view, pos); } } @@ -317,8 +327,8 @@ COMMAND_DECL(seek_token_right){ REQ_FILE_VIEW(view); REQ_FILE(file, view); - if (file->tokens_complete){ - i32 pos = seek_token_right(&file->token_stack, view->cursor.pos); + if (file->state.tokens_complete){ + i32 pos = seek_token_right(&file->state.token_stack, view->cursor.pos); view_cursor_move(view, pos); } } @@ -330,11 +340,11 @@ COMMAND_DECL(seek_white_or_token_right){ REQ_FILE(file, view); i32 token_pos, white_pos; - token_pos = file->buffer.size; - if (file->tokens_complete){ - token_pos = seek_token_right(&file->token_stack, view->cursor.pos); + token_pos = file->state.buffer.size; + if (file->state.tokens_complete){ + token_pos = seek_token_right(&file->state.token_stack, view->cursor.pos); } - white_pos = buffer_seek_whitespace_right(&file->buffer, view->cursor.pos); + white_pos = buffer_seek_whitespace_right(&file->state.buffer, view->cursor.pos); view_cursor_move(view, Min(token_pos, white_pos)); #endif } @@ -346,11 +356,11 @@ COMMAND_DECL(seek_white_or_token_left){ REQ_FILE(file, view); i32 token_pos, white_pos; - token_pos = file->buffer.size; - if (file->tokens_complete){ - token_pos = seek_token_left(&file->token_stack, view->cursor.pos); + token_pos = file->state.buffer.size; + if (file->state.tokens_complete){ + token_pos = seek_token_left(&file->state.token_stack, view->cursor.pos); } - white_pos = buffer_seek_whitespace_left(&file->buffer, view->cursor.pos); + white_pos = buffer_seek_whitespace_left(&file->state.buffer, view->cursor.pos); view_cursor_move(view, Max(token_pos, white_pos)); #endif } @@ -361,7 +371,7 @@ COMMAND_DECL(seek_alphanumeric_right){ REQ_FILE_VIEW(view); REQ_FILE(file, view); - i32 pos = buffer_seek_alphanumeric_right(&file->buffer, view->cursor.pos); + i32 pos = buffer_seek_alphanumeric_right(&file->state.buffer, view->cursor.pos); view_cursor_move(view, pos); #endif } @@ -372,7 +382,7 @@ COMMAND_DECL(seek_alphanumeric_left){ REQ_FILE_VIEW(view); REQ_FILE(file, view); - i32 pos = buffer_seek_alphanumeric_left(&file->buffer, view->cursor.pos); + i32 pos = buffer_seek_alphanumeric_left(&file->state.buffer, view->cursor.pos); view_cursor_move(view, pos); #endif } @@ -383,8 +393,8 @@ COMMAND_DECL(seek_alphanumeric_or_camel_right){ REQ_FILE_VIEW(view); REQ_FILE(file, view); - i32 an_pos = buffer_seek_alphanumeric_right(&file->buffer, view->cursor.pos); - i32 pos = buffer_seek_alphanumeric_or_camel_right(&file->buffer, view->cursor.pos, an_pos); + i32 an_pos = buffer_seek_alphanumeric_right(&file->state.buffer, view->cursor.pos); + i32 pos = buffer_seek_alphanumeric_or_camel_right(&file->state.buffer, view->cursor.pos, an_pos); view_cursor_move(view, pos); #endif } @@ -395,8 +405,8 @@ COMMAND_DECL(seek_alphanumeric_or_camel_left){ REQ_FILE_VIEW(view); REQ_FILE(file, view); - i32 an_pos = buffer_seek_alphanumeric_left(&file->buffer, view->cursor.pos); - i32 pos = buffer_seek_alphanumeric_or_camel_left(&file->buffer, view->cursor.pos, an_pos); + i32 an_pos = buffer_seek_alphanumeric_left(&file->state.buffer, view->cursor.pos); + i32 pos = buffer_seek_alphanumeric_or_camel_left(&file->state.buffer, view->cursor.pos, an_pos); view_cursor_move(view, pos); #endif } @@ -474,7 +484,6 @@ COMMAND_DECL(cut){ view_replace_range(system, mem, view, layout, range.start, range.end, 0, 0, next_cursor_pos); view->mark = range.start; - view_measure_wraps(system, &mem->general, view); view_cursor_move(view, next_cursor_pos); } } @@ -563,8 +572,8 @@ COMMAND_DECL(delete_range){ Range range = get_range(view->cursor.pos, view->mark); if (range.start < range.end){ i32 next_cursor_pos = range.start; - view_replace_range(system, mem, view, layout, range.start, range.end, 0, 0, next_cursor_pos); - view_measure_wraps(system, &mem->general, view); + view_replace_range(system, mem, view, layout, range.start, range.end, + 0, 0, next_cursor_pos); view_cursor_move(view, next_cursor_pos); view->mark = range.start; } @@ -656,6 +665,7 @@ COMMAND_DECL(history_forward){ view_history_step(system, mem, layout, view, hist_forward); } +#if UseFileHistoryDump COMMAND_DECL(save_history){ ProfileMomentFunction(); REQ_FILE_VIEW(view); @@ -664,6 +674,7 @@ COMMAND_DECL(save_history){ file_dump_history(system, mem, file, "history_data.hst"); } +#endif COMMAND_DECL(interactive_new){ ProfileMomentFunction(); @@ -674,28 +685,31 @@ COMMAND_DECL(interactive_new){ USE_WORKING_SET(working_set); USE_STYLE(style); USE_DELAY(delay); + USE_EXCHANGE(exchange); + USE_FONT_SET(font_set); View *new_view = live_set_alloc_view(live_set, mem); - view_replace_minor(system, new_view, panel, live_set); + view_replace_minor(system, exchange, new_view, panel, live_set); new_view->map = &vars->map_ui; Interactive_View *int_view = - interactive_view_init(system, - new_view, &vars->hot_directory, style, - working_set, delay); + interactive_view_init(system, new_view, &vars->hot_directory, + style, working_set, + font_set, delay); int_view->interaction = INTV_SYS_FILE_LIST; int_view->action = INTV_NEW; copy(&int_view->query, "New: "); } +#if 0 internal File_View* -app_open_file(System_Functions *system, +app_open_file(System_Functions *system, Exchange *exchange, App_Vars *vars, Mem_Options *mem, Panel *panel, Working_Set *working_set, String *string, Style *style, Live_Views *live_set, Command_Data *command_data){ File_View *result = 0; Editing_File *target_file = 0; - bool32 created_file = 0; + b32 created_file = 0; target_file = working_set_contains(working_set, *string); if (!target_file){ @@ -713,7 +727,7 @@ app_open_file(System_Functions *system, if (target_file){ View *new_view = live_set_alloc_view(live_set, &vars->mem); - view_replace_major(system, new_view, panel, live_set); + view_replace_major(system, exchange, new_view, panel, live_set); File_View *file_view = file_view_init(new_view, &vars->layout); result = file_view; @@ -727,23 +741,112 @@ app_open_file(System_Functions *system, view_set_file(system, file_view, target_file, style, - vars->hooks[hook_open_file], command_data, app_links); + vars->hooks[hook_open_file], command_data, &app_links); command_data->part = old_part; end_temp_memory(temp); - command_data->view = old_view; new_view->map = app_get_map(vars, target_file->base_map_id); #if BUFFER_EXPERIMENT_SCALPEL <= 0 - if (created_file && target_file->tokens_exist && target_file->token_stack.tokens == 0) + if (created_file && target_file->tokens_exist && + target_file->token_stack.tokens == 0){ file_first_lex_parallel(system, &mem->general, target_file); + } #endif } return result; } +#endif + +internal void +app_push_file_binding(App_Vars *vars, int sys_id, int app_id){ + Sys_App_Binding binding; + Assert(vars->sys_app_count < vars->sys_app_max); + binding.sys_id = sys_id; + binding.app_id = app_id; + vars->sys_app_bindings[vars->sys_app_count++] = binding; +} + +internal File_View* +app_open_file(System_Functions *system, App_Vars *vars, Exchange *exchange, + Live_Views *live_set, Working_Set *working_set, Panel *panel, + Command_Data *command_data, char *filename, int len){ + String filename_str; + i32 file_id; + File_View *result; + Mem_Options *mem; + Editing_File *target_file = 0; + b32 created_file = 0; + + filename_str = make_string(filename, len); + mem = &vars->mem; + + result = 0; + target_file = working_set_contains(working_set, filename_str); + if (!target_file){ + Get_File_Result file = working_set_get_available_file(working_set); + if (file.file){ + file_id = exchange_request_file(exchange, filename, len); + if (file_id){ + created_file = 1; + target_file = file.file; + file_get_loading(target_file); + table_add(&working_set->table, target_file->state.source_path, file.index); + file_init_strings(target_file); + file_set_name(target_file, filename); + + app_push_file_binding(vars, file_id, file.index); + } + else{ + file_get_dummy(file.file); + } + } + } + + if (target_file){ + Style *style = command_data->style; + + View *new_view = live_set_alloc_view(live_set, mem); + view_replace_major(system, exchange, new_view, panel, live_set); + + File_View *file_view = file_view_init(new_view, &vars->layout); + result = file_view; + + View *old_view = command_data->view; + command_data->view = new_view; + + Partition old_part = command_data->part; + Temp_Memory temp = begin_temp_memory(&mem->part); + command_data->part = partition_sub_part(&mem->part, Kbytes(16)); + + view_set_file(system, file_view, target_file, vars->font_set, + style, vars->hooks[hook_open_file], command_data, + &app_links); + + command_data->part = old_part; + end_temp_memory(temp); + command_data->view = old_view; + + new_view->map = app_get_map(vars, target_file->settings.base_map_id); + } + +#if 0 + file_id = exchange_request_file(exchange, filename, len); + + if (file_id){ + Get_File_Result + + + result = live_set_alloc_view(live_set, &vars->mem); + } + //exchange_free_file(exchange, file_id); +#endif + + return(result); +} COMMAND_DECL(interactive_open){ @@ -755,6 +858,8 @@ COMMAND_DECL(interactive_open){ USE_WORKING_SET(working_set); USE_STYLE(style); USE_DELAY(delay); + USE_EXCHANGE(exchange); + USE_FONT_SET(font_set); char *filename = 0; int filename_len = 0; @@ -771,24 +876,20 @@ COMMAND_DECL(interactive_open){ } } - bool32 made_file = 0; - if (filename){ String string = make_string(filename, filename_len); - if (app_open_file(system, - vars, mem, panel, working_set, - &string, style, live_set, command)) made_file = 1; + app_open_file(system, vars, exchange, + live_set, working_set, panel, + command, string.str, string.size); } - - if (!made_file){ + else{ View *new_view = live_set_alloc_view(live_set, mem); - view_replace_minor(system, new_view, panel, live_set); + view_replace_minor(system, exchange, new_view, panel, live_set); new_view->map = &vars->map_ui; Interactive_View *int_view = - interactive_view_init(system, - new_view, &vars->hot_directory, style, - working_set, delay); + interactive_view_init(system, new_view, &vars->hot_directory, + style, working_set, font_set, delay); int_view->interaction = INTV_SYS_FILE_LIST; int_view->action = INTV_OPEN; copy(&int_view->query, "Open: "); @@ -800,6 +901,7 @@ COMMAND_DECL(interactive_open){ // - Keep current version open and do some sort of diff to keep // the cursor position correct COMMAND_DECL(reopen){ +#if 0 ProfileMomentFunction(); REQ_FILE_VIEW(view); REQ_FILE(file, view); @@ -807,10 +909,9 @@ COMMAND_DECL(reopen){ USE_LAYOUT(layout); USE_MEM(mem); USE_VARS(vars); - + Editing_File temp_file; - if (file_create(system, - mem, &temp_file, make_c_str(file->source_path), style->font)){ + if (file_create(system, mem, &temp_file, make_c_str(file->source_path), style->font)){ file_close(system, &mem->general, file); *file = temp_file; file->source_path.str = file->source_path_; @@ -842,17 +943,22 @@ COMMAND_DECL(reopen){ } } } +#endif } COMMAND_DECL(save){ ProfileMomentFunction(); REQ_FILE_VIEW(view); REQ_FILE(file, view); + USE_VARS(vars); USE_MEM(mem); + USE_EXCHANGE(exchange); + USE_WORKING_SET(working_set); - String *file_path = &file->source_path; + String *file_path = &file->state.source_path; if (file_path->size > 0){ - file_save(system, &mem->part, file, file_path->str); + i32 sys_id = file_save(system, exchange, mem, file, file_path->str); + app_push_file_binding(vars, sys_id, get_file_id(working_set, file)); } } @@ -865,15 +971,16 @@ COMMAND_DECL(interactive_save_as){ USE_WORKING_SET(working_set); USE_STYLE(style); USE_DELAY(delay); + USE_EXCHANGE(exchange); + USE_FONT_SET(font_set); View *new_view = live_set_alloc_view(live_set, mem); - view_replace_minor(system, new_view, panel, live_set); + view_replace_minor(system, exchange, new_view, panel, live_set); new_view->map = &vars->map_ui; Interactive_View *int_view = - interactive_view_init(system, - new_view, &vars->hot_directory, style, - working_set, delay); + interactive_view_init(system, new_view, &vars->hot_directory, style, + working_set, font_set, delay); int_view->interaction = INTV_SYS_FILE_LIST; int_view->action = INTV_SAVE_AS; copy(&int_view->query, "Save As: "); @@ -899,15 +1006,16 @@ COMMAND_DECL(interactive_switch_buffer){ USE_WORKING_SET(working_set); USE_STYLE(style); USE_DELAY(delay); + USE_EXCHANGE(exchange); + USE_FONT_SET(font_set); View *new_view = live_set_alloc_view(live_set, mem); - view_replace_minor(system, new_view, panel, live_set); + view_replace_minor(system, exchange, new_view, panel, live_set); new_view->map = &vars->map_ui; Interactive_View *int_view = - interactive_view_init(system, - new_view, &vars->hot_directory, style, - working_set, delay); + interactive_view_init(system, new_view, &vars->hot_directory, style, + working_set, font_set, delay); int_view->interaction = INTV_LIVE_FILE_LIST; int_view->action = INTV_SWITCH; copy(&int_view->query, "Switch File: "); @@ -922,15 +1030,16 @@ COMMAND_DECL(interactive_kill_buffer){ USE_WORKING_SET(working_set); USE_STYLE(style); USE_DELAY(delay); + USE_EXCHANGE(exchange); + USE_FONT_SET(font_set); View *new_view = live_set_alloc_view(live_set, mem); - view_replace_minor(system, new_view, panel, live_set); + view_replace_minor(system, exchange, new_view, panel, live_set); new_view->map = &vars->map_ui; Interactive_View *int_view = - interactive_view_init(system, - new_view, &vars->hot_directory, style, - working_set, delay); + interactive_view_init(system, new_view, &vars->hot_directory, style, + working_set, font_set, delay); int_view->interaction = INTV_LIVE_FILE_LIST; int_view->action = INTV_KILL; copy(&int_view->query, "Kill File: "); @@ -942,7 +1051,7 @@ COMMAND_DECL(kill_buffer){ REQ_FILE(file, view); USE_DELAY(delay); - delayed_action(delay, DACT_TRY_KILL, file->live_name, view->view_base.panel); + delayed_action(delay, DACT_TRY_KILL, file->state.live_name, view->view_base.panel); } COMMAND_DECL(toggle_line_wrap){ @@ -979,7 +1088,7 @@ COMMAND_DECL(toggle_tokens){ REQ_FILE(file, view); USE_MEM(mem); - if (file->tokens_exist){ + if (file->settings.tokens_exist){ file_kill_tokens(system, &mem->general, file); } else{ @@ -1001,19 +1110,19 @@ case_change_range(System_Functions *system, step.edit.end = range.end; step.edit.len = range.end - range.start; - if (file->still_lexing) - system->cancel_job(BACKGROUND_THREADS, file->lex_job); + if (file->state.still_lexing) + system->cancel_job(BACKGROUND_THREADS, file->state.lex_job); file_update_history_before_edit(mem, file, step, 0, hist_normal); - u8 *data = (u8*)file->buffer.data; + u8 *data = (u8*)file->state.buffer.data; for (i32 i = range.start; i < range.end; ++i){ if (data[i] >= a && data[i] <= z){ data[i] += char_delta; } } - if (file->token_stack.tokens) + if (file->state.token_stack.tokens) file_relex_parallel(system, mem, file, range.start, range.end, 0); } #endif @@ -1050,8 +1159,8 @@ COMMAND_DECL(eol_dosify){ REQ_FILE_VIEW(view); REQ_FILE(file, view); - file->dos_write_mode = 1; - file->last_4ed_edit_time = system->time_stamp_now(); + file->settings.dos_write_mode = 1; + file->state.last_4ed_edit_time = system->time(); } COMMAND_DECL(eol_nixify){ @@ -1059,8 +1168,8 @@ COMMAND_DECL(eol_nixify){ REQ_FILE_VIEW(view); REQ_FILE(file, view); - file->dos_write_mode = 0; - file->last_4ed_edit_time = system->time_stamp_now(); + file->settings.dos_write_mode = 0; + file->state.last_4ed_edit_time = system->time(); } COMMAND_DECL(auto_tab){ @@ -1085,7 +1194,7 @@ COMMAND_DECL(auto_tab_range){ USE_LAYOUT(layout); USE_MEM(mem); - if (file->token_stack.tokens && file->tokens_complete){ + if (file->state.token_stack.tokens && file->state.tokens_complete){ Range range = get_range(view->cursor.pos, view->mark); view_auto_tab_tokens(system, mem, view, layout, range.start, range.end, 1); } @@ -1098,7 +1207,7 @@ COMMAND_DECL(auto_tab_line_at_cursor){ USE_LAYOUT(layout); USE_MEM(mem); - if (file->token_stack.tokens && file->tokens_complete){ + if (file->state.token_stack.tokens && file->state.tokens_complete){ i32 pos = view->cursor.pos; view_auto_tab_tokens(system, mem, view, layout, pos, pos, 0); } @@ -1111,8 +1220,8 @@ COMMAND_DECL(auto_tab_whole_file){ USE_LAYOUT(layout); USE_MEM(mem); - if (file->token_stack.tokens && file->tokens_complete){ - view_auto_tab_tokens(system, mem, view, layout, 0, buffer_size(&file->buffer), 1); + if (file->state.token_stack.tokens && file->state.tokens_complete){ + view_auto_tab_tokens(system, mem, view, layout, 0, buffer_size(&file->state.buffer), 1); } } @@ -1173,10 +1282,11 @@ COMMAND_DECL(close_panel){ USE_LAYOUT(layout); USE_PANEL(panel); USE_VIEW(view); + USE_EXCHANGE(exchange); if (layout->panel_count > 1){ if (view){ - live_set_free_view(system, command->live_set, view); + live_set_free_view(system, exchange, command->live_set, view); panel->view = 0; } @@ -1253,7 +1363,7 @@ COMMAND_DECL(move_right){ REQ_FILE_VIEW(view); REQ_FILE(file, view); - i32 size = buffer_size(&file->buffer); + i32 size = buffer_size(&file->state.buffer); i32 pos = view->cursor.pos; if (pos < size) ++pos; view_cursor_move(view, pos); @@ -1266,7 +1376,7 @@ COMMAND_DECL(delete){ USE_LAYOUT(layout); USE_MEM(mem); - i32 size = buffer_size(&file->buffer); + i32 size = buffer_size(&file->state.buffer); i32 cursor_pos = view->cursor.pos; if (0 < size && cursor_pos < size){ i32 start, end; @@ -1279,7 +1389,6 @@ COMMAND_DECL(delete){ i32 next_cursor_pos = start; view_replace_range(system, mem, view, layout, start, end, 0, 0, next_cursor_pos); view_cursor_move(view, next_cursor_pos); - if (view->mark >= end) view->mark -= shift; } } @@ -1290,7 +1399,7 @@ COMMAND_DECL(backspace){ USE_LAYOUT(layout); USE_MEM(mem); - i32 size = buffer_size(&file->buffer); + i32 size = buffer_size(&file->state.buffer); i32 cursor_pos = view->cursor.pos; if (cursor_pos > 0 && cursor_pos <= size){ i32 start, end; @@ -1303,7 +1412,6 @@ COMMAND_DECL(backspace){ i32 next_cursor_pos = view->cursor.pos - shift; view_replace_range(system, mem, view, layout, start, end, 0, 0, next_cursor_pos); view_cursor_move(view, next_cursor_pos); - if (view->mark >= end) view->mark -= shift; } } @@ -1311,12 +1419,14 @@ COMMAND_DECL(move_up){ ProfileMomentFunction(); REQ_FILE_VIEW(view); REQ_FILE(file, view); - - real32 cy = view_get_cursor_y(view)-view->style->font->height; - real32 px = view->preferred_x; + USE_FONT_SET(font_set); + + f32 font_height = (f32)get_font_info(font_set, view->style->font_id)->height; + f32 cy = view_get_cursor_y(view)-font_height; + f32 px = view->preferred_x; if (cy >= 0){ view->cursor = view_compute_cursor_from_xy(view, px, cy); - file->cursor_pos = view->cursor.pos; + file->state.cursor_pos = view->cursor.pos; } } @@ -1324,11 +1434,13 @@ COMMAND_DECL(move_down){ ProfileMomentFunction(); REQ_FILE_VIEW(view); REQ_FILE(file, view); - - real32 cy = view_get_cursor_y(view)+view->style->font->height; - real32 px = view->preferred_x; + USE_FONT_SET(font_set); + + f32 font_height = (f32)get_font_info(font_set, view->style->font_id)->height; + f32 cy = view_get_cursor_y(view)+font_height; + f32 px = view->preferred_x; view->cursor = view_compute_cursor_from_xy(view, px, cy); - file->cursor_pos = view->cursor.pos; + file->state.cursor_pos = view->cursor.pos; } COMMAND_DECL(seek_end_of_line){ @@ -1383,10 +1495,10 @@ COMMAND_DECL(page_up){ } inline void -open_theme_options(System_Functions *system, +open_theme_options(System_Functions *system, Exchange *exchange, App_Vars *vars, Live_Views *live_set, Mem_Options *mem, Panel *panel){ View *new_view = live_set_alloc_view(live_set, mem); - view_replace_minor(system, new_view, panel, live_set); + view_replace_minor(system, exchange, new_view, panel, live_set); new_view->map = &vars->map_ui; Color_View *color_view = color_view_init(new_view, &vars->working_set); @@ -1395,7 +1507,7 @@ open_theme_options(System_Functions *system, color_view->styles = &vars->styles; color_view->palette = vars->palette; color_view->palette_size = vars->palette_size; - color_view->fonts = &vars->fonts; + color_view->font_set = vars->font_set; } COMMAND_DECL(open_color_tweaker){ @@ -1404,8 +1516,9 @@ COMMAND_DECL(open_color_tweaker){ USE_LIVE_SET(live_set); USE_MEM(mem); USE_PANEL(panel); + USE_EXCHANGE(exchange); - open_theme_options(system, vars, live_set, mem, panel); + open_theme_options(system, exchange, vars, live_set, mem, panel); } COMMAND_DECL(open_menu){ @@ -1416,9 +1529,10 @@ COMMAND_DECL(open_menu){ USE_MEM(mem); USE_WORKING_SET(working_set); USE_STYLE(style); + USE_EXCHANGE(exchange); View *new_view = live_set_alloc_view(live_set, mem); - view_replace_minor(system, new_view, panel, live_set); + view_replace_minor(system, exchange, new_view, panel, live_set); new_view->map = &vars->map_ui; Menu_View *menu_view = menu_view_init(new_view, style, working_set, &vars->delay); @@ -1433,13 +1547,14 @@ COMMAND_DECL(open_debug_view){ USE_LIVE_SET(live_set); USE_PANEL(panel); USE_MEM(mem); + USE_EXCHANGE(exchange); View *new_view = live_set_alloc_view(live_set, mem); - view_replace_major(system, new_view, panel, live_set); + view_replace_major(system, exchange, new_view, panel, live_set); new_view->map = &vars->map_debug; Debug_View *debug_view = debug_view_init(new_view); - debug_view->font = style->font; + debug_view->font_id = style->font_id; debug_view->mode = DBG_MEMORY; } @@ -1462,8 +1577,9 @@ COMMAND_DECL(close_minor_view){ REQ_VIEW(view); USE_PANEL(panel); USE_LIVE_SET(live_set); + USE_EXCHANGE(exchange); - view_remove_minor(system, panel, live_set); + view_remove_minor(system, exchange, panel, live_set); } COMMAND_DECL(cursor_mark_swap){ @@ -1477,13 +1593,13 @@ COMMAND_DECL(cursor_mark_swap){ COMMAND_DECL(user_callback){ ProfileMomentFunction(); - if (binding.custom) binding.custom(command, app_links); + if (binding.custom) binding.custom(command, &app_links); } COMMAND_DECL(set_settings){ ProfileMomentFunction(); REQ_FILE_VIEW(view); - REQ_FILE(file, view); + REQ_FILE_LOADING(file, view); USE_VARS(vars); USE_MEM(mem); AllowLocal(mem); @@ -1497,7 +1613,7 @@ COMMAND_DECL(set_settings){ { #if BUFFER_EXPERIMENT_SCALPEL <= 0 int v = dynamic_to_bool(¶m->param.value); - if (file->tokens_exist){ + if (file->settings.tokens_exist){ if (!v) file_kill_tokens(system, &mem->general, file); } else{ @@ -1511,21 +1627,26 @@ COMMAND_DECL(set_settings){ int v = dynamic_to_bool(¶m->param.value); if (view->unwrapped_lines){ if (v){ - Relative_Scrolling scrolling = view_get_relative_scrolling(view); view->unwrapped_lines = 0; - view->target_x = 0; - view->cursor = - view_compute_cursor_from_pos(view, view->cursor.pos); - view_set_relative_scrolling(view, scrolling); + if (!file->state.is_loading){ + Relative_Scrolling scrolling = view_get_relative_scrolling(view); + view->target_x = 0; + view->cursor = + view_compute_cursor_from_pos(view, view->cursor.pos); + view_set_relative_scrolling(view, scrolling); + } } } else{ if (!v){ - Relative_Scrolling scrolling = view_get_relative_scrolling(view); view->unwrapped_lines = 1; - view->cursor = - view_compute_cursor_from_pos(view, view->cursor.pos); - view_set_relative_scrolling(view, scrolling); + + if (!file->state.is_loading){ + Relative_Scrolling scrolling = view_get_relative_scrolling(view); + view->cursor = + view_compute_cursor_from_pos(view, view->cursor.pos); + view_set_relative_scrolling(view, scrolling); + } } } }break; @@ -1533,35 +1654,36 @@ COMMAND_DECL(set_settings){ case par_key_mapid: { int v = dynamic_to_int(¶m->param.value); - if (v == mapid_global) file->base_map_id = mapid_global; - else if (v == mapid_file) file->base_map_id = mapid_file; + if (v == mapid_global) file->settings.base_map_id = mapid_global; + else if (v == mapid_file) file->settings.base_map_id = mapid_file; else if (v >= mapid_user_custom){ int index = app_get_map_index(vars, v); - if (index < vars->user_map_count) file->base_map_id = v; - else file->base_map_id = mapid_file; + if (index < vars->user_map_count) file->settings.base_map_id = v; + else file->settings.base_map_id = mapid_file; } }break; } } } -COMMAND_DECL(build){ - ProfileMomentFunction(); - USE_VARS(vars); - USE_MEM(mem); - USE_WORKING_SET(working_set); - USE_STYLE(style); - USE_LIVE_SET(live_set); - USE_PANEL(panel); - - char *buffer_name = "*cli process*"; - char *path = "..\\misc"; - char *script = "test"; - +internal void +build(System_Functions *system, Mem_Options *mem, + App_Vars *vars, Working_Set *working_set, + Font_Set *font_set, Style *style, + Live_Views *live_set, Exchange *exchange, + Panel *panel, Command_Data *command, + char *buffer_name, i32 buffer_name_len, + char *path, i32 path_len, + char *script, i32 script_len, + b32 overlap_with_conflict){ + if (buffer_name == 0 || path == 0 || script == 0){ + return; + } + if (vars->cli_processes.count < vars->cli_processes.max){ Editing_File *file = working_set_contains(working_set, make_string_slowly(buffer_name)); i32 index; - + if (!file){ Get_File_Result get_file = working_set_get_available_file(working_set); file = get_file.file; @@ -1571,24 +1693,26 @@ COMMAND_DECL(build){ i32 proc_count = vars->cli_processes.count; for (i32 i = 0; i < proc_count; ++i){ if (vars->cli_processes.procs[i].out_file == file){ - vars->cli_processes.procs[i].out_file = 0; + if (overlap_with_conflict) + vars->cli_processes.procs[i].out_file = 0; + else file = 0; + break; } } - index = (int)(file - vars->working_set.files); + index = (i32)(file - vars->working_set.files); } if (file){ - file_create_super_locked(system, mem, file, buffer_name, style->font); - table_add(&working_set->table, file->live_name, index); + file_create_super_locked(system, mem, file, buffer_name, font_set, style->font_id); + table_add(&working_set->table, file->state.live_name, index); View *new_view = live_set_alloc_view(live_set, mem); - view_replace_major(system, new_view, panel, live_set); + view_replace_major(system, exchange, new_view, panel, live_set); File_View *file_view = file_view_init(new_view, &vars->layout); - view_set_file(system, - file_view, file, style, - vars->hooks[hook_open_file], command, app_links); - new_view->map = app_get_map(vars, file->base_map_id); + view_set_file(system, file_view, file, font_set, style, + vars->hooks[hook_open_file], command, &app_links); + new_view->map = app_get_map(vars, file->settings.base_map_id); i32 i = vars->cli_processes.count++; CLI_Process *proc = vars->cli_processes.procs + i; @@ -1606,6 +1730,124 @@ COMMAND_DECL(build){ } } +COMMAND_DECL(build){ + ProfileMomentFunction(); + USE_VARS(vars); + USE_MEM(mem); + USE_WORKING_SET(working_set); + USE_STYLE(style); + USE_LIVE_SET(live_set); + USE_PANEL(panel); + USE_EXCHANGE(exchange); + USE_FONT_SET(font_set); + + char *buffer_name = 0; + char *path = 0; + char *script = 0; + + int buffer_name_len = 0; + int path_len = 0; + int script_len = 0; + b32 overlap_with_conflict = 1; + + Command_Parameter *end = param_stack_end(&command->part); + Command_Parameter *param = param_stack_first(&command->part, end); + for (; param < end; param = param_next(param, end)){ + int p = dynamic_to_int(¶m->param.param); + switch (p){ + case par_target_buffer_name: + { + if (buffer_name == 0){ + char *new_buffer_name = dynamic_to_string(¶m->param.value, &buffer_name_len); + if (new_buffer_name){ + buffer_name = new_buffer_name; + } + } + }break; + + case par_cli_path: + { + if (path == 0){ + char *new_cli_path = dynamic_to_string(¶m->param.value, &path_len); + if (new_cli_path){ + path = new_cli_path; + } + } + }break; + + case par_cli_command: + { + if (script == 0){ + char *new_command = dynamic_to_string(¶m->param.value, &script_len); + if (new_command){ + script = new_command; + } + } + }break; + + case par_cli_overlap_with_conflict: + { + overlap_with_conflict = dynamic_to_int(¶m->param.value); + }break; + } + } + + build(system, mem, vars, working_set, + font_set, style, live_set, exchange, + panel, command, + buffer_name, buffer_name_len, + path, path_len, + script, script_len, + overlap_with_conflict); +} + +COMMAND_DECL(build_here){ + ProfileMomentFunction(); + USE_VARS(vars); + USE_MEM(mem); + USE_WORKING_SET(working_set); + USE_STYLE(style); + USE_LIVE_SET(live_set); + USE_PANEL(panel); + USE_EXCHANGE(exchange); + USE_FONT_SET(font_set); + + b32 overlap_with_conflict = 0; + + char *buffer_name = "*compilation*"; + int buffer_name_len = sizeof("*compilation*")-1; + + char path_space[512]; + String path = make_fixed_width_string(path_space); + path.size = app_links.directory_get_hot(command, path.str, path.memory_size); + + char dir_space[512]; + String dir = make_fixed_width_string(dir_space); + dir.size = app_links.directory_get_hot(command, dir.str, dir.memory_size); + + for (;;){ + if (app_links.directory_has_file(dir, "build.bat")){ + if (append(&dir, "build")){ + break; + } + } + + if (app_links.directory_cd(&dir, "..") == 0){ + copy(&dir, "build"); + break; + } + } + terminate_with_null(&dir); + + build(system, mem, vars, working_set, + font_set, style, live_set, exchange, + panel, command, + buffer_name, buffer_name_len, + path.str, path.size, + dir.str, dir.size, + overlap_with_conflict); +} + internal void update_command_data(App_Vars *vars, Command_Data *cmd){ Command_Data command_data; @@ -1623,6 +1865,7 @@ update_command_data(App_Vars *vars, Command_Data *cmd){ command_data.key = cmd->key; command_data.part = cmd->part; command_data.system = cmd->system; + command_data.exchange = cmd->exchange; *cmd = command_data; } @@ -1667,7 +1910,7 @@ extern "C"{ base->type = 1; base->inline_string.str = result; base->inline_string.len = len; - return result; + return(result); } CLEAR_PARAMETERS_SIG(external_clear_parameters){ @@ -1682,33 +1925,48 @@ extern "C"{ File_View *view = view_to_file_view(cmd->view); if (view){ Editing_File *file = view->file; - if (file && !file->is_dummy){ + if (file && !file->state.is_dummy){ #if BUFFER_EXPERIMENT_SCALPEL <= 0 Working_Set *working_set = cmd->working_set; buffer.file_id = (int)(file - working_set->files); - buffer.size = file->buffer.size; - buffer.file_name_len = file->source_path.size; - buffer.buffer_name_len = file->live_name.size; - buffer.file_name = file->source_path.str; - buffer.buffer_name = file->live_name.str; - buffer.file_cursor_pos = file->cursor_pos; - buffer.is_lexed = file->tokens_exist; - buffer.map_id = file->base_map_id; + buffer.size = file->state.buffer.size; + buffer.file_name_len = file->state.source_path.size; + buffer.buffer_name_len = file->state.live_name.size; + buffer.file_name = file->state.source_path.str; + buffer.buffer_name = file->state.live_name.str; + buffer.file_cursor_pos = file->state.cursor_pos; + buffer.is_lexed = file->settings.tokens_exist; + buffer.map_id = file->settings.base_map_id; #endif } } - return buffer; + return(buffer); + } + + DIRECTORY_GET_HOT_SIG(external_directory_get_hot){ + Command_Data *cmd = (Command_Data*)cmd_context; + Hot_Directory *hot = &cmd->vars->hot_directory; + i32 copy_max = max - 1; + hot_directory_clean_end(hot); + if (copy_max > hot->string.size) + copy_max = hot->string.size; + memcpy(buffer, hot->string.str, copy_max); + buffer[copy_max] = 0; + return(copy_max); } } inline void -app_links_init(){ +app_links_init(System_Functions *system){ app_links.exec_command_keep_stack = external_exec_command_keep_stack; app_links.push_parameter = external_push_parameter; app_links.push_memory = external_push_memory; app_links.clear_parameters = external_clear_parameters; app_links.get_active_buffer = external_get_active_buffer; + app_links.directory_get_hot = external_directory_get_hot; + app_links.directory_has_file = system->directory_has_file; + app_links.directory_cd = system->directory_cd; } #if FRED_INTERNAL @@ -1797,7 +2055,9 @@ setup_file_commands(Command_Map *commands, Partition *part, Key_Codes *codes, Co map_add(commands, 's', MDFR_CTRL, command_save); map_add(commands, 'w', MDFR_CTRL, command_interactive_save_as); +#if UseFileHistoryDump map_add(commands, 'h', MDFR_ALT, command_save_history); +#endif } internal void @@ -1818,7 +2078,7 @@ setup_top_commands(Command_Map *commands, Partition *part, Key_Codes *codes, Com map_add(commands, 'i', MDFR_CTRL, command_interactive_switch_buffer); map_add(commands, 'c', MDFR_ALT, command_open_color_tweaker); map_add(commands, 'x', MDFR_ALT, command_open_menu); - map_add(commands, 'm', MDFR_ALT, command_build); + map_add(commands, 'm', MDFR_ALT, command_build_here); } internal void @@ -1894,6 +2154,7 @@ setup_command_table(){ SET(cursor_mark_swap); SET(open_menu); SET(set_settings); + SET(build); #undef SET } @@ -1963,15 +2224,15 @@ live_file_draw_helper(Render_Target *target, Working_Set *working_set, file_i < working_set->file_index_count; ++file_i){ Editing_File *file = &working_set->files[file_i]; - if (file->live_name.str && - (string->size == 0 || has_substr_unsensitive(file->live_name, *string))){ + if (file->state.live_name.str && + (string->size == 0 || has_substr_unsensitive(file->state.live_name, *string))){ if (is_first_string){ is_first_string = 0; } else{ intbar_draw_string(target, bar, str_comma, bar->style.base_color); } - intbar_draw_string(target, bar, file->live_name, bar->style.base_color); + intbar_draw_string(target, bar, file->state.live_name, bar->style.base_color); } } intbar_draw_string(target, bar, str_close_bracket, bar->style.base_color); @@ -1985,12 +2246,12 @@ app_hardcode_styles(App_Vars *vars){ Style *styles, *style; styles = vars->styles.styles; style = styles; - - Render_Font *fonts = vars->fonts.fonts; + + i16 fonts = 1; ///////////////// style_set_name(style, make_lit_string("4coder")); - style->font = fonts + 1; + style->font_id = fonts + 4; style->main.back_color = 0xFF0C0C0C; style->main.margin_color = 0xFF181818; @@ -2031,12 +2292,12 @@ app_hardcode_styles(App_Vars *vars){ ///////////////// *style = *(style-1); style_set_name(style, make_lit_string("4coder-mono")); - style->font = fonts; + style->font_id = fonts; ++style; ///////////////// style_set_name(style, make_lit_string("Handmade Hero")); - style->font = fonts; + style->font_id = fonts; style->main.back_color = 0xFF161616; style->main.margin_color = 0xFF262626; @@ -2077,7 +2338,7 @@ app_hardcode_styles(App_Vars *vars){ ///////////////// style_set_name(style, make_lit_string("Twilight")); - style->font = fonts + 2; + style->font_id = fonts + 2; style->main.back_color = 0xFF090D12; style->main.margin_color = 0xFF1A2634; @@ -2117,7 +2378,7 @@ app_hardcode_styles(App_Vars *vars){ ///////////////// style_set_name(style, make_lit_string("Wolverine")); - style->font = fonts + 1; + style->font_id = fonts + 1; style->main.back_color = 0xFF070711; style->main.margin_color = 0xFF111168; @@ -2157,7 +2418,7 @@ app_hardcode_styles(App_Vars *vars){ ///////////////// style_set_name(style, make_lit_string("stb")); - style->font = fonts + 3; + style->font_id = fonts + 3; style->main.back_color = 0xFFD6D6D6; style->main.margin_color = 0xFF9E9E9E; @@ -2201,20 +2462,6 @@ app_hardcode_styles(App_Vars *vars){ vars->style.font_changed = 0; } -internal bool32 -app_load_font(Render_Target *target, System_Functions *system, - Render_Font *font, char *filename, i32 size, void *memory, - i32 *used, i32 tab_width, String name){ - if (font_load(target, system, font, filename, size, memory, - font_predict_size(size), used, tab_width)){ - font->loaded = 1; - font->name_[ArrayCount(font->name_)-1] = 0; - font->name = make_string(font->name_, 0, ArrayCount(font->name_)-1); - copy(&font->name, name); - } - return font->loaded; -} - char *_4coder_get_extension(const char *filename, int len, int *extension_len){ char *c = (char*)(filename + len - 1); char *end = c; @@ -2238,7 +2485,7 @@ bool _4coder_str_match(const char *a, int len_a, const char *b, int len_b){ #define literal(s) s, (sizeof(s) - 1) HOOK_SIG(default_open_file_hook){ - Buffer_Summary buffer = app.get_active_buffer(cmd_context); + Buffer_Summary buffer = app->get_active_buffer(cmd_context); int treat_as_code = 0; @@ -2251,16 +2498,16 @@ HOOK_SIG(default_open_file_hook){ else if (_4coder_str_match(extension, extension_len, literal("hpp"))) treat_as_code = 1; } - app.push_parameter(cmd_context, dynamic_int(par_lex_as_cpp_file), dynamic_int(treat_as_code)); - app.push_parameter(cmd_context, dynamic_int(par_wrap_lines), dynamic_int(!treat_as_code)); - app.push_parameter(cmd_context, dynamic_int(par_key_mapid), dynamic_int(mapid_file)); + app->push_parameter(cmd_context, dynamic_int(par_lex_as_cpp_file), dynamic_int(treat_as_code)); + app->push_parameter(cmd_context, dynamic_int(par_wrap_lines), dynamic_int(!treat_as_code)); + app->push_parameter(cmd_context, dynamic_int(par_key_mapid), dynamic_int(mapid_file)); - app.exec_command_keep_stack(cmd_context, cmdid_set_settings); - app.clear_parameters(cmd_context); + app->exec_command_keep_stack(cmd_context, cmdid_set_settings); + app->clear_parameters(cmd_context); } -external App_Init_Sig(app_init){ - app_links_init(); +App_Init_Sig(app_init){ + app_links_init(system); Partition _partition = partition_open(memory->vars_memory, memory->vars_memory_size); App_Vars *vars = push_struct(&_partition, App_Vars); @@ -2269,6 +2516,7 @@ external App_Init_Sig(app_init){ vars->config_api = api; vars->mem.part = _partition; Partition *partition = &vars->mem.part; + target->partition = partition; general_memory_open(&vars->mem.general, memory->target_memory, memory->target_memory_size); i32 panel_max_count = vars->layout.panel_max_count = 16; @@ -2295,9 +2543,10 @@ external App_Init_Sig(app_init){ sizeof(Color_View), sizeof(Interactive_View), #if FRED_INTERNAL - sizeof(Debug_View) + sizeof(Debug_View), #endif }; + i32 view_chunk_size = 0; for (i32 i = 0; i < ArrayCount(view_sizes); ++i){ view_chunk_size = Max(view_chunk_size, view_sizes[i]); @@ -2449,55 +2698,63 @@ external App_Init_Sig(app_init){ if (vars->hooks[hook_open_file] == 0){ vars->hooks[hook_open_file] = default_open_file_hook; } + + vars->font_set = &target->font_set; - vars->fonts.max = 6; - vars->fonts.fonts = push_array(partition, Render_Font, vars->fonts.max); + font_set_init(vars->font_set, partition, 16, 4); { - i32 font_count = 0; - i32 memory_used; + struct Font_Setup{ + char *c_file_name; + i32 file_name_len; + char *c_name; + i32 name_len; + i32 pt_size; + }; + +#define LitStr(n) n, sizeof(n)-1 - memory_used = 0; - app_load_font(target, system, - vars->fonts.fonts + font_count++, "liberation-mono.ttf", 17, - partition_current(partition), - &memory_used, 4, make_lit_string("liberation mono")); - push_block(partition, memory_used); + Font_Setup font_setup[] = { + {LitStr("liberation-mono.ttf"), + LitStr("liberation mono"), + 16}, + + {LitStr("Hack-Regular.ttf"), + LitStr("hack"), + 16}, + + {LitStr("CutiveMono-Regular.ttf"), + LitStr("cutive mono"), + 16}, + + {LitStr("Inconsolata-Regular.ttf"), + LitStr("inconsolata"), + 16}, + + {LitStr("LiberationSans-Regular.ttf"), + LitStr("liberation sans"), + 16}, + + }; + i32 font_count = ArrayCount(font_setup); - memory_used = 0; - app_load_font(target, system, - vars->fonts.fonts + font_count++, "LiberationSans-Regular.ttf", 17, - partition_current(partition), - &memory_used, 4, make_lit_string("liberation sans")); - push_block(partition, memory_used); - - memory_used = 0; - app_load_font(target, system, - vars->fonts.fonts + font_count++, "Hack-Regular.ttf", 17, - partition_current(partition), - &memory_used, 4, make_lit_string("hack")); - push_block(partition, memory_used); - - memory_used = 0; - app_load_font(target, system, - vars->fonts.fonts + font_count++, "CutiveMono-Regular.ttf", 17, - partition_current(partition), - &memory_used, 4, make_lit_string("cutive mono")); - push_block(partition, memory_used); - - memory_used = 0; - app_load_font(target, system, - vars->fonts.fonts + font_count++, "Inconsolata-Regular.ttf", 17, - partition_current(partition), - &memory_used, 4, make_lit_string("inconsolata")); - push_block(partition, memory_used); + for (i32 i = 0; i < font_count; ++i){ + String file_name = make_string(font_setup[i].c_file_name, + font_setup[i].file_name_len); + String name = make_string(font_setup[i].c_name, + font_setup[i].name_len); + i32 pt_size = font_setup[i].pt_size; + + font_set_add(partition, vars->font_set, file_name, name, pt_size); + } +#if 0 if (vars->config_api.set_extra_font){ Extra_Font extra; extra.size = 17; vars->config_api.set_extra_font(&extra); memory_used = 0; - if (app_load_font(target, system, + if (app_load_font(target, vars->fonts.fonts + font_count, extra.file_name, extra.size, partition_current(partition), &memory_used, 4, make_string_slowly(extra.font_name))){ @@ -2510,6 +2767,7 @@ external App_Init_Sig(app_init){ } vars->fonts.count = font_count; +#endif } // NOTE(allen): file setup @@ -2550,8 +2808,8 @@ external App_Init_Sig(app_init){ AllowLocal(panel_count); panel_init(&panels[0]); - vars->hot_dir_base = make_fixed_width_string(vars->hot_dir_base_); - hot_directory_init(system, &vars->hot_directory, vars->hot_dir_base); + String hdbase = make_fixed_width_string(vars->hot_dir_base_); + hot_directory_init(&vars->hot_directory, hdbase, current_directory); vars->mini_str = make_string((char*)vars->mini_buffer, 0, 512); @@ -2561,16 +2819,22 @@ external App_Init_Sig(app_init){ vars->cli_processes.procs = push_array(partition, CLI_Process, max_children); vars->cli_processes.max = max_children; vars->cli_processes.count = 0; + + // NOTE(allen): sys app binding setup + vars->sys_app_max = exchange->file.max; + vars->sys_app_count = 0; + vars->sys_app_bindings = (Sys_App_Binding*)push_array(partition, Sys_App_Binding, vars->sys_app_max); return 1; } -external App_Step_Sig(app_step){ +App_Step_Sig(app_step){ ProfileStart(OS_syncing); Application_Step_Result app_result = {}; app_result.redraw = force_redraw; App_Vars *vars = (App_Vars*)memory->vars_memory; + target->partition = &vars->mem.part; if (first_step || !time_step){ app_result.redraw = 1; @@ -2589,13 +2853,12 @@ external App_Step_Sig(app_step){ for (i32 i = 0; i < vars->working_set.file_index_count; ++i){ Editing_File *file = vars->working_set.files + i; - if (!file->is_dummy){ - Time_Stamp time_stamp; - time_stamp = system->file_time_stamp(make_c_str(file->source_path)); + if (!file->state.is_dummy){ + u64 time_stamp = system->file_time_stamp(make_c_str(file->state.source_path)); - if (time_stamp.success){ - file->last_sys_write_time = time_stamp.time; - if (file->last_sys_write_time != file->last_4ed_write_time){ + if (time_stamp > 0){ + file->state.last_sys_write_time = time_stamp; + if (file->state.last_sys_write_time != file->state.last_4ed_write_time){ app_result.redraw = 1; } } @@ -2613,15 +2876,16 @@ external App_Step_Sig(app_step){ for (i32 i = 0; i < count; ++i){ CLI_Process *proc = vars->cli_processes.procs + i; Editing_File *out_file = proc->out_file; + + if (out_file != 0){ + i32 new_cursor = out_file->state.cursor_pos; - i32 new_cursor = out_file->cursor_pos; - for (system->cli_begin_update(&proc->cli); - system->cli_update_step(&proc->cli, dest, max, &amount);){ - if (out_file){ + for (system->cli_begin_update(&proc->cli); + system->cli_update_step(&proc->cli, dest, max, &amount);){ amount = eol_in_place_convert_in(dest, amount); Edit_Spec spec = {}; spec.step.type = ED_NORMAL; - spec.step.edit.start = buffer_size(&out_file->buffer); + spec.step.edit.start = buffer_size(&out_file->state.buffer); spec.step.edit.end = spec.step.edit.start; spec.step.edit.len = amount; spec.step.pre_pos = new_cursor; @@ -2632,21 +2896,21 @@ external App_Step_Sig(app_step){ app_result.redraw = 1; new_cursor = spec.step.post_pos; } - } - if (system->cli_end_update(&proc->cli)){ - *proc = vars->cli_processes.procs[--count]; - --i; - } + if (system->cli_end_update(&proc->cli)){ + *proc = vars->cli_processes.procs[--count]; + --i; + } - Panel *panel = vars->layout.panels; - i32 panel_count = vars->layout.panel_count; - for (i32 i = 0; i < panel_count; ++i, ++panel){ - View *view = panel->view; - if (view && view->is_minor) view = view->major; - File_View *fview = view_to_file_view(view); - if (fview){ - view_cursor_move(fview, new_cursor); + Panel *panel = vars->layout.panels; + i32 panel_count = vars->layout.panel_count; + for (i32 i = 0; i < panel_count; ++i, ++panel){ + View *view = panel->view; + if (view && view->is_minor) view = view->major; + File_View *fview = view_to_file_view(view); + if (fview){ + view_cursor_move(fview, new_cursor); + } } } } @@ -2922,6 +3186,7 @@ external App_Step_Sig(app_step){ command_data.style = &vars->style; command_data.delay = &vars->delay; command_data.vars = vars; + command_data.exchange = exchange; command_data.screen_width = target->width; command_data.screen_height = target->height; command_data.system = system; @@ -2930,7 +3195,7 @@ external App_Step_Sig(app_step){ command_data.part = partition_sub_part(&vars->mem.part, 16 << 10); if (first_step && vars->hooks[hook_start]){ - vars->hooks[hook_start](&command_data, app_links); + vars->hooks[hook_start](&command_data, &app_links); command_data.part.pos = 0; } @@ -3024,7 +3289,7 @@ external App_Step_Sig(app_step){ if (panel == mouse_panel){ input.mouse = mouse_data; } - if (view_->do_view(system, view_, panel->inner, active_view, + if (view_->do_view(system, exchange, view_, panel->inner, active_view, VMSG_STEP, 0, &input, &active_input)){ app_result.redraw = 1; } @@ -3053,8 +3318,9 @@ external App_Step_Sig(app_step){ case DACT_OPEN: { command_data.view = (View*) - app_open_file(system, - vars, mem, panel, working_set, string, style, live_set, &command_data); + app_open_file(system, vars, exchange, + live_set, working_set, panel, + &command_data, string->str, string->size); }break; case DACT_SAVE_AS: @@ -3065,8 +3331,8 @@ external App_Step_Sig(app_step){ if (!fview && view->is_minor) fview = view_to_file_view(view->major); if (fview){ Editing_File *file = fview->file; - if (file && !file->is_dummy){ - file_save_and_set_names(system, &vars->mem.part, file, string->str); + if (file && !file->state.is_dummy){ + file_save_and_set_names(system, exchange, mem, file, string->str); } } }break; @@ -3074,28 +3340,29 @@ external App_Step_Sig(app_step){ case DACT_SAVE: { Editing_File *file = working_set_lookup_file(working_set, *string); - if (!file->is_dummy){ - file_save(system, &vars->mem.part, file, file->source_path.str); + if (!file->state.is_dummy){ + file_save(system, exchange, mem, file, file->state.source_path.str); } }break; case DACT_NEW: { Get_File_Result file = working_set_get_available_file(working_set); - file_create_empty(system, mem, file.file, string->str, style->font); - table_add(&working_set->table, file.file->source_path, file.index); + file_create_empty(system, mem, file.file, string->str, + vars->font_set, style->font_id); + table_add(&working_set->table, file.file->state.source_path, file.index); View *new_view = live_set_alloc_view(live_set, mem); - view_replace_major(system, new_view, panel, live_set); + view_replace_major(system, exchange, new_view, panel, live_set); File_View *file_view = file_view_init(new_view, &vars->layout); command_data.view = (View*)file_view; - view_set_file(system, - file_view, file.file, style, - vars->hooks[hook_open_file], &command_data, app_links); - new_view->map = app_get_map(vars, file.file->base_map_id); + view_set_file(system, file_view, file.file, vars->font_set, style, + vars->hooks[hook_open_file], &command_data, &app_links); + new_view->map = app_get_map(vars, file.file->settings.base_map_id); #if BUFFER_EXPERIMENT_SCALPEL <= 0 - if (file.file->tokens_exist) file_first_lex_parallel(system, general, file.file); + if (file.file->settings.tokens_exist) + file_first_lex_parallel(system, general, file.file); #endif }break; @@ -3104,16 +3371,15 @@ external App_Step_Sig(app_step){ Editing_File *file = working_set_lookup_file(working_set, *string); if (file){ View *new_view = live_set_alloc_view(live_set, mem); - view_replace_major(system, new_view, panel, live_set); + view_replace_major(system, exchange, new_view, panel, live_set); File_View *file_view = file_view_init(new_view, &vars->layout); command_data.view = (View*)file_view; - view_set_file(system, - file_view, file, style, - vars->hooks[hook_open_file], &command_data, app_links); + view_set_file(system, file_view, file, vars->font_set, style, + vars->hooks[hook_open_file], &command_data, &app_links); - new_view->map = app_get_map(vars, file->base_map_id); + new_view->map = app_get_map(vars, file->settings.base_map_id); } }break; @@ -3121,8 +3387,8 @@ external App_Step_Sig(app_step){ { Editing_File *file = working_set_lookup_file(working_set, *string); if (file){ - table_remove(&working_set->table, file->source_path); - kill_file(system, general, file, live_set, &vars->layout); + table_remove(&working_set->table, file->state.source_path); + kill_file(system, exchange, general, file, live_set, &vars->layout); } }break; @@ -3134,25 +3400,24 @@ external App_Step_Sig(app_step){ case SYNC_BEHIND_OS: case SYNC_GOOD: { - table_remove(&working_set->table, file->source_path); - kill_file(system, general, file, live_set, &vars->layout); - view_remove_minor(system, panel, live_set); + table_remove(&working_set->table, file->state.source_path); + kill_file(system, exchange, general, file, live_set, &vars->layout); + view_remove_minor(system, exchange, panel, live_set); }break; case SYNC_UNSAVED: { View *new_view = live_set_alloc_view(live_set, mem); - view_replace_minor(system, new_view, panel, live_set); + view_replace_minor(system, exchange, new_view, panel, live_set); new_view->map = &vars->map_ui; Interactive_View *int_view = - interactive_view_init(system, - new_view, &vars->hot_directory, style, - working_set, &vars->delay); + interactive_view_init(system, new_view, &vars->hot_directory, style, + working_set, vars->font_set, &vars->delay); int_view->interaction = INTV_SURE_TO_KILL_INTER; int_view->action = INTV_SURE_TO_KILL; copy(&int_view->query, "Are you sure?"); - copy(&int_view->dest, file->live_name); + copy(&int_view->dest, file->state.live_name); }break; default: Assert(!"invalid path"); @@ -3162,17 +3427,17 @@ external App_Step_Sig(app_step){ case DACT_CLOSE_MINOR: { - view_remove_minor(system, panel, live_set); + view_remove_minor(system, exchange, panel, live_set); }break; case DACT_CLOSE_MAJOR: { - view_remove_major(system, panel, live_set); + view_remove_major(system, exchange, panel, live_set); }break; case DACT_THEME_OPTIONS: { - open_theme_options(system, vars, live_set, mem, panel); + open_theme_options(system, exchange, vars, live_set, mem, panel); }break; } } @@ -3192,12 +3457,12 @@ external App_Step_Sig(app_step){ prev.x1 != inner.x1 || prev.y1 != inner.y1){ View *view = panel->view; if (view){ - view->do_view(system, + view->do_view(system, exchange, view, inner, active_view, VMSG_RESIZE, 0, &dead_input, &active_input); view = (view->is_minor)?view->major:0; if (view){ - view->do_view(system, + view->do_view(system, exchange, view, inner, active_view, VMSG_RESIZE, 0, &dead_input, &active_input); } @@ -3215,9 +3480,13 @@ external App_Step_Sig(app_step){ Editing_File *file = vars->working_set.files; for (i32 i = vars->working_set.file_index_count; i > 0; --i, ++file){ - if (buffer_good(&file->buffer) && !file->is_dummy){ - file_measure_starts_widths(system, - &vars->mem.general, &file->buffer, vars->style.font); + if (buffer_good(&file->state.buffer) && !file->state.is_dummy){ + Render_Font *font = get_font_info(vars->font_set, vars->style.font_id)->font; + float *advance_data = 0; + if (font) advance_data = font->advance_data; + + file_measure_starts_widths(system, &vars->mem.general, + &file->state.buffer, advance_data); } } @@ -3225,12 +3494,12 @@ external App_Step_Sig(app_step){ for (i32 panel_i = vars->layout.panel_count; panel_i > 0; --panel_i, ++panel){ View *view = panel->view; if (view){ - view->do_view(system, + view->do_view(system, exchange, view, panel->inner, active_view, VMSG_STYLE_CHANGE, 0, &dead_input, &active_input); view = (view->is_minor)?view->major:0; if (view){ - view->do_view(system, + view->do_view(system, exchange, view, panel->inner, active_view, VMSG_STYLE_CHANGE, 0, &dead_input, &active_input); } @@ -3238,10 +3507,72 @@ external App_Step_Sig(app_step){ } } ProfileEnd(style_change); + + // NOTE(allen): processing bindings between system and application + ProfileStart(sys_app_bind_processing); + for (i32 i = 0; i < vars->sys_app_count; ++i){ + Sys_App_Binding *binding; + b32 remove = 0; + binding = vars->sys_app_bindings + i; + + byte *data; + i32 size, max; + + if (exchange_file_ready(exchange, binding->sys_id, &data, &size, &max)){ + Editing_File *ed_file = vars->working_set.files + binding->app_id; + char *filename = exchange_file_filename(exchange, binding->sys_id); + if (data){ + String val = make_string((char*)data, size); + file_create_from_string(system, &vars->mem, ed_file, filename, + vars->font_set, vars->style.font_id, val); + + if (ed_file->settings.tokens_exist) + file_first_lex_parallel(system, &vars->mem.general, ed_file); + + for (File_View_Iter iter = file_view_iter_init(&vars->layout, ed_file, 0); + file_view_iter_good(iter); + iter = file_view_iter_next(iter)){ + view_file_loaded_init(system, iter.view, 0); + } + } + else{ + file_create_empty(system, &vars->mem, ed_file, filename, + vars->font_set, vars->style.font_id); + } + + exchange_free_file(exchange, binding->sys_id); + remove = 1; + } + + if (exchange_file_save_complete(exchange, binding->sys_id, &data, &size, &max)){ + Assert(remove == 0); + + if (data){ + general_memory_free(&vars->mem.general, data); + exchange_clear_file(exchange, binding->sys_id); + } + + Editing_File *file = get_file(&vars->working_set, binding->app_id); + if (file){ + file_synchronize_times(system, file, file->state.source_path.str); + } + + exchange_free_file(exchange, binding->sys_id); + remove = 1; + } + + if (remove){ + *binding = vars->sys_app_bindings[--vars->sys_app_count]; + --i; + } + } + ProfileEnd(sys_app_bind_processing); ProfileStart(redraw); if (mouse_panel != vars->prev_mouse_panel) app_result.redraw = 1; if (app_result.redraw){ + begin_render_section(target); + target->clip_top = -1; draw_push_clip(target, rect_from_target(target)); @@ -3261,7 +3592,8 @@ external App_Step_Sig(app_step){ if (view){ Assert(view->do_view); draw_push_clip(target, panel->inner); - view->do_view(system, view, panel->inner, active_view, + view->do_view(system, exchange, + view, panel->inner, active_view, VMSG_DRAW, target, &dead_input, &active_input); draw_pop_clip(target); } @@ -3281,6 +3613,8 @@ external App_Step_Sig(app_step){ draw_rectangle(target, i32R(full.x0, inner.y0, inner.x0, inner.y1), margin_color); draw_rectangle(target, i32R(inner.x1, inner.y0, full.x1, inner.y1), margin_color); } + + end_render_section(target); } ProfileEnd(redraw); @@ -3314,5 +3648,30 @@ external App_Step_Sig(app_step){ return app_result; } +internal +App_Alloc_Sig(app_alloc){ + Mem_Options *mem = (Mem_Options*)(handle); + void *result = general_memory_allocate(&mem->general, size, 0); + return(result); +} + +internal +App_Free_Sig(app_free){ + Mem_Options *mem = (Mem_Options*)(handle); + general_memory_free(&mem->general, block); +} + +external App_Get_Functions_Sig(app_get_functions){ + App_Functions result = {}; + + result.init = app_init; + result.step = app_step; + + result.alloc = app_alloc; + result.free = app_free; + + return(result); +} + // BOTTOM diff --git a/4ed.h b/4ed.h index 30b24553..c417324c 100644 --- a/4ed.h +++ b/4ed.h @@ -31,10 +31,10 @@ enum Key_Control{ }; struct Key_Event_Data{ - u16 keycode; - u16 loose_keycode; - u16 character; - u16 character_no_caps_lock; + u8 keycode; + //u8 apply_shift; + u8 character; + u8 character_no_caps_lock; }; struct Key_Input_Data{ @@ -97,14 +97,44 @@ struct Clipboard_Contents{ i32 size; }; -struct Thread_Context; +#define FileNameMax (1 << 9) + +struct File_Slot{ + File_Slot *next, *prev; + byte *data; + i32 size, max; + char *filename; + i32 filename_len; + u32 flags; +}; + +enum File_Exchange_Flag{ + FEx_Request = 0x1, + FEx_Ready = 0x2, + FEx_Not_Exist = 0x4, + FEx_Save = 0x8, + FEx_Save_Complete = 0x10 +}; + +struct File_Exchange{ + File_Slot available, active, free_list; + File_Slot *files; + i32 num_active, max; +}; + +struct Exchange{ + Thread_Exchange thread; + File_Exchange file; +}; #define App_Init_Sig(name) \ b32 name(System_Functions *system, \ Render_Target *target, \ Application_Memory *memory, \ + Exchange *exchange, \ Key_Codes *loose_codes, \ Clipboard_Contents clipboard, \ + String current_directory, \ Config_API api) typedef App_Init_Sig(App_Init); @@ -131,16 +161,29 @@ struct Application_Step_Result{ Mouse_State *mouse, \ Render_Target *target, \ Application_Memory *memory, \ + Exchange *exchange, \ Clipboard_Contents clipboard, \ b32 time_step, b32 first_step, b32 force_redraw) typedef App_Step_Sig(App_Step); +#define App_Alloc_Sig(name) void *name(void *handle, i32 size) +typedef App_Alloc_Sig(App_Alloc); + +#define App_Free_Sig(name) void name(void *handle, void *block) +typedef App_Free_Sig(App_Free); + struct App_Functions{ App_Init *init; App_Step *step; + + App_Alloc *alloc; + App_Free *free; }; +#define App_Get_Functions_Sig(name) App_Functions name() +typedef App_Get_Functions_Sig(App_Get_Functions); + #endif // BOTTOM diff --git a/4ed_app_target.cpp b/4ed_app_target.cpp index 124baa15..e21e0d49 100644 --- a/4ed_app_target.cpp +++ b/4ed_app_target.cpp @@ -17,11 +17,11 @@ #include "4cpp_types.h" #define FCPP_STRING_IMPLEMENTATION -#include "4cpp_string.h" +#include "4coder_string.h" #include "4ed_mem.cpp" - #include "4ed_math.cpp" + #include "4coder_custom.h" #include "4ed_system.h" #include "4ed_rendering.h" @@ -32,6 +32,8 @@ #define FCPP_LEXER_IMPLEMENTATION #include "4cpp_lexer.h" +#include "4ed_exchange.cpp" +#include "4ed_font_set.cpp" #include "4ed_rendering_helper.cpp" #include "4ed_command.cpp" #include "4ed_layout.cpp" diff --git a/4ed_color_view.cpp b/4ed_color_view.cpp index a50a82e1..6c7b88fe 100644 --- a/4ed_color_view.cpp +++ b/4ed_color_view.cpp @@ -15,6 +15,7 @@ enum Color_View_Mode{ CV_MODE_EXPORT_FILE, CV_MODE_IMPORT, CV_MODE_EXPORT, + CV_MODE_IMPORT_WAIT, CV_MODE_ADJUSTING }; @@ -104,7 +105,7 @@ struct Color_View{ Style *main_style; Style_Library *styles; File_View *hot_file_view; - Font_Set *fonts; + Font_Set *font_set; u32 *palette; Working_Set *working_set; i32 palette_size; @@ -112,9 +113,10 @@ struct Color_View{ UI_State state; Super_Color color; Color_Highlight highlight; - bool32 p4c_only; + b32 p4c_only; Style_Library inspecting_styles; - bool8 import_export_check[64]; + b8 import_export_check[64]; + i32 import_file_id; }; inline Color_View* @@ -188,10 +190,11 @@ draw_rgb_slider(Render_Target *target, Vec4 base, i32 channel, } internal void -do_label(UI_State *state, UI_Layout *layout, char *text, real32 height = 2.f){ +do_label(UI_State *state, UI_Layout *layout, char *text, f32 height = 2.f){ Style *style = state->style; - Render_Font *font = style->font; - i32_Rect label = layout_rect(layout, FLOOR32(font->height * height)); + i16 font_id = style->font_id; + i32 line_height = get_font_info(state->font_set, font_id)->height; + i32_Rect label = layout_rect(layout, FLOOR32(line_height * height)); if (!state->input_stage){ Render_Target *target = state->target; @@ -199,8 +202,8 @@ do_label(UI_State *state, UI_Layout *layout, char *text, real32 height = 2.f){ u32 fore = style->main.default_color; draw_rectangle(target, label, back); i32 height = label.y1 - label.y0; - draw_string(target, font, text, label.x0, - label.y0 + (height - font->height)/2, fore); + draw_string(target, font_id, text, label.x0, + label.y0 + (height - line_height)/2, fore); } } @@ -221,18 +224,18 @@ do_scroll_bar(UI_State *state, i32_Rect rect){ bottom_arrow.y1 = rect.y1; bottom_arrow.y0 = bottom_arrow.y1 - w; - real32 space_h = (real32)(bottom_arrow.y0 - top_arrow.y1); + f32 space_h = (f32)(bottom_arrow.y0 - top_arrow.y1); if (space_h <= w) return; i32 slider_h = w; - real32 view_hmin = 0; - real32 view_hmax = state->height - h; - real32 L = unlerp(view_hmin, state->view_y, view_hmax); + f32 view_hmin = 0; + f32 view_hmax = state->height - h; + f32 L = unlerp(view_hmin, state->view_y, view_hmax); - real32 slider_hmin = (real32)top_arrow.y1; - real32 slider_hmax = (real32)bottom_arrow.y0 - slider_h; - real32 S = lerp(slider_hmin, L, slider_hmax); + f32 slider_hmin = (f32)top_arrow.y1; + f32 slider_hmax = (f32)bottom_arrow.y0 - slider_h; + f32 S = lerp(slider_hmin, L, slider_hmax); i32_Rect slider; slider.x0 = rect.x0; @@ -244,16 +247,17 @@ do_scroll_bar(UI_State *state, i32_Rect rect){ if (state->input_stage){ state->view_y = - ui_do_vscroll_input(state, top_arrow, bottom_arrow, slider, - wid, state->view_y, (real32)state->font->height, + ui_do_vscroll_input(state, top_arrow, bottom_arrow, slider, wid, state->view_y, + (f32)(get_font_info(state->font_set, state->font_id)->height), slider_hmin, slider_hmax, view_hmin, view_hmax); } - else{ + else{ Render_Target *target = state->target; - real32 x0, y0, x1, y1, x2, y2; - real32 w_1_2 = w*.5f; - real32 w_1_3 = w*.333333f; - real32 w_2_3 = w*.666667f; + + f32 x0, y0, x1, y1, x2, y2; + f32 w_1_2 = w*.5f; + f32 w_1_3 = w*.333333f; + f32 w_2_3 = w*.666667f; UI_Style ui_style = get_ui_style(state->style); @@ -403,22 +407,24 @@ fill_buffer_color_channel(char *buffer, u8 x, Channel_Field_Type ftype){ } } -internal bool32 +internal b32 do_channel_field(i32 sub_id, Color_UI *ui, u8 *channel, Channel_Field_Type ftype, i32 y, u32 color, u32 back, i32 x0, i32 x1){ - bool32 result = 0; - Render_Target *target = ui->state.target; - Render_Font *font = ui->state.font; - + b32 result = 0; + + i16 font_id = ui->state.font_id; + i32 line_height = get_font_info(ui->state.font_set, font_id)->height; i32_Rect hit_region; hit_region.x0 = x0; hit_region.x1 = x1; hit_region.y0 = y; - hit_region.y1 = y + font->height; + hit_region.y1 = y + line_height; i32 digit_count; if (ftype == CF_DEC) digit_count = 3; else digit_count = 2; + + Render_Target *target = ui->state.target; if (ui->state.input_stage){ i32 indx; @@ -515,7 +521,7 @@ do_channel_field(i32 sub_id, Color_UI *ui, u8 *channel, Channel_Field_Type ftype } if (!ui->state.input_stage) - draw_string_mono(target, font, string_buffer, + draw_string_mono(target, font_id, string_buffer, (real32)x0 + 1, (real32)y, ui->hex_advance, color); @@ -688,8 +694,7 @@ do_palette(Color_UI *ui, i32_Rect rect){ if (!ui->state.input_stage){ Render_Target *target = ui->state.target; - Render_Font *font = style->font; - draw_string(target, font, "Global Palette: right click to save color", + draw_string(target, style->font_id, "Global Palette: right click to save color", layout.x, layout.rect.y0, style->main.default_color); } @@ -709,15 +714,16 @@ do_palette(Color_UI *ui, i32_Rect rect){ internal void do_sub_button(i32 id, Color_UI *ui, char *text){ - Render_Font *font = ui->state.font; - - i32_Rect rect = layout_rect(&ui->layout, font->height + 2); + i16 font_id = ui->state.font_id; + i32 line_height = get_font_info(ui->state.font_set, font_id)->height; + i32_Rect rect = layout_rect(&ui->layout, line_height + 2); if (ui->state.input_stage){ ui_do_button_input(&ui->state, rect, make_sub0(&ui->state, id), 1); } else{ Render_Target *target = ui->state.target; + u32 back_color, text_color; text_color = 0xFFDDDDDD; if (ui->state.selected.sub_id0 == id){ @@ -731,7 +737,7 @@ do_sub_button(i32 id, Color_UI *ui, char *text){ } draw_rectangle(target, rect, back_color); - draw_string(target, font, text, rect.x0, rect.y0 + 1, + draw_string(target, font_id, text, rect.x0, rect.y0 + 1, text_color); } } @@ -740,9 +746,8 @@ internal void do_color_adjuster(Color_UI *ui, u32 *color, u32 text_color, u32 back_color, char *name){ i32 id = raw_ptr_dif(color, ui->state.style); - Render_Target *target = ui->state.target; - Render_Font *font = ui->state.font; - i32 character_h = font->height; + i16 font_id = ui->state.font_id; + i32 character_h = get_font_info(ui->state.font_set, font_id)->height; u32 text = 0, back = 0; i32_Rect bar = layout_rect(&ui->layout, character_h); @@ -755,6 +760,7 @@ do_color_adjuster(Color_UI *ui, u32 *color, } else{ + Render_Target *target = ui->state.target; u32 text_hover = 0xFF101010; u32 back_hover = 0xFF999999; if (ui->state.selected.id != id && ui->state.hover.id == id){ @@ -767,7 +773,7 @@ do_color_adjuster(Color_UI *ui, u32 *color, } draw_rectangle(target, bar, back); - i32 end_pos = draw_string(target, font, name, bar.x0, bar.y0, text); + i32 end_pos = draw_string(target, font_id, name, bar.x0, bar.y0, text); real32 x_spacing = ui->hex_advance; i32_Rect temp_rect = bar; @@ -780,8 +786,8 @@ do_color_adjuster(Color_UI *ui, u32 *color, n >>= 4; full_hex_string[i] = int_to_hexchar(m); } - draw_string_mono(target, font, full_hex_string, - (real32)temp_rect.x0, (real32)bar.y0, + draw_string_mono(target, font_id, full_hex_string, + (f32)temp_rect.x0, (f32)bar.y0, x_spacing, text); } @@ -794,6 +800,7 @@ do_color_adjuster(Color_UI *ui, u32 *color, } if (ui->state.selected.id == id){ + Render_Target *target = ui->state.target; i32_Rect expanded = layout_rect(&ui->layout, 115 + (character_h + 2)); UI_Layout_Restore restore = begin_sub_layout(&ui->layout, expanded); @@ -830,12 +837,14 @@ do_color_adjuster(Color_UI *ui, u32 *color, internal void do_style_name(Color_UI *ui){ i32 id = -3; - Render_Font *font = ui->state.font; - i32_Rect srect = layout_rect(&ui->layout, font->height); + i16 font_id = ui->state.font_id; + i32 line_height = get_font_info(ui->state.font_set, font_id)->height; + + i32_Rect srect = layout_rect(&ui->layout, line_height); Widget_ID wid = make_id(&ui->state, id); - bool32 selected = is_selected(&ui->state, wid); + b32 selected = is_selected(&ui->state, wid); if (ui->state.input_stage){ if (!selected){ @@ -868,18 +877,20 @@ do_style_name(Color_UI *ui){ draw_rectangle(target, srect, back); i32 x = srect.x0; - x = draw_string(target, font, "NAME: ", + x = draw_string(target, font_id, "NAME: ", x, srect.y0, fore_label); - x = draw_string(target, font, style->name.str, + x = draw_string(target, font_id, style->name.str, x, srect.y0, fore_text); } } -internal bool32 -do_font_option(Color_UI *ui, Render_Font *font){ - bool32 result = 0; - i32 sub_id = (i32)(font); - i32_Rect orect = layout_rect(&ui->layout, font->height); +internal b32 +do_font_option(Color_UI *ui, i16 font_id){ + b32 result = 0; + Font_Info *info = get_font_info(ui->state.font_set, font_id); + + i32 sub_id = (i32)(info); + i32_Rect orect = layout_rect(&ui->layout, info->height); Widget_ID wid = make_sub0(&ui->state, sub_id); if (ui->state.input_stage){ @@ -900,10 +911,8 @@ do_font_option(Color_UI *ui, Render_Font *font){ } draw_rectangle(target, orect, back); i32 x = orect.x0; - x = draw_string(target, font, "->", - x, orect.y0, fore); - x = draw_string(target, font, font->name.str, - x, orect.y0, fore); + x = draw_string(target, font_id, "->", x, orect.y0, fore); + draw_string(target, font_id, info->name.str, x, orect.y0, fore); } return result; @@ -913,11 +922,13 @@ internal void do_font_switch(Color_UI *ui){ i32 id = -2; Render_Target *target = ui->state.target; - Render_Font *font = ui->state.font; - i32 character_h = font->height; + Font_Set *font_set = ui->state.font_set; + + i16 font_id = ui->state.font_id; + Font_Info *info = get_font_info(font_set, font_id); + i32 character_h = info->height; i32_Rect srect = layout_rect(&ui->layout, character_h); - Widget_ID wid = make_id(&ui->state, id); if (ui->state.input_stage){ @@ -936,24 +947,23 @@ do_font_switch(Color_UI *ui){ } draw_rectangle(target, srect, back); i32 x = srect.x0; - x = draw_string(target, font, "FONT: ", + x = draw_string(target, font_id, "FONT: ", x, srect.y0, fore); - x = draw_string(target, font, font->name.str, + x = draw_string(target, font_id, info->name.str, x, srect.y0, fore); } if (is_selected(&ui->state, wid)){ - Font_Set *fonts = ui->fonts; - Render_Font *font_opt = fonts->fonts; - i32 count = fonts->count; srect = layout_rect(&ui->layout, character_h/2); if (!ui->state.input_stage) draw_rectangle(target, srect, 0xFF000000); - for (i32 i = 0; i < count; ++i, ++font_opt){ - if (font_opt == font) continue; - if (do_font_option(ui, font_opt)){ - ui->state.style->font = font_opt; + i32 count = font_set->count + 1; + + for (i16 i = 1; i < count; ++i){ + if (i == font_id) continue; + if (do_font_option(ui, i)){ + ui->state.style->font_id = i; ui->state.style->font_changed = 1; } } @@ -974,16 +984,17 @@ step_draw_adjusting(Color_View *color_view, i32_Rect rect, View_Message message, Color_UI ui; ui.state = ui_state_init(&color_view->state, target, user_input, - style, color_view->working_set, (message == VMSG_STEP)); + style, color_view->font_set, color_view->working_set, + (message == VMSG_STEP)); begin_layout(&ui.layout, rect); - ui.fonts = color_view->fonts; + ui.fonts = color_view->font_set; ui.highlight = color_view->highlight; ui.color = color_view->color; ui.has_hover_color = 0; ui.state.sub_id1_change = 0; - ui.hex_advance = font_get_max_width(ui.state.font, "0123456789abcdefx"); + ui.hex_advance = font_get_max_width(ui.fonts, ui.state.font_id, "0123456789abcdefx"); ui.palette = color_view->palette; ui.palette_size = color_view->palette_size; @@ -1119,15 +1130,15 @@ update_highlighting(Color_View *color_view){ Style *style = color_view->main_style; Editing_File *file = file_view->file; i32 pos = view_get_cursor_pos(file_view); - char c = file->buffer.data[pos]; + char c = file->state.buffer.data[pos]; if (c == '\r'){ color_view->highlight.ids[0] = raw_ptr_dif(&style->main.special_character_color, style); } - else if (file->tokens_complete){ - Cpp_Token_Stack *tokens = &file->token_stack; + else if (file->state.tokens_complete){ + Cpp_Token_Stack *tokens = &file->state.token_stack; Cpp_Get_Token_Result result = cpp_get_token(tokens, pos); Cpp_Token token = tokens->tokens[result.token_index]; if (!result.in_whitespace){ @@ -1183,15 +1194,17 @@ update_highlighting(Color_View *color_view){ #endif } -internal bool32 +internal b32 do_style_preview(Library_UI *ui, Style *style, i32 toggle = -1){ - bool32 result = 0; - Render_Font *font = style->font; + b32 result = 0; i32 id; if (style == ui->state.style) id = 2; else id = raw_ptr_dif(style, ui->styles->styles) + 100; + + i16 font_id = style->font_id; + Font_Info *info = get_font_info(ui->state.font_set, font_id); - i32_Rect prect = layout_rect(&ui->layout, font->height*3 + 6); + i32_Rect prect = layout_rect(&ui->layout, info->height*3 + 6); Widget_ID wid = make_id(&ui->state, id); @@ -1202,7 +1215,6 @@ do_style_preview(Library_UI *ui, Style *style, i32 toggle = -1){ } else{ Render_Target *target = ui->state.target; - u32 margin_color = style->main.margin_color; if (is_hover(&ui->state, wid)){ margin_color = style->main.margin_active_color; @@ -1211,7 +1223,7 @@ do_style_preview(Library_UI *ui, Style *style, i32 toggle = -1){ i32_Rect inner; if (toggle != -1){ i32_Rect toggle_box = prect; - toggle_box.x1 = toggle_box.x0 + font->height*2 + 6; + toggle_box.x1 = toggle_box.x0 + info->height*2 + 6; prect.x0 = toggle_box.x1; inner = get_inner_rect(toggle_box, 3); @@ -1219,12 +1231,12 @@ do_style_preview(Library_UI *ui, Style *style, i32 toggle = -1){ draw_rectangle(target, inner, style->main.back_color); i32 d; - d = font->height/2; + d = info->height/2; i32_Rect b; b.x0 = (inner.x1 + inner.x0)/2 - d; b.y0 = (inner.y1 + inner.y0)/2 - d; - b.x1 = b.x0 + font->height; - b.y1 = b.y0 + font->height; + b.x1 = b.x0 + info->height; + b.y1 = b.y0 + info->height; if (toggle) draw_rectangle(target, b, margin_color); else draw_rectangle_outline(target, b, margin_color); } @@ -1235,33 +1247,33 @@ do_style_preview(Library_UI *ui, Style *style, i32 toggle = -1){ i32 text_y = inner.y0; i32 text_x = inner.x0; - text_x = draw_string(target, font, style->name.str, + text_x = draw_string(target, font_id, style->name.str, text_x, text_y, style->main.default_color); - i32 font_x = (i32)(inner.x1 - font_string_width(font, font->name.str)); + i32 font_x = (i32)(inner.x1 - font_string_width(target, font_id, info->name.str)); if (font_x > text_x + 10) - draw_string(target, font, font->name.str, + draw_string(target, font_id, info->name.str, font_x, text_y, style->main.default_color); text_x = inner.x0; - text_y += font->height; - text_x = draw_string(target, font, "if ", text_x, text_y, + text_y += info->height; + text_x = draw_string(target, font_id, "if ", text_x, text_y, style->main.keyword_color); - text_x = draw_string(target, font, "(x < ", text_x, text_y, + text_x = draw_string(target, font_id, "(x < ", text_x, text_y, style->main.default_color); - text_x = draw_string(target, font, "0", text_x, text_y, + text_x = draw_string(target, font_id, "0", text_x, text_y, style->main.int_constant_color); - text_x = draw_string(target, font, ") { x = ", text_x, text_y, + text_x = draw_string(target, font_id, ") { x = ", text_x, text_y, style->main.default_color); - text_x = draw_string(target, font, "0", text_x, text_y, + text_x = draw_string(target, font_id, "0", text_x, text_y, style->main.int_constant_color); - text_x = draw_string(target, font, "; } ", text_x, text_y, + text_x = draw_string(target, font_id, "; } ", text_x, text_y, style->main.default_color); - text_x = draw_string(target, font, "// comment", text_x, text_y, + text_x = draw_string(target, font_id, "// comment", text_x, text_y, style->main.comment_color); text_x = inner.x0; - text_y += font->height; - text_x = draw_string(target, font, "[] () {}; * -> +-/ <>= ! && || % ^", + text_y += info->height; + text_x = draw_string(target, font_id, "[] () {}; * -> +-/ <>= ! && || % ^", text_x, text_y, style->main.default_color); } @@ -1269,13 +1281,15 @@ do_style_preview(Library_UI *ui, Style *style, i32 toggle = -1){ return result; } -internal bool32 +internal b32 do_main_file_box(System_Functions *system, UI_State *state, UI_Layout *layout, Hot_Directory *hot_directory, char *end = 0){ - bool32 result = 0; + b32 result = 0; Style *style = state->style; - Render_Font *font = style->font; - i32_Rect box = layout_rect(layout, font->height + 2); String *string = &hot_directory->string; + + i16 font_id = style->font_id; + i32 line_height = get_font_info(state->font_set, font_id)->height; + i32_Rect box = layout_rect(layout, line_height + 2); if (state->input_stage){ if (ui_do_file_field_input(system, state, hot_directory)){ @@ -1289,8 +1303,8 @@ do_main_file_box(System_Functions *system, UI_State *state, UI_Layout *layout, H u32 special = style->main.special_character_color; draw_rectangle(target, box, back); i32 x = box.x0; - x = draw_string(target, font, string->str, x, box.y0, fore); - if (end) draw_string(target, font, end, x, box.y0, special); + x = draw_string(target, font_id, string->str, x, box.y0, fore); + if (end) draw_string(target, font_id, end, x, box.y0, special); } layout->y = box.y1; @@ -1301,8 +1315,10 @@ internal bool32 do_main_string_box(System_Functions *system, UI_State *state, UI_Layout *layout, String *string){ bool32 result = 0; Style *style = state->style; - Render_Font *font = style->font; - i32_Rect box = layout_rect(layout, font->height + 2); + + i16 font_id = style->font_id; + i32 line_height = get_font_info(state->font_set, font_id)->height; + i32_Rect box = layout_rect(layout, line_height + 2); if (state->input_stage){ if (ui_do_line_field_input(system, state, string)){ @@ -1315,7 +1331,7 @@ do_main_string_box(System_Functions *system, UI_State *state, UI_Layout *layout, u32 fore = style->main.default_color; draw_rectangle(target, box, back); i32 x = box.x0; - x = draw_string(target, font, string->str, x, box.y0, fore); + x = draw_string(target, font_id, string->str, x, box.y0, fore); } layout->y = box.y1; @@ -1326,10 +1342,11 @@ internal bool32 do_list_option(i32 id, UI_State *state, UI_Layout *layout, String text){ bool32 result = 0; Style *style = state->style; - Render_Font *font = style->font; - i32 character_h = font->height; + + i16 font_id = style->font_id; + i32 character_h = get_font_info(state->font_set, font_id)->height; - i32_Rect box = layout_rect(layout, font->height*2); + i32_Rect box = layout_rect(layout, character_h*2); Widget_ID wid = make_id(state, id); if (state->input_stage){ @@ -1349,7 +1366,7 @@ do_list_option(i32 id, UI_State *state, UI_Layout *layout, String text){ draw_rectangle(target, inner, back); i32 x = inner.x0, y = box.y0 + character_h/2; - x = draw_string(target, font, text, x, y, fore); + x = draw_string(target, font_id, text, x, y, fore); draw_margin(target, box, inner, outline); } @@ -1359,14 +1376,14 @@ do_list_option(i32 id, UI_State *state, UI_Layout *layout, String text){ #define do_list_option_lit(id,state,layout,str) do_list_option(id, state, layout, make_lit_string(str)) -internal bool32 -do_file_option(i32 id, UI_State *state, UI_Layout *layout, String filename, bool32 is_folder, String extra){ - bool32 result = 0; +internal b32 +do_file_option(i32 id, UI_State *state, UI_Layout *layout, String filename, b32 is_folder, String extra){ + b32 result = 0; Style *style = state->style; - Render_Font *font = style->font; - i32 character_h = font->height; + i16 font_id = style->font_id; + i32 character_h = get_font_info(state->font_set, font_id)->height; - i32_Rect box = layout_rect(layout, font->height*2); + i32_Rect box = layout_rect(layout, character_h*2); Widget_ID wid = make_id(state, id); if (state->input_stage){ @@ -1386,9 +1403,9 @@ do_file_option(i32 id, UI_State *state, UI_Layout *layout, String filename, bool draw_rectangle(target, inner, back); i32 x = inner.x0, y = box.y0 + character_h/2; - x = draw_string(target, font, filename, x, y, fore); - if (is_folder) x = draw_string(target, font, "\\", x, y, fore); - draw_string(target, font, extra, x, y, pop); + x = draw_string(target, font_id, filename, x, y, fore); + if (is_folder) x = draw_string(target, font_id, "\\", x, y, fore); + draw_string(target, font_id, extra, x, y, pop); draw_margin(target, box, inner, outline); } @@ -1397,10 +1414,10 @@ do_file_option(i32 id, UI_State *state, UI_Layout *layout, String filename, bool } internal b32 -do_file_list_box(System_Functions *system, - UI_State *state, UI_Layout *layout, Hot_Directory *hot_dir, bool32 has_filter, - bool32 *new_dir, bool32 *selected, char *end){ - bool32 result = 0; +do_file_list_box(System_Functions *system, UI_State *state, + UI_Layout *layout, Hot_Directory *hot_dir, b32 has_filter, + b32 *new_dir, b32 *selected, char *end){ + b32 result = 0; File_List *files = &hot_dir->file_list; if (do_main_file_box(system, state, layout, hot_dir, end)){ @@ -1437,10 +1454,10 @@ do_file_list_box(System_Functions *system, Editing_File *file = working_set_contains(state->working_set, full_path); full_path.size = restore_size; - bool8 is_folder = (info->folder != 0); - bool8 ext_match = (match(file_extension(filename), p4c_extension) != 0); - bool8 name_match = (filename_match(front_name, &absolutes, filename) != 0); - bool8 is_loaded = (file != 0); + b8 is_folder = (info->folder != 0); + b8 ext_match = (match(file_extension(filename), p4c_extension) != 0); + b8 name_match = (filename_match(front_name, &absolutes, filename) != 0); + b8 is_loaded = (file != 0); String message = message_nothing; if (is_loaded){ @@ -1494,18 +1511,18 @@ do_live_file_list_box(System_Functions *system, UI_State *state, UI_Layout *layo for (i32 i = 0; i < count; ++i){ Editing_File *file = files + i; - if (!file->is_dummy){ + if (!file->state.is_dummy){ String message = message_nothing; switch (buffer_get_sync(file)){ case SYNC_BEHIND_OS: message = message_unsynced; break; case SYNC_UNSAVED: message = message_unsaved; break; } - if (filename_match(*string, &absolutes, file->live_name)){ - if (do_file_option(100+i, state, layout, file->live_name, 0, message)){ + if (filename_match(*string, &absolutes, file->state.live_name)){ + if (do_file_option(100+i, state, layout, file->state.live_name, 0, message)){ result = 1; *selected = 1; - copy(string, file->live_name); + copy(string, file->state.live_name); terminate_with_null(string); } } @@ -1517,16 +1534,17 @@ do_live_file_list_box(System_Functions *system, UI_State *state, UI_Layout *layo } internal i32 -step_draw_library(System_Functions *system, +step_draw_library(System_Functions *system, Exchange *exchange, Mem_Options *mem, Color_View *color_view, i32_Rect rect, View_Message message, Render_Target *target, Input_Summary *user_input){ i32 result = 0; Library_UI ui; ui.state = ui_state_init(&color_view->state, target, user_input, - color_view->main_style, color_view->working_set, (message == VMSG_STEP)); + color_view->main_style, color_view->font_set, + color_view->working_set, (message == VMSG_STEP)); - ui.fonts = color_view->fonts; + ui.fonts = color_view->font_set; ui.hot_directory = color_view->hot_directory; ui.styles = color_view->styles; @@ -1591,7 +1609,7 @@ step_draw_library(System_Functions *system, do_label(&ui.state, &ui.layout, "Current Theme"); do_style_preview(&ui, color_view->main_style); - bool32 file_selected = 0; + b32 file_selected = 0; do_label(&ui.state, &ui.layout, "Import Which File?"); begin_row(&ui.layout, 2); @@ -1602,7 +1620,7 @@ step_draw_library(System_Functions *system, color_view->mode = CV_MODE_LIBRARY; } - bool32 new_dir = 0; + b32 new_dir = 0; if (do_file_list_box(system, &ui.state, &ui.layout, ui.hot_directory, color_view->p4c_only, &new_dir, &file_selected, 0)){ @@ -1614,19 +1632,40 @@ step_draw_library(System_Functions *system, } if (file_selected){ memset(&color_view->inspecting_styles, 0, sizeof(Style_Library)); - memset(color_view->import_export_check, 1, sizeof(color_view->import_export_check)); - Style *styles = color_view->inspecting_styles.styles; - i32 count, max; - max = ArrayCount(color_view->inspecting_styles.styles); - if (style_library_import(system, - color_view->hot_directory->string.str, - ui.fonts, styles, max, &count)){ - color_view->mode = CV_MODE_IMPORT; + memset(color_view->import_export_check, 1, + sizeof(color_view->import_export_check)); + + color_view->import_file_id = + exchange_request_file(exchange, + color_view->hot_directory->string.str, + color_view->hot_directory->string.size); + color_view->mode = CV_MODE_IMPORT_WAIT; + + } + }break; + + case CV_MODE_IMPORT_WAIT: + { + Style *styles = color_view->inspecting_styles.styles; + Data file; + i32 file_max; + + i32 count, max; + max = ArrayCount(color_view->inspecting_styles.styles); + + if (exchange_file_ready(exchange, color_view->import_file_id, + &file.data, &file.size, &file_max)){ + if (file.data){ + if (style_library_import(file, ui.fonts, styles, max, &count)) + color_view->mode = CV_MODE_IMPORT; + else color_view->mode = CV_MODE_LIBRARY; + color_view->inspecting_styles.count = count; } else{ - color_view->mode = CV_MODE_LIBRARY; + Assert(!"this shouldn't happen!"); } - color_view->inspecting_styles.count = count; + + exchange_free_file(exchange, color_view->import_file_id); } }break; @@ -1635,7 +1674,7 @@ step_draw_library(System_Functions *system, do_label(&ui.state, &ui.layout, "Current Theme"); do_style_preview(&ui, color_view->main_style); - bool32 file_selected = 0; + b32 file_selected = 0; do_label(&ui.state, &ui.layout, "Export File Name?"); begin_row(&ui.layout, 2); @@ -1646,7 +1685,7 @@ step_draw_library(System_Functions *system, color_view->mode = CV_MODE_LIBRARY; } - bool32 new_dir = 0; + b32 new_dir = 0; if (do_file_list_box(system, &ui.state, &ui.layout, ui.hot_directory, 1, &new_dir, &file_selected, ".p4c")){ @@ -1659,8 +1698,9 @@ step_draw_library(System_Functions *system, } if (file_selected){ i32 count = ui.styles->count; - // TODO(allen): pass the transient memory in here - Style **styles = (Style**)system->get_memory(sizeof(Style*)*count); + Temp_Memory temp = begin_temp_memory(&mem->part); + Style **styles = push_array(&mem->part, Style*, sizeof(Style*)*count); + Style *style = ui.styles->styles; bool8 *export_check = color_view->import_export_check; i32 export_count = 0; @@ -1669,13 +1709,13 @@ step_draw_library(System_Functions *system, styles[export_count++] = style; } } - char *mem = (char*)system->get_memory(ui.hot_directory->string.size + 5); - String str = make_string(mem, 0, ui.hot_directory->string.size + 5); + char *data = push_array(&mem->part, char, ui.hot_directory->string.size + 5); + String str = make_string(data, 0, ui.hot_directory->string.size + 5); copy(&str, ui.hot_directory->string); append(&str, make_lit_string(".p4c")); - style_library_export(system, str.str, styles, export_count); - system->free_memory(mem); - system->free_memory(styles); + style_library_export(system, exchange, mem, &target->font_set, str.str, styles, export_count); + + end_temp_memory(temp); color_view->mode = CV_MODE_LIBRARY; } }break; @@ -1757,14 +1797,17 @@ Do_View_Sig(do_color_view){ case CV_MODE_EXPORT_FILE: case CV_MODE_IMPORT: case CV_MODE_EXPORT: + case CV_MODE_IMPORT_WAIT: switch (message){ case VMSG_STEP: { - result = step_draw_library(system, color_view, rect, message, target, user_input); + result = step_draw_library(system, exchange, view->mem, + color_view, rect, message, target, user_input); }break; case VMSG_DRAW: { - step_draw_library(system, color_view, rect, message, target, user_input); + step_draw_library(system, exchange, view->mem, + color_view, rect, message, target, user_input); }break; }break; diff --git a/4ed_command.cpp b/4ed_command.cpp index 0e037d3b..faf43d0a 100644 --- a/4ed_command.cpp +++ b/4ed_command.cpp @@ -38,8 +38,8 @@ map_hash(u16 event_code, u8 modifiers){ } internal b32 -map_add(Command_Map *map, u16 event_code, u8 modifiers, Command_Function function, - Custom_Command_Function *custom = 0){ +map_add(Command_Map *map, u16 event_code, u8 modifiers, + Command_Function function, Custom_Command_Function *custom = 0){ Assert(map->count * 8 < map->max * 7); Command_Binding bind; bind.function = function; @@ -61,7 +61,8 @@ map_add(Command_Map *map, u16 event_code, u8 modifiers, Command_Function functio } internal b32 -map_find_entry(Command_Map *map, u16 event_code, u8 modifiers, i32 *index_out){ +map_find_entry(Command_Map *map, u16 event_code, u8 modifiers, + i32 *index_out){ i64 hash = map_hash(event_code, modifiers); i32 max = map->max; i32 index = hash % map->max; @@ -77,7 +78,8 @@ map_find_entry(Command_Map *map, u16 event_code, u8 modifiers, i32 *index_out){ } internal b32 -map_find(Command_Map *map, u16 event_code, u8 modifiers, Command_Binding *bind_out){ +map_find(Command_Map *map, u16 event_code, u8 modifiers, + Command_Binding *bind_out){ b32 result; i32 index; result = map_find_entry(map, event_code, modifiers, &index); @@ -100,7 +102,8 @@ map_drop(Command_Map *map, u16 event_code, u8 modifiers){ } internal void -map_init(Command_Map *commands, Partition *part, i32 max, Command_Map *parent){ +map_init(Command_Map *commands, Partition *part, i32 max, + Command_Map *parent){ commands->parent = parent; commands->commands = push_array(part, Command_Binding, max); memset(commands->commands, 0, max*sizeof(*commands->commands)); @@ -110,31 +113,35 @@ map_init(Command_Map *commands, Partition *part, i32 max, Command_Map *parent){ } internal void -map_get_vanilla_keyboard_default(Command_Map *map, u8 command, Command_Binding *bind_out){ +map_get_vanilla_keyboard_default(Command_Map *map, u8 command, + Command_Binding *bind_out){ if (command == MDFR_NONE){ *bind_out = map->vanilla_keyboard_default; } } +inline u8 +apply_shift_to_code(u8 keycode){ + return !(keycode >= 0x20 && keycode < 0x7F && keycode != ' '); +} + internal Command_Binding map_extract(Command_Map *map, Key_Single key){ Command_Binding bind = {}; b32 ctrl = key.modifiers[CONTROL_KEY_CONTROL]; b32 alt = key.modifiers[CONTROL_KEY_ALT]; - b32 shift = key.modifiers[CONTROL_KEY_SHIFT] && key.key.loose_keycode; + b32 shift = key.modifiers[CONTROL_KEY_SHIFT]; u16 code; u8 command = MDFR_NONE; + if (key.key.character_no_caps_lock != 0 && + key.key.character_no_caps_lock != ' ') shift = 0; + if (shift) command |= MDFR_SHIFT; if (ctrl) command |= MDFR_CTRL; if (alt) command |= MDFR_ALT; - - command |= MDFR_EXACT; - code = key.key.keycode; - map_find(map, code, command, &bind); - - command &= ~(MDFR_EXACT); + code = key.key.character_no_caps_lock; if (code == 0){ code = key.key.keycode; diff --git a/4ed_debug_view.cpp b/4ed_debug_view.cpp index a26495fc..cdc83988 100644 --- a/4ed_debug_view.cpp +++ b/4ed_debug_view.cpp @@ -23,7 +23,7 @@ struct Dbg_Past_Key{ struct Debug_View{ View view_base; - Render_Font *font; + i16 font_id; Debug_Mode mode; Dbg_Past_Key past_keys[32]; i32 past_key_count, past_key_pos; @@ -38,8 +38,8 @@ view_to_debug_view(View *view){ internal i32 draw_general_memory(Debug_View *view, i32_Rect rect, Render_Target *target, i32 y){ - Render_Font *font = view->font; - i32 y_advance = font->height; + i16 font_id = view->font_id; + i32 y_advance = get_font_info(&target->font_set, font_id)->height; Bubble *sentinel = &view->view_base.mem->general.sentinel; for (Bubble *bubble = sentinel->next; @@ -70,7 +70,7 @@ draw_general_memory(Debug_View *view, i32_Rect rect, Render_Target *target, i32 append_int_to_str(bubble->size, &s); terminate_with_null(&s); - draw_string(target, font, str, rect.x0, y, color); + draw_string(target, font_id, str, rect.x0, y, color); y += y_advance; Bubble *next = bubble->next; @@ -83,7 +83,7 @@ draw_general_memory(Debug_View *view, i32_Rect rect, Render_Target *target, i32 append(&s, "discontinuity"); terminate_with_null(&s); - draw_string(target, font, str, rect.x0, y, color); + draw_string(target, font_id, str, rect.x0, y, color); y += y_advance; } } @@ -93,9 +93,10 @@ draw_general_memory(Debug_View *view, i32_Rect rect, Render_Target *target, i32 } internal i32 -draw_system_memory(System_Functions *system, Debug_View *view, i32_Rect rect, Render_Target *target, i32 y){ - Render_Font *font = view->font; - i32 y_advance = font->height; +draw_system_memory(System_Functions *system, Debug_View *view, i32_Rect rect, + Render_Target *target, i32 y){ + i16 font_id = view->font_id; + i32 y_advance = get_font_info(&target->font_set, font_id)->height; Bubble *sentinel = system->internal_sentinel(); for (Bubble *bubble = sentinel->next; @@ -114,7 +115,7 @@ draw_system_memory(System_Functions *system, Debug_View *view, i32_Rect rect, Re append_int_to_str(bubble->size, &s); terminate_with_null(&s); - draw_string(target, font, str, rect.x0, y, color); + draw_string(target, font_id, str, rect.x0, y, color); y += y_advance; } @@ -152,7 +153,7 @@ draw_background_threads(System_Functions *system, String s = make_fixed_width_string(str); append_int_to_str(pending, &s); terminate_with_null(&s); - draw_string(target, view->font, str, trect.x1, trect.y1, light); + draw_string(target, view->font_id, str, trect.x1, trect.y1, light); } struct Dbg_Modifier{ @@ -174,7 +175,7 @@ draw_modifiers(Debug_View *view, Render_Target *target, if (modifiers[m.modifier]) color = on_color; else color = off_color; - *x = draw_string(target, view->font, m.name, *x, y, color); + *x = draw_string(target, view->font_id, m.name, *x, y, color); *x += 5; } } @@ -182,15 +183,17 @@ draw_modifiers(Debug_View *view, Render_Target *target, internal i32 draw_key_event(Debug_View *view, Render_Target *target, Dbg_Past_Key *key, i32 x, i32 y, u32 on_color, u32 off_color){ - Render_Font *font = view->font; draw_modifiers(view, target, key->modifiers, on_color, off_color, &x, y); + + i16 font_id = view->font_id; + Render_Font *font = get_font_info(&target->font_set, font_id)->font; - if (font->glyphs[key->key.character].exists){ + if (font && font->glyphs[key->key.character].exists){ char c[2]; c[0] = (char)key->key.character; c[1] = 0; - x = draw_string(target, font, c, x, y, on_color); + x = draw_string(target, font_id, c, x, y, on_color); } else{ char c[10] = {}; @@ -198,7 +201,7 @@ draw_key_event(Debug_View *view, Render_Target *target, append(&str, "\\"); append_int_to_str(key->key.keycode, &str); terminate_with_null(&str); - x = draw_string(target, font, c, x, y, on_color); + x = draw_string(target, font_id, c, x, y, on_color); } return x; @@ -212,14 +215,15 @@ draw_os_events(Debug_View *view, i32_Rect rect, Render_Target *target, i32 x, y, max_x, max_y; x = rect.x0; y = rect.y0; - - Render_Font *font = view->font; + + i16 font_id = view->font_id; + i32 line_height = get_font_info(&target->font_set, font_id)->height; draw_modifiers(view, target, active_input->keys.modifiers, 0xFFFFFFFF, 0xFF444444, &x, y); max_x = x; x = rect.x0; - y += font->height; + y += line_height; for (i32 j = 0; j < view->past_key_count; ++j){ Dbg_Past_Key *key = view->past_keys + j; @@ -236,7 +240,7 @@ draw_os_events(Debug_View *view, i32_Rect rect, Render_Target *target, if (max_x < x) max_x = x; x = rect.x0; - y += font->height; + y += line_height; } i32_Rect mrect = rect; @@ -250,13 +254,13 @@ draw_os_events(Debug_View *view, i32_Rect rect, Render_Target *target, u32 color; if (active_input->mouse.out_of_window){ color = 0xFFFF0000; - draw_string(target, font, "OUT", x, y, color); + draw_string(target, font_id, "OUT", x, y, color); } else{ color = 0xFF008800; - draw_string(target, font, "IN", x, y, color); + draw_string(target, font_id, "IN", x, y, color); } - y += font->height; + y += line_height; char c[16]; String s = make_fixed_width_string(c); @@ -264,20 +268,20 @@ draw_os_events(Debug_View *view, i32_Rect rect, Render_Target *target, append(&s, ", "); append_int_to_str(active_input->mouse.my, &s); terminate_with_null(&s); - draw_string(target, font, c, x, y, color); - y += font->height; + draw_string(target, font_id, c, x, y, color); + y += line_height; u32 btn_color; if (active_input->mouse.l) btn_color = color; else btn_color = 0xFF444444; - x = draw_string(target, font, "L ", x, y, btn_color); + x = draw_string(target, font_id, "L ", x, y, btn_color); if (active_input->mouse.r) btn_color = color; else btn_color = 0xFF444444; - x = draw_string(target, font, "R", x, y, btn_color); + x = draw_string(target, font_id, "R", x, y, btn_color); x = mrect.x0; - y += font->height; + y += line_height; s = make_fixed_width_string(c); append_int_to_str(view->prev_mouse_wheel, &s); @@ -285,9 +289,9 @@ draw_os_events(Debug_View *view, i32_Rect rect, Render_Target *target, if (active_input->mouse.wheel_used) btn_color = color; else btn_color = 0xFF444444; - draw_string(target, font, c, x, y, btn_color); + draw_string(target, font_id, c, x, y, btn_color); - y += font->height; + y += line_height; } } diff --git a/4ed_exchange.cpp b/4ed_exchange.cpp new file mode 100644 index 00000000..55f00443 --- /dev/null +++ b/4ed_exchange.cpp @@ -0,0 +1,217 @@ +/* + * Mr. 4th Dimention - Allen Webster + * + * 9.12.2015 + * + * Exchange stuff + * + */ + +// TOP + +internal void +ex__file_insert(File_Slot *pos, File_Slot *file){ + pos->next->prev = file; + file->next = pos->next; + pos->next = file; + file->prev = pos; +} + +internal void +ex__file_remove(File_Slot *file){ + file->next->prev = file->prev; + file->prev->next = file->next; +} + +internal void +ex__check_file(File_Slot *pos){ + File_Slot *file = pos; + + Assert(pos == pos->next->prev); + + for (pos = pos->next; + file != pos; + pos = pos->next){ + Assert(pos == pos->next->prev); + } +} + +internal void +ex__check(File_Exchange *file_exchange){ + ex__check_file(&file_exchange->available); + ex__check_file(&file_exchange->active); + ex__check_file(&file_exchange->free_list); +} + +internal void +ex__clear(File_Slot *file){ + file->data = 0; + file->size = 0; + file->max = 0; + file->flags = 0; +} + +internal File_Slot* +ex__get_file(Exchange *exchange){ + File_Exchange *files = &exchange->file; + File_Slot *file; + + ++files->num_active; + + file = files->available.next; + ex__file_remove(file); + ex__clear(file); + ex__file_insert(&files->active, file); + ex__check(files); + + return file; +} + +internal void +ex__set_filename(File_Slot *file, char *filename, int len){ + memcpy(file->filename, filename, len); + file->filename[len] = 0; + file->filename_len = len; +} + +internal i32 +exchange_request_file(Exchange *exchange, char *filename, int len){ + File_Exchange *files = &exchange->file; + i32 result = 0; + + if (len+1 < FileNameMax){ + if (files->num_active < files->max){ + File_Slot *file = ex__get_file(exchange); + ex__set_filename(file, filename, len); + + file->flags |= FEx_Request; + result = (int)(file - files->files) + 1; + } + } + + return result; +} + +internal b32 +exchange_file_ready(Exchange *exchange, i32 file_id, byte **data, int *size, int *max){ + File_Exchange *files = &exchange->file; + b32 result = 0; + + if (file_id > 0 && file_id <= files->max){ + File_Slot *file = files->files + file_id - 1; + if (file->flags & FEx_Ready){ + *data = file->data; + *size = file->size; + *max = file->max; + result = 1; + } + if (file->flags & FEx_Not_Exist){ + *data = 0; + *size = 0; + *max = 0; + result = 1; + } + } + + return result; +} + +internal i32 +exchange_save_file(Exchange *exchange, char *filename, int len, + byte *data, int size, int max){ + File_Exchange *files = &exchange->file; + i32 result = 0; + + if (len+1 < FileNameMax){ + if (files->num_active < files->max){ + File_Slot *file = ex__get_file(exchange); + ex__set_filename(file, filename, len); + + file->flags |= FEx_Save; + file->data = data; + file->size = size; + file->max = max; + + result = (int)(file - files->files) + 1; + } + } + + return result; +} + +internal b32 +exchange_file_save_complete(Exchange *exchange, i32 file_id, byte **data, int *size, int *max){ + File_Exchange *files = &exchange->file; + b32 result = 0; + + if (file_id > 0 && file_id <= files->max){ + File_Slot *file = files->files + file_id - 1; + if (file->flags & FEx_Save_Complete){ + *data = file->data; + *size = file->size; + *max = file->max; + result = 1; + } + } + + return result; +} + +internal char* +exchange_file_filename(Exchange *exchange, i32 file_id, i32 *size = 0){ + File_Exchange *files = &exchange->file; + char *result = 0; + + if (file_id > 0 && file_id <= files->max){ + File_Slot *file = files->files + file_id - 1; + result = file->filename; + if (size) *size = file->filename_len; + } + + return result; +} + +internal void +exchange_free_file(Exchange *exchange, i32 file_id){ + File_Exchange *files = &exchange->file; + + if (file_id > 0 && file_id <= files->max){ + File_Slot *file = files->files + file_id - 1; + ex__file_remove(file); + ex__file_insert(&files->free_list, file); + ex__check(files); + --files->num_active; + } +} + +internal void +exchange_clear_file(Exchange *exchange, i32 file_id){ + File_Exchange *files = &exchange->file; + + if (file_id > 0 && file_id <= files->max){ + File_Slot *file = files->files + file_id - 1; + ex__clear(file); + } +} + +internal b32 +queue_job_is_pending(Work_Queue *queue, u32 job_id){ + b32 result; + u32 job_index; + Full_Job_Data *full_job; + + job_index = job_id % QUEUE_WRAP; + full_job = queue->jobs + job_index; + + Assert(full_job->id == job_id); + + result = 0; + if (full_job->running_thread != 0){ + result = 1; + } + + return(result); +} + +// BOTTOM + diff --git a/4ed_file_view.cpp b/4ed_file_view.cpp index 0f7be9c2..f663b1e2 100644 --- a/4ed_file_view.cpp +++ b/4ed_file_view.cpp @@ -85,37 +85,54 @@ struct Undo_Data{ b32 current_block_normal; }; -struct Editing_File{ +// NOTE(allen): The Editing_File struct is now divided into two +// parts. Variables in the Settings part can be set even when the +// file is still streaming in, and all operations except for the +// initial allocation of the file. +struct Editing_File_Settings{ + Font_Set *set; + i32 base_map_id; + i32 dos_write_mode; + b32 tokens_exist; + b32 super_locked; +}; + +// NOTE(allen): This part of the Editing_File is cleared whenever +// the contents of the file is set. +struct Editing_File_State{ + b32 is_dummy; + b32 is_loading; + + i16 font_id; Buffer_Type buffer; - Render_Font *font; i32 cursor_pos; - b32 is_dummy; char live_name_[256]; String live_name; - i32 base_map_id; - char source_path_[256]; char extension_[16]; String source_path; String extension; Undo_Data undo; - b32 super_locked; Cpp_Token_Stack token_stack; - b32 tokens_complete; - b32 tokens_exist; - b32 still_lexing; + Cpp_Token_Stack swap_stack; u32 lex_job; - i32 dos_write_mode; + b32 tokens_complete; + b32 still_lexing; u64 last_4ed_write_time; u64 last_4ed_edit_time; u64 last_sys_write_time; }; +struct Editing_File{ + Editing_File_Settings settings; + Editing_File_State state; +}; + struct File_Table_Entry{ String name; u32 hash; @@ -270,15 +287,11 @@ struct Hot_Directory{ }; internal void -hot_directory_init(System_Functions *system, Hot_Directory *hot_directory, String base){ +hot_directory_init(Hot_Directory *hot_directory, String base, String dir){ hot_directory->string = base; hot_directory->string.str[255] = 0; - i32 dir_size = system->get_current_directory(hot_directory->string.str, - hot_directory->string.memory_size); - if (dir_size <= 0){ - dir_size = system->get_easy_directory(hot_directory->string.str); - } - hot_directory->string.size = dir_size; + hot_directory->string.size = 0; + copy(&hot_directory->string, dir); append(&hot_directory->string, "\\"); } @@ -323,23 +336,19 @@ hot_directory_fixup(Hot_Directory *hot_directory, Working_Set *working_set){ } inline void -hot_directory_set(System_Functions *system, - Hot_Directory *hot_directory, String str, Working_Set *working_set){ - bool32 success = copy_checked(&hot_directory->string, str); +hot_directory_set(System_Functions *system, Hot_Directory *hot_directory, + String str, Working_Set *working_set){ + b32 success = copy_checked(&hot_directory->string, str); terminate_with_null(&hot_directory->string); if (success){ - system->free_file_list(hot_directory->file_list); - hot_directory->file_list = system->get_file_list(str); + system->set_file_list(&hot_directory->file_list, str); } hot_directory_fixup(hot_directory, working_set); } inline void hot_directory_reload(System_Functions *system, Hot_Directory *hot_directory, Working_Set *working_set){ - if (hot_directory->file_list.block){ - system->free_file_list(hot_directory->file_list); - } - hot_directory->file_list = system->get_file_list(hot_directory->string); + system->set_file_list(&hot_directory->file_list, hot_directory->string); hot_directory_fixup(hot_directory, working_set); } @@ -391,13 +400,14 @@ hot_directory_first_match(Hot_Directory *hot_directory, } struct Single_Line_Input_Step{ - bool32 hit_newline; - bool32 hit_ctrl_newline; - bool32 hit_a_character; - bool32 hit_backspace; - bool32 hit_esc; - bool32 made_a_change; - bool32 did_command; + b8 hit_newline; + b8 hit_ctrl_newline; + b8 hit_a_character; + b8 hit_backspace; + b8 hit_esc; + b8 made_a_change; + b8 did_command; + b8 no_file_match; }; enum Single_Line_Input_Type{ @@ -409,7 +419,7 @@ struct Single_Line_Mode{ Single_Line_Input_Type type; String *string; Hot_Directory *hot_directory; - bool32 fast_folder_select; + b32 fast_folder_select; }; internal Single_Line_Input_Step @@ -473,6 +483,9 @@ app_single_line_input_core(System_Functions *system, result.hit_newline = 1; } } + else{ + result.no_file_match = 1; + } } } } @@ -549,7 +562,7 @@ struct Widget_ID{ i32 sub_id2; }; -inline bool32 +inline b32 widget_match(Widget_ID s1, Widget_ID s2){ return (s1.id == s2.id && s1.sub_id0 == s2.sub_id0 && s1.sub_id1 == s2.sub_id1 && s1.sub_id2 == s2.sub_id2); @@ -558,16 +571,17 @@ widget_match(Widget_ID s1, Widget_ID s2){ struct UI_State{ Render_Target *target; Style *style; - Render_Font *font; + Font_Set *font_set; Mouse_Summary *mouse; Key_Summary *keys; Key_Codes *codes; Working_Set *working_set; + i16 font_id; Widget_ID selected, hover, hot; - bool32 activate_me; - bool32 redraw; - bool32 input_stage; + b32 activate_me; + b32 redraw; + b32 input_stage; i32 sub_id1_change; real32 height, view_y; @@ -601,17 +615,17 @@ make_sub2(UI_State *state, i32 id){ return r; } -inline bool32 +inline b32 is_selected(UI_State *state, Widget_ID id){ return widget_match(state->selected, id); } -inline bool32 +inline b32 is_hot(UI_State *state, Widget_ID id){ return widget_match(state->hot, id); } -inline bool32 +inline b32 is_hover(UI_State *state, Widget_ID id){ return widget_match(state->hover, id); } @@ -752,11 +766,12 @@ get_pop_color(UI_State *state, u32 *pop, Widget_ID wid, UI_Style style){ internal UI_State ui_state_init(UI_State *state_in, Render_Target *target, Input_Summary *user_input, - Style *style, Working_Set *working_set, bool32 input_stage){ + Style *style, Font_Set *font_set, Working_Set *working_set, b32 input_stage){ UI_State state = {}; state.target = target; state.style = style; - state.font = style->font; + state.font_set = font_set; + state.font_id = style->font_id; state.working_set = working_set; if (user_input){ state.mouse = &user_input->mouse; @@ -782,20 +797,23 @@ ui_state_match(UI_State a, UI_State b){ widget_match(a.hover, b.hover)); } -internal bool32 +internal b32 ui_finish_frame(UI_State *persist_state, UI_State *state, UI_Layout *layout, i32_Rect rect, - bool32 do_wheel, bool32 *did_activation){ - bool32 result = 0; - real32 h = layout->y + persist_state->view_y - rect.y0; - real32 max_y = h - (rect.y1 - rect.y0); + b32 do_wheel, b32 *did_activation){ + b32 result = 0; + f32 h = layout->y + persist_state->view_y - rect.y0; + f32 max_y = h - (rect.y1 - rect.y0); persist_state->height = h; persist_state->view_y = state->view_y; if (state->input_stage){ Mouse_Summary *mouse = state->mouse; + Font_Set *font_set = state->font_set; + if (mouse->wheel_used && do_wheel){ - persist_state->view_y += mouse->wheel_amount*state->font->height; + i32 height = get_font_info(font_set, state->font_id)->height; + persist_state->view_y += mouse->wheel_amount*height; result = 1; } if (mouse->release_l && widget_match(state->hot, state->hover)){ @@ -945,7 +963,7 @@ ui_do_file_field_input(System_Functions *system, terminate_with_null(str); Single_Line_Input_Step step = app_single_file_input_step(system, state->codes, state->working_set, key, str, hot_dir, 1); - if (step.hit_newline || step.hit_ctrl_newline) result = 1; + if ((step.hit_newline || step.hit_ctrl_newline) && !step.no_file_match) result = 1; } return result; } @@ -982,9 +1000,8 @@ ui_do_slider_input(UI_State *state, i32_Rect rect, Widget_ID wid, internal bool32 do_text_field(Widget_ID wid, UI_State *state, UI_Layout *layout, String prompt, String dest){ - bool32 result = 0; - Render_Font *font = state->font; - i32 character_h = font->height; + b32 result = 0; + i32 character_h = get_font_info(state->font_set, state->font_id)->height; i32_Rect rect = layout_rect(layout, character_h); @@ -1005,8 +1022,8 @@ do_text_field(Widget_ID wid, UI_State *state, UI_Layout *layout, draw_rectangle(target, rect, back); i32 x = rect.x0; - x = draw_string(target, font, prompt, x, rect.y0, prompt_pop); - draw_string(target, font, dest, x, rect.y0, ui_style.base); + x = draw_string(target, state->font_id, prompt, x, rect.y0, prompt_pop); + draw_string(target, state->font_id, dest, x, rect.y0, ui_style.base); } return result; @@ -1050,6 +1067,7 @@ struct Hyper_Link{ struct File_View{ View view_base; + Font_Set *font_set; Editing_File *file; Style *style; Editing_Layout *layout; @@ -1100,6 +1118,21 @@ view_to_file_view(View *view){ return result; } +inline i32 +get_file_id(Working_Set *working_set, Editing_File *file){ + i32 result = (i32)(file - working_set->files); + return(result); +} + +inline Editing_File* +get_file(Working_Set *working_set, i32 file_id){ + Editing_File *result = working_set->files + file_id; + if (!buffer_good(&result->state.buffer) || result->state.is_dummy){ + result = 0; + } + return(result); +} + internal Range get_range(i32 a, i32 b){ Range result = {}; @@ -1121,66 +1154,74 @@ starts_new_line(u8 character){ inline void file_init_strings(Editing_File *file){ - file->source_path = make_fixed_width_string(file->source_path_); - file->live_name = make_fixed_width_string(file->live_name_); - file->extension = make_fixed_width_string(file->extension_); + file->state.source_path = make_fixed_width_string(file->state.source_path_); + file->state.live_name = make_fixed_width_string(file->state.live_name_); + file->state.extension = make_fixed_width_string(file->state.extension_); } inline void file_set_name(Editing_File *file, char *filename){ - file->live_name = make_fixed_width_string(file->live_name_); + file->state.live_name = make_fixed_width_string(file->state.live_name_); if (filename[0] == '*'){ - copy(&file->live_name, filename); + copy(&file->state.live_name, filename); } else{ String f, ext; f = make_string_slowly(filename); - copy_checked(&file->source_path, f); - get_front_of_directory(&file->live_name, f); + copy_checked(&file->state.source_path, f); + get_front_of_directory(&file->state.live_name, f); ext = file_extension(f); - copy(&file->extension, ext); + copy(&file->state.extension, ext); } } inline void file_synchronize_times(System_Functions *system, Editing_File *file, char *filename){ - Time_Stamp stamp = system->file_time_stamp(filename); - if (stamp.success){ - file->last_4ed_write_time = stamp.time; - file->last_4ed_edit_time = stamp.time; - file->last_sys_write_time = stamp.time; + u64 stamp = system->file_time_stamp(filename); + if (stamp > 0){ + file->state.last_4ed_write_time = stamp; + file->state.last_4ed_edit_time = stamp; + file->state.last_sys_write_time = stamp; } } -internal b32 -file_save(System_Functions *system, Partition *part, Editing_File *file, char *filename){ - b32 result = 0; +internal i32 +file_save(System_Functions *system, Exchange *exchange, Mem_Options *mem, + Editing_File *file, char *filename){ + i32 result = 0; + #if BUFFER_EXPERIMENT_SCALPEL <= 3 - Temp_Memory temp = begin_temp_memory(part); - i32 max = partition_remaining(part); - if (file->dos_write_mode){ - char *data = push_array(part, char, max); - i32 size = buffer_convert_out(&file->buffer, data, max); - result = system->save_file(filename, data, size); + i32 max = buffer_size(&file->state.buffer) + file->state.buffer.line_count; + byte *data = (byte*)general_memory_allocate(&mem->general, max, 0); + Assert(data); + i32 size; + if (file->settings.dos_write_mode){ + size = buffer_convert_out(&file->state.buffer, (char*)data, max); } else{ - char *data = push_array(part, char, max); - i32 size = buffer_size(&file->buffer); - Assert(size <= max); - buffer_stringify(&file->buffer, 0, size, data); - result = system->save_file(filename, data, size); + size = buffer_size(&file->state.buffer); + buffer_stringify(&file->state.buffer, 0, size, (char*)data); } - end_temp_memory(temp); + + i32 filename_len = str_size(filename); + result = exchange_save_file(exchange, filename, filename_len, + data, size, max); + + if (result == 0){ + general_memory_free(&mem->general, data); + } + file_synchronize_times(system, file, filename); #endif + return result; } inline b32 -file_save_and_set_names(System_Functions *system, - Partition *part, Editing_File *file, char *filename){ +file_save_and_set_names(System_Functions *system, Exchange *exchange, + Mem_Options *mem, Editing_File *file, char *filename){ b32 result = 0; - if (file_save(system, part, file, filename)){ + if (file_save(system, exchange, mem, file, filename)){ result = 1; file_set_name(file, filename); } @@ -1230,8 +1271,8 @@ file_grow_starts_as_needed(General_Memory *general, Buffer_Type *buffer, i32 add } internal void -file_measure_starts_widths(System_Functions *system, - General_Memory *general, Buffer_Type *buffer, Render_Font *font){ +file_measure_starts_widths(System_Functions *system, General_Memory *general, + Buffer_Type *buffer, float *advance_data){ ProfileMomentFunction(); if (!buffer->line_starts){ i32 max = buffer->line_max = Kbytes(1); @@ -1245,9 +1286,9 @@ file_measure_starts_widths(System_Functions *system, TentativeAssert(buffer->line_starts); // TODO(allen): when unable to allocate? } - + Buffer_Measure_Starts state = {}; - while (buffer_measure_starts_widths(&state, buffer, font->advance_data)){ + while (buffer_measure_starts_widths(&state, buffer, advance_data)){ i32 count = state.count; i32 max = buffer->line_max; max = ((max + 1) << 1); @@ -1279,39 +1320,6 @@ file_measure_starts_widths(System_Functions *system, buffer->widths_count = state.count; } -#if 0 -internal void -file_measure_starts(General_Memory *general, Buffer_Type *buffer){ -#if BUFFER_EXPERIMENT_SCALPEL <= 3 - ProfileMomentFunction(); - if (!buffer->line_starts){ - i32 max = buffer->line_max = Kbytes(1); - buffer->line_starts = (i32*)general_memory_allocate(general, max*sizeof(i32), BUBBLE_STARTS); - TentativeAssert(buffer->line_starts); - // TODO(allen): when unable to allocate? - } - - Buffer_Measure_Starts state = {}; - while (buffer_measure_starts(&state, buffer)){ - i32 max = buffer->line_max; - i32 count = state.count; - i32 target_lines = count + 1; - - max = (target_lines << 1); - i32 *new_lines = (i32*) - general_memory_reallocate(general, buffer->line_starts, - sizeof(i32)*count, sizeof(i32)*max, BUBBLE_STARTS); - - // TODO(allen): when unable to grow? - TentativeAssert(new_lines); - buffer->line_starts = new_lines; - buffer->line_max = max; - } - buffer->line_count = state.count; -#endif -} -#endif - internal void file_remeasure_starts(System_Functions *system, General_Memory *general, Buffer_Type *buffer, @@ -1359,18 +1367,6 @@ file_grow_widths_as_needed(General_Memory *general, Buffer_Type *buffer){ #endif } -#if 0 -internal void -file_measure_widths(General_Memory *general, Buffer_Type *buffer, Font *font){ -#if BUFFER_EXPERIMENT_SCALPEL <= 3 - ProfileMomentFunction(); - file_grow_widths_as_needed(general, buffer); - Opaque_Font_Advance opad = get_opaque_font_advance(font); - buffer_measure_widths(buffer, opad.data, opad.stride); -#endif -} -#endif - internal void file_remeasure_widths(System_Functions *system, General_Memory *general, Buffer_Type *buffer, Render_Font *font, @@ -1383,7 +1379,7 @@ file_remeasure_widths(System_Functions *system, } inline i32 -view_wrapped_line_span(real32 line_width, real32 max_width){ +view_wrapped_line_span(f32 line_width, f32 max_width){ i32 line_count = CEIL32(line_width / max_width); if (line_count == 0) line_count = 1; return line_count; @@ -1399,15 +1395,13 @@ view_compute_lowest_line(File_View *view){ lowest_line = last_line; } else{ - Style *style = view->style; - Render_Font *font = style->font; - real32 wrap_y = view->line_wrap_y[last_line]; - lowest_line = FLOOR32(wrap_y / font->height); + f32 wrap_y = view->line_wrap_y[last_line]; + lowest_line = FLOOR32(wrap_y / view->font_height); f32 max_width = view_compute_width(view); - + Editing_File *file = view->file; - Assert(!file->is_dummy); - f32 width = file->buffer.line_widths[last_line]; + Assert(!file->state.is_dummy); + f32 width = file->state.buffer.line_widths[last_line]; i32 line_span = view_wrapped_line_span(width, max_width); lowest_line += line_span - 1; } @@ -1423,7 +1417,7 @@ view_measure_wraps(System_Functions *system, ProfileMomentFunction(); Buffer_Type *buffer; - buffer = &view->file->buffer; + buffer = &view->file->state.buffer; i32 line_count = buffer->line_count; if (view->line_max < line_count){ @@ -1438,8 +1432,7 @@ view_measure_wraps(System_Functions *system, } } - Render_Font *font = view->style->font; - f32 line_height = (f32)font->height; + f32 line_height = (f32)view->font_height; f32 max_width = view_compute_width(view); buffer_measure_wrap_y(buffer, view->line_wrap_y, line_height, max_width); @@ -1455,13 +1448,14 @@ alloc_for_buffer(void *context, int *size){ } internal void -file_create_from_string(System_Functions *system, - Mem_Options *mem, Editing_File *file, char *filename, - Render_Font *font, String val, b32 super_locked = 0){ - *file = {}; +file_create_from_string(System_Functions *system, Mem_Options *mem, + Editing_File *file, char *filename, + Font_Set *set, i16 font_id, + String val, b8 super_locked = 0){ + file->state = {}; General_Memory *general = &mem->general; #if BUFFER_EXPERIMENT_SCALPEL <= 3 - Buffer_Init_Type init = buffer_begin_init(&file->buffer, val.str, val.size); + Buffer_Init_Type init = buffer_begin_init(&file->state.buffer, val.str, val.size); for (; buffer_init_need_more(&init); ){ i32 page_size = buffer_init_page_size(&init); page_size = LargeRoundUp(page_size, Kbytes(4)); @@ -1481,73 +1475,60 @@ file_create_from_string(System_Functions *system, file_init_strings(file); file_set_name(file, (char*)filename); - file->base_map_id = mapid_file; - file->font = font; + file->settings.base_map_id = mapid_file; + file->state.font_id = font_id; file_synchronize_times(system, file, filename); - - file_measure_starts_widths(system, general, &file->buffer, font); - file->super_locked = super_locked; + Render_Font *font = get_font_info(set, font_id)->font; + float *advance_data = 0; + if (font) advance_data = font->advance_data; + file_measure_starts_widths(system, general, &file->state.buffer, advance_data); + + file->settings.super_locked = super_locked; if (!super_locked){ i32 request_size = Kbytes(64); - file->undo.undo.max = request_size; - file->undo.undo.strings = (u8*)general_memory_allocate(general, request_size, BUBBLE_UNDO_STRING); - file->undo.undo.edit_max = request_size / sizeof(Edit_Step); - file->undo.undo.edits = (Edit_Step*)general_memory_allocate(general, request_size, BUBBLE_UNDO); + file->state.undo.undo.max = request_size; + file->state.undo.undo.strings = (u8*)general_memory_allocate(general, request_size, BUBBLE_UNDO_STRING); + file->state.undo.undo.edit_max = request_size / sizeof(Edit_Step); + file->state.undo.undo.edits = (Edit_Step*)general_memory_allocate(general, request_size, BUBBLE_UNDO); - file->undo.redo.max = request_size; - file->undo.redo.strings = (u8*)general_memory_allocate(general, request_size, BUBBLE_UNDO_STRING); - file->undo.redo.edit_max = request_size / sizeof(Edit_Step); - file->undo.redo.edits = (Edit_Step*)general_memory_allocate(general, request_size, BUBBLE_UNDO); + file->state.undo.redo.max = request_size; + file->state.undo.redo.strings = (u8*)general_memory_allocate(general, request_size, BUBBLE_UNDO_STRING); + file->state.undo.redo.edit_max = request_size / sizeof(Edit_Step); + file->state.undo.redo.edits = (Edit_Step*)general_memory_allocate(general, request_size, BUBBLE_UNDO); - file->undo.history.max = request_size; - file->undo.history.strings = (u8*)general_memory_allocate(general, request_size, BUBBLE_UNDO_STRING); - file->undo.history.edit_max = request_size / sizeof(Edit_Step); - file->undo.history.edits = (Edit_Step*)general_memory_allocate(general, request_size, BUBBLE_UNDO); + file->state.undo.history.max = request_size; + file->state.undo.history.strings = (u8*)general_memory_allocate(general, request_size, BUBBLE_UNDO_STRING); + file->state.undo.history.edit_max = request_size / sizeof(Edit_Step); + file->state.undo.history.edits = (Edit_Step*)general_memory_allocate(general, request_size, BUBBLE_UNDO); - file->undo.children.max = request_size; - file->undo.children.strings = (u8*)general_memory_allocate(general, request_size, BUBBLE_UNDO_STRING); - file->undo.children.edit_max = request_size / sizeof(Buffer_Edit); - file->undo.children.edits = (Buffer_Edit*)general_memory_allocate(general, request_size, BUBBLE_UNDO); + file->state.undo.children.max = request_size; + file->state.undo.children.strings = (u8*)general_memory_allocate(general, request_size, BUBBLE_UNDO_STRING); + file->state.undo.children.edit_max = request_size / sizeof(Buffer_Edit); + file->state.undo.children.edits = (Buffer_Edit*)general_memory_allocate(general, request_size, BUBBLE_UNDO); - file->undo.history_block_count = 1; - file->undo.history_head_block = 0; - file->undo.current_block_normal = 1; + file->state.undo.history_block_count = 1; + file->state.undo.history_head_block = 0; + file->state.undo.current_block_normal = 1; } } -internal bool32 -file_create(System_Functions *system, Mem_Options *mem, Editing_File *file, - char *filename, Render_Font *font){ - bool32 result = 0; - - Data raw_file = system->load_file(filename); - if (raw_file.data){ - result = 1; - String val = make_string((char*)raw_file.data, raw_file.size); - file_create_from_string(system, mem, file, filename, font, val); - system->free_file(raw_file); - } - - return result; -} - internal b32 file_create_empty(System_Functions *system, Mem_Options *mem, Editing_File *file, - char *filename, Render_Font *font){ + char *filename, Font_Set *set, i16 font_id){ b32 result = 1; String empty_str = {}; - file_create_from_string(system, mem, file, filename, font, empty_str); + file_create_from_string(system, mem, file, filename, set, font_id, empty_str); return result; } internal b32 file_create_super_locked(System_Functions *system, Mem_Options *mem, Editing_File *file, - char *filename, Render_Font *font){ + char *filename, Font_Set *set, i16 font_id){ b32 result = 1; String empty_str = {}; - file_create_from_string(system, mem, file, filename, font, empty_str, 1); + file_create_from_string(system, mem, file, filename, set, font_id, empty_str, 1); return result; } @@ -1562,7 +1543,7 @@ working_set_get_available_file(Working_Set *working_set){ for (i32 buffer_index = 1; buffer_index < working_set->file_max_count; ++buffer_index){ if (buffer_index == working_set->file_index_count || - working_set->files[buffer_index].is_dummy){ + working_set->files[buffer_index].state.is_dummy){ result.index = buffer_index; result.file = working_set->files + buffer_index; if (buffer_index == working_set->file_index_count){ @@ -1571,22 +1552,29 @@ working_set_get_available_file(Working_Set *working_set){ break; } } + + if (result.file){ + *result.file = {}; + } - Assert(result.file); return result; } internal void file_close(System_Functions *system, General_Memory *general, Editing_File *file){ - if (file->still_lexing){ - system->cancel_job(BACKGROUND_THREADS, file->lex_job); + if (file->state.still_lexing){ + system->cancel_job(BACKGROUND_THREADS, file->state.lex_job); + if (file->state.swap_stack.tokens){ + general_memory_free(general, file->state.swap_stack.tokens); + file->state.swap_stack.tokens = 0; + } } - if (file->token_stack.tokens){ - general_memory_free(general, file->token_stack.tokens); + if (file->state.token_stack.tokens){ + general_memory_free(general, file->state.token_stack.tokens); } #if BUFFER_EXPERIMENT_SCALPEL <= 1 - Buffer_Type *buffer = &file->buffer; + Buffer_Type *buffer = &file->state.buffer; if (buffer->data){ general_memory_free(general, buffer->data); general_memory_free(general, buffer->line_starts); @@ -1596,40 +1584,45 @@ file_close(System_Functions *system, General_Memory *general, Editing_File *file // TODO #endif - if (file->undo.undo.edits){ - general_memory_free(general, file->undo.undo.strings); - general_memory_free(general, file->undo.undo.edits); + if (file->state.undo.undo.edits){ + general_memory_free(general, file->state.undo.undo.strings); + general_memory_free(general, file->state.undo.undo.edits); - general_memory_free(general, file->undo.redo.strings); - general_memory_free(general, file->undo.redo.edits); + general_memory_free(general, file->state.undo.redo.strings); + general_memory_free(general, file->state.undo.redo.edits); - general_memory_free(general, file->undo.history.strings); - general_memory_free(general, file->undo.history.edits); + general_memory_free(general, file->state.undo.history.strings); + general_memory_free(general, file->state.undo.history.edits); - general_memory_free(general, file->undo.children.strings); - general_memory_free(general, file->undo.children.edits); + general_memory_free(general, file->state.undo.children.strings); + general_memory_free(general, file->state.undo.children.edits); } } inline void file_get_dummy(Editing_File *file){ *file = {}; - file->is_dummy = 1; + file->state.is_dummy = 1; +} + +inline void +file_get_loading(Editing_File *file){ + *file = {}; + file->state.is_loading = 1; } struct Shift_Information{ i32 start, end, amount; }; -#if 0 //BUFFER_EXPERIMENT_SCALPEL <= 0 internal -Job_Callback(job_full_lex){ +Job_Callback_Sig(job_full_lex){ Editing_File *file = (Editing_File*)data[0]; General_Memory *general = (General_Memory*)data[1]; Cpp_File cpp_file; - cpp_file.data = file->buffer.data; - cpp_file.size = file->buffer.size; + cpp_file.data = file->state.buffer.data; + cpp_file.size = file->state.buffer.size; Cpp_Token_Stack tokens; tokens.tokens = (Cpp_Token*)memory->data; @@ -1638,6 +1631,7 @@ Job_Callback(job_full_lex){ Cpp_Lex_Data status; status = cpp_lex_file_nonalloc(cpp_file, &tokens); + while (!status.complete){ system->grow_thread_memory(memory); tokens.tokens = (Cpp_Token*)memory->data; @@ -1646,24 +1640,25 @@ Job_Callback(job_full_lex){ } i32 new_max = LargeRoundUp(tokens.count, Kbytes(1)); + system->acquire_lock(FRAME_LOCK); - if (file->token_stack.tokens){ - file->token_stack.tokens = (Cpp_Token*) - general_memory_reallocate_nocopy(general, file->token_stack.tokens, new_max*sizeof(Cpp_Token), BUBBLE_TOKENS); - } - else{ - file->token_stack.tokens = (Cpp_Token*) + { + Assert(file->state.swap_stack.tokens == 0); + file->state.swap_stack.tokens = (Cpp_Token*) general_memory_allocate(general, new_max*sizeof(Cpp_Token), BUBBLE_TOKENS); } system->release_lock(FRAME_LOCK); + + u8 *dest = (u8*)file->state.swap_stack.tokens; + u8 *src = (u8*)tokens.tokens; +#if 1 + memcpy(dest, src, tokens.count*sizeof(Cpp_Token)); +#else i32 copy_amount = Kbytes(8); i32 uncoppied = tokens.count*sizeof(Cpp_Token); if (copy_amount > uncoppied) copy_amount = uncoppied; - u8 *dest = (u8*)file->token_stack.tokens; - u8 *src = (u8*)tokens.tokens; - while (uncoppied > 0){ system->acquire_lock(FRAME_LOCK); memcpy(dest, src, copy_amount); @@ -1673,130 +1668,71 @@ Job_Callback(job_full_lex){ uncoppied -= copy_amount; if (copy_amount > uncoppied) copy_amount = uncoppied; } - - file->token_stack.count = tokens.count; - file->token_stack.max_count = new_max; - system->force_redraw(); - - // NOTE(allen): These are outside the locked section because I don't - // think getting these out of order will cause critical bugs, and I - // want to minimize what's done in locked sections. - file->tokens_complete = 1; - file->still_lexing = 0; -} -#else - -internal void -system_grow_memory(System_Functions *system, Data *memory){ - byte *old = memory->data; - i32 new_size = memory->size * 2; - memory->data = (byte*)system->get_memory(new_size); - memcpy(memory->data, old, memory->size); - system->free_memory(old); - memory->size = new_size; -} - -internal void -full_lex(System_Functions *system, Editing_File *file, General_Memory *general){ - Cpp_File cpp_file; - cpp_file.data = file->buffer.data; - cpp_file.size = file->buffer.size; - - Data memory_; - memory_.size = 64 << 10; - memory_.data = (byte*)system->get_memory(memory_.size); - - Data *memory = &memory_; - - Cpp_Token_Stack tokens; - tokens.tokens = (Cpp_Token*)memory->data; - tokens.max_count = memory->size / sizeof(Cpp_Token); - tokens.count = 0; - - Cpp_Lex_Data status; - status = cpp_lex_file_nonalloc(cpp_file, &tokens); - while (!status.complete){ - //system->grow_thread_memory(memory); - system_grow_memory(system, memory); - tokens.tokens = (Cpp_Token*)memory->data; - tokens.max_count = memory->size / sizeof(Cpp_Token); - status = cpp_lex_file_nonalloc(cpp_file, &tokens, status); - } - - i32 new_max = LargeRoundUp(tokens.count, Kbytes(1)); - if (file->token_stack.tokens){ - file->token_stack.tokens = (Cpp_Token*) - general_memory_reallocate_nocopy(general, file->token_stack.tokens, new_max*sizeof(Cpp_Token), BUBBLE_TOKENS); - } - else{ - file->token_stack.tokens = (Cpp_Token*) - general_memory_allocate(general, new_max*sizeof(Cpp_Token), BUBBLE_TOKENS); - } - - i32 copy_amount = Kbytes(8); - i32 uncoppied = tokens.count*sizeof(Cpp_Token); - if (copy_amount > uncoppied) copy_amount = uncoppied; - - u8 *dest = (u8*)file->token_stack.tokens; - u8 *src = (u8*)tokens.tokens; - - while (uncoppied > 0){ - memcpy(dest, src, copy_amount); - dest += copy_amount; - src += copy_amount; - uncoppied -= copy_amount; - if (copy_amount > uncoppied) copy_amount = uncoppied; - } - - file->token_stack.count = tokens.count; - file->token_stack.max_count = new_max; - system->force_redraw(); - - // NOTE(allen): These are outside the locked section because I don't - // think getting these out of order will cause critical bugs, and I - // want to minimize what's done in locked sections. - file->tokens_complete = 1; - file->still_lexing = 0; - - system->free_memory(memory_.data); -} - #endif + + system->acquire_lock(FRAME_LOCK); + { + file->state.token_stack.count = tokens.count; + file->state.token_stack.max_count = new_max; + if (file->state.token_stack.tokens) + general_memory_free(general, file->state.token_stack.tokens); + file->state.token_stack.tokens = file->state.swap_stack.tokens; + file->state.swap_stack.tokens = 0; + } + system->release_lock(FRAME_LOCK); + + exchange->force_redraw = 1; + + // NOTE(allen): These are outside the locked section because I don't + // think getting these out of order will cause critical bugs, and I + // want to minimize what's done in locked sections. + file->state.tokens_complete = 1; + file->state.still_lexing = 0; +} + internal void file_kill_tokens(System_Functions *system, General_Memory *general, Editing_File *file){ - if (file->still_lexing){ - system->cancel_job(BACKGROUND_THREADS, file->lex_job); + file->settings.tokens_exist = 0; + if (file->state.still_lexing){ + system->cancel_job(BACKGROUND_THREADS, file->state.lex_job); + if (file->state.swap_stack.tokens){ + general_memory_free(general, file->state.swap_stack.tokens); + file->state.swap_stack.tokens = 0; + } } - if (file->token_stack.tokens){ - general_memory_free(general, file->token_stack.tokens); + if (file->state.token_stack.tokens){ + general_memory_free(general, file->state.token_stack.tokens); } - file->tokens_exist = 0; - file->tokens_complete = 0; - file->token_stack = {}; + file->state.tokens_complete = 0; + file->state.token_stack = {}; } #if BUFFER_EXPERIMENT_SCALPEL <= 0 internal void file_first_lex_parallel(System_Functions *system, General_Memory *general, Editing_File *file){ - Assert(file->token_stack.tokens == 0); + file->settings.tokens_exist = 1; - file->tokens_complete = 0; - file->tokens_exist = 1; - file->still_lexing = 1; + if (file->state.is_loading == 0 && file->state.still_lexing == 0){ + Assert(file->state.token_stack.tokens == 0); + + file->state.tokens_complete = 0; + file->state.still_lexing = 1; - full_lex(system, file, general); - #if 0 - Job_Data job; - job.callback = job_full_lex; - job.data[0] = file; - job.data[1] = general; - job.memory_request = Kbytes(64); - file->lex_job = system->post_job(BACKGROUND_THREADS, job); + full_lex(system, file, general); +#else + + Job_Data job; + job.callback = job_full_lex; + job.data[0] = file; + job.data[1] = general; + job.memory_request = Kbytes(64); + file->state.lex_job = system->post_job(BACKGROUND_THREADS, job); #endif + } } internal void @@ -1805,18 +1741,18 @@ file_relex_parallel(System_Functions *system, i32 start_i, i32 end_i, i32 amount){ General_Memory *general = &mem->general; Partition *part = &mem->part; - if (file->token_stack.tokens == 0){ + if (file->state.token_stack.tokens == 0){ file_first_lex_parallel(system, general, file); return; } - b32 inline_lex = !file->still_lexing; + b32 inline_lex = !file->state.still_lexing; if (inline_lex){ Cpp_File cpp_file; - cpp_file.data = file->buffer.data; - cpp_file.size = file->buffer.size; + cpp_file.data = file->state.buffer.data; + cpp_file.size = file->state.buffer.size; - Cpp_Token_Stack *stack = &file->token_stack; + Cpp_Token_Stack *stack = &file->state.token_stack; Cpp_Relex_State state = cpp_relex_nonalloc_start(cpp_file, stack, @@ -1864,27 +1800,28 @@ file_relex_parallel(System_Functions *system, } if (!inline_lex){ - i32 end_token_i = cpp_get_end_token(&file->token_stack, end_i); - cpp_shift_token_starts(&file->token_stack, end_token_i, amount); + i32 end_token_i = cpp_get_end_token(&file->state.token_stack, end_i); + cpp_shift_token_starts(&file->state.token_stack, end_token_i, amount); --end_token_i; if (end_token_i >= 0){ - Cpp_Token *token = file->token_stack.tokens + end_token_i; + Cpp_Token *token = file->state.token_stack.tokens + end_token_i; if (token->start < end_i && token->start + token->size > end_i){ token->size += amount; } } - file->still_lexing = 1; - - full_lex(system, file, general); - + file->state.still_lexing = 1; + #if 0 + full_lex(system, file, general); +#else + Job_Data job; job.callback = job_full_lex; job.data[0] = file; job.data[1] = general; job.memory_request = Kbytes(64); - file->lex_job = system->post_job(BACKGROUND_THREADS, job); + file->state.lex_job = system->post_job(BACKGROUND_THREADS, job); #endif } } @@ -1973,11 +1910,11 @@ internal Edit_Step* file_post_undo(General_Memory *general, Editing_File *file, Edit_Step step, bool32 do_merge, bool32 can_merge){ if (step.type == ED_NORMAL){ - file->undo.redo.size = 0; - file->undo.redo.edit_count = 0; + file->state.undo.redo.size = 0; + file->state.undo.redo.edit_count = 0; } - Edit_Stack *undo = &file->undo.undo; + Edit_Stack *undo = &file->state.undo.undo; Edit_Step *result = 0; if (step.child_count == 0){ @@ -1985,7 +1922,7 @@ file_post_undo(General_Memory *general, Editing_File *file, undo_stack_grow_string(general, undo, step.edit.end - step.edit.start); Buffer_Edit inv; - buffer_invert_edit(&file->buffer, step.edit, &inv, + buffer_invert_edit(&file->state.buffer, step.edit, &inv, (char*)undo->strings, &undo->size, undo->max); Edit_Step inv_step = {}; @@ -2047,14 +1984,14 @@ undo_stack_pop(Edit_Stack *stack){ #if BUFFER_EXPERIMENT_SCALPEL <= 3 internal void file_post_redo(General_Memory *general, Editing_File *file, Edit_Step step){ - Edit_Stack *redo = &file->undo.redo; + Edit_Stack *redo = &file->state.undo.redo; if (step.child_count == 0){ if (step.edit.end - step.edit.start + redo->size > redo->max) undo_stack_grow_string(general, redo, step.edit.end - step.edit.start); Buffer_Edit inv; - buffer_invert_edit(&file->buffer, step.edit, &inv, + buffer_invert_edit(&file->state.buffer, step.edit, &inv, (char*)redo->strings, &redo->size, redo->max); Edit_Step inv_step = {}; @@ -2085,31 +2022,31 @@ file_post_redo(General_Memory *general, Editing_File *file, Edit_Step step){ inline void file_post_history_block(Editing_File *file, i32 pos){ - Assert(file->undo.history_head_block < pos); - Assert(pos < file->undo.history.edit_count); + Assert(file->state.undo.history_head_block < pos); + Assert(pos < file->state.undo.history.edit_count); - Edit_Step *history = file->undo.history.edits; - Edit_Step *step = history + file->undo.history_head_block; + Edit_Step *history = file->state.undo.history.edits; + Edit_Step *step = history + file->state.undo.history_head_block; step->next_block = pos; step = history + pos; - step->prev_block = file->undo.history_head_block; - file->undo.history_head_block = pos; - ++file->undo.history_block_count; + step->prev_block = file->state.undo.history_head_block; + file->state.undo.history_head_block = pos; + ++file->state.undo.history_block_count; } inline void file_unpost_history_block(Editing_File *file){ - Assert(file->undo.history_block_count > 1); - --file->undo.history_block_count; - Edit_Step *old_head = file->undo.history.edits + file->undo.history_head_block; - file->undo.history_head_block = old_head->prev_block; + Assert(file->state.undo.history_block_count > 1); + --file->state.undo.history_block_count; + Edit_Step *old_head = file->state.undo.history.edits + file->state.undo.history_head_block; + file->state.undo.history_head_block = old_head->prev_block; } #if BUFFER_EXPERIMENT_SCALPEL <= 3 internal Edit_Step* file_post_history(General_Memory *general, Editing_File *file, Edit_Step step, b32 do_merge, b32 can_merge){ - Edit_Stack *history = &file->undo.history; + Edit_Stack *history = &file->state.undo.history; Edit_Step *result = 0; persist Edit_Type reverse_types[4]; @@ -2125,7 +2062,7 @@ file_post_history(General_Memory *general, Editing_File *file, undo_stack_grow_string(general, history, step.edit.end - step.edit.start); Buffer_Edit inv; - buffer_invert_edit(&file->buffer, step.edit, &inv, + buffer_invert_edit(&file->state.buffer, step.edit, &inv, (char*)history->strings, &history->size, history->max); Edit_Step inv_step = {}; @@ -2182,53 +2119,67 @@ view_compute_cursor_from_pos(File_View *view, i32 pos){ #if BUFFER_EXPERIMENT_SCALPEL <= 3 Editing_File *file = view->file; Style *style = view->style; - Render_Font *font = style->font; + Render_Font *font = get_font_info(view->font_set, style->font_id)->font; + + Full_Cursor result = {}; + if (font){ + f32 max_width = view_compute_width(view); + result = buffer_cursor_from_pos(&file->state.buffer, pos, view->line_wrap_y, + max_width, (f32)view->font_height, font->advance_data); + } + return result; - real32 max_width = view_compute_width(view); - - return buffer_cursor_from_pos(&file->buffer, pos, view->line_wrap_y, - max_width, (real32)font->height, font->advance_data); #else return view->cursor; #endif } inline Full_Cursor -view_compute_cursor_from_unwrapped_xy(File_View *view, real32 seek_x, real32 seek_y, - bool32 round_down = 0){ +view_compute_cursor_from_unwrapped_xy(File_View *view, f32 seek_x, f32 seek_y, + b32 round_down = 0){ #if BUFFER_EXPERIMENT_SCALPEL <= 3 Editing_File *file = view->file; Style *style = view->style; - Render_Font *font = style->font; + Render_Font *font = get_font_info(view->font_set, style->font_id)->font; - real32 max_width = view_compute_width(view); + Full_Cursor result = {}; + if (font){ + real32 max_width = view_compute_width(view); + result = buffer_cursor_from_unwrapped_xy(&file->state.buffer, seek_x, seek_y, round_down, view->line_wrap_y, + max_width, (f32)view->font_height, font->advance_data); + } - return buffer_cursor_from_unwrapped_xy(&file->buffer, seek_x, seek_y, round_down, view->line_wrap_y, - max_width, (real32)font->height, font->advance_data); + return result; + #else return view->cursor; #endif } inline Full_Cursor -view_compute_cursor_from_wrapped_xy(File_View *view, real32 seek_x, real32 seek_y, - bool32 round_down = 0){ +view_compute_cursor_from_wrapped_xy(File_View *view, f32 seek_x, f32 seek_y, + b32 round_down = 0){ #if BUFFER_EXPERIMENT_SCALPEL <= 3 Editing_File *file = view->file; Style *style = view->style; - Render_Font *font = style->font; + Render_Font *font = get_font_info(view->font_set, style->font_id)->font; - real32 max_width = view_compute_width(view); + Full_Cursor result = {}; + if (font){ + f32 max_width = view_compute_width(view); + result = buffer_cursor_from_wrapped_xy(&file->state.buffer, seek_x, seek_y, round_down, view->line_wrap_y, + max_width, (f32)view->font_height, font->advance_data); + } + + return result; - return buffer_cursor_from_wrapped_xy(&file->buffer, seek_x, seek_y, round_down, view->line_wrap_y, - max_width, (real32)font->height, font->advance_data); #else return view->cursor; #endif } inline Full_Cursor -view_compute_cursor_from_xy(File_View *view, real32 seek_x, real32 seek_y){ +view_compute_cursor_from_xy(File_View *view, f32 seek_x, f32 seek_y){ Full_Cursor result; if (view->unwrapped_lines) result = view_compute_cursor_from_unwrapped_xy(view, seek_x, seek_y); else result = view_compute_cursor_from_wrapped_xy(view, seek_x, seek_y); @@ -2254,9 +2205,9 @@ view_get_cursor_pos(File_View *view){ return result; } -inline real32 +inline f32 view_get_cursor_x(File_View *view){ - real32 result; + f32 result; Full_Cursor *cursor; if (view->show_temp_highlight){ cursor = &view->temp_highlight; @@ -2273,10 +2224,10 @@ view_get_cursor_x(File_View *view){ return result; } -inline real32 +inline f32 view_get_cursor_y(File_View *view){ Full_Cursor *cursor; - real32 result; + f32 result; if (view->show_temp_highlight) cursor = &view->temp_highlight; else cursor = &view->cursor; @@ -2288,23 +2239,33 @@ view_get_cursor_y(File_View *view){ } internal void -view_set_file(System_Functions *system, - File_View *view, Editing_File *file, Style *style, - Custom_Command_Function *open_hook, void *cmd_context, Application_Links app){ +view_file_loaded_init(System_Functions *system, File_View *view, i32 cursor_pos){ + General_Memory *general = &view->view_base.mem->general; + + view_measure_wraps(system, general, view); + view->cursor = view_compute_cursor_from_pos(view, cursor_pos); +} + +internal void +view_set_file(System_Functions *system, File_View *view, Editing_File *file, + Font_Set *set, Style *style, Custom_Command_Function *open_hook, + void *cmd_context, Application_Links *app){ Panel *panel = view->view_base.panel; view->file = file; - view->locked = file->super_locked; - - General_Memory *general = &view->view_base.mem->general; - Render_Font *font = style->font; - view->style = style; - view->font_advance = font->advance; - view->font_height = font->height; + view->locked = file->settings.super_locked; - view_measure_wraps(system, general, view); + Font_Info *info = get_font_info(set, style->font_id); + view->style = style; + view->font_advance = info->advance; + view->font_height = info->height; + view->font_set = set; + file->settings.set = set; view->cursor = {}; - view->cursor = view_compute_cursor_from_pos(view, file->cursor_pos); + + if (!file->state.is_loading){ + view_file_loaded_init(system, view, file->state.cursor_pos); + } f32 cursor_x, cursor_y; f32 w, h; @@ -2371,7 +2332,7 @@ inline void view_cursor_move(File_View *view, Full_Cursor cursor){ view->cursor = cursor; view->preferred_x = view_get_cursor_x(view); - view->file->cursor_pos = view->cursor.pos; + view->file->state.cursor_pos = view->cursor.pos; view->show_temp_highlight = 0; } @@ -2379,7 +2340,7 @@ inline void view_cursor_move(File_View *view, i32 pos){ view->cursor = view_compute_cursor_from_pos(view, pos); view->preferred_x = view_get_cursor_x(view); - view->file->cursor_pos = view->cursor.pos; + view->file->state.cursor_pos = view->cursor.pos; view->show_temp_highlight = 0; } @@ -2392,7 +2353,7 @@ view_cursor_move(File_View *view, real32 x, real32 y, bool32 round_down = 0){ view->cursor = view_compute_cursor_from_wrapped_xy(view, x, y, round_down); } view->preferred_x = view_get_cursor_x(view); - view->file->cursor_pos = view->cursor.pos; + view->file->state.cursor_pos = view->cursor.pos; view->show_temp_highlight = 0; } @@ -2402,26 +2363,26 @@ view_set_widget(File_View *view, File_View_Widget_Type type){ } inline i32 -view_widget_height(File_View *view, Render_Font *font){ +view_widget_height(File_View *view, i32 font_height){ i32 result = 0; switch (view->widget.type){ case FWIDG_NONE: break; - case FWIDG_SEARCH: result = font->height + 2; break; - case FWIDG_GOTO_LINE: result = font->height + 2; break; + case FWIDG_SEARCH: result = font_height + 2; break; + case FWIDG_GOTO_LINE: result = font_height + 2; break; case FWIDG_TIMELINES: result = view->widget.height; break; } return result; } inline i32_Rect -view_widget_rect(File_View *view, Render_Font *font){ +view_widget_rect(File_View *view, i32 font_height){ Panel *panel = view->view_base.panel; i32_Rect whole = panel->inner; i32_Rect result; result.x0 = whole.x0; result.x1 = whole.x1; - result.y0 = whole.y0 + font->height + 2; - result.y1 = result.y0 + view_widget_height(view, font); + result.y0 = whole.y0 + font_height + 2; + result.y1 = result.y0 + view_widget_height(view, font_height); return result; } @@ -2449,25 +2410,25 @@ enum History_Mode{ internal void file_update_history_before_edit(Mem_Options *mem, Editing_File *file, Edit_Step step, u8 *str, History_Mode history_mode){ - if (!file->undo.undo.edits) return; + if (!file->state.undo.undo.edits) return; #if BUFFER_EXPERIMENT_SCALPEL <= 3 General_Memory *general = &mem->general; #if FRED_SLOW if (history_mode == hist_backward) - debug_edit_step_check(step, file->undo.history.edits[file->undo.edit_history_cursor]); + debug_edit_step_check(step, file->state.undo.history.edits[file->state.undo.edit_history_cursor]); else if (history_mode == hist_forward) - debug_edit_step_check(step, file->undo.history.edits[file->undo.history.edit_count]); + debug_edit_step_check(step, file->state.undo.history.edits[file->state.undo.history.edit_count]); switch (step.type){ case ED_UNDO: { - Assert(file->undo.undo.edit_count > 0); - debug_edit_step_check(step, file->undo.undo.edits[file->undo.undo.edit_count-1]); + Assert(file->state.undo.undo.edit_count > 0); + debug_edit_step_check(step, file->state.undo.undo.edits[file->state.undo.undo.edit_count-1]); }break; case ED_REDO: { - Assert(file->undo.redo.edit_count > 0); - debug_edit_step_check(step, file->undo.redo.edits[file->undo.redo.edit_count-1]); + Assert(file->state.undo.redo.edit_count > 0); + debug_edit_step_check(step, file->state.undo.redo.edits[file->state.undo.redo.edit_count-1]); }break; } #endif @@ -2490,18 +2451,18 @@ file_update_history_before_edit(Mem_Options *mem, Editing_File *file, Edit_Step if (history_mode != hist_forward) file_post_history(general, file, step, do_merge, can_merge); - undo_stack_pop(&file->undo.undo); + undo_stack_pop(&file->state.undo.undo); b32 restore_redos = 0; Edit_Step *redo_end = 0; - if (history_mode == hist_backward && file->undo.edit_history_cursor > 0){ + if (history_mode == hist_backward && file->state.undo.edit_history_cursor > 0){ restore_redos = 1; - redo_end = file->undo.history.edits + (file->undo.edit_history_cursor - 1); + redo_end = file->state.undo.history.edits + (file->state.undo.edit_history_cursor - 1); } - else if (history_mode == hist_forward && file->undo.history.edit_count > 0){ + else if (history_mode == hist_forward && file->state.undo.history.edit_count > 0){ restore_redos = 1; - redo_end = file->undo.history.edits + (file->undo.history.edit_count - 1); + redo_end = file->state.undo.history.edits + (file->state.undo.history.edit_count - 1); } if (restore_redos){ @@ -2527,18 +2488,19 @@ file_update_history_before_edit(Mem_Options *mem, Editing_File *file, Edit_Step ++redo_start; ++redo_end; - if (file->undo.redo.edit_count + steps_of_redo > file->undo.redo.edit_max) - undo_stack_grow_edits(general, &file->undo.redo); + if (file->state.undo.redo.edit_count + steps_of_redo > file->state.undo.redo.edit_max) + undo_stack_grow_edits(general, &file->state.undo.redo); - if (file->undo.redo.size + strings_of_redo > file->undo.redo.max) - undo_stack_grow_string(general, &file->undo.redo, strings_of_redo); + if (file->state.undo.redo.size + strings_of_redo > file->state.undo.redo.max) + undo_stack_grow_string(general, &file->state.undo.redo, strings_of_redo); - u8 *str_src = file->undo.history.strings + redo_end->edit.str_start; - u8 *str_dest_base = file->undo.redo.strings; - i32 str_redo_pos = file->undo.redo.size + strings_of_redo; + u8 *str_src = file->state.undo.history.strings + redo_end->edit.str_start; + u8 *str_dest_base = file->state.undo.redo.strings; + i32 str_redo_pos = file->state.undo.redo.size + strings_of_redo; Edit_Step *edit_src = redo_end; - Edit_Step *edit_dest = file->undo.redo.edits + file->undo.redo.edit_count + steps_of_redo; + Edit_Step *edit_dest = + file->state.undo.redo.edits + file->state.undo.redo.edit_count + steps_of_redo; i32 undo_count = 0; for (i32 i = 0; i < steps_of_redo;){ @@ -2566,8 +2528,8 @@ file_update_history_before_edit(Mem_Options *mem, Editing_File *file, Edit_Step } Assert(undo_count == 0); - file->undo.redo.size += strings_of_redo; - file->undo.redo.edit_count += steps_of_redo; + file->state.undo.redo.size += strings_of_redo; + file->state.undo.redo.edit_count += steps_of_redo; } } }break; @@ -2577,7 +2539,7 @@ file_update_history_before_edit(Mem_Options *mem, Editing_File *file, Edit_Step if (history_mode != hist_forward) file_post_history(general, file, step, do_merge, can_merge); file_post_redo(general, file, step); - undo_stack_pop(&file->undo.undo); + undo_stack_pop(&file->state.undo.undo); }break; case ED_REDO: @@ -2589,32 +2551,34 @@ file_update_history_before_edit(Mem_Options *mem, Editing_File *file, Edit_Step file_post_history(general, file, step, do_merge, can_merge); file_post_undo(general, file, step, do_merge, can_merge); - undo_stack_pop(&file->undo.redo); + undo_stack_pop(&file->state.undo.redo); }break; } if (history_mode != hist_forward){ if (step.type == ED_UNDO || step.type == ED_REDO){ - if (file->undo.current_block_normal){ - file_post_history_block(file, file->undo.history.edit_count - 1); - file->undo.current_block_normal = 0; + if (file->state.undo.current_block_normal){ + file_post_history_block(file, file->state.undo.history.edit_count - 1); + file->state.undo.current_block_normal = 0; } } else{ - if (!file->undo.current_block_normal){ - file_post_history_block(file, file->undo.history.edit_count - 1); - file->undo.current_block_normal = 1; + if (!file->state.undo.current_block_normal){ + file_post_history_block(file, file->state.undo.history.edit_count - 1); + file->state.undo.current_block_normal = 1; } } } else{ - if (file->undo.history_head_block == file->undo.history.edit_count){ + if (file->state.undo.history_head_block == file->state.undo.history.edit_count){ file_unpost_history_block(file); - file->undo.current_block_normal = !file->undo.current_block_normal; + file->state.undo.current_block_normal = !file->state.undo.current_block_normal; } } - if (history_mode == hist_normal) file->undo.edit_history_cursor = file->undo.history.edit_count; + if (history_mode == hist_normal){ + file->state.undo.edit_history_cursor = file->state.undo.history.edit_count; + } #endif } @@ -2634,10 +2598,16 @@ debug_step_match(Edit_Step a, Edit_Step b){ inline void file_pre_edit_maintenance(System_Functions *system, + General_Memory *general, Editing_File *file){ - if (file->still_lexing) - system->cancel_job(BACKGROUND_THREADS, file->lex_job); - file->last_4ed_edit_time = system->time_stamp_now(); + if (file->state.still_lexing){ + system->cancel_job(BACKGROUND_THREADS, file->state.lex_job); + if (file->state.swap_stack.tokens){ + general_memory_free(general, file->state.swap_stack.tokens); + file->state.swap_stack.tokens = 0; + } + } + file->state.last_4ed_edit_time = system->time(); } internal void @@ -2648,7 +2618,7 @@ file_do_single_edit(System_Functions *system, // NOTE(allen): fixing stuff beforewards???? file_update_history_before_edit(mem, file, spec.step, spec.str, history_mode); - file_pre_edit_maintenance(system, file); + file_pre_edit_maintenance(system, &mem->general, file); // NOTE(allen): actual text replacement #if BUFFER_EXPERIMENT_SCALPEL <= 3 @@ -2665,13 +2635,13 @@ file_do_single_edit(System_Functions *system, Assert(scratch_size > 0); i32 request_amount = 0; - while (buffer_replace_range(&file->buffer, start, end, str, str_len, &shift_amount, + while (buffer_replace_range(&file->state.buffer, start, end, str, str_len, &shift_amount, part->base + part->pos, scratch_size, &request_amount)){ void *new_data = 0; if (request_amount > 0){ new_data = general_memory_allocate(general, request_amount, BUBBLE_BUFFER); } - void *old_data = buffer_edit_provide_memory(&file->buffer, new_data, request_amount); + void *old_data = buffer_edit_provide_memory(&file->state.buffer, new_data, request_amount); if (old_data) general_memory_free(general, old_data); } @@ -2683,15 +2653,21 @@ file_do_single_edit(System_Functions *system, buffer_mugab_check(&file->buffer); #endif - i32 line_start = buffer_get_line_index(&file->buffer, start); - i32 line_end = buffer_get_line_index(&file->buffer, end); + i32 line_start = buffer_get_line_index(&file->state.buffer, start); + i32 line_end = buffer_get_line_index(&file->state.buffer, end); i32 replaced_line_count = line_end - line_start; - i32 new_line_count = buffer_count_newlines(&file->buffer, start, start+str_len); + i32 new_line_count = buffer_count_newlines(&file->state.buffer, start, start+str_len); i32 line_shift = new_line_count - replaced_line_count; - file_remeasure_starts(system, general, &file->buffer, line_start, line_end, line_shift, shift_amount); - file_remeasure_widths(system, general, &file->buffer, file->font, line_start, line_end, line_shift); - + file_remeasure_starts(system, general, &file->state.buffer, + line_start, line_end, line_shift, shift_amount); + + Render_Font *font = get_font_info(file->settings.set, file->state.font_id)->font; + if (font){ + file_remeasure_widths(system, general, &file->state.buffer, + font, line_start, line_end, line_shift); + } + i32 panel_count = layout->panel_count; Panel *current_panel = layout->panels; for (i32 i = 0; i < panel_count; ++i, ++current_panel){ @@ -2704,7 +2680,7 @@ file_do_single_edit(System_Functions *system, #if BUFFER_EXPERIMENT_SCALPEL <= 0 // NOTE(allen): fixing stuff afterwards - if (file->tokens_exist) + if (file->settings.tokens_exist) file_relex_parallel(system, mem, file, start, end, shift_amount); #endif @@ -2755,38 +2731,38 @@ view_do_white_batch_edit(System_Functions *system, Assert(file); ProfileMomentFunction(); - // NOTE(allen): fixing stuff beforewards???? + // NOTE(allen): fixing stuff "beforewards"???? Assert(spec.str == 0); file_update_history_before_edit(mem, file, spec.step, 0, history_mode); - file_pre_edit_maintenance(system, file); + file_pre_edit_maintenance(system, &mem->general, file); // NOTE(allen): actual text replacement General_Memory *general = &mem->general; Partition *part = &mem->part; - u8 *str_base = file->undo.children.strings; + u8 *str_base = file->state.undo.children.strings; i32 batch_size = spec.step.child_count; - Buffer_Edit *batch = file->undo.children.edits + spec.step.first_child; + Buffer_Edit *batch = file->state.undo.children.edits + spec.step.first_child; - Assert(spec.step.first_child < file->undo.children.edit_count); + Assert(spec.step.first_child < file->state.undo.children.edit_count); Assert(batch_size >= 0); i32 scratch_size = partition_remaining(part); Buffer_Batch_State state = {}; i32 request_amount; - while (buffer_batch_edit_step(&state, &file->buffer, batch, (char*)str_base, batch_size, + while (buffer_batch_edit_step(&state, &file->state.buffer, batch, (char*)str_base, batch_size, part->base + part->pos, scratch_size, &request_amount)){ void *new_data = 0; if (request_amount > 0){ new_data = general_memory_allocate(general, request_amount, BUBBLE_BUFFER); } - void *old_data = buffer_edit_provide_memory(&file->buffer, new_data, request_amount); + void *old_data = buffer_edit_provide_memory(&file->state.buffer, new_data, request_amount); if (old_data) general_memory_free(general, old_data); } // NOTE(allen): token fixing - if (file->tokens_complete){ - Cpp_Token_Stack tokens = file->token_stack; + if (file->state.tokens_complete){ + Cpp_Token_Stack tokens = file->state.token_stack; Cpp_Token *token = tokens.tokens; Cpp_Token *end_token = tokens.tokens + tokens.count; @@ -2815,7 +2791,10 @@ view_do_white_batch_edit(System_Functions *system, // NOTE(allen): meta data { Buffer_Measure_Starts state = {}; - buffer_measure_starts_widths(&state, &file->buffer, file->font->advance_data); + Render_Font *font = get_font_info(file->settings.set, file->state.font_id)->font; + float *advance_data = 0; + if (font) advance_data = font->advance_data; + buffer_measure_starts_widths(&state, &file->state.buffer, advance_data); } // NOTE(allen): cursor fixing @@ -2918,13 +2897,13 @@ view_undo_redo(System_Functions *system, inline void view_undo(System_Functions *system, Mem_Options *mem, Editing_Layout *layout, File_View *view){ Editing_File *file = view->file; - view_undo_redo(system, mem, layout, view, file, &file->undo.undo, ED_UNDO); + view_undo_redo(system, mem, layout, view, file, &file->state.undo.undo, ED_UNDO); } inline void view_redo(System_Functions *system, Mem_Options *mem, Editing_Layout *layout, File_View *view){ Editing_File *file = view->file; - view_undo_redo(system, mem, layout, view, file, &file->undo.redo, ED_REDO); + view_undo_redo(system, mem, layout, view, file, &file->state.undo.redo, ED_REDO); } inline u8* @@ -2933,29 +2912,32 @@ write_data(u8 *ptr, void *x, i32 size){ return (ptr + size); } +#define UseFileHistoryDump 0 + +#if UseFileHistoryDump internal void file_dump_history(System_Functions *system, Mem_Options *mem, Editing_File *file, char *filename){ - if (!file->undo.undo.edits) return; + if (!file->state.undo.undo.edits) return; i32 size = 0; size += sizeof(i32); - size += file->undo.undo.edit_count*sizeof(Edit_Step); + size += file->state.undo.undo.edit_count*sizeof(Edit_Step); size += sizeof(i32); - size += file->undo.redo.edit_count*sizeof(Edit_Step); + size += file->state.undo.redo.edit_count*sizeof(Edit_Step); size += sizeof(i32); - size += file->undo.history.edit_count*sizeof(Edit_Step); + size += file->state.undo.history.edit_count*sizeof(Edit_Step); size += sizeof(i32); - size += file->undo.children.edit_count*sizeof(Buffer_Edit); + size += file->state.undo.children.edit_count*sizeof(Buffer_Edit); size += sizeof(i32); - size += file->undo.undo.size; + size += file->state.undo.undo.size; size += sizeof(i32); - size += file->undo.redo.size; + size += file->state.undo.redo.size; size += sizeof(i32); - size += file->undo.history.size; + size += file->state.undo.history.size; size += sizeof(i32); - size += file->undo.children.size; + size += file->state.undo.children.size; Partition *part = &mem->part; i32 remaining = partition_remaining(part); @@ -2963,29 +2945,30 @@ file_dump_history(System_Functions *system, Mem_Options *mem, Editing_File *file u8 *data, *curs; data = (u8*)part->base + part->pos; curs = data; - curs = write_data(curs, &file->undo.undo.edit_count, 4); - curs = write_data(curs, &file->undo.redo.edit_count, 4); - curs = write_data(curs, &file->undo.history.edit_count, 4); - curs = write_data(curs, &file->undo.children.edit_count, 4); - curs = write_data(curs, &file->undo.undo.size, 4); - curs = write_data(curs, &file->undo.redo.size, 4); - curs = write_data(curs, &file->undo.history.size, 4); - curs = write_data(curs, &file->undo.children.size, 4); + curs = write_data(curs, &file->state.undo.undo.edit_count, 4); + curs = write_data(curs, &file->state.undo.redo.edit_count, 4); + curs = write_data(curs, &file->state.undo.history.edit_count, 4); + curs = write_data(curs, &file->state.undo.children.edit_count, 4); + curs = write_data(curs, &file->state.undo.undo.size, 4); + curs = write_data(curs, &file->state.undo.redo.size, 4); + curs = write_data(curs, &file->state.undo.history.size, 4); + curs = write_data(curs, &file->state.undo.children.size, 4); - curs = write_data(curs, file->undo.undo.edits, sizeof(Edit_Step)*file->undo.undo.edit_count); - curs = write_data(curs, file->undo.redo.edits, sizeof(Edit_Step)*file->undo.redo.edit_count); - curs = write_data(curs, file->undo.history.edits, sizeof(Edit_Step)*file->undo.history.edit_count); - curs = write_data(curs, file->undo.children.edits, sizeof(Buffer_Edit)*file->undo.children.edit_count); + curs = write_data(curs, file->state.undo.undo.edits, sizeof(Edit_Step)*file->state.undo.undo.edit_count); + curs = write_data(curs, file->state.undo.redo.edits, sizeof(Edit_Step)*file->state.undo.redo.edit_count); + curs = write_data(curs, file->state.undo.history.edits, sizeof(Edit_Step)*file->state.undo.history.edit_count); + curs = write_data(curs, file->state.undo.children.edits, sizeof(Buffer_Edit)*file->state.undo.children.edit_count); - curs = write_data(curs, file->undo.undo.strings, file->undo.undo.size); - curs = write_data(curs, file->undo.redo.strings, file->undo.redo.size); - curs = write_data(curs, file->undo.history.strings, file->undo.history.size); - curs = write_data(curs, file->undo.children.strings, file->undo.children.size); + curs = write_data(curs, file->state.undo.undo.strings, file->state.undo.undo.size); + curs = write_data(curs, file->state.undo.redo.strings, file->state.undo.redo.size); + curs = write_data(curs, file->state.undo.history.strings, file->state.undo.history.size); + curs = write_data(curs, file->state.undo.children.strings, file->state.undo.children.size); Assert((i32)(curs - data) == size); system->save_file(filename, data, size); } } +#endif internal void view_history_step(System_Functions *system, Mem_Options *mem, Editing_Layout *layout, File_View *view, History_Mode history_mode){ @@ -2997,17 +2980,17 @@ view_history_step(System_Functions *system, Mem_Options *mem, Editing_Layout *la b32 do_history_step = 0; Edit_Step step = {}; if (history_mode == hist_backward){ - if (file->undo.edit_history_cursor > 0){ + if (file->state.undo.edit_history_cursor > 0){ do_history_step = 1; - step = file->undo.history.edits[--file->undo.edit_history_cursor]; + step = file->state.undo.history.edits[--file->state.undo.edit_history_cursor]; } } else{ - if (file->undo.edit_history_cursor < file->undo.history.edit_count){ - Assert(((file->undo.history.edit_count - file->undo.edit_history_cursor) & 1) == 0); - step = file->undo.history.edits[--file->undo.history.edit_count]; - file->undo.history.size -= step.edit.len; - ++file->undo.edit_history_cursor; + if (file->state.undo.edit_history_cursor < file->state.undo.history.edit_count){ + Assert(((file->state.undo.history.edit_count - file->state.undo.edit_history_cursor) & 1) == 0); + step = file->state.undo.history.edits[--file->state.undo.history.edit_count]; + file->state.undo.history.size -= step.edit.len; + ++file->state.undo.edit_history_cursor; do_history_step = 1; } } @@ -3018,7 +3001,7 @@ view_history_step(System_Functions *system, Mem_Options *mem, Editing_Layout *la if (spec.step.child_count == 0){ spec.step.edit.str_start = 0; - spec.str = file->undo.history.strings + step.edit.str_start; + spec.str = file->state.undo.history.strings + step.edit.str_start; file_do_single_edit(system, mem, file, layout, spec, history_mode); @@ -3047,9 +3030,9 @@ internal i32 view_find_end_of_line(File_View *view, i32 pos){ #if BUFFER_EXPERIMENT_SCALPEL <= 0 Editing_File *file = view->file; - char *data = file->buffer.data; - while (pos < file->buffer.size && data[pos] != '\n') ++pos; - if (pos > file->buffer.size) pos = file->buffer.size; + char *data = file->state.buffer.data; + while (pos < file->state.buffer.size && data[pos] != '\n') ++pos; + if (pos > file->state.buffer.size) pos = file->state.buffer.size; #endif return pos; } @@ -3058,7 +3041,7 @@ internal i32 view_find_beginning_of_line(File_View *view, i32 pos){ #if BUFFER_EXPERIMENT_SCALPEL <= 0 Editing_File *file = view->file; - char *data = file->buffer.data; + char *data = file->state.buffer.data; if (pos > 0){ --pos; while (pos > 0 && data[pos] != '\n') --pos; @@ -3072,12 +3055,12 @@ internal i32 view_find_beginning_of_next_line(File_View *view, i32 pos){ #if BUFFER_EXPERIMENT_SCALPEL <= 0 Editing_File *file = view->file; - char *data = file->buffer.data; - while (pos < file->buffer.size && + char *data = file->state.buffer.data; + while (pos < file->state.buffer.size && !starts_new_line(data[pos])){ ++pos; } - if (pos < file->buffer.size){ + if (pos < file->state.buffer.size){ ++pos; } #endif @@ -3164,7 +3147,8 @@ working_set_lookup_file(Working_Set *working_set, String string){ i32 end = working_set->file_index_count; file = working_set->files; for (file_i = 0; file_i < end; ++file_i, ++file){ - if (file->live_name.str && (string.size == 0 || has_substr(file->live_name, string))){ + if (file->state.live_name.str && + (string.size == 0 || has_substr(file->state.live_name, string))){ break; } } @@ -3179,7 +3163,7 @@ clipboard_copy(System_Functions *system, General_Memory *general, Working_Set *w #if BUFFER_EXPERIMENT_SCALPEL <= 3 i32 size = range.end - range.start; String *dest = working_set_next_clipboard_string(general, working, size); - buffer_stringify(&file->buffer, range.start, range.end, dest->str); + buffer_stringify(&file->state.buffer, range.start, range.end, dest->str); dest->size = size; system->post_clipboard(*dest); #endif @@ -3195,15 +3179,15 @@ file_compute_whitespace_edit(Mem_Options *mem, Editing_File *file, i32 cursor_po i32 inv_str_pos = 0; Buffer_Invert_Batch state = {}; - if (buffer_invert_batch(&state, &file->buffer, edits, edit_count, + if (buffer_invert_batch(&state, &file->state.buffer, edits, edit_count, inverse_array, inv_str, &inv_str_pos, inv_max)) Assert(0); i32 first_child = - undo_children_push(general, &file->undo.children, + undo_children_push(general, &file->state.undo.children, edits, edit_count, (u8*)(str_base), str_size); i32 inverse_first_child = - undo_children_push(general, &file->undo.children, + undo_children_push(general, &file->state.undo.children, inverse_array, edit_count, (u8*)(inv_str), inv_str_pos); Edit_Spec spec = {}; @@ -3226,9 +3210,9 @@ internal void view_clean_whitespace(System_Functions *system, Mem_Options *mem, File_View *view, Editing_Layout *layout){ #if BUFFER_EXPERIMENT_SCALPEL <= 3 Editing_File *file = view->file; - Assert(file && !file->is_dummy); + Assert(file && !file->state.is_dummy); Partition *part = &mem->part; - i32 line_count = file->buffer.line_count; + i32 line_count = file->state.buffer.line_count; i32 edit_max = line_count * 2; i32 edit_count = 0; @@ -3238,12 +3222,12 @@ view_clean_whitespace(System_Functions *system, Mem_Options *mem, File_View *vie char *str_base = (char*)part->base + part->pos; i32 str_size = 0; for (i32 line_i = 0; line_i < line_count; ++line_i){ - i32 start = file->buffer.line_starts[line_i]; + i32 start = file->state.buffer.line_starts[line_i]; i32 preferred_indentation; bool32 all_whitespace = 0; bool32 all_space = 0; i32 hard_start = - buffer_find_hard_start(&file->buffer, start, &all_whitespace, &all_space, + buffer_find_hard_start(&file->state.buffer, start, &all_whitespace, &all_space, &preferred_indentation, 4); if (all_whitespace) preferred_indentation = 0; @@ -3287,10 +3271,10 @@ view_auto_tab_tokens(System_Functions *system, i32 start, i32 end, b32 empty_blank_lines){ #if BUFFER_EXPERIMENT_SCALPEL <= 0 Editing_File *file = view->file; - Assert(file && !file->is_dummy); + Assert(file && !file->state.is_dummy); Partition *part = &mem->part; - Buffer *buffer = &file->buffer; - Cpp_Token_Stack tokens = file->token_stack; + Buffer *buffer = &file->state.buffer; + Cpp_Token_Stack tokens = file->state.token_stack; Assert(tokens.tokens); i32 line_start = buffer_get_line_index(buffer, start); @@ -3309,7 +3293,7 @@ view_auto_tab_tokens(System_Functions *system, Cpp_Token *token, *self_token; { - i32 start_pos = file->buffer.line_starts[line_start]; + i32 start_pos = file->state.buffer.line_starts[line_start]; Cpp_Get_Token_Result result = cpp_get_token(&tokens, start_pos); token_i = result.token_index; if (result.in_whitespace) token_i += 1; @@ -3318,10 +3302,11 @@ view_auto_tab_tokens(System_Functions *system, i32 line = line_start - 1; for (; line >= 0; --line){ - i32 start = file->buffer.line_starts[line]; + i32 start = file->state.buffer.line_starts[line]; b32 all_whitespace = 0; b32 all_space = 0; - buffer_find_hard_start(&file->buffer, start, &all_whitespace, &all_space, ¤t_indent, 4); + buffer_find_hard_start(&file->state.buffer, start, + &all_whitespace, &all_space, ¤t_indent, 4); if (!all_whitespace) break; } @@ -3330,7 +3315,7 @@ view_auto_tab_tokens(System_Functions *system, token = tokens.tokens + token_i; } else{ - i32 start_pos = file->buffer.line_starts[line]; + i32 start_pos = file->state.buffer.line_starts[line]; Cpp_Get_Token_Result result = cpp_get_token(&tokens, start_pos); token_i = result.token_index; if (result.in_whitespace) token_i += 1; @@ -3347,18 +3332,19 @@ view_auto_tab_tokens(System_Functions *system, current_indent = 0; } else if (token->start < start_pos){ - line = buffer_get_line_index(&file->buffer, token->start); - i32 start = file->buffer.line_starts[line]; + line = buffer_get_line_index(&file->state.buffer, token->start); + i32 start = file->state.buffer.line_starts[line]; b32 all_whitespace = 0; b32 all_space = 0; - buffer_find_hard_start(&file->buffer, start, &all_whitespace, &all_space, ¤t_indent, 4); + buffer_find_hard_start(&file->state.buffer, start, + &all_whitespace, &all_space, ¤t_indent, 4); Assert(!all_whitespace); } } indent_marks -= line_start; i32 line_i = line_start; - i32 next_line_start = file->buffer.line_starts[line_i]; + i32 next_line_start = file->state.buffer.line_starts[line_i]; switch (token->type){ case CPP_TOKEN_BRACKET_OPEN: current_indent += 4; break; case CPP_TOKEN_PARENTHESE_OPEN: current_indent += 4; break; @@ -3370,7 +3356,7 @@ view_auto_tab_tokens(System_Functions *system, for (; line_i < line_end; ++token_i, ++token){ for (; token->start >= next_line_start && line_i < line_end;){ i32 this_line_start = next_line_start; - next_line_start = file->buffer.line_starts[line_i+1]; + next_line_start = file->state.buffer.line_starts[line_i+1]; i32 this_indent; if (prev_token && prev_token->type == CPP_TOKEN_COMMENT && prev_token->start <= this_line_start && prev_token->start + prev_token->size > this_line_start){ @@ -3425,13 +3411,13 @@ view_auto_tab_tokens(System_Functions *system, char *str_base = (char*)part->base + part->pos; i32 str_size = 0; for (i32 line_i = line_start; line_i < line_end; ++line_i){ - i32 start = file->buffer.line_starts[line_i]; + i32 start = file->state.buffer.line_starts[line_i]; i32 preferred_indentation; i32 correct_indentation; bool32 all_whitespace = 0; bool32 all_space = 0; i32 hard_start = - buffer_find_hard_start(&file->buffer, start, &all_whitespace, &all_space, + buffer_find_hard_start(&file->state.buffer, start, &all_whitespace, &all_space, &preferred_indentation, 4); correct_indentation = indent_marks[line_i]; @@ -3598,7 +3584,7 @@ view_compute_max_target_y(i32 lowest_line, i32 line_height, real32 view_height){ internal real32 view_compute_max_target_y(File_View *view){ i32 lowest_line = view_compute_lowest_line(view); - i32 line_height = view->style->font->height; + i32 line_height = view->font_height; real32 view_height = view_compute_height(view); real32 max_target_y = view_compute_max_target_y( lowest_line, line_height, view_height); @@ -3615,12 +3601,12 @@ remeasure_file_view(System_Functions *system, View *view_, i32_Rect rect){ view_set_relative_scrolling(view, relative); } -internal bool32 +internal b32 do_button(i32 id, UI_State *state, UI_Layout *layout, char *text, i32 height_mult, - bool32 is_toggle = 0, bool32 on = 0){ - bool32 result = 0; - Render_Font *font = state->font; - i32 character_h = font->height; + b32 is_toggle = 0, b32 on = 0){ + b32 result = 0; + i16 font_id = state->style->font_id; + i32 character_h = get_font_info(state->font_set, font_id)->height; i32_Rect btn_rect = layout_rect(layout, character_h * height_mult); if (height_mult > 1) btn_rect = get_inner_rect(btn_rect, 2); @@ -3645,11 +3631,11 @@ do_button(i32 id, UI_State *state, UI_Layout *layout, char *text, i32 height_mul draw_rectangle(target, btn_rect, back); draw_rectangle_outline(target, btn_rect, outline); - real32 text_width = font_string_width(font, text); + real32 text_width = font_string_width(target, font_id, text); i32 box_width = btn_rect.x1 - btn_rect.x0; i32 box_height = btn_rect.y1 - btn_rect.y0; i32 x_pos = TRUNC32(btn_rect.x0 + (box_width - text_width)*.5f); - draw_string(target, font, text, x_pos, btn_rect.y0 + (box_height - character_h) / 2, fore); + draw_string(target, font_id, text, x_pos, btn_rect.y0 + (box_height - character_h) / 2, fore); if (is_toggle){ i32_Rect on_box = get_inner_rect(btn_rect, character_h/2); @@ -3664,11 +3650,11 @@ do_button(i32 id, UI_State *state, UI_Layout *layout, char *text, i32 height_mul return result; } -internal bool32 +internal b32 do_undo_slider(Widget_ID wid, UI_State *state, UI_Layout *layout, i32 max, i32 v, Undo_Data *undo, i32 *out){ - bool32 result = 0; - Render_Font *font = state->font; - i32 character_h = font->height; + b32 result = 0; + i16 font_id = state->style->font_id; + i32 character_h = get_font_info(state->font_set, font_id)->height; i32_Rect containing_rect = layout_rect(layout, character_h); @@ -3688,8 +3674,8 @@ do_undo_slider(Widget_ID wid, UI_State *state, UI_Layout *layout, i32 max, i32 v } } else{ + Render_Target *target = state->target; if (max > 0){ - Render_Target *target = state->target; UI_Style ui_style = get_ui_style_upper(state->style); real32 L = unlerp(0.f, (real32)v, (real32)max); @@ -3810,23 +3796,21 @@ do_undo_slider(Widget_ID wid, UI_State *state, UI_Layout *layout, i32 max, i32 v internal i32 step_file_view(System_Functions *system, View *view_, i32_Rect rect, - bool32 is_active, Input_Summary *user_input){ + b32 is_active, Input_Summary *user_input){ view_->mouse_cursor_type = APP_MOUSE_CURSOR_IBEAM; i32 result = 0; File_View *view = (File_View*)view_; Editing_File *file = view->file; - Style *style = view->style; - Render_Font *font = style->font; - f32 line_height = (f32)font->height; + f32 line_height = (f32)view->font_height; f32 cursor_y = view_get_cursor_y(view); f32 target_y = view->target_y; f32 max_y = view_compute_height(view) - line_height*2; i32 lowest_line = view_compute_lowest_line(view); - f32 max_target_y = view_compute_max_target_y(lowest_line, font->height, max_y); + f32 max_target_y = view_compute_max_target_y(lowest_line, (i32)line_height, max_y); f32 delta_y = 3.f*line_height; f32 extra_top = 0.f; - extra_top += view_widget_height(view, font); + extra_top += view_widget_height(view, (i32)line_height); f32 taken_top_space = line_height + extra_top; if (user_input->mouse.my < rect.y0 + taken_top_space){ @@ -3913,18 +3897,18 @@ step_file_view(System_Functions *system, View *view_, i32_Rect rect, if (file){ i32 scrub_max = view->scrub_max; i32 undo_count, redo_count, total_count; - undo_count = file->undo.undo.edit_count; - redo_count = file->undo.redo.edit_count; + undo_count = file->state.undo.undo.edit_count; + redo_count = file->state.undo.redo.edit_count; total_count = undo_count + redo_count; switch (view->widget.type){ case FWIDG_TIMELINES: { - i32_Rect widg_rect = view_widget_rect(view, font); + i32_Rect widg_rect = view_widget_rect(view, view->font_height); UI_State state = ui_state_init(&view->widget.state, 0, user_input, - view->style, 0, 1); + view->style, view->font_set, 0, 1); UI_Layout layout; begin_layout(&layout, widg_rect); @@ -3966,9 +3950,9 @@ step_file_view(System_Functions *system, View *view_, i32_Rect rect, Widget_ID wid = make_id(&state, 4); if (view->widget.timeline.history_line){ i32 new_count; - i32 mid = ((file->undo.history.edit_count + file->undo.edit_history_cursor) >> 1); - i32 count = file->undo.edit_history_cursor; - if (do_undo_slider(wid, &state, &layout, mid, count, &file->undo, &new_count)){ + i32 mid = ((file->state.undo.history.edit_count + file->state.undo.edit_history_cursor) >> 1); + i32 count = file->state.undo.edit_history_cursor; + if (do_undo_slider(wid, &state, &layout, mid, count, &file->state.undo, &new_count)){ for (i32 i = 0; i < scrub_max && new_count < count; ++i){ view_history_step(system, view_->mem, view->layout, view, hist_backward); } @@ -4025,43 +4009,43 @@ enum File_Sync_State{ inline File_Sync_State buffer_get_sync(Editing_File *file){ File_Sync_State result = SYNC_GOOD; - if (file->last_4ed_write_time != file->last_sys_write_time) + if (file->state.last_4ed_write_time != file->state.last_sys_write_time) result = SYNC_BEHIND_OS; - else if (file->last_4ed_edit_time > file->last_sys_write_time) + else if (file->state.last_4ed_edit_time > file->state.last_sys_write_time) result = SYNC_UNSAVED; return result; } internal i32 -draw_file_view(View *view_, i32_Rect rect, bool32 is_active, - Render_Target *target){ +draw_file_loaded(View *view_, i32_Rect rect, b32 is_active, Render_Target *target){ File_View *view = (File_View*)view_; Editing_File *file = view->file; Style *style = view->style; - Render_Font *font = style->font; + + i32 line_height = view->font_height; Interactive_Bar bar; bar.style = style->main.file_info_style; - bar.font = style->font; - bar.pos_x = (real32)rect.x0; - bar.pos_y = (real32)rect.y0; + bar.font_id = style->font_id; + bar.pos_x = (f32)rect.x0; + bar.pos_y = (f32)rect.y0; bar.text_shift_y = 2; bar.text_shift_x = 0; bar.rect = rect; - bar.rect.y1 = bar.rect.y0 + font->height + 2; - rect.y0 += font->height + 2; + bar.rect.y1 = bar.rect.y0 + line_height + 2; + rect.y0 += line_height + 2; #if BUFFER_EXPERIMENT_SCALPEL <= 3 i32 max_x = rect.x1 - rect.x0; - i32 max_y = rect.y1 - rect.y0 + font->height; + i32 max_y = rect.y1 - rect.y0 + line_height; - Assert(file && !file->is_dummy && buffer_good(&file->buffer)); + Assert(file && !file->state.is_dummy && buffer_good(&file->state.buffer)); b32 tokens_use = 0; Cpp_Token_Stack token_stack = {}; if (file){ - tokens_use = file->tokens_complete && (file->token_stack.count > 0); - token_stack = file->token_stack; + tokens_use = file->state.tokens_complete && (file->state.token_stack.count > 0); + token_stack = file->state.token_stack; } b32 links_use = 0; @@ -4083,10 +4067,16 @@ draw_file_view(View *view_, i32_Rect rect, bool32 is_active, i32 max = partition_remaining(part) / sizeof(Buffer_Render_Item); Buffer_Render_Item *items = push_array(part, Buffer_Render_Item, max); + i16 font_id = style->font_id; + Render_Font *font = get_font_info(view->font_set, font_id)->font; + float *advance_data = 0; + if (font) advance_data = font->advance_data; + i32 count; - buffer_get_render_data(&file->buffer, view->line_wrap_y, items, max, &count, - (real32)rect.x0, (real32)rect.y0, view->scroll_x, view->scroll_y, !view->unwrapped_lines, - (real32)max_x, (real32)max_y, font->advance_data, (real32)font->height); + buffer_get_render_data(&file->state.buffer, view->line_wrap_y, items, max, &count, + (f32)rect.x0, (f32)rect.y0, view->scroll_x, view->scroll_y, !view->unwrapped_lines, + (f32)max_x, (f32)max_y, advance_data, (f32)line_height); + Assert(count > 0); i32 cursor_begin, cursor_end; @@ -4174,7 +4164,7 @@ draw_file_view(View *view_, i32_Rect rect, bool32 is_active, draw_rectangle_outline(target, f32R(item->x0, item->y0, item->x1, item->y1), mark_color); } if (item->glyphid != 0){ - font_draw_glyph(target, font, (u16)item->glyphid, + font_draw_glyph(target, font_id, (u8)item->glyphid, item->x0, item->y0, char_color); } prev_ind = ind; @@ -4186,15 +4176,14 @@ draw_file_view(View *view_, i32_Rect rect, bool32 is_active, if (view->widget.type != FWIDG_NONE){ UI_Style ui_style = get_ui_style_upper(style); - Render_Font *font = style->font; - i32_Rect widg_rect = view_widget_rect(view, font); + i32_Rect widg_rect = view_widget_rect(view, view->font_height); draw_rectangle(target, widg_rect, ui_style.dark); draw_rectangle_outline(target, widg_rect, ui_style.dim); UI_State state = ui_state_init(&view->widget.state, target, 0, - view->style, 0, 0); + view->style, view->font_set, 0, 0); UI_Layout layout; begin_layout(&layout, widg_rect); @@ -4208,8 +4197,8 @@ draw_file_view(View *view_, i32_Rect rect, bool32 is_active, Widget_ID wid = make_id(&state, 2); i32 undo_count, redo_count, total_count; - undo_count = file->undo.undo.edit_count; - redo_count = file->undo.redo.edit_count; + undo_count = file->state.undo.undo.edit_count; + redo_count = file->state.undo.redo.edit_count; total_count = undo_count + redo_count; do_undo_slider(wid, &state, &layout, total_count, undo_count, 0, 0); } @@ -4222,8 +4211,9 @@ draw_file_view(View *view_, i32_Rect rect, bool32 is_active, Widget_ID wid = make_id(&state, 4); i32 new_count; - i32 mid = ((file->undo.history.edit_count + file->undo.edit_history_cursor) >> 1); - do_undo_slider(wid, &state, &layout, mid, file->undo.edit_history_cursor, &file->undo, &new_count); + i32 mid = ((file->state.undo.history.edit_count + file->state.undo.edit_history_cursor) >> 1); + do_undo_slider(wid, &state, &layout, mid, + file->state.undo.edit_history_cursor, &file->state.undo, &new_count); } else{ do_button(3, &state, &layout, "+ History", 1); @@ -4259,7 +4249,7 @@ draw_file_view(View *view_, i32_Rect rect, bool32 is_active, draw_rectangle(target, bar.rect, back_color); u32 base_color = bar.style.base_color; - intbar_draw_string(target, &bar, file->live_name, base_color); + intbar_draw_string(target, &bar, file->state.live_name, base_color); intbar_draw_string(target, &bar, make_lit_string(" - "), base_color); char line_number_space[30]; @@ -4289,8 +4279,26 @@ draw_file_view(View *view_, i32_Rect rect, bool32 is_active, return 0; } +internal i32 +draw_file_view(View *view_, i32_Rect rect, bool32 is_active, + Render_Target *target){ + File_View *view = (File_View*)view_; + i32 result = 0; + + if (view->file){ + if (view->file->state.is_loading){ + // TODO(allen): draw file loading screen + } + else{ + result = draw_file_loaded(view_, rect, is_active, target); + } + } + + return (result); +} + internal void -kill_file(System_Functions *system, +kill_file(System_Functions *system, Exchange *exchange, General_Memory *general, Editing_File *file, Live_Views *live_set, Editing_Layout *layout){ i32 panel_count = layout->panel_count; Panel *panels = layout->panels, *panel; @@ -4303,7 +4311,7 @@ kill_file(System_Functions *system, if (view->is_minor) to_kill = view->major; File_View *fview = view_to_file_view(to_kill); if (fview && fview->file == file){ - live_set_free_view(system, live_set, &fview->view_base); + live_set_free_view(system, exchange, live_set, &fview->view_base); if (to_kill == view) panel->view = 0; else view->major = 0; } @@ -4374,16 +4382,18 @@ HANDLE_COMMAND_SIG(handle_command_file_view){ Temp_Memory temp = begin_temp_memory(&view->mem->part); char *spare = push_array(&view->mem->part, char, string->size); - i32 size = buffer_size(&file->buffer); + i32 size = buffer_size(&file->state.buffer); i32 pos; if (!result.hit_backspace){ if (file_view->isearch.reverse){ - pos = buffer_rfind_string(&file->buffer, start_pos - 1, string->str, string->size, spare); + pos = buffer_rfind_string(&file->state.buffer, start_pos - 1, + string->str, string->size, spare); if (pos >= 0){ if (step_backward){ file_view->isearch.pos = pos; start_pos = pos; - pos = buffer_rfind_string(&file->buffer, start_pos - 1, string->str, string->size, spare); + pos = buffer_rfind_string(&file->state.buffer, start_pos - 1, + string->str, string->size, spare); if (pos == -1) pos = start_pos; } view_set_temp_highlight(file_view, pos, pos+string->size); @@ -4391,12 +4401,14 @@ HANDLE_COMMAND_SIG(handle_command_file_view){ } else{ - pos = buffer_find_string(&file->buffer, start_pos + 1, string->str, string->size, spare); + pos = buffer_find_string(&file->state.buffer, start_pos + 1, + string->str, string->size, spare); if (pos < size){ if (step_forward){ file_view->isearch.pos = pos; start_pos = pos; - pos = buffer_find_string(&file->buffer, start_pos + 1, string->str, string->size, spare); + pos = buffer_find_string(&file->state.buffer, start_pos + 1, + string->str, string->size, spare); if (pos == size) pos = start_pos; } view_set_temp_highlight(file_view, pos, pos+string->size); @@ -4427,10 +4439,10 @@ HANDLE_COMMAND_SIG(handle_command_file_view){ if (result.hit_newline || result.hit_ctrl_newline){ i32 line_number = str_to_int(*string); - Render_Font *font = file_view->style->font; if (line_number < 1) line_number = 1; file_view->cursor = - view_compute_cursor_from_unwrapped_xy(file_view, 0, (real32)(line_number-1)*font->height); + view_compute_cursor_from_unwrapped_xy(file_view, 0, + (f32)(line_number-1)*file_view->font_height); file_view->preferred_x = view_get_cursor_x(file_view); view_set_widget(file_view, FWIDG_NONE); @@ -4489,5 +4501,57 @@ file_view_init(View *view, Editing_Layout *layout){ return result; } +struct File_View_Iter{ + File_View *view; + + Editing_File *file; + File_View *skip; + Panel *panels; + i32 panel_count; + i32 i; +}; + +internal File_View_Iter +file_view_iter_next(File_View_Iter iter){ + Panel *panel; + View *view; + File_View *file_view; + + ++iter.i; + for (panel = iter.panels + iter.i; + iter.i < iter.panel_count; + ++iter.i, ++panel){ + view = panel->view; + file_view = view_to_file_view(view); + if (file_view && file_view != iter.skip && file_view->file == iter.file){ + iter.view = file_view; + break; + } + } + + return(iter); +} + +internal File_View_Iter +file_view_iter_init(Editing_Layout *layout, Editing_File *file, File_View *skip){ + File_View_Iter result = {}; + result.panels = layout->panels; + result.panel_count = layout->panel_count; + result.file = file; + result.skip = skip; + + result.i = -1; + result = file_view_iter_next(result); + + return(result); +} + +internal b32 +file_view_iter_good(File_View_Iter iter){ + b32 result = 1; + if (iter.i >= iter.panel_count) result = 0; + return(result); +} + // BOTTOM diff --git a/4ed_font_set.cpp b/4ed_font_set.cpp new file mode 100644 index 00000000..3c7d504e --- /dev/null +++ b/4ed_font_set.cpp @@ -0,0 +1,232 @@ +/* + * Mr. 4th Dimention - Allen Webster + * + * 18.12.2015 + * + * Font set for 4coder + * + */ + +// TOP + +inline u32 +font_hash(String name){ + u32 x = 5381; + char *p = name.str; + for (i32 i = 0; i < name.size; ++i, ++p){ + x = ((x << 5) + x) ^ (*p); + } + return(x); +} + +inline void +font__insert(Font_Slot *pos, Font_Slot *slot){ + Font_Slot *nex; + nex = pos->next; + + slot->next = nex; + slot->prev = pos; + nex->prev = slot; + pos->next = slot; +} + +inline void +font__remove(Font_Slot *slot){ + Font_Slot *n, *p; + n = slot->next; + p = slot->prev; + + p->next = n; + n->prev = p; +} + +internal void +font_set_init(Font_Set *set, Partition *partition, i32 max, i16 live_max){ + partition_align(partition, 8); + set->info = push_array(partition, Font_Info, max); + partition_align(partition, 8); + set->entries = push_array(partition, Font_Table_Entry, max); + set->count = 0; + set->max = max; + + partition_align(partition, 8); + set->font_block = push_block(partition, live_max*(sizeof(Render_Font) + sizeof(Font_Slot))); + + set->free_slots = {}; + set->used_slots = {}; + + set->free_slots.next = &set->free_slots; + set->free_slots.prev = &set->free_slots; + set->used_slots.next = &set->used_slots; + set->used_slots.prev = &set->used_slots; + + char *ptr = (char*)set->font_block; + for (i32 i = 0; i < live_max; ++i){ + font__insert(&set->free_slots, (Font_Slot*)ptr); + ptr += sizeof(Font_Slot) + sizeof(Render_Font); + } + + set->font_used_flags = push_array(partition, b8, max); + set->live_max = live_max; +} + +internal b32 +font_set_can_add(Font_Set *set){ + b32 result = 0; + if (set->count*8 < set->max*7) result = 1; + return(result); +} + +internal void +font_set_add_hash(Font_Set *set, String name, i16 font_id){ + Font_Table_Entry entry; + entry.hash = font_hash(name); + entry.name = name; + entry.font_id = font_id; + + u32 i, j; + i = entry.hash % set->max; + j = i - 1; + if (i <= 1) j += set->max; + + for (; i != j; ++i){ + if (i == set->max) i = 0; + if (set->entries[i].font_id == 0){ + set->entries[i] = entry; + break; + } + } + + Assert(i != j); +} + +inline b32 +font_set_can_load(Font_Set *set){ + b32 result = (set->free_slots.next != &set->free_slots); + return(result); +} + +internal void +font_set_load(Partition *partition, Font_Set *set, i16 font_id){ + Font_Info *info = get_font_info(set, font_id); + Font_Slot *slot = set->free_slots.next; + Assert(slot != &set->free_slots); + font__remove(slot); + font__insert(&set->used_slots, slot); + + Render_Font *font = (Render_Font*)(slot + 1); + set->font_load(partition, font, info->filename.str, info->pt_size, 4); + info->font = font; + slot->font_id = font_id; +} + +internal void +font_set_evict_lru(Font_Set *set){ + Font_Slot *slot = set->used_slots.prev; + Assert(slot != &set->used_slots); + + i16 font_id = slot->font_id; + Font_Info *info = get_font_info(set, font_id); + Assert(((Font_Slot*)info->font) - 1 == slot); + + set->release_font(info->font); + + info->font = 0; + slot->font_id = 0; + font__remove(slot); + font__insert(&set->free_slots, slot); +} + +internal void +font_set_use(Partition *partition, Font_Set *set, i16 font_id){ + b8 already_used; + already_used = set->font_used_flags[font_id-1]; + + if (!already_used){ + if (set->used_this_frame < set->live_max){ + ++set->used_this_frame; + set->font_used_flags[font_id-1] = 1; + already_used = 1; + } + } + + if (already_used){ + // TODO(allen): optimize if you don't mind!!!! + Font_Info *info = get_font_info(set, font_id); + Font_Slot *slot; + if (info->font == 0){ + if (!font_set_can_load(set)){ + font_set_evict_lru(set); + } + font_set_load(partition, set, font_id); + } + slot = ((Font_Slot*)info->font) - 1; + + font__remove(slot); + font__insert(&set->used_slots, slot); + } +} + +internal b32 +font_set_add(Partition *partition, Font_Set *set, + String filename, String name, i32 pt_size){ + b32 result = 0; + if (font_set_can_add(set)){ + i16 font_id = (i16)(++set->count); + Font_Info *info = get_font_info(set, font_id); + info->filename = filename; + info->name = name; + info->pt_size = pt_size; + set->font_info_load(partition, filename.str, pt_size, &info->height, &info->advance); + font_set_add_hash(set, name, font_id); + + if (font_set_can_load(set)){ + font_set_load(partition, set, font_id); + } + + result = 1; + } + return(result); +} + +internal b32 +font_set_find_pos(Font_Set *set, String name, u32 *position){ + b32 result; + u32 hash, i, j; + hash = font_hash(name); + i = hash % set->max; + j = i - 1; + if (j <= 1) j += set->max; + + result = 0; + Font_Table_Entry *entry; + for (; i != j; ++i){ + if (i == set->max) i = 0; + entry = set->entries + i; + if (entry->hash == hash){ + if (match(name, entry->name)){ + result = 1; + *position = i; + break; + } + } + } + + return(result); +} + +internal b32 +font_set_extract(Font_Set *set, String name, i16 *font_id){ + b32 result; + u32 position; + + result = font_set_find_pos(set, name, &position); + if (result){ + *font_id = set->entries[position].font_id; + } + + return(result); +} + +// BOTTOM + diff --git a/4ed_interactive_view.cpp b/4ed_interactive_view.cpp index 9ab0a285..221c80b5 100644 --- a/4ed_interactive_view.cpp +++ b/4ed_interactive_view.cpp @@ -30,6 +30,7 @@ struct Interactive_View{ Style *style; Working_Set *working_set; Delay *delay; + Font_Set *font_set; UI_State state; Interactive_View_Interaction interaction; Interactive_View_Action action; @@ -97,19 +98,20 @@ interactive_view_complete(Interactive_View *view){ } internal i32 -step_draw_int_view(System_Functions *system, - Interactive_View *view, Render_Target *target, i32_Rect rect, - Input_Summary *user_input, bool32 input_stage){ +step_draw_int_view(System_Functions *system, Interactive_View *view, + Render_Target *target, i32_Rect rect, + Input_Summary *user_input, b32 input_stage){ i32 result = 0; UI_State state = - ui_state_init(&view->state, target, user_input, view->style, view->working_set, input_stage); + ui_state_init(&view->state, target, user_input, + view->style, view->font_set, view->working_set, input_stage); UI_Layout layout; begin_layout(&layout, rect); - bool32 new_dir = 0; - bool32 complete = 0; + b32 new_dir = 0; + b32 complete = 0; terminate_with_null(&view->query); do_label(&state, &layout, view->query.str, 1.f); @@ -202,8 +204,9 @@ Do_View_Sig(do_interactive_view){ } internal Interactive_View* -interactive_view_init(System_Functions *system, View *view, Hot_Directory *hot_dir, Style *style, - Working_Set *working_set, Delay *delay){ +interactive_view_init(System_Functions *system, View *view, + Hot_Directory *hot_dir, Style *style, + Working_Set *working_set, Font_Set *font_set, Delay *delay){ Interactive_View *result = (Interactive_View*)view; view->type = VIEW_TYPE_INTERACTIVE; view->do_view = do_interactive_view; @@ -214,6 +217,7 @@ interactive_view_init(System_Functions *system, View *view, Hot_Directory *hot_d result->dest = make_fixed_width_string(result->dest_); result->style = style; result->working_set = working_set; + result->font_set = font_set; result->delay = delay; return result; } diff --git a/4ed_keyboard.cpp b/4ed_keyboard.cpp index 228fb6ae..39e129db 100644 --- a/4ed_keyboard.cpp +++ b/4ed_keyboard.cpp @@ -9,85 +9,27 @@ // TOP -globalvar u16 keycode_lookup_table[255]; -globalvar u16 loose_keycode_lookup_table[255]; +globalvar u8 keycode_lookup_table[255]; internal void set_dynamic_key_names(Key_Codes *codes){ - u16 code = 1; - u16 *codes_array = (u16*)codes; + u8 code = 1; + u8 *codes_array = (u8*)codes; for (i32 i = 0; i < sizeof(*codes)/sizeof(codes->up);){ switch (code){ case '\n': code++; break; case '\t': code++; break; case 0x20: code = 0x7F; break; + default: + codes_array[i++] = code++; } - codes_array[i++] = code++; } } -inline u16 +inline u8 keycode_lookup(u8 system_code){ return keycode_lookup_table[system_code]; } -inline u16 -loose_keycode_lookup(u8 system_code){ - return loose_keycode_lookup_table[system_code]; -} - -inline b32 -keycode_has_ascii(u16 keycode){ - return (keycode >= 0x20 && keycode < 0x7F) || keycode == '\n' || keycode == '\t'; -} - -internal u8 -translate_key(u16 keycode, - b32 shift, - b32 caps_lock){ - u8 character = 0; - if (keycode >= 'A' && keycode <= 'Z'){ - if (caps_lock) shift = !shift; - if (!shift) character = char_to_lower((char)keycode); - else character = (u8)keycode; - } - else if (keycode >= '0' && keycode <= '9'){ - persist u8 shift_number_table[10] = { - ')', '!', '@', '#', '$', '%', '^', '&', '*', '(' - //0 1 2 3 4 5 6 7 8 9 - }; - if (shift){ - character = shift_number_table[keycode - '0']; - } - else{ - character = (u8)keycode; - } - } - else{ - if (keycode_has_ascii(keycode)){ - character = (u8)keycode; - u8 shift_character = character; - switch (keycode){ - case '-': character = '-'; shift_character = '_'; break; - case '=': character = '='; shift_character = '+'; break; - case '`': character = '`'; shift_character = '~'; break; - case '\\': character = '\\'; shift_character = '|'; break; - case '[': character = '['; shift_character = '{'; break; - case ']': character = ']'; shift_character = '}'; break; - case '\'': character = '\''; shift_character = '"'; break; - case ';': character = ';'; shift_character = ':'; break; - case '/': character = '/'; shift_character = '?'; break; - case '.': character = '.'; shift_character = '>'; break; - case ',': character = ','; shift_character = '<'; break; - case ' ': character = ' '; shift_character = ' '; break; - case '\n': character = '\n'; shift_character = '\n'; break; - case '\t': character = '\t'; shift_character = '\t'; break; - } - if (shift) character = shift_character; - } - } - return character; -} - // BOTTOM diff --git a/4ed_layout.cpp b/4ed_layout.cpp index fcf57ded..d3a9a17b 100644 --- a/4ed_layout.cpp +++ b/4ed_layout.cpp @@ -26,7 +26,7 @@ struct Interactive_Bar{ real32 pos_x, pos_y; real32 text_shift_x, text_shift_y; i32_Rect rect; - Render_Font *font; + i16 font_id; }; enum View_Message{ @@ -39,7 +39,7 @@ enum View_Message{ struct View; #define Do_View_Sig(name) \ - i32 (name)(System_Functions *system, \ + i32 (name)(System_Functions *system, Exchange *exchange, \ View *view, i32_Rect rect, View *active, \ View_Message message, Render_Target *target, \ Input_Summary *user_input, Input_Summary *active_input) @@ -78,8 +78,8 @@ struct View{ i32 type; i32 block_size; Application_Mouse_Cursor mouse_cursor_type; - bool32 is_active; - bool32 is_minor; + b32 is_active; + b32 is_minor; }; struct Live_Views{ @@ -133,31 +133,30 @@ struct Editing_Layout{ }; internal void -intbar_draw_string(Render_Target *target, Interactive_Bar *bar, - u8 *str, u32 char_color){ - Render_Font *font = bar->font; +intbar_draw_string(Render_Target *target, + Interactive_Bar *bar, u8 *str, u32 char_color){ + i16 font_id = bar->font_id; for (i32 i = 0; str[i]; ++i){ char c = str[i]; - font_draw_glyph(target, font, c, + font_draw_glyph(target, font_id, c, bar->pos_x + bar->text_shift_x, bar->pos_y + bar->text_shift_y, char_color); - bar->pos_x += font_get_glyph_width(font, c); + bar->pos_x += font_get_glyph_width(target, font_id, c); } } internal void -intbar_draw_string(Render_Target *target, - Interactive_Bar *bar, String str, - u32 char_color){ - Render_Font *font = bar->font; +intbar_draw_string(Render_Target *target, Interactive_Bar *bar, + String str, u32 char_color){ + i16 font_id = bar->font_id; for (i32 i = 0; i < str.size; ++i){ char c = str.str[i]; - font_draw_glyph(target, font, c, + font_draw_glyph(target, font_id, c, bar->pos_x + bar->text_shift_x, bar->pos_y + bar->text_shift_y, char_color); - bar->pos_x += font_get_glyph_width(font, c); + bar->pos_x += font_get_glyph_width(target, font_id, c); } } @@ -191,9 +190,9 @@ live_set_alloc_view(Live_Views *live_set, Mem_Options *mem){ } inline void -live_set_free_view(System_Functions *system, Live_Views *live_set, View *view){ +live_set_free_view(System_Functions *system, Exchange *exchange, Live_Views *live_set, View *view){ Assert(live_set->count > 0); - view->do_view(system, view, {}, 0, VMSG_FREE, 0, {}, 0); + view->do_view(system, exchange, view, {}, 0, VMSG_FREE, 0, {}, 0); view->next_free = live_set->free_view; live_set->free_view = view; --live_set->count; @@ -201,13 +200,14 @@ live_set_free_view(System_Functions *system, Live_Views *live_set, View *view){ } inline void -view_replace_major(System_Functions *system, View *new_view, Panel *panel, Live_Views *live_set){ +view_replace_major(System_Functions *system, Exchange *exchange, + View *new_view, Panel *panel, Live_Views *live_set){ View *view = panel->view; if (view){ if (view->is_minor && view->major){ - live_set_free_view(system, live_set, view->major); + live_set_free_view(system, exchange, live_set, view->major); } - live_set_free_view(system, live_set, view); + live_set_free_view(system, exchange, live_set, view); } new_view->panel = panel; new_view->minor = 0; @@ -215,13 +215,14 @@ view_replace_major(System_Functions *system, View *new_view, Panel *panel, Live_ } inline void -view_replace_minor(System_Functions *system, View *new_view, Panel *panel, Live_Views *live_set){ +view_replace_minor(System_Functions *system, Exchange *exchange, + View *new_view, Panel *panel, Live_Views *live_set){ View *view = panel->view; new_view->is_minor = 1; if (view){ if (view->is_minor){ new_view->major = view->major; - live_set_free_view(system, live_set, view); + live_set_free_view(system, exchange, live_set, view); } else{ new_view->major = view; @@ -236,40 +237,43 @@ view_replace_minor(System_Functions *system, View *new_view, Panel *panel, Live_ } inline void -view_remove_major(System_Functions *system, Panel *panel, Live_Views *live_set){ +view_remove_major(System_Functions *system, Exchange *exchange, + Panel *panel, Live_Views *live_set){ View *view = panel->view; if (view){ if (view->is_minor && view->major){ - live_set_free_view(system, live_set, view->major); + live_set_free_view(system, exchange, live_set, view->major); } - live_set_free_view(system, live_set, view); + live_set_free_view(system, exchange, live_set, view); } panel->view = 0; } inline void -view_remove_major_leave_minor(System_Functions *system, Panel *panel, Live_Views *live_set){ +view_remove_major_leave_minor(System_Functions *system, Exchange *exchange, + Panel *panel, Live_Views *live_set){ View *view = panel->view; if (view){ if (view->is_minor && view->major){ - live_set_free_view(system, live_set, view->major); + live_set_free_view(system, exchange, live_set, view->major); view->major = 0; } else{ - live_set_free_view(system, live_set, view); + live_set_free_view(system, exchange, live_set, view); panel->view = 0; } } } inline void -view_remove_minor(System_Functions *system, Panel *panel, Live_Views *live_set){ +view_remove_minor(System_Functions *system, Exchange *exchange, + Panel *panel, Live_Views *live_set){ View *view = panel->view; View *major = 0; if (view){ if (view->is_minor){ major = view->major; - live_set_free_view(system, live_set, view); + live_set_free_view(system, exchange, live_set, view); } } panel->view = major; @@ -277,10 +281,11 @@ view_remove_minor(System_Functions *system, Panel *panel, Live_Views *live_set){ } inline void -view_remove(System_Functions *system, Panel *panel, Live_Views *live_set){ +view_remove(System_Functions *system, Exchange *exchange, + Panel *panel, Live_Views *live_set){ View *view = panel->view; - if (view->is_minor) view_remove_minor(system, panel, live_set); - else view_remove_major(system, panel, live_set); + if (view->is_minor) view_remove_minor(system, exchange, panel, live_set); + else view_remove_major(system, exchange, panel, live_set); } struct Divider_And_ID{ diff --git a/4ed_mem.cpp b/4ed_mem.cpp index 0b9f3ad7..9d7913a4 100644 --- a/4ed_mem.cpp +++ b/4ed_mem.cpp @@ -14,6 +14,36 @@ struct Partition{ i32 pos, max; }; +struct Temp_Memory{ + void *handle; + int pos; +}; + +enum Memory_Bubble_Flag{ + MEM_BUBBLE_USED = 0x1, + MEM_BUBBLE_DEBUG = 0xD3000000, + MEM_BUBBLE_SYS_DEBUG = 0x5D000000, + MEM_BUBBLE_DEBUG_MASK = 0xFF000000 +}; + +struct Bubble{ + Bubble *prev; + Bubble *next; + u32 flags; + i32 size; + u32 type; + u32 _unused_; +}; + +struct General_Memory{ + Bubble sentinel; +}; + +struct Mem_Options{ + Partition part; + General_Memory general; +}; + inline Partition partition_open(void *memory, i32 size){ Partition partition; @@ -60,26 +90,6 @@ partition_sub_part(Partition *data, i32 size){ #define push_array(part, T, size) (T*)partition_allocate(part, sizeof(T)*(size)) #define push_block(part, size) partition_allocate(part, size) -enum Memory_Bubble_Flag{ - MEM_BUBBLE_USED = 0x1, - MEM_BUBBLE_DEBUG = 0xD3000000, - MEM_BUBBLE_SYS_DEBUG = 0x5D000000, - MEM_BUBBLE_DEBUG_MASK = 0xFF000000 -}; - -struct Bubble{ - Bubble *prev; - Bubble *next; - u32 flags; - i32 size; - u32 type; - u32 _unused_; -}; - -struct General_Memory{ - Bubble sentinel; -}; - inline void insert_bubble(Bubble *prev, Bubble *bubble){ bubble->prev = prev; @@ -226,28 +236,18 @@ general_memory_reallocate_nocopy(General_Memory *general, void *old, i32 size, u return general_memory_reallocate(general, old, 0, size, type); } -struct Temp_Memory{ - Partition *part; - i32 pos; -}; - internal Temp_Memory begin_temp_memory(Partition *data){ Temp_Memory result; - result.part = data; + result.handle = data; result.pos = data->pos; return result; } internal void end_temp_memory(Temp_Memory temp){ - temp.part->pos = temp.pos; + ((Partition*)temp.handle)->pos = temp.pos; } -struct Mem_Options{ - Partition part; - General_Memory general; -}; - // BOTTOM diff --git a/4ed_menu_view.cpp b/4ed_menu_view.cpp index ecad69fa..b8a73a0e 100644 --- a/4ed_menu_view.cpp +++ b/4ed_menu_view.cpp @@ -33,7 +33,7 @@ step_draw_menu_view(Menu_View *view, Render_Target *target, i32_Rect rect, UI_State state = ui_state_init(&view->state, target, user_input, - view->style, view->working_set, input_stage); + view->style, &target->font_set, view->working_set, input_stage); UI_Layout layout; begin_layout(&layout, rect); diff --git a/4ed_meta.h b/4ed_meta.h index 9a863467..c4fe1f5d 100644 --- a/4ed_meta.h +++ b/4ed_meta.h @@ -187,10 +187,10 @@ LargeRoundUp(i32 x, i32 granularity){ #define Byte_7 (0xFFU << 56) #define bytes(n) (n) -#define Kbytes(n) (bytes(n) * 1024) -#define Mbytes(n) (Kbytes(n) * 1024) -#define Gbytes(n) (Mbytes((u64)n) * 1024) -#define Tbytes(n) (Gbytes((u64)n) * 1024) +#define Kbytes(n) ((n) << 10) +#define Mbytes(n) ((n) << 20) +#define Gbytes(n) (((u64)n) << 30) +#define Tbytes(n) (((u64)n) << 40) #endif diff --git a/4ed_rendering.cpp b/4ed_rendering.cpp index b55ceca8..19d2b394 100644 --- a/4ed_rendering.cpp +++ b/4ed_rendering.cpp @@ -138,7 +138,7 @@ private_draw_gradient(Render_Target *target, f32_Rect rect, inline void private_draw_glyph(Render_Target *target, Render_Font *font, - u16 character, f32 x, f32 y, u32 color){ + u8 character, f32 x, f32 y, u32 color){ f32 x_shift, y_shift; x_shift = 0; y_shift = (f32)font->ascent; @@ -147,8 +147,8 @@ private_draw_glyph(Render_Target *target, Render_Font *font, y += y_shift; stbtt_aligned_quad q; - stbtt_GetBakedQuadUnrounded(font->chardata, font->tex_width, font->tex_height, - character, &x, &y, &q, 1); + stbtt_GetPackedQuad(font->chardata, font->tex_width, font->tex_height, + character, &x, &y, &q, 1); draw_set_color(target, color); draw_bind_texture(target, font->tex); @@ -163,7 +163,7 @@ private_draw_glyph(Render_Target *target, Render_Font *font, } inline void -private_draw_glyph_mono(Render_Target *target, Render_Font *font, u16 character, +private_draw_glyph_mono(Render_Target *target, Render_Font *font, u8 character, f32 x, f32 y, f32 advance, u32 color){ f32 x_shift, y_shift; i32 left = font->chardata[character].x0; @@ -176,7 +176,8 @@ private_draw_glyph_mono(Render_Target *target, Render_Font *font, u16 character, y += y_shift; stbtt_aligned_quad q; - stbtt_GetBakedQuadUnrounded(font->chardata, font->tex_width, font->tex_height, character, &x, &y, &q, 1); + stbtt_GetPackedQuad(font->chardata, font->tex_width, font->tex_height, + character, &x, &y, &q, 1); draw_set_color(target, color); draw_bind_texture(target, font->tex); @@ -191,7 +192,7 @@ private_draw_glyph_mono(Render_Target *target, Render_Font *font, u16 character, } inline void -private_draw_glyph_mono(Render_Target *target, Render_Font *font, u16 character, +private_draw_glyph_mono(Render_Target *target, Render_Font *font, u8 character, real32 x, real32 y, u32 color){ private_draw_glyph_mono(target, font, character, x, y, (f32)font->advance, color); } @@ -233,31 +234,34 @@ launch_rendering(Render_Target *target){ { Render_Piece_Glyph *glyph = ExtractStruct(Render_Piece_Glyph); - Render_Font *font = glyph->font_id; - private_draw_glyph(target, font, glyph->character, - glyph->pos.x, glyph->pos.y, glyph->color); + Render_Font *font = get_font_info(&target->font_set, glyph->font_id)->font; + if (font) + private_draw_glyph(target, font, glyph->character, + glyph->pos.x, glyph->pos.y, glyph->color); }break; case piece_type_mono_glyph: { Render_Piece_Glyph *glyph = ExtractStruct(Render_Piece_Glyph); - Render_Font *font = glyph->font_id; - private_draw_glyph_mono(target, font, glyph->character, - glyph->pos.x, glyph->pos.y, glyph->color); + Render_Font *font = get_font_info(&target->font_set, glyph->font_id)->font; + if (font) + private_draw_glyph_mono(target, font, glyph->character, + glyph->pos.x, glyph->pos.y, glyph->color); }break; case piece_type_mono_glyph_advance: { Render_Piece_Glyph_Advance *glyph = ExtractStruct(Render_Piece_Glyph_Advance); - Render_Font *font = glyph->font_id; - private_draw_glyph_mono(target, font, glyph->character, - glyph->pos.x, glyph->pos.y, - glyph->advance, glyph->color); + Render_Font *font = get_font_info(&target->font_set, glyph->font_id)->font; + if (font) + private_draw_glyph_mono(target, font, glyph->character, + glyph->pos.x, glyph->pos.y, + glyph->advance, glyph->color); }break; } } @@ -265,18 +269,99 @@ launch_rendering(Render_Target *target){ #undef ExtractStruct -internal i32 -draw_font_load(System_Functions *system, - Render_Font *font_out, - char *filename, - i32 pt_size, - void *font_block, - i32 font_block_size, - i32 *memory_used_out, - i32 tab_width){ +internal +Font_Info_Load_Sig(draw_font_info_load){ i32 result = 1; Data file; - file = system->load_file(filename); + file = system_load_file(filename); + Temp_Memory temp = begin_temp_memory(partition); + stbtt_packedchar *chardata = push_array(partition, stbtt_packedchar, 256); + + i32 oversample = 2; + + i32 tex_width, tex_height; + tex_width = pt_size*128*oversample; + tex_height = pt_size*2*oversample; + void *block = push_block(partition, tex_width * tex_height); + + if (!file.data){ + result = 0; + } + else{ + stbtt_fontinfo font; + if (!stbtt_InitFont(&font, (u8*)file.data, 0)){ + result = 0; + } + else{ + i32 ascent, descent, line_gap; + f32 scale; + + stbtt_GetFontVMetrics(&font, &ascent, &descent, &line_gap); + scale = stbtt_ScaleForPixelHeight(&font, (f32)pt_size); + + f32 scaled_ascent, scaled_descent, scaled_line_gap; + + scaled_ascent = scale*ascent; + scaled_descent = scale*descent; + scaled_line_gap = scale*line_gap; + + i32 font_height = (i32)(scaled_ascent - scaled_descent + scaled_line_gap); + + stbtt_pack_context spc; + if (stbtt_PackBegin(&spc, (u8*)block, tex_width, tex_height, tex_width, 1, partition)){ + stbtt_PackSetOversampling(&spc, oversample, oversample); + if (stbtt_PackFontRange(&spc, (u8*)file.data, 0, + STBTT_POINT_SIZE((f32)pt_size), 0, 128, chardata)){ + // do nothing + } + else{ + result = 0; + } + + stbtt_PackEnd(&spc); + } + else{ + result = 0; + } + + if (result){ + i32 max_advance = 0; + for (u8 code_point = 0; code_point < 128; ++code_point){ + if (stbtt_FindGlyphIndex(&font, code_point) != 0){ + i32 adv = CEIL32(chardata[code_point].xadvance); + if (max_advance < adv){ + max_advance = adv; + } + } + } + + *height = font_height; + *advance = max_advance - 1; + } + } + + system_free_memory(file.data); + } + + end_temp_memory(temp); + + return(result); +} + +internal +Font_Load_Sig(draw_font_load){ + i32 result = 1; + Data file; + file = system_load_file(filename); + Temp_Memory temp = begin_temp_memory(partition); + stbtt_packedchar *chardata = font_out->chardata; + + i32 oversample = 2; + + i32 tex_width, tex_height; + tex_width = pt_size*128*oversample; + tex_height = pt_size*2*oversample; + void *block = push_block(partition, tex_width * tex_height); if (!file.data){ result = 0; @@ -289,12 +374,12 @@ draw_font_load(System_Functions *system, } else{ i32 ascent, descent, line_gap; - real32 scale; + f32 scale; stbtt_GetFontVMetrics(&font, &ascent, &descent, &line_gap); - scale = stbtt_ScaleForPixelHeight(&font, (real32)pt_size); + scale = stbtt_ScaleForPixelHeight(&font, (f32)pt_size); - real32 scaled_ascent, scaled_descent, scaled_line_gap; + f32 scaled_ascent, scaled_descent, scaled_line_gap; scaled_ascent = scale*ascent; scaled_descent = scale*descent; @@ -305,167 +390,36 @@ draw_font_load(System_Functions *system, font_out->descent = (i32)(scaled_descent); font_out->line_skip = (i32)(scaled_line_gap); - u8 *memory_cursor = (u8*)font_block; - Assert(pt_size*pt_size*128 <= font_block_size); - - i32 tex_width, tex_height; - tex_width = pt_size*128; - tex_height = pt_size*2; - font_out->tex_width = tex_width; font_out->tex_height = tex_height; - - if (stbtt_BakeFontBitmap((u8*)file.data, 0, (real32)pt_size, - memory_cursor, tex_width, tex_height, 0, 128, font_out->chardata) <= 0){ - result = 0; - } - - else{ - GLuint font_tex; - glGenTextures(1, &font_tex); - glBindTexture(GL_TEXTURE_2D, font_tex); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, tex_width, tex_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, memory_cursor); - - font_out->tex = font_tex; - glBindTexture(GL_TEXTURE_2D, 0); - } - - font_out->chardata['\r'] = font_out->chardata[' ']; - font_out->chardata['\n'] = font_out->chardata[' ']; - font_out->chardata['\t'] = font_out->chardata[' ']; - font_out->chardata['\t'].xadvance *= tab_width; - - i32 max_advance = 0; - for (u16 code_point = 0; code_point < 128; ++code_point){ - if (stbtt_FindGlyphIndex(&font, code_point) != 0){ - font_out->glyphs[code_point].exists = 1; - i32 advance = CEIL32(font_out->chardata[code_point].xadvance); - if (max_advance < advance) max_advance = advance; - font_out->advance_data[code_point] = font_out->chardata[code_point].xadvance; - } - } - font_out->advance = max_advance - 1; - } - system->free_file(file); - } - - return result; -} + + stbtt_pack_context spc; #if 0 - -internal void -draw_rectangle(Render_Target *target, i32_Rect rect, u32 color){ - draw_set_color(target, color); - draw_bind_texture(target, 0); - glBegin(GL_QUADS); - { - glVertex2i(rect.x0, rect.y0); - glVertex2i(rect.x0, rect.y1); - glVertex2i(rect.x1, rect.y1); - glVertex2i(rect.x1, rect.y0); - } - glEnd(); -} - -internal void -draw_triangle_3corner(Render_Target *target, - real32 x0, real32 y0, - real32 x1, real32 y1, - real32 x2, real32 y2, - u32 color){ - draw_set_color(target, color); - draw_bind_texture(target, 0); - glBegin(GL_TRIANGLES); - { - glVertex2f(x0, y0); - glVertex2f(x1, y1); - glVertex2f(x2, y2); - } - glEnd(); -} - -inline void -draw_gradient_2corner_clipped(Render_Target *target, real32 l, real32 t, real32 r, real32 b, - Vec4 color_left, Vec4 color_right){ - draw_gradient_2corner_clipped(target, f32R(l,t,r,b), color_left, color_right); -} - -inline void -draw_rectangle_outline(Render_Target *target, i32_Rect rect, u32 color){ - draw_rectangle_outline(target, f32R(rect), color); -} - -internal void -draw_margin(Render_Target *target, i32_Rect outer, i32_Rect inner, u32 color){ - draw_rectangle(target, i32R(outer.x0, outer.y0, outer.x1, inner.y0), color); - draw_rectangle(target, i32R(outer.x0, inner.y1, outer.x1, outer.y1), color); - draw_rectangle(target, i32R(outer.x0, inner.y0, inner.x0, inner.y1), color); - draw_rectangle(target, i32R(inner.x1, inner.y0, outer.x1, inner.y1), color); -} - -inline internal i32 -font_predict_size(i32 pt_size){ - return pt_size*pt_size*128; -} - -internal i32 -font_load(System_Functions *system, - Render_Font *font_out, char *filename, i32 pt_size, - void *font_block, i32 font_block_size, - i32 *memory_used_out, i32 tab_width){ - i32 result = 1; - File_Data file; - file = system->load_file(filename); - - if (!file.data){ - result = 0; - } - - else{ - stbtt_fontinfo font; - if (!stbtt_InitFont(&font, (u8*)file.data, 0)){ - result = 0; - } - else{ - i32 ascent, descent, line_gap; - real32 scale; - - stbtt_GetFontVMetrics(&font, &ascent, &descent, &line_gap); - scale = stbtt_ScaleForPixelHeight(&font, (real32)pt_size); - - real32 scaled_ascent, scaled_descent, scaled_line_gap; - - scaled_ascent = scale*ascent; - scaled_descent = scale*descent; - scaled_line_gap = scale*line_gap; - - font_out->height = (i32)(scaled_ascent - scaled_descent + scaled_line_gap); - font_out->ascent = (i32)(scaled_ascent); - font_out->descent = (i32)(scaled_descent); - font_out->line_skip = (i32)(scaled_line_gap); - - u8 *memory_cursor = (u8*)font_block; - Assert(pt_size*pt_size*128 <= font_block_size); - - i32 tex_width, tex_height; - tex_width = pt_size*128; - tex_height = pt_size*2; - - font_out->tex_width = tex_width; - font_out->tex_height = tex_height; - - if (stbtt_BakeFontBitmap((u8*)file.data, 0, (real32)pt_size, - memory_cursor, tex_width, tex_height, 0, 128, font_out->chardata) <= 0){ + if (stbtt_BakeFontBitmap((u8*)file.data, 0, (f32)pt_size, + memory_cursor, tex_width, tex_height, 0, 128, + font_out->chardata, partition) <= 0){ result = 0; } - +#endif + + if (stbtt_PackBegin(&spc, (u8*)block, tex_width, tex_height, tex_width, 1, partition)){ + stbtt_PackSetOversampling(&spc, oversample, oversample); + if (stbtt_PackFontRange(&spc, (u8*)file.data, 0, + STBTT_POINT_SIZE((f32)pt_size), 0, 128, chardata)){ + // do nothing + } + else{ + result = 0; + } + + stbtt_PackEnd(&spc); + } else{ + result = 0; + } + + if (result){ GLuint font_tex; glGenTextures(1, &font_tex); glBindTexture(GL_TEXTURE_2D, font_tex); @@ -474,120 +428,45 @@ font_load(System_Functions *system, glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, tex_width, tex_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, memory_cursor); + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, tex_width, tex_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, block); font_out->tex = font_tex; glBindTexture(GL_TEXTURE_2D, 0); - } + + font_out->chardata['\r'] = font_out->chardata[' ']; + font_out->chardata['\n'] = font_out->chardata[' ']; + font_out->chardata['\t'] = font_out->chardata[' ']; + font_out->chardata['\t'].xadvance *= tab_width; - font_out->chardata['\r'] = font_out->chardata[' ']; - font_out->chardata['\n'] = font_out->chardata[' ']; - font_out->chardata['\t'] = font_out->chardata[' ']; - font_out->chardata['\t'].xadvance *= tab_width; - - i32 max_advance = 0; - for (u16 code_point = 0; code_point < 128; ++code_point){ - if (stbtt_FindGlyphIndex(&font, code_point) != 0){ - font_out->glyphs[code_point].exists = 1; - i32 advance = CEIL32(font_out->chardata[code_point].xadvance); - if (max_advance < advance) max_advance = advance; - font_out->advance_data[code_point] = font_out->chardata[code_point].xadvance; + i32 max_advance = 0; + for (u8 code_point = 0; code_point < 128; ++code_point){ + if (stbtt_FindGlyphIndex(&font, code_point) != 0){ + font_out->glyphs[code_point].exists = 1; + i32 advance = CEIL32(font_out->chardata[code_point].xadvance); + if (max_advance < advance) max_advance = advance; + font_out->advance_data[code_point] = font_out->chardata[code_point].xadvance; + } + else if (code_point == '\r' || code_point == '\n' || code_point == '\t'){ + font_out->advance_data[code_point] = font_out->chardata[code_point].xadvance; + } } + font_out->advance = max_advance - 1; } - font_out->advance = max_advance - 1; + } - system->free_file(file); + system_free_memory(file.data); } + + end_temp_memory(temp); return result; } -internal void -font_set_tabwidth(Render_Font *font, i32 tab_width){ - font->chardata['\t'].xadvance *= font->chardata[' '].xadvance * tab_width; +internal +Release_Font_Sig(draw_release_font){ + glDeleteTextures(1, &font->tex); + font->tex = 0; } -inline real32 -font_get_glyph_width(Render_Font *font, u16 character){ - return font->chardata[character].xadvance; -} - -internal real32 -font_string_width(Render_Font *font, char *str){ - real32 x = 0; - for (i32 i = 0; str[i]; ++i){ - x += font_get_glyph_width(font, str[i]); - } - return x; -} - -internal i32 -draw_string(Render_Target *target, Render_Font *font, char *str, - i32 x_, i32 y, u32 color){ - real32 x = (real32)x_; - for (i32 i = 0; str[i]; ++i){ - char c = str[i]; - font_draw_glyph(target, font, c, - x, (real32)y, color); - x += font_get_glyph_width(font, c); - } - return CEIL32(x); -} - -internal real32 -draw_string_mono(Render_Target *target, Render_Font *font, char *str, - real32 x, real32 y, real32 advance, u32 color){ - for (i32 i = 0; str[i]; ++i){ - font_draw_glyph_mono(target, font, str[i], - x, y, advance, color); - x += advance; - } - return x; -} - -internal i32 -draw_string(Render_Target *target, Render_Font *font, String str, - i32 x_, i32 y, u32 color){ - real32 x = (real32)x_; - for (i32 i = 0; i < str.size; ++i){ - char c = str.str[i]; - font_draw_glyph(target, font, c, - x, (real32)y, color); - x += font_get_glyph_width(font, c); - } - return CEIL32(x); -} - -internal real32 -draw_string_mono(Render_Target *target, Render_Font *font, String str, - real32 x, real32 y, real32 advance, u32 color){ - for (i32 i = 0; i < str.size; ++i){ - font_draw_glyph_mono(target, font, str.str[i], - x, y, advance, color); - x += advance; - } - return x; -} - -internal real32 -font_get_max_width(Render_Font *font, char *characters){ - stbtt_bakedchar *chardata = font->chardata; - real32 cx, x = 0; - for (i32 i = 0; characters[i]; ++i){ - cx = chardata[characters[i]].xadvance; - if (x < cx) x = cx; - } - return x; -} - -internal real32 -font_get_string_width(Render_Font *font, String string){ - real32 result = 0; - for (i32 i = 0; i < string.size; ++i){ - font_get_glyph_width(font, string.str[i]); - } - return result; -} -#endif - // BOTTOM + diff --git a/4ed_rendering.h b/4ed_rendering.h index bed4bdce..44552a16 100644 --- a/4ed_rendering.h +++ b/4ed_rendering.h @@ -12,6 +12,20 @@ #ifndef FRED_RENDERING_H #define FRED_RENDERING_H +internal void* +part_alloc(int size, void *context){ + Partition *part = (Partition*)context; + void *result = push_block(part, size); + return(result); +} + +internal void +part_free(void *ptr, void *context){ +} + +#define STBTT_malloc part_alloc +#define STBTT_free part_free + #define STB_TRUETYPE_IMPLEMENTATION #include "stb_truetype.h" @@ -25,7 +39,7 @@ struct Render_Font{ b32 loaded; Glyph_Data glyphs[256]; - stbtt_bakedchar chardata[256]; + stbtt_packedchar chardata[256]; float advance_data[256]; i32 height, ascent, descent, line_skip; i32 advance; @@ -67,16 +81,16 @@ struct Render_Piece_Gradient{ struct Render_Piece_Glyph{ Vec2 pos; u32 color; - Render_Font *font_id; - u16 character; + i16 font_id; + u8 character; }; struct Render_Piece_Glyph_Advance{ Vec2 pos; u32 color; f32 advance; - Render_Font *font_id; - u16 character; + i16 font_id; + u8 character; }; struct Render_Piece_Combined{ @@ -93,16 +107,62 @@ struct Render_Piece_Combined{ typedef Draw_Push_Piece_Sig(Draw_Push_Piece); #define Font_Load_Sig(name) i32 name( \ - System_Functions *system, \ + Partition *partition, \ Render_Font *font_out, \ char *filename, \ i32 pt_size, \ - void *font_block, \ - i32 font_block_size, \ - i32 *memory_used_out, \ i32 tab_width) typedef Font_Load_Sig(Font_Load); +#define Font_Info_Load_Sig(name) i32 name( \ + Partition *partition, \ + char *filename, \ + i32 pt_size, \ + i32 *height, \ + i32 *advance) +typedef Font_Info_Load_Sig(Font_Info_Load); + +#define Release_Font_Sig(name) void name(Render_Font *font) +typedef Release_Font_Sig(Release_Font); + +struct Font_Table_Entry{ + u32 hash; + String name; + i16 font_id; +}; + +struct Font_Info{ + Render_Font *font; + String filename; + String name; + i32 height, advance; + i32 pt_size; +}; + +struct Font_Slot{ + Font_Slot *next, *prev; + i16 font_id; + u8 padding[14]; +}; + +struct Font_Set{ + Font_Info *info; + Font_Table_Entry *entries; + u32 count, max; + + void *font_block; + Font_Slot free_slots; + Font_Slot used_slots; + + Font_Info_Load *font_info_load; + Font_Load *font_load; + Release_Font *release_font; + + b8 *font_used_flags; + i16 used_this_frame; + i16 live_max; +}; + struct Render_Target{ void *handle; void *context; @@ -115,10 +175,12 @@ struct Render_Target{ byte *push_buffer; i32 size, max; + Font_Set font_set; + Partition *partition; + Draw_Push_Clip *push_clip; Draw_Pop_Clip *pop_clip; Draw_Push_Piece *push_piece; - Font_Load *font_load; }; inline i32_Rect @@ -126,6 +188,12 @@ rect_from_target(Render_Target *target){ return i32R(0, 0, target->width, target->height); } +inline Font_Info* +get_font_info(Font_Set *set, i16 font_id){ + Font_Info *result = set->info + font_id - 1; + return(result); +} + #endif // BOTTOM diff --git a/4ed_rendering_helper.cpp b/4ed_rendering_helper.cpp index 161fdda3..d03bb2c8 100644 --- a/4ed_rendering_helper.cpp +++ b/4ed_rendering_helper.cpp @@ -19,6 +19,18 @@ draw_pop_clip(Render_Target *target){ target->pop_clip(target); } +internal void +begin_render_section(Render_Target *target){ + Font_Set *font_set = &target->font_set; + font_set->used_this_frame = 0; + memset(font_set->font_used_flags, 0, font_set->max); +} + +internal void +end_render_section(Render_Target *target){ + //Font_Set *font_set = &target->font_set; +} + internal void draw_rectangle(Render_Target *target, i32_Rect rect, u32 color){ Render_Piece_Combined piece; @@ -81,87 +93,80 @@ font_predict_size(i32 pt_size){ return pt_size*pt_size*128; } -internal i32 -font_load(Render_Target *target, System_Functions *system, - Render_Font *font_out, char *filename, i32 pt_size, - void *font_block, i32 font_block_size, - i32 *memory_used_out, i32 tab_width){ - i32 result = - target->font_load(system, font_out, filename, pt_size, - font_block, font_block_size, memory_used_out, tab_width); - return result; -} - internal void font_set_tabwidth(Render_Font *font, i32 tab_width){ font->chardata['\t'].xadvance *= font->chardata[' '].xadvance * tab_width; } -// TODO(allen): Abstract Render_Font all the fucking way out of the app side code. internal void -font_draw_glyph_mono(Render_Target *target, Render_Font *font, u16 character, - f32 x, f32 y, f32 advance, u32 color){ +font_draw_glyph_mono(Render_Target *target, i16 font_id, + u8 character, f32 x, f32 y, f32 advance, u32 color){ Render_Piece_Combined piece; piece.header.type = piece_type_mono_glyph; piece.glyph.pos.x = x; piece.glyph.pos.y = y; piece.glyph.color = color; - piece.glyph.font_id = font; + piece.glyph.font_id = font_id; piece.glyph.character = character; target->push_piece(target, piece); + font_set_use(target->partition, &target->font_set, font_id); } inline void -font_draw_glyph_mono(Render_Target *target, Render_Font *font, u16 character, - real32 x, real32 y, u32 color){ - font_draw_glyph_mono(target, font, character, x, y, (real32)font->advance, color); +font_draw_glyph_mono(Render_Target *target, i16 font_id, + u8 character, f32 x, f32 y, u32 color){ + f32 advance = (f32)get_font_info(&target->font_set, font_id)->advance; + font_draw_glyph_mono(target, font_id, character, x, y, advance, color); } internal void -font_draw_glyph(Render_Target *target, Render_Font *font, u16 character, - f32 x, f32 y, u32 color){ +font_draw_glyph(Render_Target *target, i16 font_id, + u8 character, f32 x, f32 y, u32 color){ Render_Piece_Combined piece; piece.header.type = piece_type_glyph; piece.glyph.pos.x = x; piece.glyph.pos.y = y; piece.glyph.color = color; - piece.glyph.font_id = font; + piece.glyph.font_id = font_id; piece.glyph.character = character; target->push_piece(target, piece); + font_set_use(target->partition, &target->font_set, font_id); } -inline real32 -font_get_glyph_width(Render_Font *font, u16 character){ - return font->chardata[character].xadvance; +inline f32 +font_get_glyph_width(Render_Target *target, i16 font_id, u16 character){ + Render_Font *font = get_font_info(&target->font_set, font_id)->font; + f32 result = 0.f; + if (font) result = font->chardata[character].xadvance; + return (result); } -internal real32 -font_string_width(Render_Font *font, char *str){ - real32 x = 0; +internal f32 +font_string_width(Render_Target *target, i16 font_id, char *str){ + f32 x = 0; for (i32 i = 0; str[i]; ++i){ - x += font_get_glyph_width(font, str[i]); + x += font_get_glyph_width(target, font_id, str[i]); } return x; } internal i32 -draw_string(Render_Target *target, Render_Font *font, char *str, - i32 x_, i32 y, u32 color){ +draw_string(Render_Target *target, i16 font_id, + char *str, i32 x_, i32 y, u32 color){ real32 x = (real32)x_; for (i32 i = 0; str[i]; ++i){ char c = str[i]; - font_draw_glyph(target, font, c, - x, (real32)y, color); - x += font_get_glyph_width(font, c); + font_draw_glyph(target, font_id, c, x, (f32)y, color); + x += font_get_glyph_width(target, font_id, c); } return CEIL32(x); } -internal real32 -draw_string_mono(Render_Target *target, Render_Font *font, char *str, - real32 x, real32 y, real32 advance, u32 color){ +internal f32 +draw_string_mono(Render_Target *target, i16 font_id, + char *str, f32 x, f32 y, f32 advance, u32 color){ for (i32 i = 0; str[i]; ++i){ - font_draw_glyph_mono(target, font, str[i], + font_draw_glyph_mono(target, font_id, str[i], x, y, advance, color); x += advance; } @@ -169,47 +174,51 @@ draw_string_mono(Render_Target *target, Render_Font *font, char *str, } internal i32 -draw_string(Render_Target *target, Render_Font *font, String str, - i32 x_, i32 y, u32 color){ - real32 x = (real32)x_; +draw_string(Render_Target *target, i16 font_id, + String str, i32 x_, i32 y, u32 color){ + f32 x = (f32)x_; for (i32 i = 0; i < str.size; ++i){ char c = str.str[i]; - font_draw_glyph(target, font, c, - x, (real32)y, color); - x += font_get_glyph_width(font, c); + font_draw_glyph(target, font_id, c, + x, (f32)y, color); + x += font_get_glyph_width(target, font_id, c); } return CEIL32(x); } -internal real32 -draw_string_mono(Render_Target *target, Render_Font *font, String str, - real32 x, real32 y, real32 advance, u32 color){ +internal f32 +draw_string_mono(Render_Target *target, i16 font_id, + String str, f32 x, f32 y, f32 advance, u32 color){ for (i32 i = 0; i < str.size; ++i){ - font_draw_glyph_mono(target, font, str.str[i], - x, y, advance, color); + font_draw_glyph_mono(target, font_id, + str.str[i], x, y, advance, color); x += advance; } return x; } -internal real32 -font_get_max_width(Render_Font *font, char *characters){ - stbtt_bakedchar *chardata = font->chardata; - real32 cx, x = 0; - for (i32 i = 0; characters[i]; ++i){ - cx = chardata[characters[i]].xadvance; - if (x < cx) x = cx; +internal f32 +font_get_max_width(Font_Set *font_set, i16 font_id, char *characters){ + Render_Font *font = get_font_info(font_set, font_id)->font; + f32 cx, x = 0; + if (font){ + stbtt_packedchar *chardata = font->chardata; + for (i32 i = 0; characters[i]; ++i){ + cx = chardata[characters[i]].xadvance; + if (x < cx) x = cx; + } } return x; } -internal real32 -font_get_string_width(Render_Font *font, String string){ - real32 result = 0; +internal f32 +font_get_string_width(Render_Target *target, i16 font_id, String string){ + f32 result = 0; for (i32 i = 0; i < string.size; ++i){ - font_get_glyph_width(font, string.str[i]); + font_get_glyph_width(target, font_id, string.str[i]); } return result; } // BOTTOM + diff --git a/4ed_rendering_old.cpp b/4ed_rendering_old.cpp deleted file mode 100644 index 41a140a1..00000000 --- a/4ed_rendering_old.cpp +++ /dev/null @@ -1,405 +0,0 @@ -/* - * Mr. 4th Dimention - Allen Webster - * - * 12.17.2014 - * - * Rendering layer for project codename "4ed" - * - */ - -// TOP - -#if 0 -inline void -draw_set_clip(Render_Target *target, i32_Rect clip_box){ - glScissor(clip_box.x0, - target->height - clip_box.y1, - clip_box.x1 - clip_box.x0, - clip_box.y1 - clip_box.y0); -} - -inline void -draw_push_clip(Render_Target *target, i32_Rect clip_box){ - Assert(target->clip_top == -1 || - fits_inside(clip_box, target->clip_boxes[target->clip_top])); - Assert(target->clip_top+1 < ArrayCount(target->clip_boxes)); - target->clip_boxes[++target->clip_top] = clip_box; - draw_set_clip(target, clip_box); -} - -inline void -draw_pop_clip(Render_Target *target){ - Assert(target->clip_top > 0); - --target->clip_top; - draw_set_clip(target, target->clip_boxes[target->clip_top]); -} - -inline void -draw_bind_texture(Render_Target *target, i32 texid){ - if (target->bound_texture != texid){ - glBindTexture(GL_TEXTURE_2D, texid); - target->bound_texture = texid; - } -} - -internal void -draw_set_color(Render_Target *target, u32 color){ - if (target->color != color){ - target->color = color; - Vec4 c = unpack_color4(color); - glColor4f(c.r, c.g, c.b, c.a); - } -} - -internal void -draw_rectangle(Render_Target *target, i32_Rect rect, u32 color){ - draw_set_color(target, color); - draw_bind_texture(target, 0); - glBegin(GL_QUADS); - { - glVertex2i(rect.x0, rect.y0); - glVertex2i(rect.x0, rect.y1); - glVertex2i(rect.x1, rect.y1); - glVertex2i(rect.x1, rect.y0); - } - glEnd(); -} - -internal void -draw_rectangle(Render_Target *target, real32_Rect rect, u32 color){ - draw_set_color(target, color); - draw_bind_texture(target, 0); - glBegin(GL_QUADS); - { - glVertex2f(rect.x0, rect.y0); - glVertex2f(rect.x0, rect.y1); - glVertex2f(rect.x1, rect.y1); - glVertex2f(rect.x1, rect.y0); - } - glEnd(); -} - -internal void -draw_triangle_3corner(Render_Target *target, - real32 x0, real32 y0, - real32 x1, real32 y1, - real32 x2, real32 y2, - u32 color){ - draw_set_color(target, color); - draw_bind_texture(target, 0); - glBegin(GL_TRIANGLES); - { - glVertex2f(x0, y0); - glVertex2f(x1, y1); - glVertex2f(x2, y2); - } - glEnd(); -} - -internal void -draw_gradient_2corner_clipped(Render_Target *target, real32_Rect rect, - Vec4 color_left, Vec4 color_right){ - Vec4 cl = color_left; - Vec4 cr = color_right; - - draw_bind_texture(target, 0); - glBegin(GL_QUADS); - { - glColor4f(cl.r, cl.g, cl.b, cl.a); - glVertex2f(rect.x0, rect.y0); - glVertex2f(rect.x0, rect.y1); - - glColor4f(cr.r, cr.g, cr.b, cr.a); - glVertex2f(rect.x1, rect.y1); - glVertex2f(rect.x1, rect.y0); - } - glEnd(); -} - -inline void -draw_gradient_2corner_clipped(Render_Target *target, real32 l, real32 t, real32 r, real32 b, - Vec4 color_left, Vec4 color_right){ - draw_gradient_2corner_clipped(target, f32R(l,t,r,b), color_left, color_right); -} - -internal void -draw_rectangle_outline(Render_Target *target, real32_Rect rect, u32 color){ - real32_Rect r; - r.x0 = rect.x0 + .5f; - r.y0 = rect.y0 + .5f; - r.x1 = rect.x1 - .5f; - r.y1 = rect.y1 - .5f; - - draw_set_color(target, color); - draw_bind_texture(target, 0); - glBegin(GL_LINE_STRIP); - { - glVertex2f(r.x0, r.y0); - glVertex2f(r.x1, r.y0); - glVertex2f(r.x1, r.y1); - glVertex2f(r.x0, r.y1); - glVertex2f(r.x0, r.y0); - } - glEnd(); -} - -inline void -draw_rectangle_outline(Render_Target *target, i32_Rect rect, u32 color){ - draw_rectangle_outline(target, f32R(rect), color); -} - -internal void -draw_margin(Render_Target *target, i32_Rect outer, i32_Rect inner, u32 color){ - draw_rectangle(target, i32R(outer.x0, outer.y0, outer.x1, inner.y0), color); - draw_rectangle(target, i32R(outer.x0, inner.y1, outer.x1, outer.y1), color); - draw_rectangle(target, i32R(outer.x0, inner.y0, inner.x0, inner.y1), color); - draw_rectangle(target, i32R(inner.x1, inner.y0, outer.x1, inner.y1), color); -} - -// TODO(allen): eliminate this? -internal i32 -font_init(){ - return 1; -} - -inline internal i32 -font_predict_size(i32 pt_size){ - return pt_size*pt_size*128; -} - -internal i32 -font_load(System_Functions *system, - Render_Font *font_out, char *filename, i32 pt_size, - void *font_block, i32 font_block_size, - i32 *memory_used_out, i32 tab_width){ - i32 result = 1; - File_Data file; - file = system->load_file(filename); - - if (!file.data){ - result = 0; - } - - else{ - stbtt_fontinfo font; - if (!stbtt_InitFont(&font, (u8*)file.data, 0)){ - result = 0; - } - else{ - i32 ascent, descent, line_gap; - real32 scale; - - stbtt_GetFontVMetrics(&font, &ascent, &descent, &line_gap); - scale = stbtt_ScaleForPixelHeight(&font, (real32)pt_size); - - real32 scaled_ascent, scaled_descent, scaled_line_gap; - - scaled_ascent = scale*ascent; - scaled_descent = scale*descent; - scaled_line_gap = scale*line_gap; - - font_out->height = (i32)(scaled_ascent - scaled_descent + scaled_line_gap); - font_out->ascent = (i32)(scaled_ascent); - font_out->descent = (i32)(scaled_descent); - font_out->line_skip = (i32)(scaled_line_gap); - - u8 *memory_cursor = (u8*)font_block; - Assert(pt_size*pt_size*128 <= font_block_size); - - i32 tex_width, tex_height; - tex_width = pt_size*128; - tex_height = pt_size*2; - - font_out->tex_width = tex_width; - font_out->tex_height = tex_height; - - if (stbtt_BakeFontBitmap((u8*)file.data, 0, (real32)pt_size, - memory_cursor, tex_width, tex_height, 0, 128, font_out->chardata) <= 0){ - result = 0; - } - - else{ - GLuint font_tex; - glGenTextures(1, &font_tex); - glBindTexture(GL_TEXTURE_2D, font_tex); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, tex_width, tex_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, memory_cursor); - - font_out->tex = font_tex; - glBindTexture(GL_TEXTURE_2D, 0); - } - - font_out->chardata['\r'] = font_out->chardata[' ']; - font_out->chardata['\n'] = font_out->chardata[' ']; - font_out->chardata['\t'] = font_out->chardata[' ']; - font_out->chardata['\t'].xadvance *= tab_width; - - i32 max_advance = 0; - for (u16 code_point = 0; code_point < 128; ++code_point){ - if (stbtt_FindGlyphIndex(&font, code_point) != 0){ - font_out->glyphs[code_point].exists = 1; - i32 advance = CEIL32(font_out->chardata[code_point].xadvance); - if (max_advance < advance) max_advance = advance; - font_out->advance_data[code_point] = font_out->chardata[code_point].xadvance; - } - } - font_out->advance = max_advance - 1; - } - system->free_file(file); - } - - return result; -} - -internal void -font_set_tabwidth(Render_Font *font, i32 tab_width){ - font->chardata['\t'].xadvance *= font->chardata[' '].xadvance * tab_width; -} - -internal void -font_draw_glyph_mono(Render_Target *target, Render_Font *font, u16 character, - real32 x, real32 y, real32 advance, u32 color){ - real32 x_shift, y_shift; - i32 left = font->chardata[character].x0; - i32 right = font->chardata[character].x1; - i32 width = (right - left); - x_shift = (real32)(advance - width) * .5f - font->chardata[character].xoff; - y_shift = (real32)font->ascent; - - x += x_shift; - y += y_shift; - - stbtt_aligned_quad q; - stbtt_GetBakedQuadUnrounded(font->chardata, font->tex_width, font->tex_height, character, &x, &y, &q, 1); - - draw_set_color(target, color); - draw_bind_texture(target, font->tex); - glBegin(GL_QUADS); - { - glTexCoord2f(q.s0, q.t1); glVertex2f(q.x0, q.y1); - glTexCoord2f(q.s1, q.t1); glVertex2f(q.x1, q.y1); - glTexCoord2f(q.s1, q.t0); glVertex2f(q.x1, q.y0); - glTexCoord2f(q.s0, q.t0); glVertex2f(q.x0, q.y0); - } - glEnd(); -} - -inline void -font_draw_glyph_mono(Render_Target *target, Render_Font *font, u16 character, - real32 x, real32 y, u32 color){ - font_draw_glyph_mono(target, font, character, x, y, (real32)font->advance, color); -} - -internal void -font_draw_glyph(Render_Target *target, Render_Font *font, u16 character, - real32 x, real32 y, u32 color){ - real32 x_shift, y_shift; - x_shift = 0; - y_shift = (real32)font->ascent; - - x += x_shift; - y += y_shift; - - stbtt_aligned_quad q; - stbtt_GetBakedQuadUnrounded(font->chardata, font->tex_width, font->tex_height, character, &x, &y, &q, 1); - - draw_set_color(target, color); - draw_bind_texture(target, font->tex); - glBegin(GL_QUADS); - { - glTexCoord2f(q.s0, q.t1); glVertex2f(q.x0, q.y1); - glTexCoord2f(q.s1, q.t1); glVertex2f(q.x1, q.y1); - glTexCoord2f(q.s1, q.t0); glVertex2f(q.x1, q.y0); - glTexCoord2f(q.s0, q.t0); glVertex2f(q.x0, q.y0); - } - glEnd(); -} - -inline real32 -font_get_glyph_width(Render_Font *font, u16 character){ - return font->chardata[character].xadvance; -} - -internal real32 -font_string_width(Render_Font *font, char *str){ - real32 x = 0; - for (i32 i = 0; str[i]; ++i){ - x += font_get_glyph_width(font, str[i]); - } - return x; -} - -internal i32 -draw_string(Render_Target *target, Render_Font *font, char *str, - i32 x_, i32 y, u32 color){ - real32 x = (real32)x_; - for (i32 i = 0; str[i]; ++i){ - char c = str[i]; - font_draw_glyph(target, font, c, - x, (real32)y, color); - x += font_get_glyph_width(font, c); - } - return CEIL32(x); -} - -internal real32 -draw_string_mono(Render_Target *target, Render_Font *font, char *str, - real32 x, real32 y, real32 advance, u32 color){ - for (i32 i = 0; str[i]; ++i){ - font_draw_glyph_mono(target, font, str[i], - x, y, advance, color); - x += advance; - } - return x; -} - -internal i32 -draw_string(Render_Target *target, Render_Font *font, String str, - i32 x_, i32 y, u32 color){ - real32 x = (real32)x_; - for (i32 i = 0; i < str.size; ++i){ - char c = str.str[i]; - font_draw_glyph(target, font, c, - x, (real32)y, color); - x += font_get_glyph_width(font, c); - } - return CEIL32(x); -} - -internal real32 -draw_string_mono(Render_Target *target, Render_Font *font, String str, - real32 x, real32 y, real32 advance, u32 color){ - for (i32 i = 0; i < str.size; ++i){ - font_draw_glyph_mono(target, font, str.str[i], - x, y, advance, color); - x += advance; - } - return x; -} - -internal real32 -font_get_max_width(Render_Font *font, char *characters){ - stbtt_bakedchar *chardata = font->chardata; - real32 cx, x = 0; - for (i32 i = 0; characters[i]; ++i){ - cx = chardata[characters[i]].xadvance; - if (x < cx) x = cx; - } - return x; -} - -internal real32 -font_get_string_width(Render_Font *font, String string){ - real32 result = 0; - for (i32 i = 0; i < string.size; ++i){ - font_get_glyph_width(font, string.str[i]); - } - return result; -} -#endif - -// BOTTOM diff --git a/4ed_style.cpp b/4ed_style.cpp index f2a07e6d..2d5cda45 100644 --- a/4ed_style.cpp +++ b/4ed_style.cpp @@ -214,9 +214,9 @@ struct Style_File_Format{ struct Style{ char name_[24]; String name; - Render_Font *font; Style_Main_Data main; - bool32 font_changed; + b32 font_changed; + i16 font_id; }; struct Style_Library{ @@ -224,11 +224,6 @@ struct Style_Library{ i32 count, max; }; -struct Font_Set{ - Render_Font *fonts; - i32 count, max; -}; - internal void style_copy(Style *dst, Style *src){ *dst = *src; @@ -243,21 +238,6 @@ style_set_name(Style *style, String name){ copy(&style->name, name); } -internal Render_Font* -font_set_extract(Font_Set *fonts, char *name, i32 size){ - String n = make_string(name, size); - i32 count = fonts->count; - Render_Font *result = 0; - Render_Font *font = fonts->fonts; - for (i32 i = 0; i < count; ++i, ++font){ - if (match(n, font->name)){ - result = font; - break; - } - } - return result; -} - internal void style_form_convert(Style_File_Format_v2 *o, Style_File_Format_v1 *i){ o->name_size = i->name_size; @@ -415,7 +395,11 @@ style_format_for_use(Font_Set *fonts, Style *out, Style_File_Format *style){ out->name = make_string(out->name_, 0, ArrayCount(out->name_) - 1); out->name_[ArrayCount(out->name_) - 1] = 0; copy(&out->name, style->name); - out->font = font_set_extract(fonts, style->font_name, style->font_name_size); + if (!font_set_extract(fonts, + make_string(style->font_name, style->font_name_size), + &out->font_id)){ + out->font_id = 0; + } i32 spec_count = style->color_specifier_count; Style_Color_Specifier *spec = (Style_Color_Specifier*)(style + 1); @@ -443,7 +427,11 @@ style_format_for_use(Font_Set *fonts, Style *out, Style_File_Format_v4 *style){ out->name = make_string(out->name_, 0, ArrayCount(out->name_) - 1); out->name_[ArrayCount(out->name_) - 1] = 0; copy(&out->name, style->name); - out->font = font_set_extract(fonts, style->font_name, style->font_name_size); + if (!font_set_extract(fonts, + make_string(style->font_name, style->font_name_size), + &out->font_id)){ + out->font_id = 0; + } out->main = style->main; } @@ -475,11 +463,9 @@ style_format_for_use(Font_Set *fonts, Style *out, Style_File_Format_v3 *style){ } internal b32 -style_library_import(System_Functions *system, - char *filename, Font_Set *fonts, Style *out, i32 max, +style_library_import(Data file, Font_Set *fonts, Style *out, i32 max, i32 *count_opt, i32 *total_opt = 0){ b32 result = 1; - Data file = system->load_file(filename); Style_Page_Header *h = 0; if (!file.data){ @@ -540,13 +526,26 @@ style_library_import(System_Functions *system, default: result = 0; break; } -early_exit: - system->free_file(file); +early_exit:; } return result; } +#if 0 +internal b32 +style_library_import(System_Functions *system, + char *filename, Font_Set *fonts, Style *out, i32 max, + i32 *count_opt, i32 *total_opt = 0){ + b32 result; + Data file = system->load_file(filename); + result = style_library_import(file, fonts, out, max, count_opt, total_opt); + system->free_file(file); + + return result; +} +#endif + internal b32 style_library_add(Style_Library *library, Style *style){ b32 result = 0; @@ -572,12 +571,13 @@ style_library_add(Style_Library *library, Style *style){ } internal Style_File_Format* -style_format_for_file(Style *style, Style_File_Format *out){ - Render_Font *font = style->font; +style_format_for_file(Font_Set *set, Style *style, Style_File_Format *out){ out->name_size = style->name.size; memcpy(out->name, style->name.str, ArrayCount(out->name)); - out->font_name_size = font->name.size; - memcpy(out->font_name, font->name.str, ArrayCount(out->font_name)); + + String font_name = get_font_info(set, style->font_id)->name; + out->font_name_size = font_name.size; + memcpy(out->font_name, font_name.str, font_name.size); Style_Color_Specifier *spec = (Style_Color_Specifier*)(out + 1); i32 count = 0; @@ -597,10 +597,12 @@ style_format_for_file(Style *style, Style_File_Format *out){ } internal void -style_library_export(System_Functions *system, char *filename, Style **styles, i32 count){ +style_library_export(System_Functions *system, Exchange *exchange, Mem_Options *mem, + Font_Set *set, char *filename, Style **styles, i32 count){ i32 size = count*(sizeof(Style_File_Format) + STAG_COUNT*sizeof(Style_Color_Specifier)) + sizeof(P4C_Page_Header) + sizeof(Style_Page_Header); - void *data = system->get_memory(size); + Temp_Memory temp = begin_temp_memory(&mem->part); + void *data = push_block(&mem->part, size); void *cursor = data; { @@ -620,10 +622,17 @@ style_library_export(System_Functions *system, char *filename, Style **styles, i Style_File_Format *out = (Style_File_Format*)cursor; Style **in = styles; for (i32 i = 0; i < count; ++i){ - out = style_format_for_file(*in++, out); + out = style_format_for_file(set, *in++, out); } + + int filename_len = str_size(filename); + exchange_save_file(exchange, filename, filename_len, + (byte*)data, size, size); +#if 0 system->save_file(filename, data, size); - system->free_memory(data); +#endif + + end_temp_memory(temp); } // BOTTOM diff --git a/4ed_system.h b/4ed_system.h index 741d3259..e35545b1 100644 --- a/4ed_system.h +++ b/4ed_system.h @@ -9,72 +9,34 @@ // TOP -struct System_Functions; - struct Plat_Handle{ u32 d[4]; }; -struct Time_Stamp{ - u64 time; - b32 success; -}; - -#define Sys_Load_File_Sig(name) Data name(char *filename) -typedef Sys_Load_File_Sig(System_Load_File); - -#define Sys_Save_File_Sig(name) i32 name(char *filename, void *data, i32 size) -typedef Sys_Save_File_Sig(System_Save_File); - -#define Sys_File_Size_Sig(name) i32 name(char *filename) -typedef Sys_File_Size_Sig(System_File_Size); - -#define Sys_File_Time_Stamp_Sig(name) Time_Stamp name(char *filename) -typedef Sys_File_Time_Stamp_Sig(System_File_Time_Stamp); - -#define Sys_Time_Stamp_Now_Sig(name) u64 name() -typedef Sys_Time_Stamp_Now_Sig(System_Time_Stamp_Now); - -#define Sys_Free_File_Sig(name) void name(Data file) -typedef Sys_Free_File_Sig(System_Free_File); - -#define Sys_Get_Current_Directory_Sig(name) i32 name(char *out, i32 max) -typedef Sys_Get_Current_Directory_Sig(System_Get_Current_Directory); - -#define Sys_Get_Easy_Directory_Sig(name) i32 name(char *destination) -typedef Sys_Get_Easy_Directory_Sig(System_Get_Easy_Directory); - struct File_Info{ String filename; b32 folder; }; struct File_List{ - File_Info *infos; void *block; - i32 count; + File_Info *infos; + i32 count, block_size; }; -#define Sys_Get_File_List_Sig(name) File_List name(String directory) -typedef Sys_Get_File_List_Sig(System_Get_File_List); +#define Sys_File_Time_Stamp_Sig(name) u64 name(char *filename) +typedef Sys_File_Time_Stamp_Sig(System_File_Time_Stamp); -#define Sys_Free_File_List_Sig(name) void name(File_List list) -typedef Sys_Free_File_List_Sig(System_Free_File_List); - -#define Sys_Get_Memory_Sig(name) void* name(i32 size, i32 line_number, char *filename) -typedef Sys_Get_Memory_Sig(System_Get_Memory); - -#define get_memory(size) get_memory_full(size, __LINE__, __FILE__) - -#define Sys_Free_Memory_Sig(name) void name(void *block) -typedef Sys_Free_Memory_Sig(System_Free_Memory); +#define Sys_Set_File_List_Sig(name) void name(File_List *file_list, String directory) +typedef Sys_Set_File_List_Sig(System_Set_File_List); #define Sys_Post_Clipboard_Sig(name) void name(String str) typedef Sys_Post_Clipboard_Sig(System_Post_Clipboard); -#define Sys_Time_Sig(name) i64 name() +#define Sys_Time_Sig(name) u64 name() typedef Sys_Time_Sig(System_Time); +// cli struct CLI_Handles{ Plat_Handle proc; Plat_Handle out_read; @@ -82,7 +44,7 @@ struct CLI_Handles{ u32 scratch_space[4]; }; -#define Sys_CLI_Call_Sig(name) b32 name(char *path, char *script, CLI_Handles *cli) +#define Sys_CLI_Call_Sig(name) b32 name(char *path, char *script_name, CLI_Handles *cli_out) typedef Sys_CLI_Call_Sig(System_CLI_Call); #define Sys_CLI_Begin_Update_Sig(name) void name(CLI_Handles *cli) @@ -94,6 +56,7 @@ typedef Sys_CLI_Update_Step_Sig(System_CLI_Update_Step); #define Sys_CLI_End_Update_Sig(name) b32 name(CLI_Handles *cli) typedef Sys_CLI_End_Update_Sig(System_CLI_End_Update); +// thread struct Thread_Context; enum Lock_ID{ @@ -120,8 +83,12 @@ struct Thread_Memory{ i32 id; }; -#define Job_Callback_Sig(name) void name(\ - System_Functions *system, Thread_Context *thread, Thread_Memory *memory, void *data[2]) +struct Thread_Exchange; +struct System_Functions; + +#define Job_Callback_Sig(name) void name( \ + System_Functions *system, Thread_Context *thread, Thread_Memory *memory, \ + Thread_Exchange *exchange, void *data[2]) typedef Job_Callback_Sig(Job_Callback); struct Job_Data{ @@ -130,21 +97,38 @@ struct Job_Data{ i32 memory_request; }; -#define Sys_Thread_Get_ID_Sig(name) u32 name(Thread_Context *thread) -typedef Sys_Thread_Get_ID_Sig(System_Thread_Get_ID); +struct Full_Job_Data{ + Job_Data job; + + u32 job_memory_index; + u32 running_thread; + b32 finished; + u32 id; +}; -#define Sys_Thread_Current_Job_ID_Sig(name) u32 name(Thread_Context *thread) -typedef Sys_Thread_Current_Job_ID_Sig(System_Thread_Current_Job_ID); +struct Work_Queue{ + Full_Job_Data jobs[256]; + Plat_Handle semaphore; + volatile u32 write_position; + volatile u32 read_position; +}; -#define Sys_Post_Job_Sig(name) u32 name(Thread_Group_ID id, Job_Data job) +#define THREAD_NOT_ASSIGNED 0xFFFFFFFF + +#define JOB_ID_WRAP (ArrayCount(queue->jobs) * 4) +#define QUEUE_WRAP (ArrayCount(queue->jobs)) + +struct Thread_Exchange{ + Work_Queue queues[THREAD_GROUP_COUNT]; + volatile u32 force_redraw; +}; + +#define Sys_Post_Job_Sig(name) u32 name(Thread_Group_ID group_id, Job_Data job) typedef Sys_Post_Job_Sig(System_Post_Job); -#define Sys_Cancel_Job_Sig(name) void name(Thread_Group_ID id, u32 job_id) +#define Sys_Cancel_Job_Sig(name) void name(Thread_Group_ID group_id, u32 job_id) typedef Sys_Cancel_Job_Sig(System_Cancel_Job); -#define Sys_Job_Is_Pending_Sig(name) b32 name(Thread_Group_ID id, u32 job_id) -typedef Sys_Job_Is_Pending_Sig(System_Job_Is_Pending); - #define Sys_Grow_Thread_Memory_Sig(name) void name(Thread_Memory *memory) typedef Sys_Grow_Thread_Memory_Sig(System_Grow_Thread_Memory); @@ -154,9 +138,7 @@ typedef Sys_Acquire_Lock_Sig(System_Acquire_Lock); #define Sys_Release_Lock_Sig(name) void name(i32 id) typedef Sys_Release_Lock_Sig(System_Release_Lock); -#define Sys_Force_Redraw_Sig(name) void name() -typedef Sys_Force_Redraw_Sig(System_Force_Redraw); - +// debug #define INTERNAL_Sys_Sentinel_Sig(name) Bubble* name() typedef INTERNAL_Sys_Sentinel_Sig(INTERNAL_System_Sentinel); @@ -167,40 +149,34 @@ typedef INTERNAL_Sys_Get_Thread_States_Sig(INTERNAL_System_Get_Thread_States); typedef INTERNAL_Sys_Debug_Message_Sig(INTERNAL_System_Debug_Message); struct System_Functions{ - System_Load_File *load_file; - System_Save_File *save_file; + // files: 2 System_File_Time_Stamp *file_time_stamp; - System_Time_Stamp_Now *time_stamp_now; - System_Free_File *free_file; - - System_Get_Current_Directory *get_current_directory; - System_Get_Easy_Directory *get_easy_directory; + System_Set_File_List *set_file_list; - System_Get_File_List *get_file_list; - System_Free_File_List *free_file_list; - - System_Get_Memory *get_memory_full; - System_Free_Memory *free_memory; + // file system navigation (4coder_custom.h): 2 + Directory_Has_File *directory_has_file; + Directory_CD *directory_cd; + // clipboard: 1 System_Post_Clipboard *post_clipboard; + + // time: 1 System_Time *time; + // cli: 4 System_CLI_Call *cli_call; System_CLI_Begin_Update *cli_begin_update; System_CLI_Update_Step *cli_update_step; System_CLI_End_Update *cli_end_update; - System_Thread_Get_ID *thread_get_id; - System_Thread_Current_Job_ID *thread_current_job_id; + // threads: 5 System_Post_Job *post_job; System_Cancel_Job *cancel_job; - System_Job_Is_Pending *job_is_pending; System_Grow_Thread_Memory *grow_thread_memory; System_Acquire_Lock *acquire_lock; System_Release_Lock *release_lock; - - System_Force_Redraw *force_redraw; - + + // debug: 3 INTERNAL_System_Sentinel *internal_sentinel; INTERNAL_System_Get_Thread_States *internal_get_thread_states; INTERNAL_System_Debug_Message *internal_debug_message; diff --git a/4ed_ttf.cpp b/4ed_ttf.cpp new file mode 100644 index 00000000..89cfa7bc --- /dev/null +++ b/4ed_ttf.cpp @@ -0,0 +1,360 @@ +/* + * YOUR INFO HERE! + */ + +// TOP + +typedef unsigned int Fixed16_16; + +struct Offset_Table{ + Fixed16_16 version; + unsigned short num_tables; + unsigned short search_range; + unsigned short entry_selector; + unsigned short range_shift; +}; + +struct Table_Directory_Entry{ + unsigned long tag; + unsigned long check_sum; + unsigned long offset; + unsigned long length; +}; + +#include +#include + +struct Data{ + char *data; + int size; +}; + +Data +open_file(const char *filename){ + Data result = {}; + FILE *file; + file = fopen(filename, "rb"); + if (file){ + fseek(file, 0, SEEK_END); + result.size = ftell(file); + fseek(file, 0, SEEK_SET); + if (result.size > 0){ + result.data = (char*)malloc(result.size); + fread(result.data, result.size, 1, file); + } + fclose(file); + } + return(result); +} + +void +print(Offset_Table *offset){ + printf("version %d\n", offset->version >> 16); + printf("number of tables %d\n", (int)(offset->num_tables)); + printf("search range %d\n", (int)(offset->search_range)); + printf("entry selector %d\n", (int)(offset->entry_selector)); + printf("range shift %d\n", (int)(offset->range_shift)); +} + +void +print(Table_Directory_Entry *entry){ + printf("tag %.4s\n", &entry->tag); + printf("check sum %08x\n", entry->check_sum); + printf("offset %d\n", entry->offset); + printf("length %d\n", entry->length); +} + +void +byte_reverse(void *ptr, int len){ + char *c; + int i,j; + char t; + c = (char*)ptr; + for (i = 0, j = len-1; i < j; ++i, --j){ + t = c[i]; + c[i] = c[j]; + c[j] = t; + } +} + +void +byte_fix(Offset_Table *offset){ + byte_reverse(&offset->version, 4); + byte_reverse(&offset->num_tables, 2); + byte_reverse(&offset->search_range, 2); + byte_reverse(&offset->entry_selector, 2); + byte_reverse(&offset->range_shift, 2); +} + +void +byte_fix(Table_Directory_Entry *entry){ + byte_reverse(&entry->check_sum, 4); + byte_reverse(&entry->offset, 4); + byte_reverse(&entry->length, 4); +} + +struct cmap_Header{ + unsigned short version; + unsigned short num_subtables; +}; + +struct cmap_Subtable_Entry{ + unsigned short plat_id; + unsigned short plat_encoding_id; + unsigned long offset_from_cmap; +}; + +void +byte_fix(cmap_Header *header){ + byte_reverse(&header->version, 2); + byte_reverse(&header->num_subtables, 2); +} + +void +print(cmap_Header *header){ + printf("cmap tables:\n"); + printf("\tversion %d\n", (int)(header->version)); + printf("\tsubtables %d\n", (int)(header->num_subtables)); +} + +void +byte_fix(cmap_Subtable_Entry *entry){ + byte_reverse(&entry->plat_id, 2); + byte_reverse(&entry->plat_encoding_id, 2); + byte_reverse(&entry->offset_from_cmap, 4); +} + +struct cmap_Subtable_Format4_Header{ + unsigned short format; + unsigned short length; + unsigned short version; + unsigned short segment_count_2; + unsigned short search_range; + unsigned short entry_selector; + unsigned short range_shift; +}; + +void +print(cmap_Subtable_Entry *entry){ + printf("\tplatform id %d\n", (int)(entry->plat_id)); + printf("\tencoding id %d\n", (int)(entry->plat_encoding_id)); + printf("\toffset from cmap %d\n", (int)(entry->offset_from_cmap)); +} + +void +byte_fix(cmap_Subtable_Format4_Header *header){ + byte_reverse(&header->length, 2); + byte_reverse(&header->version, 2); + byte_reverse(&header->segment_count_2, 2); + byte_reverse(&header->search_range, 2); + byte_reverse(&header->entry_selector, 2); + byte_reverse(&header->range_shift, 2); +} + +void +print(cmap_Subtable_Format4_Header *header){ + printf("\t\tlength %d\n", header->length); + printf("\t\tversion %d\n", header->version); + printf("\t\tsegment count doubled %d\n", header->segment_count_2); + printf("\t\tsearch range %d\n", header->search_range); + printf("\t\tentry selector %d\n", header->entry_selector); + printf("\t\trange shift %d\n", header->range_shift); +} + +struct cmap_Subtable_Format4_Segments{ + unsigned short *end_code, *start_code; + unsigned short *id_delta, *id_range_offset; +}; + +void +byte_fix(cmap_Subtable_Format4_Segments segs, int segment_count){ + for (int i = 0; i < segment_count; ++i){ + byte_reverse(segs.end_code + i, 2); + } + + for (int i = 0; i < segment_count; ++i){ + byte_reverse(segs.start_code + i, 2); + } + + for (int i = 0; i < segment_count; ++i){ + byte_reverse(segs.id_delta + i, 2); + } + + for (int i = 0; i < segment_count; ++i){ + byte_reverse(segs.id_range_offset + i, 2); + } +} + +void +print(cmap_Subtable_Format4_Segments segs, int i){ + printf("\t\tsegment %d\n", i); + printf("\t\tend code %d\n", (int)(segs.end_code[i])); + printf("\t\tstart code %d\n", (int)(segs.start_code[i])); + printf("\t\tid delta %d\n", (int)(segs.id_delta[i])); + printf("\t\tid range offset %d\n", (int)(segs.id_range_offset[i])); +} + +void +parse_cmap_subtable4(char *start){ + char *cursor = start; + cmap_Subtable_Format4_Header *header = + (cmap_Subtable_Format4_Header*)cursor; + cursor = (char*)(header + 1); + + byte_fix(header); + print(header); + + int segment_count = (header->segment_count_2 >> 1); + + cmap_Subtable_Format4_Segments segs; + + segs.end_code = (unsigned short*)cursor; + cursor = (char*)(segs.end_code + segment_count); + cursor = cursor + sizeof(unsigned short); + + segs.start_code = (unsigned short*)cursor; + cursor = (char*)(segs.start_code + segment_count); + + segs.id_delta = (unsigned short*)cursor; + cursor = (char*)(segs.id_delta + segment_count); + + segs.id_range_offset = (unsigned short*)cursor; + cursor = (char*)(segs.id_range_offset + segment_count); + + byte_fix(segs, segment_count); + for (int i = 0; i < segment_count; ++i){ + printf("\n"); + print(segs, i); + } +} + +void +parse_cmap_subtable(char *start){ + char *cursor = start; + short *format = (short*)cursor; + byte_reverse(format, 2); + printf("\t\tformat %d\n", (int)(*format)); + + switch (*format){ + case 4: + parse_cmap_subtable4(start); + break; + } +} + +void +parse_cmap(char *start){ + char *cursor = start; + cmap_Header *header = (cmap_Header*)cursor; + cursor = (char*)(header + 1); + + byte_fix(header); + print(header); + + cmap_Subtable_Entry *entry = (cmap_Subtable_Entry*)cursor; + for (int i = 0; i < header->num_subtables; ++i, ++entry){ + byte_fix(entry); + printf("\n"); + print(entry); + + if (entry->plat_id == 3 && entry->plat_encoding_id == 1){ + printf("\n\tMicrosoft Unicode table:\n"); + parse_cmap_subtable(start + entry->offset_from_cmap); + } + } +} + +struct glyf_Glyph_Header{ + short num_contours; + short x_min; + short x_max; + short y_min; + short y_max; +}; + +void +byte_fix(glyf_Glyph_Header *header){ + byte_reverse(&header->num_contours, 2); + byte_reverse(&header->x_min, 2); + byte_reverse(&header->x_max, 2); + byte_reverse(&header->y_min, 2); + byte_reverse(&header->y_max, 2); +} + +void +print(glyf_Glyph_Header *header){ + printf("\tcontours %d\n", (int)(header->num_contours)); + printf("\tx min %d\n", (int)(header->x_min)); + printf("\tx max %d\n", (int)(header->x_max)); + printf("\ty min %d\n", (int)(header->y_min)); + printf("\ty max %d\n", (int)(header->y_max)); +} + +void +parse_glyf(char *start){ + char *cursor = start; + glyf_Glyph_Header *header = (glyf_Glyph_Header*)cursor; + cursor = (char*)(header + 1); + + byte_fix(header); + print(header); +} + +#define TTF_Tag(a,b,c,d) ((a) + ((b) << 8) + ((c) << 16) + ((d) << 24)) +#define TTF_Tag_cmap TTF_Tag('c', 'm', 'a', 'p') + +#define TTF_Tag_glyf TTF_Tag('g', 'l', 'y', 'f') +#define TTF_Tag_fpgm TTF_Tag('f', 'p', 'g', 'm') +#define TTF_Tag_prep TTF_Tag('p', 'r', 'e', 'p') +#define TTF_Tag_cvt TTF_Tag('c', 'v', 't', ' ') +#define TTF_Tag_maxp TTF_Tag('m', 'a', 'x', 'p') + + +int +main(){ + Data file; + char *filename; + + filename = "test.ttf"; + file = open_file(filename); + if (file.data == 0){ + printf("could not open %s\n", filename); + return (1); + } + + char *cursor; + Offset_Table *offset; + + cursor = file.data; + offset = (Offset_Table*)cursor; + cursor = (char*)(offset + 1); + + + Table_Directory_Entry *directory_entries = (Table_Directory_Entry*)cursor; + + byte_fix(offset); + print(offset); + + int table_number = offset->num_tables; + + Table_Directory_Entry *entry = directory_entries; + for (int i = 0; i < table_number; ++i, ++entry){ + printf("\n"); + byte_fix(entry); + print(entry); + + switch (entry->tag){ + case TTF_Tag_cmap: + parse_cmap(file.data + entry->offset); + break; + + case TTF_Tag_glyf: + parse_glyf(file.data + entry->offset); + break; + } + } + + return (0); +} + +// BOTTOM diff --git a/4ed_win32_keyboard.cpp b/4ed_win32_keyboard.cpp index fcd27375..ae1fd7b0 100644 --- a/4ed_win32_keyboard.cpp +++ b/4ed_win32_keyboard.cpp @@ -14,66 +14,19 @@ internal void keycode_init(Key_Codes *codes){ set_dynamic_key_names(codes); - - u16 code, loose; - for (u8 i = 0; i < 255; ++i){ - if ((i >= '0' && i <= '9') || - (i >= 'A' && i <= 'Z')){ - keycode_lookup_table[i] = i; - loose_keycode_lookup_table[i] = 0; - } - - else{ - loose = 0; - switch (i){ - case VK_SPACE: code = loose = ' '; break; - case VK_BACK: code = loose = codes->back; break; - case VK_OEM_MINUS: code = '-'; break; - case VK_OEM_PLUS: code = '='; break; - case VK_SUBTRACT: code = '-'; break; - case VK_ADD: code = '+'; break; - case VK_MULTIPLY: code = '*'; break; - case VK_DIVIDE: code = '/'; break; - - case VK_OEM_3: code = '`'; break; - case VK_OEM_5: code = '\\'; break; - case VK_OEM_4: code = '['; break; - case VK_OEM_6: code = ']'; break; - case VK_TAB: code = loose = '\t'; break; - case VK_RETURN: code = loose = '\n'; break; - case VK_OEM_7: code = '\''; break; - - case VK_OEM_1: code = ';'; break; - case VK_OEM_2: code = '/'; break; - case VK_OEM_PERIOD: code = '.'; break; - case VK_OEM_COMMA: code = ','; break; - - case VK_DELETE: code = loose = codes->del; break; - case VK_UP: code = loose = codes->up; break; - case VK_DOWN: code = loose = codes->down; break; - case VK_LEFT: code = loose = codes->left; break; - case VK_RIGHT: code = loose = codes->right; break; - - case VK_INSERT: code = loose = codes->insert; break; - case VK_HOME: code = loose = codes->home; break; - case VK_END: code = loose = codes->end; break; - case VK_PRIOR: code = loose = codes->page_up; break; - case VK_NEXT: code = loose = codes->page_down; break; - case VK_ESCAPE: code = loose = codes->esc; break; - - case VK_NUMPAD0: - case VK_NUMPAD1: case VK_NUMPAD2: case VK_NUMPAD3: - case VK_NUMPAD4: case VK_NUMPAD5: case VK_NUMPAD6: - case VK_NUMPAD7: case VK_NUMPAD8: case VK_NUMPAD9: - code = (i - VK_NUMPAD0) + '0'; break; - - default: code = 0; break; - } - - keycode_lookup_table[i] = code; - loose_keycode_lookup_table[i] = loose; - } - } + + keycode_lookup_table[VK_BACK] = codes->back; + keycode_lookup_table[VK_DELETE] = codes->del; + keycode_lookup_table[VK_UP] = codes->up; + keycode_lookup_table[VK_DOWN] = codes->down; + keycode_lookup_table[VK_LEFT] = codes->left; + keycode_lookup_table[VK_RIGHT] = codes->right; + keycode_lookup_table[VK_INSERT] = codes->insert; + keycode_lookup_table[VK_HOME] = codes->home; + keycode_lookup_table[VK_END] = codes->end; + keycode_lookup_table[VK_PRIOR] = codes->page_up; + keycode_lookup_table[VK_NEXT] = codes->page_down; + keycode_lookup_table[VK_ESCAPE] = codes->esc; } // BOTTOM diff --git a/buffer/4coder_buffer_abstract.cpp b/buffer/4coder_buffer_abstract.cpp index 998c50cd..cb6ee55f 100644 --- a/buffer/4coder_buffer_abstract.cpp +++ b/buffer/4coder_buffer_abstract.cpp @@ -494,59 +494,8 @@ typedef struct Buffer_Measure_Starts{ } Buffer_Measure_Starts; #endif -#if 0 internal_4tech int -buffer_measure_starts(Buffer_Measure_Starts *state, Buffer_Type *buffer){ - Buffer_Stringify_Type loop; - int *starts; - int max; - char *data; - int size, end; - int start, count, i; - int result; - - size = buffer_size(buffer); - starts = buffer->line_starts; - max = buffer->line_max; - - result = 1; - - i = state->i; - count = state->count; - start = state->start; - - for (loop = buffer_stringify_loop(buffer, i, size); - buffer_stringify_good(&loop); - buffer_stringify_next(&loop)){ - end = loop.size + loop.absolute_pos; - data = loop.data - loop.absolute_pos; - for (; i < end; ++i){ - if (data[i] == '\n'){ - if (count == max) goto buffer_measure_starts_end; - - starts[count++] = start; - start = i + 1; - } - } - } - - assert_4tech(i == size); - - if (count == max) goto buffer_measure_starts_end; - starts[count++] = start; - result = 0; - -buffer_measure_starts_end: - state->i = i; - state->count = count; - state->start = start; - - return(result); -} -#endif - -internal_4tech int -buffer_measure_starts_widths(Buffer_Measure_Starts *state, Buffer_Type *buffer, float *advance_data){ +buffer_measure_starts_widths_(Buffer_Measure_Starts *state, Buffer_Type *buffer, float *advance_data){ Buffer_Stringify_Type loop; int *start_ptr, *start_end; float *width_ptr; @@ -612,6 +561,80 @@ buffer_measure_starts_widths_end: return(result); } +internal_4tech int +buffer_measure_starts_zero_widths_(Buffer_Measure_Starts *state, Buffer_Type *buffer){ + Buffer_Stringify_Type loop; + int *start_ptr, *start_end; + float *width_ptr; + debug_4tech(int widths_max); + debug_4tech(int max); + char *data; + int size, end; + int start, i; + int result; + char ch; + + size = buffer_size(buffer); + + debug_4tech(max = buffer->line_max); + debug_4tech(widths_max = buffer->widths_max); + assert_4tech(max == widths_max); + + result = 1; + + i = state->i; + start = state->start; + + start_ptr = buffer->line_starts + state->count; + width_ptr = buffer->line_widths + state->count; + start_end = buffer->line_starts + buffer->line_max; + + for (loop = buffer_stringify_loop(buffer, i, size); + buffer_stringify_good(&loop); + buffer_stringify_next(&loop)){ + end = loop.size + loop.absolute_pos; + data = loop.data - loop.absolute_pos; + for (; i < end; ++i){ + ch = data[i]; + if (ch == '\n'){ + if (start_ptr == start_end) goto buffer_measure_starts_zero_widths_end; + + *width_ptr++ = 0; + *start_ptr++ = start; + start = i + 1; + } + } + } + + assert_4tech(i == size); + + if (start_ptr == start_end) goto buffer_measure_starts_zero_widths_end; + *start_ptr++ = start; + *width_ptr++ = 0; + result = 0; + +buffer_measure_starts_zero_widths_end: + state->i = i; + state->count = (int)(start_ptr - buffer->line_starts); + state->start = start; + + return(result); +} + +internal_4tech int +buffer_measure_starts_widths(Buffer_Measure_Starts *state, Buffer_Type *buffer, float *advance_data){ + int result; + + if (advance_data){ + result = buffer_measure_starts_widths_(state, buffer, advance_data); + } + else{ + result = buffer_measure_starts_zero_widths_(state, buffer); + } + + return(result); +} + internal_4tech void buffer_remeasure_starts(Buffer_Type *buffer, int line_start, int line_end, int line_shift, int text_shift){ Buffer_Stringify_Type loop; @@ -942,28 +965,33 @@ buffer_cursor_seek(Buffer_Type *buffer, Buffer_Seek seek, float max_width, Seek_State state; int xy_seek; - - size = buffer_size(buffer); - xy_seek = (seek.type == buffer_seek_wrapped_xy || seek.type == buffer_seek_unwrapped_xy); + state.cursor = cursor; - result = 1; - i = cursor.pos; - for (loop = buffer_stringify_loop(buffer, i, size); - buffer_stringify_good(&loop); - buffer_stringify_next(&loop)){ - end = loop.size + loop.absolute_pos; - data = loop.data - loop.absolute_pos; - for (; i < end; ++i){ - result = cursor_seek_step(&state, seek, xy_seek, max_width, - font_height, advance_data, size, data[i]); - if (!result) goto buffer_cursor_seek_end; + if (advance_data){ + + size = buffer_size(buffer); + xy_seek = (seek.type == buffer_seek_wrapped_xy || seek.type == buffer_seek_unwrapped_xy); + + result = 1; + i = cursor.pos; + for (loop = buffer_stringify_loop(buffer, i, size); + buffer_stringify_good(&loop); + buffer_stringify_next(&loop)){ + end = loop.size + loop.absolute_pos; + data = loop.data - loop.absolute_pos; + for (; i < end; ++i){ + result = cursor_seek_step(&state, seek, xy_seek, max_width, + font_height, advance_data, size, data[i]); + if (!result) goto buffer_cursor_seek_end; + } } - } - if (result){ - result = cursor_seek_step(&state, seek, xy_seek, max_width, - font_height, advance_data, size, 0); - assert_4tech(result == 0); + if (result){ + result = cursor_seek_step(&state, seek, xy_seek, max_width, + font_height, advance_data, size, 0); + assert_4tech(result == 0); + } + } buffer_cursor_seek_end: @@ -1110,7 +1138,7 @@ buffer_get_render_data(Buffer_Type *buffer, float *wraps, Buffer_Render_Item *it int i, item_i; float ch_width, ch_width_sub; char ch; - + size = buffer_size(buffer); shift_x = port_x - scroll_x; @@ -1131,84 +1159,94 @@ buffer_get_render_data(Buffer_Type *buffer, float *wraps, Buffer_Render_Item *it item_i = 0; item = items + item_i; - for (loop = buffer_stringify_loop(buffer, start_cursor.pos, size); - buffer_stringify_good(&loop); - buffer_stringify_next(&loop)){ + if (advance_data){ + for (loop = buffer_stringify_loop(buffer, start_cursor.pos, size); + buffer_stringify_good(&loop); + buffer_stringify_next(&loop)){ - end = loop.size + loop.absolute_pos; - data = loop.data - loop.absolute_pos; + end = loop.size + loop.absolute_pos; + data = loop.data - loop.absolute_pos; - for (i = loop.absolute_pos; i < end; ++i){ - ch = data[i]; - ch_width = measure_character(advance_data, ch); + for (i = loop.absolute_pos; i < end; ++i){ + ch = data[i]; + ch_width = measure_character(advance_data, ch); - if (ch_width + x > width + shift_x && wrapped){ - x = shift_x; - y += font_height; - } - if (y > height + shift_y) goto buffer_get_render_data_end; + if (ch_width + x > width + shift_x && wrapped){ + x = shift_x; + y += font_height; + } + if (y > height + shift_y) goto buffer_get_render_data_end; - switch (ch){ - case '\n': - write_render_item_inline(item, i, ' ', x, y, advance_data, font_height); - ++item_i; - ++item; + switch (ch){ + case '\n': + write_render_item_inline(item, i, ' ', x, y, advance_data, font_height); + ++item_i; + ++item; - x = shift_x; - y += font_height; - break; + x = shift_x; + y += font_height; + break; - case 0: - ch_width = write_render_item_inline(item, i, '\\', x, y, advance_data, font_height); - ++item_i; - ++item; - x += ch_width; + case 0: + ch_width = write_render_item_inline(item, i, '\\', x, y, advance_data, font_height); + ++item_i; + ++item; + x += ch_width; - ch_width = write_render_item_inline(item, i, '0', x, y, advance_data, font_height); - ++item_i; - ++item; - x += ch_width; - break; + ch_width = write_render_item_inline(item, i, '0', x, y, advance_data, font_height); + ++item_i; + ++item; + x += ch_width; + break; - case '\r': - ch_width = write_render_item_inline(item, i, '\\', x, y, advance_data, font_height); - ++item_i; - ++item; - x += ch_width; + case '\r': + ch_width = write_render_item_inline(item, i, '\\', x, y, advance_data, font_height); + ++item_i; + ++item; + x += ch_width; - ch_width = write_render_item_inline(item, i, 'r', x, y, advance_data, font_height); - ++item_i; - ++item; - x += ch_width; - break; + ch_width = write_render_item_inline(item, i, 'r', x, y, advance_data, font_height); + ++item_i; + ++item; + x += ch_width; + break; - case '\t': - ch_width_sub = write_render_item_inline(item, i, '\\', x, y, advance_data, font_height); - ++item_i; - ++item; + case '\t': + ch_width_sub = write_render_item_inline(item, i, '\\', x, y, advance_data, font_height); + ++item_i; + ++item; - write_render_item_inline(item, i, 't', x + ch_width_sub, y, advance_data, font_height); - ++item_i; - ++item; - x += ch_width; - break; + write_render_item_inline(item, i, 't', x + ch_width_sub, y, advance_data, font_height); + ++item_i; + ++item; + x += ch_width; + break; - default: - write_render_item(item, i, ch, x, y, ch_width, font_height); - ++item_i; - ++item; - x += ch_width; + default: + write_render_item(item, i, ch, x, y, ch_width, font_height); + ++item_i; + ++item; + x += ch_width; - break; + break; + } + if (y > height + shift_y) goto buffer_get_render_data_end; } - if (y > height + shift_y) goto buffer_get_render_data_end; } - } buffer_get_render_data_end: - if (y <= height + shift_y || item == items){ + if (y <= height + shift_y || item == items){ + ch = 0; + ch_width = measure_character(advance_data, ' '); + write_render_item(item, size, ch, x, y, ch_width, font_height); + ++item_i; + ++item; + x += ch_width; + } + } + else{ ch = 0; - ch_width = measure_character(advance_data, ' '); + ch_width = 0; write_render_item(item, size, ch, x, y, ch_width, font_height); ++item_i; ++item; diff --git a/build.bat b/build.bat new file mode 100644 index 00000000..8c2f1a31 --- /dev/null +++ b/build.bat @@ -0,0 +1,3 @@ +@echo off + +call "w:\4ed\code\buildsuper.bat" \ No newline at end of file diff --git a/buildsuper.bat b/buildsuper.bat new file mode 100644 index 00000000..5554d22f --- /dev/null +++ b/buildsuper.bat @@ -0,0 +1,17 @@ +@echo off + +REM this is here to prevent the spammation of PATH +IF NOT DEFINED clset (call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" x64) +SET clset=64 + +SET WARNINGS=/W4 /wd4310 /wd4100 /wd4201 /wd4505 /wd4996 /wd4127 /wd4510 /wd4512 /wd4610 /WX +SET STUFF=/GR- /nologo +SET DEBUG=/Zi +SET EXPORTS=/EXPORT:get_bindings /EXPORT:set_extra_font + +cl %WARNINGS% %STUFF% %DEBUG% 4coder_custom.cpp /Fe4coder_custom /LD /link /INCREMENTAL:NO /OPT:REF %EXPORTS% + +REM more spammation preventation +del *.exp +del *.obj +del *.lib \ No newline at end of file diff --git a/temp.cpp b/temp.cpp deleted file mode 100644 index 5b8ab654..00000000 --- a/temp.cpp +++ /dev/null @@ -1,22 +0,0 @@ -/* - * YOUR INFO HERE! - */ - -// a b c d e f g - -#define swap(a,b) {auto t=a; a=b; b=t;} - -struct Thing{ - int x, y, z; -}; - -struct Stuff{ - Thing x; - int a, b, c; -}; - -void insert_sort(int *items, int size){ - -} - - diff --git a/test/experiment.cpp b/test/experiment.cpp index f70a3d47..eaccba09 100644 --- a/test/experiment.cpp +++ b/test/experiment.cpp @@ -1,7 +1,7 @@ /* * Mr. 4th Dimention - Allen Webster * - * 1.21.2015 + * 21.1.2015 * * Test for CPP lexer & parser layer for project codename "4ed" * @@ -11,6 +11,8 @@ #include "../4ed_meta.h" +#define Debug(x) x + #include "../4cpp_types.h" #define FCPP_STRING_IMPLEMENTATION #include "../4cpp_string.h" @@ -22,8 +24,6 @@ #include #include -#define FCPP_PREPROCESSOR_DBG_LEVEL 1 - internal bool system_is_absoute_path(char *path){ bool is_absolute = 0; @@ -72,7 +72,32 @@ quickie_file(String filename){ return quickie_file(buffer); } -#define STRICT_MEM_TEST 1 +internal void +preproc_init(Cpp_PP_State *state, Cpp_PP_Definitions *definitions){ + *state = {}; + state->max = (32 << 10); + state->base = (byte*)malloc(state->max); + memset(state->base, 0, state->max); + + *definitions = {}; + definitions->max = 128 << 10; + definitions->items = (byte*)malloc(definitions->max); + memset(definitions->items, 0, definitions->max); + + definitions->table.count = 0; + definitions->table.max = 4 << 10; + definitions->table.entries = (Cpp_PP_Table_Entry*) + malloc(definitions->table.max*sizeof(Cpp_PP_Table_Entry)); + memset(definitions->table.entries, 0, definitions->table.max*sizeof(Cpp_PP_Table_Entry)); + + int str_size = 16 << 10; + int token_size = 16 << 10; + void *str_mem = malloc(str_size); + void *token_mem = malloc(token_size); + cpp_preproc_set_spare_space(definitions, + str_size, str_mem, + token_size, token_mem); +} int main(int argc, char **argv){ if (argc < 2){ @@ -83,169 +108,48 @@ int main(int argc, char **argv){ Cpp_File target_file; target_file = quickie_file(TEST_FILE); - + if (target_file.data == 0){ printf("could not open file %s\n", TEST_FILE); - exit(1); + return 1; } Cpp_Token_Stack target_tokens = {}; cpp_lex_file(target_file, &target_tokens); + + Cpp_PP_State state = {}; + Cpp_PP_Definitions definitions = {}; + + preproc_init(&state, &definitions); - Cpp_Parse_Context context = {}; - Cpp_Parse_Definitions definitions = {}; - Cpp_Preproc_State state = {}; + cpp_preproc_target(&state, &definitions, target_file, target_tokens); - context.preserve_chunk_size = (200 << 10); - - definitions.table.size = 0; -#if STRICT_MEM_TEST - definitions.table.max_size = 16; -#else - definitions.table.max_size = 100; -#endif - definitions.table.table = (Table_Entry*)malloc(sizeof(Table_Entry)*definitions.table.max_size); - memset(definitions.table.table, 0, sizeof(Table_Entry)*definitions.table.max_size); - - definitions.count = 0; -#if STRICT_MEM_TEST - definitions.max = 16; -#else - definitions.max = 100; -#endif - definitions.slots = (Cpp_Def_Slot*)malloc(sizeof(Cpp_Def_Slot)*definitions.max); - - { - String string_filename = make_lit_string("~ string space"); - Cpp_File string_file; -#if STRICT_MEM_TEST - string_file.size = 100; -#else - string_file.size = (128 << 10); -#endif - string_file.data = (char*)malloc(string_file.size); - Cpp_Token_Stack string_tokens; - string_tokens.count = 0; -#if STRICT_MEM_TEST - string_tokens.max_count = 2; -#else - string_tokens.max_count = (128 << 10)/sizeof(Cpp_Token); -#endif - string_tokens.tokens = (Cpp_Token*)malloc(sizeof(Cpp_Token)*string_tokens.max_count); + for (Cpp_PP_Step step = {}; + step.finished == 0;){ + step = cpp_preproc_step_nonalloc(&state, &definitions); - Cpp_File_Data string_parse_file; - string_parse_file.file = string_file; - string_parse_file.tokens = string_tokens; - string_parse_file.filename = string_filename; - - int string_index = cpp_defs_add(&definitions, {}, CPP_DEFTYPE_FILE); - cpp_set_parse_file(&definitions, string_index, string_parse_file); - - definitions.string_file_index = string_index; - definitions.string_write_pos = 0; - - { - Cpp_Token eof_token = {}; - eof_token.type = CPP_TOKEN_EOF; - definitions.eof_token = cpp__preserve_token(&definitions, eof_token); + if (step.error_code){ + printf("error: %s\n", cpp_preproc_error_str(step.error_code)); + if (cpp_preproc_recommend_termination(step.error_code)){ + return 1; + } + } + + if (step.mem_size != 0){ + void *memory = malloc(step.mem_size); + memory = cpp_preproc_provide_memory(&state, &definitions, + step.mem_type, step.mem_size, memory); + free(memory); } - { - String string_va_args = make_lit_string("__VA_ARGS__"); - Cpp_Token va_args_token; - va_args_token.type = CPP_TOKEN_IDENTIFIER; - va_args_token.start = definitions.string_write_pos; - va_args_token.size = string_va_args.size; - cpp__preserve_string(&definitions, string_va_args); - definitions.va_args_token = cpp__preserve_token(&definitions, va_args_token); + if (step.emit){ + Cpp_File file = *cpp_preproc_get_file(&definitions, step.file_index); + Cpp_Token token = *cpp_preproc_get_token(&definitions, step.file_index, step.token_index); + + printf("TOKEN: %.*s\n", token.size, file.data + token.start); } } - state.tokens.count = 0; -#if STRICT_MEM_TEST - state.tokens.max = 5; -#else - state.tokens.max = 100; -#endif - state.tokens.tokens = (Cpp_Loose_Token*)malloc(sizeof(Cpp_Loose_Token)*state.tokens.max); - - state.spare_string_write_pos = 0; -#if STRICT_MEM_TEST - state.spare_string_size = 1; -#else - state.spare_string_size = (10 << 10); -#endif - state.spare_string = (char*)malloc(state.spare_string_size); - - String target_filename = make_lit_string(TEST_FILE); - cpp_set_target(&state, &definitions, target_file, target_tokens, target_filename); - - while (!state.finished){ - Cpp_Preproc_Result result; - result = cpp_preproc_step_nonalloc(&state, &definitions, &context); - - if (result.memory_request){ - Cpp_Memory_Request request = cpp_get_memory_request(&state, &definitions, result); - void *memory = malloc(request.size); - void *old_memory = cpp_provide_memory(request, memory); - free(old_memory); - } - - if (result.file_request){ - Cpp_File_Request request = cpp_get_file_request(&state, result); - for (; cpp_has_more_files(&request); cpp_get_next_file(&request)){ - if (!cpp_try_reuse_file(&request)){ - Cpp_File new_file = quickie_file(request.filename); - if (new_file.data == 0){ - printf("could not open file %s\n", request.filename); - exit(1); - } - Cpp_Token_Stack new_tokens = {}; - cpp_lex_file(new_file, &new_tokens); - cpp_provide_file(&request, new_file, new_tokens); - } - } - } - - if (result.error_code){ - String error_message = cpp_get_error(result.error_code); - Cpp_File_Data file = *cpp_get_parse_file(&definitions, result.file_index); - Cpp_Token token = file.tokens.tokens[result.token_index]; - bool terminate = cpp_recommend_termination(result.error_code); - - if (terminate){ - printf("FATAL "); - } - - printf("ERROR IN %.*s AT %.*s\n%.*s\n", - file.filename.size, file.filename.str, - token.size, file.file.data + token.start, - error_message.size, error_message.str); - - if (terminate){ - break; - } - } - - if (result.emit){ - Cpp_File_Data file = *cpp_get_parse_file(&definitions, result.file_index); - Cpp_Token token = file.tokens.tokens[result.token_index]; - - if (result.from_macro){ - Cpp_File_Data file = *cpp_get_parse_file(&definitions, result.invoking_file_index); - Cpp_Token token = file.tokens.tokens[result.invoking_token_index]; - - printf("EXPANDING %.*s => ", token.size, file.file.data + token.start); - } - - printf("TOKEN %.*s\n", token.size, file.file.data + token.start); - } - } - - assert(state.finished == 0 || state.expansion_level == 0); - assert(state.finished == 0 || state.param_info_used == 0); - assert(state.finished == 0 || state.state == 0); - return 0; } diff --git a/vc120.pdb b/vc120.pdb new file mode 100644 index 0000000000000000000000000000000000000000..01fe61a0f0c67310204dfa282f5b865b3d5e4d9c GIT binary patch literal 94208 zcmeHw37lL-wfDLAPLcrvnFJET7Kb1q2_{Tp2oNAlRtQ-LkOag?)6;V&)263;=^W|9@4T?%O?`Au*`Hulo0^ zzW1C{%c)bRs_v~i_tesCrdTKyy2`Ed4w`r1fvrnVT-bWZ)V8*rcieOSiGp8?NPx@k z2rCHVH^yH4zn6fQfR})mfR})mfR})mfS14bO_m{}MK&4RDT6kDsa$7vU8*co zkD9a6-M6>Pc!@^sJUTLEh@9S6C`-S>O;U_|WOG0BLuTO+P|{Oy?FuLb;VDNp5*c`#76J2)PP;|kff z^a3BC{2d|DU4R=7NYjk~yq` zkSX!I17^NjHer!S#=5kp1Jbm6y0psEUVt?nujFZO;F5HvCr^w^`nWne@kx3s;KsUk zV!4>juQ94-Z%tcjS>utecc{&)jYXlX{eYY0bdfZXQn?8EQx{q1W+`RQh^=lC9xgp` zPocOmWzbefA)|1AA3;vlnS}Na$GVh zUxA?Yl=ot!v+|BclW&%_31y9Q`o0u6k+i6;Z<0)*FOQMhjcdycopD4ikV@_i%c2Ze z7RzP6Nu6PxwC&nVZlRojI69Zq$}f-=ps9S9;9lEJ)2;%pasQvcF`w?qW(TBDhysDnDb;o6UD(&`Pb$XYC}JM40i5d8~GMoPoN87@I`;5I@x&r#oYgSHuMt*OTr| zb;N73d3o02LyPaQ1&N6pSzIQa%XOqPYlZ2XEH0bxj*H;M#2aF9-G#zhjFZDgLp&kn zcq;fwGMZXJv0{!tX~qCFD$#$Ysrv#LGF`%S(sVs78D! z>7UMnYH%YaDzw45IAeR|z~0fQe1jjn>&5uQXMZMhF#03Mv~HBcaq%1{gLjy6GkwKUp~$g|btaBubh=nJ^(EXQalX^l ziSXDuIT6JJCRm@ZKm#n*MVi( zc`q14xvF=m(I zVv0&(C+`HU+0~6>ZzRoO3Hj=8cul(|2isSF?A5tEi}E>-@mYy-gSe#+SIUCAt@U5; z?kCsOA63kDR@$>ksN2;#b9@g`$BiamTg&Ecsbi&EHR{M!;^4h`(7v!DU0f4ar}&hG z(HADTdX6+~X9}I}`J~lIsHf1G?aIc*lF?CgvhZDrIyPAyZJ75^=}i|?nOqiP>gh?F zKEru_SOs5L7Z-C-o%PvrHzMV`a@kDTJPS0NI2@0vGM%6Bl<#R%wU=wP`@>C3XIrshPWLq&M?EVhq#?2E@cph z&&0#Q>T$M_K%u@ajyI;}p}p+$cLjn7mOKyL{$eCQx;&6CHU%>Di9r7Ti9jZ8z<4%C z9p$}c8IQoJ&d)XxL?)SEZcv1~{wQ+%@<8S{MY1@I(W6ZKhjgviEEVx{QAq5NP+$nvF7u6chXhovLA@>-DvmxgloosrC&C-T?d zhjRZnBl*+Kp`7!vK+f#OTE$C&{GmtW$Ge6yA_(P?&j<3pUqo{8Eb`d*BRTIT zk@-hrK7lNry-H-m3XvCnA4%!6q4c614u3S1M=uEEir)wFQONFN%_3h#n_YdK$N?_~ za(N5ZTiz~m<-$P5{4tbb7v$I;$jy+`?fFR7Wc>81|m%k;FX-|amqr*eFJ&vU1H+YZuk;q<)A;&499J~?h zG*4rWSrf`_$n)3jk!;v2lAiw%X}>0vGwu+%?WsTxxh;|x(KeqyHyqAr2JGQcS2{;sPYK(s3Uaw#^ykN zhPr?C8zO%g63N})4y5z;Q2syay7ux=?wA_LyIKP|?=ztsccI8j^F#T|Q6e`!AySwU z$;%%P?67Ul667Ul667Ul667Uju{Yc=l zsndcHy%((dI#?cc*Xa-Z=K5zB-f`8&&X4_h+#Ec%%RyXiFW~{2ui$(ww^v-uZ-~3j zxp;aYAGu8=cULG^?k4ibzlZXN_XKj+4R|g;3VUVOM)K2KC_5a3cdQ?U@`Yyt*=blH zcjiT|`cIMk$#}lM8}D7XUo$$8%m?s}f_JUC^FrAb@0-V*AIRJOCz8`A2J+o;STl?9 z&imhyOvZch+3lfR^nU|s-4MtQ-w0(q-XBI@5J@~DlqGmqoIXF0@c#1N z4@RBjrPsp~^|YBS0ofp;s!oAh`nv+@4((35zl{!1vQ z+#1TmcwfKc=b_B)4CR5vp&Wy{JU9{o?`<1?DRT7{BJVyH<)f@aQ2v)6j${JfSFXW( z;7(`Y9sN@x@A!oH_kaKX@8ADlXYc>-TouVP2ZUzL;KNv3;QCGdn!qxw|BY>TBcs1~ z33v&333v&333v&333v&33A~0RfbB`+*MBjt@0w#7yBB-F*anl;c)R~C3{pnpo-g{? zvW1-u_rj``N ze{cV`~RffzPJCUP2Dcy?f>-~2UyC`P(As5 zkGKE#_W$^n;uUOQt0tfgK0&AwU&%hy+y7TSc7c`T=Kk&e20_i)8=37^XoI(kxBvI{ z|K9%ppZD#RKFfRi|9`dpzsSye<9z|)nrA|DzY6zfZwMugYZt;Ygpb~*-@PxC-7kvd`lDfwyF(zid>VEFUxEE} zQRLdsMe@`|p`7(q*udWr$oHoqzwbrzFzl`8{|dI$u-pF3^`YDeJM=?f2mQCBBAImn zYye=N`>p3h;!G%$Zw};ui?KHcTj7URhVp5Y_0CE7F80Ytmctf&=DT5&09%7|VaIzb z7Br&I!k!uX_jA4+%B5$aPOwkzI}LmLXNIy7`}dC(0-60nD3>Gt87D?^(br&Ce|aRU z_le}Krv=gtJBFLEDDvxR`2Oe?*xAEw;KhZZEPEg9?yn4F;Q@g>02w@ta68_(eu3*P zFGh0ErvlkyLLiR-9(8FT$HCVB=C_GF2)pgy0QWe;PWxa>5n)$^JrG(E#v$yFFdTvS zkqCPt?1L~7VHxV2jsuy1`|;1i?g7`m=A+EkNRGw*Lx)2SjE8V7-VYbxK*zbT-Mw4T6I9%{uSFDbzr?&XV#NEkstEG@{@Y?YUHW) zT7kT&yL|%B>7*N;Qfhb@vXy8B3aZONCDqr{0TPfUtA+{!diSg zf%d=lA*`n%e(CQb-?}D{(I168X9V*0Rk)rP$i-g}*tr0H1v%V@?*l#!JNME;C=c4p z|GWge1iS>i1iS>i1iS>i1iS>i1iS>cR{~|Mu+p~zeSxTNg)`m#?5*@Up!+6G@C{{r z2&CYI0pIs?-IhKjHYMI)w#naub4}7{*;Yw|uiDx@a{4sUx}8(0TO&V&b9#H>-5_1g z7V@bj+5B4PGpio!WOlC0OV_TVp(5u2N8c5+hv26Y=L4pE-|OPe+yZqCy*7nyd$TvipVBFC0vrr4@m7{y&DdP~ML#{h$#}`a0p- z9&y}*uF5Eq{{&9=t2GYGNyfPt@EG_Sq|FKAXt}j{HOZx0h*z6m6TZW@?Lyx;sv946 z_oG}J*}Zb?+d!SUClf%IuS6XES-%?UmuoBbhScd&gC^kakdg;)1*_Ba$)kK_3Vh&cSTZ{xR*gcDAy$FvQ4^Vd=@pRguxHaeX_6Awp}RKfgkGF^{zgu6YN*? zkH(PHiI2GWH@f(w(Vq_co#u6uqp3|2^Qz_%$j4nCH@kSVAR8IrpLA|tR~J0!oY;rq zt+>(DycT8lshIC4kq@ZFd3^G z4qQ1`d>*v61g$$=N_Ay(vGVdo&<{<}Go8{u8|?zyv+x$s^w%!iHeR#-w$E5!k=h2- zE4JBJaHZTS3p>U&8^3(iC;CVwjrG!gN15wA<;43R)QlahRkaVYyrw!|p%~v8hhNzl z4}&_F4i_uTD#f-TeMPlY(-?UYH#QmHwH?cAwQ;S(tW{3i0(AN*ZyRbQa2s2^57f$10O|CRg_uYH0rc~w8AwhzMx2k<)PYaG3@ zPqZ1Pn&i8PNBb4^m5Di`U(<0uW}i3tBYw5-H_2U~?TI;swvEYn$ujIbK1BXsT^TTu zgg?$`bT88GM?L}zD-XLky24S^E) z`8FFrY0Srtdx3%L=U&R7b{>Qe8RV&BGUrvssmdsnp9803C+SsMAP)g<>~pl@<;V<` z705j|{SxU|k9%BS*_R?n_O!$8yJiN~T z6LGsF{67&+`ivtys?Prtal6&|e{Rsh?w!pZYMq+wfNzcgz^_JK};amJ`&pB1&U>f@4W`CeO_R^J?LI?_>sb9-y~>>QA$@`7ag z1?k9H-Qt?M#RJk%#9j#=m9_YTdL{I#;Fw%+ZLZ12@384@ll#SArRL=2rADo?9s3 zaS^`ytPaMD^5u99o-_>{O1v;vNE<(Vq~k03`Gvj?Jp66$zXUqignmLDq<^ita<;Z6 zvt}91cAkdqefvLJGaZNi41PFK@ZLR{BSx zu73mEfDfZ1jB8`tcEza&;on_;q%{4b(%8;+wLY2u5gqF*!Fgh>dex$~PP0NC-{Lv> zjVqa_@jV$xJg+b>moAm6IOx{ARh)283kGrz@ctv_m zeHye64o~RIlr6!u8PlMRmJ~27*T+ZuEH7dfES8-DCCWkjELa!kT~<}T&^9aLp59!# zT&qVc2ehP6D&dhu%fKl&20EaZoAeJDE2|M&nE0`XL?_Ho3e=*}Ac>wsL0Jt3_>9eNV-+nhaR~8PEc7 zxQk9vtp}gP>u?RGNwoPXZk~iE%N+gFQb*7?HgNvqJv@oV#dXWwpW@5{A3 z8-Kyc3o7wXTyVmwMe_)EL2rgSy%`4iy%N_AC(2i@MgLs9GxM9jW|YBqWeuFS+Yt2q zxgM`H;;BnRkv^$Qgm*-caD?o@D}JhfEKBFyYP>*(yLdyv6XOqzgLexTXHOYw&Z^l7 zFyAM3cGnTOcDUzSmZNj_2((8F;5w0*`I_-`zUJBq>(ne<#<9%%&^8)p ztn~F^QMR()(ki)(!j#XOv4@f`7YpjUnE6Z;K7-*MgXh*jhjgu`ErDmMc!OPEW12$~ zG-{fb-)`_`wXKrRF$SkO*!;=M66wx%cH-CzS0-^wajp?L$&{gv4$tzIOQx?>F7zaE zCo^uLub8pxTf)AzE1qjc8rdN;{7!pCEj2y4t_d3Vt#@u+-;Fumrz~T&J-8vIaamI< z&%1eS7p*gEm+YJH90eh0KZQeWJg~6e7ST7k7sfua8|puxZ#FEuVGnH>vjLa=dscYF z2m&rFfA)R;4DiEuQt~rq8~7>oma{!L?MSDVD%`%+d}*H^jdD2-?22o093Z?00_T*m zyyB<*x=O3|>rt*>?}@nV*L&f5rkjIUhW2O9NxK8C@+|!$AcehwYskFox6C8i*O^CC zB^TS5**BW8=9DQE@yH)$2-Zw0}q24!)*?>!|mD=_F zeNi6u>rJ>O^^5R+2-L6fyyB<&RizEouQwwu^=p4z`MyhiVi~Gm)TIf48#3y2iSbpJ z*ltbGkpm2l_=e9qjkDtuM?*>jiJ%?w+cGv{(rQD+#0t0 z)|XsaW1kF}vQM)8C*eNX{)FE`nTMeq$SZ!TGfbztP>lya<}ThqT2)W<`CFb^5~mtNH@J?SQvXJu_!BzUm9-aMr0wa_NnQzH+KF#?l@pXqG z?iUh{q^lTX%;kNPf#Jsle$RwPy~)ehwzG@>R6Rl)iIsx4nth(*eqOiEMgfIuD~+Kqr;Q9 z3a56?Vtjq?VtaBdI>O+HZ#WiJvae=E)ftFxB#SZ4x|Wma>CASf@_l$P#n@z@ODxWw zz?135{xlvj?feporIq4%ZEAftj_4`%VtprNcYO4{sc{^0N{A~1_DQDP`h2j{WOx{| z1-d!x!{sqF8K+!Wi=}l_1nV$tAkDJq(l#gQrXHz65vL7RGI8;C7$jb@&O0XKrE|UA zX{@B+ShkF1$<%45Eyl4qk?-MKj05&Ec%{iz>$vkP$E~UJE|vJ{Vg~(?<&AK-VhL6S zKoZyDaBB+XLMn%KANLGBvXZ`x1B{AmRbNIqe5TO5QE|H}uFsAWyE(WwUBV-o)sxXl zTq@63Cd1PhhsUWgSRqRl(|Ig3y7t)J(eUIOleJVSQ|#-o>0ldSbgD1kS5^7-5o6h4@AL`5gjnd_%fIC#Yki#c-PjqjTal#CaCEalX__{*t^@Sq{g3V`dx2 z)8WZHFmbRRMF{R0fp(+{U3O@5Hl%WF^K z66MWtcq7kDA;-yOeVksadv9|c-O8&cn@5CoS#)g2&pf4@)Ah`7n<}lZ>ihg;{&*Ve zb23@r@Fm!IA(T-G^X^Ap7dl!;UpA-fmq%+k<|J93n>B3oF?a&vTEuKTf6Q}M#Jc@l zg|XELUT=5Lg*f#UR%v$4jb#M}hCveskyNI)*J_$=3!Kh`xa_^IqqsUp2EP_(bYV{! z3vtY+$>4CDAdS`%W>_kxA%@N~(|XfZc69xZRb=qm(c4WQfjth-*xD7}d*f`bv3G_t_GytP zKN!dp^CJ1mZSbl8b)30&4Ses9g+KpvAa~=N_s1`UjoPJ=d~YV+XBI&2Zx6lyfA9a_ zpa192|9eB9|L6Vxn+eYUc?oz4cnNq3cnNq3cnNq3yiO&s(+{Qvhmv>La2?OJpgH`u z>gAXDo%PEvbB7T)EN(F18zOTi0CBpnNuxV{yJL*+umZx%V1(yO?sM=hyU!d$%emj`7p$xaOZRrI~zoq2&h5V*Uzu}`T-hQC7O?c&6 zR10uPI@hR3XI#?xZEKQFe3HH!V6>_E-a*S916=Z3uH6AMUoD$3cc{m@w5J2ow0pX= zTIODWHJ$RjH*iTh(~~F0CC}sP=)@=Kt$-&tv{8WRI2Ndljg`Hvk^6Y0(BfQX-DY1BEg!>txp_BRMb;hcx2r<4iGWte*$vr<#ZTW|1}xOqbNb zX@E7aHdEnHrYG_uo%tnYtlza0Z}U=Kt^8FNlvk$ZJ=^C{Ty@ORa&0{WnFU%>Uc@t0 z(_{Z8kzV=I^s|#Rm#!CAYI8ei)qHGO>?h=bx~@DkFV;C(-}w&Kax|~Dn!KyuG-C{@ zi~b9$glCYxN|y6g&e;GGb&$!p!ICK#Yku6?fw62e};6u|9|X@MELd~iydA4 z(9!OV8JvD(Y4*N`*m&jx$645qfqI(#m{Xx!$!``D8%zVxP{)4zt=R=o_2e%ZweIWK zB$)gJl_p8GAAQ;nQD+bCo8){mUu;MD*q%z6ecVPKi>k!Ix!CN!>)cL0)R~Ow^|itv zCrW-LUe4KGnRM8XRvSq~N&j>nRD&BaQK1da1%2kgd%||;ruiJWfo2jvc-a?X-;iTd z3jHZLHk}5z8Q*TCJF&x$eN)Ea_tVXZ@283DsNl5Q+PM7oxjFIeGvo5xX4t7|mp6Ix z`(>14zF(dRIpAFIunRc-jjieBM&Xj37F~Pu7JL~nTIv|{eR3t4gOQ5!Q#Z=t{B(|! z!8=U3&d9{onK*v)4;xWqGfOz>%YpFNIyn&s-!;VoY&ckN&ZiT_S|64RWn(|8__s)0 zEEbC5{r`La|F6dQ-q^2)=?g22(Mh#0SQvdleS6^*9X}di*!PWAK(Li4bn*kiV#(+z z2C48}&~N=&KV_+gdHenUP~NszAo=^@p@BjP#f4~3l_x~|Sk8Rh{*I&H^ zyac=iyac=iyac=iyac=iUON)-`~Pfr1AclZqJ)V83oLm=6JUz$$ff})BE7w z+N_rnhCkYveqj9mzqK9k`~MR9{eNpq;P?MS@%#U3cTlx2QQM6+GoFTW0>)&u>!`J# z2xJ9lYG1Jg_iDGHX;%T)*#5_T+h~S!caPD0nH$TkJ%-=^=U%_x|ED4*w=$Ck2kAAl zlOXL6s$2X1K(EJUg=!UGe%Y;&{mQ*8hkhF!sp@e=Y6*$VTh>h_daj>;fA3Ej_4u06tpLXz#4(@mGM;-jEgD-XP^A4Wt z$~y{sXyoT`N1x;1_d0l^CAbU zJdbeYsXSrIVA@aRdA5U9o|idz0pv*;?BQUQ?=+X+qB{CQ?qcLuga<)@ZChHM1t<&1fby}OfPH&rL;Dg%^HrK-rn`!CO53zU`|KMrU4Lpy(9YqTJOpSUNn)8As8rQy$;~=gnFT2mNbsBwg!5oQ76v zow(u9nUhv8&1Q;)QlYEdx++`hOXpfoEcbP03$4?pPiNeH`-_U9oJ^Z>-N<9U(#?}X!|)UmMmSk zRVv_`4>BHu_UCtPn;`I%Rd{OmL?< zb3X1LMA+Q_S8c-qn)&bJ`(L6HsQY-dCG3y~wB;`#8Esqk?S}wwkB)2KZrlzJn|5H| zTJFYVoxgRCx)MB+u5;7`H%I6kb*O`Nj?y_x=O`WXb&k^K5uKyvyYxCo=^UqX)FMaM zIchft>m2n9$Di_#vjz>nI%nPIV4bt{c}nLjor87G`VSXh=PZ4`(&vxqj;?dqnGV)D z>=Fm-9Ci@+os71I|ExjVn*Eq<{}|f*IktJ@DPx<5jn~hZK#6bePvhU)|9ks?{T_tt z**HT6hsw~oUG-g9-;w?M|G$2H_qFu?|KE6N+IerhCm>w&Ola;`;r{Fmp`>x`LRf}y zGG1Iyz%_+Hd^f`T5iUl!0pTWu>)iE+xZZ>Cz=yG3vnZ5rA20IV`$F0MqDZbkTIAUs z0=ebWpi`=dPgANpN9Ot7sz$MEUF?&QEZ;GZ zneP_)V_xLk%L2J|G~QJ|EAlAp_vd^$luOS-oh}Nb?=;xGt z87D?^(bwQ#^zukn?*qTKrv=h|OdvPGC&I7c3-KMdhG0QWe;PWxc|Lf92y z4}?~PaR~b(3`Zb-B*LBu`yfn2ScW>M<3J|he*E*HEWvfJ`6#nBl4EiI(BY5+<00_b zV8QO#*_a&3)!_H|JkGw(g>vDHP#%Q*E_n~+hHn~DDcjbn1KRel*zTwU>&-f|p5%%A zkPnuh)T>t`Pp#Jq~m;3eQC;3eQC;3eQC;3eQC;3eQCpb|*h|G$X$g)8#mg8x?7j2Y@wCP zI5VeXYPVT)=Keh2S(f9%HS?Vuyb|zuSKj*SKBn#`!WkPJy16_iAPx7S$GbdqulWk_ zJxCsQPtxU~Yxmc?Jap}Tid#F^wR^6`50WPj?Tw2r&$ZxbM+7Vxn7ZkDzwSBfdcUsc zzuU#fE4YcT>;GzRpzHr?U!d#%3mlKS{=eM8y8aJW2PQvV|9{lwul5J@<4D=-`afQ0 z2kz(R3pnV-Z0J|^Cg*@(v)7L!gv?<_Sc`_=HM948B4|Bn9L$6EM9uRk#w!=C`#!U8Z0qr6;I$qaccS8O77X0aV2{zpoxBBnMHY4O--7r!?jGlS zS*A6gsdf1AF8{jtDV!1>=Sx|06tTvsOIs61^Iw4cahMEFp`!$)(w+-}?~XTUlbZ8p zv`yMT1R~Bw|AYY|b(rtle^(Cdb zR?=1V#t4 zx^x~#uBB5buT;mc^GIcQ(|T}sn`cQGk5dW#(0U|muev_aZlWq5jq?NKTWecUjiYTv ziwqN|GmEond30X2Prny5oD^goO(ppH4)8oG3Wo`@51RAdwJvvp#<4`l4V8_{i*shp znOVvQ>E;}-Y(9kpOyS_G+D|GpFk>cN(6o-ESv!z=BaqtkHjX=h5p_xOWpyu&hO3+i zSLsjx?dr-l&~v_2FCMjZWz$u3|0&|EY>Mer7fz|K>V5!PF5O|y3e!AB+dO(ZaMUB` zA>DWWh?|#m-}y$snr3I_Lx;MM1JgVUn9ma2OV&8ejKe4iedlum)DjF-`@pWip}lY{ zWzm%XJYeQU+b_*)U%=}#CBtJK&Wxdody|c4@|xS=`K1@OB{2s5xU)5L;DN2_GRB4u zdg^SQh(qLip&G?jj3aR|pUzEkb^9~&>_A96dHj!qPjj%q4uN!Rbr}AKI5_9vW(V(s z9_QfCJDBHLlfK%epXgv52W8Up{9@9-#AYHSM+!@<#ib@+bqfO`t8uga++cW7jqn2hX{-QX5J>1Ti1AX_%R)o6`})quS~v zo^dPB+5e!4+}uUWR;PP9XUH0?dSOj=OWlS z>lEB^p1Hw|6)6W#b>re12e&&|-yi2W_zXwa_rJ3ptTxR0zNj|KS2?=h|M&avI*vk8de5y#K>c}DDHPd*ad;{>5G+qV(|$W zKR1&R2#6;1ee2f%AO!#O67Ul667Ul667Ul667Ul667Ul667Ul65_pYC0Iu-;&r85d hz)QeOz)QeOz)QeOz)QeOz)QeOz)QeO;0-Q;{{``(RUZHV literal 0 HcmV?d00001 diff --git a/win32_4ed.cpp b/win32_4ed.cpp index 68ae375c..9859ed12 100644 --- a/win32_4ed.cpp +++ b/win32_4ed.cpp @@ -11,16 +11,13 @@ #include "4ed_config.h" -#define FPS 30 -#define frame_useconds (1000000 / FPS) - #include "4ed_meta.h" #define FCPP_FORBID_MALLOC #include "4cpp_types.h" #define FCPP_STRING_IMPLEMENTATION -#include "4cpp_string.h" +#include "4coder_string.h" #include "4ed_mem.cpp" #include "4ed_math.cpp" @@ -35,30 +32,15 @@ #include #include "4ed_dll_reader.cpp" -#include "4ed_rendering.cpp" #include "4ed_internal.h" #include "4ed_win32_keyboard.cpp" -struct Full_Job_Data{ - Job_Data job; - - u32 job_memory_index; - u32 running_thread; - bool32 finished; - u32 id; -}; - -struct Work_Queue{ - u32 volatile write_position; - u32 volatile read_position; - Full_Job_Data jobs[256]; - - HANDLE semaphore; -}; +#define FPS 30 +#define frame_useconds (1000000 / FPS) struct Thread_Context{ u32 job_id; - bool32 running; + b32 running; Work_Queue *queue; u32 id; @@ -71,7 +53,8 @@ struct Thread_Group{ i32 count; }; -#define UseWinDll 0 +#define UseWinDll 1 +#define UseThreadMemory 1 struct Win32_Vars{ HWND window_handle; @@ -80,8 +63,6 @@ struct Win32_Vars{ Render_Target target; - u32 volatile force_redraw; - Mouse_State mouse; b32 focus; b32 keep_playing; @@ -97,13 +78,16 @@ struct Win32_Vars{ Thread_Context main_thread; Thread_Group groups[THREAD_GROUP_COUNT]; - Work_Queue queues[THREAD_GROUP_COUNT]; HANDLE locks[LOCK_COUNT]; HANDLE DEBUG_sysmem_lock; - Thread_Memory *thread_memory; - i64 performance_frequency; - i64 start_pcount; +#if UseThreadMemory + Thread_Memory *thread_memory; +#endif + + u64 performance_frequency; + u64 start_pcount; + u64 start_time; HMODULE custom; #if UseWinDll @@ -122,7 +106,8 @@ struct Win32_Vars{ }; globalvar Win32_Vars win32vars; -globalvar Application_Memory win32memory; +globalvar Application_Memory memory_vars; +globalvar Exchange exchange_vars; #if FRED_INTERNAL internal Bubble* @@ -138,7 +123,7 @@ INTERNAL_system_debug_message(char *message){ #endif internal void* -system_get_memory_(i32 size, i32 line_number, char *file_name){ +Win32GetMemory_(i32 size, i32 line_number, char *file_name){ void *ptr = 0; #if FRED_INTERNAL @@ -160,10 +145,10 @@ system_get_memory_(i32 size, i32 line_number, char *file_name){ return ptr; } -#define system_get_memory(size) system_get_memory_(size, __LINE__, __FILE__) +#define Win32GetMemory(size) Win32GetMemory_(size, __LINE__, __FILE__) internal void -system_free_memory(void *block){ +Win32FreeMemory(void *block){ if (block){ #if FRED_INTERNAL Sys_Bubble *bubble = ((Sys_Bubble*)block) - 1; @@ -178,13 +163,18 @@ system_free_memory(void *block){ } } +inline void +system_free_memory(void *block){ + Win32FreeMemory(block); +} + internal Data system_load_file(char *filename){ Data result = {}; HANDLE file; file = CreateFile((char*)filename, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); - if (!file){ + if (!file || file == INVALID_HANDLE_VALUE){ return result; } @@ -197,7 +187,7 @@ system_load_file(char *filename){ } result.size = (lo) + (((u64)hi) << 32); - result.data = (byte*)system_get_memory(result.size); + result.data = (byte*)Win32GetMemory(result.size); if (!result.data){ CloseHandle(file); @@ -210,7 +200,7 @@ system_load_file(char *filename){ &read_size, 0); if (!read_result || read_size != (u32)result.size){ CloseHandle(file); - system_free_memory(result.data); + Win32FreeMemory(result.data); result = {}; return result; } @@ -219,13 +209,15 @@ system_load_file(char *filename){ return result; } +#include "4ed_rendering.cpp" + internal b32 system_save_file(char *filename, void *data, i32 size){ HANDLE file; file = CreateFile((char*)filename, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); - if (!file){ + if (!file || file == INVALID_HANDLE_VALUE){ return 0; } @@ -242,74 +234,36 @@ system_save_file(char *filename, void *data, i32 size){ return 1; } -internal Time_Stamp -system_file_time_stamp(char *filename){ - Time_Stamp result; - result = {}; +internal +Sys_File_Time_Stamp_Sig(system_file_time_stamp){ + u64 result; + result = 0; FILETIME last_write; WIN32_FILE_ATTRIBUTE_DATA data; if (GetFileAttributesEx((char*)filename, GetFileExInfoStandard, &data)){ last_write = data.ftLastWriteTime; - result.time = ((u64)last_write.dwHighDateTime << 32) | last_write.dwLowDateTime; - result.success = 1; + result = ((u64)last_write.dwHighDateTime << 32) | (last_write.dwLowDateTime); + result /= 10; } return result; } -internal u64 -system_time_stamp_now(){ - u64 result; - SYSTEMTIME sys_now; - FILETIME file_now; - GetSystemTime(&sys_now); - SystemTimeToFileTime(&sys_now, &file_now); - result = ((u64)file_now.dwHighDateTime << 32) | file_now.dwLowDateTime; - return result; -} - -internal i64 -system_time(){ - i64 result = 0; +internal +Sys_Time_Sig(system_time){ + u64 result = 0; LARGE_INTEGER time; if (QueryPerformanceCounter(&time)){ - result = (i64)(time.QuadPart - win32vars.start_pcount) * 1000000 / win32vars.performance_frequency; + result = (u64)(time.QuadPart - win32vars.start_pcount) * 1000000 / win32vars.performance_frequency; + result += win32vars.start_time; } return result; } -internal void -system_free_file(Data data){ - system_free_memory(data.data); -} - -internal i32 -system_get_current_directory(char *destination, i32 max_size){ - DWORD required = GetCurrentDirectory(0, 0); - if ((i32) required > max_size){ - // TODO(allen): WHAT NOW? Not enough space in destination for - // current directory. Two step approach perhaps? - return 0; - } - DWORD written = GetCurrentDirectory(max_size, (char*)destination); - return (i32)written; -} - -internal i32 -system_get_easy_directory(char *destination){ - persist char easydir[] = "C:\\"; - for (i32 i = 0; i < ArrayCount(easydir); ++i){ - destination[i] = easydir[i]; - } - return ArrayCount(easydir)-1; -} - -internal File_List -system_get_file_list(String directory){ - File_List result = {}; - +internal +Sys_Set_File_List_Sig(system_set_file_list){ if (directory.size > 0){ char dir_space[MAX_PATH + 32]; String dir = make_string(dir_space, 0, MAX_PATH + 32); @@ -338,15 +292,23 @@ system_get_file_list(String directory){ more_files = FindNextFile(search, &find_data); }while(more_files); FindClose(search); + + i32 required_size = count + file_count * sizeof(File_Info); + if (file_list->block_size < required_size){ + if (file_list->block){ + Win32FreeMemory(file_list->block); + } + + file_list->block = Win32GetMemory(required_size); + } - result.block = system_get_memory(count + file_count * sizeof(File_Info)); - result.infos = (File_Info*)result.block; - char *name = (char*)(result.infos + file_count); - if (result.block){ + file_list->infos = (File_Info*)file_list->block; + char *name = (char*)(file_list->infos + file_count); + if (file_list->block){ search = FindFirstFileA(c_str_dir, &find_data); if (search != INVALID_HANDLE_VALUE){ - File_Info *info = result.infos; + File_Info *info = file_list->infos; more_files = 1; do{ if (!match(find_data.cFileName, ".") && @@ -366,27 +328,93 @@ system_get_file_list(String directory){ }while(more_files); FindClose(search); - result.count = file_count; + file_list->count = file_count; }else{ - system_free_memory(result.block); - result = {}; + Win32FreeMemory(file_list->block); + file_list->block = 0; + file_list->block_size = 0; + } + } + } + } +} + +internal +DIRECTORY_HAS_FILE_SIG(system_directory_has_file){ + char *full_filename; + char space[1024]; + HANDLE file; + b32 result; + i32 len; + + full_filename = 0; + len = str_size(filename); + if (dir.memory_size - dir.size - 1 >= len){ + full_filename = dir.str; + memcpy(dir.str + dir.size, filename, len + 1); + } + else if (dir.size + len + 1 < 1024){ + full_filename = space; + memcpy(full_filename, dir.str, dir.size); + memcpy(full_filename + dir.size, filename, len + 1); + } + + result = 0; + if (full_filename){ + file = CreateFile((char*)full_filename, GENERIC_READ, 0, 0, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + if (file != INVALID_HANDLE_VALUE){ + CloseHandle(file); + result = 1; + } + dir.str[dir.size] = 0; + } + + return(result); +} + +b32 Win32DirectoryExists(char *path){ + DWORD attrib = GetFileAttributesA(path); + return (attrib != INVALID_FILE_ATTRIBUTES && + (attrib & FILE_ATTRIBUTE_DIRECTORY)); +} + +internal +DIRECTORY_CD_SIG(system_directory_cd){ + b32 result = 0; + i32 old_size; + i32 len; + + if (rel_path[0] != 0){ + if (rel_path[0] == '.' && rel_path[1] == 0){ + result = 1; + } + else if (rel_path[0] == '.' && rel_path[1] == '.' && rel_path[2] == 0){ + result = remove_last_folder(dir); + terminate_with_null(dir); + } + else{ + len = str_size(rel_path); + if (dir->size + len + 1 > dir->memory_size){ + old_size = dir->size; + append_partial(dir, rel_path); + append_partial(dir, "\\"); + if (Win32DirectoryExists(dir->str)){ + result = 1; + } + else{ + dir->size = old_size; } } } } - return result; + return(result); } -internal void -system_free_file_list(File_List list){ - system_free_memory(list.block); -} - -// TODO(allen): Probably best to just drop all system functions here again. -internal void -system_post_clipboard(String str){ +internal +Sys_Post_Clipboard_Sig(system_post_clipboard){ if (OpenClipboard(win32vars.window_handle)){ EmptyClipboard(); HANDLE memory_handle; @@ -424,29 +452,6 @@ Win32Resize(i32 width, i32 height){ } } -internal void -Win32KeyboardHandle(b8 current_state, b8 previous_state, WPARAM wParam){ - u16 key = keycode_lookup((u8)wParam); - if (key != -1){ - if (current_state & !previous_state){ - i32 count = win32vars.input_data.press_count; - if (count < KEY_INPUT_BUFFER_SIZE){ - win32vars.input_data.press[count].keycode = key; - win32vars.input_data.press[count].loose_keycode = loose_keycode_lookup((u8)wParam); - ++win32vars.input_data.press_count; - } - } - else if (current_state){ - i32 count = win32vars.input_data.hold_count; - if (count < KEY_INPUT_BUFFER_SIZE){ - win32vars.input_data.hold[count].keycode = key; - win32vars.input_data.hold[count].loose_keycode = loose_keycode_lookup((u8)wParam); - ++win32vars.input_data.hold_count; - } - } - } -} - #define HOTKEY_ALT_ID 0 internal LRESULT @@ -468,14 +473,103 @@ Win32Callback(HWND hwnd, UINT uMsg, case VK_SHIFT:case VK_LSHIFT:case VK_RSHIFT: break; default: - bool8 previous_state, current_state; + b8 previous_state, current_state; previous_state = ((lParam & Bit_30)?(1):(0)); current_state = ((lParam & Bit_31)?(0):(1)); - Win32KeyboardHandle(current_state, previous_state, wParam); + + if (current_state){ + u8 key = keycode_lookup((u8)wParam); + + i32 *count = 0; + Key_Event_Data *data = 0; + + if (!previous_state){ + count = &win32vars.input_data.press_count; + data = win32vars.input_data.press; + } + else{ + count = &win32vars.input_data.hold_count; + data = win32vars.input_data.hold; + } + + if (*count < KEY_INPUT_BUFFER_SIZE){ + if (!key){ + UINT vk = (UINT)wParam; + UINT scan = (UINT)((lParam >> 16) & 0x7F); + BYTE state[256]; + WORD x; + int result; + + GetKeyboardState(state); + if (win32vars.input_data.control_keys[CONTROL_KEY_CONTROL] && + !win32vars.input_data.control_keys[CONTROL_KEY_ALT]) + state[VK_CONTROL] = 0; + result = ToAscii(vk, scan, state, &x, 0); + if (result == 1 && x < 128){ + key = (u8)x; + if (key == '\r') key = '\n'; + data[*count].character = key; + + state[VK_CAPITAL] = 0; + result = ToAscii(vk, scan, state, &x, 0); + if (result == 1 && x < 128){ + key = (u8)x; + if (key == '\r') key = '\n'; + data[*count].character_no_caps_lock = key; + data[*count].keycode = key; + } + } + if (result != 1 || x >= 128){ + data[*count].character = 0; + data[*count].character_no_caps_lock = 0; + data[*count].keycode = 0; + } + } + else{ + data[*count].character = 0; + data[*count].character_no_caps_lock = 0; + data[*count].keycode = key; + } + ++(*count); + } + } + result = DefWindowProc(hwnd, uMsg, wParam, lParam); } }break; - + + case WM_INPUT: + { + char buffer[sizeof(RAWINPUT)] = {}; + UINT size = sizeof(RAWINPUT); + GetRawInputData((HRAWINPUT)(lParam), RID_INPUT, buffer, &size, sizeof(RAWINPUTHEADER)); + + RAWINPUT *rawinput = (RAWINPUT*)(buffer); + if (rawinput->header.dwType == RIM_TYPEKEYBOARD){ + RAWKEYBOARD *raw = &rawinput->data.keyboard; + UINT vk = raw->VKey; + UINT flags = raw->Flags; + b8 down = !(flags & 1); + + if (vk != 255){ + if (vk == VK_SHIFT){ + win32vars.input_data.control_keys[CONTROL_KEY_SHIFT] = down; + } + else if (vk == VK_CONTROL){ + win32vars.input_data.control_keys[CONTROL_KEY_CONTROL] = down; + } + else if (vk == VK_MENU){ + UINT is_gr = ((flags & RI_KEY_E0) != 0); + if (!is_gr){ + win32vars.input_data.control_keys[CONTROL_KEY_ALT] = down; + } + } + } + } + + result = DefWindowProcA(hwnd, uMsg, wParam, lParam); + }break; + case WM_MOUSEMOVE: { win32vars.mouse.x = LOWORD(lParam); @@ -518,14 +612,14 @@ Win32Callback(HWND hwnd, UINT uMsg, win32vars.focus = 0; win32vars.mouse.left_button = false; win32vars.mouse.right_button = false; - for (int i = 0; i < CONTROL_KEY_COUNT; ++i){ - win32vars.input_data.control_keys[i] = 0; - } }break; case WM_SETFOCUS: { win32vars.focus = 1; + for (int i = 0; i < CONTROL_KEY_COUNT; ++i){ + win32vars.input_data.control_keys[i] = 0; + } }break; case WM_SIZE: @@ -549,7 +643,8 @@ Win32Callback(HWND hwnd, UINT uMsg, &win32vars.previous_data, &win32vars.mouse, &win32vars.target, - &win32memory, + &memory_vars, + &exchange_vars, empty_contents, 0, 0, 1); @@ -571,10 +666,21 @@ Win32Callback(HWND hwnd, UINT uMsg, return result; } -#define THREAD_NOT_ASSIGNED 0xFFFFFFFF +internal HANDLE +Win32Handle(Plat_Handle h){ + HANDLE result; + result = {}; + result = *(HANDLE*)(&h); + return(result); +} -#define JOB_ID_WRAP (ArrayCount(queue->jobs) * 4) -#define QUEUE_WRAP (ArrayCount(queue->jobs)) +internal Plat_Handle +Win32GenHandle(HANDLE h){ + Assert(sizeof(Plat_Handle) >= sizeof(HANDLE)); + Plat_Handle result; + result = *(Plat_Handle*)(&h); + return(result); +} internal DWORD WINAPI ThreadProc(LPVOID lpParameter){ @@ -604,62 +710,40 @@ ThreadProc(LPVOID lpParameter){ if (safe_running_thread == THREAD_NOT_ASSIGNED){ thread->job_id = full_job->id; thread->running = 1; +#if UseThreadMemory Thread_Memory *thread_memory = 0; +#endif + + // TODO(allen): remove memory_request if (full_job->job.memory_request != 0){ +#if UseThreadMemory thread_memory = win32vars.thread_memory + thread->id - 1; if (thread_memory->size < full_job->job.memory_request){ if (thread_memory->data){ - system_free_memory(thread_memory->data); + Win32FreeMemory(thread_memory->data); } i32 new_size = LargeRoundUp(full_job->job.memory_request, Kbytes(4)); - thread_memory->data = system_get_memory(new_size); + thread_memory->data = Win32GetMemory(new_size); thread_memory->size = new_size; } +#endif } - full_job->job.callback(win32vars.system, thread, thread_memory, full_job->job.data); + full_job->job.callback(win32vars.system, thread, thread_memory, + &exchange_vars.thread, full_job->job.data); full_job->running_thread = 0; thread->running = 0; } } } else{ - WaitForSingleObject(queue->semaphore, INFINITE); + WaitForSingleObject(Win32Handle(queue->semaphore), INFINITE); } } } -internal b32 -Win32JobIsPending(Work_Queue *queue, u32 job_id){ - b32 result; - u32 job_index; - Full_Job_Data *full_job; - - job_index = job_id % QUEUE_WRAP; - full_job = queue->jobs + job_index; - - Assert(full_job->id == job_id); - - result = 0; - if (full_job->running_thread != 0){ - result = 1; - } - - return result; -} - -internal u32 -system_thread_get_id(Thread_Context *thread){ - return thread->id; -} - -internal u32 -system_thread_current_job_id(Thread_Context *thread){ - return thread->job_id; -} - -internal u32 -system_post_job(Thread_Group_ID group_id, Job_Data job){ - Work_Queue *queue = win32vars.queues + group_id; +internal +Sys_Post_Job_Sig(system_post_job){ + Work_Queue *queue = exchange_vars.thread.queues + group_id; Assert((queue->write_position + 1) % QUEUE_WRAP != queue->read_position % QUEUE_WRAP); @@ -678,29 +762,27 @@ system_post_job(Thread_Group_ID group_id, Job_Data job){ queue->jobs[write_index].running_thread = THREAD_NOT_ASSIGNED; queue->jobs[write_index].id = result; success = 1; - - // TODO } } - ReleaseSemaphore(queue->semaphore, 1, 0); + ReleaseSemaphore(Win32Handle(queue->semaphore), 1, 0); return result; } -internal void -system_acquire_lock(i32 id){ +internal +Sys_Acquire_Lock_Sig(system_acquire_lock){ WaitForSingleObject(win32vars.locks[id], INFINITE); } -internal void -system_release_lock(i32 id){ +internal +Sys_Release_Lock_Sig(system_release_lock){ ReleaseSemaphore(win32vars.locks[id], 1, 0); } -internal void -system_cancel_job(Thread_Group_ID group_id, u32 job_id){ - Work_Queue *queue = win32vars.queues + group_id; +internal +Sys_Cancel_Job_Sig(system_cancel_job){ + Work_Queue *queue = exchange_vars.thread.queues + group_id; Thread_Group *group = win32vars.groups + group_id; u32 job_index; @@ -727,36 +809,27 @@ system_cancel_job(Thread_Group_ID group_id, u32 job_id){ } } -internal b32 -system_job_is_pending(Thread_Group_ID group_id, u32 job_id){ - Work_Queue *queue = win32vars.queues + group_id;; - return Win32JobIsPending(queue, job_id); -} - +#if UseThreadMemory internal void system_grow_thread_memory(Thread_Memory *memory){ system_acquire_lock(CANCEL_LOCK0 + memory->id - 1); void *old_data = memory->data; i32 old_size = memory->size; i32 new_size = LargeRoundUp(memory->size*2, Kbytes(4)); - memory->data = system_get_memory(new_size); + memory->data = Win32GetMemory(new_size); memory->size = new_size; if (old_data){ memcpy(memory->data, old_data, old_size); - system_free_memory(old_data); + Win32FreeMemory(old_data); } system_release_lock(CANCEL_LOCK0 + memory->id - 1); } - -internal void -system_force_redraw(){ - InterlockedExchange(&win32vars.force_redraw, 1); -} +#endif #if FRED_INTERNAL internal void INTERNAL_get_thread_states(Thread_Group_ID id, bool8 *running, i32 *pending){ - Work_Queue *queue = win32vars.queues + id; + Work_Queue *queue = exchange_vars.thread.queues + id; u32 write = queue->write_position; u32 read = queue->read_position; if (write < read) write += JOB_ID_WRAP; @@ -769,8 +842,8 @@ INTERNAL_get_thread_states(Thread_Group_ID id, bool8 *running, i32 *pending){ } #endif -internal b32 -system_cli_call(char *path, char *script_name, CLI_Handles *cli_out){ +internal +Sys_CLI_Call_Sig(system_cli_call){ char cmd[] = "c:\\windows\\system32\\cmd.exe"; char *env_variables = 0; char command_line[2048]; @@ -779,7 +852,6 @@ system_cli_call(char *path, char *script_name, CLI_Handles *cli_out){ String s = make_fixed_width_string(command_line); copy(&s, make_lit_string("/C ")); append_partial(&s, script_name); - append_partial(&s, make_lit_string(".bat ")); success = terminate_with_null(&s); if (success){ @@ -839,15 +911,15 @@ struct CLI_Loop_Control{ u32 remaining_amount; }; -internal void -system_cli_begin_update(CLI_Handles *cli){ +internal +Sys_CLI_Begin_Update_Sig(system_cli_begin_update){ Assert(sizeof(cli->scratch_space) >= sizeof(CLI_Loop_Control)); CLI_Loop_Control *loop = (CLI_Loop_Control*)cli->scratch_space; loop->remaining_amount = 0; } -internal b32 -system_cli_update_step(CLI_Handles *cli, char *dest, u32 max, u32 *amount){ +internal +Sys_CLI_Update_Step_Sig(system_cli_update_step){ HANDLE handle = *(HANDLE*)&cli->out_read; CLI_Loop_Control *loop = (CLI_Loop_Control*)cli->scratch_space; b32 has_more = 0; @@ -882,8 +954,8 @@ system_cli_update_step(CLI_Handles *cli, char *dest, u32 max, u32 *amount){ return has_more; } -internal b32 -system_cli_end_update(CLI_Handles *cli){ +internal +Sys_CLI_End_Update_Sig(system_cli_end_update){ b32 close_me = 0; if (WaitForSingleObject(*(HANDLE*)&cli->proc, 0) == WAIT_OBJECT_0){ close_me = 1; @@ -894,11 +966,6 @@ system_cli_end_update(CLI_Handles *cli){ return close_me; } -void -DUMP(byte *d, i32 size){ - //system_save_file("DUMP", d, size); -} - internal b32 Win32LoadAppCode(){ b32 result = 0; @@ -907,13 +974,12 @@ Win32LoadAppCode(){ win32vars.app_code = LoadLibraryA("4ed_app.dll"); if (win32vars.app_code){ result = 1; - win32vars.app.init = (App_Init*) - GetProcAddress(win32vars.app_code, "app_init"); - win32vars.app.step = (App_Step*) - GetProcAddress(win32vars.app_code, "app_step"); + App_Get_Functions *get_funcs = (App_Get_Functions*) + GetProcAddress(win32vars.app_code, "app_get_functions"); + + win32vars.app = get_funcs(); } - DUMP((byte*)(win32vars.app.step) - 0x39000, Kbytes(400)); #else Data file = system_load_file("4ed_app.dll"); @@ -937,17 +1003,14 @@ Win32LoadAppCode(){ &extra_); result = 1; - win32vars.app.init = (App_Init*) - dll_load_function(&win32vars.app_dll, "app_init", 8); - - win32vars.app.step = (App_Step*) - dll_load_function(&win32vars.app_dll, "app_step", 8); + App_Get_Functions *get_functions = (App_Get_Functions*) + dll_load_function(&win32vars.app_dll, "app_get_functions", 17); } else{ // TODO(allen): file loading error } - system_free_file(file); + system_free(file.data); DUMP((byte*)(Tbytes(3)), Kbytes(400)); } @@ -962,20 +1025,11 @@ Win32LoadAppCode(){ internal void Win32LoadSystemCode(){ - win32vars.system->get_memory_full = system_get_memory_; - win32vars.system->free_memory = system_free_memory; - - win32vars.system->load_file = system_load_file; - win32vars.system->save_file = system_save_file; win32vars.system->file_time_stamp = system_file_time_stamp; - win32vars.system->time_stamp_now = system_time_stamp_now; - win32vars.system->free_file = system_free_file; + win32vars.system->set_file_list = system_set_file_list; - win32vars.system->get_current_directory = system_get_current_directory; - win32vars.system->get_easy_directory = system_get_easy_directory; - - win32vars.system->get_file_list = system_get_file_list; - win32vars.system->free_file_list = system_free_file_list; + win32vars.system->directory_has_file = system_directory_has_file; + win32vars.system->directory_cd = system_directory_cd; win32vars.system->post_clipboard = system_post_clipboard; win32vars.system->time = system_time; @@ -985,22 +1039,56 @@ Win32LoadSystemCode(){ win32vars.system->cli_update_step = system_cli_update_step; win32vars.system->cli_end_update = system_cli_end_update; - win32vars.system->thread_get_id = system_thread_get_id; - win32vars.system->thread_current_job_id = system_thread_current_job_id; win32vars.system->post_job = system_post_job; win32vars.system->cancel_job = system_cancel_job; - win32vars.system->job_is_pending = system_job_is_pending; win32vars.system->grow_thread_memory = system_grow_thread_memory; win32vars.system->acquire_lock = system_acquire_lock; win32vars.system->release_lock = system_release_lock; - win32vars.system->force_redraw = system_force_redraw; - win32vars.system->internal_sentinel = INTERNAL_system_sentinel; win32vars.system->internal_get_thread_states = INTERNAL_get_thread_states; win32vars.system->internal_debug_message = INTERNAL_system_debug_message; } +void +ex__file_insert(File_Slot *pos, File_Slot *file){ + file->next = pos->next; + file->next->prev = file; + file->prev = pos; + pos->next = file; +} + +void +ex__insert_range(File_Slot *start, File_Slot *end, File_Slot *pos){ + end->next->prev = start->prev; + start->prev->next = end->next; + + end->next = pos->next; + start->prev = pos; + pos->next->prev = end; + pos->next = start; +} + +internal void +ex__check_file(File_Slot *pos){ + File_Slot *file = pos; + + Assert(pos == pos->next->prev); + + for (pos = pos->next; + file != pos; + pos = pos->next){ + Assert(pos == pos->next->prev); + } +} + +internal void +ex__check(File_Exchange *file_exchange){ + ex__check_file(&file_exchange->available); + ex__check_file(&file_exchange->active); + ex__check_file(&file_exchange->free_list); +} + int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, @@ -1008,6 +1096,8 @@ WinMain(HINSTANCE hInstance, int nCmdShow){ win32vars = {}; + exchange_vars = {}; + #if FRED_INTERNAL win32vars.internal_bubble.next = &win32vars.internal_bubble; win32vars.internal_bubble.prev = &win32vars.internal_bubble; @@ -1030,6 +1120,11 @@ WinMain(HINSTANCE hInstance, QueryPerformanceCounter(&lpf); win32vars.start_pcount = lpf.QuadPart; + FILETIME filetime; + GetSystemTimeAsFileTime(&filetime); + win32vars.start_time = ((u64)filetime.dwHighDateTime << 32) | (filetime.dwLowDateTime); + win32vars.start_time /= 10; + keycode_init(&win32vars.key_codes); #ifdef FRED_SUPER @@ -1047,23 +1142,31 @@ WinMain(HINSTANCE hInstance, memset(background, 0, sizeof(background)); win32vars.groups[BACKGROUND_THREADS].threads = background; win32vars.groups[BACKGROUND_THREADS].count = ArrayCount(background); + +#if UseThreadMemory Thread_Memory thread_memory[ArrayCount(background)]; win32vars.thread_memory = thread_memory; +#endif + - win32vars.queues[BACKGROUND_THREADS].semaphore = - CreateSemaphore(0, 0, win32vars.groups[BACKGROUND_THREADS].count, 0); + exchange_vars.thread.queues[BACKGROUND_THREADS].semaphore = + Win32GenHandle( + CreateSemaphore(0, 0, win32vars.groups[BACKGROUND_THREADS].count, 0) + ); u32 creation_flag = 0; for (i32 i = 0; i < win32vars.groups[BACKGROUND_THREADS].count; ++i){ Thread_Context *thread = win32vars.groups[BACKGROUND_THREADS].threads + i; thread->id = i + 1; - + +#if UseThreadMemory Thread_Memory *memory = win32vars.thread_memory + i; *memory = {}; memory->id = thread->id; +#endif - thread->queue = &win32vars.queues[BACKGROUND_THREADS]; + thread->queue = &exchange_vars.thread.queues[BACKGROUND_THREADS]; thread->handle = CreateThread(0, 0, ThreadProc, thread, creation_flag, (LPDWORD)&thread->windows_id); } @@ -1109,7 +1212,7 @@ WinMain(HINSTANCE hInstance, window_rect.bottom - window_rect.top, 0, 0, hInstance, 0); - if (!window_handle){ + if (window_handle == 0){ return 2; } @@ -1118,7 +1221,14 @@ WinMain(HINSTANCE hInstance, HDC hdc = GetDC(window_handle); GetClientRect(window_handle, &window_rect); - + + RAWINPUTDEVICE device; + device.usUsagePage = 0x1; + device.usUsage = 0x6; + device.dwFlags = 0; + device.hwndTarget = window_handle; + RegisterRawInputDevices(&device, 1, sizeof(device)); + static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), 1, @@ -1161,8 +1271,8 @@ WinMain(HINSTANCE hInstance, base = (LPVOID)0; #endif - win32memory.vars_memory_size = Mbytes(2); - win32memory.vars_memory = VirtualAlloc(base, win32memory.vars_memory_size, + memory_vars.vars_memory_size = Mbytes(2); + memory_vars.vars_memory = VirtualAlloc(base, memory_vars.vars_memory_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); @@ -1171,12 +1281,12 @@ WinMain(HINSTANCE hInstance, #else base = (LPVOID)0; #endif - win32memory.target_memory_size = Mbytes(512); - win32memory.target_memory = VirtualAlloc(base, win32memory.target_memory_size, + memory_vars.target_memory_size = Mbytes(512); + memory_vars.target_memory = VirtualAlloc(base, memory_vars.target_memory_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - if (!win32memory.vars_memory){ + if (!memory_vars.vars_memory){ return 4; } @@ -1213,14 +1323,54 @@ WinMain(HINSTANCE hInstance, win32vars.target.push_clip = draw_push_clip; win32vars.target.pop_clip = draw_pop_clip; win32vars.target.push_piece = draw_push_piece; - win32vars.target.font_load = draw_font_load; + + win32vars.target.font_set.font_info_load = draw_font_info_load; + win32vars.target.font_set.font_load = draw_font_load; + win32vars.target.font_set.release_font = draw_release_font; win32vars.target.max = Mbytes(1); - win32vars.target.push_buffer = (byte*)system_get_memory(win32vars.target.max); + win32vars.target.push_buffer = (byte*)Win32GetMemory(win32vars.target.max); + + File_Slot file_slots[32]; + exchange_vars.file.max = sizeof(file_slots) / sizeof(file_slots[0]); + exchange_vars.file.available = {}; + exchange_vars.file.available.next = &exchange_vars.file.available; + exchange_vars.file.available.prev = &exchange_vars.file.available; + + exchange_vars.file.active = {}; + exchange_vars.file.active.next = &exchange_vars.file.active; + exchange_vars.file.active.prev = &exchange_vars.file.active; + + exchange_vars.file.free_list = {}; + exchange_vars.file.free_list.next = &exchange_vars.file.free_list; + exchange_vars.file.free_list.prev = &exchange_vars.file.free_list; + + exchange_vars.file.files = file_slots; + memset(file_slots, 0, sizeof(file_slots)); + + char *filename_space = (char*) + Win32GetMemory(FileNameMax*exchange_vars.file.max); + + for (int i = 0; i < exchange_vars.file.max; ++i){ + File_Slot *slot = file_slots + i; + ex__file_insert(&exchange_vars.file.available, slot); + slot->filename = filename_space; + filename_space += FileNameMax; + } + + DWORD required = GetCurrentDirectory(0, 0); + required += 1; + required *= 4; + char *current_directory_mem = (char*)Win32GetMemory(required); + DWORD written = GetCurrentDirectory(required, current_directory_mem); + + String current_directory = make_string(current_directory_mem, written, required); + terminate_with_null(¤t_directory); if (!win32vars.app.init(win32vars.system, &win32vars.target, - &win32memory, &win32vars.key_codes, - win32vars.clipboard_contents, win32vars.config_api)){ + &memory_vars, &exchange_vars, &win32vars.key_codes, + win32vars.clipboard_contents, current_directory, + win32vars.config_api)){ return 5; } @@ -1240,21 +1390,12 @@ WinMain(HINSTANCE hInstance, win32vars.input_data.hold_count = 0; win32vars.input_data.caps_lock = GetKeyState(VK_CAPITAL) & 0x1; - win32vars.input_data.control_keys[CONTROL_KEY_SHIFT] = - (GetKeyState(VK_SHIFT) & 0x0100) >> 8; - - win32vars.input_data.control_keys[CONTROL_KEY_CONTROL] = - (GetKeyState(VK_CONTROL) & 0x0100) >> 8; - - win32vars.input_data.control_keys[CONTROL_KEY_ALT] = - (GetKeyState(VK_MENU) & 0x0100) >> 8; - win32vars.mouse.left_button_prev = win32vars.mouse.left_button; win32vars.mouse.right_button_prev = win32vars.mouse.right_button; win32vars.mouse.wheel = 0; MSG msg; - while (PeekMessage(&msg, window_handle, 0, 0, PM_REMOVE) && win32vars.keep_playing){ + while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE) && win32vars.keep_playing){ if (msg.message == WM_QUIT){ win32vars.keep_playing = 0; }else{ @@ -1281,26 +1422,6 @@ WinMain(HINSTANCE hInstance, win32vars.mouse.out_of_window = 1; } - b32 shift = win32vars.input_data.control_keys[CONTROL_KEY_SHIFT]; - b32 caps_lock = win32vars.input_data.caps_lock; - for (i32 i = 0; i < win32vars.input_data.press_count; ++i){ - i16 keycode = win32vars.input_data.press[i].keycode; - - win32vars.input_data.press[i].character = - translate_key(keycode, shift, caps_lock); - win32vars.input_data.press[i].character_no_caps_lock = - translate_key(keycode, shift, 0); - } - - for (i32 i = 0; i < win32vars.input_data.hold_count; ++i){ - i16 keycode = win32vars.input_data.hold[i].keycode; - - win32vars.input_data.hold[i].character = - translate_key(keycode, shift, caps_lock); - win32vars.input_data.hold[i].character_no_caps_lock = - translate_key(keycode, shift, 0); - } - win32vars.clipboard_contents = {}; if (win32vars.clipboard_sequence != 0){ DWORD new_number = GetClipboardSequenceNumber(); @@ -1326,7 +1447,11 @@ WinMain(HINSTANCE hInstance, } } - i32 redraw = InterlockedExchange(&win32vars.force_redraw, 0); + u32 redraw = exchange_vars.thread.force_redraw; + if (redraw){ + exchange_vars.thread.force_redraw = 0; + } + ProfileEnd(OS_input); Application_Step_Result result = @@ -1335,7 +1460,8 @@ WinMain(HINSTANCE hInstance, &win32vars.input_data, &win32vars.mouse, &win32vars.target, - &win32memory, + &memory_vars, + &exchange_vars, win32vars.clipboard_contents, 1, first, redraw); @@ -1355,6 +1481,58 @@ WinMain(HINSTANCE hInstance, if (result.redraw) Win32RedrawScreen(hdc); ProfileEnd(OS_frame_out); + ProfileStart(OS_file_process); + { + File_Slot *file; + int d = 0; + + for (file = exchange_vars.file.active.next; + file != &exchange_vars.file.active; + file = file->next){ + ++d; + + if (file->flags & FEx_Save){ + Assert((file->flags & FEx_Request) == 0); + file->flags &= (~FEx_Save); + system_save_file(file->filename, file->data, file->size); + file->flags |= FEx_Save_Complete; + } + + if (file->flags & FEx_Request){ + Assert((file->flags & FEx_Save) == 0); + file->flags &= (~FEx_Request); + Data sysfile = + system_load_file(file->filename); + if (sysfile.data == 0){ + file->flags |= FEx_Not_Exist; + } + else{ + file->flags |= FEx_Ready; + file->data = sysfile.data; + file->size = sysfile.size; + } + } + } + + Assert(d == exchange_vars.file.num_active); + + for (file = exchange_vars.file.free_list.next; + file != &exchange_vars.file.free_list; + file = file->next){ + if (file->data){ + system_free_memory(file->data); + } + } + + if (exchange_vars.file.free_list.next != &exchange_vars.file.free_list){ + ex__insert_range(exchange_vars.file.free_list.next, exchange_vars.file.free_list.prev, + &exchange_vars.file.available); + } + + ex__check(&exchange_vars.file); + } + ProfileEnd(OS_file_process); + ProfileStart(frame_sleep); i64 timer_end = system_time(); i64 end_target = (timer_start + frame_useconds); @@ -1366,7 +1544,7 @@ WinMain(HINSTANCE hInstance, timer_end = system_time(); } system_acquire_lock(FRAME_LOCK); - timer_start = system_time(); + timer_start = system_time();7 ProfileEnd(frame_sleep); }