multi-gap buffer

This commit is contained in:
Allen Webster 2015-10-30 22:33:13 -04:00
parent 02d72d118d
commit afbde90d9e
10 changed files with 596 additions and 310 deletions

40
4ed.cpp
View File

@ -123,7 +123,7 @@ globalvar Application_Links app_links;
#define REQ_VIEW(n) View *n = command->view; if (!n) return #define REQ_VIEW(n) View *n = command->view; if (!n) return
#define REQ_FILE_VIEW(n) File_View *n = view_to_file_view(command->view); if (!n) return #define REQ_FILE_VIEW(n) File_View *n = view_to_file_view(command->view); if (!n) return
#define REQ_FILE(n,v) Editing_File *n = (v)->file; if (!n || !n->buffer.data || n->is_dummy) return #define REQ_FILE(n,v) Editing_File *n = (v)->file; if (!n || !buffer_good(&n->buffer) || n->is_dummy) return
#define REQ_COLOR_VIEW(n) Color_View *n = view_to_color_view(command->view); if (!n) return #define REQ_COLOR_VIEW(n) Color_View *n = view_to_color_view(command->view); if (!n) return
#define REQ_DBG_VIEW(n) Debug_View *n = view_to_debug_view(command->view); if (!n) return #define REQ_DBG_VIEW(n) Debug_View *n = view_to_debug_view(command->view); if (!n) return
@ -215,6 +215,7 @@ COMMAND_DECL(write_character){
} }
COMMAND_DECL(seek_whitespace_right){ COMMAND_DECL(seek_whitespace_right){
#if BUFFER_EXPERIMENT_SCALPEL <= 1
ProfileMomentFunction(); ProfileMomentFunction();
REQ_FILE_VIEW(view); REQ_FILE_VIEW(view);
REQ_FILE(file, view); REQ_FILE(file, view);
@ -222,9 +223,11 @@ COMMAND_DECL(seek_whitespace_right){
i32 pos = buffer_seek_whitespace_right(&file->buffer, view->cursor.pos); i32 pos = buffer_seek_whitespace_right(&file->buffer, view->cursor.pos);
view_cursor_move(view, pos); view_cursor_move(view, pos);
#endif
} }
COMMAND_DECL(seek_whitespace_left){ COMMAND_DECL(seek_whitespace_left){
#if BUFFER_EXPERIMENT_SCALPEL <= 1
ProfileMomentFunction(); ProfileMomentFunction();
REQ_FILE_VIEW(view); REQ_FILE_VIEW(view);
REQ_FILE(file, view); REQ_FILE(file, view);
@ -232,24 +235,29 @@ COMMAND_DECL(seek_whitespace_left){
i32 pos = buffer_seek_whitespace_left(&file->buffer, view->cursor.pos); i32 pos = buffer_seek_whitespace_left(&file->buffer, view->cursor.pos);
view_cursor_move(view, pos); view_cursor_move(view, pos);
#endif
} }
COMMAND_DECL(seek_whitespace_up){ COMMAND_DECL(seek_whitespace_up){
#if BUFFER_EXPERIMENT_SCALPEL <= 1
ProfileMomentFunction(); ProfileMomentFunction();
REQ_FILE_VIEW(view); REQ_FILE_VIEW(view);
REQ_FILE(file, view); REQ_FILE(file, view);
i32 pos = buffer_seek_whitespace_up(&file->buffer, view->cursor.pos); i32 pos = buffer_seek_whitespace_up(&file->buffer, view->cursor.pos);
view_cursor_move(view, pos); view_cursor_move(view, pos);
#endif
} }
COMMAND_DECL(seek_whitespace_down){ COMMAND_DECL(seek_whitespace_down){
#if BUFFER_EXPERIMENT_SCALPEL <= 1
ProfileMomentFunction(); ProfileMomentFunction();
REQ_FILE_VIEW(view); REQ_FILE_VIEW(view);
REQ_FILE(file, view); REQ_FILE(file, view);
i32 pos = buffer_seek_whitespace_down(&file->buffer, view->cursor.pos); i32 pos = buffer_seek_whitespace_down(&file->buffer, view->cursor.pos);
view_cursor_move(view, pos); view_cursor_move(view, pos);
#endif
} }
internal i32 internal i32
@ -304,7 +312,7 @@ COMMAND_DECL(seek_token_right){
} }
COMMAND_DECL(seek_white_or_token_right){ COMMAND_DECL(seek_white_or_token_right){
#if BUFFER_EXPERIMENT_SCALPEL #if BUFFER_EXPERIMENT_SCALPEL <= 0
ProfileMomentFunction(); ProfileMomentFunction();
REQ_FILE_VIEW(view); REQ_FILE_VIEW(view);
REQ_FILE(file, view); REQ_FILE(file, view);
@ -320,7 +328,7 @@ COMMAND_DECL(seek_white_or_token_right){
} }
COMMAND_DECL(seek_white_or_token_left){ COMMAND_DECL(seek_white_or_token_left){
#if BUFFER_EXPERIMENT_SCALPEL #if BUFFER_EXPERIMENT_SCALPEL <= 0
ProfileMomentFunction(); ProfileMomentFunction();
REQ_FILE_VIEW(view); REQ_FILE_VIEW(view);
REQ_FILE(file, view); REQ_FILE(file, view);
@ -336,24 +344,29 @@ COMMAND_DECL(seek_white_or_token_left){
} }
COMMAND_DECL(seek_alphanumeric_right){ COMMAND_DECL(seek_alphanumeric_right){
#if BUFFER_EXPERIMENT_SCALPEL <= 1
ProfileMomentFunction(); ProfileMomentFunction();
REQ_FILE_VIEW(view); REQ_FILE_VIEW(view);
REQ_FILE(file, view); REQ_FILE(file, view);
i32 pos = buffer_seek_alphanumeric_right(&file->buffer, view->cursor.pos); i32 pos = buffer_seek_alphanumeric_right(&file->buffer, view->cursor.pos);
view_cursor_move(view, pos); view_cursor_move(view, pos);
#endif
} }
COMMAND_DECL(seek_alphanumeric_left){ COMMAND_DECL(seek_alphanumeric_left){
#if BUFFER_EXPERIMENT_SCALPEL <= 1
ProfileMomentFunction(); ProfileMomentFunction();
REQ_FILE_VIEW(view); REQ_FILE_VIEW(view);
REQ_FILE(file, view); REQ_FILE(file, view);
i32 pos = buffer_seek_alphanumeric_left(&file->buffer, view->cursor.pos); i32 pos = buffer_seek_alphanumeric_left(&file->buffer, view->cursor.pos);
view_cursor_move(view, pos); view_cursor_move(view, pos);
#endif
} }
COMMAND_DECL(seek_alphanumeric_or_camel_right){ COMMAND_DECL(seek_alphanumeric_or_camel_right){
#if BUFFER_EXPERIMENT_SCALPEL <= 1
ProfileMomentFunction(); ProfileMomentFunction();
REQ_FILE_VIEW(view); REQ_FILE_VIEW(view);
REQ_FILE(file, view); REQ_FILE(file, view);
@ -361,9 +374,11 @@ COMMAND_DECL(seek_alphanumeric_or_camel_right){
i32 an_pos = buffer_seek_alphanumeric_right(&file->buffer, view->cursor.pos); 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); i32 pos = buffer_seek_alphanumeric_or_camel_right(&file->buffer, view->cursor.pos, an_pos);
view_cursor_move(view, pos); view_cursor_move(view, pos);
#endif
} }
COMMAND_DECL(seek_alphanumeric_or_camel_left){ COMMAND_DECL(seek_alphanumeric_or_camel_left){
#if BUFFER_EXPERIMENT_SCALPEL <= 1
ProfileMomentFunction(); ProfileMomentFunction();
REQ_FILE_VIEW(view); REQ_FILE_VIEW(view);
REQ_FILE(file, view); REQ_FILE(file, view);
@ -371,6 +386,7 @@ COMMAND_DECL(seek_alphanumeric_or_camel_left){
i32 an_pos = buffer_seek_alphanumeric_left(&file->buffer, view->cursor.pos); 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); i32 pos = buffer_seek_alphanumeric_or_camel_left(&file->buffer, view->cursor.pos, an_pos);
view_cursor_move(view, pos); view_cursor_move(view, pos);
#endif
} }
COMMAND_DECL(search){ COMMAND_DECL(search){
@ -690,7 +706,7 @@ app_open_file(App_Vars *vars, General_Memory *general, Panel *panel,
new_view->map = app_get_map(vars, target_file->base_map_id); new_view->map = app_get_map(vars, target_file->base_map_id);
#if BUFFER_EXPERIMENT_SCALPEL #if BUFFER_EXPERIMENT_SCALPEL <= 0
if (created_file && target_file->tokens_exist) if (created_file && target_file->tokens_exist)
file_first_lex_parallel(general, target_file); file_first_lex_parallel(general, target_file);
#endif #endif
@ -766,7 +782,7 @@ COMMAND_DECL(reopen){
*file = temp_file; *file = temp_file;
file->source_path.str = file->source_path_; file->source_path.str = file->source_path_;
file->live_name.str = file->live_name_; file->live_name.str = file->live_name_;
#if BUFFER_EXPERIMENT_SCALPEL #if BUFFER_EXPERIMENT_SCALPEL <= 0
if (file->tokens_exist) if (file->tokens_exist)
file_first_lex_parallel(&mem->general, file); file_first_lex_parallel(&mem->general, file);
#endif #endif
@ -920,7 +936,7 @@ COMMAND_DECL(toggle_show_whitespace){
} }
COMMAND_DECL(toggle_tokens){ COMMAND_DECL(toggle_tokens){
#if BUFFER_EXPERIMENT_SCALPEL #if BUFFER_EXPERIMENT_SCALPEL <= 0
ProfileMomentFunction(); ProfileMomentFunction();
REQ_FILE_VIEW(view); REQ_FILE_VIEW(view);
REQ_FILE(file, view); REQ_FILE(file, view);
@ -938,6 +954,7 @@ COMMAND_DECL(toggle_tokens){
internal void internal void
case_change_range(Mem_Options *mem, File_View *view, Editing_File *file, case_change_range(Mem_Options *mem, File_View *view, Editing_File *file,
u8 a, u8 z, u8 char_delta){ u8 a, u8 z, u8 char_delta){
#if BUFFER_EXPERIMENT_SCALPEL <= 0
Range range = get_range(view->cursor.pos, view->mark); Range range = get_range(view->cursor.pos, view->mark);
if (range.start < range.end){ if (range.start < range.end){
Edit_Step step = {}; Edit_Step step = {};
@ -958,11 +975,10 @@ case_change_range(Mem_Options *mem, File_View *view, Editing_File *file,
} }
} }
#if BUFFER_EXPERIMENT_SCALPEL
if (file->token_stack.tokens) if (file->token_stack.tokens)
file_relex_parallel(mem, file, range.start, range.end, 0); file_relex_parallel(mem, file, range.start, range.end, 0);
#endif
} }
#endif
} }
COMMAND_DECL(to_uppercase){ COMMAND_DECL(to_uppercase){
@ -1452,7 +1468,7 @@ COMMAND_DECL(set_settings){
switch (p){ switch (p){
case par_lex_as_cpp_file: case par_lex_as_cpp_file:
{ {
#if BUFFER_EXPERIMENT_SCALPEL #if BUFFER_EXPERIMENT_SCALPEL <= 0
int v = dynamic_to_bool(&param->param.value); int v = dynamic_to_bool(&param->param.value);
if (file->tokens_exist){ if (file->tokens_exist){
if (!v) file_kill_tokens(&mem->general, file); if (!v) file_kill_tokens(&mem->general, file);
@ -1572,7 +1588,7 @@ extern "C"{
if (view){ if (view){
Editing_File *file = view->file; Editing_File *file = view->file;
if (file && !file->is_dummy){ if (file && !file->is_dummy){
#if BUFFER_EXPERIMENT_SCALPEL #if BUFFER_EXPERIMENT_SCALPEL <= 0
Working_Set *working_set = cmd->working_set; Working_Set *working_set = cmd->working_set;
buffer.file_id = (int)(file - working_set->files); buffer.file_id = (int)(file - working_set->files);
buffer.size = file->buffer.size; buffer.size = file->buffer.size;
@ -2943,7 +2959,7 @@ app_step(Thread_Context *thread, Key_Codes *codes,
view_set_file(file_view, file.file, style, view_set_file(file_view, file.file, style,
vars->hooks[hook_open_file], &command_data, app_links); vars->hooks[hook_open_file], &command_data, app_links);
new_view->map = app_get_map(vars, file.file->base_map_id); new_view->map = app_get_map(vars, file.file->base_map_id);
#if BUFFER_EXPERIMENT_SCALPEL #if BUFFER_EXPERIMENT_SCALPEL <= 0
if (file.file->tokens_exist) file_first_lex_parallel(general, file.file); if (file.file->tokens_exist) file_first_lex_parallel(general, file.file);
#endif #endif
}break; }break;
@ -3058,7 +3074,7 @@ app_step(Thread_Context *thread, Key_Codes *codes,
Editing_File *file = vars->working_set.files; Editing_File *file = vars->working_set.files;
for (i32 i = vars->working_set.file_index_count; i > 0; --i, ++file){ for (i32 i = vars->working_set.file_index_count; i > 0; --i, ++file){
if (file->buffer.data && !file->is_dummy){ if (buffer_good(&file->buffer) && !file->is_dummy){
file_measure_widths(&vars->mem.general, file, vars->style.font); file_measure_widths(&vars->mem.general, file, vars->style.font);
} }
} }

View File

@ -1111,13 +1111,14 @@ step_draw_adjusting(Color_View *color_view, i32_Rect rect, View_Message message,
internal void internal void
update_highlighting(Color_View *color_view){ update_highlighting(Color_View *color_view){
Style *style = color_view->main_style;
File_View *file_view = color_view->hot_file_view; File_View *file_view = color_view->hot_file_view;
if (!file_view){ if (!file_view){
color_view->highlight = {}; color_view->highlight = {};
return; return;
} }
#if BUFFER_EXPERIMENT_SCALPEL <= 0
Style *style = color_view->main_style;
Editing_File *file = file_view->file; Editing_File *file = file_view->file;
i32 pos = view_get_cursor_pos(file_view); i32 pos = view_get_cursor_pos(file_view);
char c = file->buffer.data[pos]; char c = file->buffer.data[pos];
@ -1181,6 +1182,7 @@ update_highlighting(Color_View *color_view){
color_view->highlight.ids[2] = 0; color_view->highlight.ids[2] = 0;
color_view->highlight.ids[3] = 0; color_view->highlight.ids[3] = 0;
} }
#endif
} }
internal bool32 internal bool32

View File

@ -11,13 +11,17 @@
#include "buffer/4coder_shared.cpp" #include "buffer/4coder_shared.cpp"
#if BUFFER_EXPERIMENT_SCALPEL #if BUFFER_EXPERIMENT_SCALPEL == 0
#include "buffer/4coder_golden_array.cpp" #include "buffer/4coder_golden_array.cpp"
#define Buffer_Type Buffer #define Buffer_Type Buffer
#else #elif BUFFER_EXPERIMENT_SCALPEL == 1
#include "buffer/4coder_gap_buffer.cpp" #include "buffer/4coder_gap_buffer.cpp"
#define Buffer_Type Gap_Buffer #define Buffer_Type Gap_Buffer
#else
#include "buffer/4coder_multi_gap_buffer.cpp"
#define Buffer_Type Multi_Gap_Buffer
#endif #endif
#include "buffer/4coder_buffer_abstract.cpp" #include "buffer/4coder_buffer_abstract.cpp"
struct Range{ struct Range{
@ -1118,6 +1122,7 @@ file_synchronize_times(Editing_File *file, u8 *filename){
internal bool32 internal bool32
file_save(Partition *part, Editing_File *file, u8 *filename){ file_save(Partition *part, Editing_File *file, u8 *filename){
bool32 result = 0; bool32 result = 0;
#if BUFFER_EXPERIMENT_SCALPEL <= 1
Temp_Memory temp = begin_temp_memory(part); Temp_Memory temp = begin_temp_memory(part);
i32 max = partition_remaining(part); i32 max = partition_remaining(part);
if (file->dos_write_mode){ if (file->dos_write_mode){
@ -1134,6 +1139,7 @@ file_save(Partition *part, Editing_File *file, u8 *filename){
} }
end_temp_memory(temp); end_temp_memory(temp);
file_synchronize_times(file, filename); file_synchronize_times(file, filename);
#endif
return result; return result;
} }
@ -1149,7 +1155,11 @@ file_save_and_set_names(Partition *part, Editing_File *file, u8 *filename){
inline i32 inline i32
file_count_newlines(Editing_File *file, i32 start, i32 end){ file_count_newlines(Editing_File *file, i32 start, i32 end){
#if BUFFER_EXPERIMENT_SCALPEL <= 1
i32 count = buffer_count_newlines(&file->buffer, start, end); i32 count = buffer_count_newlines(&file->buffer, start, end);
#else
i32 count = 0;
#endif
return count; return count;
} }
@ -1173,6 +1183,7 @@ enum File_Bubble_Type{
internal i32 internal i32
file_grow_starts_as_needed(General_Memory *general, Editing_File *file, i32 additional_lines){ file_grow_starts_as_needed(General_Memory *general, Editing_File *file, i32 additional_lines){
bool32 result = GROW_NOT_NEEDED; bool32 result = GROW_NOT_NEEDED;
#if BUFFER_EXPERIMENT_SCALPEL <= 1
i32 max = file->buffer.line_max; i32 max = file->buffer.line_max;
i32 count = file->buffer.line_count; i32 count = file->buffer.line_count;
i32 target_lines = count + additional_lines; i32 target_lines = count + additional_lines;
@ -1190,11 +1201,13 @@ file_grow_starts_as_needed(General_Memory *general, Editing_File *file, i32 addi
result = GROW_FAILED; result = GROW_FAILED;
} }
} }
#endif
return result; return result;
} }
internal void internal void
file_measure_starts(General_Memory *general, Editing_File *file){ file_measure_starts(General_Memory *general, Editing_File *file){
#if BUFFER_EXPERIMENT_SCALPEL <= 1
ProfileMomentFunction(); ProfileMomentFunction();
if (!file->buffer.line_starts){ if (!file->buffer.line_starts){
i32 max = file->buffer.line_max = Kbytes(1); i32 max = file->buffer.line_max = Kbytes(1);
@ -1220,18 +1233,21 @@ file_measure_starts(General_Memory *general, Editing_File *file){
file->buffer.line_max = max; file->buffer.line_max = max;
} }
file->buffer.line_count = state.count; file->buffer.line_count = state.count;
#endif
} }
internal void internal void
file_remeasure_starts(General_Memory *general, Editing_File *file, file_remeasure_starts(General_Memory *general, Editing_File *file,
i32 line_start, i32 line_end, i32 line_shift, i32 line_start, i32 line_end, i32 line_shift,
i32 character_shift){ i32 character_shift){
#if BUFFER_EXPERIMENT_SCALPEL <= 1
ProfileMomentFunction(); ProfileMomentFunction();
Assert(file->buffer.line_starts); Assert(file->buffer.line_starts);
file_grow_starts_as_needed(general, file, line_shift); file_grow_starts_as_needed(general, file, line_shift);
buffer_remeasure_starts(&file->buffer, line_start, line_end, line_shift, character_shift); buffer_remeasure_starts(&file->buffer, line_start, line_end, line_shift, character_shift);
#endif
} }
struct Opaque_Font_Advance{ struct Opaque_Font_Advance{
@ -1249,6 +1265,7 @@ get_opaque_font_advance(Font *font){
internal void internal void
file_grow_widths_as_needed(General_Memory *general, Editing_File *file){ file_grow_widths_as_needed(General_Memory *general, Editing_File *file){
#if BUFFER_EXPERIMENT_SCALPEL <= 1
i32 line_count = file->buffer.line_count; i32 line_count = file->buffer.line_count;
if (line_count > file->buffer.widths_max){ if (line_count > file->buffer.widths_max){
i32 new_max = LargeRoundUp(line_count, Kbytes(1)); i32 new_max = LargeRoundUp(line_count, Kbytes(1));
@ -1262,26 +1279,31 @@ file_grow_widths_as_needed(General_Memory *general, Editing_File *file){
} }
file->buffer.widths_max = new_max; file->buffer.widths_max = new_max;
} }
#endif
} }
internal void internal void
file_measure_widths(General_Memory *general, Editing_File *file, Font *font){ file_measure_widths(General_Memory *general, Editing_File *file, Font *font){
#if BUFFER_EXPERIMENT_SCALPEL <= 1
ProfileMomentFunction(); ProfileMomentFunction();
file_grow_widths_as_needed(general, file); file_grow_widths_as_needed(general, file);
Opaque_Font_Advance opad = get_opaque_font_advance(font); Opaque_Font_Advance opad = get_opaque_font_advance(font);
buffer_measure_widths(&file->buffer, opad.data, opad.stride); buffer_measure_widths(&file->buffer, opad.data, opad.stride);
#endif
} }
internal void internal void
file_remeasure_widths(General_Memory *general, Editing_File *file, Font *font, file_remeasure_widths(General_Memory *general, Editing_File *file, Font *font,
i32 line_start, i32 line_end, i32 line_shift){ i32 line_start, i32 line_end, i32 line_shift){
#if BUFFER_EXPERIMENT_SCALPEL <= 1
ProfileMomentFunction(); ProfileMomentFunction();
file_grow_widths_as_needed(general, file); file_grow_widths_as_needed(general, file);
Opaque_Font_Advance opad = get_opaque_font_advance(font); Opaque_Font_Advance opad = get_opaque_font_advance(font);
buffer_remeasure_widths(&file->buffer, opad.data, opad.stride, buffer_remeasure_widths(&file->buffer, opad.data, opad.stride,
line_start, line_end, line_shift); line_start, line_end, line_shift);
#endif
} }
inline i32 inline i32
@ -1293,8 +1315,9 @@ view_wrapped_line_span(real32 line_width, real32 max_width){
internal i32 internal i32
view_compute_lowest_line(File_View *view){ view_compute_lowest_line(File_View *view){
i32 last_line = view->line_count - 1;
i32 lowest_line = 0; i32 lowest_line = 0;
#if BUFFER_EXPERIMENT_SCALPEL <= 1
i32 last_line = view->line_count - 1;
if (last_line > 0){ if (last_line > 0){
if (view->unwrapped_lines){ if (view->unwrapped_lines){
lowest_line = last_line; lowest_line = last_line;
@ -1313,11 +1336,13 @@ view_compute_lowest_line(File_View *view){
lowest_line += line_span - 1; lowest_line += line_span - 1;
} }
} }
#endif
return lowest_line; return lowest_line;
} }
internal void internal void
view_measure_wraps(General_Memory *general, File_View *view){ view_measure_wraps(General_Memory *general, File_View *view){
#if BUFFER_EXPERIMENT_SCALPEL <= 1
ProfileMomentFunction(); ProfileMomentFunction();
Editing_File *file = view->file; Editing_File *file = view->file;
i32 line_count = file->buffer.line_count; i32 line_count = file->buffer.line_count;
@ -1340,23 +1365,35 @@ view_measure_wraps(General_Memory *general, File_View *view){
buffer_measure_wrap_y(&file->buffer, view->line_wrap_y, line_height, max_width); buffer_measure_wrap_y(&file->buffer, view->line_wrap_y, line_height, max_width);
view->line_count = line_count; view->line_count = line_count;
#endif
}
internal void*
alloc_for_buffer(void *context, int *size){
*size = LargeRoundUp(*size, Kbytes(4));
void *data = general_memory_allocate((General_Memory*)context, *size, BUBBLE_BUFFER);
return data;
} }
internal void internal void
file_create_from_string(General_Memory *general, Editing_File *file, u8 *filename, Font *font, String val){ file_create_from_string(General_Memory *general, Editing_File *file, u8 *filename, Font *font, String val){
i32 request_size = LargeRoundUp(1+val.size*2, Kbytes(64));
u8 *data = (u8*)general_memory_allocate(general, request_size, BUBBLE_BUFFER);
// TODO(allen): if we didn't get the memory what is going on?
// request_size too large?
// need to expand general memory allocator's base pool?
// need to release least recently used target?
Assert(data);
*file = {}; *file = {};
file->buffer.data = (char*)data; #if BUFFER_EXPERIMENT_SCALPEL <= 2
file->buffer.max = request_size;
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));
void *data = general_memory_allocate(general, page_size, BUBBLE_BUFFER);
buffer_init_provide_page(&init, data, page_size);
}
i32 init_success = buffer_end_init(&init);
Assert(init_success);
#if 0
buffer_initialize(&file->buffer, val.str, val.size); buffer_initialize(&file->buffer, val.str, val.size);
#endif
#endif
file_synchronize_times(file, filename); file_synchronize_times(file, filename);
file_init_strings(file); file_init_strings(file);
@ -1368,6 +1405,7 @@ file_create_from_string(General_Memory *general, Editing_File *file, u8 *filenam
file_measure_widths(general, file, font); file_measure_widths(general, file, font);
file->font = font; file->font = font;
i32 request_size = Kbytes(64);
file->undo.undo.max = request_size; file->undo.undo.max = request_size;
file->undo.undo.strings = (u8*)general_memory_allocate(general, request_size, BUBBLE_UNDO_STRING); file->undo.undo.strings = (u8*)general_memory_allocate(general, request_size, BUBBLE_UNDO_STRING);
file->undo.undo.edit_max = request_size / sizeof(Edit_Step); file->undo.undo.edit_max = request_size / sizeof(Edit_Step);
@ -1451,9 +1489,11 @@ file_close(General_Memory *general, Editing_File *file){
if (file->token_stack.tokens){ if (file->token_stack.tokens){
general_memory_free(general, file->token_stack.tokens); general_memory_free(general, file->token_stack.tokens);
} }
#if BUFFER_EXPERIMENT_SCALPEL <= 1
general_memory_free(general, file->buffer.data); general_memory_free(general, file->buffer.data);
general_memory_free(general, file->buffer.line_starts); general_memory_free(general, file->buffer.line_starts);
general_memory_free(general, file->buffer.line_widths); general_memory_free(general, file->buffer.line_widths);
#endif
general_memory_free(general, file->undo.undo.strings); general_memory_free(general, file->undo.undo.strings);
general_memory_free(general, file->undo.undo.edits); general_memory_free(general, file->undo.undo.edits);
@ -1475,7 +1515,7 @@ struct Shift_Information{
i32 start, end, amount; i32 start, end, amount;
}; };
#if BUFFER_EXPERIMENT_SCALPEL #if BUFFER_EXPERIMENT_SCALPEL <= 0
internal internal
JOB_CALLBACK(job_full_lex){ JOB_CALLBACK(job_full_lex){
Editing_File *file = (Editing_File*)data[0]; Editing_File *file = (Editing_File*)data[0];
@ -1553,7 +1593,7 @@ file_kill_tokens(General_Memory *general, Editing_File *file){
file->token_stack = {}; file->token_stack = {};
} }
#if BUFFER_EXPERIMENT_SCALPEL #if BUFFER_EXPERIMENT_SCALPEL <= 0
internal void internal void
file_first_lex_parallel(General_Memory *general, Editing_File *file){ file_first_lex_parallel(General_Memory *general, Editing_File *file){
Assert(file->token_stack.tokens == 0); Assert(file->token_stack.tokens == 0);
@ -1659,6 +1699,7 @@ file_relex_parallel(Mem_Options *mem, Editing_File *file,
internal bool32 internal bool32
file_grow_as_needed(General_Memory *general, Editing_File *file, i32 additional_size){ file_grow_as_needed(General_Memory *general, Editing_File *file, i32 additional_size){
bool32 result = 1; bool32 result = 1;
#if BUFFER_EXPERIMENT_SCALPEL <= 1
i32 size = buffer_size(&file->buffer); i32 size = buffer_size(&file->buffer);
i32 target_size = size + additional_size + 1; i32 target_size = size + additional_size + 1;
if (target_size >= file->buffer.max){ if (target_size >= file->buffer.max){
@ -1669,6 +1710,7 @@ file_grow_as_needed(General_Memory *general, Editing_File *file, i32 additional_
void *old_data = buffer_relocate(&file->buffer, new_data, request_size); void *old_data = buffer_relocate(&file->buffer, new_data, request_size);
general_memory_free(general, old_data); general_memory_free(general, old_data);
} }
#endif
return result; return result;
} }
@ -1746,6 +1788,7 @@ struct Edit_Spec{
Edit_Step step; Edit_Step step;
}; };
#if BUFFER_EXPERIMENT_SCALPEL <= 1
internal Edit_Step* internal Edit_Step*
file_post_undo(General_Memory *general, Editing_File *file, file_post_undo(General_Memory *general, Editing_File *file,
Edit_Step step, bool32 do_merge, bool32 can_merge){ Edit_Step step, bool32 do_merge, bool32 can_merge){
@ -1809,9 +1852,9 @@ file_post_undo(General_Memory *general, Editing_File *file,
result = undo->edits + (undo->edit_count++); result = undo->edits + (undo->edit_count++);
*result = inv_step; *result = inv_step;
} }
return result; return result;
} }
#endif
inline void inline void
undo_stack_pop(Edit_Stack *stack){ undo_stack_pop(Edit_Stack *stack){
@ -1821,6 +1864,7 @@ undo_stack_pop(Edit_Stack *stack){
} }
} }
#if BUFFER_EXPERIMENT_SCALPEL <= 1
internal void internal void
file_post_redo(General_Memory *general, Editing_File *file, Edit_Step step){ file_post_redo(General_Memory *general, Editing_File *file, Edit_Step step){
Edit_Stack *redo = &file->undo.redo; Edit_Stack *redo = &file->undo.redo;
@ -1857,6 +1901,7 @@ file_post_redo(General_Memory *general, Editing_File *file, Edit_Step step){
redo->edits[redo->edit_count++] = inv_step; redo->edits[redo->edit_count++] = inv_step;
} }
} }
#endif
inline void inline void
file_post_history_block(Editing_File *file, i32 pos){ file_post_history_block(Editing_File *file, i32 pos){
@ -1880,6 +1925,7 @@ file_unpost_history_block(Editing_File *file){
file->undo.history_head_block = old_head->prev_block; file->undo.history_head_block = old_head->prev_block;
} }
#if BUFFER_EXPERIMENT_SCALPEL <= 1
internal Edit_Step* internal Edit_Step*
file_post_history(General_Memory *general, Editing_File *file, file_post_history(General_Memory *general, Editing_File *file,
Edit_Step step, bool32 do_merge, bool32 can_merge){ Edit_Step step, bool32 do_merge, bool32 can_merge){
@ -1949,9 +1995,11 @@ file_post_history(General_Memory *general, Editing_File *file,
return result; return result;
} }
#endif
inline Full_Cursor inline Full_Cursor
view_compute_cursor_from_pos(File_View *view, i32 pos){ view_compute_cursor_from_pos(File_View *view, i32 pos){
#if BUFFER_EXPERIMENT_SCALPEL <= 1
Editing_File *file = view->file; Editing_File *file = view->file;
Style *style = view->style; Style *style = view->style;
Font *font = style->font; Font *font = style->font;
@ -1961,11 +2009,15 @@ view_compute_cursor_from_pos(File_View *view, i32 pos){
return buffer_cursor_from_pos(&file->buffer, pos, view->line_wrap_y, return buffer_cursor_from_pos(&file->buffer, pos, view->line_wrap_y,
max_width, (real32)font->height, opad.data, opad.stride); max_width, (real32)font->height, opad.data, opad.stride);
#else
return view->cursor;
#endif
} }
inline Full_Cursor inline Full_Cursor
view_compute_cursor_from_unwrapped_xy(File_View *view, real32 seek_x, real32 seek_y, view_compute_cursor_from_unwrapped_xy(File_View *view, real32 seek_x, real32 seek_y,
bool32 round_down = 0){ bool32 round_down = 0){
#if BUFFER_EXPERIMENT_SCALPEL <= 1
Editing_File *file = view->file; Editing_File *file = view->file;
Style *style = view->style; Style *style = view->style;
Font *font = style->font; Font *font = style->font;
@ -1975,11 +2027,15 @@ view_compute_cursor_from_unwrapped_xy(File_View *view, real32 seek_x, real32 see
return buffer_cursor_from_unwrapped_xy(&file->buffer, seek_x, seek_y, round_down, view->line_wrap_y, return buffer_cursor_from_unwrapped_xy(&file->buffer, seek_x, seek_y, round_down, view->line_wrap_y,
max_width, (real32)font->height, opad.data, opad.stride); max_width, (real32)font->height, opad.data, opad.stride);
#else
return view->cursor;
#endif
} }
inline Full_Cursor inline Full_Cursor
view_compute_cursor_from_wrapped_xy(File_View *view, real32 seek_x, real32 seek_y, view_compute_cursor_from_wrapped_xy(File_View *view, real32 seek_x, real32 seek_y,
bool32 round_down = 0){ bool32 round_down = 0){
#if BUFFER_EXPERIMENT_SCALPEL <= 1
Editing_File *file = view->file; Editing_File *file = view->file;
Style *style = view->style; Style *style = view->style;
Font *font = style->font; Font *font = style->font;
@ -1989,6 +2045,9 @@ view_compute_cursor_from_wrapped_xy(File_View *view, real32 seek_x, real32 seek_
return buffer_cursor_from_wrapped_xy(&file->buffer, seek_x, seek_y, round_down, view->line_wrap_y, return buffer_cursor_from_wrapped_xy(&file->buffer, seek_x, seek_y, round_down, view->line_wrap_y,
max_width, (real32)font->height, opad.data, opad.stride); max_width, (real32)font->height, opad.data, opad.stride);
#else
return view->cursor;
#endif
} }
inline Full_Cursor inline Full_Cursor
@ -2212,6 +2271,7 @@ enum History_Mode{
internal void internal void
view_update_history_before_edit(Mem_Options *mem, Editing_File *file, Edit_Step step, u8 *str, view_update_history_before_edit(Mem_Options *mem, Editing_File *file, Edit_Step step, u8 *str,
History_Mode history_mode){ History_Mode history_mode){
#if BUFFER_EXPERIMENT_SCALPEL <= 1
General_Memory *general = &mem->general; General_Memory *general = &mem->general;
#if FRED_SLOW #if FRED_SLOW
@ -2376,6 +2436,7 @@ view_update_history_before_edit(Mem_Options *mem, Editing_File *file, Edit_Step
} }
if (history_mode == hist_normal) file->undo.edit_history_cursor = file->undo.history.edit_count; if (history_mode == hist_normal) file->undo.edit_history_cursor = file->undo.history.edit_count;
#endif
} }
inline b32 inline b32
@ -2410,19 +2471,20 @@ view_do_single_edit(Mem_Options *mem, File_View *view, Editing_File *file,
view_update_history_before_edit(mem, file, spec.step, spec.str, history_mode); view_update_history_before_edit(mem, file, spec.step, spec.str, history_mode);
file_pre_edit_maintenance(file); file_pre_edit_maintenance(file);
#if BUFFER_EXPERIMENT_SCALPEL <= 1
// NOTE(allen): actual text replacement // NOTE(allen): actual text replacement
General_Memory *general = &mem->general; General_Memory *general = &mem->general;
i32 start = spec.step.edit.start; i32 start = spec.step.edit.start;
i32 end = spec.step.edit.end; i32 end = spec.step.edit.end;
char *str = (char*)spec.str; AllowLocal(str); char *str = (char*)spec.str;
i32 str_len = spec.step.edit.len; i32 str_len = spec.step.edit.len;
i32 shift_amount = 0; i32 shift_amount = 0;
while (buffer_replace_range(&file->buffer, start, end, str, str_len, &shift_amount)) while (buffer_replace_range(&file->buffer, start, end, str, str_len, &shift_amount))
file_grow_as_needed(general, file, shift_amount); file_grow_as_needed(general, file, shift_amount);
#if BUFFER_EXPERIMENT_SCALPEL #if BUFFER_EXPERIMENT_SCALPEL <= 0
// NOTE(allen): fixing stuff afterwards // NOTE(allen): fixing stuff afterwards
if (file->tokens_exist) if (file->tokens_exist)
file_relex_parallel(mem, file, start, end, shift_amount); file_relex_parallel(mem, file, start, end, shift_amount);
@ -2484,11 +2546,13 @@ view_do_single_edit(Mem_Options *mem, File_View *view, Editing_File *file,
} }
end_temp_memory(cursor_temp); end_temp_memory(cursor_temp);
#endif
} }
internal void internal void
view_do_white_batch_edit(Mem_Options *mem, File_View *view, Editing_File *file, view_do_white_batch_edit(Mem_Options *mem, File_View *view, Editing_File *file,
Editing_Layout *layout, Edit_Spec spec, History_Mode history_mode){ Editing_Layout *layout, Edit_Spec spec, History_Mode history_mode){
#if BUFFER_EXPERIMENT_SCALPEL <= 1
Assert(file); Assert(file);
ProfileMomentFunction(); ProfileMomentFunction();
@ -2580,6 +2644,7 @@ view_do_white_batch_edit(Mem_Options *mem, File_View *view, Editing_File *file,
} }
end_temp_memory(cursor_temp); end_temp_memory(cursor_temp);
} }
#endif
} }
inline void inline void
@ -2704,7 +2769,7 @@ view_history_step(Mem_Options *mem, Editing_Layout *layout, File_View *view, His
// TODO(allen): should these still be view operations? // TODO(allen): should these still be view operations?
internal i32 internal i32
view_find_end_of_line(File_View *view, i32 pos){ view_find_end_of_line(File_View *view, i32 pos){
#if BUFFER_EXPERIMENT_SCALPEL #if BUFFER_EXPERIMENT_SCALPEL <= 0
Editing_File *file = view->file; Editing_File *file = view->file;
char *data = file->buffer.data; char *data = file->buffer.data;
while (pos < file->buffer.size && data[pos] != '\n') ++pos; while (pos < file->buffer.size && data[pos] != '\n') ++pos;
@ -2715,7 +2780,7 @@ view_find_end_of_line(File_View *view, i32 pos){
internal i32 internal i32
view_find_beginning_of_line(File_View *view, i32 pos){ view_find_beginning_of_line(File_View *view, i32 pos){
#if BUFFER_EXPERIMENT_SCALPEL #if BUFFER_EXPERIMENT_SCALPEL <= 0
Editing_File *file = view->file; Editing_File *file = view->file;
char *data = file->buffer.data; char *data = file->buffer.data;
if (pos > 0){ if (pos > 0){
@ -2729,7 +2794,7 @@ view_find_beginning_of_line(File_View *view, i32 pos){
internal i32 internal i32
view_find_beginning_of_next_line(File_View *view, i32 pos){ view_find_beginning_of_next_line(File_View *view, i32 pos){
#if BUFFER_EXPERIMENT_SCALPEL #if BUFFER_EXPERIMENT_SCALPEL <= 0
Editing_File *file = view->file; Editing_File *file = view->file;
char *data = file->buffer.data; char *data = file->buffer.data;
while (pos < file->buffer.size && while (pos < file->buffer.size &&
@ -2833,11 +2898,13 @@ working_set_lookup_file(Working_Set *working_set, String string){
internal void internal void
clipboard_copy(General_Memory *general, Working_Set *working, Range range, Editing_File *file){ clipboard_copy(General_Memory *general, Working_Set *working, Range range, Editing_File *file){
#if BUFFER_EXPERIMENT_SCALPEL <= 1
i32 size = range.end - range.start; i32 size = range.end - range.start;
String *dest = working_set_next_clipboard_string(general, working, size); String *dest = working_set_next_clipboard_string(general, working, size);
buffer_stringify(&file->buffer, range.start, range.end, dest->str); buffer_stringify(&file->buffer, range.start, range.end, dest->str);
dest->size = size; dest->size = size;
system_post_clipboard(*dest); system_post_clipboard(*dest);
#endif
} }
internal Edit_Spec internal Edit_Spec
@ -2845,6 +2912,7 @@ view_compute_whitespace_edit(Mem_Options *mem, Editing_File *file,
Buffer_Edit *edits, char *str_base, i32 str_size, Buffer_Edit *edits, char *str_base, i32 str_size,
Buffer_Edit *inverse_array, char *inv_str, i32 inv_max, Buffer_Edit *inverse_array, char *inv_str, i32 inv_max,
i32 edit_count){ i32 edit_count){
#if BUFFER_EXPERIMENT_SCALPEL <= 1
General_Memory *general = &mem->general; General_Memory *general = &mem->general;
i32 inv_str_pos = 0; i32 inv_str_pos = 0;
@ -2867,12 +2935,16 @@ view_compute_whitespace_edit(Mem_Options *mem, Editing_File *file,
spec.step.special_type = 1; spec.step.special_type = 1;
spec.step.child_count = edit_count; spec.step.child_count = edit_count;
spec.step.inverse_child_count = edit_count; spec.step.inverse_child_count = edit_count;
#else
Edit_Spec spec = {};
#endif
return spec; return spec;
} }
internal void internal void
view_clean_whitespace(Mem_Options *mem, File_View *view, Editing_Layout *layout){ view_clean_whitespace(Mem_Options *mem, File_View *view, Editing_Layout *layout){
#if BUFFER_EXPERIMENT_SCALPEL <= 1
Editing_File *file = view->file; Editing_File *file = view->file;
Assert(file && !file->is_dummy); Assert(file && !file->is_dummy);
Partition *part = &mem->part; Partition *part = &mem->part;
@ -2926,12 +2998,13 @@ view_clean_whitespace(Mem_Options *mem, File_View *view, Editing_Layout *layout)
} }
end_temp_memory(temp); end_temp_memory(temp);
#endif
} }
internal void internal void
view_auto_tab_tokens(Mem_Options *mem, File_View *view, Editing_Layout *layout, view_auto_tab_tokens(Mem_Options *mem, File_View *view, Editing_Layout *layout,
i32 start, i32 end, b32 empty_blank_lines){ i32 start, i32 end, b32 empty_blank_lines){
#if BUFFER_EXPERIMENT_SCALPEL #if BUFFER_EXPERIMENT_SCALPEL <= 0
Editing_File *file = view->file; Editing_File *file = view->file;
Assert(file && !file->is_dummy); Assert(file && !file->is_dummy);
Partition *part = &mem->part; Partition *part = &mem->part;
@ -3655,10 +3728,11 @@ draw_file_view(Thread_Context *thread, View *view_, i32_Rect rect, bool32 is_act
bar.rect.y1 = bar.rect.y0 + font->height + 2; bar.rect.y1 = bar.rect.y0 + font->height + 2;
rect.y0 += font->height + 2; rect.y0 += font->height + 2;
#if BUFFER_EXPERIMENT_SCALPEL <= 1
i32 max_x = rect.x1 - rect.x0; i32 max_x = rect.x1 - rect.x0;
i32 max_y = rect.y1 - rect.y0 + font->height; i32 max_y = rect.y1 - rect.y0 + font->height;
Assert(file && file->buffer.data && !file->is_dummy); Assert(file && buffer_good(&file->buffer) && !file->is_dummy);
Opaque_Font_Advance opad = get_opaque_font_advance(font); Opaque_Font_Advance opad = get_opaque_font_advance(font);
b32 tokens_use = file->tokens_complete && (file->token_stack.count > 0); b32 tokens_use = file->tokens_complete && (file->token_stack.count > 0);
@ -3756,184 +3830,6 @@ draw_file_view(Thread_Context *thread, View *view_, i32_Rect rect, bool32 is_act
} }
end_temp_memory(temp); end_temp_memory(temp);
#if 0
i32 size = (i32)file->buffer.size;
u8 *data = (u8*)file->buffer.data;
Full_Cursor start_cursor;
start_cursor = view_compute_cursor_from_xy(view, 0, view->scroll_y);
view->scroll_y_cursor = start_cursor;
i32 start_character = start_cursor.pos;
real32 shift_x = rect.x0 - view->scroll_x;
real32 shift_y = rect.y0 - view->scroll_y;
if (view->unwrapped_lines) shift_y += start_cursor.unwrapped_y;
else shift_y += start_cursor.wrapped_y;
real32 pos_x = 0;
real32 pos_y = 0;
u32 highlight_color = 0;
u32 main_color = style->main.default_color;
i32 token_i = 0;
if (tokens_use){
Cpp_Get_Token_Result result = cpp_get_token(&token_stack, start_character);
token_i = result.token_index;
main_color = *style_get_color(style, token_stack.tokens[token_i]);
++token_i;
}
data[size] = 0;
for (i32 i = start_character; i <= size; ++i){
u8 to_render;
to_render = data[i];
real32 ch_width = font_get_glyph_width(font, to_render);
real32 ch_advance = measure_character(opad.data, opad.stride, to_render);
if (!view->unwrapped_lines && pos_x + ch_advance > max_x){
pos_x = 0;
pos_y += font->height;
}
u32 fade_color = 0xFFFF00FF;
real32 fade_amount = 0.f;
if (view->paste_effect.tick_down > 0 &&
view->paste_effect.start <= i && i < view->paste_effect.end){
fade_color = view->paste_effect.color;
fade_amount = (real32)(view->paste_effect.tick_down) / view->paste_effect.tick_max;
}
highlight_color = 0;
if (tokens_use){
Cpp_Token current_token = token_stack.tokens[token_i-1];
if (token_i < token_stack.count){
if (i >= token_stack.tokens[token_i].start){
main_color =
*style_get_color(style, token_stack.tokens[token_i]);
current_token = token_stack.tokens[token_i];
++token_i;
}
else if (i >= current_token.start + current_token.size){
main_color = 0xFFFFFFFF;
}
}
if (current_token.type == CPP_TOKEN_JUNK &&
i >= current_token.start && i <= current_token.start + current_token.size){
highlight_color = style->main.highlight_junk_color;
}
}
if (highlight_color == 0 && view->show_whitespace && char_is_whitespace(data[i])){
highlight_color = style->main.highlight_white_color;
}
i32 cursor_mode = 0;
if (view->show_temp_highlight){
if (view->temp_highlight.pos <= i && i < view->temp_highlight_end_pos)
cursor_mode = 2;
}
else{
if (view->cursor.pos == i)
cursor_mode = 1;
}
real32_Rect cursor_rect =
real32XYWH(shift_x + pos_x, shift_y + pos_y,
1 + ch_width, (real32)font->height);
if (to_render == '\t' || to_render == 0){
cursor_rect.x1 = cursor_rect.x0 + font->chardata[' '].xadvance;
}
if (highlight_color != 0){
real32_Rect highlight_rect = cursor_rect;
highlight_rect.x0 += 1;
draw_rectangle(target, highlight_rect, highlight_color);
}
u32 cursor_color = 0;
switch (cursor_mode){
case 1:
cursor_color = style->main.cursor_color; break;
case 2:
cursor_color = style->main.highlight_color; break;
}
if (is_active){
if (cursor_color & 0xFF000000) draw_rectangle(target, cursor_rect, cursor_color);
}
else{
if (cursor_color & 0xFF000000)draw_rectangle_outline(target, cursor_rect, cursor_color);
}
if (i == view->mark){
draw_rectangle_outline(target, cursor_rect, style->main.mark_color);
}
u32 char_color = main_color;
u32 special_char_color = main_color;
if (to_render == '\r'){
special_char_color = char_color = style->main.special_character_color;
}
if (is_active){
switch (cursor_mode){
case 1:
char_color = style->main.at_cursor_color; break;
case 2:
special_char_color = char_color = style->main.at_highlight_color; break;
}
}
char_color = color_blend(char_color, fade_amount, fade_color);
special_char_color = color_blend(special_char_color, fade_amount, fade_color);
if (to_render == '\r'){
font_draw_glyph(target, font, '\\',
shift_x + pos_x,
shift_y + pos_y,
char_color);
pos_x += font_get_glyph_width(font, '\\');
real32 cw = font_get_glyph_width(font, 'r');
draw_rectangle(target,
real32XYWH(shift_x + pos_x,
shift_y + pos_y,
cw, (real32)font->height),
highlight_color);
font_draw_glyph(target, font, 'r',
shift_x + pos_x,
shift_y + pos_y,
special_char_color);
pos_x += cw;
}
else if (to_render == '\n'){
pos_x = 0;
pos_y += font->height;
}
else if (font->glyphs[to_render].exists){
font_draw_glyph(target, font, to_render,
shift_x + pos_x,
shift_y + pos_y,
char_color);
pos_x += ch_width;
}
else{
pos_x += ch_width;
}
if (pos_y > max_y){
break;
}
}
#endif #endif
if (view->widget.type != FWIDG_NONE){ if (view->widget.type != FWIDG_NONE){
@ -4089,7 +3985,7 @@ HANDLE_COMMAND_SIG(handle_command_file_view){
case FWIDG_SEARCH: case FWIDG_SEARCH:
{ {
#if BUFFER_EXPERIMENT_SCALPEL #if BUFFER_EXPERIMENT_SCALPEL <= 1
String *string = &file_view->isearch.str; String *string = &file_view->isearch.str;
Single_Line_Input_Step result = Single_Line_Input_Step result =
app_single_line_input_step(codes, key, string); app_single_line_input_step(codes, key, string);
@ -4100,72 +3996,61 @@ HANDLE_COMMAND_SIG(handle_command_file_view){
bool32 step_forward = 0; bool32 step_forward = 0;
bool32 step_backward = 0; bool32 step_backward = 0;
if (binding.function == command_search){ if (binding.function == command_search) step_forward = 1;
step_forward = 1; if (binding.function == command_rsearch) step_backward = 1;
}
if (binding.function == command_rsearch){
step_backward = 1;
}
i32 start_pos = file_view->isearch.pos; i32 start_pos = file_view->isearch.pos;
if (step_forward){ if (step_forward){
if (file_view->isearch.reverse){ if (file_view->isearch.reverse){
start_pos = file_view->temp_highlight.pos - 1; start_pos = file_view->temp_highlight.pos + 1;
file_view->isearch.pos = start_pos; file_view->isearch.pos = start_pos;
file_view->isearch.reverse = 0; file_view->isearch.reverse = 0;
step_forward = 0;
} }
} }
if (step_backward){ if (step_backward){
if (!file_view->isearch.reverse){ if (!file_view->isearch.reverse){
start_pos = file_view->temp_highlight.pos + 1; start_pos = file_view->temp_highlight.pos - 1;
file_view->isearch.pos = start_pos; file_view->isearch.pos = start_pos;
file_view->isearch.reverse = 1; file_view->isearch.reverse = 1;
step_backward = 0;
} }
} }
String file_string = make_string(file->buffer.data, file->buffer.size); Temp_Memory temp = begin_temp_memory(&view->mem->part);
char *spare = push_array(&view->mem->part, char, string->size);
i32 size = buffer_size(&file->buffer);
i32 pos; i32 pos;
if (!result.hit_backspace){
if (file_view->isearch.reverse){ if (file_view->isearch.reverse){
if (result.hit_backspace){ pos = buffer_rfind_string(&file->buffer, start_pos - 1, string->str, string->size, spare);
start_pos = file_view->temp_highlight.pos + 1;
file_view->isearch.pos = start_pos;
}
else{
pos = rfind_substr(file_string, start_pos - 1, *string);
if (pos >= 0){ if (pos >= 0){
if (step_backward){ // TODO(allen): this if and it's mirror are suspicious if (step_backward){
file_view->isearch.pos = pos; file_view->isearch.pos = pos;
start_pos = pos; start_pos = pos;
pos = rfind_substr(file_string, start_pos - 1, *string); pos = buffer_rfind_string(&file->buffer, start_pos - 1, string->str, string->size, spare);
if (pos == -1){ if (pos == -1) pos = start_pos;
pos = start_pos;
}
} }
view_set_temp_highlight(file_view, pos, pos+string->size); view_set_temp_highlight(file_view, pos, pos+string->size);
} }
} }
}
else{ else{
if (result.hit_backspace){ pos = buffer_find_string(&file->buffer, start_pos + 1, string->str, string->size, spare);
start_pos = file_view->temp_highlight.pos - 1; if (pos < size){
file_view->isearch.pos = start_pos;
}
else{
pos = find_substr(file_string, start_pos + 1, *string);
if (pos < file->buffer.size){
if (step_forward){ if (step_forward){
file_view->isearch.pos = pos; file_view->isearch.pos = pos;
start_pos = pos; start_pos = pos;
pos = find_substr(file_string, start_pos + 1, *string); pos = buffer_find_string(&file->buffer, start_pos + 1, string->str, string->size, spare);
if (pos == file->buffer.size){ if (pos == size) pos = start_pos;
pos = start_pos;
}
} }
view_set_temp_highlight(file_view, pos, pos+string->size); view_set_temp_highlight(file_view, pos, pos+string->size);
} }
} }
} }
end_temp_memory(temp);
} }
if (result.hit_newline || result.hit_ctrl_newline){ if (result.hit_newline || result.hit_ctrl_newline){

View File

@ -77,7 +77,7 @@ _OutDbgStr(u8*);
#endif #endif
#if FRED_SLOW #if FRED_SLOW
# define Assert(c) if(!(c)){*(int*)0 = 0;} # define Assert(c) assert(c)
#else #else
# define Assert(c) # define Assert(c)
#endif #endif

View File

@ -13,9 +13,11 @@
// TOP // TOP
#define Buffer_Init_Type cat_4tech(Buffer_Type, _Init)
#define Buffer_Stringify_Type cat_4tech(Buffer_Type, _Stringify_Loop) #define Buffer_Stringify_Type cat_4tech(Buffer_Type, _Stringify_Loop)
#define Buffer_Backify_Type cat_4tech(Buffer_Type, _Backify_Loop) #define Buffer_Backify_Type cat_4tech(Buffer_Type, _Backify_Loop)
#if BUFFER_EXPERIMENT_SCALPEL <= 1
inline_4tech void inline_4tech void
buffer_stringify(Buffer_Type *buffer, int start, int end, char *out){ buffer_stringify(Buffer_Type *buffer, int start, int end, char *out){
for (Buffer_Stringify_Type loop = buffer_stringify_loop(buffer, start, end, end - start); for (Buffer_Stringify_Type loop = buffer_stringify_loop(buffer, start, end, end - start);
@ -364,8 +366,8 @@ buffer_seek_alphanumeric_or_camel_left_end:
} }
internal_4tech int internal_4tech int
buffer_find_hard_start(Buffer_Type *buffer, int line_start, int *all_whitespace, int *all_space, buffer_find_hard_start(Buffer_Type *buffer, int line_start, int *all_whitespace,
int *preferred_indent, int tab_width){ int *all_space, int *preferred_indent, int tab_width){
Buffer_Stringify_Type loop; Buffer_Stringify_Type loop;
char *data; char *data;
int size, end; int size, end;
@ -403,6 +405,69 @@ buffer_find_hard_start_end:
return(result); return(result);
} }
internal_4tech int
buffer_find_string(Buffer_Type *buffer, int start_pos, char *str, int len, char *spare){
Buffer_Stringify_Type loop;
char *data;
int size, end;
int pos;
size = buffer_size(buffer);
pos = start_pos;
if (len > 0){
for (loop = buffer_stringify_loop(buffer, start_pos, size - len + 1, size);
buffer_stringify_good(&loop);
buffer_stringify_next(&loop)){
end = loop.size + loop.absolute_pos;
data = loop.data - loop.absolute_pos;
for (; pos < end; ++pos){
if (*str == data[pos]){
buffer_stringify(buffer, pos, pos + len, spare);
if (is_match(str, spare, len))
goto buffer_find_string_end;
}
}
}
}
buffer_find_string_end:
if (pos >= size - len + 1) pos = size;
return(pos);
}
internal_4tech int
buffer_rfind_string(Buffer_Type *buffer, int start_pos, char *str, int len, char *spare){
Buffer_Backify_Type loop;
char *data;
int end, size;
int pos;
size = buffer_size(buffer);
pos = start_pos;
if (pos > size - len) pos = size - len;
if (len > 0){
for (loop = buffer_backify_loop(buffer, start_pos, 0, size);
buffer_backify_good(&loop);
buffer_backify_next(&loop)){
end = loop.absolute_pos;
data = loop.data - loop.absolute_pos;
for (; pos >= end; --pos){
if (*str == data[pos]){
buffer_stringify(buffer, pos, pos + len, spare);
if (is_match(str, spare, len))
goto buffer_rfind_string_end;
}
}
}
}
buffer_rfind_string_end:
return(pos);
}
typedef struct{ typedef struct{
int i; int i;
int count; int count;
@ -1058,6 +1123,7 @@ buffer_get_render_data_end:
assert_4tech(item_i <= max); assert_4tech(item_i <= max);
*count = item_i; *count = item_i;
} }
#endif
#ifndef NON_ABSTRACT_4TECH #ifndef NON_ABSTRACT_4TECH
#define NON_ABSTRACT_4TECH 1 #define NON_ABSTRACT_4TECH 1

View File

@ -24,6 +24,13 @@ typedef struct{
int widths_max; int widths_max;
} Gap_Buffer; } Gap_Buffer;
inline_4tech int
buffer_good(Gap_Buffer *buffer){
int good;
good = (buffer->data != 0);
return(good);
}
inline_4tech int inline_4tech int
buffer_size(Gap_Buffer *buffer){ buffer_size(Gap_Buffer *buffer){
int size; int size;
@ -31,7 +38,79 @@ buffer_size(Gap_Buffer *buffer){
return(size); return(size);
} }
inline_4tech void typedef struct{
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){
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);
}
#if 0
internal_4tech void
buffer_initialize(Gap_Buffer *buffer, char *data, int size){ buffer_initialize(Gap_Buffer *buffer, char *data, int size){
int osize1, size1, size2; int osize1, size1, size2;
@ -51,6 +130,7 @@ buffer_initialize(Gap_Buffer *buffer, char *data, int size){
buffer->gap_size = buffer->max - size1 - size2; buffer->gap_size = buffer->max - size1 - size2;
memmove_4tech(buffer->data + size1 + buffer->gap_size, buffer->data + size1, size2); memmove_4tech(buffer->data + size1 + buffer->gap_size, buffer->data + size1, size2);
} }
#endif
internal_4tech void* internal_4tech void*
buffer_relocate(Gap_Buffer *buffer, char *new_data, int new_max){ buffer_relocate(Gap_Buffer *buffer, char *new_data, int new_max){

View File

@ -24,16 +24,81 @@ typedef struct{
int widths_max; int widths_max;
} Buffer; } Buffer;
inline_4tech int
buffer_good(Buffer *buffer){
int good;
good = (buffer->data != 0);
return(good);
}
inline_4tech int inline_4tech int
buffer_size(Buffer *buffer){ buffer_size(Buffer *buffer){
return buffer->size; return buffer->size;
} }
typedef struct{
Buffer *buffer;
char *data;
int size;
} Buffer_Init;
internal_4tech Buffer_Init
buffer_begin_init(Buffer *buffer, char *data, int size){
Buffer_Init init;
init.buffer = buffer;
init.data = data;
init.size = size;
return(init);
}
inline_4tech int
buffer_init_need_more(Buffer_Init *init){
int result;
result = 1;
if (init->buffer->data) result = 0;
return(result);
}
inline_4tech int
buffer_init_page_size(Buffer_Init *init){
int result;
result = init->size * 2;
return(result);
}
inline_4tech void
buffer_init_provide_page(Buffer_Init *init, void *page, int page_size){
Buffer *buffer;
buffer = init->buffer;
buffer->data = (char*)page;
buffer->max = page_size;
}
internal_4tech int
buffer_end_init(Buffer_Init *init){
Buffer *buffer;
int result;
result = 0;
buffer = init->buffer;
if (buffer->data){
if (buffer->max >= init->size){
buffer->size = eol_convert_in(buffer->data, init->data, init->size);
result = 1;
}
}
return(result);
}
#if 0
internal_4tech void internal_4tech void
buffer_initialize(Buffer *buffer, char *data, int size){ buffer_initialize(Buffer *buffer, char *data, int size){
assert_4tech(buffer->data);
assert_4tech(size <= buffer->max); assert_4tech(size <= buffer->max);
buffer->size = eol_convert_in(buffer->data, data, size); buffer->size = eol_convert_in(buffer->data, data, size);
} }
#endif
internal_4tech void* internal_4tech void*
buffer_relocate(Buffer *buffer, char *new_data, int new_max){ buffer_relocate(Buffer *buffer, char *new_data, int new_max){
@ -192,38 +257,5 @@ buffer_batch_edit_step(Buffer_Batch_State *state, Buffer *buffer, Buffer_Edit *s
return(result); return(result);
} }
#if 0
internal_4tech int
buffer_find_hard_start(Buffer *buffer, int line_start, int *all_whitespace, int *all_space,
int *preferred_indent, int tab_width){
char *data;
int size;
int result;
char c;
*all_space = 1;
*preferred_indent = 0;
data = buffer->data;
size = buffer->size;
tab_width -= 1;
for (result = line_start; result < size; ++result){
c = data[result];
if (c == '\n' || c == 0){
*all_whitespace = 1;
break;
}
if (c >= '!' && c <= '~') break;
if (c == '\t') *preferred_indent += tab_width;
if (c != ' ') *all_space = 0;
*preferred_indent += 1;
}
return(result);
}
#endif
// BOTTOM // BOTTOM

View File

@ -0,0 +1,165 @@
/*
* Mr. 4th Dimention - Allen Webster
* Four Tech
*
* public domain -- no warranty is offered or implied; use this code at your own risk
*
* 30.10.2015
*
* Buffer data object
* type - Multi Gap Buffer
*
* This scheme was originally introduced to me by Martin Cohen,
* who calls it a "Fixed Width Gap Buffer".
*
*/
// TOP
typedef struct{
char *data;
int size1, gap_size, size2;
int start_pos;
} Fixed_Width_Gap_Buffer;
#define fixed_width_buffer_size Kbytes(8)
#define fixed_width_buffer_half_size Kbytes(4)
typedef struct{
Fixed_Width_Gap_Buffer *gaps;
int chunk_count;
int chunk_max;
int size;
} Multi_Gap_Buffer;
inline_4tech int
buffer_good(Multi_Gap_Buffer *buffer){
int good;
good = (buffer->gaps != 0);
return(good);
}
inline_4tech int
buffer_size(Multi_Gap_Buffer *buffer){
int size;
size = buffer->size;
return(size);
}
typedef struct{
Multi_Gap_Buffer *buffer;
char *data;
int size;
int chunk_i;
int chunk_count;
} Multi_Gap_Buffer_Init;
internal_4tech Multi_Gap_Buffer_Init
buffer_begin_init(Multi_Gap_Buffer *buffer, char *data, int size){
Multi_Gap_Buffer_Init init;
init.buffer = buffer;
init.data = data;
init.size = size;
init.chunk_i = 0;
init.chunk_count = div_ceil_4tech(size, fixed_width_buffer_half_size);
return(init);
}
internal_4tech int
buffer_init_need_more(Multi_Gap_Buffer_Init *init){
int result;
result = 1;
if (init->buffer->gaps && init->chunk_i == init->chunk_count)
result = 0;
return(result);
}
internal_4tech int
buffer_init_page_size(Multi_Gap_Buffer_Init *init){
Multi_Gap_Buffer *buffer;
int result;
buffer = init->buffer;
if (buffer->gaps) result = fixed_width_buffer_size;
else result = init->chunk_count * 2 * sizeof(*buffer->gaps);
return(result);
}
internal_4tech void
buffer_init_provide_page(Multi_Gap_Buffer_Init *init, void *page, int page_size){
Multi_Gap_Buffer *buffer;
buffer = init->buffer;
if (buffer->gaps){
assert_4tech(page_size >= fixed_width_buffer_size);
buffer->gaps[init->chunk_i].data = (char*)page;
++init->chunk_i;
}
else{
buffer->gaps = (Fixed_Width_Gap_Buffer*)page;
buffer->chunk_max = page_size / sizeof(*buffer->gaps);
}
}
internal_4tech int
buffer_end_init(Multi_Gap_Buffer_Init *init){
Multi_Gap_Buffer *buffer;
Fixed_Width_Gap_Buffer *gap;
int result;
int i, count;
char *data;
int pos, size, total_size, start_pos;
int osize1, size1, size2;
result = 0;
buffer = init->buffer;
if (buffer->gaps){
if (buffer->chunk_max >= div_ceil_4tech(init->size, fixed_width_buffer_half_size)){
buffer->chunk_count = init->chunk_count;
result = 1;
data = init->data;
total_size = init->size;
gap = buffer->gaps;
count = init->chunk_count;
size = fixed_width_buffer_half_size;
pos = 0;
start_pos = 0;
for (i = 0; i < count; ++i, ++gap, pos += size){
if (pos + size > total_size) size = total_size - pos;
if (gap->data){
size2 = size >> 1;
size1 = osize1 = size - size2;
if (size1 > 0){
size1 = eol_convert_in(gap->data, data + pos, size1);
if (size2 > 0){
size2 = eol_convert_in(gap->data + size1, data + pos + osize1, size2);
}
}
gap->size1 = size1;
gap->size2 = size2;
gap->gap_size = fixed_width_buffer_size - size1 - size2;
memmove_4tech(gap->data + size1 + gap->gap_size, gap->data + size1, size2);
gap->start_pos = start_pos;
start_pos += size1 + size2;
}
else{
result = 0;
break;
}
}
buffer->size = start_pos;
}
}
return(result);
}
// BOTTOM

View File

@ -12,18 +12,43 @@
// TOP // TOP
#ifndef defines_4tech #ifndef inline_4tech
#define inline_4tech inline #define inline_4tech inline
#endif
#ifndef internal_4tech
#define internal_4tech static #define internal_4tech static
#endif
#ifndef memset_4tech
#define memset_4tech memset #define memset_4tech memset
#endif
#ifndef memcpy_4tech
#define memcpy_4tech memcpy #define memcpy_4tech memcpy
#endif
#ifndef memmove_4tech
#define memmove_4tech memmove #define memmove_4tech memmove
#define defines_4tech 1 #endif
#ifndef debug_4tech
#define debug_4tech(x) x #define debug_4tech(x) x
#endif
#ifndef assert_4tech
#define assert_4tech assert #define assert_4tech assert
#endif
#ifndef ceil_4tech
#define ceil_4tech CEIL32 #define ceil_4tech CEIL32
#endif
#ifndef div_ceil_4tech
#define div_ceil_4tech DIVCEIL32
#endif
#ifndef cat_4tech
#define cat_4tech_(a,b) a##b #define cat_4tech_(a,b) a##b
#define cat_4tech(a,b) cat_4tech_(a,b) #define cat_4tech(a,b) cat_4tech_(a,b)
#endif #endif
@ -397,5 +422,16 @@ is_lower(char c){
return (c >= 'a' && c <= 'z'); return (c >= 'a' && c <= 'z');
} }
internal_4tech int
is_match(char *a, char *b, int len){
int result;
result = 1;
for (;len > 0; --len, ++a, ++b)
if (*a != *b) { result = 0; break; }
return(result);
}
// BOTTOM // BOTTOM

View File

@ -13,24 +13,28 @@
// Fix the OwnDC thing. // Fix the OwnDC thing.
// //
#ifdef FRED_NOT_PACKAGE
#define FRED_INTERNAL 1
#define FRED_SLOW 1
#define FRED_PRINT_DEBUG 1 #define FRED_PRINT_DEBUG 1
#define FRED_PRINT_DEBUG_FILE_LINE 0 #define FRED_PRINT_DEBUG_FILE_LINE 0
#define FRED_PROFILING 1 #define FRED_PROFILING 1
#define FRED_PROFILING_OS 0 #define FRED_PROFILING_OS 0
#define FRED_FULL_ERRORS 0 #define FRED_FULL_ERRORS 0
#ifndef FRED_SLOW
#define FRED_SLOW 0
#else #else
#undef FRED_SLOW
#define FRED_SLOW 1
#endif
#ifndef FRED_INTERNAL #define FRED_SLOW 0
#define FRED_INTERNAL 0 #define FRED_INTERNAL 0
#else
#undef FRED_INTERNAL #define FRED_PRINT_DEBUG 0
#define FRED_INTERNAL 1 #define FRED_PRINT_DEBUG_FILE_LINE 0
#define FRED_PROFILING 0
#define FRED_PROFILING_OS 0
#define FRED_FULL_ERRORS 0
#endif #endif
#define SOFTWARE_RENDER 0 #define SOFTWARE_RENDER 0
@ -54,7 +58,7 @@
#define FPS 30 #define FPS 30
#define FRAME_TIME (1000000 / FPS) #define FRAME_TIME (1000000 / FPS)
#define BUFFER_EXPERIMENT_SCALPEL 0 #define BUFFER_EXPERIMENT_SCALPEL 2
#include "4ed_meta.h" #include "4ed_meta.h"