fixed EOF paste/scroll bugs - robust against render buffer overflows
parent
965500424e
commit
93ab33ee84
|
@ -636,6 +636,22 @@ view_compute_lowest_line(View *view){
|
|||
return lowest_line;
|
||||
}
|
||||
|
||||
inline f32
|
||||
view_compute_max_target_y(i32 lowest_line, i32 line_height, f32 view_height){
|
||||
f32 max_target_y = ((lowest_line+.5f)*line_height) - view_height*.5f;
|
||||
max_target_y = clamp_bottom(0.f, max_target_y);
|
||||
return(max_target_y);
|
||||
}
|
||||
|
||||
inline f32
|
||||
view_compute_max_target_y(View *view){
|
||||
i32 lowest_line = view_compute_lowest_line(view);
|
||||
i32 line_height = view->font_height;
|
||||
f32 view_height = view_file_height(view);
|
||||
f32 max_target_y = view_compute_max_target_y(lowest_line, line_height, view_height);
|
||||
return(max_target_y);
|
||||
}
|
||||
|
||||
internal void
|
||||
view_measure_wraps(General_Memory *general, View *view){
|
||||
Buffer_Type *buffer;
|
||||
|
@ -1477,12 +1493,12 @@ view_get_cursor_y(View *view){
|
|||
#define CursorMinY(m,h) (CursorMinY_(m,h) > 0)?(CursorMinY_(m,h)):(0)
|
||||
|
||||
internal void
|
||||
view_move_cursor_to_view(View *view){
|
||||
view_move_cursor_to_view(View *view, GUI_Scroll_Vars scroll){
|
||||
f32 min_target_y = 0;
|
||||
i32 line_height = view->font_height;
|
||||
f32 old_cursor_y = view_get_cursor_y(view);
|
||||
f32 cursor_y = old_cursor_y;
|
||||
f32 target_y = view->recent->scroll.target_y;
|
||||
f32 target_y = scroll.target_y;
|
||||
f32 cursor_max_y = CursorMaxY(view_file_height(view), line_height);
|
||||
f32 cursor_min_y = CursorMinY(min_target_y, line_height);
|
||||
|
||||
|
@ -1554,22 +1570,6 @@ file_view_nullify_file(View *view){
|
|||
view->file_data = file_viewing_data_zero();
|
||||
}
|
||||
|
||||
inline f32
|
||||
view_compute_max_target_y(i32 lowest_line, i32 line_height, f32 view_height){
|
||||
f32 max_target_y = ((lowest_line+.5f)*line_height) - view_height*.5f;
|
||||
max_target_y = clamp_bottom(0.f, max_target_y);
|
||||
return(max_target_y);
|
||||
}
|
||||
|
||||
internal f32
|
||||
view_compute_max_target_y(View *view){
|
||||
i32 lowest_line = view_compute_lowest_line(view);
|
||||
i32 line_height = view->font_height;
|
||||
f32 view_height = view_file_height(view);
|
||||
f32 max_target_y = view_compute_max_target_y(lowest_line, line_height, view_height);
|
||||
return(max_target_y);
|
||||
}
|
||||
|
||||
internal void
|
||||
view_set_file(View *view, Editing_File *file, Models *models){
|
||||
Font_Info *fnt_info;
|
||||
|
@ -3561,12 +3561,15 @@ view_end_cursor_scroll_updates(View *view){
|
|||
|
||||
case CursorScroll_Cursor:
|
||||
case CursorScroll_Cursor|CursorScroll_Scroll:
|
||||
if (view->gui_target.did_file){
|
||||
view->recent->scroll.max_y = view_compute_max_target_y(view);
|
||||
}
|
||||
view_move_view_to_cursor(view, view->current_scroll);
|
||||
gui_post_scroll_vars(&view->gui_target, view->current_scroll, view->scroll_region);
|
||||
break;
|
||||
|
||||
case CursorScroll_Scroll:
|
||||
view_move_cursor_to_view(view);
|
||||
view_move_cursor_to_view(view, view->recent->scroll);
|
||||
gui_post_scroll_vars(&view->gui_target, view->current_scroll, view->scroll_region);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -34,7 +34,15 @@ draw_set_color(Render_Target *target, u32 color){
|
|||
}
|
||||
}
|
||||
|
||||
#define PutStruct(s,x) *(s*)(target->push_buffer + target->size) = x; target->size += sizeof(s)
|
||||
inline void
|
||||
draw_safe_push(Render_Target *target, i32 size, void *x){
|
||||
if (size + target->size <= target->max){
|
||||
memcpy(target->push_buffer + target->size, x, size);
|
||||
target->size += size;
|
||||
}
|
||||
}
|
||||
|
||||
#define PutStruct(s,x) draw_safe_push(target, sizeof(s), &x)
|
||||
|
||||
internal void
|
||||
draw_push_piece(Render_Target *target, Render_Piece_Combined piece){
|
||||
|
|
|
@ -1313,6 +1313,42 @@ buffer_get_start_cursor(Buffer_Type *buffer, float *wraps, float scroll_y,
|
|||
return(result);
|
||||
}
|
||||
|
||||
#define BRFlag_Special_Character (1 << 0)
|
||||
|
||||
typedef struct Buffer_Render_Item{
|
||||
int index;
|
||||
unsigned short glyphid;
|
||||
unsigned short flags;
|
||||
float x0, y0;
|
||||
float x1, y1;
|
||||
} Buffer_Render_Item;
|
||||
|
||||
inline_4tech void
|
||||
write_render_item(Buffer_Render_Item *item,
|
||||
int index,
|
||||
unsigned short glyphid,
|
||||
float x, float y,
|
||||
float w, float h){
|
||||
item->index = index;
|
||||
item->glyphid = glyphid;
|
||||
item->x0 = x;
|
||||
item->y0 = y;
|
||||
item->x1 = x + w;
|
||||
item->y1 = y + h;
|
||||
}
|
||||
|
||||
inline_4tech float
|
||||
write_render_item_inline(Buffer_Render_Item *item,
|
||||
int index,
|
||||
unsigned short glyphid,
|
||||
float x, float y,
|
||||
float *advance_data, float h){
|
||||
float ch_width;
|
||||
ch_width = measure_character(advance_data, (char)glyphid);
|
||||
write_render_item(item, index, glyphid, x, y, ch_width, h);
|
||||
return(ch_width);
|
||||
}
|
||||
|
||||
internal_4tech void
|
||||
buffer_get_render_data(Buffer_Type *buffer, Buffer_Render_Item *items, int max, int *count,
|
||||
float port_x, float port_y,
|
||||
|
@ -1324,6 +1360,7 @@ buffer_get_render_data(Buffer_Type *buffer, Buffer_Render_Item *items, int max,
|
|||
|
||||
Buffer_Stringify_Type loop;
|
||||
Buffer_Render_Item *item;
|
||||
Buffer_Render_Item *item_end;
|
||||
char *data;
|
||||
int size, end;
|
||||
float shift_x, shift_y;
|
||||
|
@ -1343,10 +1380,15 @@ buffer_get_render_data(Buffer_Type *buffer, Buffer_Render_Item *items, int max,
|
|||
y = shift_y;
|
||||
item_i = 0;
|
||||
item = items + item_i;
|
||||
item_end = items + max;
|
||||
|
||||
// TODO(allen): What's the plan for when there is not enough space to store
|
||||
// more render items? It seems like we should be able to use the view_x
|
||||
// to skip items that are not in view right? That way I think it would
|
||||
// just always fit in the buffer.
|
||||
if (advance_data){
|
||||
for (loop = buffer_stringify_loop(buffer, start_cursor.pos, size);
|
||||
buffer_stringify_good(&loop);
|
||||
buffer_stringify_good(&loop) && item < item_end;
|
||||
buffer_stringify_next(&loop)){
|
||||
|
||||
end = loop.size + loop.absolute_pos;
|
||||
|
@ -1364,6 +1406,7 @@ buffer_get_render_data(Buffer_Type *buffer, Buffer_Render_Item *items, int max,
|
|||
|
||||
switch (ch){
|
||||
case '\n':
|
||||
if (item < item_end){
|
||||
write_render_item_inline(item, i, ' ', x, y, advance_data, font_height);
|
||||
item->flags = 0;
|
||||
++item_i;
|
||||
|
@ -1371,64 +1414,79 @@ buffer_get_render_data(Buffer_Type *buffer, Buffer_Render_Item *items, int max,
|
|||
|
||||
x = shift_x;
|
||||
y += font_height;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0:
|
||||
if (item < item_end){
|
||||
ch_width = write_render_item_inline(item, i, '\\', x, y, advance_data, font_height);
|
||||
item->flags = BRFlag_Special_Character;
|
||||
++item_i;
|
||||
++item;
|
||||
x += ch_width;
|
||||
|
||||
if (item < item_end){
|
||||
ch_width = write_render_item_inline(item, i, '0', x, y, advance_data, font_height);
|
||||
item->flags = BRFlag_Special_Character;
|
||||
++item_i;
|
||||
++item;
|
||||
x += ch_width;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case '\r':
|
||||
if (item < item_end){
|
||||
ch_width = write_render_item_inline(item, i, '\\', x, y, advance_data, font_height);
|
||||
item->flags = BRFlag_Special_Character;
|
||||
++item_i;
|
||||
++item;
|
||||
x += ch_width;
|
||||
|
||||
if (item < item_end){
|
||||
ch_width = write_render_item_inline(item, i, 'r', x, y, advance_data, font_height);
|
||||
item->flags = BRFlag_Special_Character;
|
||||
++item_i;
|
||||
++item;
|
||||
x += ch_width;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case '\t':
|
||||
if (opts.show_slash_t){
|
||||
if (item < item_end){
|
||||
ch_width_sub = write_render_item_inline(item, i, '\\', x, y, advance_data, font_height);
|
||||
item->flags = BRFlag_Special_Character;
|
||||
++item_i;
|
||||
++item;
|
||||
|
||||
if (item < item_end){
|
||||
write_render_item_inline(item, i, 't', x + ch_width_sub, y, advance_data, font_height);
|
||||
item->flags = BRFlag_Special_Character;
|
||||
++item_i;
|
||||
++item;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (item < item_end){
|
||||
write_render_item_inline(item, i, ' ', x, y, advance_data, font_height);
|
||||
item->flags = 0;
|
||||
++item_i;
|
||||
++item;
|
||||
}
|
||||
}
|
||||
x += ch_width;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (item < item_end){
|
||||
write_render_item(item, i, ch, x, y, ch_width, font_height);
|
||||
item->flags = 0;
|
||||
++item_i;
|
||||
++item;
|
||||
x += ch_width;
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (y > height + shift_y) goto buffer_get_render_data_end;
|
||||
|
@ -1437,6 +1495,7 @@ buffer_get_render_data(Buffer_Type *buffer, Buffer_Render_Item *items, int max,
|
|||
|
||||
buffer_get_render_data_end:
|
||||
if (y <= height + shift_y || item == items){
|
||||
if (item < item_end){
|
||||
ch = 0;
|
||||
ch_width = measure_character(advance_data, ' ');
|
||||
write_render_item(item, size, ch, x, y, ch_width, font_height);
|
||||
|
@ -1445,7 +1504,9 @@ buffer_get_render_data_end:
|
|||
x += ch_width;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (item < item_end){
|
||||
ch = 0;
|
||||
ch_width = 0;
|
||||
write_render_item(item, size, ch, x, y, ch_width, font_height);
|
||||
|
@ -1453,6 +1514,7 @@ buffer_get_render_data_end:
|
|||
++item;
|
||||
x += ch_width;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(allen): handle this with a control state
|
||||
assert_4tech(item_i <= max);
|
||||
|
|
|
@ -88,36 +88,6 @@ typedef struct Buffer_Batch_State{
|
|||
int shift_total;
|
||||
} Buffer_Batch_State;
|
||||
|
||||
#define BRFlag_Special_Character (1 << 0)
|
||||
|
||||
typedef struct Buffer_Render_Item{
|
||||
int index;
|
||||
unsigned short glyphid;
|
||||
unsigned short flags;
|
||||
float x0, y0;
|
||||
float x1, y1;
|
||||
} Buffer_Render_Item;
|
||||
|
||||
inline_4tech void
|
||||
write_render_item(Buffer_Render_Item *item, int index, unsigned short glyphid,
|
||||
float x, float y, float w, float h){
|
||||
item->index = index;
|
||||
item->glyphid = glyphid;
|
||||
item->x0 = x;
|
||||
item->y0 = y;
|
||||
item->x1 = x + w;
|
||||
item->y1 = y + h;
|
||||
}
|
||||
|
||||
inline_4tech float
|
||||
write_render_item_inline(Buffer_Render_Item *item, int index, unsigned short glyphid,
|
||||
float x, float y, float *advance_data, float h){
|
||||
float ch_width;
|
||||
ch_width = measure_character(advance_data, (char)glyphid);
|
||||
write_render_item(item, index, glyphid, x, y, ch_width, h);
|
||||
return(ch_width);
|
||||
}
|
||||
|
||||
inline_4tech Full_Cursor
|
||||
make_cursor_hint(int line_index, int *starts, float *wrap_ys, float font_height){
|
||||
Full_Cursor hint;
|
||||
|
|
Loading…
Reference in New Issue