struct Theme_Color {
Style_Tag tag;
diff --git a/4coder_custom_api.h b/4coder_custom_api.h
index 45c7282e..2086c39e 100644
--- a/4coder_custom_api.h
+++ b/4coder_custom_api.h
@@ -10,6 +10,7 @@
#define BUFFER_BOUNDARY_SEEK_SIG(n) int32_t n(Application_Links *app, Buffer_Summary *buffer, int32_t start_pos, bool32 seek_forward, Seek_Boundary_Flag flags)
#define BUFFER_READ_RANGE_SIG(n) bool32 n(Application_Links *app, Buffer_Summary *buffer, int32_t start, int32_t end, char *out)
#define BUFFER_REPLACE_RANGE_SIG(n) bool32 n(Application_Links *app, Buffer_Summary *buffer, int32_t start, int32_t end, char *str, int32_t len)
+#define BUFFER_BATCH_EDIT_SIG(n) bool32 n(Application_Links *app, Buffer_Summary *buffer, char *str, int32_t str_len, Buffer_Edit *edits, int32_t edit_count, Buffer_Batch_Edit_Type type)
#define BUFFER_SET_SETTING_SIG(n) bool32 n(Application_Links *app, Buffer_Summary *buffer, Buffer_Setting_ID setting, int32_t value)
#define BUFFER_AUTO_INDENT_SIG(n) bool32 n(Application_Links *app, Buffer_Summary *buffer, int32_t start, int32_t end, int32_t tab_width, Auto_Indent_Flag flags)
#define CREATE_BUFFER_SIG(n) Buffer_Summary n(Application_Links *app, char *filename, int32_t filename_len, Buffer_Create_Flag flags)
@@ -60,6 +61,7 @@ extern "C"{
typedef BUFFER_BOUNDARY_SEEK_SIG(Buffer_Boundary_Seek_Function);
typedef BUFFER_READ_RANGE_SIG(Buffer_Read_Range_Function);
typedef BUFFER_REPLACE_RANGE_SIG(Buffer_Replace_Range_Function);
+ typedef BUFFER_BATCH_EDIT_SIG(Buffer_Batch_Edit_Function);
typedef BUFFER_SET_SETTING_SIG(Buffer_Set_Setting_Function);
typedef BUFFER_AUTO_INDENT_SIG(Buffer_Auto_Indent_Function);
typedef CREATE_BUFFER_SIG(Create_Buffer_Function);
@@ -113,6 +115,7 @@ struct Application_Links{
Buffer_Boundary_Seek_Function *buffer_boundary_seek;
Buffer_Read_Range_Function *buffer_read_range;
Buffer_Replace_Range_Function *buffer_replace_range;
+ Buffer_Batch_Edit_Function *buffer_batch_edit;
Buffer_Set_Setting_Function *buffer_set_setting;
Buffer_Auto_Indent_Function *buffer_auto_indent;
Create_Buffer_Function *create_buffer;
@@ -168,6 +171,7 @@ app_links->get_buffer_by_name = Get_Buffer_By_Name;\
app_links->buffer_boundary_seek = Buffer_Boundary_Seek;\
app_links->buffer_read_range = Buffer_Read_Range;\
app_links->buffer_replace_range = Buffer_Replace_Range;\
+app_links->buffer_batch_edit = Buffer_Batch_Edit;\
app_links->buffer_set_setting = Buffer_Set_Setting;\
app_links->buffer_auto_indent = Buffer_Auto_Indent;\
app_links->create_buffer = Create_Buffer;\
diff --git a/4coder_default_include.cpp b/4coder_default_include.cpp
index 17953034..c1e6e670 100644
--- a/4coder_default_include.cpp
+++ b/4coder_default_include.cpp
@@ -1405,6 +1405,10 @@ CUSTOM_COMMAND_SIG(open_in_other_regular){
# define open_in_other open_in_other_regular
#endif
+//
+// Auto Indenting and Whitespace
+//
+
CUSTOM_COMMAND_SIG(auto_tab_line_at_cursor){
unsigned int access = AccessOpen;
View_Summary view = app->get_active_view(app, access);
@@ -1446,6 +1450,66 @@ CUSTOM_COMMAND_SIG(write_and_auto_tab){
exec_command(app, auto_tab_line_at_cursor);
}
+CUSTOM_COMMAND_SIG(clean_all_lines){
+ View_Summary view = app->get_active_view(app, AccessOpen);
+ Buffer_Summary buffer = app->get_buffer(app, view.buffer_id, AccessOpen);
+
+ int line_count = buffer.line_count;
+ int edit_max = line_count;
+
+ if (edit_max*sizeof(Buffer_Edit) < app->memory_size){
+ Buffer_Edit *edits = (Buffer_Edit*)app->memory;
+
+ char data[1024];
+ Stream_Chunk chunk = {0};
+
+ int i = 0;
+ if (init_stream_chunk(&chunk, app, &buffer,
+ 0, data, sizeof(data))){
+ Buffer_Edit *edit = edits;
+
+ int buffer_size = buffer.size;
+ int still_looping = true;
+ int need_stopper = true;
+ int last_hard = buffer_size;
+ do{
+ if (need_stopper && !still_looping){
+ chunk.end = i+1;
+ chunk.data[0] = '\n';
+ need_stopper = false;
+ }
+
+ for (; i < chunk.end; ++i){
+ char at_pos = chunk.data[i];
+ if (at_pos == '\n'){
+ if (last_hard+1 < i){
+ edit->str_start = 0;
+ edit->len = 0;
+ edit->start = last_hard+1;
+ edit->end = i;
+ ++edit;
+ i = buffer_size;
+ }
+ }
+ else if (char_is_whitespace(at_pos)){
+ // NOTE(allen): do nothing
+ }
+ else{
+ last_hard = i;
+ }
+ }
+
+ if (still_looping){
+ still_looping = forward_stream_chunk(&chunk);
+ }
+ }while(still_looping && need_stopper);
+
+ int edit_count = (int)(edit - edits);
+ app->buffer_batch_edit(app, &buffer, 0, edits, edit_count, BatchEdit_PreserveTokens);
+ }
+ }
+}
+
//
// Default Building Stuff
//
@@ -1455,7 +1519,7 @@ CUSTOM_COMMAND_SIG(write_and_auto_tab){
// directory of the given buffer, it cannot it get's the 4coder hot directory.
// This behavior is a little different than previous versions of 4coder.
//
-// There is requirement that a custom build system in 4coder actually use the
+// There is no requirement that a custom build system in 4coder actually use the
// directory given by this function.
enum Get_Build_Directory_Result{
BuildDir_None,
diff --git a/4coder_types.h b/4coder_types.h
index 3cd11926..8f853701 100644
--- a/4coder_types.h
+++ b/4coder_types.h
@@ -122,6 +122,15 @@ ENUM(int32_t, Event_Message_Type_ID){
EventMessage_CloseView
};
+/* DOC(A Buffer_Batch_Edit_Type is a type of batch operation.) */
+ENUM(int32_t, Buffer_Batch_Edit_Type){
+ /* DOC(The BatchEdit_Normal operation is always correct but does the most work.) */
+ BatchEdit_Normal,
+ /* DOC(The BatchEdit_PreserveTokens operation is one in which none of the edits add, delete, or change any tokens.
+ This usually applies when whitespace is being replaced with whitespace.) */
+ BatchEdit_PreserveTokens
+}
+
/* DOC(A Buffer_Setting_ID names a setting in a buffer.) */
ENUM(int32_t, Buffer_Setting_ID){
/* DOC(BufferSetting_Null is not a valid setting, it is reserved to detect errors.) */
@@ -521,6 +530,20 @@ struct Buffer_Seek{
};
};
+/* 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)*/
struct Buffer_Summary{
@@ -543,6 +566,8 @@ struct Buffer_Summary{
/* DOC(If this is not a null summary, this field specifies the size of the text in the buffer.) */
int32_t size;
+ /* DOC(If this is not a null summary, this field specifies the number of lines in the buffer.) */
+ int32_t line_count;
/* DOC(If this is not a null summary, this field specifies the file name associated to this buffer.) */
char *file_name;
diff --git a/4ed.cpp b/4ed.cpp
index 7b050b75..aceb3272 100644
--- a/4ed.cpp
+++ b/4ed.cpp
@@ -744,7 +744,64 @@ COMMAND_DECL(clean_all_lines){
REQ_OPEN_VIEW(view);
REQ_FILE(file, view);
- view_clean_whitespace(system, models, view);
+ Mem_Options *mem = &models->mem;
+ Editing_File *file = view->file_data.file;
+
+ Partition *part = &mem->part;
+ i32 line_count = file->state.buffer.line_count;
+ i32 edit_max = line_count * 2;
+ i32 edit_count = 0;
+
+ Assert(file && !file->is_dummy);
+ Assert(view->edit_pos);
+
+ Temp_Memory temp = begin_temp_memory(part);
+ Buffer_Edit *edits = push_array(part, Buffer_Edit, edit_max);
+
+ char *str_base = (char*)part->base + part->pos;
+ i32 str_size = 0;
+ for (i32 line_i = 0; line_i < line_count; ++line_i){
+ i32 start = file->state.buffer.line_starts[line_i];
+ Hard_Start_Result hard_start =
+ buffer_find_hard_start(&file->state.buffer, start, 4);
+
+ if (hard_start.all_whitespace){
+ hard_start.indent_pos = 0;
+ }
+
+ if ((hard_start.all_whitespace && hard_start.char_pos > start) || !hard_start.all_space){
+ Buffer_Edit new_edit;
+ new_edit.str_start = str_size;
+ str_size += hard_start.indent_pos;
+ char *str = push_array(part, char, hard_start.indent_pos);
+ for (i32 j = 0; j < hard_start.indent_pos; ++j) str[j] = ' ';
+ new_edit.len = hard_start.indent_pos;
+ new_edit.start = start;
+ new_edit.end = hard_start.char_pos;
+ edits[edit_count++] = new_edit;
+ }
+ Assert(edit_count <= edit_max);
+ }
+
+ if (edit_count > 0){
+ Assert(buffer_batch_debug_sort_check(edits, edit_count));
+
+ // NOTE(allen): computing edit spec, doing batch edit
+ Buffer_Edit *inverse_array = push_array(part, Buffer_Edit, edit_count);
+ Assert(inverse_array);
+
+ char *inv_str = (char*)part->base + part->pos;
+ Edit_Spec spec =
+ file_compute_whitespace_edit(mem, file,
+ view->edit_pos->cursor.pos,
+ edits, str_base, str_size,
+ inverse_array, inv_str,
+ part->max - part->pos, edit_count);
+
+ file_do_white_batch_edit(system, models, view->file_data.file, spec, hist_normal);
+ }
+
+ end_temp_memory(temp);
}
COMMAND_DECL(open_panel_vsplit){
diff --git a/4ed_api_implementation.cpp b/4ed_api_implementation.cpp
index 990927e3..e0dd4df7 100644
--- a/4ed_api_implementation.cpp
+++ b/4ed_api_implementation.cpp
@@ -24,6 +24,7 @@ fill_buffer_summary(Buffer_Summary *buffer, Editing_File *file, Working_Set *wor
buffer->buffer_id = file->id.id;
buffer->size = file->state.buffer.size;
+ buffer->line_count = file->state.buffer.line_count;
buffer->file_name_len = file->name.source_path.size;
buffer->buffer_name_len = file->name.live_name.size;
@@ -701,6 +702,56 @@ DOC_SEE(4coder_Buffer_Positioning_System)
return(result);
}
+API_EXPORT bool32
+Buffer_Batch_Edit(Application_Links *app, Buffer_Summary *buffer, char *str, int32_t str_len, Buffer_Edit *edits, int32_t edit_count, Buffer_Batch_Edit_Type type)/*
+DOC_PARAM(str, This parameter provides all of the source string for the edits in the batch.)
+DOC_PARAM(str_len, This parameter specifies the length of the str string.)
+DOC_PARAM(edits, This parameter provides about the source string and destination range of each edit as an array.)
+DOC_PARAM(edit_count, This parameter specifies the number of Buffer_Edit structs in edits.)
+DOC_PARAM(type, This prameter specifies what type of batch edit to execute.)
+DOC_RETURN(This call returns non-zero if the batch edit succeeds.)
+DOC()
+DOC_SEE(Buffer_Edit)
+DOC_SEE(Buffer_Batch_Edit_Type)
+*/{
+ Command_Data *cmd = (Command_Data*)app->cmd_context;
+ Mem_Options *mem = cmd->models;
+ Partition *part = &models->mem.part;
+ Editing_File *file = imp_get_file(cmd, buffer);
+
+ bool32 result = false;
+
+ if (file){
+ Temp_Memory temp = begin_temp_memory(part);
+ Buffer_Edit *inverse_edits = push_array(part, Buffer_Edit, edit_count);
+ char *inv_str = (char*)part->base + part->pos;
+ int inv_str_max = part->max - part->pos;
+ Assert(inverse_edits);
+
+ switch (type){
+ case BatchEdit_Normal:
+ {
+ // TODO(allen):
+ }break;
+
+ case BatchEdit_PreserveTokens:
+ {
+ Edit_Spec spec =
+ file_compute_whitespace_edit(mem, file,
+ edits, str, str_len,
+ inverse_edits, inv_str, inv_str_max,
+ edit_count);
+
+ file_do_white_batch_edit(system, models, file, spec, hist_normal);
+ }break;
+ }
+
+ end_temp_memory(part);
+ }
+
+ return(result);
+}
+
API_EXPORT bool32
Buffer_Set_Setting(Application_Links *app, Buffer_Summary *buffer, Buffer_Setting_ID setting, int32_t value)/*
DOC_PARAM(buffer, The buffer parameter specifies the buffer on which to set a setting.)
diff --git a/4ed_file_view.cpp b/4ed_file_view.cpp
index a871fb81..0f8a7818 100644
--- a/4ed_file_view.cpp
+++ b/4ed_file_view.cpp
@@ -2532,7 +2532,7 @@ clipboard_copy(System_Functions *system, General_Memory *general, Working_Set *w
}
internal Edit_Spec
-file_compute_whitespace_edit(Mem_Options *mem, Editing_File *file, i32 cursor_pos,
+file_compute_whitespace_edit(Mem_Options *mem, 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){
@@ -2563,66 +2563,6 @@ file_compute_whitespace_edit(Mem_Options *mem, Editing_File *file, i32 cursor_po
return(spec);
}
-internal void
-view_clean_whitespace(System_Functions *system, Models *models, View *view){
- Mem_Options *mem = &models->mem;
- Editing_File *file = view->file_data.file;
-
- Partition *part = &mem->part;
- i32 line_count = file->state.buffer.line_count;
- i32 edit_max = line_count * 2;
- i32 edit_count = 0;
-
- Assert(file && !file->is_dummy);
- Assert(view->edit_pos);
-
- Temp_Memory temp = begin_temp_memory(part);
- Buffer_Edit *edits = push_array(part, Buffer_Edit, edit_max);
-
- char *str_base = (char*)part->base + part->pos;
- i32 str_size = 0;
- for (i32 line_i = 0; line_i < line_count; ++line_i){
- i32 start = file->state.buffer.line_starts[line_i];
- Hard_Start_Result hard_start =
- buffer_find_hard_start(&file->state.buffer, start, 4);
-
- if (hard_start.all_whitespace) hard_start.indent_pos = 0;
-
- if ((hard_start.all_whitespace && hard_start.char_pos > start) || !hard_start.all_space){
- Buffer_Edit new_edit;
- new_edit.str_start = str_size;
- str_size += hard_start.indent_pos;
- char *str = push_array(part, char, hard_start.indent_pos);
- for (i32 j = 0; j < hard_start.indent_pos; ++j) str[j] = ' ';
- new_edit.len = hard_start.indent_pos;
- new_edit.start = start;
- new_edit.end = hard_start.char_pos;
- edits[edit_count++] = new_edit;
- }
- Assert(edit_count <= edit_max);
- }
-
- if (edit_count > 0){
- Assert(buffer_batch_debug_sort_check(edits, edit_count));
-
- // NOTE(allen): computing edit spec, doing batch edit
- Buffer_Edit *inverse_array = push_array(part, Buffer_Edit, edit_count);
- Assert(inverse_array);
-
- char *inv_str = (char*)part->base + part->pos;
- Edit_Spec spec =
- file_compute_whitespace_edit(mem, file,
- view->edit_pos->cursor.pos,
- edits, str_base, str_size,
- inverse_array, inv_str,
- part->max - part->pos, edit_count);
-
- file_do_white_batch_edit(system, models, view->file_data.file, spec, hist_normal);
- }
-
- end_temp_memory(temp);
-}
-
struct Indent_Options{
b32 empty_blank_lines;
b32 use_tabs;
diff --git a/4tech_table.cpp b/4tech_table.cpp
index fc4257c4..c1e47932 100644
--- a/4tech_table.cpp
+++ b/4tech_table.cpp
@@ -20,7 +20,6 @@ struct Table{
u32 *hash_array;
u8 *data_array;
i32 count, max;
-
i32 item_size;
};
diff --git a/buffer/4coder_shared.cpp b/buffer/4coder_shared.cpp
index cb1ee47b..ccd8b886 100644
--- a/buffer/4coder_shared.cpp
+++ b/buffer/4coder_shared.cpp
@@ -78,11 +78,6 @@ lroundup_(int x, int granularity){
#define measure_character(a,c) ((a)[c])
-typedef struct Buffer_Edit{
- int str_start, len;
- int start, end;
-} Buffer_Edit;
-
typedef struct Buffer_Batch_State{
int i;
int shift_total;