2017-04-15 21:47:23 +00:00
/*
2017-11-15 23:57:21 +00:00
4 coder_jump_sticky . cpp - Commands and helpers for parsing jump locations from
2017-04-15 21:47:23 +00:00
compiler errors , sticking markers on jump locations , and jumping to them .
*/
// TOP
2018-05-09 07:10:07 +00:00
static Marker_List_Node * marker_list_first = 0 ;
static Marker_List_Node * marker_list_last = 0 ;
2017-04-15 21:47:23 +00:00
2018-05-09 07:10:07 +00:00
////////////////////////////////
2017-04-15 21:47:23 +00:00
2019-06-20 23:43:27 +00:00
static i32
binary_search ( i64 * array , i32 stride , i32 count , i64 x ) {
2019-02-26 23:30:08 +00:00
u8 * raw = ( u8 * ) array ;
2019-06-20 23:43:27 +00:00
i32 i = 0 ;
i32 first = 0 ;
i32 last = count ;
2017-04-15 21:47:23 +00:00
if ( first < last ) {
for ( ; ; ) {
i = ( first + last ) / 2 ;
2019-06-20 23:43:27 +00:00
i64 k = * ( i64 * ) ( raw + stride * i ) ;
2018-05-07 02:47:22 +00:00
if ( k < x ) {
2017-04-15 21:47:23 +00:00
first = i ;
}
2018-05-07 02:47:22 +00:00
else if ( k > x ) {
2017-04-15 21:47:23 +00:00
last = i ;
}
else { // NOTE(allen): array[i] == x
break ;
}
2018-05-07 02:47:22 +00:00
if ( first + 1 > = last ) {
2017-04-15 21:47:23 +00:00
i = first ;
break ;
}
}
}
return ( i ) ;
}
2018-08-12 03:45:09 +00:00
static Sticky_Jump_Array
2019-06-01 23:58:28 +00:00
parse_buffer_to_jump_array ( Application_Links * app , Arena * arena , Buffer_ID buffer ) {
Sticky_Jump_Node * jump_first = 0 ; ;
Sticky_Jump_Node * jump_last = 0 ;
i32 jump_count = 0 ;
2017-04-15 21:47:23 +00:00
2019-02-26 23:08:42 +00:00
for ( i32 line = 1 ; ; line + = 1 ) {
b32 output_jump = false ;
i32 colon_index = 0 ;
b32 is_sub_error = false ;
2018-08-12 03:45:09 +00:00
Buffer_ID out_buffer_id = 0 ;
2019-02-26 23:08:42 +00:00
i32 out_pos = 0 ;
2017-04-15 21:47:23 +00:00
2019-06-01 23:58:28 +00:00
{
Scratch_Block line_auto_closer ( arena ) ;
if ( is_valid_line ( app , buffer , line ) ) {
2019-06-02 03:07:57 +00:00
String_Const_u8 line_str = push_buffer_line ( app , arena , buffer , line ) ;
2019-06-01 23:58:28 +00:00
Parsed_Jump parsed_jump = parse_jump_location ( line_str ) ;
if ( parsed_jump . success ) {
Buffer_ID jump_buffer = { } ;
if ( open_file ( app , & jump_buffer , parsed_jump . location . file , false , true ) ) {
if ( buffer_exists ( app , jump_buffer ) ) {
2019-06-19 02:31:59 +00:00
Partial_Cursor cursor = buffer_compute_cursor ( app , jump_buffer , seek_jump ( parsed_jump ) ) ;
if ( cursor . line > 0 ) {
2019-06-01 23:58:28 +00:00
out_buffer_id = jump_buffer ;
out_pos = cursor . pos ;
output_jump = true ;
}
2019-04-04 08:25:16 +00:00
}
2018-08-12 03:45:09 +00:00
}
}
2017-04-23 00:53:19 +00:00
}
2019-06-01 23:58:28 +00:00
else {
break ;
}
2017-04-23 00:53:19 +00:00
}
if ( output_jump ) {
2019-06-01 23:58:28 +00:00
Sticky_Jump_Node * jump = push_array ( arena , Sticky_Jump_Node , 1 ) ;
sll_queue_push ( jump_first , jump_last , jump ) ;
jump_count + = 1 ;
jump - > jump . list_line = line ;
jump - > jump . list_colon_index = colon_index ;
jump - > jump . is_sub_error = is_sub_error ;
jump - > jump . jump_buffer_id = out_buffer_id ;
jump - > jump . jump_pos = out_pos ;
2018-08-12 03:45:09 +00:00
}
}
2019-06-01 23:58:28 +00:00
Sticky_Jump_Array result = { } ;
result . count = jump_count ;
result . jumps = push_array ( arena , Sticky_Jump , result . count ) ;
i32 index = 0 ;
for ( Sticky_Jump_Node * node = jump_first ;
node ! = 0 ;
node = node - > next ) {
result . jumps [ index ] = node - > jump ;
index + = 1 ;
}
2018-08-12 03:45:09 +00:00
return ( result ) ;
}
2018-08-18 08:16:52 +00:00
static char sticky_jump_marker_handle_var [ ] = " DEFAULT.sticky_jump_marker_handle " ;
2019-02-26 23:08:42 +00:00
static i32 sticky_jump_marker_handle_loc ;
2018-08-12 03:45:09 +00:00
static void
2019-06-01 23:58:28 +00:00
init_marker_list ( Application_Links * app , Heap * heap , Buffer_ID buffer , Marker_List * list ) {
Arena * scratch = context_get_arena ( app ) ;
Temp_Memory temp = begin_temp ( scratch ) ;
2019-04-05 02:03:36 +00:00
2019-06-02 03:07:57 +00:00
String_Const_u8 buffer_name = push_buffer_base_name ( app , scratch , buffer ) ;
2019-06-01 23:58:28 +00:00
b32 is_compilation_buffer = string_match ( buffer_name , string_u8_litexpr ( " *compilation* " ) ) ;
2018-08-12 03:45:09 +00:00
2018-08-18 08:16:52 +00:00
Sticky_Jump_Array jumps = parse_buffer_to_jump_array ( app , scratch , buffer ) ;
2019-04-05 02:03:36 +00:00
Range_Array buffer_ranges = get_ranges_of_duplicate_keys ( scratch , & jumps . jumps - > jump_buffer_id , sizeof ( * jumps . jumps ) , jumps . count ) ;
2018-08-18 08:16:52 +00:00
Sort_Pair_i32 * range_index_buffer_id_pairs = push_array ( scratch , Sort_Pair_i32 , buffer_ranges . count ) ;
2019-02-26 23:08:42 +00:00
for ( i32 i = 0 ; i < buffer_ranges . count ; i + = 1 ) {
2018-08-18 08:16:52 +00:00
range_index_buffer_id_pairs [ i ] . index = i ;
range_index_buffer_id_pairs [ i ] . key = jumps . jumps [ buffer_ranges . ranges [ i ] . first ] . jump_buffer_id ;
}
sort_pairs_by_key ( range_index_buffer_id_pairs , buffer_ranges . count ) ;
2018-09-07 22:39:33 +00:00
Range_Array scoped_buffer_ranges = get_ranges_of_duplicate_keys ( scratch ,
& range_index_buffer_id_pairs - > key ,
sizeof ( * range_index_buffer_id_pairs ) ,
buffer_ranges . count ) ;
2018-08-12 03:45:09 +00:00
2018-08-18 08:16:52 +00:00
Sticky_Jump_Stored * stored = push_array ( scratch , Sticky_Jump_Stored , jumps . count ) ;
2018-08-12 03:45:09 +00:00
2018-11-20 08:18:54 +00:00
Managed_Scope scope_array [ 2 ] = { } ;
2019-06-19 02:31:59 +00:00
scope_array [ 0 ] = buffer_get_managed_scope ( app , buffer ) ;
2018-08-12 03:45:09 +00:00
2019-02-26 23:08:42 +00:00
for ( i32 i = 0 ; i < scoped_buffer_ranges . count ; i + = 1 ) {
2018-09-07 22:39:33 +00:00
Range buffer_range_indices = scoped_buffer_ranges . ranges [ i ] ;
2018-08-18 08:16:52 +00:00
2019-02-26 23:08:42 +00:00
u32 total_jump_count = 0 ;
2019-06-01 23:58:28 +00:00
for ( i32 j = buffer_range_indices . first ;
j < buffer_range_indices . one_past_last ;
j + = 1 ) {
i32 range_index = range_index_buffer_id_pairs [ j ] . index ;
Range range = buffer_ranges . ranges [ range_index ] ;
total_jump_count + = range_size ( range ) ;
}
Temp_Memory marker_temp = begin_temp ( scratch ) ;
Marker * markers = push_array ( scratch , Marker , total_jump_count ) ;
2018-08-18 08:16:52 +00:00
Buffer_ID target_buffer_id = 0 ;
2019-06-01 23:58:28 +00:00
u32 marker_index = 0 ;
2019-02-26 23:08:42 +00:00
for ( i32 j = buffer_range_indices . first ;
2018-08-18 08:16:52 +00:00
j < buffer_range_indices . one_past_last ;
j + = 1 ) {
2019-02-26 23:08:42 +00:00
i32 range_index = range_index_buffer_id_pairs [ j ] . index ;
2018-08-18 08:16:52 +00:00
Range range = buffer_ranges . ranges [ range_index ] ;
if ( target_buffer_id = = 0 ) {
target_buffer_id = jumps . jumps [ range . first ] . jump_buffer_id ;
}
2019-02-26 23:08:42 +00:00
for ( i32 k = range . first ; k < range . one_past_last ; k + = 1 ) {
2019-06-01 23:58:28 +00:00
markers [ marker_index ] . pos = jumps . jumps [ k ] . jump_pos ;
markers [ marker_index ] . lean_right = false ;
2018-08-18 08:16:52 +00:00
stored [ k ] . list_line = jumps . jumps [ k ] . list_line ;
stored [ k ] . list_colon_index = jumps . jumps [ k ] . list_colon_index ;
stored [ k ] . is_sub_error = jumps . jumps [ k ] . is_sub_error ;
stored [ k ] . jump_buffer_id = jumps . jumps [ k ] . jump_buffer_id ;
2019-06-01 23:58:28 +00:00
stored [ k ] . index_into_marker_array = marker_index ;
marker_index + = 1 ;
2018-08-18 08:16:52 +00:00
}
}
2018-08-12 03:45:09 +00:00
2019-06-19 02:31:59 +00:00
scope_array [ 1 ] = buffer_get_managed_scope ( app , target_buffer_id ) ;
2018-09-30 12:14:47 +00:00
Managed_Scope scope = get_managed_scope_with_multiple_dependencies ( app , scope_array , ArrayCount ( scope_array ) ) ;
Managed_Object marker_handle = alloc_buffer_markers_on_buffer ( app , target_buffer_id , total_jump_count , & scope ) ;
managed_object_store_data ( app , marker_handle , 0 , total_jump_count , markers ) ;
2018-09-22 23:45:24 +00:00
if ( is_compilation_buffer ) {
2019-08-01 03:28:43 +00:00
// TODO(allen): replace
#if 0
2018-10-01 19:32:28 +00:00
Marker_Visual visual = create_marker_visual ( app , marker_handle ) ;
2019-02-25 23:42:13 +00:00
marker_visual_set_effect ( app , visual , VisualType_LineHighlights , Stag_Highlight_Junk , 0 , 0 ) ;
2019-08-01 03:28:43 +00:00
# endif
2018-09-22 23:45:24 +00:00
}
2018-09-22 00:29:32 +00:00
2019-06-01 23:58:28 +00:00
end_temp ( marker_temp ) ;
2018-08-12 03:45:09 +00:00
2018-09-07 22:39:33 +00:00
Assert ( managed_object_get_item_size ( app , marker_handle ) = = sizeof ( Marker ) ) ;
Assert ( managed_object_get_item_count ( app , marker_handle ) = = total_jump_count ) ;
Assert ( managed_object_get_type ( app , marker_handle ) = = ManagedObjectType_Markers ) ;
2018-08-18 08:16:52 +00:00
sticky_jump_marker_handle_loc = managed_variable_create_or_get_id ( app , sticky_jump_marker_handle_var , 0 ) ;
2018-09-07 22:39:33 +00:00
managed_variable_set ( app , scope , sticky_jump_marker_handle_loc , marker_handle ) ;
2017-04-15 21:47:23 +00:00
}
2018-08-12 03:45:09 +00:00
2018-09-07 22:39:33 +00:00
Managed_Object stored_jump_array = alloc_managed_memory_in_scope ( app , scope_array [ 0 ] , sizeof ( Sticky_Jump_Stored ) , jumps . count ) ;
managed_object_store_data ( app , stored_jump_array , 0 , jumps . count , stored ) ;
2018-08-12 03:45:09 +00:00
2018-08-18 08:16:52 +00:00
list - > jump_array = stored_jump_array ;
list - > jump_count = jumps . count ;
2019-06-19 02:31:59 +00:00
list - > previous_size = ( i32 ) buffer_get_size ( app , buffer ) ;
2019-04-05 02:03:36 +00:00
list - > buffer_id = buffer ;
2019-06-01 23:58:28 +00:00
end_temp ( temp ) ;
2017-04-15 21:47:23 +00:00
}
2018-05-07 02:47:22 +00:00
static void
delete_marker_list ( Marker_List_Node * node ) {
zdll_remove ( marker_list_first , marker_list_last , node ) ;
}
static void
delete_marker_list ( Marker_List * list ) {
delete_marker_list ( CastFromMember ( Marker_List_Node , list , list ) ) ;
}
2017-04-15 21:47:23 +00:00
static Marker_List *
2019-02-26 23:08:42 +00:00
make_new_marker_list_for_buffer ( Heap * heap , i32 buffer_id ) {
2018-08-18 08:16:52 +00:00
Marker_List_Node * new_node = heap_array ( heap , Marker_List_Node , 1 ) ;
2018-05-07 02:47:22 +00:00
zdll_push_back ( marker_list_first , marker_list_last , new_node ) ;
new_node - > buffer_id = buffer_id ;
memset ( & new_node - > list , 0 , sizeof ( new_node - > list ) ) ;
Marker_List * result = & new_node - > list ;
2017-04-15 21:47:23 +00:00
return ( result ) ;
}
static Marker_List *
2018-08-18 08:16:52 +00:00
get_marker_list_for_buffer ( Buffer_ID buffer_id ) {
2018-05-07 02:47:22 +00:00
for ( Marker_List_Node * node = marker_list_first ;
node ! = 0 ;
node = node - > next ) {
if ( buffer_id = = node - > buffer_id ) {
2018-08-18 08:16:52 +00:00
return ( & node - > list ) ;
2017-04-15 21:47:23 +00:00
}
}
2018-08-18 08:16:52 +00:00
return ( 0 ) ;
2017-04-15 21:47:23 +00:00
}
static Marker_List *
2019-06-01 23:58:28 +00:00
get_or_make_list_for_buffer ( Application_Links * app , Heap * heap , Buffer_ID buffer_id ) {
2018-08-18 08:16:52 +00:00
Marker_List * result = get_marker_list_for_buffer ( buffer_id ) ;
2018-05-07 02:47:22 +00:00
if ( result ! = 0 ) {
2019-06-19 02:31:59 +00:00
i32 buffer_size = ( i32 ) buffer_get_size ( app , buffer_id ) ;
2019-04-05 02:03:36 +00:00
// TODO(allen): // TODO(allen): // TODO(allen): // TODO(allen): // TODO(allen): When buffers get an "edit sequence number" use that instead.
if ( result - > previous_size ! = buffer_size ) {
2018-05-07 02:47:22 +00:00
delete_marker_list ( result ) ;
result = 0 ;
}
}
2017-04-15 21:47:23 +00:00
if ( result = = 0 ) {
2018-08-18 08:16:52 +00:00
result = make_new_marker_list_for_buffer ( heap , buffer_id ) ;
2019-06-01 23:58:28 +00:00
init_marker_list ( app , heap , buffer_id , result ) ;
2018-09-15 23:48:02 +00:00
if ( result - > jump_count = = 0 ) {
delete_marker_list ( result ) ;
result = 0 ;
}
2017-04-15 21:47:23 +00:00
}
return ( result ) ;
}
2019-02-26 23:08:42 +00:00
static b32
get_stored_jump_from_list ( Application_Links * app , Marker_List * list , i32 index ,
2018-08-18 08:16:52 +00:00
Sticky_Jump_Stored * stored_out ) {
2018-11-20 08:18:54 +00:00
Sticky_Jump_Stored stored = { } ;
2018-09-20 19:21:39 +00:00
if ( list ! = 0 ) {
if ( managed_object_load_data ( app , list - > jump_array , index , 1 , & stored ) ) {
* stored_out = stored ;
return ( true ) ;
}
2018-08-18 08:16:52 +00:00
}
return ( false ) ;
}
static Sticky_Jump_Stored *
2019-06-01 23:58:28 +00:00
get_all_stored_jumps_from_list ( Application_Links * app , Arena * arena , Marker_List * list ) {
2018-09-20 19:21:39 +00:00
Sticky_Jump_Stored * stored = 0 ;
if ( list ! = 0 ) {
2019-06-01 23:58:28 +00:00
Temp_Memory restore_point = begin_temp ( arena ) ;
2018-09-20 19:21:39 +00:00
stored = push_array ( arena , Sticky_Jump_Stored , list - > jump_count ) ;
if ( stored ! = 0 ) {
if ( ! managed_object_load_data ( app , list - > jump_array , 0 , list - > jump_count , stored ) ) {
stored = 0 ;
2019-06-01 23:58:28 +00:00
end_temp ( restore_point ) ;
2018-09-20 19:21:39 +00:00
}
2018-08-18 08:16:52 +00:00
}
}
return ( stored ) ;
}
2019-02-26 23:08:42 +00:00
static b32
get_jump_from_list ( Application_Links * app , Marker_List * list , i32 index , ID_Pos_Jump_Location * location ) {
b32 result = false ;
2018-11-20 08:18:54 +00:00
Sticky_Jump_Stored stored = { } ;
2018-08-18 08:16:52 +00:00
if ( get_stored_jump_from_list ( app , list , index , & stored ) ) {
Buffer_ID target_buffer_id = stored . jump_buffer_id ;
2018-11-20 08:18:54 +00:00
Managed_Scope scope_array [ 2 ] = { } ;
2019-06-19 02:31:59 +00:00
scope_array [ 0 ] = buffer_get_managed_scope ( app , list - > buffer_id ) ;
scope_array [ 1 ] = buffer_get_managed_scope ( app , target_buffer_id ) ;
2018-09-07 22:39:33 +00:00
Managed_Scope scope = get_managed_scope_with_multiple_dependencies ( app , scope_array , ArrayCount ( scope_array ) ) ;
2018-08-18 08:16:52 +00:00
sticky_jump_marker_handle_loc = managed_variable_create_or_get_id ( app , sticky_jump_marker_handle_var , 0 ) ;
Managed_Object marker_array = 0 ;
2018-09-07 22:39:33 +00:00
if ( managed_variable_get ( app , scope , sticky_jump_marker_handle_loc , & marker_array ) ) {
2018-11-20 08:18:54 +00:00
Marker marker = { } ;
2018-09-07 22:39:33 +00:00
managed_object_load_data ( app , marker_array , stored . index_into_marker_array , 1 , & marker ) ;
2018-08-18 08:16:52 +00:00
location - > buffer_id = target_buffer_id ;
2017-04-15 21:47:23 +00:00
location - > pos = marker . pos ;
2019-02-12 02:33:11 +00:00
result = true ;
2017-04-15 21:47:23 +00:00
}
}
2019-02-12 02:33:11 +00:00
return ( result ) ;
2017-04-15 21:47:23 +00:00
}
2019-06-20 23:43:27 +00:00
static i64
2019-02-26 23:08:42 +00:00
get_line_from_list ( Application_Links * app , Marker_List * list , i32 index ) {
2019-06-20 23:43:27 +00:00
i64 result = 0 ;
2018-09-20 19:21:39 +00:00
if ( list ! = 0 ) {
2018-11-20 08:18:54 +00:00
Sticky_Jump_Stored stored = { } ;
2018-09-20 19:21:39 +00:00
if ( get_stored_jump_from_list ( app , list , index , & stored ) ) {
result = stored . list_line ;
}
2018-08-18 08:16:52 +00:00
}
return ( result ) ;
}
2019-02-26 23:08:42 +00:00
static b32
get_is_sub_error_from_list ( Application_Links * app , Marker_List * list , i32 index ) {
b32 result = false ;
2018-09-20 19:21:39 +00:00
if ( list ! = 0 ) {
2018-11-20 08:18:54 +00:00
Sticky_Jump_Stored stored = { } ;
2018-09-20 19:21:39 +00:00
if ( get_stored_jump_from_list ( app , list , index , & stored ) ) {
result = stored . is_sub_error ;
}
2017-04-15 21:47:23 +00:00
}
return ( result ) ;
}
2019-02-26 23:08:42 +00:00
static i32
2019-06-20 23:43:27 +00:00
get_index_nearest_from_list ( Application_Links * app , Marker_List * list , i64 line ) {
2019-02-26 23:08:42 +00:00
i32 result = - 1 ;
2018-09-20 19:21:39 +00:00
if ( list ! = 0 ) {
2019-06-01 23:58:28 +00:00
Arena * scratch = context_get_arena ( app ) ;
Temp_Memory temp = begin_temp ( scratch ) ;
2018-09-20 19:21:39 +00:00
Sticky_Jump_Stored * stored = get_all_stored_jumps_from_list ( app , scratch , list ) ;
if ( stored ! = 0 ) {
2019-06-20 23:43:27 +00:00
result = binary_search ( ( i64 * ) & stored - > list_line , sizeof ( * stored ) , list - > jump_count , line ) ;
2018-09-20 19:21:39 +00:00
}
2019-06-01 23:58:28 +00:00
end_temp ( temp ) ;
2018-08-18 08:16:52 +00:00
}
2017-04-15 21:47:23 +00:00
return ( result ) ;
}
2019-02-26 23:08:42 +00:00
static i32
2019-06-20 23:43:27 +00:00
get_index_exact_from_list ( Application_Links * app , Marker_List * list , i64 line ) {
2019-02-26 23:08:42 +00:00
i32 result = - 1 ;
2018-09-20 19:21:39 +00:00
if ( list ! = 0 ) {
2019-06-01 23:58:28 +00:00
Arena * scratch = context_get_arena ( app ) ;
Temp_Memory temp = begin_temp ( scratch ) ;
2018-09-20 19:21:39 +00:00
Sticky_Jump_Stored * stored = get_all_stored_jumps_from_list ( app , scratch , list ) ;
if ( stored ! = 0 ) {
2019-06-20 23:43:27 +00:00
i32 index = binary_search ( ( i64 * ) & stored - > list_line , sizeof ( * stored ) , list - > jump_count , line ) ;
2018-09-20 19:21:39 +00:00
if ( stored [ index ] . list_line = = line ) {
result = index ;
}
2018-08-18 08:16:52 +00:00
}
2019-06-01 23:58:28 +00:00
end_temp ( temp ) ;
2017-04-15 21:47:23 +00:00
}
return ( result ) ;
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( goto_jump_at_cursor_sticky )
CUSTOM_DOC ( " If the cursor is found to be on a jump location, parses the jump location and brings up the file and position in another view and changes the active panel to the view containing the jump. " )
{
2018-08-18 08:16:52 +00:00
Heap * heap = & global_heap ;
2017-04-15 21:47:23 +00:00
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessProtected ) ;
Buffer_ID buffer = view_get_buffer ( app , view , AccessProtected ) ;
2019-06-01 23:58:28 +00:00
Marker_List * list = get_or_make_list_for_buffer ( app , heap , buffer ) ;
2019-04-07 17:36:24 +00:00
2019-06-20 23:43:27 +00:00
i64 pos = view_get_cursor_pos ( app , view ) ;
2019-06-20 04:45:58 +00:00
Full_Cursor cursor = view_compute_cursor ( app , view , seek_pos ( pos ) ) ;
2017-04-15 21:47:23 +00:00
2019-06-01 23:58:28 +00:00
i32 list_index = get_index_exact_from_list ( app , list , cursor . line ) ;
2017-04-15 21:47:23 +00:00
if ( list_index > = 0 ) {
2018-11-20 08:18:54 +00:00
ID_Pos_Jump_Location location = { } ;
2017-04-15 21:47:23 +00:00
if ( get_jump_from_list ( app , list , list_index , & location ) ) {
if ( get_jump_buffer ( app , & buffer , & location ) ) {
change_active_panel ( app ) ;
2019-06-19 02:31:59 +00:00
View_ID target_view = get_active_view ( app , AccessAll ) ;
2019-04-07 17:36:24 +00:00
switch_to_existing_view ( app , target_view , buffer ) ;
jump_to_location ( app , target_view , buffer , location ) ;
2017-04-15 21:47:23 +00:00
}
}
}
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( goto_jump_at_cursor_same_panel_sticky )
CUSTOM_DOC ( " If the cursor is found to be on a jump location, parses the jump location and brings up the file and position in this view, losing the compilation output or jump list. " )
{
2018-08-18 08:16:52 +00:00
Heap * heap = & global_heap ;
2017-04-15 21:47:23 +00:00
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessProtected ) ;
Buffer_ID buffer = view_get_buffer ( app , view , AccessProtected ) ;
2019-04-07 17:36:24 +00:00
2019-06-01 23:58:28 +00:00
Marker_List * list = get_or_make_list_for_buffer ( app , heap , buffer ) ;
2019-04-07 17:36:24 +00:00
2019-06-20 23:43:27 +00:00
i64 pos = view_get_cursor_pos ( app , view ) ;
2019-06-20 04:45:58 +00:00
Full_Cursor cursor = view_compute_cursor ( app , view , seek_pos ( pos ) ) ;
2019-04-07 17:36:24 +00:00
2019-06-01 23:58:28 +00:00
i32 list_index = get_index_exact_from_list ( app , list , cursor . line ) ;
2017-04-15 21:47:23 +00:00
if ( list_index > = 0 ) {
2018-11-20 08:18:54 +00:00
ID_Pos_Jump_Location location = { } ;
2017-04-15 21:47:23 +00:00
if ( get_jump_from_list ( app , list , list_index , & location ) ) {
if ( get_jump_buffer ( app , & buffer , & location ) ) {
2019-04-07 17:36:24 +00:00
jump_to_location ( app , view , buffer , location ) ;
2017-04-15 21:47:23 +00:00
}
}
}
}
2017-04-23 00:53:19 +00:00
static void
2019-04-06 19:40:36 +00:00
goto_jump_in_order ( Application_Links * app , Marker_List * list , View_ID jump_view , ID_Pos_Jump_Location location ) {
2019-04-04 08:25:16 +00:00
Buffer_ID buffer = { } ;
2017-04-23 00:53:19 +00:00
if ( get_jump_buffer ( app , & buffer , & location ) ) {
2019-06-19 02:31:59 +00:00
View_ID target_view = get_active_view ( app , AccessAll ) ;
2019-04-07 17:36:24 +00:00
if ( target_view = = jump_view ) {
2017-04-23 00:53:19 +00:00
change_active_panel ( app ) ;
2019-06-19 02:31:59 +00:00
target_view = get_active_view ( app , AccessAll ) ;
2017-04-23 00:53:19 +00:00
}
2019-04-07 17:36:24 +00:00
switch_to_existing_view ( app , target_view , buffer ) ;
jump_to_location ( app , target_view , buffer , location ) ;
2017-04-23 00:53:19 +00:00
prev_location . buffer_id = location . buffer_id ;
prev_location . line = location . pos ;
prev_location . column = 0 ;
}
}
2019-02-26 23:08:42 +00:00
static b32
2018-08-12 03:45:09 +00:00
jump_is_repeat ( ID_Line_Column_Jump_Location prev , ID_Pos_Jump_Location location ) {
2019-02-26 23:08:42 +00:00
b32 skip = false ;
2018-08-12 03:45:09 +00:00
// NOTE(allen): This looks wrong, but it is correct. The prev_location is a line column type
// because that is how the old-style direct jumps worked, and they are still supported. All code paths
// in the sticky jump system treat line as the field for pos and ignore column. When the time has
// passed and the direct jump legacy system is gone then this can be corrected.
2017-04-23 00:53:19 +00:00
if ( prev . buffer_id = = location . buffer_id & & prev . line = = location . pos ) {
skip = true ;
}
return ( skip ) ;
}
static void
2019-04-06 19:40:36 +00:00
goto_next_filtered_jump ( Application_Links * app , Marker_List * list , View_ID jump_view , i32 list_index , i32 direction , b32 skip_repeats , b32 skip_sub_errors ) {
2017-04-23 00:53:19 +00:00
Assert ( direction = = 1 | | direction = = - 1 ) ;
2018-09-20 19:21:39 +00:00
if ( list ! = 0 ) {
for ( ; list_index > = 0 & & list_index < list - > jump_count ; ) {
2018-11-20 08:18:54 +00:00
ID_Pos_Jump_Location location = { } ;
2018-09-20 19:21:39 +00:00
if ( get_jump_from_list ( app , list , list_index , & location ) ) {
2019-02-26 23:08:42 +00:00
b32 skip_this = false ;
2018-09-20 19:21:39 +00:00
if ( skip_repeats & & jump_is_repeat ( prev_location , location ) ) {
skip_this = true ;
}
else if ( skip_sub_errors & & get_is_sub_error_from_list ( app , list , list_index ) ) {
skip_this = true ;
}
if ( ! skip_this ) {
goto_jump_in_order ( app , list , jump_view , location ) ;
2019-06-20 23:43:27 +00:00
i64 updated_line = get_line_from_list ( app , list , list_index ) ;
2018-09-20 19:21:39 +00:00
view_set_cursor ( app , jump_view , seek_line_char ( updated_line , 1 ) , true ) ;
break ;
}
2017-04-23 00:53:19 +00:00
}
2018-09-20 19:21:39 +00:00
list_index + = direction ;
2017-04-23 00:53:19 +00:00
}
}
}
static Locked_Jump_State
2019-06-01 23:58:28 +00:00
get_locked_jump_state ( Application_Links * app , Heap * heap ) {
2018-11-20 08:18:54 +00:00
Locked_Jump_State result = { } ;
2017-04-23 00:53:19 +00:00
result . view = get_view_for_locked_jump_buffer ( app ) ;
2019-04-06 19:40:36 +00:00
if ( result . view ! = 0 ) {
2019-06-19 02:31:59 +00:00
Buffer_ID buffer = view_get_buffer ( app , result . view , AccessAll ) ;
2019-06-01 23:58:28 +00:00
result . list = get_or_make_list_for_buffer ( app , heap , buffer ) ;
2019-04-06 19:40:36 +00:00
2019-06-20 23:43:27 +00:00
i64 cursor_position = view_get_cursor_pos ( app , result . view ) ;
2019-06-20 04:45:58 +00:00
Full_Cursor cursor = view_compute_cursor ( app , result . view , seek_pos ( cursor_position ) ) ;
2019-06-01 23:58:28 +00:00
result . list_index = get_index_nearest_from_list ( app , result . list , cursor . line ) ;
2017-04-23 00:53:19 +00:00
}
return ( result ) ;
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( goto_next_jump_sticky )
CUSTOM_DOC ( " If a buffer containing jump locations has been locked in, goes to the next jump in the buffer, skipping sub jump locations. " )
{
2018-08-18 08:16:52 +00:00
Heap * heap = & global_heap ;
2017-04-15 21:47:23 +00:00
2019-06-01 23:58:28 +00:00
Locked_Jump_State jump_state = get_locked_jump_state ( app , heap ) ;
2019-04-06 19:40:36 +00:00
if ( jump_state . view ! = 0 ) {
2019-06-20 23:43:27 +00:00
i64 cursor_position = view_get_cursor_pos ( app , jump_state . view ) ;
2019-06-20 04:45:58 +00:00
Full_Cursor cursor = view_compute_cursor ( app , jump_state . view , seek_pos ( cursor_position ) ) ;
2019-06-20 23:43:27 +00:00
i64 line = get_line_from_list ( app , jump_state . list , jump_state . list_index ) ;
2019-04-06 19:40:36 +00:00
if ( line < = cursor . line ) {
2017-04-23 00:53:19 +00:00
+ + jump_state . list_index ;
2017-04-15 21:47:23 +00:00
}
2019-04-06 19:40:36 +00:00
goto_next_filtered_jump ( app , jump_state . list , jump_state . view , jump_state . list_index , 1 , true , true ) ;
2017-04-15 21:47:23 +00:00
}
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( goto_prev_jump_sticky )
CUSTOM_DOC ( " If a buffer containing jump locations has been locked in, goes to the previous jump in the buffer, skipping sub jump locations. " ) {
2018-08-18 08:16:52 +00:00
Heap * heap = & global_heap ;
2017-04-15 21:47:23 +00:00
2019-06-01 23:58:28 +00:00
Locked_Jump_State jump_state = get_locked_jump_state ( app , heap ) ;
2019-04-06 19:40:36 +00:00
if ( jump_state . view ! = 0 ) {
2017-04-23 00:53:19 +00:00
if ( jump_state . list_index > 0 ) {
- - jump_state . list_index ;
}
2019-04-06 19:40:36 +00:00
goto_next_filtered_jump ( app , jump_state . list , jump_state . view , jump_state . list_index , - 1 , true , true ) ;
2017-04-23 00:53:19 +00:00
}
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( goto_next_jump_no_skips_sticky )
CUSTOM_DOC ( " If a buffer containing jump locations has been locked in, goes to the next jump in the buffer, and does not skip sub jump locations. " )
{
2018-08-18 08:16:52 +00:00
Heap * heap = & global_heap ;
2017-04-23 00:53:19 +00:00
2019-06-01 23:58:28 +00:00
Locked_Jump_State jump_state = get_locked_jump_state ( app , heap ) ;
2019-04-06 19:40:36 +00:00
if ( jump_state . view ! = 0 ) {
2019-06-20 23:43:27 +00:00
i64 cursor_position = view_get_cursor_pos ( app , jump_state . view ) ;
2019-06-20 04:45:58 +00:00
Full_Cursor cursor = view_compute_cursor ( app , jump_state . view , seek_pos ( cursor_position ) ) ;
2019-06-20 23:43:27 +00:00
i64 line = get_line_from_list ( app , jump_state . list , jump_state . list_index ) ;
2019-04-06 19:40:36 +00:00
if ( line < = cursor . line ) {
2017-04-23 00:53:19 +00:00
+ + jump_state . list_index ;
}
2019-04-06 19:40:36 +00:00
goto_next_filtered_jump ( app , jump_state . list , jump_state . view , jump_state . list_index , 1 , true , false ) ;
2017-04-23 00:53:19 +00:00
}
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( goto_prev_jump_no_skips_sticky )
CUSTOM_DOC ( " If a buffer containing jump locations has been locked in, goes to the previous jump in the buffer, and does not skip sub jump locations. " )
{
2018-08-18 08:16:52 +00:00
Heap * heap = & global_heap ;
2017-04-23 00:53:19 +00:00
2019-06-01 23:58:28 +00:00
Locked_Jump_State jump_state = get_locked_jump_state ( app , heap ) ;
2019-04-06 19:40:36 +00:00
if ( jump_state . view ! = 0 ) {
2017-04-23 00:53:19 +00:00
if ( jump_state . list_index > 0 ) {
- - jump_state . list_index ;
2017-04-15 21:47:23 +00:00
}
2019-04-06 19:40:36 +00:00
goto_next_filtered_jump ( app , jump_state . list , jump_state . view , jump_state . list_index , - 1 , true , false ) ;
2017-04-15 21:47:23 +00:00
}
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( goto_first_jump_sticky )
CUSTOM_DOC ( " If a buffer containing jump locations has been locked in, goes to the first jump in the buffer. " )
{
2018-08-18 08:16:52 +00:00
Heap * heap = & global_heap ;
2017-04-15 21:47:23 +00:00
2019-06-01 23:58:28 +00:00
Locked_Jump_State jump_state = get_locked_jump_state ( app , heap ) ;
2019-04-06 19:40:36 +00:00
if ( jump_state . view ! = 0 ) {
2019-02-26 23:08:42 +00:00
i32 list_index = 0 ;
2018-11-20 08:18:54 +00:00
ID_Pos_Jump_Location location = { } ;
2017-04-23 00:53:19 +00:00
if ( get_jump_from_list ( app , jump_state . list , list_index , & location ) ) {
2019-04-06 19:40:36 +00:00
goto_jump_in_order ( app , jump_state . list , jump_state . view , location ) ;
2019-06-20 23:43:27 +00:00
i64 updated_line = get_line_from_list ( app , jump_state . list , list_index ) ;
2019-04-06 19:40:36 +00:00
view_set_cursor ( app , jump_state . view , seek_line_char ( updated_line , 1 ) , true ) ;
2017-04-15 21:47:23 +00:00
}
}
}
2017-11-29 23:00:14 +00:00
CUSTOM_COMMAND_SIG ( goto_first_jump_same_panel_sticky )
CUSTOM_DOC ( " If a buffer containing jump locations has been locked in, goes to the first jump in the buffer and views the buffer in the panel where the jump list was. " )
{
2018-08-18 08:16:52 +00:00
Heap * heap = & global_heap ;
2017-11-29 23:00:14 +00:00
2019-06-01 23:58:28 +00:00
Locked_Jump_State jump_state = get_locked_jump_state ( app , heap ) ;
2019-04-06 19:40:36 +00:00
if ( jump_state . view ! = 0 ) {
2019-02-26 23:08:42 +00:00
i32 list_index = 0 ;
2018-11-20 08:18:54 +00:00
ID_Pos_Jump_Location location = { } ;
2017-11-29 23:00:14 +00:00
if ( get_jump_from_list ( app , jump_state . list , list_index , & location ) ) {
2019-04-04 08:25:16 +00:00
Buffer_ID buffer = { } ;
2017-11-29 23:00:14 +00:00
if ( get_jump_buffer ( app , & buffer , & location ) ) {
2019-04-06 19:40:36 +00:00
jump_to_location ( app , jump_state . view , buffer , location ) ;
2017-11-29 23:00:14 +00:00
}
}
}
}
2017-04-15 21:47:23 +00:00
//
// Insert Newline or Tigger Jump on Read Only Buffer
//
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( newline_or_goto_position_sticky )
CUSTOM_DOC ( " If the buffer in the active view is writable, inserts a character, otherwise performs goto_jump_at_cursor. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessProtected ) ;
Buffer_ID buffer = view_get_buffer ( app , view , AccessOpen ) ;
if ( buffer ! = 0 ) {
2017-04-15 21:47:23 +00:00
write_character ( app ) ;
}
2019-06-19 02:31:59 +00:00
else {
buffer = view_get_buffer ( app , view , AccessProtected ) ;
if ( buffer ! = 0 ) {
goto_jump_at_cursor_sticky ( app ) ;
lock_jump_buffer ( app , buffer ) ;
}
2019-04-05 02:03:36 +00:00
}
2017-04-15 21:47:23 +00:00
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( newline_or_goto_position_same_panel_sticky )
CUSTOM_DOC ( " If the buffer in the active view is writable, inserts a character, otherwise performs goto_jump_at_cursor_same_panel. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessProtected ) ;
Buffer_ID buffer = view_get_buffer ( app , view , AccessOpen ) ;
if ( buffer ! = 0 ) {
2017-04-15 21:47:23 +00:00
write_character ( app ) ;
}
2019-06-19 02:31:59 +00:00
else {
buffer = view_get_buffer ( app , view , AccessProtected ) ;
if ( buffer ! = 0 ) {
goto_jump_at_cursor_same_panel_sticky ( app ) ;
lock_jump_buffer ( app , buffer ) ;
}
2019-04-05 02:03:36 +00:00
}
2017-04-15 21:47:23 +00:00
}
2017-04-18 15:41:49 +00:00
//
// End File Hook
//
2017-06-16 23:10:50 +00:00
OPEN_FILE_HOOK_SIG ( default_end_file ) ;
2017-04-18 15:41:49 +00:00
OPEN_FILE_HOOK_SIG ( end_file_close_jump_list ) {
2018-08-18 08:16:52 +00:00
Marker_List * list = get_marker_list_for_buffer ( buffer_id ) ;
2017-04-18 15:41:49 +00:00
if ( list ! = 0 ) {
2018-05-07 02:47:22 +00:00
delete_marker_list ( list ) ;
2017-04-18 15:41:49 +00:00
}
default_end_file ( app , buffer_id ) ;
return ( 0 ) ;
}
2017-04-15 21:47:23 +00:00
// BOTTOM