This call gets the current size of the temporary buffer in the lexer state so
diff --git a/4coder_types.h b/4coder_types.h
index 17c839a8..91bd99df 100644
--- a/4coder_types.h
+++ b/4coder_types.h
@@ -57,7 +57,7 @@ ENUM(uint64_t, Command_ID){
cmdid_redo,
/* DOC(cmdid_history_backward performs a step backwards through the file history, which includes previously lost redo branches.) */
cmdid_history_backward,
- /* DOC(cmdid_history_forward unperforms the previous cmdid_history_backward step if possib.e) */
+ /* DOC(cmdid_history_forward unperforms the previous cmdid_history_backward step if possible.) */
cmdid_history_forward,
/* DOC(cmdid_interactive_new begins an interactive dialogue to create a new buffer.) */
diff --git a/4cpp_lexer.h b/4cpp_lexer.h
index ca863081..a13f8774 100644
--- a/4cpp_lexer.h
+++ b/4cpp_lexer.h
@@ -1034,7 +1034,7 @@ DOC_SEE(Cpp_Lex_Data)
FCPP_LINK Cpp_Lex_Data
cpp_lex_data_init(char *mem_buffer)/*
-DOC_PARAM(tb, The memory to use for initializing the lex state's temp memory buffer.)
+DOC_PARAM(mem_buffer, The memory to use for initializing the lex state's temp memory buffer.)
DOC_RETURN(A brand new lex state ready to begin lexing a file from the beginning.)
DOC(Creates a new lex state in the form of a Cpp_Lex_Data struct and returns the struct.
@@ -1081,6 +1081,7 @@ FCPP_LINK void
cpp_lex_data_new_temp(Cpp_Lex_Data *lex_data, char *new_buffer)/*
DOC_PARAM(lex_data, The lex state that will receive the new temporary buffer.)
DOC_PARAM(new_buffer, The new temporary buffer that has the same contents as the old temporary buffer.)
+
DOC(This call can be used to set a new temporary buffer for the lex state. In cases where you want to
discontinue lexing, store the state, and resume later. In such a situation it may be necessary for you
to free the temp buffer that was originally used to make the lex state. This call allows you to supply
@@ -1089,6 +1090,7 @@ a new temp buffer when you are ready to resume lexing.
However the new buffer needs to have the same contents the old buffer had. To ensure this you have to
use cpp_lex_data_temp_size and cpp_lex_data_temp_read to get the relevant contents of the temp buffer
before you free it.)
+
DOC_SEE(cpp_lex_data_temp_size)
DOC_SEE(cpp_lex_data_temp_read)
*/{
diff --git a/4ed.cpp b/4ed.cpp
index 50ae88ee..8cc60fd5 100644
--- a/4ed.cpp
+++ b/4ed.cpp
@@ -1125,134 +1125,165 @@ enum Command_Line_Action{
CLAct_Count
};
+enum Command_Line_Mode{
+ CLMode_App,
+ CLMode_Custom
+};
+
void
init_command_line_settings(App_Settings *settings, Plat_Settings *plat_settings,
Command_Line_Parameters clparams){
- char *arg;
+ char *arg = 0;
+ Command_Line_Mode mode = CLMode_App;
Command_Line_Action action = CLAct_Nothing;
- i32 i,index;
+ i32 i = 0, index = 0;
b32 strict = 0;
settings->init_files_max = ArrayCount(settings->init_files);
for (i = 1; i <= clparams.argc; ++i){
- if (i == clparams.argc) arg = "";
- else arg = clparams.argv[i];
- switch (action){
- case CLAct_Nothing:
+ if (i == clparams.argc){
+ arg = "";
+ }
+ else{
+ arg = clparams.argv[i];
+ }
+
+ if (arg[0] == '-' && arg[1] == '-'){
+ char *long_arg_name = arg+2;
+ if (match_cc(long_arg_name, "custom")){
+ mode = CLMode_Custom;
+ settings->custom_arg_start = i+1;
+ settings->custom_arg_end = i+1;
+ continue;
+ }
+ }
+
+ switch (mode){
+ case CLMode_App:
{
- if (arg[0] == '-'){
- action = CLAct_Ignore;
- switch (arg[1]){
- case 'u': action = CLAct_UserFile; strict = false; break;
- case 'U': action = CLAct_UserFile; strict = true; break;
-
- case 'd': action = CLAct_CustomDLL; strict = false; break;
- case 'D': action = CLAct_CustomDLL; strict = true; break;
-
- case 'i': action = CLAct_InitialFilePosition; break;
-
- case 'w': action = CLAct_WindowSize; break;
- case 'W': action = CLAct_WindowMaximize; break;
- case 'p': action = CLAct_WindowPosition; break;
- case 'F': action = CLAct_WindowFullscreen; break;
- case 'S': action = CLAct_WindowStreamMode; break;
-
- case 'f': action = CLAct_FontSize; break;
- case 'h': action = CLAct_FontStopHinting; --i; break;
- }
- }
- else if (arg[0] != 0){
- if (settings->init_files_count < settings->init_files_max){
- index = settings->init_files_count++;
- settings->init_files[index] = arg;
- }
- }
- }break;
-
- case CLAct_UserFile:
- {
- settings->user_file_is_strict = strict;
- if (i < clparams.argc){
- settings->user_file = clparams.argv[i];
- }
- action = CLAct_Nothing;
- }break;
-
- case CLAct_CustomDLL:
- {
- plat_settings->custom_dll_is_strict = strict;
- if (i < clparams.argc){
- plat_settings->custom_dll = clparams.argv[i];
- }
- action = CLAct_Nothing;
- }break;
-
- case CLAct_InitialFilePosition:
- {
- if (i < clparams.argc){
- settings->initial_line = str_to_int_c(clparams.argv[i]);
- }
- action = CLAct_Nothing;
- }break;
-
- case CLAct_WindowSize:
- {
- if (i + 1 < clparams.argc){
- plat_settings->set_window_size = true;
- plat_settings->window_w = str_to_int_c(clparams.argv[i]);
- plat_settings->window_h = str_to_int_c(clparams.argv[i+1]);
+ switch (action){
+ case CLAct_Nothing:
+ {
+ if (arg[0] == '-'){
+ action = CLAct_Ignore;
+ switch (arg[1]){
+ case 'u': action = CLAct_UserFile; strict = false; break;
+ case 'U': action = CLAct_UserFile; strict = true; break;
+
+ case 'd': action = CLAct_CustomDLL; strict = false; break;
+ case 'D': action = CLAct_CustomDLL; strict = true; break;
+
+ case 'i': action = CLAct_InitialFilePosition; break;
+
+ case 'w': action = CLAct_WindowSize; break;
+ case 'W': action = CLAct_WindowMaximize; break;
+ case 'p': action = CLAct_WindowPosition; break;
+ case 'F': action = CLAct_WindowFullscreen; break;
+ case 'S': action = CLAct_WindowStreamMode; break;
+
+ case 'f': action = CLAct_FontSize; break;
+ case 'h': action = CLAct_FontStopHinting; --i; break;
+ }
+ }
+ else if (arg[0] != 0){
+ if (settings->init_files_count < settings->init_files_max){
+ index = settings->init_files_count++;
+ settings->init_files[index] = arg;
+ }
+ }
+ }break;
- ++i;
- }
- action = CLAct_Nothing;
- }break;
-
- case CLAct_WindowMaximize:
- {
- --i;
- plat_settings->maximize_window = true;
- action = CLAct_Nothing;
- }break;
-
- case CLAct_WindowPosition:
- {
- if (i + 1 < clparams.argc){
- plat_settings->set_window_pos = true;
- plat_settings->window_x = str_to_int_c(clparams.argv[i]);
- plat_settings->window_y = str_to_int_c(clparams.argv[i+1]);
+ case CLAct_UserFile:
+ {
+ settings->user_file_is_strict = strict;
+ if (i < clparams.argc){
+ settings->user_file = clparams.argv[i];
+ }
+ action = CLAct_Nothing;
+ }break;
- ++i;
+ case CLAct_CustomDLL:
+ {
+ plat_settings->custom_dll_is_strict = strict;
+ if (i < clparams.argc){
+ plat_settings->custom_dll = clparams.argv[i];
+ }
+ action = CLAct_Nothing;
+ }break;
+
+ case CLAct_InitialFilePosition:
+ {
+ if (i < clparams.argc){
+ settings->initial_line = str_to_int_c(clparams.argv[i]);
+ }
+ action = CLAct_Nothing;
+ }break;
+
+ case CLAct_WindowSize:
+ {
+ if (i + 1 < clparams.argc){
+ plat_settings->set_window_size = true;
+ plat_settings->window_w = str_to_int_c(clparams.argv[i]);
+ plat_settings->window_h = str_to_int_c(clparams.argv[i+1]);
+
+ ++i;
+ }
+ action = CLAct_Nothing;
+ }break;
+
+ case CLAct_WindowMaximize:
+ {
+ --i;
+ plat_settings->maximize_window = true;
+ action = CLAct_Nothing;
+ }break;
+
+ case CLAct_WindowPosition:
+ {
+ if (i + 1 < clparams.argc){
+ plat_settings->set_window_pos = true;
+ plat_settings->window_x = str_to_int_c(clparams.argv[i]);
+ plat_settings->window_y = str_to_int_c(clparams.argv[i+1]);
+
+ ++i;
+ }
+ action = CLAct_Nothing;
+ }break;
+
+ case CLAct_WindowFullscreen:
+ {
+ --i;
+ plat_settings->fullscreen_window = true;
+ plat_settings->stream_mode = true;
+ action = CLAct_Nothing;
+ }break;
+
+ case CLAct_WindowStreamMode:
+ {
+ --i;
+ plat_settings->stream_mode = true;
+ action = CLAct_Nothing;
+ }break;
+
+ case CLAct_FontSize:
+ {
+ if (i < clparams.argc){
+ settings->font_size = str_to_int_c(clparams.argv[i]);
+ }
+ action = CLAct_Nothing;
+ }break;
+
+ case CLAct_FontStopHinting:
+ {
+ plat_settings->use_hinting = true;
+ action = CLAct_Nothing;
+ }break;
}
- action = CLAct_Nothing;
}break;
- case CLAct_WindowFullscreen:
+ case CLMode_Custom:
{
- --i;
- plat_settings->fullscreen_window = true;
- plat_settings->stream_mode = true;
- action = CLAct_Nothing;
- }break;
-
- case CLAct_WindowStreamMode:
- {
- --i;
- plat_settings->stream_mode = true;
- action = CLAct_Nothing;
- }break;
-
- case CLAct_FontSize:
- {
- if (i < clparams.argc){
- settings->font_size = str_to_int_c(clparams.argv[i]);
- }
- action = CLAct_Nothing;
- }break;
-
- case CLAct_FontStopHinting:
- {
- plat_settings->use_hinting = true;
- action = CLAct_Nothing;
+ settings->custom_arg_end = i+1;
}break;
}
}
diff --git a/4ed.h b/4ed.h
index c7c0ed1a..2100d1a5 100644
--- a/4ed.h
+++ b/4ed.h
@@ -121,12 +121,13 @@ struct Application_Step_Input{
String clipboard;
};
-#define App_Step_Sig(name) void \
-name(System_Functions *system, \
- Render_Target *target, \
- Application_Memory *memory, \
- Application_Step_Input *input, \
- Application_Step_Result *result)
+#define App_Step_Sig(name) void \
+name(System_Functions *system, \
+ Render_Target *target, \
+ Application_Memory *memory, \
+ Application_Step_Input *input, \
+ Application_Step_Result *result, \
+ Command_Line_Parameters params)
typedef App_Step_Sig(App_Step);
diff --git a/4ed_api_implementation.cpp b/4ed_api_implementation.cpp
index 8112a5c4..9aa01d8f 100644
--- a/4ed_api_implementation.cpp
+++ b/4ed_api_implementation.cpp
@@ -657,6 +657,7 @@ DOC_SEE(Partial_Cursor)
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(buffer, The buffer on which to apply the batch of edits.)
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.)
diff --git a/4ed_app_models.h b/4ed_app_models.h
index 2624ff3d..59f61ad2 100644
--- a/4ed_app_models.h
+++ b/4ed_app_models.h
@@ -21,6 +21,9 @@ struct App_Settings{
b32 lctrl_lalt_is_altgr;
i32 font_size;
+
+ i32 custom_arg_start;
+ i32 custom_arg_end;
};
struct Debug_Input_Event{
diff --git a/4ed_metagen.cpp b/4ed_metagen.cpp
index cdb26f85..bc4834e6 100644
--- a/4ed_metagen.cpp
+++ b/4ed_metagen.cpp
@@ -2970,9 +2970,9 @@ generate_custom_headers(){
""
"
"
- "
4cpp Lexing Library
");
+// "4cpp Lexing Library
");
-// "4coder API
");
+ "4coder API
");
struct Section{
char *id_string;
diff --git a/TODO.txt b/TODO.txt
index 0508e6f1..18e21850 100644
--- a/TODO.txt
+++ b/TODO.txt
@@ -163,7 +163,12 @@
; [] the "main_4coder" experiment
; [] multi-line editing
; [] multi-cursor editing
-;
+
+; [] API docs have duplicate ids?
+; [] introduce custom command line arguments
+; [] control the file opening/start hook relationship better
+; [] flag for hiding the *messages* buffer.
+; [] get keyboard state on launch
; buffer behavior cleanup
; [] show all characters as \# if they can't be rendered
diff --git a/buffer/4coder_gap_buffer.cpp b/buffer/4coder_gap_buffer.cpp
index 1154a569..09860aea 100644
--- a/buffer/4coder_gap_buffer.cpp
+++ b/buffer/4coder_gap_buffer.cpp
@@ -1,341 +1,355 @@
-/*
- * Mr. 4th Dimention - Allen Webster
- * Four Tech
- *
- * public domain -- no warranty is offered or implied; use this code at your own risk
- *
- * 23.10.2015
- *
- * Buffer data object
- * type - Gap Buffer
- *
- */
-
-// TOP
-
-typedef struct Gap_Buffer{
- char *data;
- int size1, gap_size, size2, max;
-
- float *line_widths;
- int *line_starts;
- int line_count;
- int widths_count;
- int line_max;
- int widths_max;
-} Gap_Buffer;
-
-inline_4tech int
-buffer_good(Gap_Buffer *buffer){
- int good;
- good = (buffer->data != 0);
- return(good);
-}
-
-inline_4tech int
-buffer_size(Gap_Buffer *buffer){
- int size;
- size = buffer->size1 + buffer->size2;
- return(size);
-}
-
-typedef struct Gap_Buffer_Init{
- Gap_Buffer *buffer;
- char *data;
- int size;
-} Gap_Buffer_Init;
-
-internal_4tech Gap_Buffer_Init
-buffer_begin_init(Gap_Buffer *buffer, char *data, int size){
- Gap_Buffer_Init init;
- init.buffer = buffer;
- init.data = data;
- init.size = size;
- return(init);
-}
-
-internal_4tech int
-buffer_init_need_more(Gap_Buffer_Init *init){
- int result;
- result = 1;
- if (init->buffer->data) result = 0;
- return(result);
-}
-
-internal_4tech int
-buffer_init_page_size(Gap_Buffer_Init *init){
- int result;
- result = init->size * 2;
- return(result);
-}
-
-internal_4tech void
-buffer_init_provide_page(Gap_Buffer_Init *init, void *page, int page_size){
- Gap_Buffer *buffer;
- buffer = init->buffer;
- buffer->data = (char*)page;
- buffer->max = page_size;
-}
-
-internal_4tech int
-buffer_end_init(Gap_Buffer_Init *init, void *scratch, int scratch_size){
- Gap_Buffer *buffer;
- int osize1, size1, size2, size;
- int result;
-
- result = 0;
- buffer = init->buffer;
- size = init->size;
- if (buffer->data){
- if (buffer->max >= init->size){
- size2 = size >> 1;
- size1 = osize1 = size - size2;
-
- if (size1 > 0){
- size1 = eol_convert_in(buffer->data, init->data, size1);
- if (size2 > 0){
- size2 = eol_convert_in(buffer->data + size1, init->data + osize1, size2);
- }
- }
-
- buffer->size1 = size1;
- buffer->size2 = size2;
- buffer->gap_size = buffer->max - size1 - size2;
- memmove_4tech(buffer->data + size1 + buffer->gap_size, buffer->data + size1, size2);
-
- result = 1;
- }
- }
-
- return(result);
-}
-
-typedef struct Gap_Buffer_Stringify_Loop{
- Gap_Buffer *buffer;
- char *data, *base;
- int absolute_pos;
- int pos, end;
- int size;
- int separated;
-} Gap_Buffer_Stringify_Loop;
-
-internal_4tech Gap_Buffer_Stringify_Loop
-buffer_stringify_loop(Gap_Buffer *buffer, int start, int end){
- Gap_Buffer_Stringify_Loop result;
- if (0 <= start && start < end && end <= buffer->size1 + buffer->size2){
- result.buffer = buffer;
- result.base = buffer->data;
- result.absolute_pos = start;
-
- if (end <= buffer->size1) result.end = end;
- else result.end = end + buffer->gap_size;
-
- if (start < buffer->size1){
- if (end <= buffer->size1) result.separated = 0;
- else result.separated = 1;
- result.pos = start;
- }
- else{
- result.separated = 0;
- result.pos = start + buffer->gap_size;
- }
- if (result.separated) result.size = buffer->size1 - start;
- else result.size = end - start;
- result.data = buffer->data + result.pos;
- }
- else result.buffer = 0;
- return(result);
-}
-
-inline_4tech int
-buffer_stringify_good(Gap_Buffer_Stringify_Loop *loop){
- int result;
- result = (loop->buffer != 0);
- return(result);
-}
-
-internal_4tech void
-buffer_stringify_next(Gap_Buffer_Stringify_Loop *loop){
- int size1, temp_end;
- if (loop->separated){
- loop->separated = 0;
- size1 = loop->buffer->size1;
- loop->pos = loop->buffer->gap_size + size1;
- loop->absolute_pos = size1;
- temp_end = loop->end;
- }
- else{
- loop->buffer = 0;
- temp_end = loop->pos;
- }
- loop->size = temp_end - loop->pos;
- loop->data = loop->base + loop->pos;
-}
-
-typedef struct Gap_Buffer_Backify_Loop{
- Gap_Buffer *buffer;
- char *data, *base;
- int pos, end;
- int size;
- int absolute_pos;
- int separated;
-} Gap_Buffer_Backify_Loop;
-
-internal_4tech Gap_Buffer_Backify_Loop
-buffer_backify_loop(Gap_Buffer *buffer, int start, int end){
- Gap_Buffer_Backify_Loop result;
-
- ++start;
- if (0 <= end && end < start && start <= buffer->size1 + buffer->size2){
- result.buffer = buffer;
- result.base = buffer->data;
-
- if (end < buffer->size1) result.end = end;
- else result.end = end + buffer->gap_size;
-
- if (start <= buffer->size1){
- result.separated = 0;
- result.pos = 0;
- }
- else{
- if (end < buffer->size1) result.separated = 1;
- else result.separated = 0;
- result.pos = buffer->size1 + buffer->gap_size;
- }
- if (!result.separated && result.pos < result.end) result.pos = result.end;
- result.size = start - result.pos;
- result.absolute_pos = result.pos;
- if (result.absolute_pos > buffer->size1) result.absolute_pos -= buffer->gap_size;
- result.data = result.base + result.pos;
- }
- else result.buffer = 0;
- return(result);
-}
-
-inline_4tech int
-buffer_backify_good(Gap_Buffer_Backify_Loop *loop){
- int result;
- result = (loop->buffer != 0);
- return(result);
-}
-
-internal_4tech void
-buffer_backify_next(Gap_Buffer_Backify_Loop *loop){
- Gap_Buffer *buffer;
- int temp_end;
- int chunk2_start;
- buffer = loop->buffer;
- chunk2_start = buffer->size1 + buffer->gap_size;
- if (loop->separated){
- loop->separated = 0;
- temp_end = buffer->size1;
- loop->pos = 0;
- loop->absolute_pos = 0;
- if (loop->pos < loop->end){
- loop->absolute_pos = loop->end;
- loop->pos = loop->end;
- }
- }
- else{
- temp_end = 0;
- loop->buffer = 0;
- }
- loop->size = temp_end - loop->pos;
- loop->data = loop->base + loop->pos;
-}
-
-internal_4tech int
-buffer_replace_range(Gap_Buffer *buffer, int start, int end, char *str, int len, int *shift_amount,
- void *scratch, int scratch_memory, int *request_amount){
- char *data;
- int result;
- int size;
- int move_size;
-
- size = buffer_size(buffer);
- assert_4tech(0 <= start);
- assert_4tech(start <= end);
- assert_4tech(end <= size);
-
- *shift_amount = (len - (end - start));
- if (*shift_amount + size <= buffer->max){
- data = buffer->data;
- if (end < buffer->size1){
- move_size = buffer->size1 - end;
- memmove_4tech(data + buffer->size1 + buffer->gap_size - move_size, data + end, move_size);
- buffer->size1 -= move_size;
- buffer->size2 += move_size;
- }
- if (start > buffer->size1){
- move_size = start - buffer->size1;
- memmove_4tech(data + buffer->size1, data + buffer->size1 + buffer->gap_size, move_size);
- buffer->size1 += move_size;
- buffer->size2 -= move_size;
- }
-
- memcpy_4tech(data + start, str, len);
- buffer->size2 = size - end;
- buffer->size1 = start + len;
- buffer->gap_size -= *shift_amount;
-
- assert_4tech(buffer->size1 + buffer->size2 == size + *shift_amount);
- assert_4tech(buffer->size1 + buffer->gap_size + buffer->size2 == buffer->max);
-
- result = 0;
- }
- else{
- *request_amount = round_up_4tech(2*(*shift_amount + size), 4 << 10);
- result = 1;
- }
-
- return(result);
-}
-
-// NOTE(allen): This could should be optimized for Gap_Buffer
-internal_4tech int
-buffer_batch_edit_step(Buffer_Batch_State *state, Gap_Buffer *buffer, Buffer_Edit *sorted_edits,
- char *strings, int edit_count, void *scratch, int scratch_size, int *request_amount){
- Buffer_Edit *edit;
- int i, result;
- int shift_total, shift_amount;
-
- result = 0;
- shift_total = state->shift_total;
- i = state->i;
-
- edit = sorted_edits + i;
- for (; i < edit_count; ++i, ++edit){
- result = buffer_replace_range(buffer, edit->start + shift_total, edit->end + shift_total,
- strings + edit->str_start, edit->len, &shift_amount,
- scratch, scratch_size, request_amount);
- if (result) break;
- shift_total += shift_amount;
- }
-
- state->shift_total = shift_total;
- state->i = i;
-
- return(result);
-}
-
-internal_4tech void*
-buffer_edit_provide_memory(Gap_Buffer *buffer, void *new_data, int new_max){
- void *result;
- int new_gap_size;
-
- assert_4tech(new_max >= buffer_size(buffer));
-
- result = buffer->data;
- new_gap_size = new_max - buffer_size(buffer);
- memcpy_4tech(new_data, buffer->data, buffer->size1);
- memcpy_4tech((char*)new_data + buffer->size1 + new_gap_size, buffer->data + buffer->size1 + buffer->gap_size, buffer->size2);
-
- buffer->data = (char*)new_data;
- buffer->gap_size = new_gap_size;
- buffer->max = new_max;
-
- return(result);
-}
-
-// BOTTOM
-
+/*
+ * Mr. 4th Dimention - Allen Webster
+ * Four Tech
+ *
+ * public domain -- no warranty is offered or implied; use this code at your own risk
+ *
+ * 23.10.2015
+ *
+ * Buffer data object
+ * type - Gap Buffer
+ *
+ */
+
+// TOP
+
+typedef struct Gap_Buffer{
+ char *data;
+ int size1;
+ int gap_size;
+ int size2;
+ int max;
+
+ float *line_widths;
+ int *line_starts;
+ int line_count;
+ int widths_count;
+ int line_max;
+ int widths_max;
+} Gap_Buffer;
+
+inline_4tech int
+buffer_good(Gap_Buffer *buffer){
+ int good = (buffer->data != 0);
+ return(good);
+}
+
+inline_4tech int
+buffer_size(Gap_Buffer *buffer){
+ int size = buffer->size1 + buffer->size2;
+ return(size);
+}
+
+typedef struct Gap_Buffer_Init{
+ Gap_Buffer *buffer;
+ char *data;
+ int size;
+} Gap_Buffer_Init;
+
+internal_4tech Gap_Buffer_Init
+buffer_begin_init(Gap_Buffer *buffer, char *data, int size){
+ Gap_Buffer_Init init;
+ init.buffer = buffer;
+ init.data = data;
+ init.size = size;
+ return(init);
+}
+
+internal_4tech int
+buffer_init_need_more(Gap_Buffer_Init *init){
+ int result = 1;
+ if (init->buffer->data) result = 0;
+ return(result);
+}
+
+internal_4tech int
+buffer_init_page_size(Gap_Buffer_Init *init){
+ int result = init->size * 2;
+ return(result);
+}
+
+internal_4tech void
+buffer_init_provide_page(Gap_Buffer_Init *init, void *page, int page_size){
+ Gap_Buffer *buffer = init->buffer;
+ buffer->data = (char*)page;
+ buffer->max = page_size;
+}
+
+internal_4tech int
+buffer_end_init(Gap_Buffer_Init *init, void *scratch, int scratch_size){
+ Gap_Buffer *buffer = init->buffer;
+ int osize1 = 0, size1 = 0, size2 = 0, size = init->size;
+ int result = 0;
+
+ if (buffer->data){
+ if (buffer->max >= init->size){
+ size2 = size >> 1;
+ size1 = osize1 = size - size2;
+
+ if (size1 > 0){
+ size1 = eol_convert_in(buffer->data, init->data, size1);
+ if (size2 > 0){
+ size2 = eol_convert_in(buffer->data + size1, init->data + osize1, size2);
+ }
+ }
+
+ buffer->size1 = size1;
+ buffer->size2 = size2;
+ buffer->gap_size = buffer->max - size1 - size2;
+ memmove_4tech(buffer->data + size1 + buffer->gap_size, buffer->data + size1, size2);
+
+ result = 1;
+ }
+ }
+
+ return(result);
+}
+
+typedef struct Gap_Buffer_Stringify_Loop{
+ Gap_Buffer *buffer;
+ char *data, *base;
+ int absolute_pos;
+ int pos, end;
+ int size;
+ int separated;
+} Gap_Buffer_Stringify_Loop;
+
+internal_4tech Gap_Buffer_Stringify_Loop
+buffer_stringify_loop(Gap_Buffer *buffer, int start, int end){
+ Gap_Buffer_Stringify_Loop result = {0};
+
+ if (0 <= start && start < end && end <= buffer->size1 + buffer->size2){
+ result.buffer = buffer;
+ result.base = buffer->data;
+ result.absolute_pos = start;
+
+ if (end <= buffer->size1){
+ result.end = end;
+ }
+ else{
+ result.end = end + buffer->gap_size;
+ }
+
+ if (start < buffer->size1){
+ if (end <= buffer->size1){
+ result.separated = 0;
+ }
+ else{
+ result.separated = 1;
+ }
+ result.pos = start;
+ }
+ else{
+ result.separated = 0;
+ result.pos = start + buffer->gap_size;
+ }
+
+ if (result.separated){
+ result.size = buffer->size1 - start;
+ }
+ else{
+ result.size = end - start;
+ }
+
+ result.data = buffer->data + result.pos;
+ }
+
+ return(result);
+}
+
+inline_4tech int
+buffer_stringify_good(Gap_Buffer_Stringify_Loop *loop){
+ int result = (loop->buffer != 0);
+ return(result);
+}
+
+internal_4tech void
+buffer_stringify_next(Gap_Buffer_Stringify_Loop *loop){
+ int size1 = 0, temp_end = 0;
+ if (loop->separated){
+ loop->separated = 0;
+ size1 = loop->buffer->size1;
+ loop->pos = loop->buffer->gap_size + size1;
+ loop->absolute_pos = size1;
+ temp_end = loop->end;
+ }
+ else{
+ loop->buffer = 0;
+ temp_end = loop->pos;
+ }
+ loop->size = temp_end - loop->pos;
+ loop->data = loop->base + loop->pos;
+}
+
+typedef struct Gap_Buffer_Backify_Loop{
+ Gap_Buffer *buffer;
+ char *data, *base;
+ int pos, end;
+ int size;
+ int absolute_pos;
+ int separated;
+} Gap_Buffer_Backify_Loop;
+
+internal_4tech Gap_Buffer_Backify_Loop
+buffer_backify_loop(Gap_Buffer *buffer, int start, int end){
+ Gap_Buffer_Backify_Loop result = {0};
+
+ ++start;
+ if (0 <= end && end < start && start <= buffer->size1 + buffer->size2){
+ result.buffer = buffer;
+ result.base = buffer->data;
+
+ if (end < buffer->size1){
+ result.end = end;
+ }
+ else{
+ result.end = end + buffer->gap_size;
+ }
+
+ if (start <= buffer->size1){
+ result.separated = 0;
+ result.pos = 0;
+ }
+ else{
+ if (end < buffer->size1){
+ result.separated = 1;
+ }
+ else{
+ result.separated = 0;
+ }
+ result.pos = buffer->size1 + buffer->gap_size;
+ }
+
+ if (!result.separated && result.pos < result.end){
+ result.pos = result.end;
+ }
+
+ result.size = start - result.pos;
+ result.absolute_pos = result.pos;
+ if (result.absolute_pos > buffer->size1){
+ result.absolute_pos -= buffer->gap_size;
+ }
+ result.data = result.base + result.pos;
+ }
+
+ return(result);
+}
+
+inline_4tech int
+buffer_backify_good(Gap_Buffer_Backify_Loop *loop){
+ int result = (loop->buffer != 0);
+ return(result);
+}
+
+internal_4tech void
+buffer_backify_next(Gap_Buffer_Backify_Loop *loop){
+ Gap_Buffer *buffer = loop->buffer;
+ int temp_end = 0;
+
+ if (loop->separated){
+ loop->separated = 0;
+ temp_end = buffer->size1;
+ loop->pos = 0;
+ loop->absolute_pos = 0;
+ if (loop->pos < loop->end){
+ loop->absolute_pos = loop->end;
+ loop->pos = loop->end;
+ }
+ }
+ else{
+ temp_end = 0;
+ loop->buffer = 0;
+ }
+
+ loop->size = temp_end - loop->pos;
+ loop->data = loop->base + loop->pos;
+}
+
+internal_4tech int
+buffer_replace_range(Gap_Buffer *buffer, int start, int end, char *str, int len, int *shift_amount,
+ void *scratch, int scratch_memory, int *request_amount){
+ char *data = buffer->data;
+ int size = buffer_size(buffer);
+ int result = 0;
+ int move_size = 0;
+
+ assert_4tech(0 <= start);
+ assert_4tech(start <= end);
+ assert_4tech(end <= size);
+
+ *shift_amount = (len - (end - start));
+ if (*shift_amount + size <= buffer->max){
+ if (end < buffer->size1){
+ move_size = buffer->size1 - end;
+ memmove_4tech(data + buffer->size1 + buffer->gap_size - move_size, data + end, move_size);
+ buffer->size1 -= move_size;
+ buffer->size2 += move_size;
+ }
+ if (start > buffer->size1){
+ move_size = start - buffer->size1;
+ memmove_4tech(data + buffer->size1, data + buffer->size1 + buffer->gap_size, move_size);
+ buffer->size1 += move_size;
+ buffer->size2 -= move_size;
+ }
+
+ memcpy_4tech(data + start, str, len);
+ buffer->size2 = size - end;
+ buffer->size1 = start + len;
+ buffer->gap_size -= *shift_amount;
+
+ assert_4tech(buffer->size1 + buffer->size2 == size + *shift_amount);
+ assert_4tech(buffer->size1 + buffer->gap_size + buffer->size2 == buffer->max);
+ }
+ else{
+ *request_amount = round_up_4tech(2*(*shift_amount + size), 4 << 10);
+ result = 1;
+ }
+
+ return(result);
+}
+
+// NOTE(allen): This could should be optimized for Gap_Buffer
+internal_4tech int
+buffer_batch_edit_step(Buffer_Batch_State *state, Gap_Buffer *buffer, Buffer_Edit *sorted_edits,
+ char *strings, int edit_count, void *scratch, int scratch_size, int *request_amount){
+ Buffer_Edit *edit = 0;
+ int i = state->i;
+ int shift_total = state->shift_total;
+ int shift_amount = 0;
+ int result = 0;
+
+ edit = sorted_edits + i;
+ for (; i < edit_count; ++i, ++edit){
+ result = buffer_replace_range(buffer, edit->start + shift_total, edit->end + shift_total,
+ strings + edit->str_start, edit->len, &shift_amount,
+ scratch, scratch_size, request_amount);
+ if (result) break;
+ shift_total += shift_amount;
+ }
+
+ state->shift_total = shift_total;
+ state->i = i;
+
+ return(result);
+}
+
+internal_4tech void*
+buffer_edit_provide_memory(Gap_Buffer *buffer, void *new_data, int new_max){
+ void *result = buffer->data;
+ int size = buffer_size(buffer);
+ int new_gap_size = new_max - size;
+
+ assert_4tech(new_max >= size);
+
+ memcpy_4tech(new_data, buffer->data, buffer->size1);
+ memcpy_4tech((char*)new_data + buffer->size1 + new_gap_size, buffer->data + buffer->size1 + buffer->gap_size, buffer->size2);
+
+ buffer->data = (char*)new_data;
+ buffer->gap_size = new_gap_size;
+ buffer->max = new_max;
+
+ return(result);
+}
+
+// BOTTOM
+
diff --git a/win32_4ed.cpp b/win32_4ed.cpp
index e4a84323..f6a9e19e 100644
--- a/win32_4ed.cpp
+++ b/win32_4ed.cpp
@@ -2438,7 +2438,8 @@ WinMain(HINSTANCE hInstance,
&win32vars.target,
&memory_vars,
&input,
- &result);
+ &result,
+ clparams);
if (result.perform_kill){
keep_playing = 0;