2017-01-23 06:19:43 +00:00
/*
4 coder_base_commands . cpp - Base commands such as inserting characters , and
moving the cursor , which work even without the default 4 coder framework .
*/
// TOP
2017-11-21 18:25:19 +00:00
static void
2019-02-26 23:30:08 +00:00
write_character_parameter ( Application_Links * app , u8 * character , u32 length ) {
2017-02-20 21:05:42 +00:00
if ( length ! = 0 ) {
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessOpen ) ;
2019-04-06 23:36:53 +00:00
if_view_has_highlighted_range_delete_range ( app , view ) ;
2017-11-21 18:25:19 +00:00
2019-06-20 23:43:27 +00:00
i64 pos = view_get_cursor_pos ( app , view ) ;
2019-09-02 18:59:36 +00:00
pos = view_get_character_legal_pos_from_pos ( app , view , pos ) ;
2017-02-24 02:30:29 +00:00
2019-09-02 18:59:36 +00:00
Buffer_ID buffer = view_get_buffer ( app , view , AccessOpen ) ;
2017-02-24 02:30:29 +00:00
2019-02-08 12:33:43 +00:00
// NOTE(allen): consecutive inserts merge logic
2019-06-20 04:45:58 +00:00
History_Record_Index first_index = buffer_history_get_current_state_index ( app , buffer ) ;
2019-02-26 23:08:42 +00:00
b32 do_merge = false ;
2019-02-09 01:48:11 +00:00
if ( character [ 0 ] ! = ' \n ' ) {
2019-04-05 02:03:36 +00:00
Record_Info record = get_single_record ( app , buffer , first_index ) ;
2019-02-09 01:48:11 +00:00
if ( record . error = = RecordError_NoError & & record . kind = = RecordKind_Single ) {
2019-06-01 23:58:28 +00:00
String_Const_u8 string = record . single . string_forward ;
2019-06-20 04:45:58 +00:00
i32 last_end = ( i32 ) ( record . single . first + string . size ) ;
2019-02-09 09:07:39 +00:00
if ( last_end = = pos & & string . size > 0 ) {
2019-02-09 01:48:11 +00:00
char c = string . str [ string . size - 1 ] ;
if ( c ! = ' \n ' ) {
2019-06-01 23:58:28 +00:00
if ( character_is_whitespace ( character [ 0 ] ) & & character_is_whitespace ( c ) ) {
2019-02-09 01:48:11 +00:00
do_merge = true ;
2019-02-08 12:33:43 +00:00
}
2019-06-01 23:58:28 +00:00
else if ( character_is_alpha_numeric ( character [ 0 ] ) & & character_is_alpha_numeric ( c ) ) {
2019-02-09 01:48:11 +00:00
do_merge = true ;
2019-02-08 12:33:43 +00:00
}
2019-02-09 01:48:11 +00:00
}
2019-02-08 12:33:43 +00:00
}
}
}
2019-02-08 11:18:48 +00:00
2019-02-08 12:33:43 +00:00
// NOTE(allen): perform the edit
2019-06-20 23:43:27 +00:00
b32 edit_success = buffer_replace_range ( app , buffer , Ii64 ( pos ) , SCu8 ( character , length ) ) ;
2017-02-24 02:30:29 +00:00
2019-02-08 12:33:43 +00:00
// NOTE(allen): finish merging records if necessary
if ( do_merge ) {
2019-06-20 04:45:58 +00:00
History_Record_Index last_index = buffer_history_get_current_state_index ( app , buffer ) ;
2019-04-05 02:03:36 +00:00
buffer_history_merge_record_range ( app , buffer , first_index , last_index , RecordMergeFlag_StateInRange_MoveStateForward ) ;
2019-02-08 12:33:43 +00:00
}
2019-02-08 11:18:48 +00:00
2019-02-08 12:33:43 +00:00
// NOTE(allen): finish updating the cursor
2019-02-12 10:21:02 +00:00
if ( edit_success ) {
2019-09-02 21:32:52 +00:00
view_set_cursor_and_preferred_x ( app , view , seek_pos ( pos + length ) ) ;
2019-02-12 10:21:02 +00:00
}
2017-01-23 06:19:43 +00:00
}
}
2017-11-21 18:25:19 +00:00
CUSTOM_COMMAND_SIG ( write_character )
CUSTOM_DOC ( " Inserts whatever character was used to trigger this command. " )
{
User_Input in = get_command_input ( app ) ;
2019-02-26 23:30:08 +00:00
u8 character [ 4 ] ;
2019-02-26 23:17:53 +00:00
u32 length = to_writable_character ( in , character ) ;
2017-11-21 18:25:19 +00:00
write_character_parameter ( app , character , length ) ;
2018-06-02 04:06:13 +00:00
}
2017-11-21 18:25:19 +00:00
CUSTOM_COMMAND_SIG ( write_underscore )
CUSTOM_DOC ( " Inserts an underscore. " )
{
2019-02-26 23:30:08 +00:00
u8 character = ' _ ' ;
2017-11-21 18:25:19 +00:00
write_character_parameter ( app , & character , 1 ) ;
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( delete_char )
CUSTOM_DOC ( " Deletes the character to the right of the cursor. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessOpen ) ;
2019-04-06 23:36:53 +00:00
if ( ! if_view_has_highlighted_range_delete_range ( app , view ) ) {
2019-06-19 02:31:59 +00:00
Buffer_ID buffer = view_get_buffer ( app , view , AccessOpen ) ;
2019-06-20 23:43:27 +00:00
i64 start = view_get_cursor_pos ( app , view ) ;
i64 buffer_size = buffer_get_size ( app , buffer ) ;
2019-04-05 02:03:36 +00:00
if ( 0 < = start & & start < buffer_size ) {
2019-09-02 18:59:36 +00:00
Buffer_Cursor cursor = view_compute_cursor ( app , view , seek_pos ( start ) ) ;
i64 character = view_relative_character_from_pos ( app , view , cursor . line , cursor . pos ) ;
i64 end = view_pos_from_relative_character ( app , view , cursor . line , character + 1 ) ;
2019-06-20 23:43:27 +00:00
buffer_replace_range ( app , buffer , Ii64 ( start , end ) , string_u8_empty ) ;
2018-09-30 12:14:47 +00:00
}
2017-01-23 06:19:43 +00:00
}
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( backspace_char )
CUSTOM_DOC ( " Deletes the character to the left of the cursor. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessOpen ) ;
2019-04-06 23:36:53 +00:00
if ( ! if_view_has_highlighted_range_delete_range ( app , view ) ) {
2019-06-19 02:31:59 +00:00
Buffer_ID buffer = view_get_buffer ( app , view , AccessOpen ) ;
2019-06-20 23:43:27 +00:00
i64 end = view_get_cursor_pos ( app , view ) ;
i64 buffer_size = buffer_get_size ( app , buffer ) ;
2019-04-05 02:03:36 +00:00
if ( 0 < end & & end < = buffer_size ) {
2019-09-02 18:59:36 +00:00
Buffer_Cursor cursor = view_compute_cursor ( app , view , seek_pos ( end ) ) ;
i64 character = view_relative_character_from_pos ( app , view , cursor . line , cursor . pos ) ;
i64 start = view_pos_from_relative_character ( app , view , cursor . line , character - 1 ) ;
2019-06-20 23:43:27 +00:00
if ( buffer_replace_range ( app , buffer , Ii64 ( start , end ) , string_u8_empty ) ) {
2019-09-02 21:32:52 +00:00
view_set_cursor_and_preferred_x ( app , view , seek_pos ( start ) ) ;
2019-02-12 10:21:02 +00:00
}
2018-09-30 12:14:47 +00:00
}
2017-01-23 06:19:43 +00:00
}
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( set_mark )
CUSTOM_DOC ( " Sets the mark to the current position of the cursor. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessProtected ) ;
2019-06-20 23:43:27 +00:00
i64 pos = view_get_cursor_pos ( app , view ) ;
2019-04-06 23:36:53 +00:00
view_set_mark ( app , view , seek_pos ( pos ) ) ;
2019-09-02 21:32:52 +00:00
view_set_cursor_and_preferred_x ( app , view , seek_pos ( pos ) ) ;
2017-01-23 06:19:43 +00:00
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( cursor_mark_swap )
CUSTOM_DOC ( " Swaps the position of the cursor and the mark. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessProtected ) ;
2019-06-20 23:43:27 +00:00
i64 cursor = view_get_cursor_pos ( app , view ) ;
i64 mark = view_get_mark_pos ( app , view ) ;
2019-09-02 21:32:52 +00:00
view_set_cursor_and_preferred_x ( app , view , seek_pos ( mark ) ) ;
2019-04-06 23:36:53 +00:00
view_set_mark ( app , view , seek_pos ( cursor ) ) ;
2017-01-23 06:19:43 +00:00
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( delete_range )
CUSTOM_DOC ( " Deletes the text in the range between the cursor and the mark. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessOpen ) ;
Buffer_ID buffer = view_get_buffer ( app , view , AccessOpen ) ;
2019-06-20 23:43:27 +00:00
Range_i64 range = get_view_range ( app , view ) ;
buffer_replace_range ( app , buffer , range , string_u8_empty ) ;
2017-01-23 06:19:43 +00:00
}
2019-06-09 21:05:57 +00:00
static void
2019-06-11 05:01:57 +00:00
current_view_boundary_delete ( Application_Links * app , Scan_Direction direction , Boundary_Function_List funcs ) {
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessOpen ) ;
Buffer_ID buffer = view_get_buffer ( app , view , AccessOpen ) ;
2019-06-20 23:43:27 +00:00
Range_i64 range = { } ;
2019-06-19 02:31:59 +00:00
range . first = view_get_cursor_pos ( app , view ) ;
2019-06-11 05:01:57 +00:00
range . one_past_last = scan ( app , funcs , buffer , direction , range . first ) ;
2019-06-09 21:05:57 +00:00
range = rectify ( range ) ;
2019-06-20 23:43:27 +00:00
buffer_replace_range ( app , buffer , range , string_u8_empty ) ;
2019-06-09 21:05:57 +00:00
}
CUSTOM_COMMAND_SIG ( backspace_alpha_numeric_boundary )
CUSTOM_DOC ( " Delete characters between the cursor position and the first alphanumeric boundary to the left. " )
{
2019-06-11 05:01:57 +00:00
Scratch_Block scratch ( app ) ;
current_view_boundary_delete ( app , Scan_Backward ,
push_boundary_list ( scratch , boundary_alpha_numeric ) ) ;
2019-06-09 21:05:57 +00:00
}
CUSTOM_COMMAND_SIG ( delete_alpha_numeric_boundary )
CUSTOM_DOC ( " Delete characters between the cursor position and the first alphanumeric boundary to the right. " )
{
2019-06-11 05:01:57 +00:00
Scratch_Block scratch ( app ) ;
current_view_boundary_delete ( app , Scan_Forward ,
push_boundary_list ( scratch , boundary_alpha_numeric ) ) ;
2019-06-09 21:05:57 +00:00
}
# define backspace_word backspace_alpha_numeric_boundary
# define delete_word delete_alpha_numeric_boundary
static void
2019-06-11 05:01:57 +00:00
current_view_snipe_delete ( Application_Links * app , Scan_Direction direction , Boundary_Function_List funcs ) {
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessOpen ) ;
Buffer_ID buffer = view_get_buffer ( app , view , AccessOpen ) ;
2019-06-20 23:43:27 +00:00
i64 pos = view_get_cursor_pos ( app , view ) ;
Range_i64 range = get_snipe_range ( app , funcs , buffer , pos , direction ) ;
2019-06-09 21:05:57 +00:00
buffer_replace_range ( app , buffer , range , string_u8_litexpr ( " " ) ) ;
}
CUSTOM_COMMAND_SIG ( snipe_backward_whitespace_or_token_boundary )
CUSTOM_DOC ( " Delete a single, whole token on or to the left of the cursor and post it to the clipboard. " )
{
2019-06-11 05:01:57 +00:00
Scratch_Block scratch ( app ) ;
current_view_snipe_delete ( app , Scan_Backward ,
push_boundary_list ( scratch , boundary_token , boundary_non_whitespace ) ) ;
2019-06-09 21:05:57 +00:00
}
CUSTOM_COMMAND_SIG ( snipe_forward_whitespace_or_token_boundary )
CUSTOM_DOC ( " Delete a single, whole token on or to the right of the cursor and post it to the clipboard. " )
{
2019-06-11 05:01:57 +00:00
Scratch_Block scratch ( app ) ;
current_view_snipe_delete ( app , Scan_Forward ,
push_boundary_list ( scratch , boundary_token , boundary_non_whitespace ) ) ;
2019-06-09 21:05:57 +00:00
}
# define snipe_token_or_word snipe_backward_whitespace_or_token_boundary
# define snipe_token_or_word_right snipe_forward_whitespace_or_token_boundary
2018-05-10 08:12:47 +00:00
////////////////////////////////
2017-01-23 06:19:43 +00:00
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( center_view )
CUSTOM_DOC ( " Centers the view vertically on the line on which the cursor sits. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessProtected ) ;
Rect_f32 region = view_get_buffer_region ( app , view ) ;
2019-09-02 18:59:36 +00:00
i64 pos = view_get_cursor_pos ( app , view ) ;
Buffer_Cursor cursor = view_compute_cursor ( app , view , seek_pos ( pos ) ) ;
f32 view_height = rect_height ( region ) ;
Buffer_Scroll scroll = view_get_buffer_scroll ( app , view ) ;
scroll . target . line_number = cursor . line ;
scroll . target . pixel_shift . y = - view_height * 0.5f ;
view_set_buffer_scroll ( app , view , scroll ) ;
2017-01-23 06:19:43 +00:00
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( left_adjust_view )
CUSTOM_DOC ( " Sets the left size of the view near the x position of the cursor. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessProtected ) ;
2019-09-02 18:59:36 +00:00
i64 pos = view_get_cursor_pos ( app , view ) ;
Buffer_Cursor cursor = view_compute_cursor ( app , view , seek_pos ( pos ) ) ;
Vec2_f32 p = view_relative_xy_of_pos ( app , view , cursor . line , pos ) ;
Buffer_Scroll scroll = view_get_buffer_scroll ( app , view ) ;
scroll . target . pixel_shift . x = clamp_bot ( 0.f , p . x - 30.f ) ;
view_set_buffer_scroll ( app , view , scroll ) ;
2017-01-23 06:19:43 +00:00
}
2018-09-27 20:15:32 +00:00
CUSTOM_COMMAND_SIG ( click_set_cursor_and_mark )
CUSTOM_DOC ( " Sets the cursor position and mark to the mouse position. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessProtected ) ;
2019-09-02 18:59:36 +00:00
if ( ! view_is_in_ui_mode ( app , view ) ) {
Mouse_State mouse = get_mouse_state ( app ) ;
i64 pos = view_pos_from_xy ( app , view , V2 ( mouse . p ) ) ;
2019-09-02 21:32:52 +00:00
view_set_cursor_and_preferred_x ( app , view , seek_pos ( pos ) ) ;
2019-09-02 18:59:36 +00:00
view_set_mark ( app , view , seek_pos ( pos ) ) ;
2018-09-27 20:15:32 +00:00
}
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( click_set_cursor )
CUSTOM_DOC ( " Sets the cursor position to the mouse position. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessProtected ) ;
2019-09-02 18:59:36 +00:00
if ( ! view_is_in_ui_mode ( app , view ) ) {
Mouse_State mouse = get_mouse_state ( app ) ;
i64 pos = view_pos_from_xy ( app , view , V2 ( mouse . p ) ) ;
2019-09-02 21:32:52 +00:00
view_set_cursor_and_preferred_x ( app , view , seek_pos ( pos ) ) ;
2019-09-02 18:59:36 +00:00
no_mark_snap_to_cursor ( app , view ) ;
2018-09-27 20:15:32 +00:00
}
}
CUSTOM_COMMAND_SIG ( click_set_cursor_if_lbutton )
CUSTOM_DOC ( " If the mouse left button is pressed, sets the cursor position to the mouse position. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessProtected ) ;
2019-09-02 18:59:36 +00:00
if ( ! view_is_in_ui_mode ( app , view ) ) {
Mouse_State mouse = get_mouse_state ( app ) ;
if ( mouse . l ) {
i64 pos = view_pos_from_xy ( app , view , V2 ( mouse . p ) ) ;
2019-09-02 21:32:52 +00:00
view_set_cursor_and_preferred_x ( app , view , seek_pos ( pos ) ) ;
2018-09-27 20:15:32 +00:00
}
2019-09-02 18:59:36 +00:00
no_mark_snap_to_cursor ( app , view ) ;
2017-01-23 06:19:43 +00:00
}
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( click_set_mark )
CUSTOM_DOC ( " Sets the mark position to the mouse position. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessProtected ) ;
2019-09-02 18:59:36 +00:00
if ( ! view_is_in_ui_mode ( app , view ) ) {
Mouse_State mouse = get_mouse_state ( app ) ;
i64 pos = view_pos_from_xy ( app , view , V2 ( mouse . p ) ) ;
view_set_mark ( app , view , seek_pos ( pos ) ) ;
no_mark_snap_to_cursor ( app , view ) ;
2017-01-23 06:19:43 +00:00
}
}
2018-09-22 23:45:24 +00:00
CUSTOM_COMMAND_SIG ( mouse_wheel_scroll )
CUSTOM_DOC ( " Reads the scroll wheel value from the mouse state and scrolls accordingly. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessProtected ) ;
2018-09-22 23:45:24 +00:00
Mouse_State mouse = get_mouse_state ( app ) ;
if ( mouse . wheel ! = 0 ) {
2019-09-02 18:59:36 +00:00
if ( view_is_in_ui_mode ( app , view ) ) {
Basic_Scroll scroll = view_get_basic_scroll ( app , view ) ;
scroll . target . y + = mouse . wheel ;
view_set_basic_scroll ( app , view , scroll ) ;
}
else {
Buffer_Scroll scroll = view_get_buffer_scroll ( app , view ) ;
scroll . target = view_move_buffer_point ( app , view , scroll . target , V2f32 ( 0.f , ( f32 ) mouse . wheel ) ) ;
view_set_buffer_scroll ( app , view , scroll ) ;
}
2018-09-22 23:45:24 +00:00
}
}
2018-05-10 08:12:47 +00:00
////////////////////////////////
2019-08-24 01:34:42 +00:00
internal void
move_vertical_pixels ( Application_Links * app , View_ID view , f32 pixels ) {
2019-09-02 18:59:36 +00:00
i64 pos = view_get_cursor_pos ( app , view ) ;
Buffer_Cursor cursor = view_compute_cursor ( app , view , seek_pos ( pos ) ) ;
Vec2_f32 p = view_relative_xy_of_pos ( app , view , cursor . line , pos ) ;
2019-09-02 21:32:52 +00:00
p . x = view_get_preferred_x ( app , view ) ;
2019-09-02 18:59:36 +00:00
p . y + = pixels ;
i64 new_pos = view_pos_at_relative_xy ( app , view , cursor . line , p ) ;
2019-09-02 21:32:52 +00:00
view_set_cursor ( app , view , seek_pos ( new_pos ) ) ;
2019-04-06 23:36:53 +00:00
no_mark_snap_to_cursor_if_shift ( app , view ) ;
2017-01-23 06:19:43 +00:00
}
2019-08-24 01:34:42 +00:00
internal void
move_vertical_pixels ( Application_Links * app , f32 pixels ) {
View_ID view = get_active_view ( app , AccessProtected ) ;
move_vertical_pixels ( app , view , pixels ) ;
}
internal void
move_vertical_lines ( Application_Links * app , View_ID view , f32 lines ) {
2019-06-19 02:31:59 +00:00
Buffer_ID buffer = view_get_buffer ( app , view , AccessProtected ) ;
2019-06-20 04:45:58 +00:00
Face_ID face_id = get_face_id ( app , buffer ) ;
Face_Metrics metrics = get_face_metrics ( app , face_id ) ;
2019-08-24 01:34:42 +00:00
f32 delta_y = lines * metrics . line_height ;
move_vertical_pixels ( app , delta_y ) ;
}
internal void
move_vertical_lines ( Application_Links * app , f32 lines ) {
View_ID view = get_active_view ( app , AccessProtected ) ;
move_vertical_lines ( app , view , lines ) ;
}
internal f32
get_page_jump ( Application_Links * app , View_ID view ) {
Rect_f32 region = view_get_buffer_region ( app , view ) ;
return ( rect_height ( region ) * .9f ) ;
2018-05-10 08:12:47 +00:00
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( move_up )
CUSTOM_DOC ( " Moves the cursor up one line. " )
{
2019-09-02 21:32:52 +00:00
move_vertical_lines ( app , - 1.f ) ;
2017-01-23 06:19:43 +00:00
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( move_down )
CUSTOM_DOC ( " Moves the cursor down one line. " )
{
2019-09-02 21:32:52 +00:00
move_vertical_lines ( app , 1.f ) ;
2017-01-23 06:19:43 +00:00
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( move_up_10 )
CUSTOM_DOC ( " Moves the cursor up ten lines. " )
{
2019-09-02 21:32:52 +00:00
move_vertical_lines ( app , - 10.f ) ;
2017-01-23 06:19:43 +00:00
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( move_down_10 )
CUSTOM_DOC ( " Moves the cursor down ten lines. " )
{
2019-09-02 21:32:52 +00:00
move_vertical_lines ( app , 10.f ) ;
2017-01-23 06:19:43 +00:00
}
2018-05-10 08:12:47 +00:00
CUSTOM_COMMAND_SIG ( move_down_textual )
CUSTOM_DOC ( " Moves down to the next line of actual text, regardless of line wrapping. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessOpen ) ;
2019-06-20 23:43:27 +00:00
i64 pos = view_get_cursor_pos ( app , view ) ;
2019-09-02 18:59:36 +00:00
Buffer_Cursor cursor = view_compute_cursor ( app , view , seek_pos ( pos ) ) ;
2019-06-20 23:43:27 +00:00
i64 next_line = cursor . line + 1 ;
2019-09-02 21:32:52 +00:00
view_set_cursor_and_preferred_x ( app , view , seek_line_col ( next_line , 1 ) ) ;
2017-01-23 06:19:43 +00:00
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( page_up )
CUSTOM_DOC ( " Scrolls the view up one view height and moves the cursor up one view height. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessProtected ) ;
2019-04-06 23:36:53 +00:00
f32 page_jump = get_page_jump ( app , view ) ;
2019-08-24 01:34:42 +00:00
move_vertical_pixels ( app , - page_jump ) ;
2017-01-23 06:19:43 +00:00
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( page_down )
CUSTOM_DOC ( " Scrolls the view down one view height and moves the cursor down one view height. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessProtected ) ;
2019-04-06 23:36:53 +00:00
f32 page_jump = get_page_jump ( app , view ) ;
2019-08-24 01:34:42 +00:00
move_vertical_pixels ( app , page_jump ) ;
2017-01-23 06:19:43 +00:00
}
2019-06-09 21:05:57 +00:00
internal void
2019-06-16 23:38:22 +00:00
seek_blank_line ( Application_Links * app , Scan_Direction direction , Position_Within_Line position ) {
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-20 23:43:27 +00:00
i64 pos = view_get_cursor_pos ( app , view ) ;
i64 new_pos = get_pos_of_blank_line_grouped ( app , buffer , direction , pos ) ;
2019-06-16 23:38:22 +00:00
switch ( position ) {
case PositionWithinLine_SkipLeadingWhitespace :
{
new_pos = get_pos_past_lead_whitespace ( app , buffer , new_pos ) ;
} break ;
case PositionWithinLine_End :
{
new_pos = get_line_side_pos_from_pos ( app , buffer , new_pos , Side_Max ) ;
} break ;
2019-06-09 21:05:57 +00:00
}
2019-09-02 21:32:52 +00:00
view_set_cursor_and_preferred_x ( app , view , seek_pos ( new_pos ) ) ;
2019-06-09 21:05:57 +00:00
no_mark_snap_to_cursor_if_shift ( app , view ) ;
}
CUSTOM_COMMAND_SIG ( move_up_to_blank_line )
CUSTOM_DOC ( " Seeks the cursor up to the next blank line. " )
{
2019-06-16 23:38:22 +00:00
seek_blank_line ( app , Scan_Backward , PositionWithinLine_Start ) ;
2019-06-09 21:05:57 +00:00
}
CUSTOM_COMMAND_SIG ( move_down_to_blank_line )
CUSTOM_DOC ( " Seeks the cursor down to the next blank line. " )
{
2019-06-16 23:38:22 +00:00
seek_blank_line ( app , Scan_Forward , PositionWithinLine_Start ) ;
}
CUSTOM_COMMAND_SIG ( move_up_to_blank_line_skip_whitespace )
CUSTOM_DOC ( " Seeks the cursor up to the next blank line and places it at the end of the line. " )
{
seek_blank_line ( app , Scan_Backward , PositionWithinLine_SkipLeadingWhitespace ) ;
}
CUSTOM_COMMAND_SIG ( move_down_to_blank_line_skip_whitespace )
CUSTOM_DOC ( " Seeks the cursor down to the next blank line and places it at the end of the line. " )
{
seek_blank_line ( app , Scan_Forward , PositionWithinLine_SkipLeadingWhitespace ) ;
2019-06-09 21:05:57 +00:00
}
CUSTOM_COMMAND_SIG ( move_up_to_blank_line_end )
CUSTOM_DOC ( " Seeks the cursor up to the next blank line and places it at the end of the line. " )
{
2019-06-16 23:38:22 +00:00
seek_blank_line ( app , Scan_Backward , PositionWithinLine_End ) ;
2019-06-09 21:05:57 +00:00
}
CUSTOM_COMMAND_SIG ( move_down_to_blank_line_end )
CUSTOM_DOC ( " Seeks the cursor down to the next blank line and places it at the end of the line. " )
{
2019-06-16 23:38:22 +00:00
seek_blank_line ( app , Scan_Forward , PositionWithinLine_End ) ;
2019-06-09 21:05:57 +00:00
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( move_left )
CUSTOM_DOC ( " Moves the cursor one character to the left. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessProtected ) ;
2019-06-20 23:43:27 +00:00
i64 pos = view_get_cursor_pos ( app , view ) ;
2019-09-02 18:59:36 +00:00
Buffer_Cursor cursor = view_compute_cursor ( app , view , seek_pos ( pos ) ) ;
i64 character = view_relative_character_from_pos ( app , view , cursor . line , pos ) ;
i64 new_pos = view_pos_from_relative_character ( app , view , cursor . line , character - 1 ) ;
2019-09-02 21:32:52 +00:00
view_set_cursor_and_preferred_x ( app , view , seek_pos ( new_pos ) ) ;
2019-04-06 23:36:53 +00:00
no_mark_snap_to_cursor_if_shift ( app , view ) ;
2017-01-23 06:19:43 +00:00
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( move_right )
CUSTOM_DOC ( " Moves the cursor one character to the right. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessProtected ) ;
2019-06-20 23:43:27 +00:00
i64 pos = view_get_cursor_pos ( app , view ) ;
2019-09-02 18:59:36 +00:00
Buffer_Cursor cursor = view_compute_cursor ( app , view , seek_pos ( pos ) ) ;
i64 character = view_relative_character_from_pos ( app , view , cursor . line , pos ) ;
i64 new_pos = view_pos_from_relative_character ( app , view , cursor . line , character + 1 ) ;
2019-09-02 21:32:52 +00:00
view_set_cursor_and_preferred_x ( app , view , seek_pos ( new_pos ) ) ;
2019-04-06 23:36:53 +00:00
no_mark_snap_to_cursor_if_shift ( app , view ) ;
2017-01-23 06:19:43 +00:00
}
2019-06-09 21:05:57 +00:00
static void
2019-06-11 05:01:57 +00:00
current_view_scan_move ( Application_Links * app , Scan_Direction direction , Boundary_Function_List funcs ) {
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-20 23:43:27 +00:00
i64 cursor_pos = view_get_cursor_pos ( app , view ) ;
i64 pos = scan ( app , funcs , buffer , direction , cursor_pos ) ;
2019-09-02 21:32:52 +00:00
view_set_cursor_and_preferred_x ( app , view , seek_pos ( pos ) ) ;
2019-06-09 21:05:57 +00:00
no_mark_snap_to_cursor_if_shift ( app , view ) ;
}
CUSTOM_COMMAND_SIG ( move_right_whitespace_boundary )
CUSTOM_DOC ( " Seek right for the next boundary between whitespace and non-whitespace. " )
{
2019-06-11 05:01:57 +00:00
Scratch_Block scratch ( app ) ;
current_view_scan_move ( app , Scan_Forward ,
push_boundary_list ( scratch , boundary_non_whitespace ) ) ;
2019-06-09 21:05:57 +00:00
}
CUSTOM_COMMAND_SIG ( move_left_whitespace_boundary )
CUSTOM_DOC ( " Seek left for the next boundary between whitespace and non-whitespace. " )
{
2019-06-11 05:01:57 +00:00
Scratch_Block scratch ( app ) ;
current_view_scan_move ( app , Scan_Backward ,
push_boundary_list ( scratch , boundary_non_whitespace ) ) ;
2019-06-09 21:05:57 +00:00
}
CUSTOM_COMMAND_SIG ( move_right_token_boundary )
CUSTOM_DOC ( " Seek right for the next end of a token. " )
{
2019-06-11 05:01:57 +00:00
Scratch_Block scratch ( app ) ;
current_view_scan_move ( app , Scan_Forward ,
push_boundary_list ( scratch , boundary_token ) ) ;
2019-06-09 21:05:57 +00:00
}
CUSTOM_COMMAND_SIG ( move_left_token_boundary )
CUSTOM_DOC ( " Seek left for the next beginning of a token. " )
{
2019-06-11 05:01:57 +00:00
Scratch_Block scratch ( app ) ;
current_view_scan_move ( app , Scan_Backward ,
push_boundary_list ( scratch , boundary_token ) ) ;
2019-06-09 21:05:57 +00:00
}
CUSTOM_COMMAND_SIG ( move_right_whitespace_or_token_boundary )
CUSTOM_DOC ( " Seek right for the next end of a token or boundary between whitespace and non-whitespace. " )
{
2019-06-11 05:01:57 +00:00
Scratch_Block scratch ( app ) ;
current_view_scan_move ( app , Scan_Forward ,
push_boundary_list ( scratch , boundary_token , boundary_non_whitespace ) ) ;
2019-06-09 21:05:57 +00:00
}
CUSTOM_COMMAND_SIG ( move_left_whitespace_or_token_boundary )
CUSTOM_DOC ( " Seek left for the next end of a token or boundary between whitespace and non-whitespace. " )
{
2019-06-11 05:01:57 +00:00
Scratch_Block scratch ( app ) ;
current_view_scan_move ( app , Scan_Backward ,
push_boundary_list ( scratch , boundary_token , boundary_non_whitespace ) ) ;
2019-06-09 21:05:57 +00:00
}
CUSTOM_COMMAND_SIG ( move_right_alpha_numeric_boundary )
CUSTOM_DOC ( " Seek right for boundary between alphanumeric characters and non-alphanumeric characters. " )
{
2019-06-11 05:01:57 +00:00
Scratch_Block scratch ( app ) ;
current_view_scan_move ( app , Scan_Forward ,
push_boundary_list ( scratch , boundary_alpha_numeric ) ) ;
2019-06-09 21:05:57 +00:00
}
CUSTOM_COMMAND_SIG ( move_left_alpha_numeric_boundary )
CUSTOM_DOC ( " Seek left for boundary between alphanumeric characters and non-alphanumeric characters. " )
{
2019-06-11 05:01:57 +00:00
Scratch_Block scratch ( app ) ;
current_view_scan_move ( app , Scan_Backward ,
push_boundary_list ( scratch , boundary_alpha_numeric ) ) ;
2019-06-09 21:05:57 +00:00
}
CUSTOM_COMMAND_SIG ( move_right_alpha_numeric_or_camel_boundary )
CUSTOM_DOC ( " Seek right for boundary between alphanumeric characters or camel case word and non-alphanumeric characters. " )
{
2019-06-11 05:01:57 +00:00
Scratch_Block scratch ( app ) ;
current_view_scan_move ( app , Scan_Forward ,
push_boundary_list ( scratch , boundary_alpha_numeric_camel ) ) ;
2019-06-09 21:05:57 +00:00
}
CUSTOM_COMMAND_SIG ( move_left_alpha_numeric_or_camel_boundary )
CUSTOM_DOC ( " Seek left for boundary between alphanumeric characters or camel case word and non-alphanumeric characters. " )
{
2019-06-11 05:01:57 +00:00
Scratch_Block scratch ( app ) ;
current_view_scan_move ( app , Scan_Backward ,
push_boundary_list ( scratch , boundary_alpha_numeric_camel ) ) ;
2019-06-09 21:05:57 +00:00
}
# define seek_whitespace_right move_right_whitespace_boundary
# define seek_whitespace_left move_left_whitespace_boundary
# define seek_token_right move_right_token_boundary
# define seek_token_left move_left_token_boundary
# define seek_white_or_token_right move_right_whitespace_or_token_boundary
# define seek_white_or_token_left move_left_whitespace_or_token_boundary
# define seek_alphanumeric_right move_right_alpha_numeric_boundary
# define seek_alphanumeric_left move_left_alpha_numeric_boundary
# define seek_alphanumeric_or_camel_right move_right_alpha_numeric_or_camel_boundary
# define seek_alphanumeric_or_camel_left move_left_alpha_numeric_or_camel_boundary
////////////////////////////////
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( select_all )
CUSTOM_DOC ( " Puts the cursor at the top of the file, and the mark at the bottom of the file. " )
{
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 ) ;
i32 buffer_size = ( i32 ) buffer_get_size ( app , buffer ) ;
2019-09-02 21:32:52 +00:00
view_set_cursor_and_preferred_x ( app , view , seek_pos ( 0 ) ) ;
2019-04-06 23:36:53 +00:00
view_set_mark ( app , view , seek_pos ( buffer_size ) ) ;
no_mark_snap_to_cursor ( app , view ) ;
2017-01-23 06:19:43 +00:00
}
2018-05-10 08:12:47 +00:00
////////////////////////////////
2017-01-23 06:19:43 +00:00
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( to_uppercase )
CUSTOM_DOC ( " Converts all ascii text in the range between the cursor and the mark to uppercase. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessOpen ) ;
Buffer_ID buffer = view_get_buffer ( app , view , AccessOpen ) ;
2019-06-20 23:43:27 +00:00
Range_i64 range = get_view_range ( app , view ) ;
2019-06-18 04:47:00 +00:00
Scratch_Block scratch ( app ) ;
String_Const_u8 string = push_buffer_range ( app , scratch , buffer , range ) ;
string = string_mod_upper ( string ) ;
buffer_replace_range ( app , buffer , range , string ) ;
2019-09-02 21:32:52 +00:00
view_set_cursor_and_preferred_x ( app , view , seek_pos ( range . max ) ) ;
2017-01-23 06:19:43 +00:00
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( to_lowercase )
CUSTOM_DOC ( " Converts all ascii text in the range between the cursor and the mark to lowercase. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessOpen ) ;
Buffer_ID buffer = view_get_buffer ( app , view , AccessOpen ) ;
2019-06-20 23:43:27 +00:00
Range_i64 range = get_view_range ( app , view ) ;
2019-06-18 04:47:00 +00:00
Scratch_Block scratch ( app ) ;
String_Const_u8 string = push_buffer_range ( app , scratch , buffer , range ) ;
string = string_mod_lower ( string ) ;
buffer_replace_range ( app , buffer , range , string ) ;
2019-09-02 21:32:52 +00:00
view_set_cursor_and_preferred_x ( app , view , seek_pos ( range . max ) ) ;
2017-01-23 06:19:43 +00:00
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( clean_all_lines )
CUSTOM_DOC ( " Removes trailing whitespace from all lines in the current buffer. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessOpen ) ;
Buffer_ID buffer = view_get_buffer ( app , view , AccessOpen ) ;
2019-04-01 02:41:39 +00:00
2019-06-14 21:47:05 +00:00
Scratch_Block scratch ( app ) ;
2019-09-02 18:59:36 +00:00
Batch_Edit * batch_first = 0 ;
Batch_Edit * batch_last = 0 ;
2017-01-23 06:19:43 +00:00
2019-06-14 21:47:05 +00:00
String_Const_u8 text = push_whole_buffer ( app , scratch , buffer ) ;
umem whitespace_start = 0 ;
for ( umem i = 0 ; i < text . size ; i + = 1 ) {
u8 v = string_get_character ( text , i ) ;
if ( v = = ' \n ' | | i + 1 = = text . size ) {
if ( whitespace_start < i ) {
2019-09-02 18:59:36 +00:00
Batch_Edit * batch = push_array ( scratch , Batch_Edit , 1 ) ;
sll_queue_push ( batch_first , batch_last , batch ) ;
batch - > edit . text = SCu8 ( ) ;
batch - > edit . range = Ii64 ( whitespace_start , i ) ;
2017-01-23 06:19:43 +00:00
}
2019-06-14 21:47:05 +00:00
whitespace_start = i + 1 ;
}
else if ( ! character_is_whitespace ( v ) ) {
whitespace_start = i + 1 ;
2017-01-23 06:19:43 +00:00
}
}
2019-06-14 21:47:05 +00:00
2019-09-02 18:59:36 +00:00
buffer_batch_edit ( app , buffer , batch_first ) ;
2017-01-23 06:19:43 +00:00
}
2018-05-10 08:12:47 +00:00
////////////////////////////////
2017-01-23 06:19:43 +00:00
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( basic_change_active_panel )
CUSTOM_DOC ( " Change the currently active panel, moving to the panel with the next highest view_id. Will not skipe the build panel if it is open. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessAll ) ;
2019-04-06 23:36:53 +00:00
get_next_view_looped_all_panels ( app , view , AccessAll ) ;
view_set_active ( app , view ) ;
2017-01-23 06:19:43 +00:00
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( close_panel )
CUSTOM_DOC ( " Closes the currently active panel if it is not the only panel open. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessAll ) ;
2019-04-06 23:36:53 +00:00
view_close ( app , view ) ;
2017-01-23 06:19:43 +00:00
}
2018-05-10 08:12:47 +00:00
////////////////////////////////
2017-01-23 06:19:43 +00:00
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( show_scrollbar )
CUSTOM_DOC ( " Sets the current view to show it's scrollbar. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessAll ) ;
2019-04-06 23:36:53 +00:00
view_set_setting ( app , view , ViewSetting_ShowScrollbar , true ) ;
2017-02-12 23:04:50 +00:00
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( hide_scrollbar )
CUSTOM_DOC ( " Sets the current view to hide it's scrollbar. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessAll ) ;
2019-04-06 23:36:53 +00:00
view_set_setting ( app , view , ViewSetting_ShowScrollbar , false ) ;
2017-02-12 23:04:50 +00:00
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( show_filebar )
CUSTOM_DOC ( " Sets the current view to show it's filebar. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessAll ) ;
2019-04-06 23:36:53 +00:00
view_set_setting ( app , view , ViewSetting_ShowFileBar , true ) ;
2017-03-27 22:36:42 +00:00
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( hide_filebar )
CUSTOM_DOC ( " Sets the current view to hide it's filebar. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessAll ) ;
2019-04-06 23:36:53 +00:00
view_set_setting ( app , view , ViewSetting_ShowFileBar , false ) ;
2017-03-27 22:36:42 +00:00
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( toggle_filebar )
CUSTOM_DOC ( " Toggles the visibility status of the current view's filebar. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessAll ) ;
b32 value = false ;
2019-04-06 23:36:53 +00:00
view_get_setting ( app , view , ViewSetting_ShowFileBar , & value ) ;
view_set_setting ( app , view , ViewSetting_ShowFileBar , ! value ) ;
2017-03-30 15:18:16 +00:00
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( toggle_line_wrap )
CUSTOM_DOC ( " Toggles the current buffer's line wrapping status. " )
{
2019-09-04 05:31:35 +00:00
NotImplemented ;
#if 0
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-06 23:36:53 +00:00
b32 wrapped ;
buffer_get_setting ( app , buffer , BufferSetting_WrapLine , & wrapped ) ;
buffer_set_setting ( app , buffer , BufferSetting_WrapLine , ! wrapped ) ;
2019-09-04 05:31:35 +00:00
# endif
2017-01-23 06:19:43 +00:00
}
2019-02-25 23:42:13 +00:00
CUSTOM_COMMAND_SIG ( toggle_fps_meter )
CUSTOM_DOC ( " Toggles the visibility of the FPS performance meter " )
{
show_fps_hud = ! show_fps_hud ;
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( increase_line_wrap )
CUSTOM_DOC ( " Increases the current buffer's width for line wrapping. " )
{
2019-09-04 05:31:35 +00:00
NotImplemented ;
#if 0
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-02-26 23:17:53 +00:00
i32 wrap = 0 ;
2019-04-05 02:03:36 +00:00
buffer_get_setting ( app , buffer , BufferSetting_WrapPosition , & wrap ) ;
buffer_set_setting ( app , buffer , BufferSetting_WrapPosition , wrap + 10 ) ;
2019-09-04 05:31:35 +00:00
# endif
2017-01-23 06:19:43 +00:00
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( decrease_line_wrap )
CUSTOM_DOC ( " Decrases the current buffer's width for line wrapping. " )
{
2019-09-04 05:31:35 +00:00
NotImplemented ;
#if 0
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-02-26 23:17:53 +00:00
i32 wrap = 0 ;
2019-04-05 02:03:36 +00:00
buffer_get_setting ( app , buffer , BufferSetting_WrapPosition , & wrap ) ;
buffer_set_setting ( app , buffer , BufferSetting_WrapPosition , wrap - 10 ) ;
2019-09-04 05:31:35 +00:00
# endif
2017-01-23 06:19:43 +00:00
}
2017-11-21 18:25:19 +00:00
CUSTOM_COMMAND_SIG ( increase_face_size )
CUSTOM_DOC ( " Increase the size of the face used by the current buffer. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessAll ) ;
Buffer_ID buffer = view_get_buffer ( app , view , AccessAll ) ;
2019-06-20 04:45:58 +00:00
Face_ID face_id = get_face_id ( app , buffer ) ;
2017-11-21 18:25:19 +00:00
Face_Description description = get_face_description ( app , face_id ) ;
2019-07-24 07:41:40 +00:00
+ + description . parameters . pt_size ;
2017-11-21 18:25:19 +00:00
try_modify_face ( app , face_id , & description ) ;
}
CUSTOM_COMMAND_SIG ( decrease_face_size )
CUSTOM_DOC ( " Decrease the size of the face used by the current buffer. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessAll ) ;
Buffer_ID buffer = view_get_buffer ( app , view , AccessAll ) ;
2019-06-20 04:45:58 +00:00
Face_ID face_id = get_face_id ( app , buffer ) ;
2017-11-21 18:25:19 +00:00
Face_Description description = get_face_description ( app , face_id ) ;
2019-07-24 07:41:40 +00:00
- - description . parameters . pt_size ;
2017-11-21 18:25:19 +00:00
try_modify_face ( app , face_id , & description ) ;
}
2018-12-17 04:31:04 +00:00
CUSTOM_COMMAND_SIG ( mouse_wheel_change_face_size )
CUSTOM_DOC ( " Reads the state of the mouse wheel and uses it to either increase or decrease the face size. " )
{
static Microsecond_Time_Stamp next_resize_time = 0 ;
Microsecond_Time_Stamp now = get_microseconds_timestamp ( app ) ;
if ( now > = next_resize_time ) {
next_resize_time = now + 50 * 1000 ;
Mouse_State mouse = get_mouse_state ( app ) ;
if ( mouse . wheel > 0 ) {
decrease_face_size ( app ) ;
}
else if ( mouse . wheel < 0 ) {
increase_face_size ( app ) ;
}
}
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( toggle_virtual_whitespace )
CUSTOM_DOC ( " Toggles the current buffer's virtual whitespace status. " )
{
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-02-26 23:17:53 +00:00
i32 vwhite = 0 ;
2019-04-05 02:03:36 +00:00
buffer_get_setting ( app , buffer , BufferSetting_VirtualWhitespace , & vwhite ) ;
buffer_set_setting ( app , buffer , BufferSetting_VirtualWhitespace , ! vwhite ) ;
2017-01-23 06:19:43 +00:00
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( toggle_show_whitespace )
CUSTOM_DOC ( " Toggles the current buffer's whitespace visibility status. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessProtected ) ;
2019-04-06 23:36:53 +00:00
b32 show_whitespace ;
view_get_setting ( app , view , ViewSetting_ShowWhitespace , & show_whitespace ) ;
view_set_setting ( app , view , ViewSetting_ShowWhitespace , ! show_whitespace ) ;
2017-01-23 06:19:43 +00:00
}
2019-02-27 21:14:25 +00:00
CUSTOM_COMMAND_SIG ( toggle_line_numbers )
CUSTOM_DOC ( " Toggles the left margin line numbers. " )
{
global_config . show_line_number_margins = ! global_config . show_line_number_margins ;
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( eol_dosify )
CUSTOM_DOC ( " Puts the buffer in DOS line ending mode. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessOpen ) ;
Buffer_ID buffer = view_get_buffer ( app , view , AccessOpen ) ;
2019-04-05 02:03:36 +00:00
buffer_set_setting ( app , buffer , BufferSetting_Eol , 1 ) ;
2017-01-23 06:19:43 +00:00
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( eol_nixify )
CUSTOM_DOC ( " Puts the buffer in NIX line ending mode. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessOpen ) ;
Buffer_ID buffer = view_get_buffer ( app , view , AccessOpen ) ;
2019-04-05 02:03:36 +00:00
buffer_set_setting ( app , buffer , BufferSetting_Eol , 0 ) ;
2017-01-23 06:19:43 +00:00
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( exit_4coder )
CUSTOM_DOC ( " Attempts to close 4coder. " )
{
2017-01-23 06:19:43 +00:00
send_exit_signal ( app ) ;
}
2018-05-10 08:12:47 +00:00
////////////////////////////////
2017-01-23 06:19:43 +00:00
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( goto_line )
CUSTOM_DOC ( " Queries the user for a number, and jumps the cursor to the corresponding line. " )
{
2019-06-01 23:58:28 +00:00
u8 string_space [ 256 ] ;
2018-11-20 08:18:54 +00:00
Query_Bar bar = { } ;
2019-06-01 23:58:28 +00:00
bar . prompt = string_u8_litexpr ( " Goto Line: " ) ;
bar . string = SCu8 ( string_space , ( umem ) 0 ) ;
bar . string_capacity = sizeof ( string_space ) ;
2017-01-23 06:19:43 +00:00
if ( query_user_number ( app , & bar ) ) {
2019-06-01 23:58:28 +00:00
i32 line_number = ( i32 ) string_to_integer ( bar . string , 10 ) ;
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessProtected ) ;
2019-09-02 21:32:52 +00:00
view_set_cursor_and_preferred_x ( app , view , seek_line_col ( line_number , 0 ) ) ;
2017-01-23 06:19:43 +00:00
}
}
CUSTOM_COMMAND_SIG ( search ) ;
CUSTOM_COMMAND_SIG ( reverse_search ) ;
2018-09-22 00:29:32 +00:00
static void
2019-08-02 20:07:08 +00:00
isearch__update_highlight ( Application_Links * app , View_ID view , Range_i64 range ) {
view_set_highlight_range ( app , view , range ) ;
2019-09-02 21:32:52 +00:00
view_set_cursor_and_preferred_x ( app , view , seek_pos ( range . start ) ) ;
2018-09-22 00:29:32 +00:00
}
2017-01-23 06:19:43 +00:00
static void
2019-06-01 23:58:28 +00:00
isearch ( Application_Links * app , b32 start_reversed , String_Const_u8 query_init , b32 on_the_query_init_string ) {
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessProtected ) ;
2019-06-20 04:45:58 +00:00
Buffer_ID buffer = view_get_buffer ( app , view , AccessProtected ) ;
if ( ! buffer_exists ( app , buffer ) ) {
2018-09-27 20:15:32 +00:00
return ;
}
2017-01-23 06:19:43 +00:00
2018-11-20 08:18:54 +00:00
Query_Bar bar = { } ;
2018-09-27 20:15:32 +00:00
if ( start_query_bar ( app , & bar , 0 ) = = 0 ) {
return ;
}
2017-01-23 06:19:43 +00:00
2019-02-26 23:08:42 +00:00
b32 reverse = start_reversed ;
2019-06-20 23:43:27 +00:00
i64 first_pos = view_get_cursor_pos ( app , view ) ;
2017-03-29 16:32:06 +00:00
2019-06-20 23:43:27 +00:00
i64 pos = first_pos ;
2017-03-29 16:32:06 +00:00
if ( query_init . size ! = 0 ) {
pos + = 2 ;
}
2019-06-20 23:43:27 +00:00
i64 start_pos = pos ;
Range_i64 match = Ii64 ( pos ) ;
2017-01-23 06:19:43 +00:00
2019-06-01 23:58:28 +00:00
u8 bar_string_space [ 256 ] ;
bar . string = SCu8 ( bar_string_space , query_init . size ) ;
block_copy ( bar . string . str , query_init . str , query_init . size ) ;
2017-01-23 06:19:43 +00:00
2019-06-01 23:58:28 +00:00
String_Const_char isearch_str = string_litexpr ( " I-Search: " ) ;
String_Const_char rsearch_str = string_litexpr ( " Reverse-I-Search: " ) ;
2017-01-23 06:19:43 +00:00
2019-02-26 23:08:42 +00:00
b32 first_step = true ;
2017-03-29 16:32:06 +00:00
2019-08-01 03:28:43 +00:00
// TODO(allen): rewrite
2019-08-02 20:07:08 +00:00
isearch__update_highlight ( app , view , match ) ;
2018-09-30 12:14:47 +00:00
cursor_is_hidden = true ;
2018-09-22 00:29:32 +00:00
2018-11-20 08:18:54 +00:00
User_Input in = { } ;
2017-01-23 06:19:43 +00:00
for ( ; ; ) {
// NOTE(allen): Change the bar's prompt to match the current direction.
2017-03-29 16:32:06 +00:00
if ( reverse ) {
2019-06-01 23:58:28 +00:00
bar . prompt = SCu8 ( rsearch_str ) ;
2017-03-29 16:32:06 +00:00
}
else {
2019-06-01 23:58:28 +00:00
bar . prompt = SCu8 ( isearch_str ) ;
2017-03-29 16:32:06 +00:00
}
2017-01-23 06:19:43 +00:00
2019-02-26 23:08:42 +00:00
b32 step_forward = false ;
b32 step_backward = false ;
b32 backspace = false ;
b32 suppress_highligh_update = false ;
2017-01-23 06:19:43 +00:00
2017-03-29 16:32:06 +00:00
if ( ! first_step ) {
2017-04-15 21:47:23 +00:00
in = get_user_input ( app , EventOnAnyKey , EventOnEsc ) ;
2017-03-29 16:32:06 +00:00
if ( in . abort ) break ;
2019-02-26 23:30:08 +00:00
u8 character [ 4 ] ;
2019-02-26 23:17:53 +00:00
u32 length = to_writable_character ( in , character ) ;
2017-04-15 21:47:23 +00:00
2019-02-26 23:08:42 +00:00
b32 made_change = false ;
2017-03-29 16:32:06 +00:00
if ( in . key . keycode = = ' \n ' | | in . key . keycode = = ' \t ' ) {
2018-06-16 20:57:32 +00:00
if ( in . key . modifiers [ MDFR_CONTROL_INDEX ] ) {
2019-06-01 23:58:28 +00:00
bar . string . size = cstring_length ( previous_isearch_query ) ;
block_copy ( bar . string . str , previous_isearch_query , bar . string . size ) ;
2018-06-16 20:57:32 +00:00
}
else {
2019-06-01 23:58:28 +00:00
umem size = bar . string . size ;
size = clamp_top ( size , sizeof ( previous_isearch_query ) - 1 ) ;
block_copy ( previous_isearch_query , bar . string . str , size ) ;
previous_isearch_query [ size ] = 0 ;
2018-06-16 20:57:32 +00:00
break ;
}
2017-03-29 16:32:06 +00:00
}
2017-04-15 21:47:23 +00:00
else if ( length ! = 0 & & key_is_unmodified ( & in . key ) ) {
2019-06-01 23:58:28 +00:00
String_u8 string = Su8 ( bar . string , sizeof ( bar_string_space ) ) ;
string_append ( & string , SCu8 ( character , length ) ) ;
bar . string = string . string ;
2017-03-29 16:32:06 +00:00
made_change = true ;
}
else if ( in . key . keycode = = key_back ) {
2018-06-16 20:57:32 +00:00
if ( key_is_unmodified ( & in . key ) ) {
2019-06-01 23:58:28 +00:00
umem old_bar_string_size = bar . string . size ;
bar . string = backspace_utf8 ( bar . string ) ;
made_change = ( bar . string . size < old_bar_string_size ) ;
2018-06-16 20:57:32 +00:00
backspace = true ;
}
else if ( in . key . modifiers [ MDFR_CONTROL_INDEX ] ) {
if ( bar . string . size > 0 ) {
made_change = true ;
bar . string . size = 0 ;
backspace = true ;
}
}
2017-03-29 16:32:06 +00:00
}
if ( ( in . command . command = = search ) | | in . key . keycode = = key_page_down | | in . key . keycode = = key_down ) {
step_forward = true ;
}
2018-09-22 23:45:24 +00:00
if ( in . command . command = = mouse_wheel_scroll ) {
mouse_wheel_scroll ( app ) ;
suppress_highligh_update = true ;
}
2017-03-29 16:32:06 +00:00
if ( ( in . command . command = = reverse_search ) | | in . key . keycode = = key_page_up | | in . key . keycode = = key_up ) {
step_backward = true ;
}
2017-01-23 06:19:43 +00:00
}
2017-03-29 16:32:06 +00:00
else {
2018-06-16 20:57:32 +00:00
if ( query_init . size ! = 0 & & on_the_query_init_string ) {
2017-03-29 16:32:06 +00:00
step_backward = true ;
2017-01-23 06:19:43 +00:00
}
2017-03-29 16:32:06 +00:00
first_step = false ;
2017-01-23 06:19:43 +00:00
}
start_pos = pos ;
if ( step_forward & & reverse ) {
start_pos = match . start + 1 ;
pos = start_pos ;
2017-03-29 16:32:06 +00:00
reverse = false ;
step_forward = false ;
2017-01-23 06:19:43 +00:00
}
if ( step_backward & & ! reverse ) {
start_pos = match . start - 1 ;
pos = start_pos ;
2017-03-29 16:32:06 +00:00
reverse = true ;
step_backward = false ;
2017-01-23 06:19:43 +00:00
}
2017-03-29 16:32:06 +00:00
if ( ! backspace ) {
2017-01-23 06:19:43 +00:00
if ( reverse ) {
2019-06-20 23:43:27 +00:00
i64 new_pos = 0 ;
2019-07-29 20:24:47 +00:00
buffer_seek_string_insensitive_backward ( app , buffer , start_pos + 1 , 0 , bar . string , & new_pos ) ;
2017-01-23 06:19:43 +00:00
if ( new_pos > = 0 ) {
if ( step_backward ) {
pos = new_pos ;
start_pos = new_pos ;
2019-07-29 20:24:47 +00:00
buffer_seek_string_insensitive_backward ( app , buffer , start_pos + 1 , 0 , bar . string , & new_pos ) ;
2017-03-29 16:32:06 +00:00
if ( new_pos < 0 ) {
new_pos = start_pos ;
}
2017-01-23 06:19:43 +00:00
}
match . start = new_pos ;
2019-06-01 23:58:28 +00:00
match . end = match . start + ( i32 ) bar . string . size ;
2017-01-23 06:19:43 +00:00
}
}
else {
2019-06-20 23:43:27 +00:00
i64 new_pos = 0 ;
2019-07-29 20:24:47 +00:00
buffer_seek_string_insensitive_forward ( app , buffer , start_pos , 0 , bar . string , & new_pos ) ;
2019-06-20 23:43:27 +00:00
i64 buffer_size = buffer_get_size ( app , buffer ) ;
2019-04-01 02:41:39 +00:00
if ( new_pos < buffer_size ) {
2017-01-23 06:19:43 +00:00
if ( step_forward ) {
pos = new_pos ;
start_pos = new_pos ;
2019-07-29 20:24:47 +00:00
buffer_seek_string_insensitive_forward ( app , buffer , start_pos , 0 , bar . string , & new_pos ) ;
2019-04-01 02:41:39 +00:00
if ( new_pos > = buffer_size ) {
2017-03-29 16:32:06 +00:00
new_pos = start_pos ;
}
2017-01-23 06:19:43 +00:00
}
match . start = new_pos ;
2019-06-01 23:58:28 +00:00
match . end = match . start + ( i32 ) bar . string . size ;
2017-01-23 06:19:43 +00:00
}
}
}
else {
2019-06-01 23:58:28 +00:00
if ( match . end > match . start + ( i32 ) bar . string . size ) {
match . end = match . start + ( i32 ) bar . string . size ;
2017-01-23 06:19:43 +00:00
}
}
2018-09-22 23:45:24 +00:00
if ( ! suppress_highligh_update ) {
2019-08-02 20:07:08 +00:00
isearch__update_highlight ( app , view , match ) ;
2018-09-22 23:45:24 +00:00
}
2017-01-23 06:19:43 +00:00
}
2017-03-29 16:32:06 +00:00
2019-08-02 20:07:08 +00:00
view_disable_highlight_range ( app , view ) ;
2018-09-30 12:14:47 +00:00
cursor_is_hidden = false ;
2018-09-27 20:15:32 +00:00
2017-01-23 06:19:43 +00:00
if ( in . abort ) {
2019-06-01 23:58:28 +00:00
umem size = bar . string . size ;
size = clamp_top ( size , sizeof ( previous_isearch_query ) - 1 ) ;
block_copy ( previous_isearch_query , bar . string . str , size ) ;
previous_isearch_query [ size ] = 0 ;
2019-09-02 21:32:52 +00:00
view_set_cursor_and_preferred_x ( app , view , seek_pos ( first_pos ) ) ;
2017-01-23 06:19:43 +00:00
}
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( search )
CUSTOM_DOC ( " Begins an incremental search down through the current buffer for a user specified string. " )
{
2019-06-01 23:58:28 +00:00
isearch ( app , false , SCu8 ( ) , false ) ;
2017-01-23 06:19:43 +00:00
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( reverse_search )
CUSTOM_DOC ( " Begins an incremental search up through the current buffer for a user specified string. " )
{
2019-06-01 23:58:28 +00:00
isearch ( app , true , SCu8 ( ) , false ) ;
2017-03-29 16:32:06 +00:00
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( search_identifier )
CUSTOM_DOC ( " Begins an incremental search down through the current buffer for the word or token under the cursor. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessProtected ) ;
Buffer_ID buffer_id = view_get_buffer ( app , view , AccessProtected ) ;
2019-06-20 23:43:27 +00:00
i64 pos = view_get_cursor_pos ( app , view ) ;
2019-06-01 23:58:28 +00:00
Scratch_Block scratch ( app ) ;
2019-06-20 23:43:27 +00:00
String_Const_u8 query = push_enclose_range_at_pos ( app , scratch , buffer_id , pos , enclose_alpha_numeric_underscore ) ;
2018-06-16 20:57:32 +00:00
isearch ( app , false , query , true ) ;
2017-03-29 16:32:06 +00:00
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( reverse_search_identifier )
CUSTOM_DOC ( " Begins an incremental search up through the current buffer for the word or token under the cursor. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessProtected ) ;
Buffer_ID buffer_id = view_get_buffer ( app , view , AccessProtected ) ;
2019-06-20 23:43:27 +00:00
i64 pos = view_get_cursor_pos ( app , view ) ;
2019-06-01 23:58:28 +00:00
Scratch_Block scratch ( app ) ;
2019-06-20 23:43:27 +00:00
String_Const_u8 query = push_enclose_range_at_pos ( app , scratch , buffer_id , pos , enclose_alpha_numeric_underscore ) ;
2018-06-16 20:57:32 +00:00
isearch ( app , true , query , true ) ;
2017-01-23 06:19:43 +00:00
}
2019-07-13 00:43:17 +00:00
struct String_Pair {
b32 valid ;
String_Const_u8 a ;
String_Const_u8 b ;
} ;
internal String_Pair
query_user_replace_pair ( Application_Links * app , Arena * arena ) {
2019-07-13 03:19:24 +00:00
Query_Bar * replace = push_array ( arena , Query_Bar , 1 ) ;
u8 * replace_space = push_array ( arena , u8 , KB ( 1 ) ) ;
replace - > prompt = string_u8_litexpr ( " Replace: " ) ;
replace - > string = SCu8 ( replace_space , ( umem ) 0 ) ;
replace - > string_capacity = KB ( 1 ) ;
2017-01-23 06:19:43 +00:00
2019-07-13 03:19:24 +00:00
Query_Bar * with = push_array ( arena , Query_Bar , 1 ) ;
u8 * with_space = push_array ( arena , u8 , KB ( 1 ) ) ;
with - > prompt = string_u8_litexpr ( " With: " ) ;
with - > string = SCu8 ( with_space , ( umem ) 0 ) ;
with - > string_capacity = KB ( 1 ) ;
2017-01-23 06:19:43 +00:00
2019-07-13 00:43:17 +00:00
String_Pair result = { } ;
2019-07-13 03:19:24 +00:00
if ( query_user_string ( app , replace ) & & replace - > string . size ! = 0 & & query_user_string ( app , with ) ) {
2019-07-13 00:43:17 +00:00
result . valid = true ;
2019-07-13 03:19:24 +00:00
result . a = replace - > string ;
result . b = with - > string ;
2017-01-23 06:19:43 +00:00
}
2019-07-13 00:43:17 +00:00
return ( result ) ;
}
2019-07-13 03:19:24 +00:00
// NOTE(allen): This is a bit of a hacky setup because of Query_Bar lifetimes. This must be
// called as the last operation of a command.
2019-07-13 00:43:17 +00:00
internal void
replace_in_range_query_user ( Application_Links * app , Buffer_ID buffer , Range_i64 range ) {
Scratch_Block scratch ( app ) ;
String_Pair pair = query_user_replace_pair ( app , scratch ) ;
if ( pair . valid ) {
replace_in_range ( app , buffer , range , pair . a , pair . b ) ;
}
}
CUSTOM_COMMAND_SIG ( replace_in_range )
CUSTOM_DOC ( " Queries the user for a needle and string. Replaces all occurences of needle with string in the range between cursor and the mark in the active buffer. " )
{
View_ID view = get_active_view ( app , AccessOpen ) ;
Buffer_ID buffer = view_get_buffer ( app , view , AccessOpen ) ;
Range_i64 range = get_view_range ( app , view ) ;
replace_in_range_query_user ( app , buffer , range ) ;
}
CUSTOM_COMMAND_SIG ( replace_in_buffer )
CUSTOM_DOC ( " Queries the user for a needle and string. Replaces all occurences of needle with string in the active buffer. " )
{
View_ID view = get_active_view ( app , AccessOpen ) ;
Buffer_ID buffer = view_get_buffer ( app , view , AccessOpen ) ;
Range_i64 range = buffer_range ( app , buffer ) ;
replace_in_range_query_user ( app , buffer , range ) ;
}
CUSTOM_COMMAND_SIG ( replace_in_all_buffers )
CUSTOM_DOC ( " Queries the user for a needle and string. Replaces all occurences of needle with string in all editable buffers. " )
{
global_history_edit_group_begin ( app ) ;
Scratch_Block scratch ( app ) ;
String_Pair pair = query_user_replace_pair ( app , scratch ) ;
for ( Buffer_ID buffer = get_buffer_next ( app , 0 , AccessOpen ) ;
buffer ! = 0 ;
buffer = get_buffer_next ( app , buffer , AccessOpen ) ) {
Range_i64 range = buffer_range ( app , buffer ) ;
replace_in_range ( app , buffer , range , pair . a , pair . b ) ;
}
global_history_edit_group_end ( app ) ;
2017-01-23 06:19:43 +00:00
}
2017-03-29 16:32:06 +00:00
static void
2019-06-20 23:43:27 +00:00
query_replace_base ( Application_Links * app , View_ID view , Buffer_ID buffer_id , i64 pos , String_Const_u8 r , String_Const_u8 w ) {
i64 new_pos = 0 ;
2019-06-18 22:56:09 +00:00
buffer_seek_string_forward ( app , buffer_id , pos - 1 , 0 , r , & new_pos ) ;
2017-03-29 16:32:06 +00:00
2018-09-30 12:14:47 +00:00
cursor_is_hidden = true ;
2019-06-20 23:43:27 +00:00
i64 buffer_size = buffer_get_size ( app , buffer_id ) ;
2019-04-01 02:41:39 +00:00
2018-11-20 08:18:54 +00:00
User_Input in = { } ;
2019-04-01 02:41:39 +00:00
for ( ; new_pos < buffer_size ; ) {
2019-06-20 23:43:27 +00:00
Range_i64 match = Ii64 ( new_pos , new_pos + r . size ) ;
2019-08-02 20:07:08 +00:00
isearch__update_highlight ( app , view , match ) ;
2017-03-29 16:32:06 +00:00
2018-11-20 08:18:54 +00:00
in = get_user_input ( app , EventOnAnyKey , EventOnMouseLeftButton | EventOnMouseRightButton ) ;
2018-09-30 12:14:47 +00:00
if ( in . abort | | in . key . keycode = = key_esc | | ! key_is_unmodified ( & in . key ) ) break ;
2017-03-29 16:32:06 +00:00
2018-09-30 12:14:47 +00:00
if ( in . key . character = = ' y ' | | in . key . character = = ' Y ' | |
in . key . character = = ' \n ' | | in . key . character = = ' \t ' ) {
2019-04-05 23:30:24 +00:00
buffer_replace_range ( app , buffer_id , match , w ) ;
2019-06-20 23:43:27 +00:00
pos = match . start + w . size ;
2017-03-29 16:32:06 +00:00
}
else {
pos = match . max ;
}
2019-06-01 23:58:28 +00:00
buffer_seek_string_forward ( app , buffer_id , pos , 0 , r , & new_pos ) ;
2017-03-29 16:32:06 +00:00
}
2019-08-02 20:07:08 +00:00
view_disable_highlight_range ( app , view ) ;
2018-09-30 12:14:47 +00:00
cursor_is_hidden = false ;
if ( in . abort ) {
return ;
}
2017-03-29 16:32:06 +00:00
2019-09-02 21:32:52 +00:00
view_set_cursor_and_preferred_x ( app , view , seek_pos ( pos ) ) ;
2017-03-29 16:32:06 +00:00
}
2017-11-21 18:25:19 +00:00
static void
2019-06-20 23:43:27 +00:00
query_replace_parameter ( Application_Links * app , String_Const_u8 replace_str , i64 start_pos , b32 add_replace_query_bar ) {
2019-06-01 23:58:28 +00:00
Query_Bar replace = { } ;
replace . prompt = string_u8_litexpr ( " Replace: " ) ;
2017-11-21 18:25:19 +00:00
replace . string = replace_str ;
if ( add_replace_query_bar ) {
start_query_bar ( app , & replace , 0 ) ;
}
2017-01-23 06:19:43 +00:00
2019-06-01 23:58:28 +00:00
Query_Bar with = { } ;
u8 with_space [ 1024 ] ;
with . prompt = string_u8_litexpr ( " With: " ) ;
with . string = SCu8 ( with_space , ( umem ) 0 ) ;
with . string_capacity = sizeof ( with_space ) ;
2017-01-23 06:19:43 +00:00
2019-04-06 23:36:53 +00:00
if ( query_user_string ( app , & with ) ) {
2019-06-01 23:58:28 +00:00
String_Const_u8 r = replace . string ;
String_Const_u8 w = with . string ;
2019-04-06 23:36:53 +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-20 23:43:27 +00:00
i64 pos = start_pos ;
2019-04-06 23:36:53 +00:00
2019-06-01 23:58:28 +00:00
Query_Bar bar = { } ;
bar . prompt = string_u8_litexpr ( " Replace? (y)es, (n)ext, (esc) \n " ) ;
2019-04-06 23:36:53 +00:00
start_query_bar ( app , & bar , 0 ) ;
2019-06-19 02:31:59 +00:00
query_replace_base ( app , view , buffer , pos , r , w ) ;
2018-09-30 12:14:47 +00:00
}
2017-03-29 16:32:06 +00:00
}
2017-11-21 18:25:19 +00:00
CUSTOM_COMMAND_SIG ( query_replace )
CUSTOM_DOC ( " Queries the user for two strings, and incrementally replaces every occurence of the first string with the second string. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessOpen ) ;
Buffer_ID buffer = view_get_buffer ( app , view , AccessOpen ) ;
2019-04-05 02:03:36 +00:00
if ( buffer ! = 0 ) {
Query_Bar replace = { } ;
2019-06-01 23:58:28 +00:00
u8 replace_space [ 1024 ] ;
replace . prompt = string_u8_litexpr ( " Replace: " ) ;
replace . string = SCu8 ( replace_space , ( umem ) 0 ) ;
replace . string_capacity = sizeof ( replace_space ) ;
2019-04-05 02:03:36 +00:00
if ( query_user_string ( app , & replace ) ) {
if ( replace . string . size > 0 ) {
2019-06-20 23:43:27 +00:00
i64 pos = view_get_cursor_pos ( app , view ) ;
2019-04-06 23:36:53 +00:00
query_replace_parameter ( app , replace . string , pos , false ) ;
2019-04-05 02:03:36 +00:00
}
}
2018-09-30 12:14:47 +00:00
}
2017-11-21 18:25:19 +00:00
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( query_replace_identifier )
CUSTOM_DOC ( " Queries the user for a string, and incrementally replace every occurence of the word or token found at the cursor with the specified string. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessOpen ) ;
Buffer_ID buffer = view_get_buffer ( app , view , AccessOpen ) ;
2019-06-09 21:05:57 +00:00
if ( buffer ! = 0 ) {
2019-06-01 23:58:28 +00:00
Scratch_Block scratch ( app ) ;
2019-06-20 23:43:27 +00:00
i64 pos = view_get_cursor_pos ( app , view ) ;
Range_i64 range = enclose_pos_alpha_numeric_underscore ( app , buffer , pos ) ;
2019-06-09 21:05:57 +00:00
String_Const_u8 replace = push_buffer_range ( app , scratch , buffer , range ) ;
2019-04-05 02:03:36 +00:00
if ( replace . size ! = 0 ) {
query_replace_parameter ( app , replace , range . min , true ) ;
}
2017-01-23 06:19:43 +00:00
}
}
2018-05-10 03:55:00 +00:00
CUSTOM_COMMAND_SIG ( query_replace_selection )
CUSTOM_DOC ( " Queries the user for a string, and incrementally replace every occurence of the string found in the selected range with the specified string. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessOpen ) ;
Buffer_ID buffer = view_get_buffer ( app , view , AccessOpen ) ;
2019-04-05 02:03:36 +00:00
if ( buffer ! = 0 ) {
2019-06-20 23:43:27 +00:00
Scratch_Block scratch ( app ) ;
Range_i64 range = get_view_range ( app , view ) ;
String_Const_u8 replace = push_buffer_range ( app , scratch , buffer , range ) ;
if ( replace . size ! = 0 ) {
query_replace_parameter ( app , replace , range . min , true ) ;
2018-05-10 03:55:00 +00:00
}
}
}
2018-05-10 08:12:47 +00:00
////////////////////////////////
2017-02-12 23:04:50 +00:00
2018-08-10 22:57:46 +00:00
static void
2019-06-01 23:58:28 +00:00
save_all_dirty_buffers_with_postfix ( Application_Links * app , String_Const_u8 postfix ) {
2019-04-05 02:03:36 +00:00
Arena * scratch = context_get_arena ( app ) ;
2019-06-19 02:31:59 +00:00
for ( Buffer_ID buffer = get_buffer_next ( app , 0 , AccessOpen ) ;
2019-04-05 02:03:36 +00:00
buffer ! = 0 ;
2019-06-19 02:31:59 +00:00
buffer = get_buffer_next ( app , buffer , AccessOpen ) ) {
Dirty_State dirty = buffer_get_dirty_state ( app , buffer ) ;
2019-04-05 02:03:36 +00:00
if ( dirty = = DirtyState_UnsavedChanges ) {
2019-06-01 23:58:28 +00:00
Temp_Memory temp = begin_temp ( scratch ) ;
2019-06-02 03:07:57 +00:00
String_Const_u8 file_name = push_buffer_file_name ( app , scratch , buffer ) ;
2019-06-01 23:58:28 +00:00
if ( string_match ( string_postfix ( file_name , postfix . size ) , postfix ) ) {
buffer_save ( app , buffer , file_name , 0 ) ;
2018-08-10 22:57:46 +00:00
}
2019-06-01 23:58:28 +00:00
end_temp ( temp ) ;
2017-02-12 23:04:50 +00:00
}
}
}
2018-08-10 22:57:46 +00:00
CUSTOM_COMMAND_SIG ( save_all_dirty_buffers )
CUSTOM_DOC ( " Saves all buffers marked dirty (showing the '*' indicator). " )
{
2019-06-01 23:58:28 +00:00
String_Const_u8 empty = { } ;
2018-08-10 22:57:46 +00:00
save_all_dirty_buffers_with_postfix ( app , empty ) ;
}
2017-11-21 21:30:40 +00:00
static void
2019-06-01 23:58:28 +00:00
delete_file_base ( Application_Links * app , String_Const_u8 file_name , Buffer_ID buffer_id ) {
String_Const_u8 path = string_remove_last_folder ( file_name ) ;
Scratch_Block scratch ( app ) ;
List_String_Const_u8 list = { } ;
# if OS_WINDOWS
string_list_push_u8_lit ( scratch , & list , " del " ) ;
# elif OS_LINUX || OS_MAC
string_list_push_u8_lit ( scratch , & list , " rm " ) ;
2017-11-21 21:30:40 +00:00
# else
# error no delete file command for this platform
# endif
2019-06-01 23:58:28 +00:00
string_list_pushf ( scratch , & list , " \" %.*s \" " , string_expand ( file_name ) ) ;
String_Const_u8 cmd = string_list_flatten ( scratch , list , StringFill_NullTerminate ) ;
exec_system_command ( app , 0 , buffer_identifier ( 0 ) , path , cmd , 0 ) ;
2019-06-19 02:31:59 +00:00
buffer_kill ( app , buffer_id , BufferKill_AlwaysKill ) ;
2017-11-21 21:30:40 +00:00
}
CUSTOM_COMMAND_SIG ( delete_file_query )
CUSTOM_DOC ( " Deletes the file of the current buffer if 4coder has the appropriate access rights. Will ask the user for confirmation first. " )
2017-11-21 19:48:04 +00:00
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessAll ) ;
Buffer_ID buffer = view_get_buffer ( app , view , AccessAll ) ;
2019-06-01 23:58:28 +00:00
Scratch_Block scratch ( app ) ;
2019-06-02 03:07:57 +00:00
String_Const_u8 file_name = push_buffer_file_name ( app , scratch , buffer ) ;
2019-04-05 02:03:36 +00:00
if ( file_name . size > 0 ) {
2019-06-01 23:58:28 +00:00
Query_Bar bar = { } ;
2019-06-18 22:56:09 +00:00
bar . prompt = push_u8_stringf ( scratch , " Delete '%.*s' (Y)es, (n)o " , string_expand ( file_name ) ) ;
2019-04-05 02:03:36 +00:00
if ( start_query_bar ( app , & bar , 0 ) ! = 0 ) {
2019-06-01 23:58:28 +00:00
b32 cancelled = false ;
for ( ; ! cancelled ; ) {
User_Input in = get_user_input ( app , EventOnAnyKey , 0 ) ;
switch ( in . key . keycode ) {
case ' Y ' :
{
delete_file_base ( app , file_name , buffer ) ;
2019-06-02 00:49:03 +00:00
cancelled = true ;
2019-06-01 23:58:28 +00:00
} break ;
case key_shift :
case key_ctrl :
case key_alt :
case key_cmnd :
case key_caps :
{ } break ;
default :
{
cancelled = true ;
} break ;
}
2019-04-05 02:03:36 +00:00
}
}
2017-11-21 21:30:40 +00:00
}
}
2018-03-24 10:06:45 +00:00
CUSTOM_COMMAND_SIG ( save_to_query )
2018-09-15 23:48:02 +00:00
CUSTOM_DOC ( " Queries the user for a file name and saves the contents of the current buffer, altering the buffer's name too. " )
2018-03-24 10:06:45 +00:00
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessAll ) ;
Buffer_ID buffer = view_get_buffer ( app , view , AccessAll ) ;
2018-03-24 10:06:45 +00:00
2019-04-05 02:03:36 +00:00
Arena * scratch = context_get_arena ( app ) ;
2019-06-01 23:58:28 +00:00
Temp_Memory temp = begin_temp ( scratch ) ;
2019-06-02 03:07:57 +00:00
String_Const_u8 buffer_name = push_buffer_unique_name ( app , scratch , buffer ) ;
2018-03-24 10:06:45 +00:00
2019-04-05 02:03:36 +00:00
// Query the user
2019-06-01 23:58:28 +00:00
u8 name_space [ 4096 ] ;
2019-04-05 02:03:36 +00:00
Query_Bar bar = { } ;
2019-06-18 22:56:09 +00:00
bar . prompt = push_u8_stringf ( scratch , " Save '%.*s' to: " , string_expand ( buffer_name ) ) ;
2019-06-01 23:58:28 +00:00
bar . string = SCu8 ( name_space , ( umem ) 0 ) ;
bar . string_capacity = sizeof ( name_space ) ;
2019-04-05 02:03:36 +00:00
if ( query_user_string ( app , & bar ) ) {
if ( bar . string . size ! = 0 ) {
2019-06-01 23:58:28 +00:00
List_String_Const_u8 new_file_name_list = { } ;
string_list_push ( scratch , & new_file_name_list , push_hot_directory ( app , scratch ) ) ;
string_list_push ( scratch , & new_file_name_list , bar . string ) ;
String_Const_u8 new_file_name = string_list_flatten ( scratch , new_file_name_list ) ;
if ( buffer_save ( app , buffer , new_file_name , BufferSave_IgnoreDirtyFlag ) ) {
2019-06-19 02:31:59 +00:00
Buffer_ID new_buffer = create_buffer ( app , new_file_name , BufferCreate_NeverNew | BufferCreate_JustChangedFile ) ;
2019-06-01 23:58:28 +00:00
if ( new_buffer ! = 0 & & new_buffer ! = buffer ) {
2019-06-19 02:31:59 +00:00
buffer_kill ( app , buffer , BufferKill_AlwaysKill ) ;
2019-06-01 23:58:28 +00:00
view_set_buffer ( app , view , new_buffer , 0 ) ;
2018-03-24 10:06:45 +00:00
}
}
}
}
2019-04-05 02:03:36 +00:00
2019-06-01 23:58:28 +00:00
end_temp ( temp ) ;
2018-03-24 10:06:45 +00:00
}
2017-11-21 21:30:40 +00:00
CUSTOM_COMMAND_SIG ( rename_file_query )
CUSTOM_DOC ( " Queries the user for a new name and renames the file of the current buffer, altering the buffer's name too. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessAll ) ;
Buffer_ID buffer = view_get_buffer ( app , view , AccessAll ) ;
2019-04-05 02:03:36 +00:00
Arena * scratch = context_get_arena ( app ) ;
2019-06-01 23:58:28 +00:00
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 file_name = push_buffer_file_name ( app , scratch , buffer ) ;
2019-04-05 02:03:36 +00:00
if ( file_name . size > 0 ) {
// Query the user
2019-06-01 23:58:28 +00:00
String_Const_u8 front = string_front_of_path ( file_name ) ;
u8 name_space [ 4096 ] ;
2019-04-05 02:03:36 +00:00
Query_Bar bar = { } ;
2019-06-18 22:56:09 +00:00
bar . prompt = push_u8_stringf ( scratch , " Rename '%.*s' to: " , string_expand ( front ) ) ;
2019-06-01 23:58:28 +00:00
bar . string = SCu8 ( name_space , ( umem ) 0 ) ;
bar . string_capacity = sizeof ( name_space ) ;
2019-04-05 02:03:36 +00:00
if ( query_user_string ( app , & bar ) ) {
if ( bar . string . size ! = 0 ) {
// TODO(allen): There should be a way to say, "detach a buffer's file" and "attach this file to a buffer"
2019-06-01 23:58:28 +00:00
List_String_Const_u8 new_file_name_list = { } ;
string_list_push ( scratch , & new_file_name_list , file_name ) ;
string_list_push ( scratch , & new_file_name_list , bar . string ) ;
String_Const_u8 new_file_name = string_list_flatten ( scratch , new_file_name_list , StringFill_NullTerminate ) ;
2019-04-05 02:03:36 +00:00
if ( buffer_save ( app , buffer , new_file_name , BufferSave_IgnoreDirtyFlag ) ) {
2019-06-19 02:31:59 +00:00
Buffer_ID new_buffer = create_buffer ( app , new_file_name , BufferCreate_NeverNew | BufferCreate_JustChangedFile ) ;
2019-04-05 02:03:36 +00:00
if ( new_buffer ! = 0 & & new_buffer ! = buffer ) {
delete_file_base ( app , file_name , buffer ) ;
2019-04-06 23:36:53 +00:00
view_set_buffer ( app , view , new_buffer , 0 ) ;
2019-04-05 02:03:36 +00:00
}
2018-12-16 00:22:28 +00:00
}
2017-11-21 21:30:40 +00:00
}
}
2019-04-05 02:03:36 +00:00
2017-11-21 19:48:04 +00:00
}
2019-04-05 02:03:36 +00:00
2019-06-01 23:58:28 +00:00
end_temp ( temp ) ;
2017-11-21 19:48:04 +00:00
}
2017-11-21 21:47:40 +00:00
CUSTOM_COMMAND_SIG ( make_directory_query )
CUSTOM_DOC ( " Queries the user for a name and creates a new directory with the given name. " )
{
2019-06-01 23:58:28 +00:00
Scratch_Block scratch ( app ) ;
String_Const_u8 hot = push_hot_directory ( app , scratch ) ;
// Query the user
u8 name_space [ 4096 ] ;
Query_Bar bar = { } ;
2019-06-18 22:56:09 +00:00
bar . prompt = push_u8_stringf ( scratch , " Make directory at '%.*s': " , string_expand ( hot ) ) ;
2019-06-01 23:58:28 +00:00
bar . string = SCu8 ( name_space , ( umem ) 0 ) ;
bar . string_capacity = sizeof ( name_space ) ;
if ( ! query_user_string ( app , & bar ) ) return ;
if ( bar . string . size = = 0 ) return ;
2019-06-18 22:56:09 +00:00
String_Const_u8 cmd = push_u8_stringf ( scratch , " mkdir %.*s " , string_expand ( bar . string ) ) ;
2019-06-01 23:58:28 +00:00
exec_system_command ( app , 0 , buffer_identifier ( 0 ) , hot , cmd , 0 ) ;
2017-11-21 21:47:40 +00:00
}
2018-05-10 08:12:47 +00:00
////////////////////////////////
2019-06-14 22:01:50 +00:00
internal void
current_view_move_line ( Application_Links * app , Scan_Direction direction ) {
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessOpen ) ;
Buffer_ID buffer = view_get_buffer ( app , view , AccessOpen ) ;
2019-06-20 23:43:27 +00:00
i64 pos = view_get_cursor_pos ( app , view ) ;
i64 line_number = get_line_number_from_pos ( app , buffer , pos ) ;
2019-06-14 22:01:50 +00:00
pos = move_line ( app , buffer , line_number , direction ) ;
2019-09-02 21:32:52 +00:00
view_set_cursor_and_preferred_x ( app , view , seek_pos ( pos ) ) ;
2019-06-14 22:01:50 +00:00
}
2018-05-10 08:12:47 +00:00
CUSTOM_COMMAND_SIG ( move_line_up )
CUSTOM_DOC ( " Swaps the line under the cursor with the line above it, and moves the cursor up with it. " )
{
2019-06-14 22:01:50 +00:00
current_view_move_line ( app , Scan_Backward ) ;
2018-05-10 08:12:47 +00:00
}
CUSTOM_COMMAND_SIG ( move_line_down )
CUSTOM_DOC ( " Swaps the line under the cursor with the line below it, and moves the cursor down with it. " )
{
2019-06-14 22:01:50 +00:00
current_view_move_line ( app , Scan_Forward ) ;
2018-05-10 08:12:47 +00:00
}
CUSTOM_COMMAND_SIG ( duplicate_line )
CUSTOM_DOC ( " Create a copy of the line on which the cursor sits. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessOpen ) ;
Buffer_ID buffer = view_get_buffer ( app , view , AccessOpen ) ;
2019-06-20 23:43:27 +00:00
i64 pos = view_get_cursor_pos ( app , view ) ;
i64 line = get_line_number_from_pos ( app , buffer , pos ) ;
2019-06-01 23:58:28 +00:00
Scratch_Block scratch ( app ) ;
2019-06-14 22:01:50 +00:00
String_Const_u8 s = push_buffer_line ( app , scratch , buffer , line ) ;
2019-06-18 22:56:09 +00:00
s = push_u8_stringf ( scratch , " %.*s \n " , string_expand ( s ) ) ;
2019-06-16 23:38:22 +00:00
pos = get_line_side_pos ( app , buffer , line , Side_Min ) ;
2019-06-20 23:43:27 +00:00
buffer_replace_range ( app , buffer , Ii64 ( pos ) , s ) ;
2018-05-10 08:12:47 +00:00
}
CUSTOM_COMMAND_SIG ( delete_line )
CUSTOM_DOC ( " Delete the line the on which the cursor sits. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessOpen ) ;
Buffer_ID buffer = view_get_buffer ( app , view , AccessOpen ) ;
2019-06-20 23:43:27 +00:00
i64 pos = view_get_cursor_pos ( app , view ) ;
i64 line = get_line_number_from_pos ( app , buffer , pos ) ;
Range_i64 range = get_line_pos_range ( app , buffer , line ) ;
2019-06-14 22:01:50 +00:00
range . end + = 1 ;
2019-06-19 02:31:59 +00:00
i32 size = ( i32 ) buffer_get_size ( app , buffer ) ;
2019-06-14 22:01:50 +00:00
range . end = clamp_top ( range . end , size ) ;
if ( range_size ( range ) = = 0 | |
buffer_get_char ( app , buffer , range . end - 1 ) ! = ' \n ' ) {
2019-06-02 03:07:57 +00:00
range . start - = 1 ;
range . first = clamp_bot ( 0 , range . first ) ;
2018-05-10 08:12:47 +00:00
}
2019-06-02 03:07:57 +00:00
buffer_replace_range ( app , buffer , range , string_u8_litexpr ( " " ) ) ;
2018-05-10 08:12:47 +00:00
}
////////////////////////////////
2017-01-23 06:19:43 +00:00
2019-02-26 23:08:42 +00:00
static b32
2019-04-04 08:25:16 +00:00
get_cpp_matching_file ( Application_Links * app , Buffer_ID buffer , Buffer_ID * buffer_out ) {
2019-02-26 23:08:42 +00:00
b32 result = false ;
2019-06-01 23:58:28 +00:00
Scratch_Block scratch ( app ) ;
2019-06-02 03:07:57 +00:00
String_Const_u8 file_name = push_buffer_file_name ( app , scratch , buffer ) ;
2019-04-04 08:25:16 +00:00
if ( file_name . size > 0 ) {
2019-06-01 23:58:28 +00:00
String_Const_u8 extension = string_file_extension ( file_name ) ;
String_Const_u8 new_extensions [ 2 ] = { } ;
2019-02-26 23:17:53 +00:00
i32 new_extensions_count = 0 ;
2019-06-01 23:58:28 +00:00
if ( string_match ( extension , string_u8_litexpr ( " cpp " ) ) | | string_match ( extension , string_u8_litexpr ( " cc " ) ) ) {
new_extensions [ 0 ] = string_u8_litexpr ( " h " ) ;
new_extensions [ 1 ] = string_u8_litexpr ( " hpp " ) ;
2018-05-11 20:46:26 +00:00
new_extensions_count = 2 ;
}
2019-06-01 23:58:28 +00:00
else if ( string_match ( extension , string_u8_litexpr ( " c " ) ) ) {
new_extensions [ 0 ] = string_u8_litexpr ( " h " ) ;
2018-05-11 20:46:26 +00:00
new_extensions_count = 1 ;
}
2019-06-01 23:58:28 +00:00
else if ( string_match ( extension , string_u8_litexpr ( " h " ) ) ) {
new_extensions [ 0 ] = string_u8_litexpr ( " c " ) ;
new_extensions [ 1 ] = string_u8_litexpr ( " cpp " ) ;
2018-05-11 20:46:26 +00:00
new_extensions_count = 2 ;
}
2019-06-01 23:58:28 +00:00
else if ( string_match ( extension , string_u8_litexpr ( " hpp " ) ) ) {
new_extensions [ 0 ] = string_u8_litexpr ( " cpp " ) ;
2018-05-11 20:46:26 +00:00
new_extensions_count = 1 ;
}
2019-06-01 23:58:28 +00:00
String_Const_u8 file_without_extension = string_file_without_extension ( file_name ) ;
for ( i32 i = 0 ; i < new_extensions_count ; i + = 1 ) {
Temp_Memory temp = begin_temp ( scratch ) ;
String_Const_u8 new_extension = new_extensions [ i ] ;
2019-06-18 22:56:09 +00:00
String_Const_u8 new_file_name = push_u8_stringf ( scratch , " %.*s.%.*s " , string_expand ( file_without_extension ) , string_expand ( new_extension ) ) ;
2019-06-01 23:58:28 +00:00
if ( open_file ( app , buffer_out , new_file_name , false , true ) ) {
result = true ;
break ;
}
end_temp ( temp ) ;
}
2018-05-11 20:46:26 +00:00
}
return ( result ) ;
}
CUSTOM_COMMAND_SIG ( open_file_in_quotes )
CUSTOM_DOC ( " Reads a filename from surrounding ' \" ' characters and attempts to open the corresponding file. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessProtected ) ;
2019-06-20 23:43:27 +00:00
Buffer_ID buffer = view_get_buffer ( app , view , AccessProtected ) ;
if ( buffer_exists ( app , buffer ) ) {
2019-06-01 23:58:28 +00:00
Scratch_Block scratch ( app ) ;
2019-04-01 02:41:39 +00:00
2019-06-20 23:43:27 +00:00
i64 pos = view_get_cursor_pos ( app , view ) ;
2019-04-06 23:36:53 +00:00
2019-06-20 23:43:27 +00:00
Range_i64 range = enclose_pos_inside_quotes ( app , buffer , pos ) ;
2019-04-06 23:36:53 +00:00
2019-06-20 23:43:27 +00:00
String_Const_u8 quoted_name = push_buffer_range ( app , scratch , buffer , range ) ;
2019-06-01 23:58:28 +00:00
2019-06-20 23:43:27 +00:00
String_Const_u8 file_name = push_buffer_file_name ( app , scratch , buffer ) ;
2019-06-01 23:58:28 +00:00
String_Const_u8 path = string_remove_last_folder ( file_name ) ;
if ( character_is_slash ( string_get_character ( path , path . size - 1 ) ) ) {
path = string_chop ( path , 1 ) ;
2018-05-11 20:46:26 +00:00
}
2019-04-06 23:36:53 +00:00
2019-06-18 22:56:09 +00:00
String_Const_u8 new_file_name = push_u8_stringf ( scratch , " %.*s/%.*s " , string_expand ( path ) , string_expand ( quoted_name ) ) ;
2019-06-01 23:58:28 +00:00
view = get_next_view_looped_primary_panels ( app , view , AccessAll ) ;
if ( view ! = 0 ) {
if ( view_open_file ( app , view , new_file_name , true ) ) {
view_set_active ( app , view ) ;
}
}
2018-05-11 20:46:26 +00:00
}
}
CUSTOM_COMMAND_SIG ( open_matching_file_cpp )
CUSTOM_DOC ( " If the current file is a *.cpp or *.h, attempts to open the corresponding *.h or *.cpp file in the other view. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessAll ) ;
Buffer_ID buffer = view_get_buffer ( app , view , AccessAll ) ;
2019-04-04 08:25:16 +00:00
Buffer_ID new_buffer = 0 ;
2018-05-11 20:46:26 +00:00
if ( get_cpp_matching_file ( app , buffer , & new_buffer ) ) {
2019-06-01 23:58:28 +00:00
view = get_next_view_looped_primary_panels ( app , view , AccessAll ) ;
2019-04-06 23:36:53 +00:00
view_set_buffer ( app , view , new_buffer , 0 ) ;
view_set_active ( app , view ) ;
2018-05-11 20:46:26 +00:00
}
}
CUSTOM_COMMAND_SIG ( view_buffer_other_panel )
CUSTOM_DOC ( " Set the other non-active panel to view the buffer that the active panel views, and switch to that panel. " )
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessAll ) ;
Buffer_ID buffer = view_get_buffer ( app , view , AccessAll ) ;
2019-06-20 23:43:27 +00:00
i64 pos = view_get_cursor_pos ( app , view ) ;
2018-05-11 20:46:26 +00:00
change_active_panel ( app ) ;
2019-06-19 02:31:59 +00:00
view = get_active_view ( app , AccessAll ) ;
2019-04-06 23:36:53 +00:00
view_set_buffer ( app , view , buffer , 0 ) ;
2019-09-02 21:32:52 +00:00
view_set_cursor_and_preferred_x ( app , view , seek_pos ( pos ) ) ;
2018-05-11 20:46:26 +00:00
}
CUSTOM_COMMAND_SIG ( swap_buffers_between_panels )
CUSTOM_DOC ( " Set the other non-active panel to view the buffer that the active panel views, and switch to that panel. " )
{
2019-06-19 02:31:59 +00:00
View_ID view1 = get_active_view ( app , AccessAll ) ;
2018-05-11 20:46:26 +00:00
change_active_panel ( app ) ;
2019-06-19 02:31:59 +00:00
View_ID view2 = get_active_view ( app , AccessAll ) ;
2019-04-06 23:36:53 +00:00
2019-09-02 18:59:36 +00:00
if ( view1 ! = view2 & &
! view_is_in_ui_mode ( app , view1 ) & &
! view_is_in_ui_mode ( app , view2 ) ) {
2019-06-19 02:31:59 +00:00
Buffer_ID buffer1 = view_get_buffer ( app , view1 , AccessAll ) ;
Buffer_ID buffer2 = view_get_buffer ( app , view2 , AccessAll ) ;
2019-04-06 23:36:53 +00:00
if ( buffer1 ! = buffer2 ) {
view_set_buffer ( app , view1 , buffer2 , 0 ) ;
view_set_buffer ( app , view2 , buffer1 , 0 ) ;
2018-06-08 22:51:36 +00:00
}
else {
2019-06-20 23:43:27 +00:00
i64 p1 = view_get_cursor_pos ( app , view1 ) ;
i64 m1 = view_get_mark_pos ( app , view1 ) ;
2019-09-02 18:59:36 +00:00
Buffer_Scroll sc1 = view_get_buffer_scroll ( app , view1 ) ;
2019-06-20 23:43:27 +00:00
i64 p2 = view_get_cursor_pos ( app , view2 ) ;
i64 m2 = view_get_mark_pos ( app , view2 ) ;
2019-09-02 18:59:36 +00:00
Buffer_Scroll sc2 = view_get_buffer_scroll ( app , view2 ) ;
2019-04-06 23:36:53 +00:00
2019-09-02 21:32:52 +00:00
view_set_cursor_and_preferred_x ( app , view1 , seek_pos ( p2 ) ) ;
view_set_mark ( app , view1 , seek_pos ( m2 ) ) ;
2019-09-02 18:59:36 +00:00
view_set_buffer_scroll ( app , view1 , sc2 ) ;
2019-09-02 21:32:52 +00:00
view_set_cursor_and_preferred_x ( app , view2 , seek_pos ( p1 ) ) ;
view_set_mark ( app , view2 , seek_pos ( m1 ) ) ;
2019-09-02 18:59:36 +00:00
view_set_buffer_scroll ( app , view2 , sc1 ) ;
2018-06-08 22:51:36 +00:00
}
2018-05-11 20:46:26 +00:00
}
}
////////////////////////////////
2018-08-05 07:09:18 +00:00
CUSTOM_COMMAND_SIG ( kill_buffer )
CUSTOM_DOC ( " Kills the current buffer. " )
{
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 ) ;
try_buffer_kill ( app , buffer , view , 0 ) ;
2018-08-05 07:09:18 +00:00
}
2018-11-21 07:48:42 +00:00
CUSTOM_COMMAND_SIG ( save )
CUSTOM_DOC ( " Saves the current buffer. " )
{
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-05 02:03:36 +00:00
Arena * scratch = context_get_arena ( app ) ;
2019-06-01 23:58:28 +00:00
Temp_Memory temp = begin_temp ( scratch ) ;
2019-06-02 03:07:57 +00:00
String_Const_u8 file_name = push_buffer_file_name ( app , scratch , buffer ) ;
2019-04-05 02:03:36 +00:00
buffer_save ( app , buffer , file_name , 0 ) ;
2019-06-01 23:58:28 +00:00
end_temp ( temp ) ;
2018-11-21 07:48:42 +00:00
}
CUSTOM_COMMAND_SIG ( reopen )
CUSTOM_DOC ( " Reopen the current buffer from the hard drive. " )
{
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 ) ;
buffer_reopen ( app , buffer , 0 ) ;
2018-11-21 07:48:42 +00:00
}
2018-08-05 07:09:18 +00:00
////////////////////////////////
2019-03-22 05:06:30 +00:00
static i32
record_get_new_cursor_position_undo ( Application_Links * app , Buffer_ID buffer_id , History_Record_Index index , Record_Info record ) {
i32 new_edit_position = 0 ;
switch ( record . kind ) {
default :
case RecordKind_Single :
{
2019-06-20 04:45:58 +00:00
new_edit_position = ( i32 ) ( record . single . first + record . single . string_backward . size ) ;
2019-03-22 05:06:30 +00:00
} break ;
case RecordKind_Group :
{
2019-06-20 04:45:58 +00:00
Record_Info sub_record = buffer_history_get_group_sub_record ( app , buffer_id , index , 0 ) ;
new_edit_position = ( i32 ) ( sub_record . single . first + sub_record . single . string_backward . size ) ;
2019-03-22 05:06:30 +00:00
} break ;
}
return ( new_edit_position ) ;
}
static i32
record_get_new_cursor_position_undo ( Application_Links * app , Buffer_ID buffer_id , History_Record_Index index ) {
2019-06-20 04:45:58 +00:00
Record_Info record = buffer_history_get_record_info ( app , buffer_id , index ) ;
2019-03-22 05:06:30 +00:00
return ( record_get_new_cursor_position_undo ( app , buffer_id , index , record ) ) ;
}
static i32
record_get_new_cursor_position_redo ( Application_Links * app , Buffer_ID buffer_id , History_Record_Index index , Record_Info record ) {
2019-06-20 04:45:58 +00:00
i64 new_edit_position = 0 ;
2019-03-22 05:06:30 +00:00
switch ( record . kind ) {
default :
case RecordKind_Single :
{
2019-06-20 04:45:58 +00:00
new_edit_position = record . single . first + record . single . string_forward . size ;
2019-03-22 05:06:30 +00:00
} break ;
case RecordKind_Group :
{
2019-06-20 04:45:58 +00:00
Record_Info sub_record = buffer_history_get_group_sub_record ( app , buffer_id , index , record . group . count - 1 ) ;
new_edit_position = sub_record . single . first + sub_record . single . string_forward . size ;
2019-03-22 05:06:30 +00:00
} break ;
}
2019-06-20 04:45:58 +00:00
return ( ( i32 ) ( new_edit_position ) ) ;
2019-03-22 05:06:30 +00:00
}
static i32
record_get_new_cursor_position_redo ( Application_Links * app , Buffer_ID buffer_id , History_Record_Index index ) {
2019-06-20 04:45:58 +00:00
Record_Info record = buffer_history_get_record_info ( app , buffer_id , index ) ;
2019-03-22 05:06:30 +00:00
return ( record_get_new_cursor_position_redo ( app , buffer_id , index , record ) ) ;
}
2019-04-07 17:36:24 +00:00
CUSTOM_COMMAND_SIG ( undo )
2019-02-12 03:03:49 +00:00
CUSTOM_DOC ( " Advances backwards through the undo history of the current buffer. " )
2017-11-15 23:57:21 +00:00
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessOpen ) ;
Buffer_ID buffer = view_get_buffer ( app , view , AccessOpen ) ;
2019-06-20 04:45:58 +00:00
History_Record_Index current = buffer_history_get_current_state_index ( app , buffer ) ;
2019-02-08 10:03:48 +00:00
if ( current > 0 ) {
2019-04-06 23:36:53 +00:00
i32 new_position = record_get_new_cursor_position_undo ( app , buffer , current ) ;
buffer_history_set_current_state_index ( app , buffer , current - 1 ) ;
2019-09-02 21:32:52 +00:00
view_set_cursor_and_preferred_x ( app , view , seek_pos ( new_position ) ) ;
2019-02-08 10:03:48 +00:00
}
2017-01-23 06:19:43 +00:00
}
2019-04-07 17:36:24 +00:00
CUSTOM_COMMAND_SIG ( redo )
2019-02-12 03:03:49 +00:00
CUSTOM_DOC ( " Advances forwards through the undo history of the current buffer. " )
2019-02-08 10:03:48 +00:00
{
2019-06-19 02:31:59 +00:00
View_ID view = get_active_view ( app , AccessOpen ) ;
Buffer_ID buffer = view_get_buffer ( app , view , AccessOpen ) ;
2019-06-20 04:45:58 +00:00
History_Record_Index current = buffer_history_get_current_state_index ( app , buffer ) ;
History_Record_Index max_index = buffer_history_get_max_record_index ( app , buffer ) ;
2019-02-08 10:03:48 +00:00
if ( current < max_index ) {
2019-04-06 23:36:53 +00:00
i32 new_position = record_get_new_cursor_position_redo ( app , buffer , current + 1 ) ;
buffer_history_set_current_state_index ( app , buffer , current + 1 ) ;
2019-09-02 21:32:52 +00:00
view_set_cursor_and_preferred_x ( app , view , seek_pos ( new_position ) ) ;
2019-02-12 03:03:49 +00:00
}
}
2019-04-07 17:36:24 +00:00
CUSTOM_COMMAND_SIG ( undo_all_buffers )
2019-02-12 03:03:49 +00:00
CUSTOM_DOC ( " Advances backward through the undo history in the buffer containing the most recent regular edit. " )
{
2019-06-01 23:58:28 +00:00
Arena * scratch = context_get_arena ( app ) ;
2019-02-26 23:17:53 +00:00
i32 highest_edit_number = - 1 ;
2019-02-12 03:03:49 +00:00
Buffer_ID first_buffer_match = 0 ;
Buffer_ID last_buffer_match = 0 ;
2019-02-26 23:17:53 +00:00
i32 match_count = 0 ;
2019-02-12 03:03:49 +00:00
2019-04-05 21:18:16 +00:00
{
2019-06-19 02:31:59 +00:00
for ( Buffer_ID buffer = get_buffer_next ( app , 0 , AccessAll ) ;
2019-04-05 21:18:16 +00:00
buffer ! = 0 ;
2019-06-19 02:31:59 +00:00
buffer = get_buffer_next ( app , buffer , AccessAll ) ) {
2019-06-20 04:45:58 +00:00
History_Record_Index index = buffer_history_get_current_state_index ( app , buffer ) ;
2019-04-05 21:18:16 +00:00
if ( index > 0 ) {
2019-06-20 04:45:58 +00:00
Record_Info record = buffer_history_get_record_info ( app , buffer , index ) ;
2019-04-05 21:18:16 +00:00
if ( record . edit_number > highest_edit_number ) {
highest_edit_number = record . edit_number ;
first_buffer_match = buffer ;
last_buffer_match = buffer ;
match_count = 1 ;
}
else if ( record . edit_number = = highest_edit_number ) {
last_buffer_match = buffer ;
match_count + = 1 ;
}
2019-02-12 03:03:49 +00:00
}
}
}
2019-06-01 23:58:28 +00:00
Temp_Memory temp = begin_temp ( scratch ) ;
2019-02-12 03:10:42 +00:00
Buffer_ID * match_buffers = push_array ( scratch , Buffer_ID , match_count ) ;
2019-03-22 05:06:30 +00:00
i32 * new_positions = push_array ( scratch , i32 , match_count ) ;
2019-02-12 03:10:42 +00:00
match_count = 0 ;
2019-02-12 03:03:49 +00:00
if ( highest_edit_number ! = - 1 ) {
2019-04-05 02:03:36 +00:00
for ( Buffer_ID buffer = first_buffer_match ;
buffer ! = 0 ;
2019-06-19 02:31:59 +00:00
buffer = get_buffer_next ( app , buffer , AccessAll ) ) {
2019-02-26 23:08:42 +00:00
b32 did_match = false ;
2019-03-22 05:06:30 +00:00
i32 new_edit_position = 0 ;
2019-02-12 03:03:49 +00:00
for ( ; ; ) {
2019-06-20 04:45:58 +00:00
History_Record_Index index = buffer_history_get_current_state_index ( app , buffer ) ;
2019-02-12 03:03:49 +00:00
if ( index > 0 ) {
2019-06-20 04:45:58 +00:00
Record_Info record = buffer_history_get_record_info ( app , buffer , index ) ;
2019-02-12 03:03:49 +00:00
if ( record . edit_number = = highest_edit_number ) {
2019-02-12 03:10:42 +00:00
did_match = true ;
2019-04-05 02:03:36 +00:00
new_edit_position = record_get_new_cursor_position_undo ( app , buffer , index , record ) ;
buffer_history_set_current_state_index ( app , buffer , index - 1 ) ;
2019-02-12 03:03:49 +00:00
}
else {
break ;
}
}
else {
break ;
}
}
2019-02-12 03:10:42 +00:00
if ( did_match ) {
2019-04-05 02:03:36 +00:00
match_buffers [ match_count ] = buffer ;
2019-03-22 05:06:30 +00:00
new_positions [ match_count ] = new_edit_position ;
2019-02-12 03:10:42 +00:00
match_count + = 1 ;
}
2019-04-05 02:03:36 +00:00
if ( buffer = = last_buffer_match ) {
2019-02-12 03:03:49 +00:00
break ;
}
}
}
2019-02-12 03:10:42 +00:00
2019-03-22 05:06:30 +00:00
view_buffer_set ( app , match_buffers , new_positions , match_count ) ;
2019-02-12 03:10:42 +00:00
2019-06-01 23:58:28 +00:00
end_temp ( temp ) ;
2019-02-12 03:03:49 +00:00
}
2019-04-07 17:36:24 +00:00
CUSTOM_COMMAND_SIG ( redo_all_buffers )
2019-02-12 03:03:49 +00:00
CUSTOM_DOC ( " Advances forward through the undo history in the buffer containing the most recent regular edit. " )
{
2019-06-01 23:58:28 +00:00
Arena * scratch = context_get_arena ( app ) ;
2019-02-26 23:17:53 +00:00
i32 lowest_edit_number = 0x7FFFFFFF ;
2019-02-12 03:03:49 +00:00
Buffer_ID first_buffer_match = 0 ;
Buffer_ID last_buffer_match = 0 ;
2019-02-26 23:17:53 +00:00
i32 match_count = 0 ;
2019-02-12 03:03:49 +00:00
2019-04-05 21:18:16 +00:00
{
2019-06-19 02:31:59 +00:00
for ( Buffer_ID buffer = get_buffer_next ( app , 0 , AccessAll ) ;
2019-04-05 21:18:16 +00:00
buffer ! = 0 ;
2019-06-19 02:31:59 +00:00
buffer = get_buffer_next ( app , buffer , AccessAll ) ) {
2019-06-20 04:45:58 +00:00
History_Record_Index max_index = buffer_history_get_max_record_index ( app , buffer ) ;
History_Record_Index index = buffer_history_get_current_state_index ( app , buffer ) ;
2019-04-05 21:18:16 +00:00
if ( index < max_index ) {
2019-06-20 04:45:58 +00:00
Record_Info record = buffer_history_get_record_info ( app , buffer , index + 1 ) ;
2019-04-05 21:18:16 +00:00
if ( record . edit_number < lowest_edit_number ) {
lowest_edit_number = record . edit_number ;
first_buffer_match = buffer ;
last_buffer_match = buffer ;
match_count = 1 ;
}
else if ( record . edit_number = = lowest_edit_number ) {
last_buffer_match = buffer ;
match_count + = 1 ;
}
2019-02-12 03:03:49 +00:00
}
}
}
2019-06-01 23:58:28 +00:00
Temp_Memory temp = begin_temp ( scratch ) ;
2019-02-12 03:17:21 +00:00
Buffer_ID * match_buffers = push_array ( scratch , Buffer_ID , match_count ) ;
2019-03-22 05:06:30 +00:00
i32 * new_positions = push_array ( scratch , i32 , match_count ) ;
2019-02-12 03:17:21 +00:00
match_count = 0 ;
2019-02-12 03:10:42 +00:00
2019-02-12 03:03:49 +00:00
if ( lowest_edit_number ! = - 1 ) {
2019-04-05 02:03:36 +00:00
for ( Buffer_ID buffer = first_buffer_match ;
buffer ! = 0 ;
2019-06-19 02:31:59 +00:00
buffer = get_buffer_next ( app , buffer , AccessAll ) ) {
2019-02-26 23:08:42 +00:00
b32 did_match = false ;
2019-03-22 05:06:30 +00:00
i32 new_edit_position = 0 ;
2019-06-20 04:45:58 +00:00
History_Record_Index max_index = buffer_history_get_max_record_index ( app , buffer ) ;
2019-02-12 03:10:42 +00:00
for ( ; ; ) {
2019-06-20 04:45:58 +00:00
History_Record_Index index = buffer_history_get_current_state_index ( app , buffer ) ;
2019-02-12 03:10:42 +00:00
if ( index < max_index ) {
2019-06-20 04:45:58 +00:00
Record_Info record = buffer_history_get_record_info ( app , buffer , index + 1 ) ;
2019-02-12 03:10:42 +00:00
if ( record . edit_number = = lowest_edit_number ) {
did_match = true ;
2019-04-05 02:03:36 +00:00
new_edit_position = record_get_new_cursor_position_redo ( app , buffer , index + 1 , record ) ;
buffer_history_set_current_state_index ( app , buffer , index + 1 ) ;
2019-02-12 03:10:42 +00:00
}
else {
break ;
}
}
else {
break ;
2019-02-12 03:03:49 +00:00
}
}
2019-02-12 03:10:42 +00:00
if ( did_match ) {
2019-04-05 02:03:36 +00:00
match_buffers [ match_count ] = buffer ;
2019-03-22 05:06:30 +00:00
new_positions [ match_count ] = new_edit_position ;
2019-02-12 03:10:42 +00:00
match_count + = 1 ;
}
2019-04-05 02:03:36 +00:00
if ( buffer = = last_buffer_match ) {
2019-02-12 03:03:49 +00:00
break ;
}
}
2019-02-08 10:03:48 +00:00
}
2019-02-12 03:10:42 +00:00
2019-03-22 05:06:30 +00:00
view_buffer_set ( app , match_buffers , new_positions , match_count ) ;
2019-02-12 03:10:42 +00:00
2019-06-01 23:58:28 +00:00
end_temp ( temp ) ;
2017-01-23 06:19:43 +00:00
}
2018-05-11 20:46:26 +00:00
////////////////////////////////
2019-02-25 23:42:13 +00:00
#if 0
2018-08-10 22:57:46 +00:00
CUSTOM_COMMAND_SIG ( reload_themes )
CUSTOM_DOC ( " Loads all the theme files in the theme folder, replacing duplicates with the new theme data. " )
{
String fcoder_extension = make_lit_string ( " .4coder " ) ;
save_all_dirty_buffers_with_postfix ( app , fcoder_extension ) ;
Partition * scratch = & global_part ;
Temp_Memory temp = begin_temp_memory ( scratch ) ;
load_folder_of_themes_into_live_set ( app , scratch , " themes " ) ;
String name = get_theme_name ( app , scratch , 0 ) ;
2019-02-26 23:17:53 +00:00
i32 theme_count = get_theme_count ( app ) ;
for ( i32 i = 1 ; i < theme_count ; i + = 1 ) {
2018-08-10 22:57:46 +00:00
Temp_Memory sub_temp = begin_temp_memory ( scratch ) ;
String style_name = get_theme_name ( app , scratch , i ) ;
if ( match ( name , style_name ) ) {
change_theme_by_index ( app , i ) ;
break ;
}
end_temp_memory ( sub_temp ) ;
}
end_temp_memory ( temp ) ;
}
2019-02-25 23:42:13 +00:00
# endif
2018-08-10 22:57:46 +00:00
2018-05-11 20:46:26 +00:00
CUSTOM_COMMAND_SIG ( open_in_other )
2018-06-02 04:06:13 +00:00
CUSTOM_DOC ( " Interactively opens a file in the other panel. " )
2018-05-11 20:46:26 +00:00
{
change_active_panel ( app ) ;
interactive_open_or_new ( app ) ;
}
2017-01-23 06:19:43 +00:00
// BOTTOM