dialectic API for line wrap measurements

master
Allen Webster 2016-09-27 00:41:59 -04:00
parent 3cfb743a12
commit 980cb9e477
3 changed files with 203 additions and 62 deletions

View File

@ -955,8 +955,40 @@ file_allocate_wraps_as_needed(General_Memory *general, Editing_File *file){
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);
buffer_measure_wrap_y(&file->state.buffer, file->state.wraps,
font_height, adv, (f32)file->settings.display_width); Buffer_Measure_Wrap_Params params;
params.buffer = &file->state.buffer;
params.wraps = file->state.wraps;
params.font_height = font_height;
params.adv = adv;
params.width = (f32)file->settings.display_width;
params.virtual_white = VWHITE;
Buffer_Measure_Wrap_State state = {0};
Buffer_Layout_Stop stop = {0};
f32 edge_tolerance = 50.f;
if (edge_tolerance > params.width){
edge_tolerance = params.width;
}
f32 line_shift = 0.f;
do{
f32 this_line_shift = line_shift;
if (this_line_shift > params.width - edge_tolerance){
this_line_shift = params.width - edge_tolerance;
}
stop = buffer_measure_wrap_y(&state, params, this_line_shift);
switch (stop.status){
case BLStatus_NeedWrapLineShift:
case BLStatus_NeedLineShift:
line_shift = (stop.line_index%4)*9.f;
break;
}
}while(stop.status != BLStatus_Finished);
buffer_measure_wrap_y(&state, params, 0.f);
file_update_cursor_positions(models, file); file_update_cursor_positions(models, file);
} }
@ -2065,15 +2097,19 @@ 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); file_allocate_character_starts_as_needed(general, file);
buffer_remeasure_character_starts(buffer, line_start, line_end, line_shift, buffer_remeasure_character_starts(buffer, line_start, line_end, line_shift,
file->state.character_starts, 0, VWHITE); file->state.character_starts, 0, VWHITE);
// TODO(allen): Redo this as some sort of dialectic API
#if 0
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,
(f32)file->settings.display_width); (f32)file->settings.display_width);
#endif
file_measure_wraps(models, file, (f32)font->height, font->advance_data);
// NOTE(allen): cursor fixing // NOTE(allen): cursor fixing
Cursor_Fix_Descriptor desc = {}; Cursor_Fix_Descriptor desc = {};

View File

@ -86,6 +86,15 @@
; [] view fails to follow cursor after deleting long line ; [] view fails to follow cursor after deleting long line
; ;
; BEFORE I SHIP
;
; [] ad hoc call for setting up/down keys for interactive screens
; [] miblo's various number editors
; [] API docs have duplicate ids?
; [] query buffer font info
; [] option to not open *messages* every startup
;
; TODOS ; TODOS
; [X] success message when compiler works ; [X] success message when compiler works
; [X] auto-complete ; [X] auto-complete
@ -132,6 +141,7 @@
; [X] why are command line files not loading any more? ; [X] why are command line files not loading any more?
; [X] use strange theme ; [X] use strange theme
; [X] cuber's return to previous buffer idea ; [X] cuber's return to previous buffer idea
; [X] find matches for current identifier
; Token related upgrades ; Token related upgrades
; [X] tokens in the custom API ; [X] tokens in the custom API
@ -155,7 +165,7 @@
; [] word level wrapping ; [] word level wrapping
; [] code level wrapping ; [] code level wrapping
; buffer behavior cleanup ; Buffer behavior cleanup
; [X] show all characters as \# if they can't be rendered ; [X] show all characters as \# if they can't be rendered
; [X] get the navigation working correctly around multi-glyph characters ; [X] get the navigation working correctly around multi-glyph characters
; [] wrap remeasuring routine for local edits ; [] wrap remeasuring routine for local edits
@ -165,21 +175,17 @@
; [] unicode buffer mode ; [] unicode buffer mode
; [] support full length unicode file names ; [] support full length unicode file names
; [] miblo's various number editors
; [] user file bar string ; [] user file bar string
; [] API docs as text file ; [] API docs as text file
; [] read only files ; [] read only files
; [] option to hide hidden files ; [] option to hide hidden files
; [] control over how mouse effects panel focus ; [] control over how mouse effects panel focus
; [] option to not open *messages* every startup
;
; [] query buffer font info
; [] option to break buffer name ties by adding parent directories instead of <#> ; [] option to break buffer name ties by adding parent directories instead of <#>
; [] undo groups ; [] undo groups
; [] cursor/scroll groups ; [] cursor/scroll groups
; [] double binding warnings ; [] double binding warnings
;
;
; [] the "main_4coder" experiment ; [] the "main_4coder" experiment
; [] real multi-line editing ; [] real multi-line editing
; [] multi-cursor editing ; [] multi-cursor editing
@ -188,10 +194,8 @@
; [] simple text based project file ; [] simple text based project file
; [] system commands bound to <ctrl #> in project file ; [] system commands bound to <ctrl #> in project file
; [] find matches for current identifier
; [] ability to save and reopen the window state ; [] ability to save and reopen the window state
; [] API docs have duplicate ids?
; [] introduce custom command line arguments ; [] introduce custom command line arguments
; [] control the file opening/start hook relationship better ; [] control the file opening/start hook relationship better
; [] get keyboard state on launch ; [] get keyboard state on launch
@ -222,6 +226,7 @@
; [X] wave search ; [X] wave search
; [] optimize search ; [] optimize search
; [] smarter isearch behavior ; [] smarter isearch behavior
; [] cleanup word complete so it may be case-insensitive
; ;
; theme related business ; theme related business

View File

@ -130,7 +130,7 @@ buffer_measure_starts(Buffer_Measure_Starts *state, Buffer_Type *buffer){
} }
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_white){
assert_4tech(mode == 0); assert_4tech(mode == 0);
Buffer_Stream_Type stream = {0}; Buffer_Stream_Type stream = {0};
@ -144,7 +144,7 @@ buffer_measure_character_starts(Buffer_Type *buffer, i32 *character_starts, i32
character_starts[line_index++] = character_index; character_starts[line_index++] = character_index;
if (virtual_whitespace){ if (virtual_white){
skipping_whitespace = 1; skipping_whitespace = 1;
} }
@ -158,7 +158,7 @@ buffer_measure_character_starts(Buffer_Type *buffer, i32 *character_starts, i32
if (ch == '\n'){ if (ch == '\n'){
++character_index; ++character_index;
character_starts[line_index++] = character_index; character_starts[line_index++] = character_index;
if (virtual_whitespace){ if (virtual_white){
skipping_whitespace = 1; skipping_whitespace = 1;
} }
} }
@ -179,50 +179,142 @@ buffer_measure_character_starts(Buffer_Type *buffer, i32 *character_starts, i32
assert_4tech(line_index-1 == buffer->line_count); assert_4tech(line_index-1 == buffer->line_count);
} }
internal_4tech void struct Buffer_Measure_Wrap_Params{
buffer_measure_wrap_y(Buffer_Type *buffer, f32 *wraps, f32 font_height, f32 *adv, f32 max_width){ Buffer_Type *buffer;
Buffer_Stream_Type stream = {0}; f32 *wraps;
i32 i = 0; f32 font_height;
i32 size = buffer_size(buffer); f32 *adv;
f32 width;
b32 virtual_white;
};
struct Buffer_Measure_Wrap_State{
Buffer_Stream_Type stream;
i32 i;
i32 size;
i32 wrap_index;
i32 wrap_index = 0; f32 current_wrap;
f32 current_wrap = 0.f; f32 current_adv;
f32 x;
f32 x = 0.f; b32 skipping_whitespace;
wraps[wrap_index++] = current_wrap; b32 still_looping;
if (buffer_stringify_loop(&stream, buffer, i, size)){ u8 ch;
b32 still_looping = 0;
i32 __pc__;
};
// duff-routine defines
#define DrCase(PC) case PC: goto resumespot_##PC
#define DrYield(PC, n) { *S_ptr = S; S_ptr->__pc__ = PC; return(n); resumespot_##PC:; }
#define DrReturn(n) { *S_ptr = S; S_ptr->__pc__ = -1; return(n); }
enum{
BLStatus_Finished,
BLStatus_NeedWrapLineShift,
BLStatus_NeedLineShift
};
struct Buffer_Layout_Stop{
u32 status;
i32 line_index;
i32 pos;
};
internal_4tech Buffer_Layout_Stop
buffer_measure_wrap_y(Buffer_Measure_Wrap_State *S_ptr, Buffer_Measure_Wrap_Params params, f32 line_shift){
Buffer_Measure_Wrap_State S = *S_ptr;
Buffer_Layout_Stop S_stop;
S.size = buffer_size(params.buffer);
switch (S.__pc__){
DrCase(1);
DrCase(2);
DrCase(3);
}
if (params.virtual_white){
S_stop.status = BLStatus_NeedLineShift;
S_stop.line_index = S.wrap_index;
S_stop.pos = S.i;
DrYield(1, S_stop);
}
S.x = line_shift;
params.wraps[S.wrap_index++] = 0;
if (params.virtual_white){
S.skipping_whitespace = 1;
}
if (buffer_stringify_loop(&S.stream, params.buffer, S.i, S.size)){
S.still_looping = 0;
do{ do{
for (; i < stream.end; ++i){ for (; S.i < S.stream.end; ++S.i){
u8 ch = (u8)stream.data[i]; S.ch = (u8)S.stream.data[S.i];
if (ch == '\n'){ if (S.ch == '\n'){
current_wrap += font_height; S.current_wrap += params.font_height;
wraps[wrap_index++] = current_wrap; params.wraps[S.wrap_index++] = S.current_wrap;
x = 0.f;
if (params.virtual_white){
S_stop.status = BLStatus_NeedLineShift;
S_stop.line_index = S.wrap_index - 1;
S_stop.pos = S.i+1;
DrYield(2, S_stop);
}
S.x = line_shift;
if (params.virtual_white){
S.skipping_whitespace = 1;
}
} }
else{ else{
f32 current_adv = adv[ch]; if (S.ch != ' ' && S.ch != '\t'){
if (x + current_adv > max_width){ S.skipping_whitespace = 0;
current_wrap += font_height;
x = current_adv;
} }
else{
x += current_adv; if (!S.skipping_whitespace){
S.current_adv = params.adv[S.ch];
if (S.x + S.current_adv > params.width){
S.current_wrap += params.font_height;
if (params.virtual_white){
S_stop.status = BLStatus_NeedWrapLineShift;
S_stop.line_index = S.wrap_index - 1;
S_stop.pos = S.i;
DrYield(3, S_stop);
}
S.x = line_shift + S.current_adv;
}
else{
S.x += S.current_adv;
}
} }
} }
} }
still_looping = buffer_stringify_next(&stream); S.still_looping = buffer_stringify_next(&S.stream);
}while(still_looping); }while(S.still_looping);
} }
current_wrap += font_height; S.current_wrap += params.font_height;
wraps[wrap_index++] = current_wrap; params.wraps[S.wrap_index++] = S.current_wrap;
assert_4tech(wrap_index-1 == buffer->line_count); assert_4tech(S.wrap_index-1 == params.buffer->line_count);
S_stop.status = BLStatus_Finished;
DrReturn(S_stop);
} }
#undef DrCase
#undef DrYield
#undef DrReturn
internal_4tech void internal_4tech void
buffer_remeasure_starts(Buffer_Type *buffer, i32 line_start, i32 line_end, i32 line_shift, i32 text_shift){ buffer_remeasure_starts(Buffer_Type *buffer, i32 line_start, i32 line_end, i32 line_shift, i32 text_shift){
i32 *starts = buffer->line_starts; i32 *starts = buffer->line_starts;
@ -628,6 +720,8 @@ struct Buffer_Cursor_Seek_State{
i32 i; i32 i;
i32 size; i32 size;
b32 xy_seek; b32 xy_seek;
f32 ch_width;
u8 ch; u8 ch;
i32 __pc__; i32 __pc__;
@ -638,18 +732,6 @@ struct Buffer_Cursor_Seek_State{
#define DrYield(PC, n) { *S_ptr = S; S_ptr->__pc__ = PC; return(n); resumespot_##PC:; } #define DrYield(PC, n) { *S_ptr = S; S_ptr->__pc__ = PC; return(n); resumespot_##PC:; }
#define DrReturn(n) { *S_ptr = S; S_ptr->__pc__ = -1; return(n); } #define DrReturn(n) { *S_ptr = S; S_ptr->__pc__ = -1; return(n); }
enum{
BLStatus_Finished,
BLStatus_NeedWrapLineShift,
BLStatus_NeedLineShift
};
struct Buffer_Layout_Stop{
u32 status;
i32 line_index;
i32 pos;
};
internal_4tech Buffer_Layout_Stop internal_4tech Buffer_Layout_Stop
buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params params, buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params params,
f32 line_shift, Full_Cursor *cursor_out){ f32 line_shift, Full_Cursor *cursor_out){
@ -658,6 +740,8 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa
switch (S.__pc__){ switch (S.__pc__){
DrCase(1); DrCase(1);
DrCase(2);
DrCase(3);
} }
S.xy_seek = (params.seek.type == buffer_seek_wrapped_xy || params.seek.type == buffer_seek_unwrapped_xy); S.xy_seek = (params.seek.type == buffer_seek_wrapped_xy || params.seek.type == buffer_seek_unwrapped_xy);
@ -832,23 +916,39 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa
S.cursor.wrapped_y += params.font_height; S.cursor.wrapped_y += params.font_height;
S.cursor.character = 1; S.cursor.character = 1;
S.cursor.unwrapped_x = 0; S.cursor.unwrapped_x = 0;
S.cursor.wrapped_x = 0;
if (params.virtual_white){
S_stop.status = BLStatus_NeedLineShift;
S_stop.line_index = S.cursor.line-1;
S_stop.pos = S.cursor.pos+1;
DrYield(2, S_stop);
}
S.cursor.wrapped_x = line_shift;
}break; }break;
default: default:
{ {
f32 ch_width = params.adv[S.ch]; S.ch_width = params.adv[S.ch];
if (S.cursor.wrapped_x + ch_width > params.width){ if (S.cursor.wrapped_x + S.ch_width > params.width){
S.cursor.wrapped_y += params.font_height; S.cursor.wrapped_y += params.font_height;
S.cursor.wrapped_x = 0;
if (params.virtual_white){
S_stop.status = BLStatus_NeedWrapLineShift;
S_stop.line_index = S.cursor.line-1;
S_stop.pos = S.cursor.pos;
DrYield(3, S_stop);
}
S.cursor.wrapped_x = line_shift;
S.prev_cursor = S.cursor; S.prev_cursor = S.cursor;
} }
++S.cursor.character_pos; ++S.cursor.character_pos;
++S.cursor.character; ++S.cursor.character;
S.cursor.unwrapped_x += ch_width; S.cursor.unwrapped_x += S.ch_width;
S.cursor.wrapped_x += ch_width; S.cursor.wrapped_x += S.ch_width;
}break; }break;
} }
@ -930,9 +1030,9 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa
DrReturn(S_stop); DrReturn(S_stop);
} }
#undef DrCase
#undef DrYield #undef DrYield
#undef DrReturn #undef DrReturn
#undef DrCase
internal_4tech void internal_4tech void
buffer_invert_edit_shift(Buffer_Type *buffer, Buffer_Edit edit, Buffer_Edit *inverse, char *strings, buffer_invert_edit_shift(Buffer_Type *buffer, Buffer_Edit edit, Buffer_Edit *inverse, char *strings,