fix navigations when zero-delta-on-select is enabled in multi-line controls; thread line break parsing

This commit is contained in:
Ryan Fleury
2026-07-27 14:47:34 -07:00
parent 36da346590
commit 604fe35d91
2 changed files with 59 additions and 18 deletions
+14 -10
View File
@@ -142,6 +142,7 @@ rd_code_view_build(Arena *arena, RD_CodeViewState *cv, RD_CodeViewBuildFlags fla
} }
B32 taken = 0; B32 taken = 0;
U64 start_cursor = *cursor; U64 start_cursor = *cursor;
U64 start_mark = *mark;
Vec2S32 delta = evt->delta_2s32; Vec2S32 delta = evt->delta_2s32;
U64 line_count = text_patched.line_map.total_line_count; U64 line_count = text_patched.line_map.total_line_count;
U64 line_num = txt_line_num_from_off(&text_patched.line_map, *cursor); U64 line_num = txt_line_num_from_off(&text_patched.line_map, *cursor);
@@ -158,8 +159,11 @@ rd_code_view_build(Arena *arena, RD_CodeViewState *cv, RD_CodeViewBuildFlags fla
*cursor = single_line_op.cursor; *cursor = single_line_op.cursor;
*mark = single_line_op.mark; *mark = single_line_op.mark;
//- rjf: determine if we need to navigate
B32 need_nav = (start_cursor == start_mark || !(evt->flags & UI_EventFlag_ZeroDeltaOnSelect));
//- rjf: wrap lines right //- rjf: wrap lines right
if(evt->delta_unit != UI_EventDeltaUnit_Whole && delta.x > 0 && start_cursor == line_range.max && line_num+1 <= line_count) if(need_nav && evt->delta_unit != UI_EventDeltaUnit_Whole && delta.x > 0 && start_cursor == line_range.max && line_num+1 <= line_count)
{ {
Rng1U64 next_line_range = txt_range_from_line_num(&text_patched.line_map, line_num+1); Rng1U64 next_line_range = txt_range_from_line_num(&text_patched.line_map, line_num+1);
*cursor = next_line_range.min; *cursor = next_line_range.min;
@@ -167,7 +171,7 @@ rd_code_view_build(Arena *arena, RD_CodeViewState *cv, RD_CodeViewBuildFlags fla
} }
//- rjf: wrap lines left //- rjf: wrap lines left
if(evt->delta_unit != UI_EventDeltaUnit_Whole && delta.x < 0 && start_cursor == line_range.min && line_num-1 >= 1) if(need_nav && evt->delta_unit != UI_EventDeltaUnit_Whole && delta.x < 0 && start_cursor == line_range.min && line_num-1 >= 1)
{ {
Rng1U64 prev_line_range = txt_range_from_line_num(&text_patched.line_map, line_num-1); Rng1U64 prev_line_range = txt_range_from_line_num(&text_patched.line_map, line_num-1);
*cursor = prev_line_range.max; *cursor = prev_line_range.max;
@@ -175,7 +179,7 @@ rd_code_view_build(Arena *arena, RD_CodeViewState *cv, RD_CodeViewBuildFlags fla
} }
//- rjf: movement down (plain) //- rjf: movement down (plain)
if(evt->delta_unit == UI_EventDeltaUnit_Char && delta.y > 0 && line_num+1 <= line_count) if(need_nav && evt->delta_unit == UI_EventDeltaUnit_Char && delta.y > 0 && line_num+1 <= line_count)
{ {
Rng1U64 next_line_range = txt_range_from_line_num(&text_patched.line_map, line_num+1); Rng1U64 next_line_range = txt_range_from_line_num(&text_patched.line_map, line_num+1);
*cursor = next_line_range.min + *preferred_column; *cursor = next_line_range.min + *preferred_column;
@@ -183,7 +187,7 @@ rd_code_view_build(Arena *arena, RD_CodeViewState *cv, RD_CodeViewBuildFlags fla
} }
//- rjf: movement up (plain) //- rjf: movement up (plain)
if(evt->delta_unit == UI_EventDeltaUnit_Char && delta.y < 0 && line_num > 1) if(need_nav && evt->delta_unit == UI_EventDeltaUnit_Char && delta.y < 0 && line_num > 1)
{ {
Rng1U64 prev_line_range = txt_range_from_line_num(&text_patched.line_map, line_num-1); Rng1U64 prev_line_range = txt_range_from_line_num(&text_patched.line_map, line_num-1);
*cursor = prev_line_range.min + *preferred_column; *cursor = prev_line_range.min + *preferred_column;
@@ -191,7 +195,7 @@ rd_code_view_build(Arena *arena, RD_CodeViewState *cv, RD_CodeViewBuildFlags fla
} }
//- rjf: movement down (chunk) //- rjf: movement down (chunk)
if(evt->delta_unit == UI_EventDeltaUnit_Word && delta.y > 0 && line_num+1 <= line_count) if(need_nav && evt->delta_unit == UI_EventDeltaUnit_Word && delta.y > 0 && line_num+1 <= line_count)
{ {
for(U64 scan_line_num = line_num+1; scan_line_num <= line_count; scan_line_num += 1) for(U64 scan_line_num = line_num+1; scan_line_num <= line_count; scan_line_num += 1)
{ {
@@ -212,7 +216,7 @@ rd_code_view_build(Arena *arena, RD_CodeViewState *cv, RD_CodeViewBuildFlags fla
} }
//- rjf: movement up (chunk) //- rjf: movement up (chunk)
if(evt->delta_unit == UI_EventDeltaUnit_Word && delta.y < 0 && line_num > 1) if(need_nav && evt->delta_unit == UI_EventDeltaUnit_Word && delta.y < 0 && line_num > 1)
{ {
for(U64 scan_line_num = line_num-1; scan_line_num > 0; scan_line_num -= 1) for(U64 scan_line_num = line_num-1; scan_line_num > 0; scan_line_num -= 1)
{ {
@@ -233,7 +237,7 @@ rd_code_view_build(Arena *arena, RD_CodeViewState *cv, RD_CodeViewBuildFlags fla
} }
//- rjf: movement down (page) //- rjf: movement down (page)
if(evt->delta_unit == UI_EventDeltaUnit_Page && delta.y > 0) if(need_nav && evt->delta_unit == UI_EventDeltaUnit_Page && delta.y > 0)
{ {
U64 advance = line_count_per_page; U64 advance = line_count_per_page;
U64 next_line = line_num + advance; U64 next_line = line_num + advance;
@@ -243,7 +247,7 @@ rd_code_view_build(Arena *arena, RD_CodeViewState *cv, RD_CodeViewBuildFlags fla
} }
//- rjf: movement up (page) //- rjf: movement up (page)
if(evt->delta_unit == UI_EventDeltaUnit_Page && delta.y < 0) if(need_nav && evt->delta_unit == UI_EventDeltaUnit_Page && delta.y < 0)
{ {
S64 advance = -line_count_per_page; S64 advance = -line_count_per_page;
if(line_num < line_count_per_page) if(line_num < line_count_per_page)
@@ -257,13 +261,13 @@ rd_code_view_build(Arena *arena, RD_CodeViewState *cv, RD_CodeViewBuildFlags fla
} }
//- rjf: movement to endpoint (+) //- rjf: movement to endpoint (+)
if(evt->delta_unit == UI_EventDeltaUnit_Whole && (delta.y > 0 || delta.x > 0)) if(need_nav && evt->delta_unit == UI_EventDeltaUnit_Whole && (delta.y > 0 || delta.x > 0))
{ {
*cursor = text_patched.size; *cursor = text_patched.size;
} }
//- rjf: movement to endpoint (-) //- rjf: movement to endpoint (-)
if(evt->delta_unit == UI_EventDeltaUnit_Whole && (delta.y < 0 || delta.x < 0)) if(need_nav && evt->delta_unit == UI_EventDeltaUnit_Whole && (delta.y < 0 || delta.x < 0))
{ {
*cursor = 0; *cursor = 0;
} }
+45 -8
View File
@@ -3004,19 +3004,21 @@ txt_artifact_create(String8 key, B32 *cancel_signal, AC_Status *status_out, U64
//- rjf: count # of lines //- rjf: count # of lines
U64 lane_line_count = 0; U64 lane_line_count = 0;
U64 *lane_line_counts = 0;
if(lane_idx() == 0) if(lane_idx() == 0)
{ {
lane_line_count = 1; lane_line_counts = push_array(scratch.arena, U64, lane_count());
} }
lane_sync_u64(&lane_line_counts, 0);
{ {
Rng1U64 range = lane_range(data.size); Rng1U64 range = lane_range(data.size+1);
for EachInRange(idx, range) for EachInRange(idx, range)
{ {
if(idx%1000 == 0 && ins_atomic_u32_eval(cancel_signal)) if(idx%1000 == 0 && ins_atomic_u32_eval(cancel_signal))
{ {
break; break;
} }
if(data.str[idx] == '\n') if(idx == data.size || data.str[idx] == '\n')
{ {
lane_line_count += 1; lane_line_count += 1;
} }
@@ -3027,16 +3029,35 @@ txt_artifact_create(String8 key, B32 *cancel_signal, AC_Status *status_out, U64
} }
} }
ins_atomic_u64_add_eval(&shared->info.lines_count, lane_line_count); ins_atomic_u64_add_eval(&shared->info.lines_count, lane_line_count);
lane_line_counts[lane_idx()] = lane_line_count;
lane_sync(); lane_sync();
set_progress(Min(data.size, 1024) + data.size); set_progress(Min(data.size, 1024) + data.size);
//- rjf: figure out which starting line idx each lane will take
U64 *lane_line_base_idxs = 0;
if(lane_idx() == 0)
{
lane_line_base_idxs = push_array(scratch.arena, U64, lane_count());
U64 idx = 0;
for EachIndex(l_idx, lane_count())
{
lane_line_base_idxs[l_idx] = idx;
idx += lane_line_counts[l_idx];
}
}
lane_sync_u64(&lane_line_base_idxs, 0);
//- rjf: allocate & store line ranges //- rjf: allocate & store line ranges
if(lane_idx() == 0) if(lane_idx() == 0)
{ {
shared->info.lines_ranges = push_array_no_zero(shared->arena, Rng1U64, shared->info.lines_count); shared->info.lines_ranges = push_array_no_zero(shared->arena, Rng1U64, shared->info.lines_count);
U64 line_idx = 0; }
U64 line_start_idx = 0; lane_sync();
for(U64 idx = 0; idx <= data.size; idx += 1) {
Rng1U64 range = lane_range(data.size+1);
U64 lane_line_idx = 0;
U64 line_start_idx = range.min;
for EachInRange(idx, range)
{ {
if(idx%1000 == 0 && ins_atomic_u32_eval(cancel_signal)) if(idx%1000 == 0 && ins_atomic_u32_eval(cancel_signal))
{ {
@@ -3044,15 +3065,31 @@ txt_artifact_create(String8 key, B32 *cancel_signal, AC_Status *status_out, U64
} }
if(idx == data.size || data.str[idx] == '\n') if(idx == data.size || data.str[idx] == '\n')
{ {
if(lane_line_idx == 0 && line_start_idx > 0)
{
for(U64 idx2 = line_start_idx - 1; idx2 < data.size; idx2 -= 1)
{
if(data.str[idx2] == '\n')
{
line_start_idx = idx2+1;
break;
}
else if(idx2 == 0)
{
line_start_idx = idx2;
break;
}
}
}
Rng1U64 line_range = r1u64(line_start_idx, idx); Rng1U64 line_range = r1u64(line_start_idx, idx);
if(idx > 0 && data.str[idx-1] == '\r' && line_range.max > line_range.min) if(idx > 0 && data.str[idx-1] == '\r' && line_range.max > line_range.min)
{ {
line_range.max -= 1; line_range.max -= 1;
} }
U64 line_size = dim_1u64(line_range); U64 line_size = dim_1u64(line_range);
shared->info.lines_ranges[line_idx] = line_range; shared->info.lines_ranges[lane_line_base_idxs[lane_idx()] + lane_line_idx] = line_range;
shared->info.lines_max_size = Max(shared->info.lines_max_size, line_size); shared->info.lines_max_size = Max(shared->info.lines_max_size, line_size);
line_idx += 1; lane_line_idx += 1;
line_start_idx = idx+1; line_start_idx = idx+1;
} }
if(idx && idx%1000 == 0) if(idx && idx%1000 == 0)