From 7c2d26463e4afb8f8ce8a131580c3b6c4e2202be Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Wed, 28 Oct 2015 18:59:39 -0400 Subject: [PATCH] gap buffer editing --- 4coder_custom.cpp | 92 +++++++++++++---------- 4ed.cpp | 90 ++++++----------------- 4ed_file_view.cpp | 117 +++++++++++++++++++++--------- buffer/4coder_buffer_abstract.cpp | 76 ++++++++++++++++++- buffer/4coder_gap_buffer.cpp | 81 +++++++++++++++++---- buffer/4coder_golden_array.cpp | 32 ++++++-- buffer/4coder_shared.cpp | 10 +++ win32_4ed.cpp | 2 +- 8 files changed, 336 insertions(+), 164 deletions(-) diff --git a/4coder_custom.cpp b/4coder_custom.cpp index c3bd0c62..e86606a5 100644 --- a/4coder_custom.cpp +++ b/4coder_custom.cpp @@ -2,7 +2,7 @@ * Example use of customization API */ -// NOTE(allen): NEW THINGS TO LOOK FOR: +// NOTE(allen|a3.1): NEW THINGS TO LOOK FOR: // mapid_user_custom - define maps other than the built in global and file maps // // inherit_map - override bindings or add new bindings in a new map with another @@ -52,7 +52,7 @@ #define literal(s) s, (sizeof(s)-1) -// NOTE(allen): All of your custom ids should be >= mapid_user_custom. +// NOTE(allen|a3.1): All of your custom ids should be >= mapid_user_custom. // I recommend enumerating your own map ids as shown here. enum My_Maps{ my_code_map = mapid_user_custom, @@ -63,30 +63,6 @@ HOOK_SIG(my_start){ exec_command(cmd_context, cmdid_change_active_panel); } -CUSTOM_COMMAND_SIG(open_my_files){ - // NOTE(allen): The command cmdid_interactive_open has is now able to - // open a file specified on the parameter stack. If the file does not - // exist cmdid_interactive_open behaves as usual. - push_parameter(cmd_context, par_name, literal("w:/4ed/data/test/basic.cpp")); - exec_command(cmd_context, cmdid_interactive_open); - - exec_command(cmd_context, cmdid_change_active_panel); - - char my_file[256]; - int my_file_len; - - my_file_len = sizeof("w:/4ed/data/test/basic.txt") - 1; - for (int i = 0; i < my_file_len; ++i){ - my_file[i] = ("w:/4ed/data/test/basic.txt")[i]; - } - - // NOTE(allen): null terminators are not needed for strings. - push_parameter(cmd_context, par_name, my_file, my_file_len); - exec_command(cmd_context, cmdid_interactive_open); - - exec_command(cmd_context, cmdid_change_active_panel); -} - char *get_extension(const char *filename, int len, int *extension_len){ char *c = (char*)(filename + len - 1); char *end = c; @@ -112,7 +88,7 @@ HOOK_SIG(my_file_settings){ int treat_as_code = 0; - // NOTE(allen): This checks buffer.file_name just in case get_active_buffer returns back + // NOTE(allen|a3.1): This checks buffer.file_name just in case get_active_buffer returns back // a null buffer (where every member is 0). if (buffer.file_name && buffer.size < (16 << 20)){ int extension_len; @@ -134,12 +110,41 @@ CUSTOM_COMMAND_SIG(open_in_other){ exec_command(cmd_context, cmdid_interactive_open); } +CUSTOM_COMMAND_SIG(open_my_files){ + // NOTE(allen|a3.1): The command cmdid_interactive_open can now open + // a file specified on the parameter stack. If the file does not + // exist cmdid_interactive_open behaves as usual. + push_parameter(cmd_context, par_name, literal("w:/4ed/data/test/basic.cpp")); + exec_command(cmd_context, cmdid_interactive_open); + + exec_command(cmd_context, cmdid_change_active_panel); + + char my_file[256]; + int my_file_len; + + my_file_len = sizeof("w:/4ed/data/test/basic.txt") - 1; + for (int i = 0; i < my_file_len; ++i){ + my_file[i] = ("w:/4ed/data/test/basic.txt")[i]; + } + + // NOTE(allen|3.1): null terminators are not needed for strings. + push_parameter(cmd_context, par_name, my_file, my_file_len); + exec_command(cmd_context, cmdid_interactive_open); + + exec_command(cmd_context, cmdid_change_active_panel); +} + +CUSTOM_COMMAND_SIG(write_and_auto_tab){ + exec_command(cmd_context, cmdid_write_character); + exec_command(cmd_context, cmdid_auto_tab_line_at_cursor); +} + extern "C" GET_BINDING_DATA(get_bindings){ Bind_Helper context_actual = begin_bind_helper(data, size); Bind_Helper *context = &context_actual; - // NOTE(allen): Right now hooks have no loyalties to maps, all hooks are - // global and once set they always apply. + // NOTE(allen|a3.1): Right now hooks have no loyalties to maps, all hooks are + // global and once set they always apply, regardless of what map is active. set_hook(context, hook_start, my_start); set_hook(context, hook_open_file, my_file_settings); @@ -156,7 +161,8 @@ extern "C" GET_BINDING_DATA(get_bindings){ bind(context, 'c', MDFR_ALT, cmdid_open_color_tweaker); bind(context, 'x', MDFR_ALT, cmdid_open_menu); bind_me(context, 'o', MDFR_ALT, open_in_other); - // NOTE(allen): Go look at open_my_files, that's the only point of this being here. + // NOTE(allen|a3.1): Go look at open_my_files, that's the only point of this being here, + // it won't actually be useful for you. bind_me(context, 'M', MDFR_ALT | MDFR_CTRL, open_my_files); end_map(context); @@ -164,26 +170,36 @@ extern "C" GET_BINDING_DATA(get_bindings){ begin_map(context, my_code_map); - // NOTE(allen): Set this map (my_code_map == mapid_user_custom) to + // NOTE(allen|a3.1): Set this map (my_code_map == mapid_user_custom) to // inherit from mapid_file. When searching if a key is bound // in this map, if it is not found here it will then search mapid_file. // // If this is not set, it defaults to mapid_global. inherit_map(context, mapid_file); - - // NOTE(allen): This demonstrates that children can override parent's bindings. + + // NOTE(allen|a3.1): Children can override parent's bindings. bind(context, codes->right, MDFR_CTRL, cmdid_seek_alphanumeric_or_camel_right); bind(context, codes->left, MDFR_CTRL, cmdid_seek_alphanumeric_or_camel_left); - // NOTE(allen): Not currently functional - bind(context, '\t', MDFR_CTRL, cmdid_auto_tab); + // NOTE(allen|a3.1.1): Specific keys can override vanilla keys, + // and write character writes whichever character corresponds + // to the key that triggered the command. + bind_me(context, '\n', MDFR_NONE, write_and_auto_tab); + bind_me(context, '}', MDFR_NONE, write_and_auto_tab); + bind_me(context, ')', MDFR_NONE, write_and_auto_tab); + bind_me(context, ']', MDFR_NONE, write_and_auto_tab); + bind_me(context, ';', MDFR_NONE, write_and_auto_tab); + + bind(context, '\t', MDFR_NONE, cmdid_auto_tab_line_at_cursor); + bind(context, '\t', MDFR_CTRL, cmdid_auto_tab_range); + bind(context, '\t', MDFR_CTRL | MDFR_SHIFT, cmdid_write_character); end_map(context); - + begin_map(context, mapid_file); - // NOTE(allen): Binding this essentially binds all key combos that + // NOTE(allen|a3.1): Binding this essentially binds all key combos that // would normally insert a character into a buffer. // Or apply this rule (which always works): if the code for the key // is not in the codes struct, it is a vanilla key. @@ -228,7 +244,7 @@ extern "C" GET_BINDING_DATA(get_bindings){ bind(context, '?', MDFR_CTRL, cmdid_toggle_show_whitespace); bind(context, '~', MDFR_CTRL, cmdid_clean_all_lines); - // NOTE(allen): These now only set the mode of the file for writing to disk + // NOTE(allen|a3.1.1): These now only set the mode of the file for writing to disk // they do no longer effect the internal representation. bind(context, '1', MDFR_CTRL, cmdid_eol_dosify); bind(context, '!', MDFR_CTRL, cmdid_eol_nixify); diff --git a/4ed.cpp b/4ed.cpp index 2fcc1cde..638e13f3 100644 --- a/4ed.cpp +++ b/4ed.cpp @@ -354,55 +354,23 @@ COMMAND_DECL(seek_alphanumeric_left){ } COMMAND_DECL(seek_alphanumeric_or_camel_right){ -#if 0 ProfileMomentFunction(); REQ_FILE_VIEW(view); REQ_FILE(file, view); - - char *data = file->buffer.data; - - i32 an_pos, camel_pos; - an_pos = seek_alphanumeric_right( - (u8*)file->buffer.data, file->buffer.size, view->cursor.pos); - - u8 curr_char; - u8 prev_char = data[view->cursor.pos + 1]; - for (camel_pos = view->cursor.pos + 2; camel_pos < an_pos; ++camel_pos){ - curr_char = data[camel_pos]; - if (char_is_upper(curr_char) && char_is_lower(prev_char)){ - break; - } - prev_char = curr_char; - } - - view_cursor_move(view, camel_pos); -#endif + + i32 an_pos = buffer_seek_alphanumeric_right(&file->buffer, view->cursor.pos); + i32 pos = buffer_seek_alphanumeric_or_camel_right(&file->buffer, view->cursor.pos, an_pos); + view_cursor_move(view, pos); } COMMAND_DECL(seek_alphanumeric_or_camel_left){ -#if 0 ProfileMomentFunction(); REQ_FILE_VIEW(view); REQ_FILE(file, view); - u8 *data = (u8*)file->buffer.data; - - i32 an_pos, camel_pos; - an_pos = buffer_seek_alphanumeric_left( - data, view->cursor.pos); - - char curr_char; - char prev_char = data[view->cursor.pos]; - for (camel_pos = view->cursor.pos - 1; camel_pos > an_pos; --camel_pos){ - curr_char = data[camel_pos]; - if (char_is_upper(curr_char) && char_is_lower(prev_char)){ - break; - } - prev_char = curr_char; - } - - view_cursor_move(view, camel_pos); -#endif + i32 an_pos = buffer_seek_alphanumeric_left(&file->buffer, view->cursor.pos); + i32 pos = buffer_seek_alphanumeric_or_camel_left(&file->buffer, view->cursor.pos, an_pos); + view_cursor_move(view, pos); } COMMAND_DECL(search){ @@ -458,13 +426,11 @@ COMMAND_DECL(copy){ Range range = get_range(view->cursor.pos, view->mark); if (range.start < range.end){ - u8 *data = (u8*)file->buffer.data; - clipboard_copy(&mem->general, working_set, data, range); + clipboard_copy(&mem->general, working_set, range, file); } } COMMAND_DECL(cut){ -#if BUFFER_EXPERIMENT_SCALPEL ProfileMomentFunction(); REQ_FILE_VIEW(view); REQ_FILE(file, view); @@ -474,17 +440,15 @@ COMMAND_DECL(cut){ Range range = get_range(view->cursor.pos, view->mark); if (range.start < range.end){ - u8 *data = (u8*)file->buffer.data; - i32 next_cursor_pos = range.start; - clipboard_copy(&mem->general, working_set, data, range); + + clipboard_copy(&mem->general, working_set, range, file); view_replace_range(mem, view, layout, range.start, range.end, 0, 0, next_cursor_pos); view->mark = range.start; view_measure_wraps(&mem->general, view); view_cursor_move(view, next_cursor_pos); } -#endif } COMMAND_DECL(paste){ @@ -561,7 +525,6 @@ COMMAND_DECL(paste_next){ } COMMAND_DECL(delete_chunk){ -#if BUFFER_EXPERIMENT_SCALPEL ProfileMomentFunction(); REQ_FILE_VIEW(view); REQ_FILE(file, view); @@ -576,7 +539,6 @@ COMMAND_DECL(delete_chunk){ view_cursor_move(view, next_cursor_pos); view->mark = range.start; } -#endif } COMMAND_DECL(timeline_scrub){ @@ -1246,15 +1208,15 @@ COMMAND_DECL(move_right){ } COMMAND_DECL(delete){ -#if BUFFER_EXPERIMENT_SCALPEL ProfileMomentFunction(); REQ_FILE_VIEW(view); REQ_FILE(file, view); USE_LAYOUT(layout); USE_MEM(mem); - + + i32 size = buffer_size(&file->buffer); i32 cursor_pos = view->cursor.pos; - if (file->buffer.size > 0 && cursor_pos < file->buffer.size){ + if (0 < size && cursor_pos < size){ i32 start, end; start = cursor_pos; end = cursor_pos+1; @@ -1267,22 +1229,20 @@ COMMAND_DECL(delete){ view_cursor_move(view, next_cursor_pos); if (view->mark >= end) view->mark -= shift; } -#endif } COMMAND_DECL(backspace){ -#if BUFFER_EXPERIMENT_SCALPEL ProfileMomentFunction(); REQ_FILE_VIEW(view); REQ_FILE(file, view); USE_LAYOUT(layout); USE_MEM(mem); + i32 size = buffer_size(&file->buffer); i32 cursor_pos = view->cursor.pos; - if (cursor_pos > 0 && cursor_pos <= (i32)file->buffer.size){ + if (cursor_pos > 0 && cursor_pos <= size){ i32 start, end; end = cursor_pos; - start = cursor_pos-1; i32 shift = (end - start); @@ -1293,7 +1253,6 @@ COMMAND_DECL(backspace){ view_cursor_move(view, next_cursor_pos); if (view->mark >= end) view->mark -= shift; } -#endif } COMMAND_DECL(move_up){ @@ -1531,13 +1490,12 @@ COMMAND_DECL(set_settings){ case par_key_mapid: { int v = dynamic_to_int(¶m->param.value); - Command_Map *map = 0; - if (v == mapid_global) map = &vars->map_top; - else if (v == mapid_file) map = &vars->map_file; + if (v == mapid_global) file->base_map_id = mapid_global; + else if (v == mapid_file) file->base_map_id = mapid_file; else if (v >= mapid_user_custom){ int index = app_get_map_index(vars, v); - if (index < vars->user_map_count) map = vars->user_maps + index; - else map = 0; + if (index < vars->user_map_count) file->base_map_id = v; + else file->base_map_id = mapid_file; } }break; } @@ -1685,8 +1643,8 @@ setup_file_commands(Command_Map *commands, Partition *part, Key_Codes *codes, Co map_add(commands, codes->page_up, MDFR_NONE, command_page_up); map_add(commands, codes->page_down, MDFR_NONE, command_page_down); - map_add(commands, codes->right, MDFR_CTRL, command_seek_whitespace_right); - map_add(commands, codes->left, MDFR_CTRL, command_seek_whitespace_left); + map_add(commands, codes->right, MDFR_CTRL, command_seek_alphanumeric_or_camel_right); + map_add(commands, codes->left, MDFR_CTRL, command_seek_alphanumeric_or_camel_left); map_add(commands, codes->up, MDFR_CTRL, command_seek_whitespace_up); map_add(commands, codes->down, MDFR_CTRL, command_seek_whitespace_down); @@ -2568,9 +2526,7 @@ app_step(Thread_Context *thread, Key_Codes *codes, if (!view_->is_active) continue; File_View *view = view_to_file_view(view_); if (!view) continue; -#if BUFFER_EXPERIMENT_SCALPEL view_measure_wraps(&vars->mem.general, view); -#endif view->cursor = view_compute_cursor_from_pos(view, view->cursor.pos); } app_result.redraw = 1; @@ -3099,15 +3055,13 @@ app_step(Thread_Context *thread, Key_Codes *codes, // NOTE(allen): send style change messages if the style has changed if (vars->style.font_changed){ vars->style.font_changed = 0; - -#if BUFFER_EXPERIMENT_SCALPEL + Editing_File *file = vars->working_set.files; for (i32 i = vars->working_set.file_index_count; i > 0; --i, ++file){ if (file->buffer.data && !file->is_dummy){ file_measure_widths(&vars->mem.general, file, vars->style.font); } } -#endif Panel *panel = panels; for (i32 panel_i = vars->layout.panel_count; panel_i > 0; --panel_i, ++panel){ diff --git a/4ed_file_view.cpp b/4ed_file_view.cpp index f7bba12f..94446df3 100644 --- a/4ed_file_view.cpp +++ b/4ed_file_view.cpp @@ -1664,14 +1664,10 @@ file_grow_as_needed(General_Memory *general, Editing_File *file, i32 additional_ if (target_size >= file->buffer.max){ i32 request_size = LargeRoundUp(target_size*2, Kbytes(256)); char *new_data = (char*) - general_memory_reallocate(general, file->buffer.data, size, request_size, BUBBLE_BUFFER); - if (new_data){ - file->buffer.data = new_data; - file->buffer.max = request_size; - } - else{ - result = 0; - } + 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); } return result; } @@ -2427,10 +2423,10 @@ view_do_single_edit(Mem_Options *mem, File_View *view, Editing_File *file, i32 str_len = spec.step.edit.len; i32 shift_amount = 0; -#if BUFFER_EXPERIMENT_SCALPEL while (buffer_replace_range(&file->buffer, start, end, str, str_len, &shift_amount)) file_grow_as_needed(general, file, shift_amount); +#if BUFFER_EXPERIMENT_SCALPEL // NOTE(allen): fixing stuff afterwards if (file->tokens_exist) file_relex_parallel(mem, file, start, end, shift_amount); @@ -2844,11 +2840,12 @@ working_set_lookup_file(Working_Set *working_set, String string){ } internal void -clipboard_copy(General_Memory *general, Working_Set *working, u8 *data, Range range){ - i32 size = range.end - range.start; - String *dest = working_set_next_clipboard_string(general, working, size); - copy(dest, make_string((char*)data + range.start, size)); - system_post_clipboard(*dest); +clipboard_copy(General_Memory *general, Working_Set *working, Range range, Editing_File *file){ + i32 size = range.end - range.start; + String *dest = working_set_next_clipboard_string(general, working, size); + buffer_stringify(&file->buffer, range.start, range.end, dest->str); + dest->size = size; + system_post_clipboard(*dest); } internal Edit_Spec @@ -2856,6 +2853,7 @@ view_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){ +#if BUFFER_EXPERIMENT_SCALPEL General_Memory *general = &mem->general; i32 inv_str_pos = 0; @@ -2878,7 +2876,9 @@ 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; - +#else + Edit_Spec spec = {}; +#endif return spec; } @@ -2964,47 +2964,92 @@ view_auto_tab_tokens(Mem_Options *mem, File_View *view, Editing_Layout *layout, i32 *indent_marks = push_array(part, i32, indent_mark_count); { i32 current_indent = 0; - i32 line; - for (line = line_start - 1; line >= 0; --line){ + i32 token_i; + Cpp_Token *token, *self_token; + + { + i32 start_pos = file->buffer.line_starts[line_start]; + Cpp_Get_Token_Result result = cpp_get_token(&tokens, start_pos); + token_i = result.token_index; + if (result.in_whitespace) token_i += 1; + self_token = tokens.tokens + token_i; + } + + i32 line = line_start - 1; + for (; line >= 0; --line){ i32 start = file->buffer.line_starts[line]; b32 all_whitespace = 0; b32 all_space = 0; buffer_find_hard_start(&file->buffer, start, &all_whitespace, &all_space, ¤t_indent, 4); if (!all_whitespace) break; } - - if (line < 0) line = 0; - i32 start_pos = file->buffer.line_starts[line]; - Cpp_Get_Token_Result result = cpp_get_token(&tokens, start_pos); - i32 start_token; - if (result.in_whitespace) start_token = result.token_index + 1; - else start_token = result.token_index; + + if (line < 0){ + token_i = 0; + token = tokens.tokens + token_i; + } + else{ + i32 start_pos = file->buffer.line_starts[line]; + Cpp_Get_Token_Result result = cpp_get_token(&tokens, start_pos); + token_i = result.token_index; + if (result.in_whitespace) token_i += 1; + token = tokens.tokens + token_i; + + if (token->start < start_pos){ + line = buffer_get_line_index(&file->buffer, token->start); + i32 start = file->buffer.line_starts[line]; + b32 all_whitespace = 0; + b32 all_space = 0; + buffer_find_hard_start(&file->buffer, start, &all_whitespace, &all_space, ¤t_indent, 4); + Assert(!all_whitespace); + } + } indent_marks -= line_start; i32 line_i = line_start; i32 next_line_start = file->buffer.line_starts[line_i]; - Cpp_Token *token = tokens.tokens + start_token; switch (token->type){ case CPP_TOKEN_BRACKET_OPEN: current_indent += 4; break; case CPP_TOKEN_PARENTHESE_OPEN: current_indent += 4; break; case CPP_TOKEN_BRACE_OPEN: current_indent += 4; break; } + + Cpp_Token *prev_token = token; ++token; - for (i32 token_i = start_token + 1; line_i < line_end; ++token_i, ++token){ + for (; line_i < line_end; ++token_i, ++token){ for (; token->start >= next_line_start && line_i < line_end;){ + i32 this_line_start = next_line_start; next_line_start = file->buffer.line_starts[line_i+1]; - i32 this_indent = current_indent; - if (token->start < next_line_start){ - switch (token->type){ - case CPP_TOKEN_BRACKET_CLOSE: this_indent -= 4; break; - case CPP_TOKEN_PARENTHESE_CLOSE: this_indent -= 4; break; - case CPP_TOKEN_BRACE_CLOSE: this_indent -= 4; break; - } + i32 this_indent; + if (prev_token && prev_token->type == CPP_TOKEN_COMMENT && + prev_token->start <= this_line_start && prev_token->start + prev_token->size > this_line_start){ + this_indent = -1; + } + else{ + this_indent = current_indent; + if (token->start < next_line_start){ + switch (token->type){ + case CPP_TOKEN_BRACKET_CLOSE: this_indent -= 4; break; + case CPP_TOKEN_PARENTHESE_CLOSE: this_indent -= 4; break; + case CPP_TOKEN_BRACE_CLOSE: this_indent -= 4; break; + case CPP_TOKEN_BRACE_OPEN: break; + default: + if (current_indent > 0 && prev_token){ + switch (prev_token->type){ + case CPP_TOKEN_BRACKET_OPEN: case CPP_TOKEN_PARENTHESE_OPEN: + case CPP_TOKEN_BRACE_OPEN: case CPP_TOKEN_BRACE_CLOSE: + case CPP_TOKEN_SEMICOLON: case CPP_TOKEN_COLON: break; + default: this_indent += 4; + } + } + } + } + if (this_indent < 0) this_indent = 0; } - if (this_indent < 0) this_indent = 0; indent_marks[line_i] = this_indent; ++line_i; } + switch (token->type){ case CPP_TOKEN_BRACKET_OPEN: current_indent += 4; break; case CPP_TOKEN_BRACKET_CLOSE: current_indent -= 4; break; @@ -3013,6 +3058,7 @@ view_auto_tab_tokens(Mem_Options *mem, File_View *view, Editing_Layout *layout, case CPP_TOKEN_BRACE_OPEN: current_indent += 4; break; case CPP_TOKEN_BRACE_CLOSE: current_indent -= 4; break; } + prev_token = token; } } @@ -3032,6 +3078,7 @@ view_auto_tab_tokens(Mem_Options *mem, File_View *view, Editing_Layout *layout, correct_indentation = indent_marks[line_i]; if (all_whitespace && empty_blank_lines) correct_indentation = 0; + if (correct_indentation == -1) correct_indentation = preferred_indentation; if ((all_whitespace && hard_start > start) || !all_space || correct_indentation != preferred_indentation){ Buffer_Edit new_edit; @@ -3653,7 +3700,7 @@ draw_file_view(Thread_Context *thread, View *view_, i32_Rect rect, bool32 is_act u32 mark_color = style->main.mark_color; Buffer_Render_Item *item = items; i32 prev_ind = -1; - u32 highlight_color = 0; + u32 highlight_color = 0; AllowLocal(highlight_color); for (i32 i = 0; i < count; ++i, ++item){ i32 ind = item->index; if (tokens_use && ind != prev_ind){ diff --git a/buffer/4coder_buffer_abstract.cpp b/buffer/4coder_buffer_abstract.cpp index df4219f5..281e9baa 100644 --- a/buffer/4coder_buffer_abstract.cpp +++ b/buffer/4coder_buffer_abstract.cpp @@ -18,7 +18,7 @@ inline_4tech void buffer_stringify(Buffer_Type *buffer, int start, int end, char *out){ - for (Buffer_Stringify_Loop loop = buffer_stringify_loop(buffer, start, end, end - start); + for (Buffer_Stringify_Type loop = buffer_stringify_loop(buffer, start, end, end - start); buffer_stringify_good(&loop); buffer_stringify_next(&loop)){ memcpy_4tech(out, loop.data, loop.size); @@ -133,7 +133,7 @@ buffer_seek_whitespace_up(Buffer_Type *buffer, int pos){ buffer_backify_next(&loop)){ end = loop.absolute_pos; data = loop.data - loop.absolute_pos; - for (;pos > end; --pos){ + for (;pos >= end && pos > 0; --pos){ if (!is_whitespace(data[pos])) goto buffer_seek_whitespace_up_mid; } } @@ -144,7 +144,7 @@ buffer_seek_whitespace_up_mid: buffer_backify_next(&loop)){ end = loop.absolute_pos; data = loop.data - loop.absolute_pos; - for (; pos > end; --pos){ + for (; pos >= end && pos > 0; --pos){ if (data[pos] == '\n'){ if (no_hard) goto buffer_seek_whitespace_up_end; else no_hard = 1; @@ -293,6 +293,76 @@ buffer_seek_alphanumeric_left(Buffer_Type *buffer, int pos){ return(pos); } +internal_4tech int +buffer_seek_alphanumeric_or_camel_right(Buffer_Type *buffer, int pos, int an_pos){ + Buffer_Stringify_Type loop; + char *data; + int end, size; + char ch, prev_ch; + + size = buffer_size(buffer); + assert_4tech(pos < an_pos); + assert_4tech(an_pos < size); + + ++pos; + if (pos < an_pos){ + loop = buffer_stringify_loop(buffer, pos, an_pos, size); + if (buffer_stringify_good(&loop)){ + prev_ch = loop.data[0]; + ++pos; + + for (;buffer_stringify_good(&loop); + buffer_stringify_next(&loop)){ + end = loop.size + loop.absolute_pos; + data = loop.data - loop.absolute_pos; + for (; pos < end; ++pos){ + ch = data[pos]; + if (is_upper(ch) && is_lower(prev_ch)) goto buffer_seek_alphanumeric_or_camel_right_end; + prev_ch = ch; + } + } + } + } + else{ + pos = an_pos; + } + +buffer_seek_alphanumeric_or_camel_right_end: + return(pos); +} + +internal_4tech int +buffer_seek_alphanumeric_or_camel_left(Buffer_Type *buffer, int pos, int an_pos){ + Buffer_Backify_Type loop; + char *data; + int end, size; + char ch, prev_ch; + + size = buffer_size(buffer); + assert_4tech(an_pos < pos); + assert_4tech(0 <= an_pos); + + loop = buffer_backify_loop(buffer, pos, an_pos, size); + if (buffer_backify_good(&loop)){ + prev_ch = loop.data[0]; + --pos; + + for (;buffer_backify_good(&loop); + buffer_backify_next(&loop)){ + end = loop.absolute_pos; + data = loop.data - loop.absolute_pos; + for (; pos >= end && pos > 0; --pos){ + ch = data[pos]; + if (is_upper(ch) && is_lower(prev_ch)) goto buffer_seek_alphanumeric_or_camel_left_end; + prev_ch = ch; + } + } + } + +buffer_seek_alphanumeric_or_camel_left_end: + return(pos); +} + typedef struct{ int i; int count; diff --git a/buffer/4coder_gap_buffer.cpp b/buffer/4coder_gap_buffer.cpp index b357e146..3c43cf93 100644 --- a/buffer/4coder_gap_buffer.cpp +++ b/buffer/4coder_gap_buffer.cpp @@ -24,18 +24,23 @@ typedef struct{ int widths_max; } Gap_Buffer; +inline_4tech int +buffer_size(Gap_Buffer *buffer){ + int size; + size = buffer->size1 + buffer->size2; + return(size); +} + inline_4tech void buffer_initialize(Gap_Buffer *buffer, char *data, int size){ int osize1, size1, size2; assert_4tech(buffer->max >= size); - size2 = size >> 1; size1 = osize1 = size - size2; if (size1 > 0){ size1 = eol_convert_in(buffer->data, data, size1); - if (size2 > 0){ size2 = eol_convert_in(buffer->data + size1, data + osize1, size2); } @@ -47,11 +52,23 @@ buffer_initialize(Gap_Buffer *buffer, char *data, int size){ memmove_4tech(buffer->data + size1 + buffer->gap_size, buffer->data + size1, size2); } -inline_4tech int -buffer_size(Gap_Buffer *buffer){ - int size; - size = buffer->size1 + buffer->size2; - return(size); +internal_4tech void* +buffer_relocate(Gap_Buffer *buffer, char *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(new_data + buffer->size1 + new_gap_size, buffer->data + buffer->size1 + buffer->gap_size, buffer->size2); + + buffer->data = new_data; + buffer->gap_size = new_gap_size; + buffer->max = new_max; + + return(result); } typedef struct{ @@ -149,6 +166,7 @@ buffer_backify_loop(Gap_Buffer *buffer, int start, int end, int page_size){ Gap_Buffer_Backify_Loop result; int chunk2_start; + ++start; if (0 <= end && end < start && start <= buffer->size1 + buffer->size2){ chunk2_start = buffer->size1 + buffer->gap_size; @@ -237,14 +255,49 @@ buffer_backify_next(Gap_Buffer_Backify_Loop *loop){ loop->data = loop->base + loop->pos; } -inline_4tech void -buffer_stringify(Gap_Buffer *buffer, int start, int end, char *out){ - for (Gap_Buffer_Stringify_Loop loop = buffer_stringify_loop(buffer, start, end, end - start); - buffer_stringify_good(&loop); - buffer_stringify_next(&loop)){ - memcpy_4tech(out, loop.data, loop.size); - out += loop.size; +internal_4tech int +buffer_replace_range(Gap_Buffer *buffer, int start, int end, char *str, int len, int *shift_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{ + result = *shift_amount + size; + } + + return(result); } // BOTTOM diff --git a/buffer/4coder_golden_array.cpp b/buffer/4coder_golden_array.cpp index 5677c80d..6b6a8f5a 100644 --- a/buffer/4coder_golden_array.cpp +++ b/buffer/4coder_golden_array.cpp @@ -24,15 +24,29 @@ typedef struct{ int widths_max; } Buffer; +inline_4tech int +buffer_size(Buffer *buffer){ + return buffer->size; +} + internal_4tech void buffer_initialize(Buffer *buffer, char *data, int size){ assert_4tech(size <= buffer->max); buffer->size = eol_convert_in(buffer->data, data, size); } -inline_4tech int -buffer_size(Buffer *buffer){ - return buffer->size; +internal_4tech void* +buffer_relocate(Buffer *buffer, char *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->max = new_max; + + return(result); } typedef struct{ @@ -88,6 +102,8 @@ typedef struct{ inline_4tech Buffer_Backify_Loop buffer_backify_loop(Buffer *buffer, int start, int end, int page_size){ Buffer_Backify_Loop result; + + ++start; if (0 <= end && end < start && start <= buffer->size){ result.buffer = buffer; result.end = buffer->data + end; @@ -128,9 +144,15 @@ internal_4tech int buffer_replace_range(Buffer *buffer, int start, int end, char *str, int len, int *shift_amount){ char *data; int result; + int 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 + buffer->size + 1 <= buffer->max){ + if (*shift_amount + size <= buffer->max){ data = (char*)buffer->data; memmove_4tech(data + end + *shift_amount, data + end, buffer->size - end); buffer->size += *shift_amount; @@ -140,7 +162,7 @@ buffer_replace_range(Buffer *buffer, int start, int end, char *str, int len, int result = 0; } else{ - result = *shift_amount + buffer->size + 1; + result = *shift_amount + size; } return(result); diff --git a/buffer/4coder_shared.cpp b/buffer/4coder_shared.cpp index 493bd4c8..5bc8ce60 100644 --- a/buffer/4coder_shared.cpp +++ b/buffer/4coder_shared.cpp @@ -383,5 +383,15 @@ is_alphanumeric_true(char c){ return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9'); } +inline_4tech int +is_upper(char c){ + return (c >= 'A' && c <= 'Z'); +} + +inline_4tech int +is_lower(char c){ + return (c >= 'a' && c <= 'z'); +} + // BOTTOM diff --git a/win32_4ed.cpp b/win32_4ed.cpp index d5d6b584..3c61cbc1 100644 --- a/win32_4ed.cpp +++ b/win32_4ed.cpp @@ -54,7 +54,7 @@ #define FPS 30 #define FRAME_TIME (1000000 / FPS) -#define BUFFER_EXPERIMENT_SCALPEL 1 +#define BUFFER_EXPERIMENT_SCALPEL 0 #include "4ed_meta.h"