From a89b46fda798290c80578f583df1cef21849aabb Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Sun, 1 Nov 2015 20:04:37 -0500 Subject: [PATCH] new memory interface --- 4cpp_string.h | 14 ++- 4ed.cpp | 149 +++++++++++++++++++++++++---- 4ed.h | 26 ++++- 4ed_file_view.cpp | 116 ++++++++++++---------- 4ed_internal.h | 2 +- 4ed_system.h | 21 ++++ buffer/4coder_buffer_abstract.cpp | 15 +-- buffer/4coder_gap_buffer.cpp | 16 ++-- buffer/4coder_golden_array.cpp | 15 +-- buffer/4coder_multi_gap_buffer.cpp | 113 +++++++++++++++++++--- buffer/4coder_shared.cpp | 13 +++ win32_4ed.cpp | 144 ++++++++++++++++++++++++++-- 12 files changed, 525 insertions(+), 119 deletions(-) diff --git a/4cpp_string.h b/4cpp_string.h index 752b96bf..3ece385b 100644 --- a/4cpp_string.h +++ b/4cpp_string.h @@ -128,8 +128,18 @@ FCPP_LINK bool append_partial(String *dest, String src); FCPP_LINK bool append(String *dest, char c); inline bool append(String *dest, String src) { return append_partial(dest, src); } inline bool append(String *dest, char *src) { return append_partial(dest, src); } -inline void terminate_with_null(String *str) -{ if (str->size < str->memory_size) str->str[str->size] = 0; else str->str[str->size-1] = 0; } +inline bool terminate_with_null(String *str){ + bool result; + if (str->size < str->memory_size){ + str->str[str->size] = 0; + result = 1; + } + else{ + str->str[str->size-1] = 0; + result = 0; + } + return result; +} FCPP_LINK int compare(char *a, char *b); FCPP_LINK int compare(String a, char *b); diff --git a/4ed.cpp b/4ed.cpp index baeb4c9b..3a6707ca 100644 --- a/4ed.cpp +++ b/4ed.cpp @@ -23,6 +23,16 @@ struct App_State_Resizing{ i32 min, max; }; +struct CLI_Process{ + CLI_Handles cli; + Editing_File *out_file; +}; + +struct CLI_List{ + CLI_Process *procs; + i32 count, max; +}; + struct App_Vars{ Mem_Options mem; Command_Map map_top; @@ -51,6 +61,8 @@ struct App_Vars{ char hot_dir_base_[256]; String hot_dir_base; Hot_Directory hot_directory; + + CLI_List cli_processes; char query_[256]; char dest_[256]; @@ -480,7 +492,7 @@ COMMAND_DECL(paste){ String *src = working_set_clipboard_head(working_set); i32 pos_left = view->cursor.pos; - + i32 next_cursor_pos = pos_left+src->size; view_replace_range(mem, view, layout, pos_left, pos_left, (u8*)src->str, src->size, next_cursor_pos); @@ -966,7 +978,7 @@ case_change_range(Mem_Options *mem, File_View *view, Editing_File *file, if (file->still_lexing) system_cancel_job(BACKGROUND_THREADS, file->lex_job); - view_update_history_before_edit(mem, file, step, 0, hist_normal); + file_update_history_before_edit(mem, file, step, 0, hist_normal); u8 *data = (u8*)file->buffer.data; for (i32 i = range.start; i < range.end; ++i){ @@ -1518,9 +1530,71 @@ COMMAND_DECL(set_settings){ } } +COMMAND_DECL(build){ + ProfileMomentFunction(); + USE_VARS(vars); + USE_MEM(mem); + USE_WORKING_SET(working_set); + USE_STYLE(style); + USE_LIVE_SET(live_set); + USE_PANEL(panel); + + if (vars->cli_processes.count < vars->cli_processes.max){ + Get_File_Result file = working_set_get_available_file(working_set); + if (file.file){ + file_create_empty(&mem->general, file.file, (u8*)"*cli process*", style->font); + table_add(&working_set->table, file.file->source_path, file.index); + + View *new_view = live_set_alloc_view(live_set, mem); + view_replace_major(new_view, panel, live_set); + + File_View *file_view = file_view_init(new_view, &vars->delay, &vars->layout); + view_set_file(file_view, file.file, style, + vars->hooks[hook_open_file], command, app_links); + file.file->tokens_exist = 0; + new_view->map = app_get_map(vars, file.file->base_map_id); + + i32 i = vars->cli_processes.count++; + CLI_Process *proc = vars->cli_processes.procs + i; + if (!system_cli_call("..\\misc", "build_all_test", &proc->cli)){ + --vars->cli_processes.count; + } + proc->out_file = file.file; + } + else{ + // TODO(allen): feedback message - no available file + } + } + else{ + // TODO(allen): feedback message - no available process slot + } +} + +internal void +update_command_data(App_Vars *vars, Command_Data *cmd){ + Command_Data command_data; + command_data.vars = vars; + command_data.mem = &vars->mem; + command_data.working_set = &vars->working_set; + command_data.layout = &vars->layout; + command_data.panel = command_data.layout->panels + command_data.layout->active_panel; + command_data.view = command_data.panel->view; + command_data.live_set = &vars->live_set; + command_data.style = &vars->style; + command_data.delay = &vars->delay; + command_data.screen_width = cmd->screen_width; + command_data.screen_height = cmd->screen_height; + command_data.key = cmd->key; + command_data.part = cmd->part; + + *cmd = command_data; +} + COMPOSE_DECL(compose_write_auto_tab_line){ command_write_character(command, binding); + update_command_data(command->vars, command); command_auto_tab_line_at_cursor(command, binding); + update_command_data(command->vars, command); } globalvar Command_Function command_table[cmdid_count]; @@ -1532,7 +1606,9 @@ extern "C"{ Command_Binding binding; binding.function = function; if (function) function(cmd, binding); - + + update_command_data(cmd->vars, cmd); +#if 0 App_Vars *vars = cmd->vars; Command_Data command_data; command_data.vars = vars; @@ -1550,6 +1626,7 @@ extern "C"{ command_data.part = cmd->part; *cmd = command_data; +#endif } PUSH_PARAMETER_SIG(external_push_parameter){ @@ -1724,24 +1801,9 @@ setup_top_commands(Command_Map *commands, Partition *part, Key_Codes *codes, Com map_add(commands, 'i', MDFR_CTRL, command_interactive_switch_buffer); map_add(commands, 'c', MDFR_ALT, command_open_color_tweaker); map_add(commands, 'x', MDFR_ALT, command_open_menu); + map_add(commands, 'm', MDFR_ALT, command_build); } -#if 0 // TODO(allen): Here's an idea -internal void -setup_command_table(){ - BEGIN_META_CODE{ - int count; - char **command_names = get_all_commands(&count); - for (int i = 0; i < count; ++i){ - char *name_ = command_names[i]; - String name = make_string_slowly(name_); - - outcode("command_table[cmdid_", out_str(name), "] = command_", out_str(name), "\n"); - } - }END_META_CODE -} -#endif - internal void setup_command_table(){ #define SET(n) command_table[cmdid_##n] = command_##n @@ -2475,6 +2537,13 @@ app_init(Thread_Context *thread, Application_Memory *memory, vars->mini_str = make_string((char*)vars->mini_buffer, 0, 512); + // NOTE(allen): child proc list setup + i32 max_children = 16; + partition_align(partition, 8); + vars->cli_processes.procs = push_array(partition, CLI_Process, max_children); + vars->cli_processes.max = max_children; + vars->cli_processes.count = 0; + return 1; } @@ -2522,6 +2591,48 @@ app_step(Thread_Context *thread, Key_Codes *codes, } } + // NOTE(allen): update child processes + { + Temp_Memory temp = begin_temp_memory(&vars->mem.part); + u32 max = Kbytes(32); + char *dest = push_array(&vars->mem.part, char, max); + u32 amount; + + i32 count = vars->cli_processes.count; + for (i32 i = 0; i < count; ++i){ + CLI_Process *proc = vars->cli_processes.procs + i; + Editing_File *out_file = proc->out_file; + + i32 new_cursor = out_file->cursor_pos; + for (system_cli_begin_update(&proc->cli); + system_cli_update_step(&proc->cli, dest, max, &amount);){ + if (out_file){ + amount = eol_in_place_convert_in(dest, amount); + Edit_Spec spec = {}; + spec.step.type = ED_NORMAL; + spec.step.edit.start = buffer_size(&out_file->buffer); + spec.step.edit.end = spec.step.edit.start; + spec.step.edit.len = amount; + spec.step.pre_pos = new_cursor; + spec.step.post_pos = spec.step.edit.start + amount; + spec.str = (u8*)dest; + file_do_single_edit(&vars->mem, out_file, + &vars->layout, spec, hist_normal); + app_result.redraw = 1; + new_cursor = spec.step.post_pos; + } + } + + if (system_cli_end_update(&proc->cli)){ + *proc = vars->cli_processes.procs[--count]; + --i; + } + } + + vars->cli_processes.count = count; + end_temp_memory(temp); + } + // NOTE(allen): reorganizing panels on screen i32 prev_width = vars->layout.full_width; i32 prev_height = vars->layout.full_height; diff --git a/4ed.h b/4ed.h index 97854a8b..e0578e6c 100644 --- a/4ed.h +++ b/4ed.h @@ -112,6 +112,27 @@ general_memory_open(General_Memory *general, void *memory, i32 size){ insert_bubble(&general->sentinel, first); } +internal void +general_memory_check(General_Memory *general){ + Bubble *sentinel = &general->sentinel; + for (Bubble *bubble = sentinel->next; + bubble != sentinel; + bubble = bubble->next){ + Assert(bubble); + + Bubble *next = bubble->next; + Assert(bubble == next->prev); + if (next != sentinel){ + Assert(bubble->next > bubble); + Assert(bubble > bubble->prev); + + char *end_ptr = (char*)(bubble + 1) + bubble->size; + char *next_ptr = (char*)next; + Assert(end_ptr == next_ptr); + } + } +} + #define BUBBLE_MIN_SIZE 1024 internal void @@ -129,9 +150,6 @@ general_memory_attempt_split(Bubble *bubble, i32 wanted_size){ internal void* general_memory_allocate(General_Memory *general, i32 size, u32 type = 0){ void *result = 0; - if (size < Kbytes(1)){ - int x = 1; AllowLocal(x); - } for (Bubble *bubble = general->sentinel.next; bubble != &general->sentinel; bubble = bubble->next){ @@ -150,6 +168,8 @@ general_memory_allocate(General_Memory *general, i32 size, u32 type = 0){ inline void general_memory_do_merge(Bubble *left, Bubble *right){ + Assert(left->next == right); + Assert(right->prev == left); left->size += sizeof(Bubble) + right->size; remove_bubble(right); } diff --git a/4ed_file_view.cpp b/4ed_file_view.cpp index 0573f053..ad089218 100644 --- a/4ed_file_view.cpp +++ b/4ed_file_view.cpp @@ -1187,8 +1187,8 @@ file_grow_starts_as_needed(General_Memory *general, Editing_File *file, i32 addi i32 max = file->buffer.line_max; i32 count = file->buffer.line_count; i32 target_lines = count + additional_lines; - if (target_lines > max){ - max <<= 1; + if (target_lines > max || max == 0){ + max = LargeRoundUp(target_lines + max, Kbytes(1)); i32 *new_lines = (i32*) general_memory_reallocate(general, file->buffer.line_starts, sizeof(i32)*count, sizeof(i32)*max, BUBBLE_STARTS); @@ -1267,15 +1267,17 @@ internal void file_grow_widths_as_needed(General_Memory *general, Editing_File *file){ #if BUFFER_EXPERIMENT_SCALPEL <= 2 i32 line_count = file->buffer.line_count; - if (line_count > file->buffer.widths_max){ + if (line_count > file->buffer.widths_max || file->buffer.widths_max == 0){ i32 new_max = LargeRoundUp(line_count, Kbytes(1)); + if (new_max < Kbytes(1)) new_max = Kbytes(1); if (file->buffer.line_widths){ - file->buffer.line_widths = (real32*) - general_memory_reallocate_nocopy(general, file->buffer.line_widths, sizeof(real32)*new_max, BUBBLE_WIDTHS); + file->buffer.line_widths = (f32*) + general_memory_reallocate(general, file->buffer.line_widths, + sizeof(f32)*file->buffer.widths_count, sizeof(f32)*new_max, BUBBLE_WIDTHS); } else{ - file->buffer.line_widths = (real32*) - general_memory_allocate(general, sizeof(real32)*new_max, BUBBLE_WIDTHS); + file->buffer.line_widths = (f32*) + general_memory_allocate(general, sizeof(f32)*new_max, BUBBLE_WIDTHS); } file->buffer.widths_max = new_max; } @@ -1379,11 +1381,11 @@ internal void file_create_from_string(General_Memory *general, Editing_File *file, u8 *filename, Font *font, String val){ *file = {}; #if BUFFER_EXPERIMENT_SCALPEL <= 2 - Buffer_Init_Type init = buffer_begin_init(&file->buffer, val.str, val.size); for (; buffer_init_need_more(&init); ){ i32 page_size = buffer_init_page_size(&init); page_size = LargeRoundUp(page_size, Kbytes(4)); + if (page_size < Kbytes(4)) page_size = Kbytes(4); void *data = general_memory_allocate(general, page_size, BUBBLE_BUFFER); buffer_init_provide_page(&init, data, page_size); } @@ -1396,7 +1398,7 @@ file_create_from_string(General_Memory *general, Editing_File *file, u8 *filenam file_set_name(file, filename); file->base_map_id = mapid_file; - + file_measure_starts(general, file); file_measure_widths(general, file, font); file->font = font; @@ -1695,21 +1697,7 @@ file_relex_parallel(Mem_Options *mem, Editing_File *file, #endif internal bool32 -file_grow_as_needed(General_Memory *general, Editing_File *file, i32 additional_size){ - bool32 result = 1; -#if BUFFER_EXPERIMENT_SCALPEL <= 1 - i32 size = buffer_size(&file->buffer); - i32 target_size = size + additional_size + 1; - if (target_size >= file->buffer.max){ - i32 request_size = LargeRoundUp(target_size*2, Kbytes(256)); - char *new_data = (char*) - general_memory_allocate(general, request_size, BUBBLE_BUFFER); - TentativeAssert(new_data); - void *old_data = buffer_relocate(&file->buffer, new_data, request_size); - general_memory_free(general, old_data); - } -#endif - return result; +file_grow_as_needed_(General_Memory *general, Editing_File *file, i32 new_size){ } internal void @@ -2267,7 +2255,7 @@ enum History_Mode{ }; internal void -view_update_history_before_edit(Mem_Options *mem, Editing_File *file, Edit_Step step, u8 *str, +file_update_history_before_edit(Mem_Options *mem, Editing_File *file, Edit_Step step, u8 *str, History_Mode history_mode){ #if BUFFER_EXPERIMENT_SCALPEL <= 1 General_Memory *general = &mem->general; @@ -2460,13 +2448,13 @@ file_pre_edit_maintenance(Editing_File *file){ } internal void -view_do_single_edit(Mem_Options *mem, File_View *view, Editing_File *file, +file_do_single_edit(Mem_Options *mem, Editing_File *file, Editing_Layout *layout, Edit_Spec spec, History_Mode history_mode){ Assert(file); ProfileMomentFunction(); // NOTE(allen): fixing stuff beforewards???? - view_update_history_before_edit(mem, file, spec.step, spec.str, history_mode); + file_update_history_before_edit(mem, file, spec.step, spec.str, history_mode); file_pre_edit_maintenance(file); #if BUFFER_EXPERIMENT_SCALPEL <= 1 @@ -2479,8 +2467,15 @@ view_do_single_edit(Mem_Options *mem, File_View *view, Editing_File *file, i32 str_len = spec.step.edit.len; i32 shift_amount = 0; - while (buffer_replace_range(&file->buffer, start, end, str, str_len, &shift_amount)) - file_grow_as_needed(general, file, shift_amount); + i32 request_amount = 0; + while (buffer_replace_range(&file->buffer, start, end, str, str_len, &shift_amount, &request_amount)){ + void *new_data = 0; + if (request_amount > 0){ + new_data = general_memory_allocate(general, request_amount, BUBBLE_BUFFER); + } + void *old_data = buffer_edit_provide_memory(&file->buffer, new_data, request_amount); + if (old_data) general_memory_free(general, old_data); + } #if BUFFER_EXPERIMENT_SCALPEL <= 0 // NOTE(allen): fixing stuff afterwards @@ -2516,10 +2511,8 @@ view_do_single_edit(Mem_Options *mem, File_View *view, Editing_File *file, File_View *current_view = view_to_file_view(current_panel->view); if (current_view && current_view->file == file){ view_measure_wraps(general, current_view); - if (current_view != view){ - write_cursor_with_index(cursors, &cursor_count, current_view->cursor.pos); - write_cursor_with_index(cursors, &cursor_count, current_view->mark); - } + write_cursor_with_index(cursors, &cursor_count, current_view->cursor.pos); + write_cursor_with_index(cursors, &cursor_count, current_view->mark); } } @@ -2535,11 +2528,9 @@ view_do_single_edit(Mem_Options *mem, File_View *view, Editing_File *file, for (i32 i = 0; i < panel_count; ++i, ++current_panel){ File_View *current_view = view_to_file_view(current_panel->view); if (current_view && current_view->file == file){ - if (current_view != view){ - view_cursor_move(current_view, cursors[cursor_count++].pos); - current_view->mark = cursors[cursor_count++].pos; - current_view->preferred_x = view_get_cursor_x(current_view); - } + view_cursor_move(current_view, cursors[cursor_count++].pos); + current_view->mark = cursors[cursor_count++].pos; + current_view->preferred_x = view_get_cursor_x(current_view); } } @@ -2556,7 +2547,7 @@ view_do_white_batch_edit(Mem_Options *mem, File_View *view, Editing_File *file, // NOTE(allen): fixing stuff beforewards???? Assert(spec.str == 0); - view_update_history_before_edit(mem, file, spec.step, 0, history_mode); + file_update_history_before_edit(mem, file, spec.step, 0, history_mode); file_pre_edit_maintenance(file); // NOTE(allen): actual text replacement @@ -2569,11 +2560,18 @@ view_do_white_batch_edit(Mem_Options *mem, File_View *view, Editing_File *file, Assert(spec.step.first_child < file->undo.children.edit_count); Assert(batch_size >= 0); - - i32 shift_amount = buffer_batch_edit_max_shift(batch, batch_size); - file_grow_as_needed(general, file, shift_amount); - - buffer_batch_edit(&file->buffer, batch, (char*)str_base, batch_size); + + Buffer_Batch_State state = {}; + i32 request_amount; + while (buffer_batch_edit_step(&state, &file->buffer, + batch, (char*)str_base, batch_size, &request_amount)){ + void *new_data = 0; + if (request_amount > 0){ + new_data = general_memory_allocate(general, request_amount, BUBBLE_BUFFER); + } + void *old_data = buffer_edit_provide_memory(&file->buffer, new_data, request_amount); + if (old_data) general_memory_free(general, old_data); + } // NOTE(allen): token fixing if (file->tokens_complete){ @@ -2585,12 +2583,18 @@ view_do_white_batch_edit(Mem_Options *mem, File_View *view, Editing_File *file, Buffer_Edit *end_edit = batch + batch_size; i32 shift_amount = 0; + i32 local_shift = 0; for (; token < end_token && edit < end_edit; ++edit){ + local_shift = (edit->len - (edit->end - edit->start)); + for (; token->start < edit->start && edit->start < token->start + token->size && + token < end_token; ++token){ + token->size += local_shift; + } for (; token->start < edit->start && token < end_token; ++token){ token->start += shift_amount; } - shift_amount += (edit->len - (edit->end - edit->start)); + shift_amount += local_shift; } for (; token < end_token; ++token){ token->start += shift_amount; @@ -2656,7 +2660,7 @@ view_replace_range(Mem_Options *mem, File_View *view, Editing_Layout *layout, spec.step.pre_pos = view->cursor.pos; spec.step.post_pos = next_cursor; spec.str = str; - view_do_single_edit(mem, view, view->file, layout, spec, hist_normal); + file_do_single_edit(mem, view->file, layout, spec, hist_normal); } internal void @@ -2683,7 +2687,7 @@ view_undo_redo(Mem_Options *mem, Editing_Layout *layout, File_View *view, Editin spec.step.edit.str_start = 0; spec.str = stack->strings + step.edit.str_start; - view_do_single_edit(mem, view, file, layout, spec, hist_normal); + file_do_single_edit(mem, file, layout, spec, hist_normal); if (expected_type == ED_UNDO) view_cursor_move(view, step.pre_pos); else view_cursor_move(view, step.post_pos); @@ -2742,7 +2746,7 @@ view_history_step(Mem_Options *mem, Editing_Layout *layout, File_View *view, His spec.step.edit.str_start = 0; spec.str = file->undo.history.strings + step.edit.str_start; - view_do_single_edit(mem, view, file, layout, spec, history_mode); + file_do_single_edit(mem, file, layout, spec, history_mode); switch (spec.step.type){ case ED_NORMAL: @@ -2906,7 +2910,7 @@ clipboard_copy(General_Memory *general, Working_Set *working, Range range, Editi } internal Edit_Spec -view_compute_whitespace_edit(Mem_Options *mem, Editing_File *file, +file_compute_whitespace_edit(Mem_Options *mem, Editing_File *file, i32 cursor_pos, Buffer_Edit *edits, char *str_base, i32 str_size, Buffer_Edit *inverse_array, char *inv_str, i32 inv_max, i32 edit_count){ @@ -2933,6 +2937,8 @@ view_compute_whitespace_edit(Mem_Options *mem, Editing_File *file, spec.step.special_type = 1; spec.step.child_count = edit_count; spec.step.inverse_child_count = edit_count; + spec.step.pre_pos = cursor_pos; + spec.step.post_pos = cursor_pos; #else Edit_Spec spec = {}; #endif @@ -2989,7 +2995,7 @@ view_clean_whitespace(Mem_Options *mem, File_View *view, Editing_Layout *layout) char *inv_str = (char*)part->base + part->pos; Edit_Spec spec = - view_compute_whitespace_edit(mem, file, edits, str_base, str_size, + file_compute_whitespace_edit(mem, file, view->cursor.pos, edits, str_base, str_size, inverse_array, inv_str, part->max - part->pos, edit_count); view_do_white_batch_edit(mem, view, file, layout, spec, hist_normal); @@ -3178,7 +3184,7 @@ view_auto_tab_tokens(Mem_Options *mem, File_View *view, Editing_Layout *layout, char *inv_str = (char*)part->base + part->pos; Edit_Spec spec = - view_compute_whitespace_edit(mem, file, edits, str_base, str_size, + file_compute_whitespace_edit(mem, file, view->cursor.pos, edits, str_base, str_size, inverse_array, inv_str, part->max - part->pos, edit_count); view_do_white_batch_edit(mem, view, file, layout, spec, hist_normal); @@ -3537,8 +3543,12 @@ step_file_view(Thread_Context *thread, View *view_, i32_Rect rect, result = 1; } - while (cursor_y > target_y + max_y) target_y += delta_y; - while (cursor_y < target_y + taken_top_space) target_y -= delta_y; + if (cursor_y > target_y + max_y){ + target_y = cursor_y - max_y + delta_y; + } + if (cursor_y < target_y + taken_top_space){ + target_y = cursor_y - delta_y - taken_top_space; + } if (target_y > max_target_y) target_y = max_target_y; if (target_y < -extra_top) target_y = -extra_top; diff --git a/4ed_internal.h b/4ed_internal.h index 9319d92f..537d5804 100644 --- a/4ed_internal.h +++ b/4ed_internal.h @@ -31,7 +31,7 @@ struct Debug_Event{ struct Debug_Event_Array{ volatile u32 count; - Debug_Event e[512]; + Debug_Event e[4096]; }; struct Profile_Frame{ diff --git a/4ed_system.h b/4ed_system.h index 71f6b4d5..5d7e73d8 100644 --- a/4ed_system.h +++ b/4ed_system.h @@ -7,6 +7,8 @@ * */ +struct Plat_Handle{ u64 d[2]; }; + // TODO(allen): This should either be a String or it should be improved // to handle 64-bit sized files. Staying in this state, however, is unacceptable. struct File_Data{ @@ -76,6 +78,25 @@ system_post_clipboard(String str); internal i64 system_time(); +struct CLI_Handles{ + Plat_Handle proc; + Plat_Handle out_read; + Plat_Handle out_write; + u32 scratch_space[4]; +}; + +internal b32 +system_cli_call(char *path, char *script_name, CLI_Handles *cli_out); + +internal void +system_cli_begin_update(CLI_Handles *cli); + +internal b32 +system_cli_update_step(CLI_Handles *cli, char *dest, u32 max, u32 *amount); + +internal b32 +system_cli_end_update(CLI_Handles *cli); + struct Thread_Context; struct Thread_Memory{ diff --git a/buffer/4coder_buffer_abstract.cpp b/buffer/4coder_buffer_abstract.cpp index d771a8a2..aa38cc86 100644 --- a/buffer/4coder_buffer_abstract.cpp +++ b/buffer/4coder_buffer_abstract.cpp @@ -597,6 +597,7 @@ buffer_remeasure_widths(Buffer_Type *buffer, void *advance_data, int stride, int *starts; float *widths; int line_count; + int widths_count; char *data; int size, end; int i, j; @@ -606,17 +607,17 @@ buffer_remeasure_widths(Buffer_Type *buffer, void *advance_data, int stride, starts = buffer->line_starts; widths = buffer->line_widths; line_count = buffer->line_count; + widths_count = buffer->widths_count; assert_4tech(0 <= line_start); assert_4tech(line_start <= line_end); - assert_4tech(line_end < line_count); assert_4tech(line_count <= buffer->widths_max); - - ++line_end; + if (line_shift != 0){ memmove_4tech(widths + line_end + line_shift, widths + line_end, - sizeof(float)*(line_count - line_end)); + sizeof(float)*(widths_count - line_end)); } + buffer->widths_count = line_count; line_end += line_shift; i = line_start; @@ -733,7 +734,6 @@ buffer_get_line_index_from_wrapped_y(float *wraps, float y, float font_height, i #endif #ifndef NON_ABSTRACT_4TECH - typedef struct{ Full_Cursor cursor, prev_cursor; } Seek_State; @@ -1000,13 +1000,15 @@ buffer_invert_batch(Buffer_Invert_Batch *state, Buffer_Type *buffer, Buffer_Edit internal_4tech void buffer_batch_edit(Buffer_Type *buffer, Buffer_Edit *sorted_edits, char *strings, int edit_count){ Buffer_Batch_State state; + int r; + debug_4tech(int result); state.i = 0; state.shift_total = 0; debug_4tech(result =) - buffer_batch_edit_step(&state, buffer, sorted_edits, strings, edit_count); + buffer_batch_edit_step(&state, buffer, sorted_edits, strings, edit_count, &r); assert_4tech(result == 0); } #endif @@ -1121,7 +1123,6 @@ buffer_get_render_data(Buffer_Type *buffer, float *wraps, Buffer_Render_Item *it } buffer_get_render_data_end: - if (y <= height + shift_y || item == items){ ch = 0; ch_width = measure_character(advance_data, stride, ' '); diff --git a/buffer/4coder_gap_buffer.cpp b/buffer/4coder_gap_buffer.cpp index 1e4ba399..58d49f58 100644 --- a/buffer/4coder_gap_buffer.cpp +++ b/buffer/4coder_gap_buffer.cpp @@ -20,6 +20,7 @@ typedef struct{ float *line_widths; int *line_starts; int line_count; + int widths_count; int line_max; int widths_max; } Gap_Buffer; @@ -110,7 +111,7 @@ buffer_end_init(Gap_Buffer_Init *init){ } internal_4tech void* -buffer_relocate(Gap_Buffer *buffer, char *new_data, int new_max){ +buffer_edit_provide_memory(Gap_Buffer *buffer, void *new_data, int new_max){ void *result; int new_gap_size; @@ -119,9 +120,9 @@ buffer_relocate(Gap_Buffer *buffer, char *new_data, int new_max){ result = buffer->data; new_gap_size = new_max - buffer_size(buffer); memcpy_4tech(new_data, buffer->data, buffer->size1); - memcpy_4tech(new_data + buffer->size1 + new_gap_size, buffer->data + buffer->size1 + buffer->gap_size, buffer->size2); + memcpy_4tech((char*)new_data + buffer->size1 + new_gap_size, buffer->data + buffer->size1 + buffer->gap_size, buffer->size2); - buffer->data = new_data; + buffer->data = (char*)new_data; buffer->gap_size = new_gap_size; buffer->max = new_max; @@ -263,7 +264,7 @@ buffer_backify_next(Gap_Buffer_Backify_Loop *loop){ } internal_4tech int -buffer_replace_range(Gap_Buffer *buffer, int start, int end, char *str, int len, int *shift_amount){ +buffer_replace_range(Gap_Buffer *buffer, int start, int end, char *str, int len, int *shift_amount, int *request_amount){ char *data; int result; int size; @@ -301,7 +302,8 @@ buffer_replace_range(Gap_Buffer *buffer, int start, int end, char *str, int len, result = 0; } else{ - result = *shift_amount + size; + *request_amount = round_up_4tech(2*(*shift_amount + size), 4 << 10); + result = 1; } return(result); @@ -309,7 +311,7 @@ buffer_replace_range(Gap_Buffer *buffer, int start, int end, char *str, int len, // 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){ +buffer_batch_edit_step(Buffer_Batch_State *state, Gap_Buffer *buffer, Buffer_Edit *sorted_edits, char *strings, int edit_count, int *request_amount){ Buffer_Edit *edit; int i, result; int shift_total, shift_amount; @@ -321,7 +323,7 @@ buffer_batch_edit_step(Buffer_Batch_State *state, Gap_Buffer *buffer, Buffer_Edi 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); + strings + edit->str_start, edit->len, &shift_amount, request_amount); if (result) break; shift_total += shift_amount; } diff --git a/buffer/4coder_golden_array.cpp b/buffer/4coder_golden_array.cpp index d437ccaa..6d893f7f 100644 --- a/buffer/4coder_golden_array.cpp +++ b/buffer/4coder_golden_array.cpp @@ -20,6 +20,7 @@ typedef struct{ int *line_starts; float *line_widths; int line_count; + int widths_count; int line_max; int widths_max; } Buffer; @@ -92,14 +93,14 @@ buffer_end_init(Buffer_Init *init){ } internal_4tech void* -buffer_relocate(Buffer *buffer, char *new_data, int new_max){ +buffer_edit_provide_memory(Buffer *buffer, void *new_data, int new_max){ void *result; assert_4tech(new_max >= buffer->size); result = buffer->data; memcpy_4tech(new_data, buffer->data, buffer->size); - buffer->data = new_data; + buffer->data = (char*)new_data; buffer->max = new_max; return(result); @@ -174,7 +175,7 @@ buffer_backify_next(Buffer_Backify_Loop *loop){ } internal_4tech int -buffer_replace_range(Buffer *buffer, int start, int end, char *str, int len, int *shift_amount){ +buffer_replace_range(Buffer *buffer, int start, int end, char *str, int len, int *shift_amount, int *request_amount){ char *data; int result; int size; @@ -189,20 +190,20 @@ buffer_replace_range(Buffer *buffer, int start, int end, char *str, int len, int data = (char*)buffer->data; memmove_4tech(data + end + *shift_amount, data + end, buffer->size - end); buffer->size += *shift_amount; - data[buffer->size] = 0; if (len != 0) memcpy_4tech(data + start, str, len); result = 0; } else{ - result = *shift_amount + size; + *request_amount = round_up_4tech(2*(*shift_amount + size), 4 << 10); + result = 1; } return(result); } internal_4tech int -buffer_batch_edit_step(Buffer_Batch_State *state, Buffer *buffer, Buffer_Edit *sorted_edits, char *strings, int edit_count){ +buffer_batch_edit_step(Buffer_Batch_State *state, Buffer *buffer, Buffer_Edit *sorted_edits, char *strings, int edit_count, int *request_amount){ Buffer_Edit *edit; int i, result; int shift_total, shift_amount; @@ -214,7 +215,7 @@ buffer_batch_edit_step(Buffer_Batch_State *state, Buffer *buffer, Buffer_Edit *s 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); + strings + edit->str_start, edit->len, &shift_amount, request_amount); if (result) break; shift_total += shift_amount; } diff --git a/buffer/4coder_multi_gap_buffer.cpp b/buffer/4coder_multi_gap_buffer.cpp index fb785328..62abc9b7 100644 --- a/buffer/4coder_multi_gap_buffer.cpp +++ b/buffer/4coder_multi_gap_buffer.cpp @@ -34,6 +34,7 @@ typedef struct{ float *line_widths; int *line_starts; int line_count; + int widths_count; int line_max; int widths_max; } Multi_Gap_Buffer; @@ -170,21 +171,27 @@ internal_4tech int buffer_find_chunk(Multi_Gap_Buffer *buffer, int pos){ Fixed_Width_Gap_Buffer *gaps; int start, end, m, this_pos; - - gaps = buffer->gaps; - start = 0; - end = buffer->chunk_count; - for(;;){ - m = (start + end) / 2; - this_pos = gaps[m].start_pos; - if (this_pos < pos) start = m; - else if (this_pos > pos) end = m; - else break; - if (start+1 == end){ - m = start; break; - } - assert_4tech(start < end); + + if (pos == buffer_size(buffer)){ + m = buffer->chunk_count; } + else{ + gaps = buffer->gaps; + start = 0; + end = buffer->chunk_count; + for(;;){ + m = (start + end) / 2; + this_pos = gaps[m].start_pos; + if (this_pos < pos) start = m; + else if (this_pos > pos) end = m; + else break; + if (start+1 == end){ + m = start; break; + } + assert_4tech(start < end); + } + } + return(m); } @@ -360,6 +367,84 @@ buffer_backify_next(Multi_Gap_Buffer_Backify_Loop *loop){ } } +internal_4tech int +buffer_replace_range(Multi_Gap_Buffer *buffer, int start, int end, char *str, int len, int *shift_amount_out, int *request_amount){ + Fixed_Width_Gap_Buffer *gaps, *gap; + int gap_start, gap_end; + int result; + int size; + int local_end; + int shift_amount; + + size = buffer_size(buffer); + assert_4tech(0 <= start); + assert_4tech(start <= end); + assert_4tech(end <= size); + + *shift_amount_out = (len - (end - start)); + + gaps = buffer->gaps; + gap_start = buffer_find_chunk(buffer, start); + gap_end = buffer_find_chunk(buffer, end); + + gap = gaps + gap_start; + if (gap_start < gap_end){ + memmove_4tech(gap + 1, gaps + gap_end, sizeof(*gaps)*(buffer->chunk_count - gap_end)); + buffer->chunk_count -= (gap_end - gap_start + 1); + ++gap; + + local_end = end - gap->start_pos; + + if (gap->size1 >= local_end){ + gap->size2 -= (local_end - gap->size1); + gap->size1 = 0; + } + else{ + memmove_4tech(gap->data, gap->data + local_end, gap->size1 - local_end); + gap->size1 -= local_end; + } + + --gap; + } + if (end > gap->size1 + gap->size2) end = gap->size1 + gap->size2; + + shift_amount = (len - (end - start)); + + if (shift_amount + gap->size1 + gap->size2 <= fixed_width_buffer_size){ + start -= gap->start_pos; + end -= gap->start_pos; + + data = gap->data; + if (end < gap->size1){ + move_size = gap->size1 - end; + memmove_4tech(data + gap->size1 + gap->gap_size - move_size, data + end, move_size); + gap->size1 -= move_size; + gap->size2 += move_size; + } + if (start > gap->size1){ + move_size = start - gap->size1; + memmove_4tech(data + gap->size1, data + gap->size1 + gap->gap_size, move_size); + gap->size1 += move_size; + gap->size2 -= move_size; + } + + memcpy_4tech(data + start, str, len); + gap->size2 = size - end; + gap->size1 = start + len; + gap->gap_size -= shift_amount; + + assert_4tech(gap->size1 + gap->size2 == size + shift_amount); + assert_4tech(gap->size1 + gap->gap_size + gap->size2 == gap->max); + + result = 0; + } + else{ + div_ceil_4tech(shift_amount, fixed_width_buffer_half_size); + result = 1; + } + + return(result); +} // BOTTOM diff --git a/buffer/4coder_shared.cpp b/buffer/4coder_shared.cpp index 2685c0c6..b103d464 100644 --- a/buffer/4coder_shared.cpp +++ b/buffer/4coder_shared.cpp @@ -53,6 +53,19 @@ #define cat_4tech(a,b) cat_4tech_(a,b) #endif +#ifndef round_up_4tech +internal_4tech int +lroundup_(int x, int granularity){ + int original_x; + original_x = x; + x /= granularity; + x *= granularity; + if (x < original_x) x += granularity; + return x; +} +#define round_up_4tech(x,g) lroundup_(x,g) +#endif + inline_4tech float measure_character(void *advance_data, int stride, char character){ char *advances; diff --git a/win32_4ed.cpp b/win32_4ed.cpp index c5780b46..01f488e1 100644 --- a/win32_4ed.cpp +++ b/win32_4ed.cpp @@ -58,7 +58,7 @@ #define FPS 30 #define FRAME_TIME (1000000 / FPS) -#define BUFFER_EXPERIMENT_SCALPEL 2 +#define BUFFER_EXPERIMENT_SCALPEL 0 #include "4ed_meta.h" @@ -545,11 +545,18 @@ Win32Callback(HWND hwnd, UINT uMsg, case WM_KEYDOWN: case WM_KEYUP: { - bool8 previous_state, current_state; - previous_state = ((lParam & Bit_30)?(1):(0)); - current_state = ((lParam & Bit_31)?(0):(1)); - Win32KeyboardHandle(current_state, previous_state, wParam); - result = DefWindowProc(hwnd, uMsg, wParam, lParam); + switch (wParam){ + case VK_CONTROL:case VK_LCONTROL:case VK_RCONTROL: + case VK_MENU:case VK_LMENU:case VK_RMENU: + case VK_SHIFT:case VK_LSHIFT:case VK_RSHIFT: break; + + default: + bool8 previous_state, current_state; + previous_state = ((lParam & Bit_30)?(1):(0)); + current_state = ((lParam & Bit_31)?(0):(1)); + Win32KeyboardHandle(current_state, previous_state, wParam); + result = DefWindowProc(hwnd, uMsg, wParam, lParam); + } }break; case WM_MOUSEMOVE: @@ -880,6 +887,131 @@ INTERNAL_get_thread_states(Thread_Group_ID id, bool8 *running, i32 *pending){ } #endif +internal b32 +system_cli_call(char *path, char *script_name, CLI_Handles *cli_out){ + char cmd[] = "c:\\windows\\system32\\cmd.exe"; + char *env_variables = 0; + char command_line[2048]; + + b32 success = 1; + String s = make_fixed_width_string(command_line); + copy(&s, make_lit_string("/C ")); + append_partial(&s, script_name); + append_partial(&s, make_lit_string(".bat ")); + success = terminate_with_null(&s); + + if (success){ + success = 0; + + SECURITY_ATTRIBUTES sec_attributes; + HANDLE out_read; + HANDLE out_write; + + sec_attributes = {}; + sec_attributes.nLength = sizeof(SECURITY_ATTRIBUTES); + sec_attributes.bInheritHandle = TRUE; + + if (CreatePipe(&out_read, &out_write, &sec_attributes, 0)){ + if (SetHandleInformation(out_read, HANDLE_FLAG_INHERIT, 0)){ + STARTUPINFO startup = {}; + startup.cb = sizeof(STARTUPINFO); + startup.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; + startup.hStdError = out_write; + startup.hStdOutput = out_write; + startup.wShowWindow = SW_HIDE; + + PROCESS_INFORMATION info = {}; + + Assert(sizeof(Plat_Handle) >= sizeof(HANDLE)); + if (CreateProcess(cmd, command_line, + 0, 0, TRUE, 0, + env_variables, path, + &startup, &info)){ + success = 1; + CloseHandle(info.hThread); + *(HANDLE*)&cli_out->proc = info.hProcess; + *(HANDLE*)&cli_out->out_read = out_read; + *(HANDLE*)&cli_out->out_write = out_write; + } + else{ + CloseHandle(out_read); + CloseHandle(out_write); + *(HANDLE*)&cli_out->proc = INVALID_HANDLE_VALUE; + *(HANDLE*)&cli_out->out_read = INVALID_HANDLE_VALUE; + *(HANDLE*)&cli_out->out_write = INVALID_HANDLE_VALUE; + } + } + else{ + // TODO(allen): failed SetHandleInformation + } + } + else{ + // TODO(allen): failed CreatePipe + } + } + + return success; +} + +struct CLI_Loop_Control{ + u32 remaining_amount; +}; + +internal void +system_cli_begin_update(CLI_Handles *cli){ + Assert(sizeof(cli->scratch_space) >= sizeof(CLI_Loop_Control)); + CLI_Loop_Control *loop = (CLI_Loop_Control*)cli->scratch_space; + loop->remaining_amount = 0; +} + +internal b32 +system_cli_update_step(CLI_Handles *cli, char *dest, u32 max, u32 *amount){ + HANDLE handle = *(HANDLE*)&cli->out_read; + CLI_Loop_Control *loop = (CLI_Loop_Control*)cli->scratch_space; + b32 has_more = 0; + DWORD remaining = loop->remaining_amount; + u32 pos = 0; + DWORD read_amount = 0; + + for (;;){ + if (remaining == 0){ + if (!PeekNamedPipe(handle, 0, 0, 0, &remaining, 0)) break; + if (remaining == 0) break; + } + + if (remaining + pos < max){ + has_more = 1; + ReadFile(handle, dest + pos, remaining, &read_amount, 0); + TentativeAssert(remaining == read_amount); + pos += remaining; + remaining = 0; + } + else{ + has_more = 1; + ReadFile(handle, dest + pos, max - pos, &read_amount, 0); + TentativeAssert(max - pos == read_amount); + loop->remaining_amount = remaining - (max - pos); + pos = max; + break; + } + } + *amount = pos; + + return has_more; +} + +internal b32 +system_cli_end_update(CLI_Handles *cli){ + b32 close_me = 0; + if (WaitForSingleObject(*(HANDLE*)&cli->proc, 0) == WAIT_OBJECT_0){ + close_me = 1; + CloseHandle(*(HANDLE*)&cli->proc); + CloseHandle(*(HANDLE*)&cli->out_read); + CloseHandle(*(HANDLE*)&cli->out_write); + } + return close_me; +} + int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,