Basics of new history system working:
This commit is contained in:
parent
d0eb652ab1
commit
0482cd05fe
|
@ -561,18 +561,6 @@ STRUCT Partial_Cursor{
|
|||
int32_t character;
|
||||
};
|
||||
|
||||
/* DOC(Buffer_Edit describes a range of a buffer and string to replace that range. A Buffer_Edit has to be paired with a string that contains the actual text that will be replaced into the buffer.) */
|
||||
STRUCT Buffer_Edit{
|
||||
/* DOC(The str_start field specifies the first character in the accompanying string that corresponds with this edit.) */
|
||||
int32_t str_start;
|
||||
/* DOC(The len field specifies the length of the string being written into the buffer.) */
|
||||
int32_t len;
|
||||
/* DOC(The start field specifies the start of the range in the buffer to replace in absolute position.) */
|
||||
int32_t start;
|
||||
/* DOC(The end field specifies one past the end of the range in the buffer to replace in absolute position.) */
|
||||
int32_t end;
|
||||
};
|
||||
|
||||
/* DOC(Buffer_Summary acts as a handle to a buffer and describes the state of the buffer.)
|
||||
DOC_SEE(Access_Flag)
|
||||
DOC_SEE(Dirty_State) */
|
||||
|
@ -981,8 +969,22 @@ ENUM(int32_t, Buffer_Batch_Edit_Type){
|
|||
BatchEdit_PreserveTokens
|
||||
};
|
||||
|
||||
/* DOC(Buffer_Edit describes a range of a buffer and string to replace that range. A Buffer_Edit has to be paired with a string that contains the actual
|
||||
text that will be replaced into the buffer.) */
|
||||
STRUCT Buffer_Edit{
|
||||
/* DOC(The str_start field specifies the first character in the accompanying string that corresponds with this edit.) */
|
||||
int32_t str_start;
|
||||
/* DOC(The len field specifies the length of the string being written into the buffer.) */
|
||||
int32_t len;
|
||||
/* DOC(The start field specifies the start of the range in the buffer to replace in absolute position.) */
|
||||
int32_t start;
|
||||
/* DOC(The end field specifies one past the end of the range in the buffer to replace in absolute position.) */
|
||||
int32_t end;
|
||||
};
|
||||
|
||||
/*
|
||||
DOC(This struct is used to bundle the parameters of the buffer_batch_edit function. It is convenient for a few functions that return a batch edit to the user.)
|
||||
DOC_SEE(Buffer_Edit)
|
||||
DOC_SEE(buffer_batch_edit)
|
||||
*/
|
||||
STRUCT Buffer_Batch_Edit{
|
||||
|
@ -997,6 +999,17 @@ STRUCT Buffer_Batch_Edit{
|
|||
int32_t edit_count;
|
||||
};
|
||||
|
||||
ENUM(int32_t, Record_Kind){
|
||||
RecordKind_Single,
|
||||
RecordKind_Batch,
|
||||
RecordKind_Group,
|
||||
};
|
||||
|
||||
TYPEDEF int32_t History_Record_Index;
|
||||
|
||||
STRUCT Record_Data{
|
||||
|
||||
};
|
||||
|
||||
/* DOC(Custom_Command_Function is a function type which matches the signature used for commands. To declare a command use CUSTOM_COMMAND_SIG.) DOC_SEE(CUSTOM_COMMAND_SIG) */
|
||||
TYPEDEF void Custom_Command_Function(struct Application_Links *app);
|
||||
|
|
|
@ -1582,23 +1582,26 @@ CUSTOM_DOC("Reopen the current buffer from the hard drive.")
|
|||
CUSTOM_COMMAND_SIG(undo)
|
||||
CUSTOM_DOC("Advances backwards through the undo history.")
|
||||
{
|
||||
// TODO(allen): // TODO(allen): // TODO(allen): // TODO(allen): // TODO(allen):
|
||||
// TODO(allen): // TODO(allen): // TODO(allen): // TODO(allen): // TODO(allen):
|
||||
// TODO(allen): // TODO(allen): // TODO(allen): // TODO(allen): // TODO(allen):
|
||||
// TODO(allen): // TODO(allen): // TODO(allen): // TODO(allen): // TODO(allen):
|
||||
// TODO(allen): // TODO(allen): // TODO(allen): // TODO(allen): // TODO(allen):
|
||||
// re-implement undo
|
||||
View_Summary view = get_active_view(app, AccessOpen);
|
||||
Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessOpen);
|
||||
History_Record_Index current = buffer_history_get_current_state_index(app, &buffer);
|
||||
if (current > 0){
|
||||
current -= 1;
|
||||
buffer_history_set_current_state_index(app, &buffer, current);
|
||||
}
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(redo)
|
||||
CUSTOM_DOC("Advances forewards through the undo history.")
|
||||
CUSTOM_DOC("Advances forwards through the undo history.")
|
||||
{
|
||||
// TODO(allen): // TODO(allen): // TODO(allen): // TODO(allen): // TODO(allen):
|
||||
// TODO(allen): // TODO(allen): // TODO(allen): // TODO(allen): // TODO(allen):
|
||||
// TODO(allen): // TODO(allen): // TODO(allen): // TODO(allen): // TODO(allen):
|
||||
// TODO(allen): // TODO(allen): // TODO(allen): // TODO(allen): // TODO(allen):
|
||||
// TODO(allen): // TODO(allen): // TODO(allen): // TODO(allen): // TODO(allen):
|
||||
// re-implement redo
|
||||
View_Summary view = get_active_view(app, AccessOpen);
|
||||
Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessOpen);
|
||||
History_Record_Index current = buffer_history_get_current_state_index(app, &buffer);
|
||||
History_Record_Index max_index = buffer_history_newest_record_index(app, &buffer);
|
||||
if (current < max_index){
|
||||
current += 1;
|
||||
buffer_history_set_current_state_index(app, &buffer, current);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
|
|
|
@ -95,6 +95,16 @@ struct Application_Links;
|
|||
#define GET_LARGEST_FACE_ID_SIG(n) Face_ID n(Application_Links *app)
|
||||
#define SET_GLOBAL_FACE_SIG(n) bool32 n(Application_Links *app, Face_ID id, bool32 apply_to_all_buffers)
|
||||
#define BUFFER_SET_FACE_SIG(n) bool32 n(Application_Links *app, Buffer_Summary *buffer, Face_ID id)
|
||||
#define BUFFER_HISTORY_NEWEST_RECORD_INDEX_SIG(n) History_Record_Index n(Application_Links *app, Buffer_Summary *buffer)
|
||||
#define BUFFER_HISTORY_GET_RECORD_SIG(n) Record_Data n(Application_Links *app, Buffer_Summary *buffer, History_Record_Index record)
|
||||
#define BUFFER_HISTORY_GET_CURRENT_STATE_INDEX_SIG(n) History_Record_Index n(Application_Links *app, Buffer_Summary *buffer)
|
||||
#define BUFFER_HISTORY_SET_CURRENT_STATE_INDEX_SIG(n) bool32 n(Application_Links *app, Buffer_Summary *buffer, History_Record_Index index)
|
||||
#define BUFFER_HISTORY_MERGE_RECORDS_BETWEEN_STATES_SIG(n) bool32 n(Application_Links *app, Buffer_Summary *buffer, History_Record_Index first_index, History_Record_Index last_index)
|
||||
#define BUFFER_HISTORY_SPLIT_GROUP_RECORD_SIG(n) bool32 n(Application_Links *app, Buffer_Summary *buffer, History_Record_Index record_index, int32_t sub_record_index)
|
||||
#define BUFFER_HISTORY_SPLIT_SINGLE_RECORD_SIG(n) bool32 n(Application_Links *app, Buffer_Summary *buffer, History_Record_Index record_index, int32_t forward_str_split, int32_t backward_str_split)
|
||||
#define BUFFER_HISTORY_CLEAR_AFTER_UNDO_POSITION_SIG(n) bool32 n(Application_Links *app, Buffer_Summary *buffer)
|
||||
#define GLOBAL_HISTORY_EDIT_GROUP_BEGIN_SIG(n) void n(Application_Links *app)
|
||||
#define GLOBAL_HISTORY_EDIT_GROUP_END_SIG(n) void n(Application_Links *app)
|
||||
#define GET_FACE_DESCRIPTION_SIG(n) Face_Description n(Application_Links *app, Face_ID id)
|
||||
#define GET_FACE_ID_SIG(n) Face_ID n(Application_Links *app, Buffer_Summary *buffer)
|
||||
#define TRY_CREATE_NEW_FACE_SIG(n) Face_ID n(Application_Links *app, Face_Description *description)
|
||||
|
@ -222,6 +232,16 @@ typedef CHANGE_THEME_BY_INDEX_SIG(Change_Theme_By_Index_Function);
|
|||
typedef GET_LARGEST_FACE_ID_SIG(Get_Largest_Face_ID_Function);
|
||||
typedef SET_GLOBAL_FACE_SIG(Set_Global_Face_Function);
|
||||
typedef BUFFER_SET_FACE_SIG(Buffer_Set_Face_Function);
|
||||
typedef BUFFER_HISTORY_NEWEST_RECORD_INDEX_SIG(Buffer_History_Newest_Record_Index_Function);
|
||||
typedef BUFFER_HISTORY_GET_RECORD_SIG(Buffer_History_Get_Record_Function);
|
||||
typedef BUFFER_HISTORY_GET_CURRENT_STATE_INDEX_SIG(Buffer_History_Get_Current_State_Index_Function);
|
||||
typedef BUFFER_HISTORY_SET_CURRENT_STATE_INDEX_SIG(Buffer_History_Set_Current_State_Index_Function);
|
||||
typedef BUFFER_HISTORY_MERGE_RECORDS_BETWEEN_STATES_SIG(Buffer_History_Merge_Records_Between_States_Function);
|
||||
typedef BUFFER_HISTORY_SPLIT_GROUP_RECORD_SIG(Buffer_History_Split_Group_Record_Function);
|
||||
typedef BUFFER_HISTORY_SPLIT_SINGLE_RECORD_SIG(Buffer_History_Split_Single_Record_Function);
|
||||
typedef BUFFER_HISTORY_CLEAR_AFTER_UNDO_POSITION_SIG(Buffer_History_Clear_After_Undo_Position_Function);
|
||||
typedef GLOBAL_HISTORY_EDIT_GROUP_BEGIN_SIG(Global_History_Edit_Group_Begin_Function);
|
||||
typedef GLOBAL_HISTORY_EDIT_GROUP_END_SIG(Global_History_Edit_Group_End_Function);
|
||||
typedef GET_FACE_DESCRIPTION_SIG(Get_Face_Description_Function);
|
||||
typedef GET_FACE_ID_SIG(Get_Face_ID_Function);
|
||||
typedef TRY_CREATE_NEW_FACE_SIG(Try_Create_New_Face_Function);
|
||||
|
@ -351,6 +371,16 @@ Change_Theme_By_Index_Function *change_theme_by_index;
|
|||
Get_Largest_Face_ID_Function *get_largest_face_id;
|
||||
Set_Global_Face_Function *set_global_face;
|
||||
Buffer_Set_Face_Function *buffer_set_face;
|
||||
Buffer_History_Newest_Record_Index_Function *buffer_history_newest_record_index;
|
||||
Buffer_History_Get_Record_Function *buffer_history_get_record;
|
||||
Buffer_History_Get_Current_State_Index_Function *buffer_history_get_current_state_index;
|
||||
Buffer_History_Set_Current_State_Index_Function *buffer_history_set_current_state_index;
|
||||
Buffer_History_Merge_Records_Between_States_Function *buffer_history_merge_records_between_states;
|
||||
Buffer_History_Split_Group_Record_Function *buffer_history_split_group_record;
|
||||
Buffer_History_Split_Single_Record_Function *buffer_history_split_single_record;
|
||||
Buffer_History_Clear_After_Undo_Position_Function *buffer_history_clear_after_undo_position;
|
||||
Global_History_Edit_Group_Begin_Function *global_history_edit_group_begin;
|
||||
Global_History_Edit_Group_End_Function *global_history_edit_group_end;
|
||||
Get_Face_Description_Function *get_face_description;
|
||||
Get_Face_ID_Function *get_face_id;
|
||||
Try_Create_New_Face_Function *try_create_new_face;
|
||||
|
@ -479,6 +509,16 @@ Change_Theme_By_Index_Function *change_theme_by_index_;
|
|||
Get_Largest_Face_ID_Function *get_largest_face_id_;
|
||||
Set_Global_Face_Function *set_global_face_;
|
||||
Buffer_Set_Face_Function *buffer_set_face_;
|
||||
Buffer_History_Newest_Record_Index_Function *buffer_history_newest_record_index_;
|
||||
Buffer_History_Get_Record_Function *buffer_history_get_record_;
|
||||
Buffer_History_Get_Current_State_Index_Function *buffer_history_get_current_state_index_;
|
||||
Buffer_History_Set_Current_State_Index_Function *buffer_history_set_current_state_index_;
|
||||
Buffer_History_Merge_Records_Between_States_Function *buffer_history_merge_records_between_states_;
|
||||
Buffer_History_Split_Group_Record_Function *buffer_history_split_group_record_;
|
||||
Buffer_History_Split_Single_Record_Function *buffer_history_split_single_record_;
|
||||
Buffer_History_Clear_After_Undo_Position_Function *buffer_history_clear_after_undo_position_;
|
||||
Global_History_Edit_Group_Begin_Function *global_history_edit_group_begin_;
|
||||
Global_History_Edit_Group_End_Function *global_history_edit_group_end_;
|
||||
Get_Face_Description_Function *get_face_description_;
|
||||
Get_Face_ID_Function *get_face_id_;
|
||||
Try_Create_New_Face_Function *try_create_new_face_;
|
||||
|
@ -615,6 +655,16 @@ app_links->change_theme_by_index_ = Change_Theme_By_Index;\
|
|||
app_links->get_largest_face_id_ = Get_Largest_Face_ID;\
|
||||
app_links->set_global_face_ = Set_Global_Face;\
|
||||
app_links->buffer_set_face_ = Buffer_Set_Face;\
|
||||
app_links->buffer_history_newest_record_index_ = Buffer_History_Newest_Record_Index;\
|
||||
app_links->buffer_history_get_record_ = Buffer_History_Get_Record;\
|
||||
app_links->buffer_history_get_current_state_index_ = Buffer_History_Get_Current_State_Index;\
|
||||
app_links->buffer_history_set_current_state_index_ = Buffer_History_Set_Current_State_Index;\
|
||||
app_links->buffer_history_merge_records_between_states_ = Buffer_History_Merge_Records_Between_States;\
|
||||
app_links->buffer_history_split_group_record_ = Buffer_History_Split_Group_Record;\
|
||||
app_links->buffer_history_split_single_record_ = Buffer_History_Split_Single_Record;\
|
||||
app_links->buffer_history_clear_after_undo_position_ = Buffer_History_Clear_After_Undo_Position;\
|
||||
app_links->global_history_edit_group_begin_ = Global_History_Edit_Group_Begin;\
|
||||
app_links->global_history_edit_group_end_ = Global_History_Edit_Group_End;\
|
||||
app_links->get_face_description_ = Get_Face_Description;\
|
||||
app_links->get_face_id_ = Get_Face_ID;\
|
||||
app_links->try_create_new_face_ = Try_Create_New_Face;\
|
||||
|
@ -743,6 +793,16 @@ static bool32 change_theme_by_index(Application_Links *app, int32_t index){retur
|
|||
static Face_ID get_largest_face_id(Application_Links *app){return(app->get_largest_face_id(app));}
|
||||
static bool32 set_global_face(Application_Links *app, Face_ID id, bool32 apply_to_all_buffers){return(app->set_global_face(app, id, apply_to_all_buffers));}
|
||||
static bool32 buffer_set_face(Application_Links *app, Buffer_Summary *buffer, Face_ID id){return(app->buffer_set_face(app, buffer, id));}
|
||||
static History_Record_Index buffer_history_newest_record_index(Application_Links *app, Buffer_Summary *buffer){return(app->buffer_history_newest_record_index(app, buffer));}
|
||||
static Record_Data buffer_history_get_record(Application_Links *app, Buffer_Summary *buffer, History_Record_Index record){return(app->buffer_history_get_record(app, buffer, record));}
|
||||
static History_Record_Index buffer_history_get_current_state_index(Application_Links *app, Buffer_Summary *buffer){return(app->buffer_history_get_current_state_index(app, buffer));}
|
||||
static bool32 buffer_history_set_current_state_index(Application_Links *app, Buffer_Summary *buffer, History_Record_Index index){return(app->buffer_history_set_current_state_index(app, buffer, index));}
|
||||
static bool32 buffer_history_merge_records_between_states(Application_Links *app, Buffer_Summary *buffer, History_Record_Index first_index, History_Record_Index last_index){return(app->buffer_history_merge_records_between_states(app, buffer, first_index, last_index));}
|
||||
static bool32 buffer_history_split_group_record(Application_Links *app, Buffer_Summary *buffer, History_Record_Index record_index, int32_t sub_record_index){return(app->buffer_history_split_group_record(app, buffer, record_index, sub_record_index));}
|
||||
static bool32 buffer_history_split_single_record(Application_Links *app, Buffer_Summary *buffer, History_Record_Index record_index, int32_t forward_str_split, int32_t backward_str_split){return(app->buffer_history_split_single_record(app, buffer, record_index, forward_str_split, backward_str_split));}
|
||||
static bool32 buffer_history_clear_after_undo_position(Application_Links *app, Buffer_Summary *buffer){return(app->buffer_history_clear_after_undo_position(app, buffer));}
|
||||
static void global_history_edit_group_begin(Application_Links *app){(app->global_history_edit_group_begin(app));}
|
||||
static void global_history_edit_group_end(Application_Links *app){(app->global_history_edit_group_end(app));}
|
||||
static Face_Description get_face_description(Application_Links *app, Face_ID id){return(app->get_face_description(app, id));}
|
||||
static Face_ID get_face_id(Application_Links *app, Buffer_Summary *buffer){return(app->get_face_id(app, buffer));}
|
||||
static Face_ID try_create_new_face(Application_Links *app, Face_Description *description){return(app->try_create_new_face(app, description));}
|
||||
|
@ -871,6 +931,16 @@ static bool32 change_theme_by_index(Application_Links *app, int32_t index){retur
|
|||
static Face_ID get_largest_face_id(Application_Links *app){return(app->get_largest_face_id_(app));}
|
||||
static bool32 set_global_face(Application_Links *app, Face_ID id, bool32 apply_to_all_buffers){return(app->set_global_face_(app, id, apply_to_all_buffers));}
|
||||
static bool32 buffer_set_face(Application_Links *app, Buffer_Summary *buffer, Face_ID id){return(app->buffer_set_face_(app, buffer, id));}
|
||||
static History_Record_Index buffer_history_newest_record_index(Application_Links *app, Buffer_Summary *buffer){return(app->buffer_history_newest_record_index_(app, buffer));}
|
||||
static Record_Data buffer_history_get_record(Application_Links *app, Buffer_Summary *buffer, History_Record_Index record){return(app->buffer_history_get_record_(app, buffer, record));}
|
||||
static History_Record_Index buffer_history_get_current_state_index(Application_Links *app, Buffer_Summary *buffer){return(app->buffer_history_get_current_state_index_(app, buffer));}
|
||||
static bool32 buffer_history_set_current_state_index(Application_Links *app, Buffer_Summary *buffer, History_Record_Index index){return(app->buffer_history_set_current_state_index_(app, buffer, index));}
|
||||
static bool32 buffer_history_merge_records_between_states(Application_Links *app, Buffer_Summary *buffer, History_Record_Index first_index, History_Record_Index last_index){return(app->buffer_history_merge_records_between_states_(app, buffer, first_index, last_index));}
|
||||
static bool32 buffer_history_split_group_record(Application_Links *app, Buffer_Summary *buffer, History_Record_Index record_index, int32_t sub_record_index){return(app->buffer_history_split_group_record_(app, buffer, record_index, sub_record_index));}
|
||||
static bool32 buffer_history_split_single_record(Application_Links *app, Buffer_Summary *buffer, History_Record_Index record_index, int32_t forward_str_split, int32_t backward_str_split){return(app->buffer_history_split_single_record_(app, buffer, record_index, forward_str_split, backward_str_split));}
|
||||
static bool32 buffer_history_clear_after_undo_position(Application_Links *app, Buffer_Summary *buffer){return(app->buffer_history_clear_after_undo_position_(app, buffer));}
|
||||
static void global_history_edit_group_begin(Application_Links *app){(app->global_history_edit_group_begin_(app));}
|
||||
static void global_history_edit_group_end(Application_Links *app){(app->global_history_edit_group_end_(app));}
|
||||
static Face_Description get_face_description(Application_Links *app, Face_ID id){return(app->get_face_description_(app, id));}
|
||||
static Face_ID get_face_id(Application_Links *app, Buffer_Summary *buffer){return(app->get_face_id_(app, buffer));}
|
||||
static Face_ID try_create_new_face(Application_Links *app, Face_Description *description){return(app->try_create_new_face_(app, description));}
|
||||
|
|
|
@ -364,7 +364,7 @@ static Command_Metadata fcoder_metacmd_table[220] = {
|
|||
{ PROC_LINKS(open_all_code_recursive, 0), "open_all_code_recursive", 23, "Works as open_all_code but also runs in all subdirectories.", 59, "w:\\4ed\\code\\4coder_project_commands.cpp", 39, 1074 },
|
||||
{ PROC_LINKS(open_color_tweaker, 0), "open_color_tweaker", 18, "Opens the 4coder theme selector list.", 37, "w:\\4ed\\code\\4coder_lists.cpp", 28, 938 },
|
||||
{ PROC_LINKS(open_file_in_quotes, 0), "open_file_in_quotes", 19, "Reads a filename from surrounding '\"' characters and attempts to open the corresponding file.", 94, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1464 },
|
||||
{ PROC_LINKS(open_in_other, 0), "open_in_other", 13, "Interactively opens a file in the other panel.", 46, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1629 },
|
||||
{ PROC_LINKS(open_in_other, 0), "open_in_other", 13, "Interactively opens a file in the other panel.", 46, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1632 },
|
||||
{ PROC_LINKS(open_long_braces, 0), "open_long_braces", 16, "At the cursor, insert a '{' and '}' separated by a blank line.", 62, "w:\\4ed\\code\\4coder_combined_write_commands.cpp", 46, 55 },
|
||||
{ PROC_LINKS(open_long_braces_break, 0), "open_long_braces_break", 22, "At the cursor, insert a '{' and '}break;' separated by a blank line.", 68, "w:\\4ed\\code\\4coder_combined_write_commands.cpp", 46, 71 },
|
||||
{ PROC_LINKS(open_long_braces_semicolon, 0), "open_long_braces_semicolon", 26, "At the cursor, insert a '{' and '};' separated by a blank line.", 63, "w:\\4ed\\code\\4coder_combined_write_commands.cpp", 46, 63 },
|
||||
|
@ -384,8 +384,8 @@ static Command_Metadata fcoder_metacmd_table[220] = {
|
|||
{ PROC_LINKS(query_replace, 0), "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\\4coder_base_commands.cpp", 36, 1019 },
|
||||
{ PROC_LINKS(query_replace_identifier, 0), "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\\4coder_base_commands.cpp", 36, 1043 },
|
||||
{ PROC_LINKS(query_replace_selection, 0), "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\\4coder_base_commands.cpp", 36, 1061 },
|
||||
{ PROC_LINKS(redo, 0), "redo", 4, "Advances forewards through the undo history.", 44, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1593 },
|
||||
{ PROC_LINKS(reload_themes, 0), "reload_themes", 13, "Loads all the theme files in the theme folder, replacing duplicates with the new theme data.", 92, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1606 },
|
||||
{ PROC_LINKS(redo, 0), "redo", 4, "Advances forwards through the undo history.", 43, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1594 },
|
||||
{ PROC_LINKS(reload_themes, 0), "reload_themes", 13, "Loads all the theme files in the theme folder, replacing duplicates with the new theme data.", 92, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1609 },
|
||||
{ PROC_LINKS(remap_interactive, 0), "remap_interactive", 17, "Switch to a named key binding map.", 34, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 290 },
|
||||
{ PROC_LINKS(rename_file_query, 0), "rename_file_query", 17, "Queries the user for a new name and renames the file of the current buffer, altering the buffer's name too.", 107, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1201 },
|
||||
{ PROC_LINKS(reopen, 0), "reopen", 6, "Reopen the current buffer from the hard drive.", 46, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1572 },
|
||||
|
|
|
@ -236,6 +236,23 @@ end_temp_memory(Temp_Memory_Arena temp){
|
|||
}
|
||||
}
|
||||
|
||||
static Temp_Memory_Arena_Light
|
||||
temp_memory_light(Temp_Memory_Arena temp){
|
||||
Temp_Memory_Arena_Light light = {};
|
||||
light.part = temp.part;
|
||||
light.pos = temp.pos;
|
||||
return(light);
|
||||
}
|
||||
|
||||
static void
|
||||
end_temp_memory(Arena *arena, Temp_Memory_Arena_Light temp){
|
||||
Temp_Memory_Arena full_temp = {};
|
||||
full_temp.arena = arena;
|
||||
full_temp.part = temp.part;
|
||||
full_temp.pos = temp.pos;
|
||||
end_temp_memory(full_temp);
|
||||
}
|
||||
|
||||
static void*
|
||||
push_allocator_allocate(Arena *arena, i32_4tech size){
|
||||
return(arena_allocate(arena, size));
|
||||
|
|
|
@ -75,6 +75,11 @@ struct Temp_Memory_Arena{
|
|||
i32_4tech pos;
|
||||
};
|
||||
|
||||
struct Temp_Memory_Arena_Light{
|
||||
Partition_Chained *part;
|
||||
i32_4tech pos;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
12
4ed.cpp
12
4ed.cpp
|
@ -58,7 +58,14 @@ internal void
|
|||
output_file_append(System_Functions *system, Models *models, Editing_File *file, String value){
|
||||
if (!file->is_dummy){
|
||||
i32 end = buffer_size(&file->state.buffer);
|
||||
edit_single(system, models, file, end, end, value.str, value.size);
|
||||
Edit edit = {};
|
||||
edit.str = value.str;
|
||||
edit.length = value.size;
|
||||
edit.range.first = end;
|
||||
edit.range.one_past_last = end;
|
||||
|
||||
Edit_Behaviors behaviors = {};
|
||||
edit_single(system, models, file, edit, behaviors);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -834,6 +841,9 @@ App_Init_Sig(app_init){
|
|||
models->working_set.default_display_width = DEFAULT_DISPLAY_WIDTH;
|
||||
models->working_set.default_minimum_base_display_width = DEFAULT_MINIMUM_BASE_DISPLAY_WIDTH;
|
||||
|
||||
// NOTE(allen): history setup
|
||||
global_history_init(&models->global_history);
|
||||
|
||||
// NOTE(allen): clipboard setup
|
||||
models->working_set.clipboard_max_size = ArrayCount(models->working_set.clipboards);
|
||||
models->working_set.clipboard_size = 0;
|
||||
|
|
|
@ -646,8 +646,14 @@ DOC_SEE(4coder_Buffer_Positioning_System)
|
|||
if (file != 0){
|
||||
size = buffer_size(&file->state.buffer);
|
||||
if (0 <= start && start <= end && end <= size){
|
||||
Edit edit = {};
|
||||
edit.str = str;
|
||||
edit.length = len;
|
||||
edit.range.first = start;
|
||||
edit.range.one_past_last = end;
|
||||
Edit_Behaviors behaviors = {};
|
||||
edit_single(models->system, models, file, edit, behaviors);
|
||||
result = true;
|
||||
edit_single(models->system, models, file, start, end, str, len);
|
||||
}
|
||||
fill_buffer_summary(buffer, file, &models->working_set);
|
||||
}
|
||||
|
@ -704,13 +710,22 @@ DOC_SEE(Buffer_Batch_Edit_Type)
|
|||
if (file != 0){
|
||||
if (edit_count > 0){
|
||||
Temp_Memory temp = begin_temp_memory(part);
|
||||
Buffer_Edit *inverse_edits = push_array(part, Buffer_Edit, edit_count);
|
||||
Assert(inverse_edits != 0);
|
||||
char *inv_str = (char*)part->base + part->pos;
|
||||
int32_t inv_str_max = part->max - part->pos;
|
||||
Edit_Spec spec = edit_compute_batch_spec(&mem->heap, file, edits, str, str_len,
|
||||
inverse_edits, inv_str, inv_str_max, edit_count, type);
|
||||
edit_batch(system, models, file, spec, hist_normal, type);
|
||||
Edit_Array real_edits = {};
|
||||
real_edits.vals = push_array(part, Edit, edit_count);
|
||||
real_edits.count = edit_count;
|
||||
Edit *edit_out = real_edits.vals;
|
||||
Buffer_Edit *edit_in = edits;
|
||||
Edit *one_past_last_edit_out = real_edits.vals + edit_count;
|
||||
for (;edit_out < one_past_last_edit_out;
|
||||
edit_out += 1, edit_in += 1){
|
||||
edit_out->str = str + edit_in->str_start;
|
||||
edit_out->length = edit_in->len;
|
||||
edit_out->range.first = edit_in->start;
|
||||
edit_out->range.one_past_last = edit_in->end;
|
||||
}
|
||||
Edit_Behaviors behaviors = {};
|
||||
behaviors.batch_type = type;
|
||||
edit_batch(system, models, file, real_edits, behaviors);
|
||||
end_temp_memory(temp);
|
||||
}
|
||||
result = true;
|
||||
|
@ -1224,7 +1239,10 @@ DOC_SEE(Buffer_Create_Flag)
|
|||
if (file != 0 && (flags & BufferCreate_AlwaysNew) != 0){
|
||||
i32 size = buffer_size(&file->state.buffer);
|
||||
if (size > 0){
|
||||
edit_single(system, models, file, 0, size, 0, 0);
|
||||
Edit edit = {};
|
||||
edit.range.one_past_last = size;
|
||||
Edit_Behaviors behaviors = {};
|
||||
edit_single(system, models, file, edit, behaviors);
|
||||
if (has_canon_name){
|
||||
buffer_is_for_new_file = true;
|
||||
}
|
||||
|
@ -1315,7 +1333,7 @@ DOC_SEE(Buffer_Identifier)
|
|||
if (file->canon.name.size != 0){
|
||||
buffer_unbind_file(system, working_set, file);
|
||||
}
|
||||
file_free(system, &models->app_links, &models->mem.heap, &models->lifetime_allocator, file);
|
||||
file_free(system, &models->mem.heap, &models->lifetime_allocator, file);
|
||||
working_set_free_file(&models->mem.heap, working_set, file);
|
||||
|
||||
Layout *layout = &models->layout;
|
||||
|
@ -1397,7 +1415,7 @@ Reopen_Buffer(Application_Links *app, Buffer_Summary *buffer, Buffer_Reopen_Flag
|
|||
++vptr_count;
|
||||
}
|
||||
|
||||
file_free(system, &models->app_links, &models->mem.heap, &models->lifetime_allocator, file);
|
||||
file_free(system, &models->mem.heap, &models->lifetime_allocator, file);
|
||||
working_set_file_default_settings(&models->working_set, file);
|
||||
init_normal_file(system, models, file_memory, size, file);
|
||||
|
||||
|
@ -2526,7 +2544,7 @@ DOC(Managed objects allocate memory that is tied to the scope. When the scope i
|
|||
Managed_Object result = 0;
|
||||
if (workspace != 0){
|
||||
int32_t size = count*item_size;
|
||||
void *ptr = dynamic_memory_bank_allocate(heap, &workspace->mem_bank, size + sizeof(Managed_Memory_Header));
|
||||
void *ptr = memory_bank_allocate(heap, &workspace->mem_bank, size + sizeof(Managed_Memory_Header));
|
||||
Managed_Memory_Header *header = (Managed_Memory_Header*)ptr;
|
||||
header->std_header.type = ManagedObjectType_Memory;
|
||||
header->std_header.item_size = item_size;
|
||||
|
@ -2563,7 +2581,7 @@ DOC_SEE(Marker)
|
|||
Managed_Object result = 0;
|
||||
if (workspace != 0){
|
||||
i32 size = count*sizeof(Marker);
|
||||
void *ptr = dynamic_memory_bank_allocate(heap, &workspace->mem_bank, size + sizeof(Managed_Buffer_Markers_Header));
|
||||
void *ptr = memory_bank_allocate(heap, &workspace->mem_bank, size + sizeof(Managed_Buffer_Markers_Header));
|
||||
Managed_Buffer_Markers_Header *header = (Managed_Buffer_Markers_Header*)ptr;
|
||||
header->std_header.type = ManagedObjectType_Markers;
|
||||
header->std_header.item_size = sizeof(Marker);
|
||||
|
@ -2907,7 +2925,7 @@ DOC(Permanently frees the specified object. Not only does this free up the memo
|
|||
workspace->buffer_markers_list.count -= 1;
|
||||
}
|
||||
dynamic_workspace_erase_pointer(workspace, lo_id);
|
||||
dynamic_memory_bank_free(&workspace->mem_bank, object_ptr);
|
||||
memory_bank_free(&workspace->mem_bank, object_ptr);
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
|
@ -3291,6 +3309,84 @@ DOC_RETURN(Returns true if the given id was a valid face and the change was made
|
|||
return(did_change);
|
||||
}
|
||||
|
||||
API_EXPORT History_Record_Index
|
||||
Buffer_History_Newest_Record_Index(Application_Links *app, Buffer_Summary *buffer){
|
||||
Models *models = (Models*)app->cmd_context;
|
||||
Editing_File *file = imp_get_file(models, buffer);
|
||||
History_Record_Index result = 0;
|
||||
if (file != 0){
|
||||
result = history_get_record_count(&file->state.history);
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
API_EXPORT Record_Data
|
||||
Buffer_History_Get_Record(Application_Links *app, Buffer_Summary *buffer, History_Record_Index record){
|
||||
Record_Data result = {};
|
||||
return(result);
|
||||
}
|
||||
|
||||
API_EXPORT History_Record_Index
|
||||
Buffer_History_Get_Current_State_Index(Application_Links *app, Buffer_Summary *buffer){
|
||||
Models *models = (Models*)app->cmd_context;
|
||||
Editing_File *file = imp_get_file(models, buffer);
|
||||
History_Record_Index result = 0;
|
||||
if (file != 0){
|
||||
result = file_get_current_record_index(file);
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
API_EXPORT bool32
|
||||
Buffer_History_Set_Current_State_Index(Application_Links *app, Buffer_Summary *buffer, History_Record_Index index){
|
||||
Models *models = (Models*)app->cmd_context;
|
||||
Editing_File *file = imp_get_file(models, buffer);
|
||||
bool32 result = false;
|
||||
if (file != 0){
|
||||
i32 max_index = history_get_record_count(&file->state.history);
|
||||
if (0 <= index && index <= max_index){
|
||||
System_Functions *system = models->system;
|
||||
edit_change_current_history_state(system, models, file, index);
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
API_EXPORT bool32
|
||||
Buffer_History_Merge_Records_Between_States(Application_Links *app, Buffer_Summary *buffer, History_Record_Index first_index, History_Record_Index last_index){
|
||||
bool32 result = false;
|
||||
return(result);
|
||||
}
|
||||
|
||||
API_EXPORT bool32
|
||||
Buffer_History_Split_Group_Record(Application_Links *app, Buffer_Summary *buffer, History_Record_Index record_index, int32_t sub_record_index){
|
||||
bool32 result = false;
|
||||
return(result);
|
||||
}
|
||||
|
||||
API_EXPORT bool32
|
||||
Buffer_History_Split_Single_Record(Application_Links *app, Buffer_Summary *buffer, History_Record_Index record_index, int32_t forward_str_split, int32_t backward_str_split){
|
||||
bool32 result = false;
|
||||
return(result);
|
||||
}
|
||||
|
||||
API_EXPORT bool32
|
||||
Buffer_History_Clear_After_Undo_Position(Application_Links *app, Buffer_Summary *buffer){
|
||||
bool32 result = false;
|
||||
return(result);
|
||||
}
|
||||
|
||||
API_EXPORT void
|
||||
Global_History_Edit_Group_Begin(Application_Links *app){
|
||||
|
||||
}
|
||||
|
||||
API_EXPORT void
|
||||
Global_History_Edit_Group_End(Application_Links *app){
|
||||
|
||||
}
|
||||
|
||||
internal void
|
||||
font_pointers_to_face_description(Font_Pointers font, Face_Description *description){
|
||||
Font_Metrics *metrics = font.metrics;
|
||||
|
|
|
@ -68,6 +68,7 @@ struct Models{
|
|||
Working_Set working_set;
|
||||
Live_Views live_set;
|
||||
Parse_Context_Memory parse_context_memory;
|
||||
Global_History global_history;
|
||||
|
||||
Dynamic_Variable_Layout variable_layout;
|
||||
Dynamic_Workspace dynamic_workspace;
|
||||
|
|
|
@ -44,13 +44,14 @@ struct Mem_Options{
|
|||
#include "4ed_linked_node_macros.h"
|
||||
#include "4ed_log.h"
|
||||
#include "4ed_ptr_check.h"
|
||||
#include "4ed_memory_bank.h"
|
||||
#include "4ed_dynamic_variables.h"
|
||||
|
||||
#include "4ed_buffer_model.h"
|
||||
#include "4ed_translation.h"
|
||||
#include "4ed_command.h"
|
||||
#include "4ed_buffer.h"
|
||||
#include "4ed_undo.h"
|
||||
#include "4ed_history.h"
|
||||
#include "4ed_file.h"
|
||||
#include "4ed_code_wrap.h"
|
||||
|
||||
|
@ -62,11 +63,13 @@ struct Mem_Options{
|
|||
#include "4ed_gui.h"
|
||||
#include "4ed_layout.h"
|
||||
#include "4ed_view.h"
|
||||
#include "4ed_edit.h"
|
||||
#include "4ed_app_models.h"
|
||||
|
||||
#include "4ed_mem.cpp"
|
||||
#include "4ed_hash_functions.cpp"
|
||||
#include "4ed_ptr_check.cpp"
|
||||
#include "4ed_memory_bank.cpp"
|
||||
#include "4ed_dynamic_variables.cpp"
|
||||
#include "4ed_parse_context.cpp"
|
||||
#include "4ed_font.cpp"
|
||||
|
@ -75,7 +78,7 @@ struct Mem_Options{
|
|||
#include "4ed_render_format.cpp"
|
||||
#include "4ed_command.cpp"
|
||||
#include "4ed_buffer.cpp"
|
||||
#include "4ed_undo.cpp"
|
||||
#include "4ed_history.cpp"
|
||||
#include "4ed_file_lex.cpp"
|
||||
#include "4ed_file.cpp"
|
||||
#include "4ed_code_wrap.cpp"
|
||||
|
|
108
4ed_buffer.cpp
108
4ed_buffer.cpp
|
@ -112,22 +112,73 @@ buffer_batch_debug_sort_check(Buffer_Edit *sorted_edits, i32 edit_count){
|
|||
return(result);
|
||||
}
|
||||
|
||||
// TODO(allen): This now relies on Edit and Edit_Array from 4ed_edit.h even though we sort of think of that
|
||||
// as cheating... gotta rethink the separation of buffer from everything else moving forward or something.
|
||||
|
||||
internal i32
|
||||
buffer_batch_edit_max_shift(Buffer_Edit *sorted_edits, i32 edit_count){
|
||||
i32 i = 0;
|
||||
i32 shift_total = 0, shift_max = 0;
|
||||
buffer_batch_edit_update_cursors(Cursor_With_Index *sorted_positions, i32 count, Edit_Array sorted_edits, b32 lean_right){
|
||||
Cursor_With_Index *position = sorted_positions;
|
||||
Cursor_With_Index *one_past_last_position = sorted_positions + count;
|
||||
Edit *edit = sorted_edits.vals;
|
||||
Edit *one_past_last_edit = sorted_edits.vals + sorted_edits.count;
|
||||
|
||||
Buffer_Edit *edit = sorted_edits;
|
||||
for (i = 0; i < edit_count; ++i, ++edit){
|
||||
shift_total += (edit->len - (edit->end - edit->start));
|
||||
if (shift_total > shift_max){
|
||||
shift_max = shift_total;
|
||||
i32 shift_amount = 0;
|
||||
if (lean_right){
|
||||
for (;edit < one_past_last_edit && position < one_past_last_position;
|
||||
++edit){
|
||||
i32 start = edit->range.first;
|
||||
i32 end = edit->range.one_past_last;
|
||||
|
||||
for (;position->pos < start && position < one_past_last_position;
|
||||
++position){
|
||||
position->pos += shift_amount;
|
||||
}
|
||||
|
||||
i32 new_end = start + edit->length + shift_amount;
|
||||
for (;position->pos <= end && position < one_past_last_position;
|
||||
++position){
|
||||
position->pos = new_end;
|
||||
}
|
||||
|
||||
shift_amount += (edit->length - (end - start));
|
||||
}
|
||||
}
|
||||
else{
|
||||
for (;edit < one_past_last_edit && position < one_past_last_position;
|
||||
++edit){
|
||||
i32 start = edit->range.first;
|
||||
i32 end = edit->range.one_past_last;
|
||||
|
||||
for (;position->pos < start && position < one_past_last_position;
|
||||
++position){
|
||||
position->pos += shift_amount;
|
||||
}
|
||||
|
||||
i32 new_end = start + shift_amount;
|
||||
for (;position->pos <= end && position < one_past_last_position;
|
||||
++position){
|
||||
position->pos = new_end;
|
||||
}
|
||||
|
||||
shift_amount += (edit->length - (end - start));
|
||||
}
|
||||
}
|
||||
|
||||
return(shift_max);
|
||||
for (;position < one_past_last_position;
|
||||
++position){
|
||||
position->pos += shift_amount;
|
||||
}
|
||||
|
||||
for (;edit < one_past_last_edit;
|
||||
++edit){
|
||||
shift_amount += (edit->length - (edit->range.one_past_last - edit->range.first));
|
||||
}
|
||||
|
||||
return(shift_amount);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
internal i32
|
||||
buffer_batch_edit_update_cursors(Cursor_With_Index *sorted_positions, i32 count, Buffer_Edit *sorted_edits, i32 edit_count, b32 lean_right){
|
||||
Cursor_With_Index *position = sorted_positions;
|
||||
|
@ -181,6 +232,7 @@ buffer_batch_edit_update_cursors(Cursor_With_Index *sorted_positions, i32 count,
|
|||
|
||||
return(shift_amount);
|
||||
}
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
|
@ -471,6 +523,38 @@ buffer_replace_range(Gap_Buffer *buffer, i32 start, i32 end, char *str, i32 len,
|
|||
// TODO(allen): do(optimize Gap_Buffer batch edit)
|
||||
// Now that we are just using Gap_Buffer we could afford to improve
|
||||
// this for the Gap_Buffer's behavior.
|
||||
|
||||
// TODO(allen): This now relies on Edit and Edit_Array from 4ed_edit.h even though we sort of think of that
|
||||
// as cheating... gotta rethink the separation of buffer from everything else moving forward or something.
|
||||
|
||||
internal b32
|
||||
buffer_batch_edit_step(Buffer_Batch_State *state, Gap_Buffer *buffer, Edit_Array sorted_edits, void *scratch, i32 scratch_size, i32 *request_amount){
|
||||
b32 result = false;
|
||||
|
||||
i32 shift_total = state->shift_total;
|
||||
i32 i = state->i;
|
||||
|
||||
Edit *edit = sorted_edits.vals + i;
|
||||
for (; i < sorted_edits.count; ++i, ++edit){
|
||||
char *str = edit->str;
|
||||
i32 length = edit->length;
|
||||
i32 start = edit->range.first + shift_total;
|
||||
i32 end = edit->range.one_past_last + shift_total;
|
||||
i32 shift_amount = buffer_replace_range_compute_shift(start, end, length);
|
||||
result = buffer_replace_range(buffer, start, end, str, length, shift_amount, scratch, scratch_size, request_amount);
|
||||
if (result){
|
||||
break;
|
||||
}
|
||||
shift_total += shift_amount;
|
||||
}
|
||||
|
||||
state->shift_total = shift_total;
|
||||
state->i = i;
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
#if 0
|
||||
internal i32
|
||||
buffer_batch_edit_step(Buffer_Batch_State *state, Gap_Buffer *buffer, Buffer_Edit *sorted_edits, char *strings, i32 edit_count,
|
||||
void *scratch, i32 scratch_size, i32 *request_amount){
|
||||
|
@ -497,6 +581,7 @@ buffer_batch_edit_step(Buffer_Batch_State *state, Gap_Buffer *buffer, Buffer_Edi
|
|||
|
||||
return(result);
|
||||
}
|
||||
#endif
|
||||
|
||||
internal void*
|
||||
buffer_edit_provide_memory(Gap_Buffer *buffer, void *new_data, i32 new_max){
|
||||
|
@ -553,6 +638,11 @@ buffer_stringify(Gap_Buffer *buffer, i32 start, i32 end, char *out){
|
|||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
buffer_stringify_range(Gap_Buffer *buffer, Range range, char *out){
|
||||
buffer_stringify(buffer, range.first, range.one_past_last, out);
|
||||
}
|
||||
|
||||
internal i32
|
||||
buffer_convert_out(Gap_Buffer *buffer, char *dest, i32 max){
|
||||
Gap_Buffer_Stream stream = {};
|
||||
|
|
|
@ -66,49 +66,6 @@ dynamic_variables_create(Heap *heap, Dynamic_Variable_Layout *layout, String nam
|
|||
|
||||
////////////////////////////////
|
||||
|
||||
internal void
|
||||
dynamic_memory_bank_init(Heap *heap, Dynamic_Memory_Bank *mem_bank){
|
||||
heap_init(&mem_bank->heap);
|
||||
mem_bank->first = 0;
|
||||
mem_bank->last = 0;
|
||||
mem_bank->total_memory_size = 0;
|
||||
}
|
||||
|
||||
internal void*
|
||||
dynamic_memory_bank_allocate(Heap *heap, Dynamic_Memory_Bank *mem_bank, i32 size){
|
||||
void *ptr = heap_allocate(&mem_bank->heap, size);
|
||||
if (ptr == 0){
|
||||
i32 alloc_size = clamp_bottom(4096, size*4 + sizeof(Dynamic_Memory_Header));
|
||||
void *new_block = heap_allocate(heap, alloc_size);
|
||||
if (new_block != 0){
|
||||
Dynamic_Memory_Header *header = (Dynamic_Memory_Header*)new_block;
|
||||
sll_push(mem_bank->first, mem_bank->last, header);
|
||||
mem_bank->total_memory_size += alloc_size;
|
||||
heap_extend(&mem_bank->heap, header + 1, alloc_size - sizeof(*header));
|
||||
ptr = heap_allocate(&mem_bank->heap, size);
|
||||
}
|
||||
}
|
||||
return(ptr);
|
||||
}
|
||||
|
||||
internal void
|
||||
dynamic_memory_bank_free(Dynamic_Memory_Bank *mem_bank, void *ptr){
|
||||
heap_free(&mem_bank->heap, ptr);
|
||||
}
|
||||
|
||||
internal void
|
||||
dynamic_memory_bank_free_all(Heap *heap, Dynamic_Memory_Bank *mem_bank){
|
||||
for (Dynamic_Memory_Header *header = mem_bank->first, *next = 0;
|
||||
header != 0;
|
||||
header = next){
|
||||
next = header->next;
|
||||
heap_free(heap, header);
|
||||
}
|
||||
mem_bank->total_memory_size = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal void
|
||||
dynamic_variables_block_init(Dynamic_Variable_Block *block){
|
||||
block->val_array = 0;
|
||||
|
@ -117,12 +74,12 @@ dynamic_variables_block_init(Dynamic_Variable_Block *block){
|
|||
}
|
||||
|
||||
internal void
|
||||
dynamic_variables_block_grow_max_to(Heap *heap, Dynamic_Memory_Bank *mem_bank, i32 new_max, Dynamic_Variable_Block *block){
|
||||
dynamic_variables_block_grow_max_to(Heap *heap, Memory_Bank *mem_bank, i32 new_max, Dynamic_Variable_Block *block){
|
||||
i32 new_size = new_max*sizeof(u64);
|
||||
u64 *new_array = (u64*)dynamic_memory_bank_allocate(heap, mem_bank, new_size);
|
||||
u64 *new_array = (u64*)memory_bank_allocate(heap, mem_bank, new_size);
|
||||
if (block->val_array != 0){
|
||||
memcpy(new_array, block->val_array, sizeof(u64)*block->count);
|
||||
dynamic_memory_bank_free(mem_bank, block->val_array);
|
||||
memory_bank_free(mem_bank, block->val_array);
|
||||
}
|
||||
block->val_array = new_array;
|
||||
}
|
||||
|
@ -142,7 +99,7 @@ dynamic_variables_block_fill_unset_values(Dynamic_Variable_Layout *layout, Dynam
|
|||
}
|
||||
|
||||
internal b32
|
||||
dynamic_variables_get_ptr(Heap *heap, Dynamic_Memory_Bank *mem_bank,
|
||||
dynamic_variables_get_ptr(Heap *heap, Memory_Bank *mem_bank,
|
||||
Dynamic_Variable_Layout *layout, Dynamic_Variable_Block *block,
|
||||
i32 location, u64 **ptr_out){
|
||||
b32 result = false;
|
||||
|
@ -164,17 +121,17 @@ dynamic_variables_get_ptr(Heap *heap, Dynamic_Memory_Bank *mem_bank,
|
|||
////////////////////////////////
|
||||
|
||||
internal void
|
||||
insert_u32_Ptr_table(Heap *heap, Dynamic_Memory_Bank *mem_bank, u32_Ptr_Table *table, u32 key, void* val){
|
||||
insert_u32_Ptr_table(Heap *heap, Memory_Bank *mem_bank, u32_Ptr_Table *table, u32 key, void* val){
|
||||
if (at_max_u32_Ptr_table(table)){
|
||||
i32 new_max = (table->max + 1)*2;
|
||||
i32 new_mem_size = max_to_memsize_u32_Ptr_table(new_max);
|
||||
void *new_mem = dynamic_memory_bank_allocate(heap, mem_bank, new_mem_size);
|
||||
void *new_mem = memory_bank_allocate(heap, mem_bank, new_mem_size);
|
||||
u32_Ptr_Table new_table = make_u32_Ptr_table(new_mem, new_mem_size);
|
||||
if (table->mem != 0){
|
||||
b32 result = move_u32_Ptr_table(&new_table, table);
|
||||
Assert(result);
|
||||
AllowLocal(result);
|
||||
dynamic_memory_bank_free(mem_bank, table->mem);
|
||||
memory_bank_free(mem_bank, table->mem);
|
||||
}
|
||||
*table = new_table;
|
||||
}
|
||||
|
@ -191,12 +148,12 @@ marker_visual_allocator_init(Marker_Visual_Allocator *allocator){
|
|||
}
|
||||
|
||||
internal Marker_Visual_Data*
|
||||
dynamic_workspace_alloc_visual(Heap *heap, Dynamic_Memory_Bank *mem_bank, Dynamic_Workspace *workspace){
|
||||
dynamic_workspace_alloc_visual(Heap *heap, Memory_Bank *mem_bank, Dynamic_Workspace *workspace){
|
||||
Marker_Visual_Allocator *allocator = &workspace->visual_allocator;
|
||||
if (allocator->free_count == 0){
|
||||
i32 new_slots_count = clamp_bottom(16, allocator->total_visual_count);
|
||||
i32 memsize = new_slots_count*sizeof(Marker_Visual_Data);
|
||||
void *new_slots_memory = dynamic_memory_bank_allocate(heap, mem_bank, memsize);
|
||||
void *new_slots_memory = memory_bank_allocate(heap, mem_bank, memsize);
|
||||
memset(new_slots_memory, 0, memsize);
|
||||
Marker_Visual_Data *new_slot = (Marker_Visual_Data*)new_slots_memory;
|
||||
allocator->free_count += new_slots_count;
|
||||
|
@ -254,7 +211,7 @@ marker_visual_defaults(Marker_Visual_Data *data){
|
|||
internal void
|
||||
dynamic_workspace_init(Heap *heap, Lifetime_Allocator *lifetime_allocator, i32 user_type, void *user_back_ptr, Dynamic_Workspace *workspace){
|
||||
memset(workspace, 0, sizeof(*workspace));
|
||||
dynamic_memory_bank_init(heap, &workspace->mem_bank);
|
||||
memory_bank_init(&workspace->mem_bank);
|
||||
dynamic_variables_block_init(&workspace->var_block);
|
||||
marker_visual_allocator_init(&workspace->visual_allocator);
|
||||
if (lifetime_allocator->scope_id_counter == 0){
|
||||
|
@ -269,13 +226,13 @@ dynamic_workspace_init(Heap *heap, Lifetime_Allocator *lifetime_allocator, i32 u
|
|||
internal void
|
||||
dynamic_workspace_free(Heap *heap, Lifetime_Allocator *lifetime_allocator, Dynamic_Workspace *workspace){
|
||||
erase_u32_Ptr_table(&lifetime_allocator->scope_id_to_scope_ptr_table, workspace->scope_id);
|
||||
dynamic_memory_bank_free_all(heap, &workspace->mem_bank);
|
||||
memory_bank_free_all(heap, &workspace->mem_bank);
|
||||
}
|
||||
|
||||
internal void
|
||||
dynamic_workspace_clear_contents(Heap *heap, Dynamic_Workspace *workspace){
|
||||
dynamic_memory_bank_free_all(heap, &workspace->mem_bank);
|
||||
dynamic_memory_bank_init(heap, &workspace->mem_bank);
|
||||
memory_bank_free_all(heap, &workspace->mem_bank);
|
||||
memory_bank_init(&workspace->mem_bank);
|
||||
|
||||
dynamic_variables_block_init(&workspace->var_block);
|
||||
marker_visual_allocator_init(&workspace->visual_allocator);
|
||||
|
|
|
@ -98,22 +98,9 @@ struct Dynamic_Variable_Block{
|
|||
|
||||
////////////////////////////////
|
||||
|
||||
struct Dynamic_Memory_Header{
|
||||
Dynamic_Memory_Header *next;
|
||||
};
|
||||
|
||||
struct Dynamic_Memory_Bank{
|
||||
Heap heap;
|
||||
Dynamic_Memory_Header *first;
|
||||
Dynamic_Memory_Header *last;
|
||||
umem total_memory_size;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
struct Dynamic_Workspace{
|
||||
Dynamic_Variable_Block var_block;
|
||||
Dynamic_Memory_Bank mem_bank;
|
||||
Memory_Bank mem_bank;
|
||||
Marker_Visual_Allocator visual_allocator;
|
||||
u32_Ptr_Table object_id_to_object_ptr;
|
||||
u32 object_id_counter;
|
||||
|
|
311
4ed_edit.cpp
311
4ed_edit.cpp
|
@ -70,8 +70,11 @@ edit_fix_markers__read_workspace_markers(Dynamic_Workspace *workspace, Buffer_ID
|
|||
}
|
||||
|
||||
internal void
|
||||
edit_fix_markers(System_Functions *system, Models *models, Editing_File *file, Layout *layout, Cursor_Fix_Descriptor desc){
|
||||
edit_fix_markers(System_Functions *system, Models *models, Editing_File *file, Edit_Array edits){
|
||||
Partition *part = &models->mem.part;
|
||||
Layout *layout = &models->layout;
|
||||
|
||||
Assert(edits.count > 0);
|
||||
|
||||
Temp_Memory cursor_temp = begin_temp_memory(part);
|
||||
|
||||
|
@ -136,6 +139,7 @@ edit_fix_markers(System_Functions *system, Models *models, Editing_File *file, L
|
|||
|
||||
if (cursor_count > 0 || r_cursor_count > 0){
|
||||
buffer_sort_cursors(cursors, cursor_count);
|
||||
#if 0
|
||||
if (desc.is_batch){
|
||||
buffer_batch_edit_update_cursors(cursors, cursor_count, desc.batch, desc.batch_size, false);
|
||||
buffer_batch_edit_update_cursors(r_cursors, r_cursor_count, desc.batch, desc.batch_size, true);
|
||||
|
@ -144,6 +148,18 @@ edit_fix_markers(System_Functions *system, Models *models, Editing_File *file, L
|
|||
buffer_update_cursors(cursors, cursor_count, desc.start, desc.end, desc.shift_amount + (desc.end - desc.start), false);
|
||||
buffer_update_cursors(r_cursors, r_cursor_count, desc.start, desc.end, desc.shift_amount + (desc.end - desc.start), true);
|
||||
}
|
||||
#endif
|
||||
|
||||
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_unsort_cursors(cursors, cursor_count);
|
||||
|
||||
cursor_count = 0;
|
||||
|
@ -200,45 +216,58 @@ edit_fix_markers(System_Functions *system, Models *models, Editing_File *file, L
|
|||
}
|
||||
|
||||
internal void
|
||||
edit_single__inner(System_Functions *system, Models *models, Editing_File *file, Edit_Spec spec, History_Mode history_mode){
|
||||
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;
|
||||
Layout *layout = &models->layout;
|
||||
Heap *heap = &mem->heap;
|
||||
Partition *part = &mem->part;
|
||||
|
||||
Gap_Buffer *buffer = &file->state.buffer;
|
||||
Assert(0 <= edit.range.first);
|
||||
Assert(edit.range.first <= edit.range.one_past_last);
|
||||
Assert(edit.range.one_past_last <= buffer_size(buffer));
|
||||
|
||||
// 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, edit);
|
||||
file->state.current_record_index = history_get_record_count(&file->state.history);
|
||||
}
|
||||
|
||||
// NOTE(allen): fixing stuff beforewards????
|
||||
file_update_history_before_edit(mem, file, spec.step, spec.str, history_mode);
|
||||
edit_pre_state_change(system, &mem->heap, models, file);
|
||||
|
||||
// NOTE(allen): expand spec, compute shift
|
||||
char *str = (char*)spec.str;
|
||||
i32 start = spec.step.edit.start;
|
||||
i32 end = spec.step.edit.end;
|
||||
i32 str_len = spec.step.edit.len;
|
||||
i32 shift_amount = buffer_replace_range_compute_shift(start, end, str_len);
|
||||
i32 shift_amount = buffer_replace_range_compute_shift(edit.range.first, edit.range.one_past_last, edit.length);
|
||||
|
||||
// NOTE(allen): actual text replacement
|
||||
i32 scratch_size = part_remaining(part);
|
||||
Assert(scratch_size > 0);
|
||||
i32 request_amount = 0;
|
||||
Assert(end <= buffer_size(&file->state.buffer));
|
||||
for (;buffer_replace_range(&file->state.buffer, start, end, str, str_len, shift_amount, part->base + part->pos, scratch_size, &request_amount);){
|
||||
for (;buffer_replace_range(buffer, edit.range.first, edit.range.one_past_last, edit.str, edit.length,
|
||||
shift_amount, part->base + part->pos, 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);
|
||||
void *old_data = buffer_edit_provide_memory(buffer, new_data, request_amount);
|
||||
if (old_data){
|
||||
heap_free(heap, old_data);
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE(allen): line meta data
|
||||
Gap_Buffer *buffer = &file->state.buffer;
|
||||
i32 line_start = buffer_get_line_number(&file->state.buffer, start);
|
||||
i32 line_end = buffer_get_line_number(&file->state.buffer, end);
|
||||
i32 line_start = buffer_get_line_number(buffer, edit.range.first);
|
||||
i32 line_end = buffer_get_line_number(buffer, edit.range.one_past_last);
|
||||
i32 replaced_line_count = line_end - line_start;
|
||||
i32 new_line_count = buffer_count_newlines(&file->state.buffer, start, start+str_len);
|
||||
i32 new_line_count = buffer_count_newlines(buffer, edit.range.first, edit.range.first + edit.length);
|
||||
i32 line_shift = new_line_count - replaced_line_count;
|
||||
|
||||
Font_Pointers font = system->font.get_pointers_by_id(file->settings.font_id);
|
||||
|
@ -252,18 +281,14 @@ edit_single__inner(System_Functions *system, Models *models, Editing_File *file,
|
|||
|
||||
// NOTE(allen): token fixing
|
||||
if (file->settings.tokens_exist){
|
||||
file_relex(system, models, file, start, end, shift_amount);
|
||||
file_relex(system, models, file, edit.range.first, edit.range.one_past_last, shift_amount);
|
||||
}
|
||||
|
||||
// NOTE(allen): wrap meta data
|
||||
file_measure_wraps(system, &models->mem, file, font);
|
||||
|
||||
// NOTE(allen): cursor fixing
|
||||
Cursor_Fix_Descriptor desc = {};
|
||||
desc.start = start;
|
||||
desc.end = end;
|
||||
desc.shift_amount = shift_amount;
|
||||
edit_fix_markers(system, models, file, layout, desc);
|
||||
edit_fix_markers(system, models, file, edit);
|
||||
|
||||
// NOTE(allen): mark edit finished
|
||||
if (file->settings.tokens_exist){
|
||||
|
@ -276,28 +301,14 @@ edit_single__inner(System_Functions *system, Models *models, Editing_File *file,
|
|||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
edit_single(System_Functions *system, Models *models, Editing_File *file,
|
||||
i32 start, i32 end, char *str, i32 len){
|
||||
Edit_Spec spec = {};
|
||||
spec.step.type = ED_NORMAL;
|
||||
spec.step.edit.start = start;
|
||||
spec.step.edit.end = end;
|
||||
spec.step.edit.len = len;
|
||||
spec.str = (u8*)str;
|
||||
edit_single__inner(system, models, file, spec, hist_normal);
|
||||
}
|
||||
|
||||
#if 0
|
||||
internal Edit_Spec
|
||||
edit_compute_batch_spec(Heap *heap,
|
||||
Editing_File *file,
|
||||
Buffer_Edit *edits, char *str_base, i32 str_size,
|
||||
edit_compute_batch_spec(Heap *heap, Editing_File *file, Buffer_Edit *edits, char *str_base, i32 str_size,
|
||||
Buffer_Edit *inverse_array, char *inv_str, i32 inv_max, i32 edit_count, i32 batch_type){
|
||||
|
||||
i32 inv_str_pos = 0;
|
||||
Buffer_Invert_Batch state = {};
|
||||
if (buffer_invert_batch(&state, &file->state.buffer, edits, edit_count,
|
||||
inverse_array, inv_str, &inv_str_pos, inv_max)){
|
||||
if (buffer_invert_batch(&state, &file->state.buffer, edits, edit_count, inverse_array, inv_str, &inv_str_pos, inv_max)){
|
||||
InvalidCodePath;
|
||||
}
|
||||
|
||||
|
@ -313,31 +324,33 @@ edit_compute_batch_spec(Heap *heap,
|
|||
spec.step.inverse_child_count = edit_count;
|
||||
return(spec);
|
||||
}
|
||||
#endif
|
||||
|
||||
internal void
|
||||
edit_batch(System_Functions *system, Models *models, Editing_File *file, Edit_Spec spec, History_Mode history_mode, Buffer_Batch_Edit_Type batch_type){
|
||||
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;
|
||||
Layout *layout = &models->layout;
|
||||
|
||||
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"???
|
||||
Assert(spec.str == 0);
|
||||
file_update_history_before_edit(mem, file, spec.step, 0, history_mode);
|
||||
edit_pre_state_change(system, &mem->heap, models, file);
|
||||
|
||||
// NOTE(allen): expand spec
|
||||
u8 *str_base = file->state.undo.children.strings;
|
||||
i32 batch_size = spec.step.child_count;
|
||||
Buffer_Edit *batch = file->state.undo.children.edits + spec.step.first_child;
|
||||
Assert(spec.step.first_child < file->state.undo.children.edit_count);
|
||||
Assert(batch_size >= 0);
|
||||
|
||||
// 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, &file->state.buffer, batch, (char*)str_base, batch_size, part->base + part->pos, scratch_size, &request_amount);){
|
||||
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);
|
||||
|
@ -360,14 +373,14 @@ edit_batch(System_Functions *system, Models *models, Editing_File *file, Edit_Sp
|
|||
buffer_measure_character_starts(system, font, &file->state.buffer, file->state.character_starts, 0, file->settings.virtual_white);
|
||||
|
||||
// NOTE(allen): token fixing
|
||||
switch (batch_type){
|
||||
switch (behaviors.batch_type){
|
||||
case BatchEdit_Normal:
|
||||
{
|
||||
if (file->settings.tokens_exist){
|
||||
// TODO(allen): Write a smart fast one here someday.
|
||||
Buffer_Edit *first_edit = batch;
|
||||
Buffer_Edit *last_edit = batch + batch_size - 1;
|
||||
file_relex(system, models, file, first_edit->start, last_edit->end, shift_total);
|
||||
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);
|
||||
|
@ -382,22 +395,25 @@ edit_batch(System_Functions *system, Models *models, Editing_File *file, Edit_Sp
|
|||
Cpp_Token *end_token = tokens.tokens + tokens.count;
|
||||
Cpp_Token original = {};
|
||||
|
||||
Buffer_Edit *edit = batch;
|
||||
Buffer_Edit *end_edit = batch + batch_size;
|
||||
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 < end_edit && edit->start <= original.start; ++edit){
|
||||
local_shift = (edit->len - (edit->end - edit->start));
|
||||
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;
|
||||
for (; edit < end_edit && edit->start < original.start + original.size; ++edit){
|
||||
local_shift += (edit->len - (edit->end - edit->start));
|
||||
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;
|
||||
|
@ -411,11 +427,7 @@ edit_batch(System_Functions *system, Models *models, Editing_File *file, Edit_Sp
|
|||
file_measure_wraps(system, &models->mem, file, font);
|
||||
|
||||
// NOTE(allen): cursor fixing
|
||||
Cursor_Fix_Descriptor desc = {};
|
||||
desc.is_batch = true;
|
||||
desc.batch = batch;
|
||||
desc.batch_size = batch_size;
|
||||
edit_fix_markers(system, models, file, layout, desc);
|
||||
edit_fix_markers(system, models, file, edits);
|
||||
|
||||
// NOTE(allen): mark edit finished
|
||||
if (file->settings.tokens_exist){
|
||||
|
@ -466,31 +478,162 @@ edit_clear(System_Functions *system, Models *models, Editing_File *file){
|
|||
file->state.edit_pos_stack_top = -1;
|
||||
}
|
||||
|
||||
edit_single(system, models, file, 0, buffer_size(&file->state.buffer), 0, 0);
|
||||
Edit edit = {};
|
||||
edit.range.one_past_last = buffer_size(&file->state.buffer);
|
||||
|
||||
Edit_Behaviors behaviors = {};
|
||||
edit_single(system, models, file, edit, behaviors);
|
||||
}
|
||||
|
||||
internal void
|
||||
edit_historical(System_Functions *system, Models *models, Editing_File *file, View *view, Edit_Stack *stack,
|
||||
Edit_Step step, History_Mode history_mode){
|
||||
Edit_Spec spec = {};
|
||||
spec.step = step;
|
||||
edit__apply_record_forward(System_Functions *system, Models *models, Editing_File *file, Record *record, Edit_Behaviors behaviors_prototype){
|
||||
// NOTE(allen): // NOTE(allen): // NOTE(allen): // NOTE(allen): // NOTE(allen):
|
||||
// Whenever you change this also change the backward version!
|
||||
|
||||
if (step.child_count == 0){
|
||||
spec.step.edit.str_start = 0;
|
||||
spec.str = stack->strings + step.edit.str_start;
|
||||
switch (record->kind){
|
||||
case RecordKind_Single:
|
||||
{
|
||||
Edit edit = {};
|
||||
edit.str = record->single.str_forward;
|
||||
edit.length = record->single.length_forward;
|
||||
edit.range.first = record->single.first;
|
||||
edit.range.one_past_last = edit.range.first + record->single.length_backward;
|
||||
edit_single(system, models, file, edit, behaviors_prototype);
|
||||
}break;
|
||||
|
||||
edit_single__inner(system, models, file, spec, history_mode);
|
||||
|
||||
if (view != 0){
|
||||
view_cursor_move(system, view, step.edit.start + step.edit.len);
|
||||
view->transient.edit_pos.mark = view->transient.edit_pos.cursor.pos;
|
||||
case RecordKind_Batch:
|
||||
{
|
||||
Partition *scratch = &models->mem.part;
|
||||
Temp_Memory temp = begin_temp_memory(scratch);
|
||||
|
||||
Style *style = &models->styles.styles[0];
|
||||
view_post_paste_effect(view, 0.333f, step.edit.start, step.edit.len, style->theme.colors[Stag_Undo]);
|
||||
}
|
||||
i32 count = record->batch.count;
|
||||
Edit_Array edits = {};
|
||||
edits.vals = push_array(scratch, Edit, count);
|
||||
edits.count = count;
|
||||
|
||||
Edit *edit = edits.vals;
|
||||
Record_Batch_Slot *batch_slot = record->batch.batch_records;
|
||||
char *str_base_forward = record->batch.str_base_forward;
|
||||
for (i32 i = 0; i < count; i += 1, edit += 1, batch_slot += 1){
|
||||
edit->str = str_base_forward;
|
||||
edit->length = batch_slot->length_forward;
|
||||
edit->range.first = batch_slot->first;
|
||||
edit->range.one_past_last = edit->range.first + batch_slot->length_backward;
|
||||
str_base_forward += batch_slot->length_forward;
|
||||
}
|
||||
|
||||
Edit_Behaviors behaviors = behaviors_prototype;
|
||||
behaviors.batch_type = record->batch.type;
|
||||
edit_batch(system, models, file, edits, behaviors);
|
||||
|
||||
end_temp_memory(temp);
|
||||
}break;
|
||||
|
||||
case RecordKind_Group:
|
||||
{
|
||||
Node *sentinel = &record->group.children;
|
||||
for (Node *node = sentinel->next;
|
||||
node != sentinel;
|
||||
node = node->next){
|
||||
Record *record = CastFromMember(Record, node, node);
|
||||
edit__apply_record_forward(system, models, file, record, behaviors_prototype);
|
||||
}
|
||||
}break;
|
||||
}
|
||||
else{
|
||||
edit_batch(system, models, view->transient.file_data.file, spec, hist_normal, spec.step.special_type);
|
||||
}
|
||||
|
||||
internal void
|
||||
edit__apply_record_backward(System_Functions *system, Models *models, Editing_File *file, Record *record, Edit_Behaviors behaviors_prototype){
|
||||
// NOTE(allen): // NOTE(allen): // NOTE(allen): // NOTE(allen): // NOTE(allen):
|
||||
// Whenever you change this also change the forward version!
|
||||
|
||||
switch (record->kind){
|
||||
case RecordKind_Single:
|
||||
{
|
||||
Edit edit = {};
|
||||
edit.str = record->single.str_backward;
|
||||
edit.length = record->single.length_backward;
|
||||
edit.range.first = record->single.first;
|
||||
edit.range.one_past_last = edit.range.first + record->single.length_forward;
|
||||
edit_single(system, models, file, edit, behaviors_prototype);
|
||||
}break;
|
||||
|
||||
case RecordKind_Batch:
|
||||
{
|
||||
Partition *scratch = &models->mem.part;
|
||||
Temp_Memory temp = begin_temp_memory(scratch);
|
||||
|
||||
i32 count = record->batch.count;
|
||||
Edit_Array edits = {};
|
||||
edits.vals = push_array(scratch, Edit, count);
|
||||
edits.count = count;
|
||||
|
||||
i32 shift_amount = 0;
|
||||
|
||||
Edit *edit = edits.vals;
|
||||
Record_Batch_Slot *batch_slot = record->batch.batch_records;
|
||||
char *str_base_backward = record->batch.str_base_backward;
|
||||
for (i32 i = 0; i < count; i += 1, edit += 1, batch_slot += 1){
|
||||
edit->str = str_base_backward;
|
||||
edit->length = batch_slot->length_backward;
|
||||
edit->range.first = batch_slot->first + shift_amount;
|
||||
edit->range.one_past_last = edit->range.first + batch_slot->length_forward;
|
||||
str_base_backward += batch_slot->length_backward;
|
||||
shift_amount += batch_slot->length_forward - batch_slot->length_backward;
|
||||
}
|
||||
|
||||
Edit_Behaviors behaviors = behaviors_prototype;
|
||||
behaviors.batch_type = record->batch.type;
|
||||
edit_batch(system, models, file, edits, behaviors);
|
||||
|
||||
end_temp_memory(temp);
|
||||
}break;
|
||||
|
||||
case RecordKind_Group:
|
||||
{
|
||||
Node *sentinel = &record->group.children;
|
||||
for (Node *node = sentinel->prev;
|
||||
node != sentinel;
|
||||
node = node->prev){
|
||||
Record *record = CastFromMember(Record, node, node);
|
||||
edit__apply_record_backward(system, models, file, record, behaviors_prototype);
|
||||
}
|
||||
}break;
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
edit_change_current_history_state(System_Functions *system, Models *models, Editing_File *file, i32 target_index){
|
||||
History *history = &file->state.history;
|
||||
if (history->activated && file->state.current_record_index != target_index){
|
||||
Assert(0 <= target_index && target_index <= history->record_count);
|
||||
|
||||
i32 current = file->state.current_record_index;
|
||||
Record *record = history_get_record(history, current);
|
||||
Assert(record != 0);
|
||||
Record *dummy_record = history_get_dummy_record(history);
|
||||
|
||||
Edit_Behaviors behaviors_prototype = {};
|
||||
behaviors_prototype.do_not_post_to_history = true;
|
||||
|
||||
if (current < target_index){
|
||||
do{
|
||||
current += 1;
|
||||
record = CastFromMember(Record, node, record->node.next);
|
||||
Assert(record != dummy_record);
|
||||
edit__apply_record_forward(system, models, file, record, behaviors_prototype);
|
||||
} while (current != target_index);
|
||||
}
|
||||
else{
|
||||
do{
|
||||
Assert(record != dummy_record);
|
||||
edit__apply_record_backward(system, models, file, record, behaviors_prototype);
|
||||
current -= 1;
|
||||
record = CastFromMember(Record, node, record->node.prev);
|
||||
} while (current != target_index);
|
||||
}
|
||||
|
||||
file->state.current_record_index = current;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 07.02.2019
|
||||
*
|
||||
* Types used for edit operations
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#if !defined(FRED_EDIT_H)
|
||||
#define FRED_EDIT_H
|
||||
|
||||
struct Edit{
|
||||
char *str;
|
||||
i32 length;
|
||||
Range range;
|
||||
};
|
||||
|
||||
struct Edit_Array{
|
||||
Edit *vals;
|
||||
i32 count;
|
||||
};
|
||||
|
||||
struct Edit_Behaviors{
|
||||
Buffer_Batch_Edit_Type batch_type;
|
||||
b32 do_not_post_to_history;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
50
4ed_file.cpp
50
4ed_file.cpp
|
@ -441,31 +441,7 @@ file_create_from_string(System_Functions *system, Models *models, Editing_File *
|
|||
|
||||
file->settings.read_only = ((flags & FileCreateFlag_ReadOnly) != 0);
|
||||
if (!file->settings.read_only){
|
||||
// TODO(allen): Redo undo system (if you don't mind the pun)
|
||||
i32 request_size = KB(64);
|
||||
file->state.undo.undo.max = request_size;
|
||||
file->state.undo.undo.strings = (u8*)heap_allocate(heap, request_size);
|
||||
file->state.undo.undo.edit_max = request_size/sizeof(Edit_Step);
|
||||
file->state.undo.undo.edits = (Edit_Step*)heap_allocate(heap, request_size);
|
||||
|
||||
file->state.undo.redo.max = request_size;
|
||||
file->state.undo.redo.strings = (u8*)heap_allocate(heap, request_size);
|
||||
file->state.undo.redo.edit_max = request_size/sizeof(Edit_Step);
|
||||
file->state.undo.redo.edits = (Edit_Step*)heap_allocate(heap, request_size);
|
||||
|
||||
file->state.undo.history.max = request_size;
|
||||
file->state.undo.history.strings = (u8*)heap_allocate(heap, request_size);
|
||||
file->state.undo.history.edit_max = request_size/sizeof(Edit_Step);
|
||||
file->state.undo.history.edits = (Edit_Step*)heap_allocate(heap, request_size);
|
||||
|
||||
file->state.undo.children.max = request_size;
|
||||
file->state.undo.children.strings = (u8*)heap_allocate(heap, request_size);
|
||||
file->state.undo.children.edit_max = request_size/sizeof(Buffer_Edit);
|
||||
file->state.undo.children.edits = (Buffer_Edit*)heap_allocate(heap, request_size);
|
||||
|
||||
file->state.undo.history_block_count = 1;
|
||||
file->state.undo.history_head_block = 0;
|
||||
file->state.undo.current_block_normal = 1;
|
||||
history_init(&models->app_links, &file->state.history);
|
||||
}
|
||||
|
||||
// TODO(allen): do(cleanup the create and settings dance)
|
||||
|
@ -491,8 +467,7 @@ file_create_from_string(System_Functions *system, Models *models, Editing_File *
|
|||
}
|
||||
|
||||
internal void
|
||||
file_free(System_Functions *system, Application_Links *app, Heap *heap, Lifetime_Allocator *lifetime_allocator,
|
||||
Editing_File *file){
|
||||
file_free(System_Functions *system, Heap *heap, Lifetime_Allocator *lifetime_allocator, Editing_File *file){
|
||||
if (file->state.still_lexing){
|
||||
system->cancel_job(BACKGROUND_THREADS, file->state.lex_job);
|
||||
if (file->state.swap_array.tokens){
|
||||
|
@ -516,19 +491,7 @@ file_free(System_Functions *system, Application_Links *app, Heap *heap, Lifetime
|
|||
heap_free(heap, file->state.character_starts);
|
||||
heap_free(heap, file->state.line_indents);
|
||||
|
||||
if (file->state.undo.undo.edits){
|
||||
heap_free(heap, file->state.undo.undo.strings);
|
||||
heap_free(heap, file->state.undo.undo.edits);
|
||||
|
||||
heap_free(heap, file->state.undo.redo.strings);
|
||||
heap_free(heap, file->state.undo.redo.edits);
|
||||
|
||||
heap_free(heap, file->state.undo.history.strings);
|
||||
heap_free(heap, file->state.undo.history.edits);
|
||||
|
||||
heap_free(heap, file->state.undo.children.strings);
|
||||
heap_free(heap, file->state.undo.children.edits);
|
||||
}
|
||||
history_free(heap, &file->state.history);
|
||||
}
|
||||
|
||||
internal void
|
||||
|
@ -543,5 +506,12 @@ init_read_only_file(System_Functions *system, Models *models, Editing_File *file
|
|||
file_create_from_string(system, models, file, val, FileCreateFlag_ReadOnly);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal i32
|
||||
file_get_current_record_index(Editing_File *file){
|
||||
return(file->state.current_record_index);
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
|
|
@ -75,7 +75,8 @@ struct Editing_File_State{
|
|||
i32 wrap_position_count;
|
||||
i32 wrap_position_max;
|
||||
|
||||
Undo_Data undo;
|
||||
History history;
|
||||
i32 current_record_index;
|
||||
|
||||
Cpp_Token_Array token_array;
|
||||
Cpp_Token_Array swap_array;
|
||||
|
|
|
@ -0,0 +1,262 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 24.03.2018
|
||||
*
|
||||
* History
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
// TODO(allen): do(make an index <-> node acceleration structure for history)
|
||||
|
||||
internal i32
|
||||
history__to_index(History *history, Node *node){
|
||||
i32 result = -1;
|
||||
i32 counter = 0;
|
||||
Node *sentinel = &history->records;
|
||||
Node *it = sentinel;
|
||||
do{
|
||||
if (it == node){
|
||||
result = counter;
|
||||
break;
|
||||
}
|
||||
counter += 1;
|
||||
it = it->next;
|
||||
} while (it != sentinel);
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal Node*
|
||||
history__to_node(History *history, int32_t index){
|
||||
Node *result = 0;
|
||||
if (0 <= index && index <= history->record_count){
|
||||
i32 counter = 0;
|
||||
Node *sentinel = &history->records;
|
||||
Node *it = sentinel;
|
||||
do{
|
||||
if (counter == index){
|
||||
result = it;
|
||||
break;
|
||||
}
|
||||
counter += 1;
|
||||
it = it->next;
|
||||
} while (it != sentinel);
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal Record*
|
||||
history__allocate_record(Heap *heap, History *history){
|
||||
Node *sentinel = &history->free_records;
|
||||
Node *new_node = sentinel->next;
|
||||
if (new_node == sentinel){
|
||||
i32 new_record_count = 1024;
|
||||
void *memory = memory_bank_allocate(heap, &history->bank, sizeof(Record)*new_record_count);
|
||||
|
||||
Record *new_record = (Record*)memory;
|
||||
sentinel->next = &new_record->node;
|
||||
new_record->node.prev = sentinel;
|
||||
for (i32 i = 1; i < new_record_count; i += 1, new_record += 1){
|
||||
new_record[0].node.next = &new_record[1].node;
|
||||
new_record[1].node.prev = &new_record[0].node;
|
||||
}
|
||||
new_record[0].node.next = sentinel;
|
||||
sentinel->prev = &new_record[0].node;
|
||||
|
||||
new_node = &((Record*)memory)->node;
|
||||
}
|
||||
dll_remove(new_node);
|
||||
Record *record = CastFromMember(Record, node, new_node);
|
||||
block_zero_struct(record);
|
||||
return(record);
|
||||
}
|
||||
|
||||
internal void
|
||||
global_history_init(Global_History *global_history){
|
||||
global_history->edit_number_counter = 0;
|
||||
global_history->edit_grouping_counter = 0;
|
||||
}
|
||||
|
||||
internal i32
|
||||
global_history_get_edit_number(Global_History *global_history){
|
||||
i32 result = global_history->edit_number_counter;
|
||||
if (global_history->edit_grouping_counter == 0){
|
||||
global_history->edit_number_counter += 1;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal void
|
||||
global_history_adjust_edit_grouping_counter(Global_History *global_history, i32 adjustment){
|
||||
global_history->edit_grouping_counter += adjustment;
|
||||
}
|
||||
|
||||
internal void
|
||||
history_init(Application_Links *app, History *history){
|
||||
history->activated = true;
|
||||
history->arena = make_arena(app, KB(32));
|
||||
memory_bank_init(&history->bank);
|
||||
dll_init_sentinel(&history->free_records);
|
||||
dll_init_sentinel(&history->records);
|
||||
history->record_count = 0;
|
||||
}
|
||||
|
||||
internal void
|
||||
history_free(Heap *heap, History *history){
|
||||
if (history->activated){
|
||||
arena_release_all(&history->arena);
|
||||
memory_bank_free_all(heap, &history->bank);
|
||||
}
|
||||
}
|
||||
|
||||
internal i32
|
||||
history_get_record_count(History *history){
|
||||
return(history->record_count);
|
||||
}
|
||||
|
||||
internal Record*
|
||||
history_get_record(History *history, i32 index){
|
||||
Record *record = 0;
|
||||
Node *node = history__to_node(history, index);
|
||||
if (node != 0){
|
||||
record = CastFromMember(Record, node, node);
|
||||
}
|
||||
return(record);
|
||||
}
|
||||
|
||||
internal Record*
|
||||
history_get_dummy_record(History *history){
|
||||
return(CastFromMember(Record, node, &history->records));
|
||||
}
|
||||
|
||||
internal void
|
||||
history__stash_record(History *history, Record *new_record){
|
||||
dll_insert_back(&history->records, &new_record->node);
|
||||
history->record_count += 1;
|
||||
}
|
||||
|
||||
internal void
|
||||
history__free_nodes(History *history, i32 first_index, Node *first_node, Node *last_node){
|
||||
if (first_node == last_node){
|
||||
dll_remove(first_node);
|
||||
dll_insert(&history->free_records, first_node);
|
||||
}
|
||||
else{
|
||||
{
|
||||
Node *left = first_node->prev;
|
||||
Node *right = last_node->next;
|
||||
left->next = right;
|
||||
right->prev = left;
|
||||
}
|
||||
|
||||
{
|
||||
Node *left = &history->free_records;
|
||||
Node *right = left->next;
|
||||
left->next = first_node;
|
||||
first_node->prev = left;
|
||||
right->prev = last_node;
|
||||
last_node->next = right;
|
||||
}
|
||||
}
|
||||
Assert(first_index != 0);
|
||||
history->record_count = first_index - 1;
|
||||
}
|
||||
|
||||
internal void
|
||||
history_record_edit(Heap *heap, Global_History *global_history, History *history, Gap_Buffer *buffer, Edit edit){
|
||||
if (history->activated){
|
||||
Record *new_record = history__allocate_record(heap, history);
|
||||
history__stash_record(history, new_record);
|
||||
|
||||
new_record->restore_point = temp_memory_light(begin_temp_memory(&history->arena));
|
||||
new_record->edit_number = global_history_get_edit_number(global_history);
|
||||
|
||||
new_record->kind = RecordKind_Single;
|
||||
|
||||
i32 length_forward = edit.length;
|
||||
i32 length_backward = edit.range.one_past_last - edit.range.first;
|
||||
|
||||
new_record->single.str_forward = push_array(&history->arena, char, length_forward);
|
||||
new_record->single.str_backward = push_array(&history->arena, char, length_backward);
|
||||
new_record->single.length_forward = length_forward;
|
||||
new_record->single.length_backward = length_backward;
|
||||
new_record->single.first = edit.range.first;
|
||||
|
||||
block_copy(new_record->single.str_forward, edit.str, length_forward);
|
||||
buffer_stringify_range(buffer, edit.range, new_record->single.str_backward);
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
history_record_edit(Heap *heap, Global_History *global_history, History *history, Gap_Buffer *buffer, Edit_Array edits, Buffer_Batch_Edit_Type batch_type){
|
||||
if (history->activated){
|
||||
Record *new_record = history__allocate_record(heap, history);
|
||||
history__stash_record(history, new_record);
|
||||
|
||||
new_record->restore_point = temp_memory_light(begin_temp_memory(&history->arena));
|
||||
new_record->edit_number = global_history_get_edit_number(global_history);
|
||||
|
||||
new_record->kind = RecordKind_Batch;
|
||||
|
||||
i32 length_forward = 0;
|
||||
i32 length_backward = 0;
|
||||
|
||||
for (i32 i = 0; i < edits.count; i += 1){
|
||||
length_forward += edits.vals[i].length;
|
||||
length_backward += edits.vals[i].range.one_past_last - edits.vals[i].range.first;
|
||||
}
|
||||
|
||||
new_record->batch.type = batch_type;
|
||||
new_record->batch.count = edits.count;
|
||||
new_record->batch.str_base_forward = push_array(&history->arena, char, length_forward);
|
||||
new_record->batch.str_base_backward = push_array(&history->arena, char, length_backward);
|
||||
new_record->batch.batch_records = push_array(&history->arena, Record_Batch_Slot, edits.count);
|
||||
|
||||
char *str_base_forward = new_record->batch.str_base_forward;
|
||||
char *cursor_forward = str_base_forward;
|
||||
char *str_base_backward = new_record->batch.str_base_backward;
|
||||
char *cursor_backward = str_base_backward;
|
||||
|
||||
Record_Batch_Slot *batch_slot = new_record->batch.batch_records;
|
||||
Edit *edit = edits.vals;
|
||||
|
||||
for (i32 i = 0; i < edits.count; i += 1, batch_slot += 1, edit += 1){
|
||||
i32 first = edit->range.first;
|
||||
i32 length_forward = edit->length;
|
||||
i32 length_backward = edit->range.one_past_last - first;
|
||||
|
||||
batch_slot->length_forward = length_forward ;
|
||||
batch_slot->length_backward = length_backward;
|
||||
batch_slot->first = first;
|
||||
|
||||
block_copy(cursor_forward , edit->str, length_forward);
|
||||
buffer_stringify_range(buffer, edit->range, cursor_backward);
|
||||
|
||||
cursor_forward += length_forward ;
|
||||
cursor_backward += length_backward;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
history_dump_records_after_index(History *history, i32 index){
|
||||
Assert(0 <= index && index <= history->record_count);
|
||||
if (index < history->record_count){
|
||||
Node *node = history__to_node(history, index);
|
||||
Node *first_node_to_clear = node->next;
|
||||
|
||||
Node *sentinel = &history->records;
|
||||
Assert(first_node_to_clear != sentinel);
|
||||
|
||||
Record *first_record_to_clear = CastFromMember(Record, node, first_node_to_clear);
|
||||
end_temp_memory(&history->arena, first_record_to_clear->restore_point);
|
||||
|
||||
Node *last_node_to_clear = sentinel->prev;
|
||||
|
||||
history__free_nodes(history, index + 1, first_node_to_clear, last_node_to_clear);
|
||||
}
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 24.03.2018
|
||||
*
|
||||
* History
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#if !defined(FRED_HISTORY_H)
|
||||
#define FRED_HISTORY_H
|
||||
|
||||
struct Record_Batch_Slot{
|
||||
i32 length_forward;
|
||||
i32 length_backward;
|
||||
i32 first;
|
||||
};
|
||||
|
||||
struct Record{
|
||||
Node node;
|
||||
Temp_Memory_Arena_Light restore_point;
|
||||
i32 edit_number;
|
||||
Record_Kind kind;
|
||||
union{
|
||||
struct{
|
||||
char *str_forward;
|
||||
char *str_backward;
|
||||
i32 length_forward;
|
||||
i32 length_backward;
|
||||
i32 first;
|
||||
} single;
|
||||
|
||||
struct{
|
||||
Buffer_Batch_Edit_Type type;
|
||||
i32 count;
|
||||
char *str_base_forward;
|
||||
char *str_base_backward;
|
||||
Record_Batch_Slot *batch_records;
|
||||
} batch;
|
||||
|
||||
struct{
|
||||
Node children;
|
||||
i32 count;
|
||||
} group;
|
||||
};
|
||||
};
|
||||
|
||||
struct History{
|
||||
b32 activated;
|
||||
Arena arena;
|
||||
Memory_Bank bank;
|
||||
Node free_records;
|
||||
Node records;
|
||||
i32 record_count;
|
||||
};
|
||||
|
||||
struct Global_History{
|
||||
i32 edit_number_counter;
|
||||
i32 edit_grouping_counter;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
|
@ -838,7 +838,7 @@ fits_inside(i32_Rect rect, i32_Rect outer){
|
|||
return(rect.x0 >= outer.x0 && rect.x1 <= outer.x1 && rect.y0 >= outer.y0 && rect.y1 <= outer.y1);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
internal int32_t
|
||||
interval_overlap(float a0, float a1, float b0, float b1){
|
||||
if ((a0 <= b0 && b0 < a1) || (b0 <= a0 && a0 < b1)){
|
||||
return(true);
|
||||
|
@ -846,7 +846,7 @@ interval_overlap(float a0, float a1, float b0, float b1){
|
|||
return(false);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
internal int32_t
|
||||
rect_opverlap(f32_Rect a, f32_Rect b){
|
||||
if (interval_overlap(a.x0, a.x1, b.x0, b.x1) &&
|
||||
interval_overlap(a.y0, a.y1, b.y0, b.y1)){
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 07.02.2019
|
||||
*
|
||||
* Memory bank wrapper for heap
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
internal void
|
||||
memory_bank_init(Memory_Bank *mem_bank){
|
||||
heap_init(&mem_bank->heap);
|
||||
mem_bank->first = 0;
|
||||
mem_bank->last = 0;
|
||||
mem_bank->total_memory_size = 0;
|
||||
}
|
||||
|
||||
internal void*
|
||||
memory_bank_allocate(Heap *heap, Memory_Bank *mem_bank, i32 size){
|
||||
void *ptr = heap_allocate(&mem_bank->heap, size);
|
||||
if (ptr == 0){
|
||||
i32 alloc_size = clamp_bottom(4096, size*4 + sizeof(Memory_Header));
|
||||
void *new_block = heap_allocate(heap, alloc_size);
|
||||
if (new_block != 0){
|
||||
Memory_Header *header = (Memory_Header*)new_block;
|
||||
sll_push(mem_bank->first, mem_bank->last, header);
|
||||
mem_bank->total_memory_size += alloc_size;
|
||||
heap_extend(&mem_bank->heap, header + 1, alloc_size - sizeof(*header));
|
||||
ptr = heap_allocate(&mem_bank->heap, size);
|
||||
}
|
||||
}
|
||||
return(ptr);
|
||||
}
|
||||
|
||||
internal void
|
||||
memory_bank_free(Memory_Bank *mem_bank, void *ptr){
|
||||
heap_free(&mem_bank->heap, ptr);
|
||||
}
|
||||
|
||||
internal void
|
||||
memory_bank_free_all(Heap *heap, Memory_Bank *mem_bank){
|
||||
for (Memory_Header *header = mem_bank->first, *next = 0;
|
||||
header != 0;
|
||||
header = next){
|
||||
next = header->next;
|
||||
heap_free(heap, header);
|
||||
}
|
||||
mem_bank->total_memory_size = 0;
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 07.02.2019
|
||||
*
|
||||
* Memory bank wrapper for heap
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#if !defined(FRED_MEMORY_BANK_H)
|
||||
#define FRED_MEMORY_BANK_H
|
||||
|
||||
struct Memory_Header{
|
||||
Memory_Header *next;
|
||||
};
|
||||
|
||||
struct Memory_Bank{
|
||||
Heap heap;
|
||||
Memory_Header *first;
|
||||
Memory_Header *last;
|
||||
umem total_memory_size;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
456
4ed_undo.cpp
456
4ed_undo.cpp
|
@ -1,456 +0,0 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 24.03.2018
|
||||
*
|
||||
* Undo
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
internal void
|
||||
undo_stack_grow_string(Heap *heap, Edit_Stack *stack, i32 extra_size){
|
||||
i32 old_max = stack->max;
|
||||
u8 *old_str = stack->strings;
|
||||
i32 new_max = old_max*2 + extra_size;
|
||||
u8 *new_str = heap_array(heap, u8, new_max);
|
||||
memcpy(new_str, old_str, sizeof(*new_str)*old_max);
|
||||
heap_free(heap, old_str);
|
||||
stack->strings = new_str;
|
||||
stack->max = new_max;
|
||||
}
|
||||
|
||||
internal void
|
||||
undo_stack_grow_edits(Heap *heap, Edit_Stack *stack){
|
||||
i32 old_max = stack->edit_max;
|
||||
Edit_Step *old_eds = stack->edits;
|
||||
i32 new_max = old_max*2 + 2;
|
||||
Edit_Step *new_eds = heap_array(heap, Edit_Step, new_max);
|
||||
memcpy(new_eds, old_eds, sizeof(*new_eds)*old_max);
|
||||
heap_free(heap, old_eds);
|
||||
stack->edits = new_eds;
|
||||
stack->edit_max = new_max;
|
||||
}
|
||||
|
||||
internal void
|
||||
child_stack_grow_string(Heap *heap, Small_Edit_Stack *stack, i32 extra_size){
|
||||
i32 old_max = stack->max;
|
||||
u8 *old_str = stack->strings;
|
||||
i32 new_max = old_max*2 + extra_size;
|
||||
u8 *new_str = heap_array(heap, u8, new_max);
|
||||
memcpy(new_str, old_str, sizeof(*new_str)*old_max);
|
||||
heap_free(heap, old_str);
|
||||
stack->strings = new_str;
|
||||
stack->max = new_max;
|
||||
}
|
||||
|
||||
internal void
|
||||
child_stack_grow_edits(Heap *heap, Small_Edit_Stack *stack, i32 amount){
|
||||
i32 old_max = stack->edit_max;
|
||||
Buffer_Edit *old_eds = stack->edits;
|
||||
i32 new_max = old_max*2 + amount;
|
||||
Buffer_Edit *new_eds = heap_array(heap, Buffer_Edit, new_max);
|
||||
memcpy(new_eds, old_eds, sizeof(*new_eds)*new_max);
|
||||
heap_free(heap, old_eds);
|
||||
stack->edits = new_eds;
|
||||
stack->edit_max = new_max;
|
||||
}
|
||||
|
||||
internal i32
|
||||
undo_children_push(Heap *heap, Small_Edit_Stack *children, Buffer_Edit *edits, i32 edit_count, u8 *strings, i32 string_size){
|
||||
i32 result = children->edit_count;
|
||||
if (children->edit_count + edit_count > children->edit_max){
|
||||
child_stack_grow_edits(heap, children, edit_count);
|
||||
}
|
||||
|
||||
if (children->size + string_size > children->max){
|
||||
child_stack_grow_string(heap, children, string_size);
|
||||
}
|
||||
|
||||
memcpy(children->edits + children->edit_count, edits, edit_count*sizeof(Buffer_Edit));
|
||||
memcpy(children->strings + children->size, strings, string_size);
|
||||
|
||||
Buffer_Edit *edit = children->edits + children->edit_count;
|
||||
i32 start_pos = children->size;
|
||||
for (i32 i = 0; i < edit_count; ++i, ++edit){
|
||||
edit->str_start += start_pos;
|
||||
}
|
||||
|
||||
children->edit_count += edit_count;
|
||||
children->size += string_size;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal Edit_Step*
|
||||
file_post_undo(Heap *heap, Editing_File *file, Edit_Step step, b32 do_merge, b32 can_merge){
|
||||
if (step.type == ED_NORMAL){
|
||||
file->state.undo.redo.size = 0;
|
||||
file->state.undo.redo.edit_count = 0;
|
||||
}
|
||||
|
||||
Edit_Stack *undo = &file->state.undo.undo;
|
||||
Edit_Step *result = 0;
|
||||
|
||||
if (step.child_count == 0){
|
||||
if (step.edit.end - step.edit.start + undo->size > undo->max){
|
||||
undo_stack_grow_string(heap, undo, step.edit.end - step.edit.start);
|
||||
}
|
||||
|
||||
Buffer_Edit inv;
|
||||
buffer_invert_edit(&file->state.buffer, step.edit, &inv, (char*)undo->strings, &undo->size, undo->max);
|
||||
|
||||
Edit_Step inv_step = {};
|
||||
inv_step.edit = inv;
|
||||
inv_step.can_merge = (b8)can_merge;
|
||||
inv_step.type = ED_UNDO;
|
||||
|
||||
b32 did_merge = 0;
|
||||
if (do_merge && undo->edit_count > 0){
|
||||
Edit_Step prev = undo->edits[undo->edit_count-1];
|
||||
if (prev.can_merge && inv_step.edit.len == 0 && prev.edit.len == 0){
|
||||
if (prev.edit.end == inv_step.edit.start){
|
||||
did_merge = 1;
|
||||
inv_step.edit.start = prev.edit.start;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (did_merge){
|
||||
result = undo->edits + (undo->edit_count-1);
|
||||
*result = inv_step;
|
||||
}
|
||||
else{
|
||||
if (undo->edit_count == undo->edit_max){
|
||||
undo_stack_grow_edits(heap, undo);
|
||||
}
|
||||
|
||||
result = undo->edits + (undo->edit_count++);
|
||||
*result = inv_step;
|
||||
}
|
||||
}
|
||||
else{
|
||||
Edit_Step inv_step = {};
|
||||
inv_step.type = ED_UNDO;
|
||||
inv_step.first_child = step.inverse_first_child;
|
||||
inv_step.inverse_first_child = step.first_child;
|
||||
inv_step.special_type = step.special_type;
|
||||
inv_step.child_count = step.inverse_child_count;
|
||||
inv_step.inverse_child_count = step.child_count;
|
||||
|
||||
if (undo->edit_count == undo->edit_max){
|
||||
undo_stack_grow_edits(heap, undo);
|
||||
}
|
||||
result = undo->edits + (undo->edit_count++);
|
||||
*result = inv_step;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal void
|
||||
undo_stack_pop(Edit_Stack *stack){
|
||||
if (stack->edit_count > 0){
|
||||
Edit_Step *edit = stack->edits + (--stack->edit_count);
|
||||
if (edit->child_count == 0){
|
||||
stack->size -= edit->edit.len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
file_post_redo(Heap *heap, Editing_File *file, Edit_Step step){
|
||||
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(heap, redo, step.edit.end - step.edit.start);
|
||||
}
|
||||
|
||||
Buffer_Edit inv;
|
||||
buffer_invert_edit(&file->state.buffer, step.edit, &inv, (char*)redo->strings, &redo->size, redo->max);
|
||||
|
||||
Edit_Step inv_step = {};
|
||||
inv_step.edit = inv;
|
||||
inv_step.type = ED_REDO;
|
||||
|
||||
if (redo->edit_count == redo->edit_max){
|
||||
undo_stack_grow_edits(heap, redo);
|
||||
}
|
||||
redo->edits[redo->edit_count++] = inv_step;
|
||||
}
|
||||
else{
|
||||
Edit_Step inv_step = {};
|
||||
inv_step.type = ED_REDO;
|
||||
inv_step.first_child = step.inverse_first_child;
|
||||
inv_step.inverse_first_child = step.first_child;
|
||||
inv_step.special_type = step.special_type;
|
||||
inv_step.child_count = step.inverse_child_count;
|
||||
inv_step.inverse_child_count = step.child_count;
|
||||
|
||||
if (redo->edit_count == redo->edit_max){
|
||||
undo_stack_grow_edits(heap, redo);
|
||||
}
|
||||
redo->edits[redo->edit_count++] = inv_step;
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
file_post_history_block(Editing_File *file, i32 pos){
|
||||
Assert(file->state.undo.history_head_block < pos);
|
||||
Assert(pos < file->state.undo.history.edit_count);
|
||||
|
||||
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->state.undo.history_head_block;
|
||||
file->state.undo.history_head_block = pos;
|
||||
++file->state.undo.history_block_count;
|
||||
}
|
||||
|
||||
internal void
|
||||
file_unpost_history_block(Editing_File *file){
|
||||
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;
|
||||
}
|
||||
|
||||
internal Edit_Step*
|
||||
file_post_history(Heap *heap, Editing_File *file, Edit_Step step, b32 do_merge, b32 can_merge){
|
||||
Edit_Stack *history = &file->state.undo.history;
|
||||
Edit_Step *result = 0;
|
||||
|
||||
local_persist Edit_Type reverse_types[4];
|
||||
if (reverse_types[ED_UNDO] == 0){
|
||||
reverse_types[ED_NORMAL] = ED_REVERSE_NORMAL;
|
||||
reverse_types[ED_REVERSE_NORMAL] = ED_NORMAL;
|
||||
reverse_types[ED_UNDO] = ED_REDO;
|
||||
reverse_types[ED_REDO] = ED_UNDO;
|
||||
}
|
||||
|
||||
if (step.child_count == 0){
|
||||
if (step.edit.end - step.edit.start + history->size > history->max){
|
||||
undo_stack_grow_string(heap, history, step.edit.end - step.edit.start);
|
||||
}
|
||||
|
||||
Buffer_Edit inv;
|
||||
buffer_invert_edit(&file->state.buffer, step.edit, &inv,
|
||||
(char*)history->strings, &history->size, history->max);
|
||||
|
||||
Edit_Step inv_step = {};
|
||||
inv_step.edit = inv;
|
||||
inv_step.can_merge = (b8)can_merge;
|
||||
inv_step.type = reverse_types[step.type];
|
||||
|
||||
b32 did_merge = 0;
|
||||
if (do_merge && history->edit_count > 0){
|
||||
Edit_Step prev = history->edits[history->edit_count-1];
|
||||
if (prev.can_merge && inv_step.edit.len == 0 && prev.edit.len == 0){
|
||||
if (prev.edit.end == inv_step.edit.start){
|
||||
did_merge = 1;
|
||||
inv_step.edit.start = prev.edit.start;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (did_merge){
|
||||
result = history->edits + (history->edit_count-1);
|
||||
}
|
||||
else{
|
||||
if (history->edit_count == history->edit_max){
|
||||
undo_stack_grow_edits(heap, history);
|
||||
}
|
||||
result = history->edits + (history->edit_count++);
|
||||
}
|
||||
|
||||
*result = inv_step;
|
||||
}
|
||||
else{
|
||||
Edit_Step inv_step = {};
|
||||
inv_step.type = reverse_types[step.type];
|
||||
inv_step.first_child = step.inverse_first_child;
|
||||
inv_step.inverse_first_child = step.first_child;
|
||||
inv_step.special_type = step.special_type;
|
||||
inv_step.inverse_child_count = step.child_count;
|
||||
inv_step.child_count = step.inverse_child_count;
|
||||
|
||||
if (history->edit_count == history->edit_max){
|
||||
undo_stack_grow_edits(heap, history);
|
||||
}
|
||||
result = history->edits + (history->edit_count++);
|
||||
*result = inv_step;
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal void
|
||||
file_update_history_before_edit(Mem_Options *mem, Editing_File *file, Edit_Step step, u8 *str, History_Mode history_mode){
|
||||
if (!file->state.undo.undo.edits) return;
|
||||
Heap *heap = &mem->heap;
|
||||
|
||||
b32 can_merge = 0, do_merge = 0;
|
||||
switch (step.type){
|
||||
case ED_NORMAL:
|
||||
{
|
||||
if (step.edit.len == 1 && str && char_is_alpha_numeric(*str)){
|
||||
can_merge = 1;
|
||||
}
|
||||
if (step.edit.len == 1 && str && (can_merge || char_is_whitespace(*str))){
|
||||
do_merge = 1;
|
||||
}
|
||||
|
||||
if (history_mode != hist_forward){
|
||||
file_post_history(heap, file, step, do_merge, can_merge);
|
||||
}
|
||||
|
||||
file_post_undo(heap, file, step, do_merge, can_merge);
|
||||
}break;
|
||||
|
||||
case ED_REVERSE_NORMAL:
|
||||
{
|
||||
if (history_mode != hist_forward){
|
||||
file_post_history(heap, file, step, do_merge, can_merge);
|
||||
}
|
||||
|
||||
undo_stack_pop(&file->state.undo.undo);
|
||||
|
||||
b32 restore_redos = 0;
|
||||
Edit_Step *redo_end = 0;
|
||||
|
||||
if (history_mode == hist_backward && file->state.undo.edit_history_cursor > 0){
|
||||
restore_redos = 1;
|
||||
redo_end = file->state.undo.history.edits + (file->state.undo.edit_history_cursor - 1);
|
||||
}
|
||||
else if (history_mode == hist_forward && file->state.undo.history.edit_count > 0){
|
||||
restore_redos = 1;
|
||||
redo_end = file->state.undo.history.edits + (file->state.undo.history.edit_count - 1);
|
||||
}
|
||||
|
||||
if (restore_redos){
|
||||
Edit_Step *redo_start = redo_end;
|
||||
i32 steps_of_redo = 0;
|
||||
i32 strings_of_redo = 0;
|
||||
{
|
||||
i32 undo_count = 0;
|
||||
while (redo_start->type == ED_REDO || redo_start->type == ED_UNDO){
|
||||
if (redo_start->type == ED_REDO){
|
||||
if (undo_count > 0){
|
||||
--undo_count;
|
||||
}
|
||||
else{
|
||||
++steps_of_redo;
|
||||
strings_of_redo += redo_start->edit.len;
|
||||
}
|
||||
}
|
||||
else{
|
||||
++undo_count;
|
||||
}
|
||||
--redo_start;
|
||||
}
|
||||
}
|
||||
|
||||
if (redo_start < redo_end){
|
||||
++redo_start;
|
||||
++redo_end;
|
||||
|
||||
if (file->state.undo.redo.edit_count + steps_of_redo > file->state.undo.redo.edit_max)
|
||||
undo_stack_grow_edits(heap, &file->state.undo.redo);
|
||||
|
||||
if (file->state.undo.redo.size + strings_of_redo > file->state.undo.redo.max)
|
||||
undo_stack_grow_string(heap, &file->state.undo.redo, 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->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;){
|
||||
--edit_src;
|
||||
str_src -= edit_src->edit.len;
|
||||
if (edit_src->type == ED_REDO){
|
||||
if (undo_count > 0){
|
||||
--undo_count;
|
||||
}
|
||||
else{
|
||||
++i;
|
||||
|
||||
--edit_dest;
|
||||
*edit_dest = *edit_src;
|
||||
|
||||
str_redo_pos -= edit_dest->edit.len;
|
||||
edit_dest->edit.str_start = str_redo_pos;
|
||||
|
||||
memcpy(str_dest_base + str_redo_pos, str_src, edit_dest->edit.len);
|
||||
}
|
||||
}
|
||||
else{
|
||||
++undo_count;
|
||||
}
|
||||
}
|
||||
Assert(undo_count == 0);
|
||||
}
|
||||
|
||||
file->state.undo.redo.size += strings_of_redo;
|
||||
file->state.undo.redo.edit_count += steps_of_redo;
|
||||
}
|
||||
}
|
||||
}break;
|
||||
|
||||
case ED_UNDO:
|
||||
{
|
||||
if (history_mode != hist_forward){
|
||||
file_post_history(heap, file, step, do_merge, can_merge);
|
||||
}
|
||||
file_post_redo(heap, file, step);
|
||||
undo_stack_pop(&file->state.undo.undo);
|
||||
}break;
|
||||
|
||||
case ED_REDO:
|
||||
{
|
||||
if (step.edit.len == 1 && str && char_is_alpha_numeric(*str)) can_merge = 1;
|
||||
if (step.edit.len == 1 && str && (can_merge || char_is_whitespace(*str))) do_merge = 1;
|
||||
|
||||
if (history_mode != hist_forward){
|
||||
file_post_history(heap, file, step, do_merge, can_merge);
|
||||
}
|
||||
|
||||
file_post_undo(heap, file, step, do_merge, can_merge);
|
||||
undo_stack_pop(&file->state.undo.redo);
|
||||
}break;
|
||||
}
|
||||
|
||||
if (history_mode != hist_forward){
|
||||
if (step.type == ED_UNDO || step.type == ED_REDO){
|
||||
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->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->state.undo.history_head_block == file->state.undo.history.edit_count){
|
||||
file_unpost_history_block(file);
|
||||
file->state.undo.current_block_normal = !file->state.undo.current_block_normal;
|
||||
}
|
||||
}
|
||||
|
||||
if (history_mode == hist_normal){
|
||||
file->state.undo.edit_history_cursor = file->state.undo.history.edit_count;
|
||||
}
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
73
4ed_undo.h
73
4ed_undo.h
|
@ -1,73 +0,0 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 24.01.2018
|
||||
*
|
||||
* Buffer types
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#if !defined(FRED_UNDO_H)
|
||||
#define FRED_UNDO_H
|
||||
|
||||
enum Edit_Type{
|
||||
ED_NORMAL,
|
||||
ED_REVERSE_NORMAL,
|
||||
ED_UNDO,
|
||||
ED_REDO,
|
||||
};
|
||||
|
||||
struct Edit_Step{
|
||||
Edit_Type type;
|
||||
union{
|
||||
struct{
|
||||
b32 can_merge;
|
||||
Buffer_Edit edit;
|
||||
i32 next_block;
|
||||
i32 prev_block;
|
||||
};
|
||||
struct{
|
||||
i32 first_child;
|
||||
i32 inverse_first_child;
|
||||
i32 inverse_child_count;
|
||||
i32 special_type;
|
||||
};
|
||||
};
|
||||
i32 child_count;
|
||||
};
|
||||
|
||||
struct Edit_Stack{
|
||||
u8 *strings;
|
||||
i32 size;
|
||||
i32 max;
|
||||
Edit_Step *edits;
|
||||
i32 edit_count;
|
||||
i32 edit_max;
|
||||
};
|
||||
|
||||
struct Small_Edit_Stack{
|
||||
u8 *strings;
|
||||
i32 size;
|
||||
i32 max;
|
||||
Buffer_Edit *edits;
|
||||
i32 edit_count;
|
||||
i32 edit_max;
|
||||
};
|
||||
|
||||
struct Undo_Data{
|
||||
Edit_Stack undo;
|
||||
Edit_Stack redo;
|
||||
Edit_Stack history;
|
||||
Small_Edit_Stack children;
|
||||
|
||||
i32 history_block_count;
|
||||
i32 history_head_block;
|
||||
i32 edit_history_cursor;
|
||||
b32 current_block_normal;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
26
4ed_view.h
26
4ed_view.h
|
@ -114,11 +114,6 @@ struct Shift_Information{
|
|||
i32 amount;
|
||||
};
|
||||
|
||||
struct Edit_Spec{
|
||||
u8 *str;
|
||||
Edit_Step step;
|
||||
};
|
||||
|
||||
struct Relative_Scrolling{
|
||||
f32 scroll_x;
|
||||
f32 scroll_y;
|
||||
|
@ -126,20 +121,6 @@ struct Relative_Scrolling{
|
|||
f32 target_y;
|
||||
};
|
||||
|
||||
struct Cursor_Fix_Descriptor{
|
||||
b32 is_batch;
|
||||
union{
|
||||
struct{
|
||||
Buffer_Edit *batch;
|
||||
i32 batch_size;
|
||||
};
|
||||
struct{
|
||||
i32 start, end;
|
||||
i32 shift_amount;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
struct File_Bar{
|
||||
f32 pos_x;
|
||||
f32 pos_y;
|
||||
|
@ -196,13 +177,6 @@ enum{
|
|||
FileCreateFlag_ReadOnly = 1,
|
||||
};
|
||||
|
||||
typedef i32 History_Mode;
|
||||
enum{
|
||||
hist_normal,
|
||||
hist_backward,
|
||||
hist_forward
|
||||
};
|
||||
|
||||
struct Render_Marker{
|
||||
Marker_Visual_Type type;
|
||||
u32 color;
|
||||
|
|
Loading…
Reference in New Issue