From 249c6f5e4a9bdee43b9da7a3e366d993006c72ef Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Sat, 24 Sep 2016 13:25:11 -0400 Subject: [PATCH] introduced first pass version of character start measuring --- 4coder_default_include.cpp | 12 +-- 4ed_file.cpp | 53 +------------- 4ed_file_view.cpp | 118 +++++++++++++++++++++++++----- buffer/4coder_buffer_abstract.cpp | 27 ++++++- 4 files changed, 130 insertions(+), 80 deletions(-) diff --git a/4coder_default_include.cpp b/4coder_default_include.cpp index a91e7be3..606a81ee 100644 --- a/4coder_default_include.cpp +++ b/4coder_default_include.cpp @@ -944,19 +944,15 @@ CUSTOM_COMMAND_SIG(page_down){ CUSTOM_COMMAND_SIG(move_left){ uint32_t access = AccessProtected; View_Summary view = get_active_view(app, access); - int32_t new_pos = view.cursor.pos - 1; - view_set_cursor(app, &view, - seek_pos(new_pos), - true); + int32_t new_pos = view.cursor.character_pos - 1; + view_set_cursor(app, &view, seek_character_pos(new_pos), 1); } CUSTOM_COMMAND_SIG(move_right){ uint32_t access = AccessProtected; View_Summary view = get_active_view(app, access); - int32_t new_pos = view.cursor.pos + 1; - view_set_cursor(app, &view, - seek_pos(new_pos), - true); + int32_t new_pos = view.cursor.character_pos + 1; + view_set_cursor(app, &view, seek_character_pos(new_pos), 1); } // diff --git a/4ed_file.cpp b/4ed_file.cpp index 7fc0013a..243729fd 100644 --- a/4ed_file.cpp +++ b/4ed_file.cpp @@ -110,6 +110,9 @@ struct Editing_File_State{ f32 *wraps; i32 wrap_max; + i32 *character_starts; + i32 character_start_max; + Undo_Data undo; Cpp_Token_Array token_array; @@ -329,54 +332,6 @@ edit_pos_get_new(Editing_File *file, i32 index){ return(result); } -// -// Buffer Metadata Measuring -// - -internal void -file_measure_starts(System_Functions *system, General_Memory *general, Buffer_Type *buffer){ - if (!buffer->line_starts){ - i32 max = buffer->line_max = Kbytes(1); - buffer->line_starts = (i32*)general_memory_allocate(general, max*sizeof(i32)); - TentativeAssert(buffer->line_starts); - // TODO(allen): when unable to allocate? - } - - Buffer_Measure_Starts state = {0}; - while (buffer_measure_starts(&state, buffer)){ - i32 count = state.count; - i32 max = buffer->line_max; - max = ((max + 1) << 1); - - { - i32 *new_lines = (i32*)general_memory_reallocate( - general, buffer->line_starts, sizeof(i32)*count, sizeof(i32)*max); - - // TODO(allen): when unable to grow? - TentativeAssert(new_lines); - buffer->line_starts = new_lines; - buffer->line_max = max; - } - } - buffer->line_count = state.count; -} - -internal i32 -file_compute_lowest_line(Editing_File *file, f32 font_height){ - i32 lowest_line = 0; - - Buffer_Type *buffer = &file->state.buffer; - if (file->settings.unwrapped_lines){ - lowest_line = buffer->line_count - 1; - } - else{ - f32 term_line_y = file->state.wraps[buffer->line_count]; - lowest_line = CEIL32((term_line_y/font_height) - 1); - } - - return(lowest_line); -} - // // File Cursor Seeking // @@ -415,8 +370,6 @@ file_compute_partial_cursor(Editing_File *file, Buffer_Seek seek, Partial_Cursor return(result); } - - // // Working_Set stuff // diff --git a/4ed_file_view.cpp b/4ed_file_view.cpp index edfeb1fd..d6c46db4 100644 --- a/4ed_file_view.cpp +++ b/4ed_file_view.cpp @@ -448,6 +448,22 @@ view_compute_max_target_y(i32 lowest_line, i32 line_height, f32 view_height){ return(CEIL32(max_target_y)); } +internal i32 +file_compute_lowest_line(Editing_File *file, f32 font_height){ + i32 lowest_line = 0; + + Buffer_Type *buffer = &file->state.buffer; + if (file->settings.unwrapped_lines){ + lowest_line = buffer->line_count; + } + else{ + f32 term_line_y = file->state.wraps[buffer->line_count]; + lowest_line = CEIL32(term_line_y/font_height); + } + + return(lowest_line); +} + inline i32 view_compute_max_target_y(View *view){ i32 line_height = view->line_height; @@ -848,34 +864,83 @@ file_update_cursor_positions(Models *models, Editing_File *file){ } } -// NOTE(allen): This call assumes that the buffer's line starts are already correct, +// +// File Metadata Measuring +// + +internal void +file_measure_starts(System_Functions *system, General_Memory *general, Buffer_Type *buffer){ + if (!buffer->line_starts){ + i32 max = buffer->line_max = Kbytes(1); + buffer->line_starts = (i32*)general_memory_allocate(general, max*sizeof(i32)); + TentativeAssert(buffer->line_starts); + // TODO(allen): when unable to allocate? + } + + Buffer_Measure_Starts state = {0}; + while (buffer_measure_starts(&state, buffer)){ + i32 count = state.count; + i32 max = buffer->line_max; + max = ((max + 1) << 1); + + { + i32 *new_lines = (i32*)general_memory_reallocate( + general, buffer->line_starts, sizeof(i32)*count, sizeof(i32)*max); + + // TODO(allen): when unable to grow? + TentativeAssert(new_lines); + buffer->line_starts = new_lines; + buffer->line_max = max; + } + } + buffer->line_count = state.count; +} + +// NOTE(allen): These calls assumes that the buffer's line starts are already correct, // and that the buffer's line_count is correct. internal void -file_allocate_wraps_as_needed(General_Memory *general, Editing_File *file){ - Buffer_Type *buffer = &file->state.buffer; - - if (file->state.wraps == 0){ +file_allocate_metadata_as_needed(General_Memory *general, Buffer_Type *buffer, + void **mem, i32 *mem_max_count, i32 item_size){ + if (*mem == 0){ i32 max = ((buffer->line_count+1)*2); - max = (max+(0x1FF))&(~(0x1FF)); - file->state.wraps = (f32*)general_memory_allocate(general, max*sizeof(f32)); - file->state.wrap_max = max; + max = (max+(0x3FF))&(~(0x3FF)); + *mem = general_memory_allocate(general, max*item_size); + *mem_max_count = max; } - else if (file->state.wrap_max < buffer->line_count){ - i32 old_max = file->state.wrap_max; + else if (*mem_max_count < buffer->line_count){ + i32 old_max = *mem_max_count; i32 max = ((buffer->line_count+1)*2); - max = (max+(0x1FF))&(~(0x1FF)); + max = (max+(0x3FF))&(~(0x3FF)); - f32 *new_wraps = (f32*)general_memory_reallocate( - general, file->state.wraps, sizeof(f32)*old_max, sizeof(f32)*max); + void *new_mem = general_memory_reallocate(general, *mem, item_size*old_max, item_size*max); - TentativeAssert(new_wraps); - file->state.wraps = new_wraps; - file->state.wrap_max = max; + TentativeAssert(new_mem); + *mem = new_mem; + *mem_max_count = max; } } -// NOTE(allen): This call assumes that the buffer's line starts are already correct, -// and that the buffer's line_count is correct. +inline void +file_allocate_character_starts_as_needed(General_Memory *general, Editing_File *file){ + file_allocate_metadata_as_needed(general, &file->state.buffer, + (void**)&file->state.character_starts, + &file->state.character_start_max, sizeof(i32)); +} + +internal void +file_measure_character_starts(Models *models, Editing_File *file){ + file_allocate_character_starts_as_needed(&models->mem.general, file); + buffer_measure_character_starts(&file->state.buffer, file->state.character_starts, 0, 1); + file_update_cursor_positions(models, file); +} + +inline void +file_allocate_wraps_as_needed(General_Memory *general, Editing_File *file){ + file_allocate_metadata_as_needed(general, &file->state.buffer, + (void**)&file->state.wraps, + &file->state.wrap_max, sizeof(f32)); +} + internal void file_measure_wraps(Models *models, Editing_File *file, f32 font_height, f32 *adv){ file_allocate_wraps_as_needed(&models->mem.general, file); @@ -884,14 +949,16 @@ file_measure_wraps(Models *models, Editing_File *file, f32 font_height, f32 *adv file_update_cursor_positions(models, file); } -// NOTE(allen): This call assumes that the buffer's line starts are already correct, -// and that the buffer's line_count is correct. internal void file_set_display_width(Models *models, Editing_File *file, i32 display_width, f32 font_height, f32 *adv){ file->settings.display_width = display_width; file_measure_wraps(models, file, font_height, adv); } +// +// +// + internal void file_create_from_string(System_Functions *system, Models *models, Editing_File *file, String val, b8 read_only = 0){ @@ -922,8 +989,12 @@ file_create_from_string(System_Functions *system, Models *models, } file_synchronize_times(system, file); + // TODO(allen): batch some of these together so we can avoid + // making so many passes over the buffer? file_measure_starts(system, general, &file->state.buffer); + file_measure_character_starts(models, file); + i16 font_id = models->global_font.font_id; file->settings.font_id = font_id; Render_Font *font = get_font_info(font_set, font_id)->font; @@ -1983,6 +2054,10 @@ file_do_single_edit(System_Functions *system, file_grow_starts_as_needed(general, buffer, line_shift); buffer_remeasure_starts(buffer, line_start, line_end, line_shift, shift_amount); + // TODO(allen): write the remeasurement version + file_allocate_character_starts_as_needed(general, file); + buffer_measure_character_starts(buffer, file->state.character_starts, 0, 1); + file_allocate_wraps_as_needed(general, file); buffer_remeasure_wrap_y(buffer, line_start, line_end, line_shift, file->state.wraps, (f32)font->height, font->advance_data, @@ -2049,6 +2124,9 @@ file_do_batch_edit(System_Functions *system, Models *models, Editing_File *file, Buffer_Measure_Starts measure_state = {}; buffer_measure_starts(&measure_state, &file->state.buffer); + // TODO(allen): write the remeasurement version + file_measure_character_starts(models, file); + Render_Font *font = get_font_info(models->font_set, file->settings.font_id)->font; file_measure_wraps(models, file, (f32)font->height, font->advance_data); diff --git a/buffer/4coder_buffer_abstract.cpp b/buffer/4coder_buffer_abstract.cpp index c82eafbc..d3d776bb 100644 --- a/buffer/4coder_buffer_abstract.cpp +++ b/buffer/4coder_buffer_abstract.cpp @@ -129,7 +129,6 @@ buffer_measure_starts(Buffer_Measure_Starts *state, Buffer_Type *buffer){ return(result); } -#if 0 internal_4tech void buffer_measure_character_starts(Buffer_Type *buffer, i32 *character_starts, i32 mode, i32 virtual_whitespace){ assert_4tech(mode == 0); @@ -139,8 +138,32 @@ buffer_measure_character_starts(Buffer_Type *buffer, i32 *character_starts, i32 i32 size = buffer_size(buffer); i32 line_index = 0; + i32 character_index = 0; + + character_starts[line_index++] = character_index; + + if (buffer_stringify_loop(&stream, buffer, i, size)){ + b32 still_looping = 0; + do{ + for (; i < stream.end; ++i){ + u8 ch = (u8)stream.data[i]; + if (ch == '\n'){ + ++character_index; + character_starts[line_index++] = character_index; + } + else{ + ++character_index; + } + } + still_looping = buffer_stringify_next(&stream); + }while(still_looping); + } + + ++character_index; + character_starts[line_index++] = character_index; + + assert_4tech(line_index-1 == buffer->line_count); } -#endif internal_4tech void buffer_measure_wrap_y(Buffer_Type *buffer, f32 *wraps, f32 font_height, f32 *adv, f32 max_width){