Layout with cool parantheses thing working

master
Allen Webster 2019-11-04 05:37:45 -08:00
parent 745ca37668
commit eb29349caf
12 changed files with 373 additions and 372 deletions

10
4ed.cpp
View File

@ -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_Preproc] = color_table.vals[Stag_Default];
color_table.vals[Stag_Special_Character] = 0xFFFF0000;
color_table.vals[Stag_Ghost_Character] = color_blend(color_table.vals[Stag_Default],
0.5f,
color_table.vals[Stag_Back]);
color_table.vals[Stag_Ghost_Character] = color_blend(color_table.vals[Stag_Default], 0.5f, color_table.vals[Stag_Back]);
color_table.vals[Stag_Paste] = 0xFFDDEE00;
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] == '-'){
char *long_arg_name = arg+2;
if (string_match(SCu8(long_arg_name),
string_u8_litexpr("custom"))){
if (string_match(SCu8(long_arg_name), string_u8_litexpr("custom"))){
mode = CLMode_Custom;
continue;
}
@ -625,8 +622,7 @@ App_Step_Sig(app_step){
b32 event_was_handled = false;
Input_Event *event = &node->event;
if (event->kind == InputEventKind_TextInsert &&
event->text.blocked){
if (event->kind == InputEventKind_TextInsert && event->text.blocked){
continue;
}

View File

@ -413,9 +413,7 @@ buffer_pos_at_relative_xy(Application_Links *app, Buffer_ID buffer_id,
}
api(custom) function Rect_f32
buffer_relative_box_of_pos(Application_Links *app, Buffer_ID buffer_id,
f32 width, Face_ID face_id,
i64 base_line, i64 pos){
buffer_relative_box_of_pos(Application_Links *app, Buffer_ID buffer_id, f32 width, Face_ID face_id, i64 base_line, i64 pos){
Models *models = (Models*)app->cmd_context;
Editing_File *file = imp_get_file(models, buffer_id);
Rect_f32 result = {};

View File

@ -61,6 +61,7 @@
////////////////////////////////
#include "4coder_base_types.cpp"
#include "4coder_layout.cpp"
#include "4coder_system_helpers.cpp"
#include "4coder_events.cpp"
#include "4coder_string_match.cpp"

View File

@ -854,236 +854,5 @@ buffer_chunk_position_iterate(String_Const_u8_Array chunks, Buffer_Chunk_Positio
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

View File

@ -413,8 +413,7 @@ file_line_y_difference(Thread_Context *tctx, Models *models, Editing_File *file,
if (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){
Layout_Item_List line = file_get_line_layout(tctx, models, file, layout_func,
width, face, i);
Layout_Item_List line = file_get_line_layout(tctx, models, file, layout_func, width, face, i);
result += line.height;
}
if (line_a < line_b){
@ -428,14 +427,10 @@ internal i64
file_pos_at_relative_xy(Thread_Context *tctx, Models *models, Editing_File *file,
Layout_Function *layout_func, f32 width, Face *face,
i64 base_line, Vec2_f32 relative_xy){
Line_Shift_Vertical shift = file_line_shift_y(tctx, models, file,
layout_func, width, face, base_line,
relative_xy.y);
Line_Shift_Vertical shift = file_line_shift_y(tctx, models, file, layout_func, width, face, base_line, relative_xy.y);
relative_xy.y -= shift.y_delta;
Layout_Item_List line = file_get_line_layout(tctx, models, file,
layout_func, width, face,
shift.line);
return(buffer_layout_nearest_pos_to_xy(line, relative_xy));
Layout_Item_List line = file_get_line_layout(tctx, models, file, layout_func, width, face, shift.line);
return(layout_nearest_pos_to_xy(line, relative_xy));
}
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,
i64 base_line, i64 pos){
i64 line_number = buffer_get_line_index(&file->state.buffer, pos) + 1;
Layout_Item_List line = file_get_line_layout(tctx, models, file,
layout_func, width, face,
line_number);
Rect_f32 result = buffer_layout_box_of_pos(line, pos);
Layout_Item_List line = file_get_line_layout(tctx, models, file, layout_func, width, face, line_number);
Rect_f32 result = layout_box_of_pos(line, pos);
f32 y_difference = file_line_y_difference(tctx, models, file,
layout_func, width, face,
line_number, base_line);
f32 y_difference = file_line_y_difference(tctx, models, file, layout_func, width, face, line_number, base_line);
result.y0 += 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,
Layout_Function *layout_func, f32 width, Face *face,
i64 base_line, i64 pos){
Rect_f32 rect = file_relative_box_of_pos(tctx, models, file,
layout_func, width, face,
base_line, pos);
Rect_f32 rect = file_relative_box_of_pos(tctx, models, file, layout_func, width, face, base_line, pos);
return(rect_center(rect));
}
@ -471,9 +460,7 @@ internal Buffer_Point
file_normalize_buffer_point(Thread_Context *tctx, Models *models, Editing_File *file,
Layout_Function *layout_func, f32 width, Face *face,
Buffer_Point point){
Line_Shift_Vertical shift = file_line_shift_y(tctx, models, file,
layout_func, width, face, point.line_number,
point.pixel_shift.y);
Line_Shift_Vertical shift = file_line_shift_y(tctx, models, file, layout_func, width, face, point.line_number, point.pixel_shift.y);
point.line_number = shift.line;
point.pixel_shift.y -= shift.y_delta;
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,
Layout_Function *layout_func, f32 width, Face *face,
Buffer_Point a, Buffer_Point b){
f32 y_difference = file_line_y_difference(tctx, models, file,
layout_func, width, face,
a.line_number, b.line_number);
f32 y_difference = file_line_y_difference(tctx, models, file, layout_func, width, face, a.line_number, b.line_number);
Vec2_f32 result = a.pixel_shift - b.pixel_shift;
result.y += y_difference;
return(result);
}
internal Line_Shift_Character
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){
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){
Line_Shift_Character result = {};
i64 line_character = 0;
@ -516,9 +499,7 @@ file_line_shift_characters(Thread_Context *tctx, Models *models, Editing_File *f
line_number = 1;
break;
}
Layout_Item_List line = file_get_line_layout(tctx, models, file,
layout_func, width, face,
line_number);
Layout_Item_List line = file_get_line_layout(tctx, models, file, layout_func, width, face, line_number);
line_character -= line.character_count;
}
if (!has_result){
@ -531,9 +512,7 @@ file_line_shift_characters(Thread_Context *tctx, Models *models, Editing_File *f
b32 has_result = false;
i64 line_count = buffer_line_count(&file->state.buffer);
for (;;line_number += 1){
Layout_Item_List line = file_get_line_layout(tctx, models, file,
layout_func, width, face,
line_number);
Layout_Item_List line = file_get_line_layout(tctx, models, file, layout_func, width, face, line_number);
i64 next_character = line_character + line.character_count;
if (character_delta < next_character){
has_result = true;
@ -556,15 +535,12 @@ file_line_shift_characters(Thread_Context *tctx, Models *models, Editing_File *f
}
internal i64
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){
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){
i64 result = 0;
if (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){
Layout_Item_List line = file_get_line_layout(tctx, models, file,
layout_func, width, face, i);
Layout_Item_List line = file_get_line_layout(tctx, models, file, layout_func, width, face, i);
result += line.character_count;
}
if (line_a < line_b){
@ -578,26 +554,19 @@ internal i64
file_pos_from_relative_character(Thread_Context *tctx, Models *models, Editing_File *file,
Layout_Function *layout_func, f32 width, Face *face,
i64 base_line, i64 relative_character){
Line_Shift_Character shift = file_line_shift_characters(tctx, models, file,
layout_func, width, face,
base_line, relative_character);
Line_Shift_Character shift = file_line_shift_characters(tctx, models, file, layout_func, width, face, base_line, relative_character);
relative_character -= shift.character_delta;
Layout_Item_List line = file_get_line_layout(tctx, models, file,
layout_func, width, face,
shift.line);
return(buffer_layout_get_pos_at_character(line, relative_character));
Layout_Item_List line = file_get_line_layout(tctx, models, file, layout_func, width, face, shift.line);
return(layout_get_pos_at_character(line, relative_character));
}
internal i64
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 line_number = buffer_get_line_index(&file->state.buffer, pos) + 1;
Layout_Item_List line = file_get_line_layout(tctx, models, file,
layout_func, width, face,
line_number);
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);
Layout_Item_List line = file_get_line_layout(tctx, models, file, layout_func, width, face, line_number);
i64 result = layout_character_from_pos(line, pos);
result += file_line_character_difference(tctx, models, file, layout_func, width, face, line_number, base_line);
return(result);
}

View File

@ -225,16 +225,16 @@ generic_parse_init(Application_Links *app, Arena *arena, String_Const_u8 content
}
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*
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*
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*
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);
Code_Index_Nest *result = push_array_zero(state->arena, Code_Index_Nest, 1);
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->file = index;
result->open_indentation = indentation;
result->interior_indentation = indentation + 4;
result->close_indentation = indentation + 4;
state->in_statement = true;
for (;;){
@ -296,7 +292,7 @@ generic_parse_statement(Code_Index_File *index, Generic_Parse_State *state, i64
}
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);
Code_Index_Nest *result = push_array_zero(state->arena, Code_Index_Nest, 1);
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->file = index;
result->open_indentation = 0;
result->interior_indentation = 0;
result->close_indentation = 0;
indentation = 0;
state->in_preprocessor = true;
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){
Code_Index_Nest *nest = generic_parse_scope(index, state, indentation);
Code_Index_Nest *nest = generic_parse_scope(index, state);
nest->parent = result;
code_index_push_nest(&result->nest_list, nest);
continue;
}
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;
code_index_push_nest(&result->nest_list, nest);
continue;
@ -351,7 +342,7 @@ generic_parse_preprocessor(Code_Index_File *index, Generic_Parse_State *state, i
}
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);
Code_Index_Nest *result = push_array_zero(state->arena, Code_Index_Nest, 1);
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->file = index;
result->open_indentation = indentation;
result->interior_indentation = indentation + 4;
result->close_indentation = indentation;
indentation = result->interior_indentation;
state->scope_counter += 1;
generic_parse_inc(state);
@ -382,7 +368,7 @@ generic_parse_scope(Code_Index_File *index, Generic_Parse_State *state, i64 inde
}
else{
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);
continue;
}
@ -396,14 +382,14 @@ generic_parse_scope(Code_Index_File *index, Generic_Parse_State *state, i64 inde
}
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;
code_index_push_nest(&result->nest_list, nest);
continue;
}
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;
code_index_push_nest(&result->nest_list, nest);
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;
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*
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);
Code_Index_Nest *result = push_array_zero(state->arena, Code_Index_Nest, 1);
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;
}
indentation += manifested_characters_on_line;
result->open_indentation = indentation;
result->interior_indentation = indentation;
result->close_indentation = indentation;
state->paren_counter += 1;
generic_parse_inc(state);
@ -475,7 +455,7 @@ generic_parse_paren(Code_Index_File *index, Generic_Parse_State *state, i64 inde
}
else{
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);
continue;
}
@ -493,14 +473,14 @@ generic_parse_paren(Code_Index_File *index, Generic_Parse_State *state, i64 inde
}
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;
code_index_push_nest(&result->nest_list, nest);
continue;
}
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;
code_index_push_nest(&result->nest_list, nest);
continue;
@ -520,7 +500,6 @@ function b32
generic_parse_full_input_breaks(Code_Index_File *index, Generic_Parse_State *state, i32 limit){
b32 result = false;
i64 indentation = 0;
i64 first_index = token_it_index(&state->it);
i64 one_past_last_index = first_index + limit;
for (;;){
@ -533,15 +512,15 @@ generic_parse_full_input_breaks(Code_Index_File *index, Generic_Parse_State *sta
}
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);
}
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);
}
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);
}
else{
@ -580,28 +559,49 @@ generic_parse_init(Application_Links *app, Arena *arena, String_Const_u8 content
////////////////////////////////
function i64
layout_index_indent(Code_Index_File *file, i64 pos){
i64 indent = 0;
Code_Index_Nest *nest = code_index_get_nest(file, pos);
function f32
layout_index_x_shift(Application_Links *app, Layout_Reflex *reflex, Code_Index_Nest *nest, i64 pos, f32 space_advance){
f32 result = 0.f;
if (nest != 0){
if (pos == nest->open.min && pos == nest->open.max){
indent = nest->open_indentation;
switch (nest->kind){
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){
indent = nest->close_indentation;
}break;
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{
indent = nest->interior_indentation;
}break;
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
layout_index_x_shift(Code_Index_File *file, i64 pos, f32 space_advance){
i64 indent = layout_index_indent(file, pos);
return(((f32)indent)*space_advance);
layout_index_x_shift(Application_Links *app, Layout_Reflex *reflex, Code_Index_File *file, i64 pos, f32 space_advance){
f32 indent = 0;
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
@ -617,6 +617,8 @@ layout_index_unwrapped__inner(Application_Links *app, Arena *arena, Buffer_ID bu
f32 wrap_align_x = width - metrics.normal_advance;
Layout_Reflex reflex = get_layout_reflex(&list, buffer, width, face);
if (text.size == 0){
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_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);
}
}
else{
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);
}
@ -735,7 +737,7 @@ layout_index_unwrapped__inner(Application_Links *app, Arena *arena, Buffer_ID bu
case '\n':
{
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);
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)){
i64 index = layout_index_from_ptr(ptr, text.str, range.first);
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);
lr_tb_advance_x_without_item(&pos_vars, shift);
}

View File

@ -34,10 +34,6 @@ struct Code_Index_Nest{
Range_i64 open;
Range_i64 close;
i64 open_indentation;
i64 interior_indentation;
i64 close_indentation;
struct Code_Index_File *file;
Code_Index_Nest *parent;

View File

@ -59,6 +59,7 @@
#define DYNAMIC_LINK_API
#include "generated/system_api.cpp"
#include "4coder_system_helpers.cpp"
#include "4coder_layout.cpp"
#include "4coder_profile.cpp"
#include "4coder_profile_static_enable.cpp"
#include "4coder_events.cpp"

237
custom/4coder_layout.cpp Normal file
View File

@ -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

View File

@ -4,6 +4,31 @@
// 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
layout_index_from_ptr(u8 *ptr, u8 *string_base, i64 index_base){
return((i64)(ptr - string_base) + index_base);

View File

@ -26,6 +26,13 @@ struct LefRig_TopBot_Layout_Vars{
f32 width;
};
struct Layout_Reflex{
Layout_Item_List *list;
Buffer_ID buffer;
f32 width;
Face_ID face;
};
#endif
// BOTTOM

View File

@ -138,7 +138,7 @@ string_match_list_merge_nearest(String_Match_List *a, String_Match_List *b, Rang
internal String_Match_List
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