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
static uint32_t
2018-05-07 02:47:22 +00:00
binary_search ( uint32_t * array , int32_t stride , int32_t count , uint32_t x ) {
uint8_t * raw = ( uint8_t * ) array ;
2017-04-15 21:47:23 +00:00
uint32_t i = 0 ;
uint32_t first = 0 ;
uint32_t last = count ;
if ( first < last ) {
for ( ; ; ) {
i = ( first + last ) / 2 ;
2018-05-07 02:47:22 +00:00
uint32_t k = * ( uint32_t * ) ( raw + stride * i ) ;
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
parse_buffer_to_jump_array ( Application_Links * app , Partition * arena , Buffer_Summary buffer ) {
2018-11-20 08:18:54 +00:00
Sticky_Jump_Array result = { } ;
2018-08-12 03:45:09 +00:00
result . jumps = push_array ( arena , Sticky_Jump , 0 ) ;
2017-04-15 21:47:23 +00:00
2018-08-12 03:45:09 +00:00
for ( int32_t line = 1 ; ; line + = 1 ) {
2017-04-23 00:53:19 +00:00
bool32 output_jump = false ;
2018-08-12 03:45:09 +00:00
int32_t colon_index = 0 ;
2017-04-23 00:53:19 +00:00
bool32 is_sub_error = false ;
2018-08-12 03:45:09 +00:00
Buffer_ID out_buffer_id = 0 ;
int32_t out_pos = 0 ;
2017-04-15 21:47:23 +00:00
2018-08-12 03:45:09 +00:00
Temp_Memory temp = begin_temp_memory ( arena ) ;
2018-11-20 08:18:54 +00:00
String line_str = { } ;
2018-08-12 03:45:09 +00:00
if ( read_line ( app , arena , & buffer , line , & line_str ) ) {
2018-11-20 08:18:54 +00:00
Name_Line_Column_Location location = { } ;
2017-04-23 00:53:19 +00:00
if ( parse_jump_location ( line_str , & location , & colon_index , & is_sub_error ) ) {
2018-11-20 08:18:54 +00:00
Buffer_Summary jump_buffer = { } ;
2018-08-12 03:45:09 +00:00
if ( open_file ( app , & jump_buffer , location . file . str , location . file . size , false , true ) ) {
if ( jump_buffer . exists ) {
2018-11-20 08:18:54 +00:00
Partial_Cursor cursor = { } ;
2018-08-12 03:45:09 +00:00
if ( buffer_compute_cursor ( app , & jump_buffer ,
seek_line_char ( location . line , location . column ) ,
& cursor ) ) {
out_buffer_id = jump_buffer . buffer_id ;
out_pos = cursor . pos ;
output_jump = true ;
}
}
}
2017-04-23 00:53:19 +00:00
}
}
else {
2018-08-12 03:45:09 +00:00
end_temp_memory ( temp ) ;
2017-04-23 00:53:19 +00:00
break ;
}
2018-08-12 03:45:09 +00:00
end_temp_memory ( temp ) ;
2017-04-23 00:53:19 +00:00
if ( output_jump ) {
2018-08-12 03:45:09 +00:00
Sticky_Jump * jump = push_array ( arena , Sticky_Jump , 1 ) ;
jump - > list_line = line ;
jump - > list_colon_index = colon_index ;
jump - > is_sub_error = is_sub_error ;
jump - > jump_buffer_id = out_buffer_id ;
jump - > jump_pos = out_pos ;
}
}
result . count = ( int32_t ) ( push_array ( arena , Sticky_Jump , 0 ) - result . jumps ) ;
return ( result ) ;
}
2018-08-18 08:16:52 +00:00
static char sticky_jump_marker_handle_var [ ] = " DEFAULT.sticky_jump_marker_handle " ;
static int32_t sticky_jump_marker_handle_loc ;
2018-08-12 03:45:09 +00:00
static void
2018-08-18 08:16:52 +00:00
init_marker_list ( Application_Links * app , Partition * scratch , Heap * heap , Buffer_ID buffer_id ,
2018-08-12 03:45:09 +00:00
Marker_List * list ) {
Buffer_Summary buffer = get_buffer ( app , buffer_id , AccessAll ) ;
2018-09-22 23:45:24 +00:00
bool32 is_compilation_buffer = match ( make_string ( buffer . buffer_name , buffer . buffer_name_len ) , " *compilation* " ) ;
2018-08-12 03:45:09 +00:00
2018-08-18 08:16:52 +00:00
Temp_Memory temp = begin_temp_memory ( scratch ) ;
Sticky_Jump_Array jumps = parse_buffer_to_jump_array ( app , scratch , buffer ) ;
Range_Array buffer_ranges = get_ranges_of_duplicate_keys ( scratch ,
& jumps . jumps - > jump_buffer_id , sizeof ( * jumps . jumps ) ,
jumps . count ) ;
Sort_Pair_i32 * range_index_buffer_id_pairs = push_array ( scratch , Sort_Pair_i32 , buffer_ranges . count ) ;
for ( int32_t i = 0 ; i < buffer_ranges . count ; i + = 1 ) {
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 ] = { } ;
2018-09-07 22:39:33 +00:00
scope_array [ 0 ] = buffer_get_managed_scope ( app , buffer_id ) ;
2018-08-12 03:45:09 +00:00
2018-09-07 22:39:33 +00:00
for ( int32_t i = 0 ; i < scoped_buffer_ranges . count ; i + = 1 ) {
Range buffer_range_indices = scoped_buffer_ranges . ranges [ i ] ;
2018-08-18 08:16:52 +00:00
Temp_Memory marker_temp = begin_temp_memory ( scratch ) ;
Marker * markers = push_array ( scratch , Marker , 0 ) ;
2018-09-07 22:39:33 +00:00
uint32_t total_jump_count = 0 ;
2018-08-18 08:16:52 +00:00
Buffer_ID target_buffer_id = 0 ;
for ( int32_t j = buffer_range_indices . first ;
j < buffer_range_indices . one_past_last ;
j + = 1 ) {
int32_t range_index = range_index_buffer_id_pairs [ j ] . index ;
Range range = buffer_ranges . ranges [ range_index ] ;
if ( target_buffer_id = = 0 ) {
target_buffer_id = jumps . jumps [ range . first ] . jump_buffer_id ;
}
for ( int32_t k = range . first ; k < range . one_past_last ; k + = 1 ) {
Marker * new_marker = push_array ( scratch , Marker , 1 ) ;
new_marker - > pos = jumps . jumps [ k ] . jump_pos ;
new_marker - > lean_right = false ;
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 ;
stored [ k ] . index_into_marker_array = total_jump_count ;
total_jump_count + = 1 ;
}
}
2018-08-12 03:45:09 +00:00
2018-09-30 12:14:47 +00:00
scope_array [ 1 ] = buffer_get_managed_scope ( app , target_buffer_id ) ;
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 ) {
Theme_Color color = { } ;
color . tag = Stag_Highlight_Junk ;
get_theme_colors ( app , & color , 1 ) ;
2018-10-01 19:32:28 +00:00
Marker_Visual visual = create_marker_visual ( app , marker_handle ) ;
2018-10-02 22:04:57 +00:00
marker_visual_set_effect ( app , visual ,
VisualType_LineHighlights , color . color , 0 , 0 ) ;
2018-09-22 23:45:24 +00:00
}
2018-09-22 00:29:32 +00:00
2018-08-12 03:45:09 +00:00
end_temp_memory ( marker_temp ) ;
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
end_temp_memory ( temp ) ;
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 ;
2018-08-12 03:45:09 +00:00
list - > previous_size = buffer . size ;
2018-08-18 08:16:52 +00:00
list - > buffer_id = buffer_id ;
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 *
2018-08-18 08:16:52 +00:00
make_new_marker_list_for_buffer ( Heap * heap , int32_t buffer_id ) {
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 *
2018-09-15 23:48:02 +00:00
get_or_make_list_for_buffer ( Application_Links * app , Partition * scratch , 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 ) {
Buffer_Summary buffer = get_buffer ( app , buffer_id , AccessAll ) ;
// TODO(allen): When buffers get an "edit sequence number" use that instead.
if ( result - > previous_size ! = buffer . size ) {
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 ) ;
2018-09-15 23:48:02 +00:00
init_marker_list ( app , scratch , heap , buffer_id , result ) ;
if ( result - > jump_count = = 0 ) {
delete_marker_list ( result ) ;
result = 0 ;
}
2017-04-15 21:47:23 +00:00
}
return ( result ) ;
}
2018-08-18 08:16:52 +00:00
static bool32
get_stored_jump_from_list ( Application_Links * app , Marker_List * list , int32_t index ,
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 *
get_all_stored_jumps_from_list ( Application_Links * app , Partition * arena , Marker_List * list ) {
2018-09-20 19:21:39 +00:00
Sticky_Jump_Stored * stored = 0 ;
if ( list ! = 0 ) {
Temp_Memory restore_point = begin_temp_memory ( arena ) ;
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 ;
end_temp_memory ( restore_point ) ;
}
2018-08-18 08:16:52 +00:00
}
}
return ( stored ) ;
}
2017-04-15 21:47:23 +00:00
static bool32
get_jump_from_list ( Application_Links * app , Marker_List * list , int32_t index , ID_Pos_Jump_Location * location ) {
2019-02-12 02:33:11 +00:00
bool32 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 ] = { } ;
2018-09-07 22:39:33 +00:00
scope_array [ 0 ] = buffer_get_managed_scope ( app , list - > buffer_id ) ;
scope_array [ 1 ] = buffer_get_managed_scope ( app , target_buffer_id ) ;
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
}
static int32_t
2018-08-18 08:16:52 +00:00
get_line_from_list ( Application_Links * app , Marker_List * list , int32_t index ) {
int32_t 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 ) ;
}
static bool32
get_is_sub_error_from_list ( Application_Links * app , Marker_List * list , int32_t index ) {
bool32 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 ) ;
}
static int32_t
2018-08-18 08:16:52 +00:00
get_index_nearest_from_list ( Application_Links * app , Partition * scratch , Marker_List * list , int32_t line ) {
int32_t result = - 1 ;
2018-09-20 19:21:39 +00:00
if ( list ! = 0 ) {
Temp_Memory temp = begin_temp_memory ( scratch ) ;
Sticky_Jump_Stored * stored = get_all_stored_jumps_from_list ( app , scratch , list ) ;
if ( stored ! = 0 ) {
result = binary_search ( ( uint32_t * ) & stored - > list_line , sizeof ( * stored ) , list - > jump_count , line ) ;
}
end_temp_memory ( temp ) ;
2018-08-18 08:16:52 +00:00
}
2017-04-15 21:47:23 +00:00
return ( result ) ;
}
static int32_t
2018-08-18 08:16:52 +00:00
get_index_exact_from_list ( Application_Links * app , Partition * scratch , Marker_List * list , int32_t line ) {
int32_t result = - 1 ;
2018-09-20 19:21:39 +00:00
if ( list ! = 0 ) {
Temp_Memory temp = begin_temp_memory ( scratch ) ;
Sticky_Jump_Stored * stored = get_all_stored_jumps_from_list ( app , scratch , list ) ;
if ( stored ! = 0 ) {
int32_t index = binary_search ( ( uint32_t * ) & stored - > list_line , sizeof ( * stored ) , list - > jump_count , line ) ;
if ( stored [ index ] . list_line = = line ) {
result = index ;
}
2018-08-18 08:16:52 +00:00
}
2018-09-20 19:21:39 +00:00
end_temp_memory ( 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
Partition * part = & global_part ;
Temp_Memory temp = begin_temp_memory ( part ) ;
View_Summary view = get_active_view ( app , AccessProtected ) ;
2018-08-18 08:16:52 +00:00
Marker_List * list = get_or_make_list_for_buffer ( app , part , heap , view . buffer_id ) ;
2017-04-15 21:47:23 +00:00
2018-08-18 08:16:52 +00:00
int32_t list_index = get_index_exact_from_list ( app , part , list , view . 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 ) ) {
2018-11-20 08:18:54 +00:00
Buffer_Summary buffer = { } ;
2017-04-15 21:47:23 +00:00
if ( get_jump_buffer ( app , & buffer , & location ) ) {
change_active_panel ( app ) ;
View_Summary target_view = get_active_view ( app , AccessAll ) ;
switch_to_existing_view ( app , & target_view , & buffer ) ;
jump_to_location ( app , & target_view , & buffer , location ) ;
}
}
}
end_temp_memory ( temp ) ;
}
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
Partition * part = & global_part ;
Temp_Memory temp = begin_temp_memory ( part ) ;
View_Summary view = get_active_view ( app , AccessProtected ) ;
2018-08-18 08:16:52 +00:00
Marker_List * list = get_or_make_list_for_buffer ( app , part , heap , view . buffer_id ) ;
int32_t list_index = get_index_exact_from_list ( app , part , list , view . 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 ) ) {
2018-11-20 08:18:54 +00:00
Buffer_Summary buffer = { } ;
2017-04-15 21:47:23 +00:00
if ( get_jump_buffer ( app , & buffer , & location ) ) {
View_Summary target_view = view ;
jump_to_location ( app , & target_view , & buffer , location ) ;
}
}
}
end_temp_memory ( temp ) ;
}
2017-04-23 00:53:19 +00:00
static void
goto_jump_in_order ( Application_Links * app , Marker_List * list , View_Summary * jump_view , ID_Pos_Jump_Location location ) {
2018-11-20 08:18:54 +00:00
Buffer_Summary buffer = { } ;
2017-04-23 00:53:19 +00:00
if ( get_jump_buffer ( app , & buffer , & location ) ) {
View_Summary target_view = get_active_view ( app , AccessAll ) ;
if ( target_view . view_id = = jump_view - > view_id ) {
change_active_panel ( app ) ;
target_view = get_active_view ( app , AccessAll ) ;
}
switch_to_existing_view ( app , & target_view , & buffer ) ;
jump_to_location ( app , & target_view , & buffer , location ) ;
prev_location . buffer_id = location . buffer_id ;
prev_location . line = location . pos ;
prev_location . column = 0 ;
}
}
static bool32
2018-08-12 03:45:09 +00:00
jump_is_repeat ( ID_Line_Column_Jump_Location prev , ID_Pos_Jump_Location location ) {
2017-04-23 00:53:19 +00:00
bool32 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
goto_next_filtered_jump ( Application_Links * app , Marker_List * list , View_Summary * jump_view , int32_t list_index , int32_t direction , bool32 skip_repeats , bool32 skip_sub_errors ) {
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 ) ) {
bool32 skip_this = false ;
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 ) ;
int32_t updated_line = get_line_from_list ( app , list , list_index ) ;
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
2018-08-18 08:16:52 +00:00
get_locked_jump_state ( Application_Links * app , Partition * part , 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 ) ;
if ( result . view . exists ) {
2018-08-18 08:16:52 +00:00
result . list = get_or_make_list_for_buffer ( app , part , heap , result . view . buffer_id ) ;
result . list_index = get_index_nearest_from_list ( app , part , result . list , result . view . 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
Partition * part = & global_part ;
2018-08-18 08:16:52 +00:00
Locked_Jump_State jump_state = get_locked_jump_state ( app , part , heap ) ;
2017-04-23 00:53:19 +00:00
if ( jump_state . view . exists ) {
2018-08-18 08:16:52 +00:00
int32_t line = get_line_from_list ( app , jump_state . list , jump_state . list_index ) ;
2017-04-23 00:53:19 +00:00
if ( line < = jump_state . view . cursor . line ) {
+ + jump_state . list_index ;
2017-04-15 21:47:23 +00:00
}
2017-04-23 00:53:19 +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
Partition * part = & global_part ;
2018-08-18 08:16:52 +00:00
Locked_Jump_State jump_state = get_locked_jump_state ( app , part , heap ) ;
2017-04-23 00:53:19 +00:00
if ( jump_state . view . exists ) {
if ( jump_state . list_index > 0 ) {
- - jump_state . list_index ;
}
goto_next_filtered_jump ( app , jump_state . list , & jump_state . view , jump_state . list_index , - 1 , true , true ) ;
}
}
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
Partition * part = & global_part ;
2018-08-18 08:16:52 +00:00
Locked_Jump_State jump_state = get_locked_jump_state ( app , part , heap ) ;
2017-04-23 00:53:19 +00:00
if ( jump_state . view . exists ) {
2018-08-18 08:16:52 +00:00
int32_t line = get_line_from_list ( app , jump_state . list , jump_state . list_index ) ;
2017-04-23 00:53:19 +00:00
if ( line < = jump_state . view . cursor . line ) {
+ + jump_state . list_index ;
}
goto_next_filtered_jump ( app , jump_state . list , & jump_state . view , jump_state . list_index , 1 , true , false ) ;
}
}
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
Partition * part = & global_part ;
2018-08-18 08:16:52 +00:00
Locked_Jump_State jump_state = get_locked_jump_state ( app , part , heap ) ;
2017-04-23 00:53:19 +00:00
if ( jump_state . view . exists ) {
if ( jump_state . list_index > 0 ) {
- - jump_state . list_index ;
2017-04-15 21:47:23 +00:00
}
2017-04-23 00:53:19 +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
Partition * part = & global_part ;
2018-08-18 08:16:52 +00:00
Locked_Jump_State jump_state = get_locked_jump_state ( app , part , heap ) ;
2017-04-23 00:53:19 +00:00
if ( jump_state . view . exists ) {
2017-04-15 21:47:23 +00:00
int32_t 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 ) ) {
goto_jump_in_order ( app , jump_state . list , & jump_state . view , location ) ;
2018-08-18 08:16:52 +00:00
int32_t updated_line = get_line_from_list ( app , jump_state . list , list_index ) ;
2017-04-23 00:53:19 +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
Partition * part = & global_part ;
2018-08-18 08:16:52 +00:00
Locked_Jump_State jump_state = get_locked_jump_state ( app , part , heap ) ;
2017-11-29 23:00:14 +00:00
if ( jump_state . view . exists ) {
int32_t 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 ) ) {
2018-11-20 08:18:54 +00:00
Buffer_Summary buffer = { } ;
2017-11-29 23:00:14 +00:00
if ( get_jump_buffer ( app , & buffer , & location ) ) {
jump_to_location ( app , & jump_state . view , & buffer , location ) ;
}
}
}
}
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. " )
{
2017-04-15 21:47:23 +00:00
View_Summary view = get_active_view ( app , AccessProtected ) ;
Buffer_Summary buffer = get_buffer ( app , view . buffer_id , AccessProtected ) ;
if ( buffer . lock_flags & AccessProtected ) {
2017-11-15 23:57:21 +00:00
goto_jump_at_cursor_sticky ( app ) ;
2017-04-15 21:47:23 +00:00
lock_jump_buffer ( buffer ) ;
}
else {
write_character ( app ) ;
}
}
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. " )
{
2017-04-15 21:47:23 +00:00
View_Summary view = get_active_view ( app , AccessProtected ) ;
Buffer_Summary buffer = get_buffer ( app , view . buffer_id , AccessProtected ) ;
if ( buffer . lock_flags & AccessProtected ) {
2017-11-15 23:57:21 +00:00
goto_jump_at_cursor_same_panel_sticky ( app ) ;
2017-04-15 21:47:23 +00:00
lock_jump_buffer ( buffer ) ;
}
else {
write_character ( app ) ;
}
}
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 ) ;
}
2019-02-12 02:33:11 +00:00
////////////////////////////////
static bool32
search_buffer_edit_handler__inner ( Application_Links * app , Partition * part , Buffer_ID buffer_id , int32_t start , int32_t one_past_last , String text ) {
Buffer_Summary buffer = get_buffer ( app , buffer_id , AccessProtected ) ;
// NOTE(allen): get the list for this buffer
Marker_List * list = get_or_make_list_for_buffer ( app , part , & global_heap , buffer_id ) ;
if ( list = = 0 ) {
return ( false ) ;
}
// NOTE(allen): activate jumps
if ( match ( text , " \n " ) ) {
// TODO(allen): do(determine when shift is held here and do *same_panel* version of goto_jump_at_cursor_sticky)
goto_jump_at_cursor_sticky ( app ) ;
lock_jump_buffer ( buffer ) ;
return ( false ) ;
}
// NOTE(allen): do not allow new lines to be inserted ever
if ( find_s_char ( text , 0 , ' \n ' ) ! = text . size ) {
return ( false ) ;
}
// NOTE(allen): check that the range is entirely inside an editable range
Partial_Cursor start_cursor = { } ;
Partial_Cursor one_past_last_cursor = { } ;
if ( ! ( buffer_compute_cursor ( app , & buffer , seek_pos ( start ) , & start_cursor ) & &
buffer_compute_cursor ( app , & buffer , seek_pos ( one_past_last ) , & one_past_last_cursor ) ) ) {
return ( false ) ;
}
if ( start_cursor . line ! = one_past_last_cursor . line ) {
return ( false ) ;
}
int32_t line_number = start_cursor . line ;
Partial_Cursor line_start_cursor = { } ;
Partial_Cursor line_one_past_last_cursor = { } ;
String line = { } ;
if ( ! read_line ( app , part , & buffer , line_number , & line , & line_start_cursor , & line_one_past_last_cursor ) ) {
return ( false ) ;
}
int32_t line_start = line_start_cursor . pos ;
int32_t line_one_past_last = line_one_past_last_cursor . pos ;
int32_t colon_index = find_substr ( line , 0 , make_lit_string ( " : " ) ) ;
if ( colon_index = = line . size ) {
return ( false ) ;
}
int32_t editable_start = line_start + colon_index + 2 ;
int32_t editable_one_past_last = line_one_past_last ;
if ( ! ( editable_start < = start & & one_past_last < = editable_one_past_last ) ) {
return ( false ) ;
}
// NOTE(allen): figure out the target buffer make sure we want to edit it
int32_t list_index = get_index_exact_from_list ( app , part , list , line_number ) ;
if ( list_index < 0 ) {
return ( false ) ;
}
ID_Pos_Jump_Location location = { } ;
if ( ! get_jump_from_list ( app , list , list_index , & location ) ) {
return ( false ) ;
}
Buffer_Summary target_buffer = { } ;
if ( ! get_jump_buffer ( app , & target_buffer , & location , AccessOpen ) ) {
return ( false ) ;
}
int32_t is_unimportant = false ;
if ( ! buffer_get_setting ( app , & target_buffer , BufferSetting_Unimportant , & is_unimportant ) ) {
return ( false ) ;
}
if ( is_unimportant ) {
return ( false ) ;
}
// NOTE(allen): figure out the shift of the edit from the search buffer to the target buffer
Partial_Cursor target_pos = { } ;
if ( ! buffer_compute_cursor ( app , & target_buffer , seek_pos ( location . pos ) , & target_pos ) ) {
return ( false ) ;
}
int32_t target_line_number = target_pos . line ;
Partial_Cursor target_line_start_cursor = { } ;
Partial_Cursor target_line_one_past_last_cursor = { } ;
String target_line = { } ;
if ( ! read_line ( app , part , & target_buffer , target_line_number , & target_line , & target_line_start_cursor , & target_line_one_past_last_cursor ) ) {
return ( false ) ;
}
int32_t target_line_start = target_line_start_cursor . pos ;
//int32_t target_line_one_past_last = target_line_one_past_last_cursor.pos;
String target_line_skip_whitespace = skip_whitespace ( target_line ) ;
int32_t skip_into_line_amount = ( int32_t ) ( target_line_skip_whitespace . str - target_line . str ) ;
int32_t target_editable_start = target_line_start + skip_into_line_amount ;
int32_t edit_range_shift = target_editable_start - editable_start ;
// NOTE(allen): try to apply the edits
if ( buffer_replace_range ( app , & target_buffer , start + edit_range_shift , one_past_last + edit_range_shift , text . str , text . size ) ) {
if ( buffer_replace_range ( app , & buffer , start , one_past_last , text . str , text . size ) ) {
return ( true ) ;
}
}
return ( false ) ;
}
static bool32
search_buffer_edit_handler ( Application_Links * app , Buffer_ID buffer_id , int32_t start , int32_t one_past_last , String text ) {
Partition * scratch = & global_part ;
Temp_Memory temp = begin_temp_memory ( scratch ) ;
bool32 result = search_buffer_edit_handler__inner ( app , scratch , buffer_id , start , one_past_last , text ) ;
end_temp_memory ( temp ) ;
return ( result ) ;
}
2017-04-15 21:47:23 +00:00
// BOTTOM