diff --git a/4coder_API/4coder_types.h b/4coder_API/4coder_types.h index 9967c4df..2ddae21f 100644 --- a/4coder_API/4coder_types.h +++ b/4coder_API/4coder_types.h @@ -1106,6 +1106,8 @@ ENUM(i32, Special_Hook_ID){ /* DOC(TODO) */ special_hook_end_file, /* DOC(TODO) */ + special_hook_file_edit_range, + /* DOC(TODO) */ special_hook_file_edit_finished, /* DOC(TODO) */ special_hook_command_caller, @@ -1137,6 +1139,9 @@ TYPEDEF_FUNC i32 Hook_Function(struct Application_Links *app); TYPEDEF_FUNC i32 Open_File_Hook_Function(struct Application_Links *app, Buffer_ID buffer_id); #define OPEN_FILE_HOOK_SIG(name) i32 name(struct Application_Links *app, Buffer_ID buffer_id) +TYPEDEF_FUNC i32 File_Edit_Range_Function(struct Application_Links *app, Buffer_ID buffer_id, Range range, String text); +#define FILE_EDIT_RANGE_SIG(name) i32 name(struct Application_Links *app, Buffer_ID buffer_id, Range range, String text) + TYPEDEF_FUNC i32 File_Edit_Finished_Function(struct Application_Links *app, Buffer_ID *buffer_ids, i32 buffer_id_count); #define FILE_EDIT_FINISHED_SIG(name) i32 name(struct Application_Links *app, Buffer_ID *buffer_ids, i32 buffer_id_count) diff --git a/4coder_default_hooks.cpp b/4coder_default_hooks.cpp index f4566a68..d2cb8436 100644 --- a/4coder_default_hooks.cpp +++ b/4coder_default_hooks.cpp @@ -1128,7 +1128,30 @@ OPEN_FILE_HOOK_SIG(default_file_save){ return(0); } -FILE_EDIT_FINISHED_SIG(default_file_edit){ +FILE_EDIT_RANGE_SIG(default_file_edit_range){ + Buffer_Summary buffer_summary = {}; + if (get_buffer_summary(app, buffer_id, AccessAll, &buffer_summary)){ + if (!match(make_string(buffer_summary.buffer_name, buffer_summary.buffer_name_len), make_lit_string("*messages*"))){ + char space[1024]; + String str = make_fixed_width_string(space); + append(&str, "'"); + append(&str, make_string(buffer_summary.buffer_name, buffer_summary.buffer_name_len)); + append(&str, "' ["); + append_int_to_str(&str, range.first); + append(&str, ", "); + append_int_to_str(&str, range.one_past_last); + append(&str, ") '"); + append(&str, substr(text, 0, 32)); + append(&str, "'\n"); + print_message(app, str.str, str.size); + } + } + + // no meaning for return + return(0); +} + +FILE_EDIT_FINISHED_SIG(default_file_edit_finished){ for (i32 i = 0; i < buffer_id_count; i += 1){ #if 0 // NOTE(allen|4.0.31): This code is example usage, it's not a particularly nice feature to actually have. @@ -1269,7 +1292,9 @@ set_all_default_hooks(Bind_Helper *context){ set_open_file_hook(context, default_file_settings); set_new_file_hook(context, default_new_file); set_save_file_hook(context, default_file_save); - set_file_edit_finished_hook(context, default_file_edit); + set_file_edit_range_hook(context, default_file_edit_range); + set_file_edit_finished_hook(context, default_file_edit_finished); + set_file_edit_range_hook(context, default_file_edit_range); set_end_file_hook(context, end_file_close_jump_list); diff --git a/4coder_helper.cpp b/4coder_helper.cpp index 7be01503..b1ccd23e 100644 --- a/4coder_helper.cpp +++ b/4coder_helper.cpp @@ -206,6 +206,15 @@ set_end_file_hook(Bind_Helper *helper, Open_File_Hook_Function *func){ write_unit(helper, unit); } +static void +set_file_edit_range_hook(Bind_Helper *helper, File_Edit_Range_Function *func){ + Binding_Unit unit = {}; + unit.type = unit_hook; + unit.hook.hook_id = special_hook_file_edit_range; + unit.hook.func = (void*)func; + write_unit(helper, unit); +} + static void set_file_edit_finished_hook(Bind_Helper *helper, File_Edit_Finished_Function *func){ Binding_Unit unit = {}; diff --git a/4ed.cpp b/4ed.cpp index 9d391c0c..a6d208b7 100644 --- a/4ed.cpp +++ b/4ed.cpp @@ -166,6 +166,7 @@ interpret_binding_buffer(Models *models, void *buffer, i32 size){ models->hook_new_file = 0; models->hook_save_file = 0; models->hook_end_file = 0; + models->hook_file_edit_range = 0; models->hook_file_edit_finished = 0; models->command_caller = 0; models->render_caller = 0; @@ -367,6 +368,11 @@ interpret_binding_buffer(Models *models, void *buffer, i32 size){ models->hook_end_file = (Open_File_Hook_Function*)unit->hook.func; }break; + case special_hook_file_edit_range: + { + models->hook_file_edit_range = (File_Edit_Range_Function*)unit->hook.func; + }break; + case special_hook_file_edit_finished: { models->hook_file_edit_finished = (File_Edit_Finished_Function*)unit->hook.func; diff --git a/4ed_app_models.h b/4ed_app_models.h index 464a2892..9e858c28 100644 --- a/4ed_app_models.h +++ b/4ed_app_models.h @@ -50,6 +50,7 @@ struct Models{ Open_File_Hook_Function *hook_new_file; Open_File_Hook_Function *hook_save_file; Open_File_Hook_Function *hook_end_file; + File_Edit_Range_Function *hook_file_edit_range; File_Edit_Finished_Function *hook_file_edit_finished; Command_Caller_Hook_Function *command_caller; Render_Caller_Function *render_caller; diff --git a/4ed_edit.cpp b/4ed_edit.cpp index 60956c07..a8dcefd8 100644 --- a/4ed_edit.cpp +++ b/4ed_edit.cpp @@ -90,9 +90,7 @@ edit_fix_markers__compute_scroll_y(i32 line_height, i32 old_y_val, f32 new_y_val } internal void -edit_fix_markers(System_Functions *system, Models *models, Editing_File *file, Edit_Array edits){ - Assert(edits.count > 0); - +edit_fix_markers(System_Functions *system, Models *models, Editing_File *file, Edit edit){ Partition *part = &models->mem.part; Layout *layout = &models->layout; @@ -162,15 +160,8 @@ edit_fix_markers(System_Functions *system, Models *models, Editing_File *file, E if (cursor_count > 0 || r_cursor_count > 0){ buffer_sort_cursors( cursors, cursor_count); buffer_sort_cursors(r_cursors, r_cursor_count); - if (edits.count > 1){ - buffer_batch_edit_update_cursors( cursors, cursor_count, edits, false); - buffer_batch_edit_update_cursors(r_cursors, r_cursor_count, edits, true); - } - else{ - Edit edit = edits.vals[0]; - buffer_update_cursors( cursors, cursor_count, edit.range.first, edit.range.one_past_last, edit.length, false); - buffer_update_cursors(r_cursors, r_cursor_count, edit.range.first, edit.range.one_past_last, edit.length, true); - } + buffer_update_cursors( cursors, cursor_count, edit.range.first, edit.range.one_past_last, edit.length, false); + buffer_update_cursors(r_cursors, r_cursor_count, edit.range.first, edit.range.one_past_last, edit.length, true); buffer_unsort_cursors( cursors, cursor_count); buffer_unsort_cursors(r_cursors, r_cursor_count); @@ -238,14 +229,6 @@ edit_fix_markers(System_Functions *system, Models *models, Editing_File *file, E end_temp_memory(cursor_temp); } -internal void -edit_fix_markers(System_Functions *system, Models *models, Editing_File *file, Edit edit){ - Edit_Array edits = {}; - edits.vals = &edit; - edits.count = 1; - edit_fix_markers(system, models, file, edits); -} - internal void edit_single(System_Functions *system, Models *models, Editing_File *file, Edit edit, Edit_Behaviors behaviors){ Mem_Options *mem = &models->mem; @@ -265,7 +248,12 @@ edit_single(System_Functions *system, Models *models, Editing_File *file, Edit e } // NOTE(allen): fixing stuff beforewards???? - edit_pre_state_change(system, &mem->heap, models, file); + edit_pre_state_change(system, heap, models, file); + + // NOTE(allen): edit range hook + if (models->hook_file_edit_range != 0){ + models->hook_file_edit_range(&models->app_links, file->id.id, edit.range, make_string(edit.str, edit.length)); + } // NOTE(allen): expand spec, compute shift i32 shift_amount = buffer_replace_range_compute_shift(edit.range.first, edit.range.one_past_last, edit.length); @@ -308,7 +296,7 @@ edit_single(System_Functions *system, Models *models, Editing_File *file, Edit e } // NOTE(allen): wrap meta data - file_measure_wraps(system, &models->mem, file, font); + file_measure_wraps(system, mem, file, font); // NOTE(allen): cursor fixing edit_fix_markers(system, models, file, edit); @@ -324,117 +312,12 @@ edit_single(System_Functions *system, Models *models, Editing_File *file, Edit e } } +// TODO(allen): this isn't "real" anymore, batch edits are now superseded a combination of other features, we should dump this someday internal void edit_batch(System_Functions *system, Models *models, Editing_File *file, Edit_Array edits, Edit_Behaviors behaviors){ - Mem_Options *mem = &models->mem; - Heap *heap = &mem->heap; - Partition *part = &mem->part; - - Gap_Buffer *buffer = &file->state.buffer; - Assert(edits.count > 0); - - // NOTE(allen): history update - if (!behaviors.do_not_post_to_history){ - history_dump_records_after_index(&file->state.history, file->state.current_record_index); - history_record_edit(heap, &models->global_history, &file->state.history, buffer, edits, behaviors.batch_type); - file->state.current_record_index = history_get_record_count(&file->state.history); - } - - // NOTE(allen): fixing stuff "beforewards"??? - edit_pre_state_change(system, &mem->heap, models, file); - - // NOTE(allen): actual text replacement - void *scratch = push_array(part, u8, 0); - i32 scratch_size = part_remaining(part); - Buffer_Batch_State state = {}; - i32 request_amount = 0; - for (;buffer_batch_edit_step(&state, buffer, edits, scratch, scratch_size, &request_amount);){ - void *new_data = 0; - if (request_amount > 0){ - new_data = heap_allocate(heap, request_amount); - } - void *old_data = buffer_edit_provide_memory(&file->state.buffer, new_data, request_amount); - if (old_data){ - heap_free(heap, old_data); - } - } - i32 shift_total = state.shift_total; - - // NOTE(allen): line meta data - // TODO(allen): Let's try to switch to remeasuring here moron! - file_measure_starts(heap, &file->state.buffer); - - Font_Pointers font = system->font.get_pointers_by_id(file->settings.font_id); - Assert(font.valid); - - file_allocate_character_starts_as_needed(heap, file); - buffer_measure_character_starts(system, font, &file->state.buffer, file->state.character_starts, 0, file->settings.virtual_white); - - // NOTE(allen): token fixing - switch (behaviors.batch_type){ - case BatchEdit_Normal: - { - if (file->settings.tokens_exist){ - // TODO(allen): Write a smart fast one here someday. - i32 start = edits.vals[0].range.first; - i32 end = edits.vals[edits.count - 1].range.one_past_last; - file_relex(system, models, file, start, end, shift_total); - } - else{ - file_mark_edit_finished(&models->working_set, file); - } - }break; - - case BatchEdit_PreserveTokens: - { - if (file->state.tokens_complete){ - Cpp_Token_Array tokens = file->state.token_array; - Cpp_Token *token = tokens.tokens; - Cpp_Token *end_token = tokens.tokens + tokens.count; - Cpp_Token original = {}; - - Edit *edit = edits.vals; - Edit *one_past_last_edit = edits.vals + edits.count; - - i32 shift_amount = 0; - i32 local_shift = 0; - - for (;token < end_token; ++token){ - original = *token; - for (;edit < one_past_last_edit && edit->range.first <= original.start; - ++edit){ - local_shift = (edit->length - (edit->range.one_past_last - edit->range.first)); - shift_amount += local_shift; - } - token->start += shift_amount; - local_shift = 0; - i32 original_end = original.start + original.size; - for (;edit < one_past_last_edit && edit->range.first < original_end; - ++edit){ - local_shift += (edit->length - (edit->range.one_past_last - edit->range.first)); - } - token->size += local_shift; - shift_amount += local_shift; - } - file_mark_edit_finished(&models->working_set, file); - } - }break; - } - - // NOTE(allen): wrap meta data - file_measure_wraps(system, &models->mem, file, font); - - // NOTE(allen): cursor fixing - edit_fix_markers(system, models, file, edits); - - // NOTE(allen): mark edit finished - if (file->settings.tokens_exist){ - if (file->settings.virtual_white){ - file_mark_edit_finished(&models->working_set, file); - } - } - else{ - file_mark_edit_finished(&models->working_set, file); + Edit *edit = edits.vals; + for (i32 i = 0; i < edits.count; i += 1, edit += 1){ + edit_single(system, models, file, *edit, behaviors); } }