From 63bfed7ab1f230962a0308d950ebf442167e09c3 Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Fri, 1 May 2020 07:38:57 -0700 Subject: [PATCH] Quick fix for thread handle leak; project parse crash bug fix --- 4ed.cpp | 30 +++++++++++ 4ed_api_implementation.cpp | 52 ------------------- 4ed_app_models.cpp | 77 +++++++++++++++++++++++++++++ 4ed_app_models.h | 7 +++ 4ed_app_target.cpp | 1 + 4ed_view.cpp | 7 +++ custom/4coder_config.cpp | 2 +- custom/4coder_default_hooks.cpp | 1 - custom/4coder_project_commands.cpp | 16 +++--- custom/generated/command_metadata.h | 22 ++++----- ship_files/changes.txt | 4 +- 11 files changed, 146 insertions(+), 73 deletions(-) create mode 100644 4ed_app_models.cpp diff --git a/4ed.cpp b/4ed.cpp index aeab7006..5ec54853 100644 --- a/4ed.cpp +++ b/4ed.cpp @@ -746,6 +746,36 @@ App_Step_Sig(app_step){ end_render_section(target); } + // TODO(allen): This is dumb. Let's rethink view cleanup strategy. + // NOTE(allen): wind down coroutines + for (;;){ + Model_Wind_Down_Co *node = models->wind_down_stack; + if (node == 0){ + break; + } + sll_stack_pop(models->wind_down_stack); + Coroutine *co = node->co; + + for (i32 j = 0; co != 0; j += 1){ + Co_In in = {}; + in.user_input.abort = true; + Co_Out ignore = {}; + co = co_run(tctx, models, co, &in, &ignore); + if (j == 100){ + Application_Links app = {}; + app.tctx = tctx; + app.cmd_context = models; +#define M "SERIOUS ERROR: coroutine wind down did not complete" + print_message(&app, string_u8_litexpr(M)); +#undef M + break; + } + } + + sll_stack_push(models->free_wind_downs, node); + } + + // NOTE(allen): flush the log log_flush(tctx, models); diff --git a/4ed_api_implementation.cpp b/4ed_api_implementation.cpp index 0feb4f68..b2cca585 100644 --- a/4ed_api_implementation.cpp +++ b/4ed_api_implementation.cpp @@ -33,58 +33,6 @@ file_cursor_to_end(Thread_Context *tctx, Models *models, Editing_File *file){ } } -function void -models_push_view_command_function(Models *models, View_ID view_id, Custom_Command_Function *custom_func){ - Model_View_Command_Function *node = models->free_view_cmd_funcs; - if (node == 0){ - node = push_array(models->arena, Model_View_Command_Function, 1); - } - else{ - sll_stack_pop(models->free_view_cmd_funcs); - } - sll_queue_push(models->first_view_cmd_func, models->last_view_cmd_func, node); - node->view_id = view_id; - node->custom_func = custom_func; -} - -function Model_View_Command_Function -models_pop_view_command_function(Models *models){ - Model_View_Command_Function result = {}; - if (models->first_view_cmd_func != 0){ - Model_View_Command_Function *node = models->first_view_cmd_func; - result.custom_func = node->custom_func; - result.view_id = node->view_id; - sll_queue_pop(models->first_view_cmd_func, models->last_view_cmd_func); - sll_stack_push(models->free_view_cmd_funcs, node); - } - return(result); -} - -function void -models_push_virtual_event(Models *models, Input_Event *event){ - Model_Input_Event_Node *node = models->free_virtual_event; - if (node == 0){ - node = push_array(&models->virtual_event_arena, Model_Input_Event_Node, 1); - } - else{ - sll_stack_pop(models->free_virtual_event); - } - sll_queue_push(models->first_virtual_event, models->last_virtual_event, node); - node->event = copy_input_event(&models->virtual_event_arena, event); -} - -function Input_Event -models_pop_virtual_event(Arena *arena, Models *models){ - Input_Event result = {}; - if (models->first_virtual_event != 0){ - Model_Input_Event_Node *node = models->first_virtual_event; - result = copy_input_event(arena, &node->event); - sll_queue_pop(models->first_virtual_event, models->last_virtual_event); - sll_stack_push(models->free_virtual_event, node); - } - return(result); -} - //////////////////////////////// function b32 diff --git a/4ed_app_models.cpp b/4ed_app_models.cpp new file mode 100644 index 00000000..c9ff957d --- /dev/null +++ b/4ed_app_models.cpp @@ -0,0 +1,77 @@ +/* + * Mr. 4th Dimention - Allen Webster + * + * 01.05.2020 + * + * Implementation of the root models features. + * + */ + +// TOP + +function void +models_push_view_command_function(Models *models, View_ID view_id, Custom_Command_Function *custom_func){ + Model_View_Command_Function *node = models->free_view_cmd_funcs; + if (node == 0){ + node = push_array(models->arena, Model_View_Command_Function, 1); + } + else{ + sll_stack_pop(models->free_view_cmd_funcs); + } + sll_queue_push(models->first_view_cmd_func, models->last_view_cmd_func, node); + node->view_id = view_id; + node->custom_func = custom_func; +} + +function Model_View_Command_Function +models_pop_view_command_function(Models *models){ + Model_View_Command_Function result = {}; + if (models->first_view_cmd_func != 0){ + Model_View_Command_Function *node = models->first_view_cmd_func; + result.custom_func = node->custom_func; + result.view_id = node->view_id; + sll_queue_pop(models->first_view_cmd_func, models->last_view_cmd_func); + sll_stack_push(models->free_view_cmd_funcs, node); + } + return(result); +} + +function void +models_push_virtual_event(Models *models, Input_Event *event){ + Model_Input_Event_Node *node = models->free_virtual_event; + if (node == 0){ + node = push_array(&models->virtual_event_arena, Model_Input_Event_Node, 1); + } + else{ + sll_stack_pop(models->free_virtual_event); + } + sll_queue_push(models->first_virtual_event, models->last_virtual_event, node); + node->event = copy_input_event(&models->virtual_event_arena, event); +} + +function Input_Event +models_pop_virtual_event(Arena *arena, Models *models){ + Input_Event result = {}; + if (models->first_virtual_event != 0){ + Model_Input_Event_Node *node = models->first_virtual_event; + result = copy_input_event(arena, &node->event); + sll_queue_pop(models->first_virtual_event, models->last_virtual_event); + sll_stack_push(models->free_virtual_event, node); + } + return(result); +} + +function void +models_push_wind_down(Models *models, Coroutine *co){ + Model_Wind_Down_Co *node = models->free_wind_downs; + if (node != 0){ + sll_stack_pop(models->free_wind_downs); + } + else{ + node = push_array(models->arena, Model_Wind_Down_Co, 1); + } + sll_stack_push(models->wind_down_stack, node); + node->co = co; +} + +// BOTTOM diff --git a/4ed_app_models.h b/4ed_app_models.h index e8203fef..d8ad515a 100644 --- a/4ed_app_models.h +++ b/4ed_app_models.h @@ -44,6 +44,11 @@ struct Model_Input_Event_Node{ Input_Event event; }; +struct Model_Wind_Down_Co{ + Model_Wind_Down_Co *next; + Coroutine *co; +}; + struct Models{ Arena arena_; Arena *arena; @@ -55,6 +60,8 @@ struct Models{ Face_ID global_face_id; Coroutine_Group coroutines; + Model_Wind_Down_Co *wind_down_stack; + Model_Wind_Down_Co *free_wind_downs; Child_Process_Container child_processes; Custom_API config_api; diff --git a/4ed_app_target.cpp b/4ed_app_target.cpp index 16e980de..8f13a1c5 100644 --- a/4ed_app_target.cpp +++ b/4ed_app_target.cpp @@ -108,6 +108,7 @@ #include "4ed_font_set.cpp" #include "4ed_translation.cpp" #include "4ed_render_target.cpp" +#include "4ed_app_models.cpp" #include "4ed_buffer.cpp" #include "4ed_string_matching.cpp" #include "4ed_history.cpp" diff --git a/4ed_view.cpp b/4ed_view.cpp index 2594694d..fb54ce8e 100644 --- a/4ed_view.cpp +++ b/4ed_view.cpp @@ -591,11 +591,16 @@ view_init(Thread_Context *tctx, Models *models, View *view, Editing_File *initia Assert(view->co != 0); } +// TODO(allen): This doesn't make any sense!!!!!! COROUTINE SHUTDOWN? VIEW CLOSING? WADAFUQ? + function b32 view_close(Models *models, View *view){ Layout *layout = &models->layout; b32 result = false; if (layout_close_panel(layout, view->panel)){ + if (view->co != 0){ + models_push_wind_down(models, view->co); + } live_set_free_view(&models->lifetime_allocator, &models->view_set, view); result = true; } @@ -614,6 +619,8 @@ view_check_co_exited(Models *models, View *view){ } } +// TODO(allen): This is dumb. Let's rethink view cleanup strategy. + internal void co_single_abort(Thread_Context *tctx, Models *models, View *view){ Coroutine *co = view->co; diff --git a/custom/4coder_config.cpp b/custom/4coder_config.cpp index ba8aa720..6c5ccf3a 100644 --- a/custom/4coder_config.cpp +++ b/custom/4coder_config.cpp @@ -944,7 +944,7 @@ function b32 config_compound_compound_member(Config *config, Config_Compound *compound, String_Const_u8 var_name, i32 index, Config_Compound** var_out){ Config_Get_Result result = config_compound_member(config, compound, var_name, index); - b32 success = result.success && result.type == ConfigRValueType_Compound; + b32 success = (result.success && result.type == ConfigRValueType_Compound); if (success){ *var_out = result.compound; } diff --git a/custom/4coder_default_hooks.cpp b/custom/4coder_default_hooks.cpp index 05864d97..7ef1d4b6 100644 --- a/custom/4coder_default_hooks.cpp +++ b/custom/4coder_default_hooks.cpp @@ -892,7 +892,6 @@ BUFFER_HOOK_SIG(default_file_save){ b32 is_virtual = global_config.enable_virtual_whitespace; if (global_config.automatically_indent_text_on_save && is_virtual){ - clean_all_lines_buffer(app, buffer_id); auto_indent_buffer(app, buffer_id, buffer_range(app, buffer_id)); } diff --git a/custom/4coder_project_commands.cpp b/custom/4coder_project_commands.cpp index 00b686c3..5abe56f6 100644 --- a/custom/4coder_project_commands.cpp +++ b/custom/4coder_project_commands.cpp @@ -332,9 +332,8 @@ parse_project__config_data__version_1(Application_Links *app, Arena *arena, Stri goto finish_command; } - cmd_result = config_compound_member(parsed, src, - string_u8_litexpr("cmd"), 1); - if (cmd_result.success){ + cmd_result = config_compound_member(parsed, src, string_u8_litexpr("cmd"), 1); + if (cmd_result.success && cmd_result.type == ConfigRValueType_Compound){ cmd_set = cmd_result.compound; cmd_pos = cmd_result.pos; } @@ -691,18 +690,21 @@ set_current_project(Application_Links *app, Project *project, Config *parsed){ if (print_feedback){ Temp_Memory temp = begin_temp(scratch); - // Top - print_message(app, string_u8_litexpr("Loaded project file:\n")); - // Errors String_Const_u8 error_text = config_stringize_errors(app, scratch, parsed); - print_message(app, error_text); + if (error_text.size > 0){ + print_message(app, string_u8_litexpr("Project errors:\n")); + print_message(app, error_text); + print_message(app, string_u8_litexpr("\n")); + } // Values if (project == 0){ print_message(app, string_u8_litexpr("Could not instantiate project\n")); } else{ + print_message(app, string_u8_litexpr("New project contents:\n")); + Temp_Memory temp2 = begin_temp(scratch); List_String_Const_u8 list = {}; diff --git a/custom/generated/command_metadata.h b/custom/generated/command_metadata.h index 0f4df701..b26058d1 100644 --- a/custom/generated/command_metadata.h +++ b/custom/generated/command_metadata.h @@ -287,7 +287,7 @@ static Command_Metadata fcoder_metacmd_table[243] = { { PROC_LINKS(click_set_cursor_if_lbutton, 0), false, "click_set_cursor_if_lbutton", 27, "If the mouse left button is pressed, sets the cursor position to the mouse position.", 84, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 241 }, { PROC_LINKS(click_set_mark, 0), false, "click_set_mark", 14, "Sets the mark position to the mouse position.", 45, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 253 }, { PROC_LINKS(clipboard_record_clip, 0), false, "clipboard_record_clip", 21, "In response to a new clipboard contents events, saves the new clip onto the clipboard history", 93, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 7 }, -{ PROC_LINKS(close_all_code, 0), false, "close_all_code", 14, "Closes any buffer with a filename ending with an extension configured to be recognized as a code file type.", 107, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 842 }, +{ PROC_LINKS(close_all_code, 0), false, "close_all_code", 14, "Closes any buffer with a filename ending with an extension configured to be recognized as a code file type.", 107, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 844 }, { PROC_LINKS(close_build_panel, 0), false, "close_build_panel", 17, "If the special build panel is open, closes it.", 46, "w:\\4ed\\code\\custom\\4coder_build_commands.cpp", 44, 174 }, { PROC_LINKS(close_panel, 0), false, "close_panel", 11, "Closes the currently active panel if it is not the only panel open.", 67, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 653 }, { PROC_LINKS(command_documentation, 0), true, "command_documentation", 21, "Prompts the user to select a command then loads a doc buffer for that item", 74, "w:\\4ed\\code\\custom\\4coder_docs.cpp", 34, 190 }, @@ -360,7 +360,7 @@ static Command_Metadata fcoder_metacmd_table[243] = { { PROC_LINKS(list_all_locations_of_type_definition_of_identifier, 0), false, "list_all_locations_of_type_definition_of_identifier", 51, "Reads a token or word under the cursor and lists all locations of strings that appear to define a type whose name matches it.", 125, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 221 }, { PROC_LINKS(list_all_substring_locations, 0), false, "list_all_substring_locations", 28, "Queries the user for a string and lists all case-sensitive substring matches found in all open buffers.", 103, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 171 }, { PROC_LINKS(list_all_substring_locations_case_insensitive, 0), false, "list_all_substring_locations_case_insensitive", 45, "Queries the user for a string and lists all case-insensitive substring matches found in all open buffers.", 105, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 183 }, -{ PROC_LINKS(load_project, 0), false, "load_project", 12, "Looks for a project.4coder file in the current directory and tries to load it. Looks in parent directories until a project file is found or there are no more parents.", 167, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 862 }, +{ PROC_LINKS(load_project, 0), false, "load_project", 12, "Looks for a project.4coder file in the current directory and tries to load it. Looks in parent directories until a project file is found or there are no more parents.", 167, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 864 }, { PROC_LINKS(load_theme_current_buffer, 0), false, "load_theme_current_buffer", 25, "Parse the current buffer as a theme file and add the theme to the theme list. If the buffer has a .4coder postfix in it's name, it is removed when the name is saved.", 165, "w:\\4ed\\code\\custom\\4coder_config.cpp", 36, 1627 }, { PROC_LINKS(load_themes_default_folder, 0), false, "load_themes_default_folder", 26, "Loads all the theme files in the default theme folder.", 54, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 457 }, { PROC_LINKS(load_themes_hot_directory, 0), false, "load_themes_hot_directory", 25, "Loads all the theme files in the current hot directory.", 55, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 469 }, @@ -401,8 +401,8 @@ static Command_Metadata fcoder_metacmd_table[243] = { { PROC_LINKS(multi_paste, 0), false, "multi_paste", 11, "Paste multiple entries from the clipboard at once", 49, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 224 }, { PROC_LINKS(multi_paste_interactive, 0), false, "multi_paste_interactive", 23, "Paste multiple lines from the clipboard history, controlled with arrow keys", 75, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 366 }, { PROC_LINKS(multi_paste_interactive_quick, 0), false, "multi_paste_interactive_quick", 29, "Paste multiple lines from the clipboard history, controlled by inputing the number of lines to paste", 100, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 375 }, -{ PROC_LINKS(open_all_code, 0), false, "open_all_code", 13, "Open all code in the current directory. File types are determined by extensions. An extension is considered code based on the extensions specified in 4coder.config.", 164, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 848 }, -{ PROC_LINKS(open_all_code_recursive, 0), false, "open_all_code_recursive", 23, "Works as open_all_code but also runs in all subdirectories.", 59, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 854 }, +{ PROC_LINKS(open_all_code, 0), false, "open_all_code", 13, "Open all code in the current directory. File types are determined by extensions. An extension is considered code based on the extensions specified in 4coder.config.", 164, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 850 }, +{ PROC_LINKS(open_all_code_recursive, 0), false, "open_all_code_recursive", 23, "Works as open_all_code but also runs in all subdirectories.", 59, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 856 }, { PROC_LINKS(open_file_in_quotes, 0), false, "open_file_in_quotes", 19, "Reads a filename from surrounding '\"' characters and attempts to open the corresponding file.", 94, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1558 }, { PROC_LINKS(open_in_other, 0), false, "open_in_other", 13, "Interactively opens a file in the other panel.", 46, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1889 }, { PROC_LINKS(open_long_braces, 0), false, "open_long_braces", 16, "At the cursor, insert a '{' and '}' separated by a blank line.", 62, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 46 }, @@ -423,9 +423,9 @@ static Command_Metadata fcoder_metacmd_table[243] = { { PROC_LINKS(profile_disable, 0), false, "profile_disable", 15, "Prevent 4coder's self profiler from gathering new profiling information.", 72, "w:\\4ed\\code\\custom\\4coder_profile.cpp", 37, 219 }, { PROC_LINKS(profile_enable, 0), false, "profile_enable", 14, "Allow 4coder's self profiler to gather new profiling information.", 65, "w:\\4ed\\code\\custom\\4coder_profile.cpp", 37, 212 }, { PROC_LINKS(profile_inspect, 0), true, "profile_inspect", 15, "Inspect all currently collected profiling information in 4coder's self profiler.", 80, "w:\\4ed\\code\\custom\\4coder_profile_inspect.cpp", 45, 886 }, -{ PROC_LINKS(project_command_lister, 0), false, "project_command_lister", 22, "Open a lister of all commands in the currently loaded project.", 62, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1288 }, -{ PROC_LINKS(project_fkey_command, 0), false, "project_fkey_command", 20, "Run an 'fkey command' configured in a project.4coder file. Determines the index of the 'fkey command' by which function key or numeric key was pressed to trigger the command.", 175, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 870 }, -{ PROC_LINKS(project_go_to_root_directory, 0), false, "project_go_to_root_directory", 28, "Changes 4coder's hot directory to the root directory of the currently loaded project. With no loaded project nothing hapepns.", 125, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 896 }, +{ PROC_LINKS(project_command_lister, 0), false, "project_command_lister", 22, "Open a lister of all commands in the currently loaded project.", 62, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1290 }, +{ PROC_LINKS(project_fkey_command, 0), false, "project_fkey_command", 20, "Run an 'fkey command' configured in a project.4coder file. Determines the index of the 'fkey command' by which function key or numeric key was pressed to trigger the command.", 175, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 872 }, +{ PROC_LINKS(project_go_to_root_directory, 0), false, "project_go_to_root_directory", 28, "Changes 4coder's hot directory to the root directory of the currently loaded project. With no loaded project nothing hapepns.", 125, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 898 }, { PROC_LINKS(query_replace, 0), false, "query_replace", 13, "Queries the user for two strings, and incrementally replaces every occurence of the first string with the second string.", 120, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1249 }, { PROC_LINKS(query_replace_identifier, 0), false, "query_replace_identifier", 24, "Queries the user for a string, and incrementally replace every occurence of the word or token found at the cursor with the specified string.", 140, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1270 }, { PROC_LINKS(query_replace_selection, 0), false, "query_replace_selection", 23, "Queries the user for a string, and incrementally replace every occurence of the string found in the selected range with the specified string.", 141, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1286 }, @@ -463,10 +463,10 @@ static Command_Metadata fcoder_metacmd_table[243] = { { PROC_LINKS(set_mark, 0), false, "set_mark", 8, "Sets the mark to the current position of the cursor.", 52, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 115 }, { PROC_LINKS(set_mode_to_notepad_like, 0), false, "set_mode_to_notepad_like", 24, "Sets the edit mode to Notepad like.", 35, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 427 }, { PROC_LINKS(set_mode_to_original, 0), false, "set_mode_to_original", 20, "Sets the edit mode to 4coder original.", 38, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 421 }, -{ PROC_LINKS(setup_build_bat, 0), false, "setup_build_bat", 15, "Queries the user for several configuration options and initializes a new build batch script.", 92, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1237 }, -{ PROC_LINKS(setup_build_bat_and_sh, 0), false, "setup_build_bat_and_sh", 22, "Queries the user for several configuration options and initializes a new build batch script.", 92, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1249 }, -{ PROC_LINKS(setup_build_sh, 0), false, "setup_build_sh", 14, "Queries the user for several configuration options and initializes a new build shell script.", 92, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1243 }, -{ PROC_LINKS(setup_new_project, 0), false, "setup_new_project", 17, "Queries the user for several configuration options and initializes a new 4coder project with build scripts for every OS.", 120, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1230 }, +{ PROC_LINKS(setup_build_bat, 0), false, "setup_build_bat", 15, "Queries the user for several configuration options and initializes a new build batch script.", 92, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1239 }, +{ PROC_LINKS(setup_build_bat_and_sh, 0), false, "setup_build_bat_and_sh", 22, "Queries the user for several configuration options and initializes a new build batch script.", 92, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1251 }, +{ PROC_LINKS(setup_build_sh, 0), false, "setup_build_sh", 14, "Queries the user for several configuration options and initializes a new build shell script.", 92, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1245 }, +{ PROC_LINKS(setup_new_project, 0), false, "setup_new_project", 17, "Queries the user for several configuration options and initializes a new 4coder project with build scripts for every OS.", 120, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1232 }, { PROC_LINKS(show_filebar, 0), false, "show_filebar", 12, "Sets the current view to show it's filebar.", 43, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 676 }, { PROC_LINKS(show_scrollbar, 0), false, "show_scrollbar", 14, "Sets the current view to show it's scrollbar.", 45, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 662 }, { PROC_LINKS(show_the_log_graph, 0), true, "show_the_log_graph", 18, "Parses *log* and displays the 'log graph' UI", 44, "w:\\4ed\\code\\custom\\4coder_log_parser.cpp", 40, 993 }, diff --git a/ship_files/changes.txt b/ship_files/changes.txt index 69f7973d..73ef6695 100644 --- a/ship_files/changes.txt +++ b/ship_files/changes.txt @@ -5,7 +5,9 @@ + Fix: when generated/metadata* files are missing buildsuper still succeeds + Fix: mac does not hang opening multiple files + Fix: line number margin performance - + Fix: crash in notepade like mode when replacing a highlighted range in a parsed file + + Fix: no crash in notepade like mode when replacing a highlighted range in a parsed file + + Fix: no thread handle leak when closing a view + + Fix: no crash when a project file .cmd is not the right type 4.1.4 + MAJOR: The clipboard history is now a fully custom layer implemented system. Users maintaining a customization layer should try to update their call sites to the old clipboard API. #define FCODER_TRANSITION_TO 4001004 to disable the transitional function wrappers when you are ready to make the transition.