introduced first pass version of character start measuring
This commit is contained in:
parent
fcd6f703b4
commit
249c6f5e4a
|
@ -944,19 +944,15 @@ CUSTOM_COMMAND_SIG(page_down){
|
||||||
CUSTOM_COMMAND_SIG(move_left){
|
CUSTOM_COMMAND_SIG(move_left){
|
||||||
uint32_t access = AccessProtected;
|
uint32_t access = AccessProtected;
|
||||||
View_Summary view = get_active_view(app, access);
|
View_Summary view = get_active_view(app, access);
|
||||||
int32_t new_pos = view.cursor.pos - 1;
|
int32_t new_pos = view.cursor.character_pos - 1;
|
||||||
view_set_cursor(app, &view,
|
view_set_cursor(app, &view, seek_character_pos(new_pos), 1);
|
||||||
seek_pos(new_pos),
|
|
||||||
true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CUSTOM_COMMAND_SIG(move_right){
|
CUSTOM_COMMAND_SIG(move_right){
|
||||||
uint32_t access = AccessProtected;
|
uint32_t access = AccessProtected;
|
||||||
View_Summary view = get_active_view(app, access);
|
View_Summary view = get_active_view(app, access);
|
||||||
int32_t new_pos = view.cursor.pos + 1;
|
int32_t new_pos = view.cursor.character_pos + 1;
|
||||||
view_set_cursor(app, &view,
|
view_set_cursor(app, &view, seek_character_pos(new_pos), 1);
|
||||||
seek_pos(new_pos),
|
|
||||||
true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
53
4ed_file.cpp
53
4ed_file.cpp
|
@ -110,6 +110,9 @@ struct Editing_File_State{
|
||||||
f32 *wraps;
|
f32 *wraps;
|
||||||
i32 wrap_max;
|
i32 wrap_max;
|
||||||
|
|
||||||
|
i32 *character_starts;
|
||||||
|
i32 character_start_max;
|
||||||
|
|
||||||
Undo_Data undo;
|
Undo_Data undo;
|
||||||
|
|
||||||
Cpp_Token_Array token_array;
|
Cpp_Token_Array token_array;
|
||||||
|
@ -329,54 +332,6 @@ edit_pos_get_new(Editing_File *file, i32 index){
|
||||||
return(result);
|
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
|
// File Cursor Seeking
|
||||||
//
|
//
|
||||||
|
@ -415,8 +370,6 @@ file_compute_partial_cursor(Editing_File *file, Buffer_Seek seek, Partial_Cursor
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Working_Set stuff
|
// Working_Set stuff
|
||||||
//
|
//
|
||||||
|
|
|
@ -448,6 +448,22 @@ view_compute_max_target_y(i32 lowest_line, i32 line_height, f32 view_height){
|
||||||
return(CEIL32(max_target_y));
|
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
|
inline i32
|
||||||
view_compute_max_target_y(View *view){
|
view_compute_max_target_y(View *view){
|
||||||
i32 line_height = view->line_height;
|
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.
|
// and that the buffer's line_count is correct.
|
||||||
internal void
|
internal void
|
||||||
file_allocate_wraps_as_needed(General_Memory *general, Editing_File *file){
|
file_allocate_metadata_as_needed(General_Memory *general, Buffer_Type *buffer,
|
||||||
Buffer_Type *buffer = &file->state.buffer;
|
void **mem, i32 *mem_max_count, i32 item_size){
|
||||||
|
if (*mem == 0){
|
||||||
if (file->state.wraps == 0){
|
|
||||||
i32 max = ((buffer->line_count+1)*2);
|
i32 max = ((buffer->line_count+1)*2);
|
||||||
max = (max+(0x1FF))&(~(0x1FF));
|
max = (max+(0x3FF))&(~(0x3FF));
|
||||||
file->state.wraps = (f32*)general_memory_allocate(general, max*sizeof(f32));
|
*mem = general_memory_allocate(general, max*item_size);
|
||||||
file->state.wrap_max = max;
|
*mem_max_count = max;
|
||||||
}
|
}
|
||||||
else if (file->state.wrap_max < buffer->line_count){
|
else if (*mem_max_count < buffer->line_count){
|
||||||
i32 old_max = file->state.wrap_max;
|
i32 old_max = *mem_max_count;
|
||||||
i32 max = ((buffer->line_count+1)*2);
|
i32 max = ((buffer->line_count+1)*2);
|
||||||
max = (max+(0x1FF))&(~(0x1FF));
|
max = (max+(0x3FF))&(~(0x3FF));
|
||||||
|
|
||||||
f32 *new_wraps = (f32*)general_memory_reallocate(
|
void *new_mem = general_memory_reallocate(general, *mem, item_size*old_max, item_size*max);
|
||||||
general, file->state.wraps, sizeof(f32)*old_max, sizeof(f32)*max);
|
|
||||||
|
|
||||||
TentativeAssert(new_wraps);
|
TentativeAssert(new_mem);
|
||||||
file->state.wraps = new_wraps;
|
*mem = new_mem;
|
||||||
file->state.wrap_max = max;
|
*mem_max_count = max;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE(allen): This call assumes that the buffer's line starts are already correct,
|
inline void
|
||||||
// and that the buffer's line_count is correct.
|
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
|
internal void
|
||||||
file_measure_wraps(Models *models, Editing_File *file, f32 font_height, f32 *adv){
|
file_measure_wraps(Models *models, Editing_File *file, f32 font_height, f32 *adv){
|
||||||
file_allocate_wraps_as_needed(&models->mem.general, file);
|
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);
|
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
|
internal void
|
||||||
file_set_display_width(Models *models, Editing_File *file, i32 display_width, f32 font_height, f32 *adv){
|
file_set_display_width(Models *models, Editing_File *file, i32 display_width, f32 font_height, f32 *adv){
|
||||||
file->settings.display_width = display_width;
|
file->settings.display_width = display_width;
|
||||||
file_measure_wraps(models, file, font_height, adv);
|
file_measure_wraps(models, file, font_height, adv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
file_create_from_string(System_Functions *system, Models *models,
|
file_create_from_string(System_Functions *system, Models *models,
|
||||||
Editing_File *file, String val, b8 read_only = 0){
|
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);
|
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_starts(system, general, &file->state.buffer);
|
||||||
|
|
||||||
|
file_measure_character_starts(models, file);
|
||||||
|
|
||||||
i16 font_id = models->global_font.font_id;
|
i16 font_id = models->global_font.font_id;
|
||||||
file->settings.font_id = font_id;
|
file->settings.font_id = font_id;
|
||||||
Render_Font *font = get_font_info(font_set, font_id)->font;
|
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);
|
file_grow_starts_as_needed(general, buffer, line_shift);
|
||||||
buffer_remeasure_starts(buffer, line_start, line_end, line_shift, shift_amount);
|
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);
|
file_allocate_wraps_as_needed(general, file);
|
||||||
buffer_remeasure_wrap_y(buffer, line_start, line_end, line_shift,
|
buffer_remeasure_wrap_y(buffer, line_start, line_end, line_shift,
|
||||||
file->state.wraps, (f32)font->height, font->advance_data,
|
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 = {};
|
||||||
buffer_measure_starts(&measure_state, &file->state.buffer);
|
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;
|
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);
|
file_measure_wraps(models, file, (f32)font->height, font->advance_data);
|
||||||
|
|
||||||
|
|
|
@ -129,7 +129,6 @@ buffer_measure_starts(Buffer_Measure_Starts *state, Buffer_Type *buffer){
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
internal_4tech void
|
internal_4tech void
|
||||||
buffer_measure_character_starts(Buffer_Type *buffer, i32 *character_starts, i32 mode, i32 virtual_whitespace){
|
buffer_measure_character_starts(Buffer_Type *buffer, i32 *character_starts, i32 mode, i32 virtual_whitespace){
|
||||||
assert_4tech(mode == 0);
|
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 size = buffer_size(buffer);
|
||||||
|
|
||||||
i32 line_index = 0;
|
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
|
internal_4tech void
|
||||||
buffer_measure_wrap_y(Buffer_Type *buffer, f32 *wraps, f32 font_height, f32 *adv, f32 max_width){
|
buffer_measure_wrap_y(Buffer_Type *buffer, f32 *wraps, f32 font_height, f32 *adv, f32 max_width){
|
||||||
|
|
Loading…
Reference in New Issue