Layout with cool parantheses thing working
parent
745ca37668
commit
eb29349caf
10
4ed.cpp
10
4ed.cpp
|
@ -61,9 +61,7 @@ fill_hardcode_default_style(Color_Table color_table){
|
||||||
color_table.vals[Stag_Include] = color_table.vals[Stag_Str_Constant];
|
color_table.vals[Stag_Include] = color_table.vals[Stag_Str_Constant];
|
||||||
color_table.vals[Stag_Preproc] = color_table.vals[Stag_Default];
|
color_table.vals[Stag_Preproc] = color_table.vals[Stag_Default];
|
||||||
color_table.vals[Stag_Special_Character] = 0xFFFF0000;
|
color_table.vals[Stag_Special_Character] = 0xFFFF0000;
|
||||||
color_table.vals[Stag_Ghost_Character] = color_blend(color_table.vals[Stag_Default],
|
color_table.vals[Stag_Ghost_Character] = color_blend(color_table.vals[Stag_Default], 0.5f, color_table.vals[Stag_Back]);
|
||||||
0.5f,
|
|
||||||
color_table.vals[Stag_Back]);
|
|
||||||
|
|
||||||
color_table.vals[Stag_Paste] = 0xFFDDEE00;
|
color_table.vals[Stag_Paste] = 0xFFDDEE00;
|
||||||
color_table.vals[Stag_Undo] = 0xFF00DDEE;
|
color_table.vals[Stag_Undo] = 0xFF00DDEE;
|
||||||
|
@ -116,8 +114,7 @@ init_command_line_settings(App_Settings *settings, Plat_Settings *plat_settings,
|
||||||
|
|
||||||
if (arg[0] == '-' && arg[1] == '-'){
|
if (arg[0] == '-' && arg[1] == '-'){
|
||||||
char *long_arg_name = arg+2;
|
char *long_arg_name = arg+2;
|
||||||
if (string_match(SCu8(long_arg_name),
|
if (string_match(SCu8(long_arg_name), string_u8_litexpr("custom"))){
|
||||||
string_u8_litexpr("custom"))){
|
|
||||||
mode = CLMode_Custom;
|
mode = CLMode_Custom;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -625,8 +622,7 @@ App_Step_Sig(app_step){
|
||||||
b32 event_was_handled = false;
|
b32 event_was_handled = false;
|
||||||
Input_Event *event = &node->event;
|
Input_Event *event = &node->event;
|
||||||
|
|
||||||
if (event->kind == InputEventKind_TextInsert &&
|
if (event->kind == InputEventKind_TextInsert && event->text.blocked){
|
||||||
event->text.blocked){
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -413,9 +413,7 @@ buffer_pos_at_relative_xy(Application_Links *app, Buffer_ID buffer_id,
|
||||||
}
|
}
|
||||||
|
|
||||||
api(custom) function Rect_f32
|
api(custom) function Rect_f32
|
||||||
buffer_relative_box_of_pos(Application_Links *app, Buffer_ID buffer_id,
|
buffer_relative_box_of_pos(Application_Links *app, Buffer_ID buffer_id, f32 width, Face_ID face_id, i64 base_line, i64 pos){
|
||||||
f32 width, Face_ID face_id,
|
|
||||||
i64 base_line, i64 pos){
|
|
||||||
Models *models = (Models*)app->cmd_context;
|
Models *models = (Models*)app->cmd_context;
|
||||||
Editing_File *file = imp_get_file(models, buffer_id);
|
Editing_File *file = imp_get_file(models, buffer_id);
|
||||||
Rect_f32 result = {};
|
Rect_f32 result = {};
|
||||||
|
|
|
@ -61,6 +61,7 @@
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
||||||
#include "4coder_base_types.cpp"
|
#include "4coder_base_types.cpp"
|
||||||
|
#include "4coder_layout.cpp"
|
||||||
#include "4coder_system_helpers.cpp"
|
#include "4coder_system_helpers.cpp"
|
||||||
#include "4coder_events.cpp"
|
#include "4coder_events.cpp"
|
||||||
#include "4coder_string_match.cpp"
|
#include "4coder_string_match.cpp"
|
||||||
|
|
231
4ed_buffer.cpp
231
4ed_buffer.cpp
|
@ -854,236 +854,5 @@ buffer_chunk_position_iterate(String_Const_u8_Array chunks, Buffer_Chunk_Positio
|
||||||
return(past_end);
|
return(past_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
|
|
||||||
internal i64
|
|
||||||
buffer_layout_nearest_pos_to_xy(Layout_Item_List list, Vec2_f32 p){
|
|
||||||
i64 closest_match = 0;
|
|
||||||
if (p.y < 0.f){
|
|
||||||
closest_match = list.manifested_index_range.min;
|
|
||||||
}
|
|
||||||
else if (p.y >= list.height){
|
|
||||||
closest_match = list.manifested_index_range.max;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
if (0.f < p.x && p.x < max_f32){
|
|
||||||
f32 bottom_padding = list.bottom_padding;
|
|
||||||
f32 closest_x = -max_f32;
|
|
||||||
for (Layout_Item_Block *block = list.first;
|
|
||||||
block != 0;
|
|
||||||
block = block->next){
|
|
||||||
i64 count = block->item_count;
|
|
||||||
Layout_Item *item = block->items;
|
|
||||||
for (i32 i = 0; i < count; i += 1, item += 1){
|
|
||||||
if (HasFlag(item->flags, LayoutItemFlag_Ghost_Character)){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// NOTE(allen): This only works if we build layouts in y-sorted order.
|
|
||||||
if (p.y < item->rect.y0){
|
|
||||||
goto double_break;
|
|
||||||
}
|
|
||||||
if (item->rect.y1 + bottom_padding <= p.y){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
f32 dist0 = p.x - item->rect.x0;
|
|
||||||
f32 dist1 = item->rect.x1 - p.x;
|
|
||||||
if (dist0 >= 0.f && dist1 > 0.f){
|
|
||||||
closest_match = item->index;
|
|
||||||
goto double_break;
|
|
||||||
}
|
|
||||||
// NOTE(allen): One of dist0 and dist1 are negative, but certainly not both.
|
|
||||||
// 1. Take the negative one.
|
|
||||||
// 2. If the negative distance is larger than closest_x, then this is closer.
|
|
||||||
f32 neg_dist = min(dist0, dist1);
|
|
||||||
if (closest_x < neg_dist){
|
|
||||||
closest_x = neg_dist;
|
|
||||||
closest_match = item->index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
double_break:;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
|
|
||||||
if (p.x == max_f32){
|
|
||||||
Layout_Item *prev_item = 0;
|
|
||||||
for (Layout_Item_Block *block = list.first;
|
|
||||||
block != 0;
|
|
||||||
block = block->next){
|
|
||||||
i64 count = block->item_count;
|
|
||||||
Layout_Item *item = block->items;
|
|
||||||
for (i32 i = 0; i < count; i += 1, item += 1){
|
|
||||||
if (HasFlag(item->flags, LayoutItemFlag_Ghost_Character)){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (p.y < item->rect.y0){
|
|
||||||
goto double_break_2;
|
|
||||||
}
|
|
||||||
prev_item = item;
|
|
||||||
if (item->rect.y1 <= p.y){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
double_break_2:;
|
|
||||||
if (prev_item != 0){
|
|
||||||
closest_match = prev_item->index;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
closest_match = list.manifested_index_range.max;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
Layout_Item *closest_item = 0;
|
|
||||||
for (Layout_Item_Block *block = list.first;
|
|
||||||
block != 0;
|
|
||||||
block = block->next){
|
|
||||||
i64 count = block->item_count;
|
|
||||||
Layout_Item *item = block->items;
|
|
||||||
for (i32 i = 0; i < count; i += 1, item += 1){
|
|
||||||
if (HasFlag(item->flags, LayoutItemFlag_Ghost_Character)){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// NOTE(allen): This only works if we build layouts in y-sorted order.
|
|
||||||
if (p.y < item->rect.y0){
|
|
||||||
goto double_break_3;
|
|
||||||
}
|
|
||||||
if (item->rect.y1 <= p.y){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
closest_item = item;
|
|
||||||
goto double_break_3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
double_break_3:;
|
|
||||||
if (closest_item != 0){
|
|
||||||
closest_match = closest_item->index;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
closest_match = list.manifested_index_range.min;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return(closest_match);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal Layout_Item*
|
|
||||||
buffer_layout_get_first_with_index(Layout_Item_List list, i64 index){
|
|
||||||
Layout_Item *result = 0;
|
|
||||||
Layout_Item *prev = 0;
|
|
||||||
for (Layout_Item_Block *block = list.first;
|
|
||||||
block != 0;
|
|
||||||
block = block->next){
|
|
||||||
i64 count = block->item_count;
|
|
||||||
Layout_Item *item = block->items;
|
|
||||||
for (i32 i = 0; i < count; i += 1, item += 1){
|
|
||||||
if (HasFlag(item->flags, LayoutItemFlag_Ghost_Character)){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (item->index > index){
|
|
||||||
result = prev;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (item->index == index){
|
|
||||||
result = item;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
prev = item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (result == 0){
|
|
||||||
result = prev;
|
|
||||||
}
|
|
||||||
done:;
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal Rect_f32
|
|
||||||
buffer_layout_box_of_pos(Layout_Item_List list, i64 index){
|
|
||||||
Rect_f32 result = {};
|
|
||||||
Layout_Item *item = buffer_layout_get_first_with_index(list, index);
|
|
||||||
if (item != 0){
|
|
||||||
result = item->rect;
|
|
||||||
}
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal i64
|
|
||||||
buffer_layout_get_pos_at_character(Layout_Item_List list, i64 character){
|
|
||||||
i64 result = 0;
|
|
||||||
if (character <= 0){
|
|
||||||
result = list.manifested_index_range.min;
|
|
||||||
}
|
|
||||||
else if (character >= list.character_count){
|
|
||||||
result = list.manifested_index_range.max;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
i64 counter = 0;
|
|
||||||
i64 next_counter = 0;
|
|
||||||
for (Layout_Item_Block *node = list.first;
|
|
||||||
node != 0;
|
|
||||||
node = node->next, counter = next_counter){
|
|
||||||
next_counter = counter + node->character_count;
|
|
||||||
if (character >= next_counter){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
i64 count = node->item_count;
|
|
||||||
i64 relative_character = character - counter;
|
|
||||||
i64 relative_character_counter = 0;
|
|
||||||
|
|
||||||
Layout_Item *item = node->items;
|
|
||||||
for (i64 i = 0; i < count; i += 1, item += 1){
|
|
||||||
if (HasFlag(item->flags, LayoutItemFlag_Ghost_Character)){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (relative_character_counter == relative_character){
|
|
||||||
result = item->index;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
relative_character_counter += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal i64
|
|
||||||
buffer_layout_character_from_pos(Layout_Item_List list, i64 index){
|
|
||||||
i64 result = 0;
|
|
||||||
i64 prev_index = -1;
|
|
||||||
if (index <= list.manifested_index_range.first){
|
|
||||||
result = 0;
|
|
||||||
}
|
|
||||||
else if (index > list.manifested_index_range.one_past_last){
|
|
||||||
result = list.character_count - 1;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
for (Layout_Item_Block *node = list.first;
|
|
||||||
node != 0;
|
|
||||||
node = node->next){
|
|
||||||
Layout_Item *item = node->items;
|
|
||||||
i64 count = node->item_count;
|
|
||||||
for (i64 i = 0; i < count; i += 1, item += 1){
|
|
||||||
if (item->index >= index){
|
|
||||||
goto double_break;
|
|
||||||
}
|
|
||||||
if (item->index > prev_index){
|
|
||||||
prev_index = item->index;
|
|
||||||
result += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
double_break:;
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
// BOTTOM
|
// BOTTOM
|
||||||
|
|
||||||
|
|
73
4ed_file.cpp
73
4ed_file.cpp
|
@ -413,8 +413,7 @@ file_line_y_difference(Thread_Context *tctx, Models *models, Editing_File *file,
|
||||||
if (line_a != line_b){
|
if (line_a != line_b){
|
||||||
Interval_i64 line_range = Ii64(line_a, line_b);
|
Interval_i64 line_range = Ii64(line_a, line_b);
|
||||||
for (i64 i = line_range.min; i < line_range.max; i += 1){
|
for (i64 i = line_range.min; i < line_range.max; i += 1){
|
||||||
Layout_Item_List line = file_get_line_layout(tctx, models, file, layout_func,
|
Layout_Item_List line = file_get_line_layout(tctx, models, file, layout_func, width, face, i);
|
||||||
width, face, i);
|
|
||||||
result += line.height;
|
result += line.height;
|
||||||
}
|
}
|
||||||
if (line_a < line_b){
|
if (line_a < line_b){
|
||||||
|
@ -428,14 +427,10 @@ internal i64
|
||||||
file_pos_at_relative_xy(Thread_Context *tctx, Models *models, Editing_File *file,
|
file_pos_at_relative_xy(Thread_Context *tctx, Models *models, Editing_File *file,
|
||||||
Layout_Function *layout_func, f32 width, Face *face,
|
Layout_Function *layout_func, f32 width, Face *face,
|
||||||
i64 base_line, Vec2_f32 relative_xy){
|
i64 base_line, Vec2_f32 relative_xy){
|
||||||
Line_Shift_Vertical shift = file_line_shift_y(tctx, models, file,
|
Line_Shift_Vertical shift = file_line_shift_y(tctx, models, file, layout_func, width, face, base_line, relative_xy.y);
|
||||||
layout_func, width, face, base_line,
|
|
||||||
relative_xy.y);
|
|
||||||
relative_xy.y -= shift.y_delta;
|
relative_xy.y -= shift.y_delta;
|
||||||
Layout_Item_List line = file_get_line_layout(tctx, models, file,
|
Layout_Item_List line = file_get_line_layout(tctx, models, file, layout_func, width, face, shift.line);
|
||||||
layout_func, width, face,
|
return(layout_nearest_pos_to_xy(line, relative_xy));
|
||||||
shift.line);
|
|
||||||
return(buffer_layout_nearest_pos_to_xy(line, relative_xy));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal Rect_f32
|
internal Rect_f32
|
||||||
|
@ -443,14 +438,10 @@ file_relative_box_of_pos(Thread_Context *tctx, Models *models, Editing_File *fil
|
||||||
Layout_Function *layout_func, f32 width, Face *face,
|
Layout_Function *layout_func, f32 width, Face *face,
|
||||||
i64 base_line, i64 pos){
|
i64 base_line, i64 pos){
|
||||||
i64 line_number = buffer_get_line_index(&file->state.buffer, pos) + 1;
|
i64 line_number = buffer_get_line_index(&file->state.buffer, pos) + 1;
|
||||||
Layout_Item_List line = file_get_line_layout(tctx, models, file,
|
Layout_Item_List line = file_get_line_layout(tctx, models, file, layout_func, width, face, line_number);
|
||||||
layout_func, width, face,
|
Rect_f32 result = layout_box_of_pos(line, pos);
|
||||||
line_number);
|
|
||||||
Rect_f32 result = buffer_layout_box_of_pos(line, pos);
|
|
||||||
|
|
||||||
f32 y_difference = file_line_y_difference(tctx, models, file,
|
f32 y_difference = file_line_y_difference(tctx, models, file, layout_func, width, face, line_number, base_line);
|
||||||
layout_func, width, face,
|
|
||||||
line_number, base_line);
|
|
||||||
result.y0 += y_difference;
|
result.y0 += y_difference;
|
||||||
result.y1 += y_difference;
|
result.y1 += y_difference;
|
||||||
|
|
||||||
|
@ -461,9 +452,7 @@ function Vec2_f32
|
||||||
file_relative_xy_of_pos(Thread_Context *tctx, Models *models, Editing_File *file,
|
file_relative_xy_of_pos(Thread_Context *tctx, Models *models, Editing_File *file,
|
||||||
Layout_Function *layout_func, f32 width, Face *face,
|
Layout_Function *layout_func, f32 width, Face *face,
|
||||||
i64 base_line, i64 pos){
|
i64 base_line, i64 pos){
|
||||||
Rect_f32 rect = file_relative_box_of_pos(tctx, models, file,
|
Rect_f32 rect = file_relative_box_of_pos(tctx, models, file, layout_func, width, face, base_line, pos);
|
||||||
layout_func, width, face,
|
|
||||||
base_line, pos);
|
|
||||||
return(rect_center(rect));
|
return(rect_center(rect));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -471,9 +460,7 @@ internal Buffer_Point
|
||||||
file_normalize_buffer_point(Thread_Context *tctx, Models *models, Editing_File *file,
|
file_normalize_buffer_point(Thread_Context *tctx, Models *models, Editing_File *file,
|
||||||
Layout_Function *layout_func, f32 width, Face *face,
|
Layout_Function *layout_func, f32 width, Face *face,
|
||||||
Buffer_Point point){
|
Buffer_Point point){
|
||||||
Line_Shift_Vertical shift = file_line_shift_y(tctx, models, file,
|
Line_Shift_Vertical shift = file_line_shift_y(tctx, models, file, layout_func, width, face, point.line_number, point.pixel_shift.y);
|
||||||
layout_func, width, face, point.line_number,
|
|
||||||
point.pixel_shift.y);
|
|
||||||
point.line_number = shift.line;
|
point.line_number = shift.line;
|
||||||
point.pixel_shift.y -= shift.y_delta;
|
point.pixel_shift.y -= shift.y_delta;
|
||||||
point.pixel_shift.x = clamp_bot(0.f, point.pixel_shift.x);
|
point.pixel_shift.x = clamp_bot(0.f, point.pixel_shift.x);
|
||||||
|
@ -485,18 +472,14 @@ internal Vec2_f32
|
||||||
file_buffer_point_difference(Thread_Context *tctx, Models *models, Editing_File *file,
|
file_buffer_point_difference(Thread_Context *tctx, Models *models, Editing_File *file,
|
||||||
Layout_Function *layout_func, f32 width, Face *face,
|
Layout_Function *layout_func, f32 width, Face *face,
|
||||||
Buffer_Point a, Buffer_Point b){
|
Buffer_Point a, Buffer_Point b){
|
||||||
f32 y_difference = file_line_y_difference(tctx, models, file,
|
f32 y_difference = file_line_y_difference(tctx, models, file, layout_func, width, face, a.line_number, b.line_number);
|
||||||
layout_func, width, face,
|
|
||||||
a.line_number, b.line_number);
|
|
||||||
Vec2_f32 result = a.pixel_shift - b.pixel_shift;
|
Vec2_f32 result = a.pixel_shift - b.pixel_shift;
|
||||||
result.y += y_difference;
|
result.y += y_difference;
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal Line_Shift_Character
|
internal Line_Shift_Character
|
||||||
file_line_shift_characters(Thread_Context *tctx, Models *models, Editing_File *file,
|
file_line_shift_characters(Thread_Context *tctx, Models *models, Editing_File *file, Layout_Function *layout_func, f32 width, Face *face, i64 line_number, i64 character_delta){
|
||||||
Layout_Function *layout_func, f32 width, Face *face,
|
|
||||||
i64 line_number, i64 character_delta){
|
|
||||||
Line_Shift_Character result = {};
|
Line_Shift_Character result = {};
|
||||||
|
|
||||||
i64 line_character = 0;
|
i64 line_character = 0;
|
||||||
|
@ -516,9 +499,7 @@ file_line_shift_characters(Thread_Context *tctx, Models *models, Editing_File *f
|
||||||
line_number = 1;
|
line_number = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Layout_Item_List line = file_get_line_layout(tctx, models, file,
|
Layout_Item_List line = file_get_line_layout(tctx, models, file, layout_func, width, face, line_number);
|
||||||
layout_func, width, face,
|
|
||||||
line_number);
|
|
||||||
line_character -= line.character_count;
|
line_character -= line.character_count;
|
||||||
}
|
}
|
||||||
if (!has_result){
|
if (!has_result){
|
||||||
|
@ -531,9 +512,7 @@ file_line_shift_characters(Thread_Context *tctx, Models *models, Editing_File *f
|
||||||
b32 has_result = false;
|
b32 has_result = false;
|
||||||
i64 line_count = buffer_line_count(&file->state.buffer);
|
i64 line_count = buffer_line_count(&file->state.buffer);
|
||||||
for (;;line_number += 1){
|
for (;;line_number += 1){
|
||||||
Layout_Item_List line = file_get_line_layout(tctx, models, file,
|
Layout_Item_List line = file_get_line_layout(tctx, models, file, layout_func, width, face, line_number);
|
||||||
layout_func, width, face,
|
|
||||||
line_number);
|
|
||||||
i64 next_character = line_character + line.character_count;
|
i64 next_character = line_character + line.character_count;
|
||||||
if (character_delta < next_character){
|
if (character_delta < next_character){
|
||||||
has_result = true;
|
has_result = true;
|
||||||
|
@ -556,15 +535,12 @@ file_line_shift_characters(Thread_Context *tctx, Models *models, Editing_File *f
|
||||||
}
|
}
|
||||||
|
|
||||||
internal i64
|
internal i64
|
||||||
file_line_character_difference(Thread_Context *tctx, Models *models, Editing_File *file,
|
file_line_character_difference(Thread_Context *tctx, Models *models, Editing_File *file, Layout_Function *layout_func, f32 width, Face *face, i64 line_a, i64 line_b){
|
||||||
Layout_Function *layout_func, f32 width, Face *face,
|
|
||||||
i64 line_a, i64 line_b){
|
|
||||||
i64 result = 0;
|
i64 result = 0;
|
||||||
if (line_a != line_b){
|
if (line_a != line_b){
|
||||||
Interval_i64 line_range = Ii64(line_a, line_b);
|
Interval_i64 line_range = Ii64(line_a, line_b);
|
||||||
for (i64 i = line_range.min; i < line_range.max; i += 1){
|
for (i64 i = line_range.min; i < line_range.max; i += 1){
|
||||||
Layout_Item_List line = file_get_line_layout(tctx, models, file,
|
Layout_Item_List line = file_get_line_layout(tctx, models, file, layout_func, width, face, i);
|
||||||
layout_func, width, face, i);
|
|
||||||
result += line.character_count;
|
result += line.character_count;
|
||||||
}
|
}
|
||||||
if (line_a < line_b){
|
if (line_a < line_b){
|
||||||
|
@ -578,26 +554,19 @@ internal i64
|
||||||
file_pos_from_relative_character(Thread_Context *tctx, Models *models, Editing_File *file,
|
file_pos_from_relative_character(Thread_Context *tctx, Models *models, Editing_File *file,
|
||||||
Layout_Function *layout_func, f32 width, Face *face,
|
Layout_Function *layout_func, f32 width, Face *face,
|
||||||
i64 base_line, i64 relative_character){
|
i64 base_line, i64 relative_character){
|
||||||
Line_Shift_Character shift = file_line_shift_characters(tctx, models, file,
|
Line_Shift_Character shift = file_line_shift_characters(tctx, models, file, layout_func, width, face, base_line, relative_character);
|
||||||
layout_func, width, face,
|
|
||||||
base_line, relative_character);
|
|
||||||
relative_character -= shift.character_delta;
|
relative_character -= shift.character_delta;
|
||||||
Layout_Item_List line = file_get_line_layout(tctx, models, file,
|
Layout_Item_List line = file_get_line_layout(tctx, models, file, layout_func, width, face, shift.line);
|
||||||
layout_func, width, face,
|
return(layout_get_pos_at_character(line, relative_character));
|
||||||
shift.line);
|
|
||||||
return(buffer_layout_get_pos_at_character(line, relative_character));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal i64
|
internal i64
|
||||||
file_relative_character_from_pos(Thread_Context *tctx, Models *models, Editing_File *file, Layout_Function *layout_func, f32 width, Face *face,
|
file_relative_character_from_pos(Thread_Context *tctx, Models *models, Editing_File *file, Layout_Function *layout_func, f32 width, Face *face,
|
||||||
i64 base_line, i64 pos){
|
i64 base_line, i64 pos){
|
||||||
i64 line_number = buffer_get_line_index(&file->state.buffer, pos) + 1;
|
i64 line_number = buffer_get_line_index(&file->state.buffer, pos) + 1;
|
||||||
Layout_Item_List line = file_get_line_layout(tctx, models, file,
|
Layout_Item_List line = file_get_line_layout(tctx, models, file, layout_func, width, face, line_number);
|
||||||
layout_func, width, face,
|
i64 result = layout_character_from_pos(line, pos);
|
||||||
line_number);
|
result += file_line_character_difference(tctx, models, file, layout_func, width, face, line_number, base_line);
|
||||||
i64 result = buffer_layout_character_from_pos(line, pos);
|
|
||||||
result += file_line_character_difference(tctx, models, file,
|
|
||||||
layout_func, width, face, line_number, base_line);
|
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -225,16 +225,16 @@ generic_parse_init(Application_Links *app, Arena *arena, String_Const_u8 content
|
||||||
}
|
}
|
||||||
|
|
||||||
function Code_Index_Nest*
|
function Code_Index_Nest*
|
||||||
generic_parse_preprocessor(Code_Index_File *index, Generic_Parse_State *state, i64 indentation);
|
generic_parse_preprocessor(Code_Index_File *index, Generic_Parse_State *state);
|
||||||
|
|
||||||
function Code_Index_Nest*
|
function Code_Index_Nest*
|
||||||
generic_parse_scope(Code_Index_File *index, Generic_Parse_State *state, i64 indentation);
|
generic_parse_scope(Code_Index_File *index, Generic_Parse_State *state);
|
||||||
|
|
||||||
function Code_Index_Nest*
|
function Code_Index_Nest*
|
||||||
generic_parse_paren(Code_Index_File *index, Generic_Parse_State *state, i64 indentation);
|
generic_parse_paren(Code_Index_File *index, Generic_Parse_State *state);
|
||||||
|
|
||||||
function Code_Index_Nest*
|
function Code_Index_Nest*
|
||||||
generic_parse_statement(Code_Index_File *index, Generic_Parse_State *state, i64 indentation){
|
generic_parse_statement(Code_Index_File *index, Generic_Parse_State *state){
|
||||||
Token *token = token_it_read(&state->it);
|
Token *token = token_it_read(&state->it);
|
||||||
Code_Index_Nest *result = push_array_zero(state->arena, Code_Index_Nest, 1);
|
Code_Index_Nest *result = push_array_zero(state->arena, Code_Index_Nest, 1);
|
||||||
result->kind = CodeIndexNest_Statement;
|
result->kind = CodeIndexNest_Statement;
|
||||||
|
@ -242,10 +242,6 @@ generic_parse_statement(Code_Index_File *index, Generic_Parse_State *state, i64
|
||||||
result->close = Ii64(max_i64);
|
result->close = Ii64(max_i64);
|
||||||
result->file = index;
|
result->file = index;
|
||||||
|
|
||||||
result->open_indentation = indentation;
|
|
||||||
result->interior_indentation = indentation + 4;
|
|
||||||
result->close_indentation = indentation + 4;
|
|
||||||
|
|
||||||
state->in_statement = true;
|
state->in_statement = true;
|
||||||
|
|
||||||
for (;;){
|
for (;;){
|
||||||
|
@ -296,7 +292,7 @@ generic_parse_statement(Code_Index_File *index, Generic_Parse_State *state, i64
|
||||||
}
|
}
|
||||||
|
|
||||||
function Code_Index_Nest*
|
function Code_Index_Nest*
|
||||||
generic_parse_preprocessor(Code_Index_File *index, Generic_Parse_State *state, i64 indentation){
|
generic_parse_preprocessor(Code_Index_File *index, Generic_Parse_State *state){
|
||||||
Token *token = token_it_read(&state->it);
|
Token *token = token_it_read(&state->it);
|
||||||
Code_Index_Nest *result = push_array_zero(state->arena, Code_Index_Nest, 1);
|
Code_Index_Nest *result = push_array_zero(state->arena, Code_Index_Nest, 1);
|
||||||
result->kind = CodeIndexNest_Preprocessor;
|
result->kind = CodeIndexNest_Preprocessor;
|
||||||
|
@ -304,11 +300,6 @@ generic_parse_preprocessor(Code_Index_File *index, Generic_Parse_State *state, i
|
||||||
result->close = Ii64(max_i64);
|
result->close = Ii64(max_i64);
|
||||||
result->file = index;
|
result->file = index;
|
||||||
|
|
||||||
result->open_indentation = 0;
|
|
||||||
result->interior_indentation = 0;
|
|
||||||
result->close_indentation = 0;
|
|
||||||
indentation = 0;
|
|
||||||
|
|
||||||
state->in_preprocessor = true;
|
state->in_preprocessor = true;
|
||||||
|
|
||||||
generic_parse_inc(state);
|
generic_parse_inc(state);
|
||||||
|
@ -327,14 +318,14 @@ generic_parse_preprocessor(Code_Index_File *index, Generic_Parse_State *state, i
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token->kind == TokenBaseKind_ScopeOpen){
|
if (token->kind == TokenBaseKind_ScopeOpen){
|
||||||
Code_Index_Nest *nest = generic_parse_scope(index, state, indentation);
|
Code_Index_Nest *nest = generic_parse_scope(index, state);
|
||||||
nest->parent = result;
|
nest->parent = result;
|
||||||
code_index_push_nest(&result->nest_list, nest);
|
code_index_push_nest(&result->nest_list, nest);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token->kind == TokenBaseKind_ParentheticalOpen){
|
if (token->kind == TokenBaseKind_ParentheticalOpen){
|
||||||
Code_Index_Nest *nest = generic_parse_paren(index, state, indentation);
|
Code_Index_Nest *nest = generic_parse_paren(index, state);
|
||||||
nest->parent = result;
|
nest->parent = result;
|
||||||
code_index_push_nest(&result->nest_list, nest);
|
code_index_push_nest(&result->nest_list, nest);
|
||||||
continue;
|
continue;
|
||||||
|
@ -351,7 +342,7 @@ generic_parse_preprocessor(Code_Index_File *index, Generic_Parse_State *state, i
|
||||||
}
|
}
|
||||||
|
|
||||||
function Code_Index_Nest*
|
function Code_Index_Nest*
|
||||||
generic_parse_scope(Code_Index_File *index, Generic_Parse_State *state, i64 indentation){
|
generic_parse_scope(Code_Index_File *index, Generic_Parse_State *state){
|
||||||
Token *token = token_it_read(&state->it);
|
Token *token = token_it_read(&state->it);
|
||||||
Code_Index_Nest *result = push_array_zero(state->arena, Code_Index_Nest, 1);
|
Code_Index_Nest *result = push_array_zero(state->arena, Code_Index_Nest, 1);
|
||||||
result->kind = CodeIndexNest_Scope;
|
result->kind = CodeIndexNest_Scope;
|
||||||
|
@ -359,11 +350,6 @@ generic_parse_scope(Code_Index_File *index, Generic_Parse_State *state, i64 inde
|
||||||
result->close = Ii64(max_i64);
|
result->close = Ii64(max_i64);
|
||||||
result->file = index;
|
result->file = index;
|
||||||
|
|
||||||
result->open_indentation = indentation;
|
|
||||||
result->interior_indentation = indentation + 4;
|
|
||||||
result->close_indentation = indentation;
|
|
||||||
indentation = result->interior_indentation;
|
|
||||||
|
|
||||||
state->scope_counter += 1;
|
state->scope_counter += 1;
|
||||||
|
|
||||||
generic_parse_inc(state);
|
generic_parse_inc(state);
|
||||||
|
@ -382,7 +368,7 @@ generic_parse_scope(Code_Index_File *index, Generic_Parse_State *state, i64 inde
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
if (token->kind == TokenBaseKind_Preprocessor){
|
if (token->kind == TokenBaseKind_Preprocessor){
|
||||||
Code_Index_Nest *nest = generic_parse_preprocessor(index, state, indentation);
|
Code_Index_Nest *nest = generic_parse_preprocessor(index, state);
|
||||||
code_index_push_nest(&index->nest_list, nest);
|
code_index_push_nest(&index->nest_list, nest);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -396,14 +382,14 @@ generic_parse_scope(Code_Index_File *index, Generic_Parse_State *state, i64 inde
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token->kind == TokenBaseKind_ScopeOpen){
|
if (token->kind == TokenBaseKind_ScopeOpen){
|
||||||
Code_Index_Nest *nest = generic_parse_scope(index, state, indentation);
|
Code_Index_Nest *nest = generic_parse_scope(index, state);
|
||||||
nest->parent = result;
|
nest->parent = result;
|
||||||
code_index_push_nest(&result->nest_list, nest);
|
code_index_push_nest(&result->nest_list, nest);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token->kind == TokenBaseKind_ParentheticalOpen){
|
if (token->kind == TokenBaseKind_ParentheticalOpen){
|
||||||
Code_Index_Nest *nest = generic_parse_paren(index, state, indentation);
|
Code_Index_Nest *nest = generic_parse_paren(index, state);
|
||||||
nest->parent = result;
|
nest->parent = result;
|
||||||
code_index_push_nest(&result->nest_list, nest);
|
code_index_push_nest(&result->nest_list, nest);
|
||||||
continue;
|
continue;
|
||||||
|
@ -415,7 +401,7 @@ generic_parse_scope(Code_Index_File *index, Generic_Parse_State *state, i64 inde
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Code_Index_Nest *nest = generic_parse_statement(index, state, indentation);
|
Code_Index_Nest *nest = generic_parse_statement(index, state);
|
||||||
nest->parent = result;
|
nest->parent = result;
|
||||||
code_index_push_nest(&result->nest_list, nest);
|
code_index_push_nest(&result->nest_list, nest);
|
||||||
}
|
}
|
||||||
|
@ -429,7 +415,7 @@ generic_parse_scope(Code_Index_File *index, Generic_Parse_State *state, i64 inde
|
||||||
}
|
}
|
||||||
|
|
||||||
function Code_Index_Nest*
|
function Code_Index_Nest*
|
||||||
generic_parse_paren(Code_Index_File *index, Generic_Parse_State *state, i64 indentation){
|
generic_parse_paren(Code_Index_File *index, Generic_Parse_State *state){
|
||||||
Token *token = token_it_read(&state->it);
|
Token *token = token_it_read(&state->it);
|
||||||
Code_Index_Nest *result = push_array_zero(state->arena, Code_Index_Nest, 1);
|
Code_Index_Nest *result = push_array_zero(state->arena, Code_Index_Nest, 1);
|
||||||
result->kind = CodeIndexNest_Paren;
|
result->kind = CodeIndexNest_Paren;
|
||||||
|
@ -451,12 +437,6 @@ generic_parse_paren(Code_Index_File *index, Generic_Parse_State *state, i64 inde
|
||||||
manifested_characters_on_line = (i64)(end_ptr - ptr) + token->size;
|
manifested_characters_on_line = (i64)(end_ptr - ptr) + token->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
indentation += manifested_characters_on_line;
|
|
||||||
|
|
||||||
result->open_indentation = indentation;
|
|
||||||
result->interior_indentation = indentation;
|
|
||||||
result->close_indentation = indentation;
|
|
||||||
|
|
||||||
state->paren_counter += 1;
|
state->paren_counter += 1;
|
||||||
|
|
||||||
generic_parse_inc(state);
|
generic_parse_inc(state);
|
||||||
|
@ -475,7 +455,7 @@ generic_parse_paren(Code_Index_File *index, Generic_Parse_State *state, i64 inde
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
if (token->kind == TokenBaseKind_Preprocessor){
|
if (token->kind == TokenBaseKind_Preprocessor){
|
||||||
Code_Index_Nest *nest = generic_parse_preprocessor(index, state, indentation);
|
Code_Index_Nest *nest = generic_parse_preprocessor(index, state);
|
||||||
code_index_push_nest(&index->nest_list, nest);
|
code_index_push_nest(&index->nest_list, nest);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -493,14 +473,14 @@ generic_parse_paren(Code_Index_File *index, Generic_Parse_State *state, i64 inde
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token->kind == TokenBaseKind_ScopeOpen){
|
if (token->kind == TokenBaseKind_ScopeOpen){
|
||||||
Code_Index_Nest *nest = generic_parse_scope(index, state, indentation);
|
Code_Index_Nest *nest = generic_parse_scope(index, state);
|
||||||
nest->parent = result;
|
nest->parent = result;
|
||||||
code_index_push_nest(&result->nest_list, nest);
|
code_index_push_nest(&result->nest_list, nest);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token->kind == TokenBaseKind_ParentheticalOpen){
|
if (token->kind == TokenBaseKind_ParentheticalOpen){
|
||||||
Code_Index_Nest *nest = generic_parse_paren(index, state, indentation);
|
Code_Index_Nest *nest = generic_parse_paren(index, state);
|
||||||
nest->parent = result;
|
nest->parent = result;
|
||||||
code_index_push_nest(&result->nest_list, nest);
|
code_index_push_nest(&result->nest_list, nest);
|
||||||
continue;
|
continue;
|
||||||
|
@ -520,7 +500,6 @@ function b32
|
||||||
generic_parse_full_input_breaks(Code_Index_File *index, Generic_Parse_State *state, i32 limit){
|
generic_parse_full_input_breaks(Code_Index_File *index, Generic_Parse_State *state, i32 limit){
|
||||||
b32 result = false;
|
b32 result = false;
|
||||||
|
|
||||||
i64 indentation = 0;
|
|
||||||
i64 first_index = token_it_index(&state->it);
|
i64 first_index = token_it_index(&state->it);
|
||||||
i64 one_past_last_index = first_index + limit;
|
i64 one_past_last_index = first_index + limit;
|
||||||
for (;;){
|
for (;;){
|
||||||
|
@ -533,15 +512,15 @@ generic_parse_full_input_breaks(Code_Index_File *index, Generic_Parse_State *sta
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token->kind == TokenBaseKind_Preprocessor){
|
if (token->kind == TokenBaseKind_Preprocessor){
|
||||||
Code_Index_Nest *nest = generic_parse_preprocessor(index, state, indentation);
|
Code_Index_Nest *nest = generic_parse_preprocessor(index, state);
|
||||||
code_index_push_nest(&index->nest_list, nest);
|
code_index_push_nest(&index->nest_list, nest);
|
||||||
}
|
}
|
||||||
else if (token->kind == TokenBaseKind_ScopeOpen){
|
else if (token->kind == TokenBaseKind_ScopeOpen){
|
||||||
Code_Index_Nest *nest = generic_parse_scope(index, state, indentation);
|
Code_Index_Nest *nest = generic_parse_scope(index, state);
|
||||||
code_index_push_nest(&index->nest_list, nest);
|
code_index_push_nest(&index->nest_list, nest);
|
||||||
}
|
}
|
||||||
else if (token->kind == TokenBaseKind_ParentheticalOpen){
|
else if (token->kind == TokenBaseKind_ParentheticalOpen){
|
||||||
Code_Index_Nest *nest = generic_parse_paren(index, state, indentation);
|
Code_Index_Nest *nest = generic_parse_paren(index, state);
|
||||||
code_index_push_nest(&index->nest_list, nest);
|
code_index_push_nest(&index->nest_list, nest);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
@ -580,28 +559,49 @@ generic_parse_init(Application_Links *app, Arena *arena, String_Const_u8 content
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
||||||
function i64
|
function f32
|
||||||
layout_index_indent(Code_Index_File *file, i64 pos){
|
layout_index_x_shift(Application_Links *app, Layout_Reflex *reflex, Code_Index_Nest *nest, i64 pos, f32 space_advance){
|
||||||
i64 indent = 0;
|
f32 result = 0.f;
|
||||||
Code_Index_Nest *nest = code_index_get_nest(file, pos);
|
|
||||||
if (nest != 0){
|
if (nest != 0){
|
||||||
if (pos == nest->open.min && pos == nest->open.max){
|
switch (nest->kind){
|
||||||
indent = nest->open_indentation;
|
case CodeIndexNest_Scope:
|
||||||
|
case CodeIndexNest_Preprocessor:
|
||||||
|
{
|
||||||
|
|
||||||
|
result = layout_index_x_shift(app, reflex, nest->parent, pos, space_advance);
|
||||||
|
if (nest->open.min < pos && nest->open.max <= pos &&
|
||||||
|
(!nest->is_closed || pos < nest->close.min)){
|
||||||
|
result += 4.f*space_advance;
|
||||||
}
|
}
|
||||||
else if (pos == nest->close.min){
|
}break;
|
||||||
indent = nest->close_indentation;
|
|
||||||
|
case CodeIndexNest_Statement:
|
||||||
|
{
|
||||||
|
result = layout_index_x_shift(app, reflex, nest->parent, pos, space_advance);
|
||||||
|
if (nest->open.min < pos && nest->open.max <= pos &&
|
||||||
|
(!nest->is_closed || pos < nest->close.min)){
|
||||||
|
result += 4.f*space_advance;
|
||||||
}
|
}
|
||||||
else{
|
}break;
|
||||||
indent = nest->interior_indentation;
|
|
||||||
|
case CodeIndexNest_Paren:
|
||||||
|
{
|
||||||
|
Rect_f32 box = layout_reflex_get_rect(app, reflex, nest->open.max - 1);
|
||||||
|
result = box.x1;
|
||||||
|
}break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return(indent);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
function f32
|
function f32
|
||||||
layout_index_x_shift(Code_Index_File *file, i64 pos, f32 space_advance){
|
layout_index_x_shift(Application_Links *app, Layout_Reflex *reflex, Code_Index_File *file, i64 pos, f32 space_advance){
|
||||||
i64 indent = layout_index_indent(file, pos);
|
f32 indent = 0;
|
||||||
return(((f32)indent)*space_advance);
|
Code_Index_Nest *nest = code_index_get_nest(file, pos);
|
||||||
|
if (nest != 0){
|
||||||
|
indent = layout_index_x_shift(app, reflex, nest, pos, space_advance);
|
||||||
|
}
|
||||||
|
return(indent);
|
||||||
}
|
}
|
||||||
|
|
||||||
function Layout_Item_List
|
function Layout_Item_List
|
||||||
|
@ -617,6 +617,8 @@ layout_index_unwrapped__inner(Application_Links *app, Arena *arena, Buffer_ID bu
|
||||||
|
|
||||||
f32 wrap_align_x = width - metrics.normal_advance;
|
f32 wrap_align_x = width - metrics.normal_advance;
|
||||||
|
|
||||||
|
Layout_Reflex reflex = get_layout_reflex(&list, buffer, width, face);
|
||||||
|
|
||||||
if (text.size == 0){
|
if (text.size == 0){
|
||||||
lr_tb_write_blank(&pos_vars, arena, &list, range.start);
|
lr_tb_write_blank(&pos_vars, arena, &list, range.start);
|
||||||
}
|
}
|
||||||
|
@ -681,13 +683,13 @@ layout_index_unwrapped__inner(Application_Links *app, Arena *arena, Buffer_ID bu
|
||||||
lr_tb_write_ghost(&pos_vars, arena, &list, index, '\\');
|
lr_tb_write_ghost(&pos_vars, arena, &list, index, '\\');
|
||||||
|
|
||||||
lr_tb_next_line(&pos_vars);
|
lr_tb_next_line(&pos_vars);
|
||||||
f32 shift = layout_index_x_shift(file, index, metrics.space_advance);
|
f32 shift = layout_index_x_shift(app, &reflex, file, index, metrics.space_advance);
|
||||||
lr_tb_advance_x_without_item(&pos_vars, shift);
|
lr_tb_advance_x_without_item(&pos_vars, shift);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
i64 index = layout_index_from_ptr(word.str, text.str, range.first);
|
i64 index = layout_index_from_ptr(word.str, text.str, range.first);
|
||||||
f32 shift = layout_index_x_shift(file, index, metrics.space_advance);
|
f32 shift = layout_index_x_shift(app, &reflex, file, index, metrics.space_advance);
|
||||||
lr_tb_advance_x_without_item(&pos_vars, shift);
|
lr_tb_advance_x_without_item(&pos_vars, shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -735,7 +737,7 @@ layout_index_unwrapped__inner(Application_Links *app, Arena *arena, Buffer_ID bu
|
||||||
case '\n':
|
case '\n':
|
||||||
{
|
{
|
||||||
if (first_of_the_line){
|
if (first_of_the_line){
|
||||||
f32 shift = layout_index_x_shift(file, index,
|
f32 shift = layout_index_x_shift(app, &reflex, file, index,
|
||||||
metrics.space_advance);
|
metrics.space_advance);
|
||||||
lr_tb_advance_x_without_item(&pos_vars, shift);
|
lr_tb_advance_x_without_item(&pos_vars, shift);
|
||||||
}
|
}
|
||||||
|
@ -754,7 +756,7 @@ layout_index_unwrapped__inner(Application_Links *app, Arena *arena, Buffer_ID bu
|
||||||
if (newline_layout_consume_finish(&newline_vars)){
|
if (newline_layout_consume_finish(&newline_vars)){
|
||||||
i64 index = layout_index_from_ptr(ptr, text.str, range.first);
|
i64 index = layout_index_from_ptr(ptr, text.str, range.first);
|
||||||
if (first_of_the_line){
|
if (first_of_the_line){
|
||||||
f32 shift = layout_index_x_shift(file, index,
|
f32 shift = layout_index_x_shift(app, &reflex, file, index,
|
||||||
metrics.space_advance);
|
metrics.space_advance);
|
||||||
lr_tb_advance_x_without_item(&pos_vars, shift);
|
lr_tb_advance_x_without_item(&pos_vars, shift);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,10 +34,6 @@ struct Code_Index_Nest{
|
||||||
Range_i64 open;
|
Range_i64 open;
|
||||||
Range_i64 close;
|
Range_i64 close;
|
||||||
|
|
||||||
i64 open_indentation;
|
|
||||||
i64 interior_indentation;
|
|
||||||
i64 close_indentation;
|
|
||||||
|
|
||||||
struct Code_Index_File *file;
|
struct Code_Index_File *file;
|
||||||
Code_Index_Nest *parent;
|
Code_Index_Nest *parent;
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,7 @@
|
||||||
#define DYNAMIC_LINK_API
|
#define DYNAMIC_LINK_API
|
||||||
#include "generated/system_api.cpp"
|
#include "generated/system_api.cpp"
|
||||||
#include "4coder_system_helpers.cpp"
|
#include "4coder_system_helpers.cpp"
|
||||||
|
#include "4coder_layout.cpp"
|
||||||
#include "4coder_profile.cpp"
|
#include "4coder_profile.cpp"
|
||||||
#include "4coder_profile_static_enable.cpp"
|
#include "4coder_profile_static_enable.cpp"
|
||||||
#include "4coder_events.cpp"
|
#include "4coder_events.cpp"
|
||||||
|
|
|
@ -0,0 +1,237 @@
|
||||||
|
/*
|
||||||
|
4coder_layout.cpp - Implementation of basic lookup routines on line layout data.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TOP
|
||||||
|
|
||||||
|
internal i64
|
||||||
|
layout_nearest_pos_to_xy(Layout_Item_List list, Vec2_f32 p){
|
||||||
|
i64 closest_match = 0;
|
||||||
|
if (p.y < 0.f){
|
||||||
|
closest_match = list.manifested_index_range.min;
|
||||||
|
}
|
||||||
|
else if (p.y >= list.height){
|
||||||
|
closest_match = list.manifested_index_range.max;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if (0.f < p.x && p.x < max_f32){
|
||||||
|
f32 bottom_padding = list.bottom_padding;
|
||||||
|
f32 closest_x = -max_f32;
|
||||||
|
for (Layout_Item_Block *block = list.first;
|
||||||
|
block != 0;
|
||||||
|
block = block->next){
|
||||||
|
i64 count = block->item_count;
|
||||||
|
Layout_Item *item = block->items;
|
||||||
|
for (i32 i = 0; i < count; i += 1, item += 1){
|
||||||
|
if (HasFlag(item->flags, LayoutItemFlag_Ghost_Character)){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// NOTE(allen): This only works if we build layouts in y-sorted order.
|
||||||
|
if (p.y < item->rect.y0){
|
||||||
|
goto double_break;
|
||||||
|
}
|
||||||
|
if (item->rect.y1 + bottom_padding <= p.y){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
f32 dist0 = p.x - item->rect.x0;
|
||||||
|
f32 dist1 = item->rect.x1 - p.x;
|
||||||
|
if (dist0 >= 0.f && dist1 > 0.f){
|
||||||
|
closest_match = item->index;
|
||||||
|
goto double_break;
|
||||||
|
}
|
||||||
|
// NOTE(allen): One of dist0 and dist1 are negative, but certainly not both.
|
||||||
|
// 1. Take the negative one.
|
||||||
|
// 2. If the negative distance is larger than closest_x, then this is closer.
|
||||||
|
f32 neg_dist = min(dist0, dist1);
|
||||||
|
if (closest_x < neg_dist){
|
||||||
|
closest_x = neg_dist;
|
||||||
|
closest_match = item->index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
double_break:;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
|
||||||
|
if (p.x == max_f32){
|
||||||
|
Layout_Item *prev_item = 0;
|
||||||
|
for (Layout_Item_Block *block = list.first;
|
||||||
|
block != 0;
|
||||||
|
block = block->next){
|
||||||
|
i64 count = block->item_count;
|
||||||
|
Layout_Item *item = block->items;
|
||||||
|
for (i32 i = 0; i < count; i += 1, item += 1){
|
||||||
|
if (HasFlag(item->flags, LayoutItemFlag_Ghost_Character)){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (p.y < item->rect.y0){
|
||||||
|
goto double_break_2;
|
||||||
|
}
|
||||||
|
prev_item = item;
|
||||||
|
if (item->rect.y1 <= p.y){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double_break_2:;
|
||||||
|
if (prev_item != 0){
|
||||||
|
closest_match = prev_item->index;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
closest_match = list.manifested_index_range.max;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
Layout_Item *closest_item = 0;
|
||||||
|
for (Layout_Item_Block *block = list.first;
|
||||||
|
block != 0;
|
||||||
|
block = block->next){
|
||||||
|
i64 count = block->item_count;
|
||||||
|
Layout_Item *item = block->items;
|
||||||
|
for (i32 i = 0; i < count; i += 1, item += 1){
|
||||||
|
if (HasFlag(item->flags, LayoutItemFlag_Ghost_Character)){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// NOTE(allen): This only works if we build layouts in y-sorted order.
|
||||||
|
if (p.y < item->rect.y0){
|
||||||
|
goto double_break_3;
|
||||||
|
}
|
||||||
|
if (item->rect.y1 <= p.y){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
closest_item = item;
|
||||||
|
goto double_break_3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double_break_3:;
|
||||||
|
if (closest_item != 0){
|
||||||
|
closest_match = closest_item->index;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
closest_match = list.manifested_index_range.min;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(closest_match);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Layout_Item*
|
||||||
|
layout_get_first_with_index(Layout_Item_List list, i64 index){
|
||||||
|
Layout_Item *result = 0;
|
||||||
|
Layout_Item *prev = 0;
|
||||||
|
for (Layout_Item_Block *block = list.first;
|
||||||
|
block != 0;
|
||||||
|
block = block->next){
|
||||||
|
i64 count = block->item_count;
|
||||||
|
Layout_Item *item = block->items;
|
||||||
|
for (i32 i = 0; i < count; i += 1, item += 1){
|
||||||
|
if (HasFlag(item->flags, LayoutItemFlag_Ghost_Character)){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (item->index > index){
|
||||||
|
result = prev;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (item->index == index){
|
||||||
|
result = item;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
prev = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (result == 0){
|
||||||
|
result = prev;
|
||||||
|
}
|
||||||
|
done:;
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Rect_f32
|
||||||
|
layout_box_of_pos(Layout_Item_List list, i64 index){
|
||||||
|
Rect_f32 result = {};
|
||||||
|
Layout_Item *item = layout_get_first_with_index(list, index);
|
||||||
|
if (item != 0){
|
||||||
|
result = item->rect;
|
||||||
|
}
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal i64
|
||||||
|
layout_get_pos_at_character(Layout_Item_List list, i64 character){
|
||||||
|
i64 result = 0;
|
||||||
|
if (character <= 0){
|
||||||
|
result = list.manifested_index_range.min;
|
||||||
|
}
|
||||||
|
else if (character >= list.character_count){
|
||||||
|
result = list.manifested_index_range.max;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
i64 counter = 0;
|
||||||
|
i64 next_counter = 0;
|
||||||
|
for (Layout_Item_Block *node = list.first;
|
||||||
|
node != 0;
|
||||||
|
node = node->next, counter = next_counter){
|
||||||
|
next_counter = counter + node->character_count;
|
||||||
|
if (character >= next_counter){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
i64 count = node->item_count;
|
||||||
|
i64 relative_character = character - counter;
|
||||||
|
i64 relative_character_counter = 0;
|
||||||
|
|
||||||
|
Layout_Item *item = node->items;
|
||||||
|
for (i64 i = 0; i < count; i += 1, item += 1){
|
||||||
|
if (HasFlag(item->flags, LayoutItemFlag_Ghost_Character)){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (relative_character_counter == relative_character){
|
||||||
|
result = item->index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
relative_character_counter += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal i64
|
||||||
|
layout_character_from_pos(Layout_Item_List list, i64 index){
|
||||||
|
i64 result = 0;
|
||||||
|
i64 prev_index = -1;
|
||||||
|
if (index <= list.manifested_index_range.first){
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
else if (index > list.manifested_index_range.one_past_last){
|
||||||
|
result = list.character_count - 1;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
for (Layout_Item_Block *node = list.first;
|
||||||
|
node != 0;
|
||||||
|
node = node->next){
|
||||||
|
Layout_Item *item = node->items;
|
||||||
|
i64 count = node->item_count;
|
||||||
|
for (i64 i = 0; i < count; i += 1, item += 1){
|
||||||
|
if (item->index >= index){
|
||||||
|
goto double_break;
|
||||||
|
}
|
||||||
|
if (item->index > prev_index){
|
||||||
|
prev_index = item->index;
|
||||||
|
result += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
double_break:;
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// BOTTOM
|
||||||
|
|
|
@ -4,6 +4,31 @@
|
||||||
|
|
||||||
// TOP
|
// TOP
|
||||||
|
|
||||||
|
function Layout_Reflex
|
||||||
|
get_layout_reflex(Layout_Item_List *list, Buffer_ID buffer, f32 width, Face_ID face){
|
||||||
|
Layout_Reflex reflex = {};
|
||||||
|
reflex.list = list;
|
||||||
|
reflex.buffer = buffer;
|
||||||
|
reflex.width = width;
|
||||||
|
reflex.face = face;
|
||||||
|
return(reflex);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Rect_f32
|
||||||
|
layout_reflex_get_rect(Application_Links *app, Layout_Reflex *reflex, i64 pos){
|
||||||
|
Rect_f32 rect = {};
|
||||||
|
if (range_contains(reflex->list->input_index_range, pos)){
|
||||||
|
rect = layout_box_of_pos(*reflex->list, pos);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
Buffer_Cursor cursor = buffer_compute_cursor(app, reflex->buffer, seek_pos(pos));
|
||||||
|
rect = buffer_relative_box_of_pos(app, reflex->buffer, reflex->width, reflex->face, cursor.line, cursor.pos);
|
||||||
|
}
|
||||||
|
return(rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
|
||||||
function i64
|
function i64
|
||||||
layout_index_from_ptr(u8 *ptr, u8 *string_base, i64 index_base){
|
layout_index_from_ptr(u8 *ptr, u8 *string_base, i64 index_base){
|
||||||
return((i64)(ptr - string_base) + index_base);
|
return((i64)(ptr - string_base) + index_base);
|
||||||
|
|
|
@ -26,6 +26,13 @@ struct LefRig_TopBot_Layout_Vars{
|
||||||
f32 width;
|
f32 width;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Layout_Reflex{
|
||||||
|
Layout_Item_List *list;
|
||||||
|
Buffer_ID buffer;
|
||||||
|
f32 width;
|
||||||
|
Face_ID face;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// BOTTOM
|
// BOTTOM
|
||||||
|
|
|
@ -138,7 +138,7 @@ string_match_list_merge_nearest(String_Match_List *a, String_Match_List *b, Rang
|
||||||
|
|
||||||
internal String_Match_List
|
internal String_Match_List
|
||||||
string_match_list_merge_front_to_back(String_Match_List *a, String_Match_List *b){
|
string_match_list_merge_front_to_back(String_Match_List *a, String_Match_List *b){
|
||||||
return(string_match_list_merge_nearest(a, b, Ii64(0)));
|
return(string_match_list_merge_nearest(a, b, Ii64((i64)0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// BOTTOM
|
// BOTTOM
|
||||||
|
|
Loading…
Reference in New Issue