dialectic API for line wrap measurements

This commit is contained in:
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
file_measure_wraps(Models *models, Editing_File *file, f32 font_height, f32 *adv){
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);
}
@ -2065,15 +2097,19 @@ 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_remeasure_character_starts(buffer, line_start, line_end, line_shift,
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);
buffer_remeasure_wrap_y(buffer, line_start, line_end, line_shift,
file->state.wraps, (f32)font->height, font->advance_data,
(f32)file->settings.display_width);
#endif
file_measure_wraps(models, file, (f32)font->height, font->advance_data);
// NOTE(allen): cursor fixing
Cursor_Fix_Descriptor desc = {};

View File

@ -86,6 +86,15 @@
; [] 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
; [X] success message when compiler works
; [X] auto-complete
@ -132,6 +141,7 @@
; [X] why are command line files not loading any more?
; [X] use strange theme
; [X] cuber's return to previous buffer idea
; [X] find matches for current identifier
; Token related upgrades
; [X] tokens in the custom API
@ -155,7 +165,7 @@
; [] word level wrapping
; [] code level wrapping
; buffer behavior cleanup
; Buffer behavior cleanup
; [X] show all characters as \# if they can't be rendered
; [X] get the navigation working correctly around multi-glyph characters
; [] wrap remeasuring routine for local edits
@ -165,21 +175,17 @@
; [] unicode buffer mode
; [] support full length unicode file names
; [] miblo's various number editors
; [] user file bar string
; [] API docs as text file
; [] read only files
; [] option to hide hidden files
; [] 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 <#>
; [] undo groups
; [] cursor/scroll groups
; [] double binding warnings
;
;
; [] the "main_4coder" experiment
; [] real multi-line editing
; [] multi-cursor editing
@ -188,10 +194,8 @@
; [] simple text based project file
; [] system commands bound to <ctrl #> in project file
; [] find matches for current identifier
; [] ability to save and reopen the window state
; [] API docs have duplicate ids?
; [] introduce custom command line arguments
; [] control the file opening/start hook relationship better
; [] get keyboard state on launch
@ -222,6 +226,7 @@
; [X] wave search
; [] optimize search
; [] smarter isearch behavior
; [] cleanup word complete so it may be case-insensitive
;
; theme related business

View File

@ -130,7 +130,7 @@ buffer_measure_starts(Buffer_Measure_Starts *state, Buffer_Type *buffer){
}
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);
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;
if (virtual_whitespace){
if (virtual_white){
skipping_whitespace = 1;
}
@ -158,7 +158,7 @@ buffer_measure_character_starts(Buffer_Type *buffer, i32 *character_starts, i32
if (ch == '\n'){
++character_index;
character_starts[line_index++] = character_index;
if (virtual_whitespace){
if (virtual_white){
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);
}
internal_4tech void
buffer_measure_wrap_y(Buffer_Type *buffer, f32 *wraps, f32 font_height, f32 *adv, f32 max_width){
Buffer_Stream_Type stream = {0};
i32 i = 0;
i32 size = buffer_size(buffer);
struct Buffer_Measure_Wrap_Params{
Buffer_Type *buffer;
f32 *wraps;
f32 font_height;
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 = 0.f;
f32 current_wrap;
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)){
b32 still_looping = 0;
u8 ch;
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{
for (; i < stream.end; ++i){
u8 ch = (u8)stream.data[i];
if (ch == '\n'){
current_wrap += font_height;
wraps[wrap_index++] = current_wrap;
x = 0.f;
for (; S.i < S.stream.end; ++S.i){
S.ch = (u8)S.stream.data[S.i];
if (S.ch == '\n'){
S.current_wrap += params.font_height;
params.wraps[S.wrap_index++] = S.current_wrap;
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{
f32 current_adv = adv[ch];
if (x + current_adv > max_width){
current_wrap += font_height;
x = current_adv;
if (S.ch != ' ' && S.ch != '\t'){
S.skipping_whitespace = 0;
}
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);
}while(still_looping);
S.still_looping = buffer_stringify_next(&S.stream);
}while(S.still_looping);
}
current_wrap += font_height;
wraps[wrap_index++] = current_wrap;
S.current_wrap += params.font_height;
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
buffer_remeasure_starts(Buffer_Type *buffer, i32 line_start, i32 line_end, i32 line_shift, i32 text_shift){
i32 *starts = buffer->line_starts;
@ -628,6 +720,8 @@ struct Buffer_Cursor_Seek_State{
i32 i;
i32 size;
b32 xy_seek;
f32 ch_width;
u8 ch;
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 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_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params params,
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__){
DrCase(1);
DrCase(2);
DrCase(3);
}
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.character = 1;
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;
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_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.cursor.character_pos;
++S.cursor.character;
S.cursor.unwrapped_x += ch_width;
S.cursor.wrapped_x += ch_width;
S.cursor.unwrapped_x += S.ch_width;
S.cursor.wrapped_x += S.ch_width;
}break;
}
@ -930,9 +1030,9 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa
DrReturn(S_stop);
}
#undef DrCase
#undef DrYield
#undef DrReturn
#undef DrCase
internal_4tech void
buffer_invert_edit_shift(Buffer_Type *buffer, Buffer_Edit edit, Buffer_Edit *inverse, char *strings,