From 2c381917fde081bb282d5770260bca23ebf2fb38 Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Thu, 21 Mar 2019 22:06:30 -0700 Subject: [PATCH] Undo/Redo cursor positioning fixed --- 4coder_API/4coder_types.h | 5 - 4coder_base_commands.cpp | 68 ++++++- 4coder_base_types.h | 19 +- 4coder_default_framework.cpp | 157 +++++++++++---- 4coder_default_hooks.cpp | 2 + 4coder_generated/app_functions.h | 7 + 4coder_generated/command_metadata.h | 38 ++-- 4coder_helper.cpp | 136 ++++++------- 4ed_api_implementation.cpp | 43 +++- 4ed_edit.cpp | 59 ------ 4ed_history.cpp | 298 +++++++++++----------------- 4ed_layout.cpp | 10 + 12 files changed, 447 insertions(+), 395 deletions(-) diff --git a/4coder_API/4coder_types.h b/4coder_API/4coder_types.h index 2ddae21f..e35ab970 100644 --- a/4coder_API/4coder_types.h +++ b/4coder_API/4coder_types.h @@ -972,7 +972,6 @@ STRUCT Buffer_Batch_Edit{ ENUM(i32, Record_Kind){ RecordKind_Single, - RecordKind_Batch, RecordKind_Group, }; @@ -1003,10 +1002,6 @@ STRUCT Record_Info{ String string_backward; i32 first; } single; - struct{ - Buffer_Batch_Edit_Type type; - i32 count; - } batch; struct{ i32 count; } group; diff --git a/4coder_base_commands.cpp b/4coder_base_commands.cpp index 04e47188..bcf9363c 100644 --- a/4coder_base_commands.cpp +++ b/4coder_base_commands.cpp @@ -1622,6 +1622,58 @@ CUSTOM_DOC("Reopen the current buffer from the hard drive.") //////////////////////////////// +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: + { + new_edit_position = record.single.first + record.single.string_backward.size; + }break; + case RecordKind_Group: + { + Record_Info sub_record = {}; + buffer_history_get_group_sub_record(app, buffer_id, index, 0, &sub_record); + new_edit_position = sub_record.single.first + sub_record.single.string_backward.size; + }break; + } + return(new_edit_position); +} + +static i32 +record_get_new_cursor_position_undo(Application_Links *app, Buffer_ID buffer_id, History_Record_Index index){ + Record_Info record = {}; + buffer_history_get_record_info(app, buffer_id, index, &record); + 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){ + i32 new_edit_position = 0; + switch (record.kind){ + default: + case RecordKind_Single: + { + new_edit_position = record.single.first + record.single.string_forward.size; + }break; + case RecordKind_Group: + { + Record_Info sub_record = {}; + buffer_history_get_group_sub_record(app, buffer_id, index, record.group.count - 1, &sub_record); + new_edit_position = sub_record.single.first + sub_record.single.string_forward.size; + }break; + } + return(new_edit_position); +} + +static i32 +record_get_new_cursor_position_redo(Application_Links *app, Buffer_ID buffer_id, History_Record_Index index){ + Record_Info record = {}; + buffer_history_get_record_info(app, buffer_id, index, &record); + return(record_get_new_cursor_position_redo(app, buffer_id, index, record)); +} + CUSTOM_COMMAND_SIG(undo_this_buffer) CUSTOM_DOC("Advances backwards through the undo history of the current buffer.") { @@ -1630,7 +1682,9 @@ CUSTOM_DOC("Advances backwards through the undo history of the current buffer.") History_Record_Index current = 0; buffer_history_get_current_state_index(app, buffer_id, ¤t); if (current > 0){ + i32 new_position = record_get_new_cursor_position_undo(app, buffer_id, current); buffer_history_set_current_state_index(app, buffer_id, current - 1); + view_set_cursor(app, view.view_id, seek_pos(new_position), true); } } @@ -1644,7 +1698,9 @@ CUSTOM_DOC("Advances forwards through the undo history of the current buffer.") buffer_history_get_current_state_index(app, buffer_id, ¤t); buffer_history_get_max_record_index(app, buffer_id, &max_index); if (current < max_index){ + i32 new_position = record_get_new_cursor_position_redo(app, buffer_id, current + 1); buffer_history_set_current_state_index(app, buffer_id, current + 1); + view_set_cursor(app, view.view_id, seek_pos(new_position), true); } } @@ -1680,6 +1736,7 @@ CUSTOM_DOC("Advances backward through the undo history in the buffer containing Temp_Memory temp = begin_temp_memory(scratch); Buffer_ID *match_buffers = push_array(scratch, Buffer_ID, match_count); + i32 *new_positions = push_array(scratch, i32, match_count); match_count = 0; if (highest_edit_number != -1){ @@ -1687,6 +1744,7 @@ CUSTOM_DOC("Advances backward through the undo history in the buffer containing buffer.exists; get_buffer_next(app, &buffer, AccessAll)){ b32 did_match = false; + i32 new_edit_position = 0; for (;;){ History_Record_Index index = 0; buffer_history_get_current_state_index(app, buffer.buffer_id, &index); @@ -1695,6 +1753,7 @@ CUSTOM_DOC("Advances backward through the undo history in the buffer containing buffer_history_get_record_info(app, buffer.buffer_id, index, &record); if (record.edit_number == highest_edit_number){ did_match = true; + new_edit_position = record_get_new_cursor_position_undo(app, buffer.buffer_id, index, record); buffer_history_set_current_state_index(app, buffer.buffer_id, index - 1); } else{ @@ -1707,6 +1766,7 @@ CUSTOM_DOC("Advances backward through the undo history in the buffer containing } if (did_match){ match_buffers[match_count] = buffer.buffer_id; + new_positions[match_count] = new_edit_position; match_count += 1; } if (buffer.buffer_id == last_buffer_match){ @@ -1715,7 +1775,7 @@ CUSTOM_DOC("Advances backward through the undo history in the buffer containing } } - view_buffer_set(app, match_buffers, match_count); + view_buffer_set(app, match_buffers, new_positions, match_count); end_temp_memory(temp); } @@ -1754,6 +1814,7 @@ CUSTOM_DOC("Advances forward through the undo history in the buffer containing t Temp_Memory temp = begin_temp_memory(scratch); Buffer_ID *match_buffers = push_array(scratch, Buffer_ID, match_count); + i32 *new_positions = push_array(scratch, i32, match_count); match_count = 0; if (lowest_edit_number != -1){ @@ -1761,6 +1822,7 @@ CUSTOM_DOC("Advances forward through the undo history in the buffer containing t buffer.exists; get_buffer_next(app, &buffer, AccessAll)){ b32 did_match = false; + i32 new_edit_position = 0; History_Record_Index max_index = 0; buffer_history_get_max_record_index(app, buffer.buffer_id, &max_index); for (;;){ @@ -1771,6 +1833,7 @@ CUSTOM_DOC("Advances forward through the undo history in the buffer containing t buffer_history_get_record_info(app, buffer.buffer_id, index + 1, &record); if (record.edit_number == lowest_edit_number){ did_match = true; + new_edit_position = record_get_new_cursor_position_redo(app, buffer.buffer_id, index + 1, record); buffer_history_set_current_state_index(app, buffer.buffer_id, index + 1); } else{ @@ -1783,6 +1846,7 @@ CUSTOM_DOC("Advances forward through the undo history in the buffer containing t } if (did_match){ match_buffers[match_count] = buffer.buffer_id; + new_positions[match_count] = new_edit_position; match_count += 1; } if (buffer.buffer_id == last_buffer_match){ @@ -1791,7 +1855,7 @@ CUSTOM_DOC("Advances forward through the undo history in the buffer containing t } } - view_buffer_set(app, match_buffers, match_count); + view_buffer_set(app, match_buffers, new_positions, match_count); end_temp_memory(temp); } diff --git a/4coder_base_types.h b/4coder_base_types.h index c27b8b73..7e4fd58e 100644 --- a/4coder_base_types.h +++ b/4coder_base_types.h @@ -73,6 +73,7 @@ typedef double f64; #define PtrDif(a,b) ((u8*)(a) - (u8*)(b)) #define PtrAsInt(a) PtrDif(a,0) #define HandleAsU64(a) (uint64_t)(PtrAsInt(a)) +#define NullMember(S,m) (&Member(S,m)) #define OffsetOfMember(S,m) PtrAsInt(&Member(S,m)) #define CastFromMember(S,m,ptr) (S*)( (u8*)(ptr) - OffsetOfMember(S,m) ) #define IntAsPtr(a) (void*)(((u8*)0) + a) @@ -215,12 +216,13 @@ static const u64 bit_63 = (((u64)1) << (31 + 32)); #define dll_remove(n) (n)->next->prev=(n)->prev,(n)->prev->next=(n)->next,(n)->next=(n)->prev=0 #define zdll_push_back_(f,l,n) if(f==0){n->next=n->prev=0;f=l=n;}else{n->prev=l;n->next=0;l->next=n;l=n;} -#define zdll_push_back(f,l,n) Stmnt( zdll_push_back_((f),(l),(n)) ) #define zdll_push_front_(f,l,n) if(f==0){n->prev=n->next=0;f=l=n;}else{n->next=l;n->prev=0;l->prev=n;l=n;} -#define zdll_push_front(f,l,n) Stmnt( zdll_push_front_((f),(l),(n)) ) #define zdll_remove_front_(f,l,n) if(f==l){f=l=0;}else{f=f->next;f->prev=0;} -#define zdll_remove_back_(f,l,n) if(f==l){f=l=0;}else{l=l->prev;l->next=0;} #define zdll_remove_(f,l,n) if(f==n){zdll_remove_front_(f,l,n);}else if(l==n){zdll_remove_back_(f,l,n);}else{dll_remove(n);} + +#define zdll_push_back(f,l,n) Stmnt( zdll_push_back_((f),(l),(n)) ) +#define zdll_push_front(f,l,n) Stmnt( zdll_push_front_((f),(l),(n)) ) +#define zdll_remove_back_(f,l,n) if(f==l){f=l=0;}else{l=l->prev;l->next=0;} #define zdll_remove(f,l,n) Stmnt( zdll_remove_((f),(l),(n)) ) #define sll_clear(f,l) (f)=(l)=0 @@ -231,17 +233,6 @@ static const u64 bit_63 = (((u64)1) << (31 + 32)); #define sll_insert(p,v) Stmnt( (v)->next=(p)->next; (p)->next = (v); ) #define sll_remove(p,v) Stmnt( Assert((p)->next == (v)); (p)->next = (v)->next; ) -#if 0 -#define dll_remove(n) (n)->next->prev=(n)->prev,(n)->prev->next=(n)->next - -#define zdll_push_back_(f,l,n) if(f==0){n->next=n->prev=0;f=l=n;}else{n->prev=l;n->next=0;l->next=n;l=n;} -#define zdll_push_back(f,l,n) do{ zdll_push_back_((f),(l),(n)) }while(0) -#define zdll_remove_front_(f,l,n) if(f==l){f=l=0;}else{f=f->next;f->prev=0;} -#define zdll_remove_back_(f,l,n) if(f==l){f=l=0;}else{l=l->prev;l->next=0;} -#define zdll_remove_(f,l,n) if(f==n){zdll_remove_front_(f,l,n);}else if(l==n){zdll_remove_back_(f,l,n);}else{dll_remove(n);} -#define zdll_remove(f,l,n) do{ zdll_remove_((f),(l),(n)) }while(0) -#endif - struct Node{ Node *next; Node *prev; diff --git a/4coder_default_framework.cpp b/4coder_default_framework.cpp index 2255b4b7..fb87bc86 100644 --- a/4coder_default_framework.cpp +++ b/4coder_default_framework.cpp @@ -60,14 +60,14 @@ new_view_settings(Application_Links *app, View_Summary *view){ //////////////////////////////// static void -view_set_passive(Application_Links *app, View_Summary *view, b32 value){ - Managed_Scope scope = view_get_managed_scope(app, view->view_id); +view_set_passive(Application_Links *app, View_ID view_id, b32 value){ + Managed_Scope scope = view_get_managed_scope(app, view_id); managed_variable_set(app, scope, view_is_passive_loc, (u64)value); } static b32 -view_get_is_passive(Application_Links *app, View_Summary *view){ - Managed_Scope scope = view_get_managed_scope(app, view->view_id); +view_get_is_passive(Application_Links *app, View_ID view_id){ + Managed_Scope scope = view_get_managed_scope(app, view_id); u64 is_passive = 0; managed_variable_get(app, scope, view_is_passive_loc, &is_passive); return(is_passive != 0); @@ -78,12 +78,10 @@ open_footer_panel(Application_Links *app, View_Summary *view){ View_Summary special_view = open_view(app, view, ViewSplit_Bottom); new_view_settings(app, &special_view); view_set_split_pixel_size(app, &special_view, (i32)(special_view.line_height*20.f)); - view_set_passive(app, &special_view, true); + view_set_passive(app, special_view.view_id, true); return(special_view); } -//////////////////////////////// - static void close_build_footer_panel(Application_Links *app){ View_Summary special_view = get_view(app, build_footer_panel_view_id, AccessAll); @@ -93,48 +91,78 @@ close_build_footer_panel(Application_Links *app){ build_footer_panel_view_id = 0; } -static View_Summary -open_build_footer_panel(Application_Links *app, b32 create_if_not_exist = true){ - View_Summary special_view = get_view(app, build_footer_panel_view_id, AccessAll); - if (create_if_not_exist && !special_view.exists){ +static b32 +open_build_footer_panel(Application_Links *app, View_ID *view_id_out){ + View_Summary special_view = {}; + get_view_summary(app, build_footer_panel_view_id, AccessAll, &special_view); + if (!special_view.exists){ View_Summary view = get_active_view(app, AccessAll); special_view = open_footer_panel(app, &view); set_active_view(app, &view); build_footer_panel_view_id = special_view.view_id; } - return(special_view); + *view_id_out = build_footer_panel_view_id; + return(true); +} + +static View_ID +get_next_view_looped_primary_panels(Application_Links *app, View_ID start_view_id, Access_Flag access){ + View_ID view_id = start_view_id; + do{ + view_id = get_next_view_looped_all_panels(app, view_id, access); + if (!view_get_is_passive(app, view_id)){ + break; + } + }while(view_id != start_view_id); + return(view_id); +} + +static View_ID +get_prev_view_looped_primary_panels(Application_Links *app, View_ID start_view_id, Access_Flag access){ + View_ID view_id = start_view_id; + do{ + view_id = get_prev_view_looped_all_panels(app, view_id, access); + if (!view_get_is_passive(app, view_id)){ + break; + } + }while(view_id != start_view_id); + return(view_id); +} + +//// + +static void +view_set_passive(Application_Links *app, View_Summary *view, b32 value){ + if (view != 0){ + view_set_passive(app, view->view_id, value); + } +} + +static b32 +view_get_is_passive(Application_Links *app, View_Summary *view){ + return(view != 0 && view_get_is_passive(app, view->view_id)); +} + +static View_Summary +open_build_footer_panel(Application_Links *app){ + View_Summary summary = {}; + View_ID build_footer_id = 0; + if (open_build_footer_panel(app, &build_footer_id)){ + get_view_summary(app, build_footer_id, AccessAll, &summary); + } + return(summary); } static void get_next_view_looped_primary_panels(Application_Links *app, View_Summary *view_start, Access_Flag access){ - View_ID original_view_id = view_start->view_id; - View_Summary view = *view_start; - do{ - get_next_view_looped_all_panels(app, &view, access); - if (!view_get_is_passive(app, &view)){ - break; - } - }while(view.view_id != original_view_id); - if (!view.exists){ - memset(&view, 0, sizeof(view)); - } - *view_start = view; + View_ID new_id = get_next_view_looped_primary_panels(app, view_start->view_id, access); + get_view_summary(app, new_id, AccessAll, view_start); } static void get_prev_view_looped_primary_panels(Application_Links *app, View_Summary *view_start, Access_Flag access){ - View_ID original_view_id = view_start->view_id; - View_Summary view = *view_start; - do{ - get_prev_view_looped_all_panels(app, &view, access); - if (!view_get_is_passive(app, &view)){ - break; - } - }while(view.view_id != original_view_id); - if (!view.exists){ - memset(&view, 0, sizeof(view)); - } - *view_start = view; + View_ID new_id = get_prev_view_looped_primary_panels(app, view_start->view_id, access); + get_view_summary(app, new_id, AccessAll, view_start); } static View_Summary @@ -146,6 +174,63 @@ get_next_view_after_active(Application_Links *app, u32 access){ return(view); } +//////////////////////////////// + +static void +view_buffer_set(Application_Links *app, Buffer_ID *buffers, i32 *positions, i32 count){ + if (count > 0){ + // TODO(allen): replace with context supplied arena + Arena arena = make_arena(app); + + struct View_Node{ + View_Node *next; + View_ID view_id; + }; + + View_ID active_view_id = 0; + get_active_view(app, AccessAll, &active_view_id); + View_ID first_view_id = active_view_id; + if (view_get_is_passive(app, active_view_id)){ + first_view_id = get_next_view_looped_primary_panels(app, active_view_id, AccessAll); + } + + View_ID view_id = first_view_id; + + View_Node *primary_view_first = 0; + View_Node *primary_view_last = 0; + i32 available_view_count = 0; + + primary_view_first = primary_view_last = push_array(&arena, View_Node, 1); + primary_view_last->next = 0; + primary_view_last->view_id = view_id; + available_view_count += 1; + for (;;){ + view_id = get_next_view_looped_primary_panels(app, view_id, AccessAll); + if (view_id == first_view_id){ + break; + } + View_Node *node = push_array(&arena, View_Node, 1); + primary_view_last->next = node; + node->next = 0; + node->view_id = view_id; + primary_view_last = node; + available_view_count += 1; + } + + i32 buffer_set_count = clamp_top(count, available_view_count); + View_Node *node = primary_view_first; + for (i32 i = 0; i < buffer_set_count; i += 1, node = node->next){ + if (view_set_buffer(app, node->view_id, buffers[i], 0)){ + view_set_cursor(app, node->view_id, seek_pos(positions[i]), true); + } + } + + arena_release_all(&arena); + } +} + +//////////////////////////////// + CUSTOM_COMMAND_SIG(change_active_panel) CUSTOM_DOC("Change the currently active panel, moving to the panel with the next highest view_id.") { diff --git a/4coder_default_hooks.cpp b/4coder_default_hooks.cpp index d2cb8436..4aaa8274 100644 --- a/4coder_default_hooks.cpp +++ b/4coder_default_hooks.cpp @@ -1129,6 +1129,7 @@ OPEN_FILE_HOOK_SIG(default_file_save){ } FILE_EDIT_RANGE_SIG(default_file_edit_range){ +#if 0 Buffer_Summary buffer_summary = {}; if (get_buffer_summary(app, buffer_id, AccessAll, &buffer_summary)){ if (!match(make_string(buffer_summary.buffer_name, buffer_summary.buffer_name_len), make_lit_string("*messages*"))){ @@ -1146,6 +1147,7 @@ FILE_EDIT_RANGE_SIG(default_file_edit_range){ print_message(app, str.str, str.size); } } +#endif // no meaning for return return(0); diff --git a/4coder_generated/app_functions.h b/4coder_generated/app_functions.h index f2520a17..296cb008 100644 --- a/4coder_generated/app_functions.h +++ b/4coder_generated/app_functions.h @@ -36,6 +36,7 @@ struct Application_Links; #define BUFFER_GET_FILE_ATTRIBUTES_SIG(n) b32 n(Application_Links *app, Buffer_ID buffer_id, File_Attributes *attributes_out) #define GET_VIEW_FIRST_SIG(n) b32 n(Application_Links *app, Access_Flag access, View_ID *view_id_out) #define GET_VIEW_NEXT_SIG(n) b32 n(Application_Links *app, View_ID view_id, Access_Flag access, View_ID *view_id_out) +#define GET_VIEW_PREV_SIG(n) b32 n(Application_Links *app, View_ID view_id, Access_Flag access, View_ID *view_id_out) #define GET_VIEW_SUMMARY_SIG(n) b32 n(Application_Links *app, View_ID view_id, Access_Flag access, View_Summary *view_summary_out) #define GET_ACTIVE_VIEW_SIG(n) b32 n(Application_Links *app, Access_Flag access, View_ID *view_id_out) #define GET_ACTIVE_PANEL_SIG(n) b32 n(Application_Links *app, Panel_ID *panel_id_out) @@ -191,6 +192,7 @@ typedef BUFFER_REOPEN_SIG(Buffer_Reopen_Function); typedef BUFFER_GET_FILE_ATTRIBUTES_SIG(Buffer_Get_File_Attributes_Function); typedef GET_VIEW_FIRST_SIG(Get_View_First_Function); typedef GET_VIEW_NEXT_SIG(Get_View_Next_Function); +typedef GET_VIEW_PREV_SIG(Get_View_Prev_Function); typedef GET_VIEW_SUMMARY_SIG(Get_View_Summary_Function); typedef GET_ACTIVE_VIEW_SIG(Get_Active_View_Function); typedef GET_ACTIVE_PANEL_SIG(Get_Active_Panel_Function); @@ -348,6 +350,7 @@ Buffer_Reopen_Function *buffer_reopen; Buffer_Get_File_Attributes_Function *buffer_get_file_attributes; Get_View_First_Function *get_view_first; Get_View_Next_Function *get_view_next; +Get_View_Prev_Function *get_view_prev; Get_View_Summary_Function *get_view_summary; Get_Active_View_Function *get_active_view; Get_Active_Panel_Function *get_active_panel; @@ -504,6 +507,7 @@ Buffer_Reopen_Function *buffer_reopen_; Buffer_Get_File_Attributes_Function *buffer_get_file_attributes_; Get_View_First_Function *get_view_first_; Get_View_Next_Function *get_view_next_; +Get_View_Prev_Function *get_view_prev_; Get_View_Summary_Function *get_view_summary_; Get_Active_View_Function *get_active_view_; Get_Active_Panel_Function *get_active_panel_; @@ -668,6 +672,7 @@ app_links->buffer_reopen_ = Buffer_Reopen;\ app_links->buffer_get_file_attributes_ = Buffer_Get_File_Attributes;\ app_links->get_view_first_ = Get_View_First;\ app_links->get_view_next_ = Get_View_Next;\ +app_links->get_view_prev_ = Get_View_Prev;\ app_links->get_view_summary_ = Get_View_Summary;\ app_links->get_active_view_ = Get_Active_View;\ app_links->get_active_panel_ = Get_Active_Panel;\ @@ -824,6 +829,7 @@ static b32 buffer_reopen(Application_Links *app, Buffer_ID buffer_id, Buffer_Reo static b32 buffer_get_file_attributes(Application_Links *app, Buffer_ID buffer_id, File_Attributes *attributes_out){return(app->buffer_get_file_attributes(app, buffer_id, attributes_out));} static b32 get_view_first(Application_Links *app, Access_Flag access, View_ID *view_id_out){return(app->get_view_first(app, access, view_id_out));} static b32 get_view_next(Application_Links *app, View_ID view_id, Access_Flag access, View_ID *view_id_out){return(app->get_view_next(app, view_id, access, view_id_out));} +static b32 get_view_prev(Application_Links *app, View_ID view_id, Access_Flag access, View_ID *view_id_out){return(app->get_view_prev(app, view_id, access, view_id_out));} static b32 get_view_summary(Application_Links *app, View_ID view_id, Access_Flag access, View_Summary *view_summary_out){return(app->get_view_summary(app, view_id, access, view_summary_out));} static b32 get_active_view(Application_Links *app, Access_Flag access, View_ID *view_id_out){return(app->get_active_view(app, access, view_id_out));} static b32 get_active_panel(Application_Links *app, Panel_ID *panel_id_out){return(app->get_active_panel(app, panel_id_out));} @@ -980,6 +986,7 @@ static b32 buffer_reopen(Application_Links *app, Buffer_ID buffer_id, Buffer_Reo static b32 buffer_get_file_attributes(Application_Links *app, Buffer_ID buffer_id, File_Attributes *attributes_out){return(app->buffer_get_file_attributes_(app, buffer_id, attributes_out));} static b32 get_view_first(Application_Links *app, Access_Flag access, View_ID *view_id_out){return(app->get_view_first_(app, access, view_id_out));} static b32 get_view_next(Application_Links *app, View_ID view_id, Access_Flag access, View_ID *view_id_out){return(app->get_view_next_(app, view_id, access, view_id_out));} +static b32 get_view_prev(Application_Links *app, View_ID view_id, Access_Flag access, View_ID *view_id_out){return(app->get_view_prev_(app, view_id, access, view_id_out));} static b32 get_view_summary(Application_Links *app, View_ID view_id, Access_Flag access, View_Summary *view_summary_out){return(app->get_view_summary_(app, view_id, access, view_summary_out));} static b32 get_active_view(Application_Links *app, Access_Flag access, View_ID *view_id_out){return(app->get_active_view_(app, access, view_id_out));} static b32 get_active_panel(Application_Links *app, Panel_ID *panel_id_out){return(app->get_active_panel_(app, panel_id_out));} diff --git a/4coder_generated/command_metadata.h b/4coder_generated/command_metadata.h index 8490525d..6615e756 100644 --- a/4coder_generated/command_metadata.h +++ b/4coder_generated/command_metadata.h @@ -255,7 +255,7 @@ int32_t source_name_len; int32_t line_number; }; static Command_Metadata fcoder_metacmd_table[234] = { -{ PROC_LINKS(allow_mouse, 0), "allow_mouse", 11, "Shows the mouse and causes all mouse input to be processed normally.", 68, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 247 }, +{ PROC_LINKS(allow_mouse, 0), "allow_mouse", 11, "Shows the mouse and causes all mouse input to be processed normally.", 68, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 332 }, { PROC_LINKS(auto_tab_line_at_cursor, 0), "auto_tab_line_at_cursor", 23, "Auto-indents the line on which the cursor sits.", 47, "w:\\4ed\\code\\4coder_auto_indent.cpp", 34, 629 }, { PROC_LINKS(auto_tab_range, 0), "auto_tab_range", 14, "Auto-indents the range between the cursor and the mark.", 55, "w:\\4ed\\code\\4coder_auto_indent.cpp", 34, 640 }, { PROC_LINKS(auto_tab_whole_file, 0), "auto_tab_whole_file", 19, "Audo-indents the entire current buffer.", 39, "w:\\4ed\\code\\4coder_auto_indent.cpp", 34, 619 }, @@ -265,8 +265,8 @@ static Command_Metadata fcoder_metacmd_table[234] = { { PROC_LINKS(build_in_build_panel, 0), "build_in_build_panel", 20, "Looks for a build.bat, build.sh, or makefile in the current and parent directories. Runs the first that it finds and prints the output to *compilation*. Puts the *compilation* buffer in a panel at the footer of the current view.", 230, "w:\\4ed\\code\\4coder_build_commands.cpp", 37, 187 }, { PROC_LINKS(build_search, 0), "build_search", 12, "Looks for a build.bat, build.sh, or makefile in the current and parent directories. Runs the first that it finds and prints the output to *compilation*.", 153, "w:\\4ed\\code\\4coder_build_commands.cpp", 37, 155 }, { PROC_LINKS(center_view, 0), "center_view", 11, "Centers the view vertically on the line on which the cursor sits.", 65, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 151 }, -{ PROC_LINKS(change_active_panel, 0), "change_active_panel", 19, "Change the currently active panel, moving to the panel with the next highest view_id.", 85, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 149 }, -{ PROC_LINKS(change_active_panel_backwards, 0), "change_active_panel_backwards", 29, "Change the currently active panel, moving to the panel with the next lowest view_id.", 84, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 159 }, +{ PROC_LINKS(change_active_panel, 0), "change_active_panel", 19, "Change the currently active panel, moving to the panel with the next highest view_id.", 85, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 234 }, +{ PROC_LINKS(change_active_panel_backwards, 0), "change_active_panel_backwards", 29, "Change the currently active panel, moving to the panel with the next lowest view_id.", 84, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 244 }, { PROC_LINKS(change_to_build_panel, 0), "change_to_build_panel", 21, "If the special build panel is open, makes the build panel the active panel.", 75, "w:\\4ed\\code\\4coder_build_commands.cpp", 37, 209 }, { PROC_LINKS(clean_all_lines, 0), "clean_all_lines", 15, "Removes trailing whitespace from all lines in the current buffer.", 65, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 441 }, { PROC_LINKS(click_set_cursor, 0), "click_set_cursor", 16, "Sets the cursor position to the mouse position.", 47, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 210 }, @@ -385,13 +385,13 @@ static Command_Metadata fcoder_metacmd_table[234] = { { PROC_LINKS(open_all_code, 0), "open_all_code", 13, "Open all code in the current directory. File types are determined by extensions. An extension is considered code based on the extensions specified in 4coder.config.", 164, "w:\\4ed\\code\\4coder_project_commands.cpp", 39, 1067 }, { PROC_LINKS(open_all_code_recursive, 0), "open_all_code_recursive", 23, "Works as open_all_code but also runs in all subdirectories.", 59, "w:\\4ed\\code\\4coder_project_commands.cpp", 39, 1074 }, { PROC_LINKS(open_file_in_quotes, 0), "open_file_in_quotes", 19, "Reads a filename from surrounding '\"' characters and attempts to open the corresponding file.", 94, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1507 }, -{ PROC_LINKS(open_in_other, 0), "open_in_other", 13, "Interactively opens a file in the other panel.", 46, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1826 }, +{ PROC_LINKS(open_in_other, 0), "open_in_other", 13, "Interactively opens a file in the other panel.", 46, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1890 }, { PROC_LINKS(open_long_braces, 0), "open_long_braces", 16, "At the cursor, insert a '{' and '}' separated by a blank line.", 62, "w:\\4ed\\code\\4coder_combined_write_commands.cpp", 46, 55 }, { PROC_LINKS(open_long_braces_break, 0), "open_long_braces_break", 22, "At the cursor, insert a '{' and '}break;' separated by a blank line.", 68, "w:\\4ed\\code\\4coder_combined_write_commands.cpp", 46, 71 }, { PROC_LINKS(open_long_braces_semicolon, 0), "open_long_braces_semicolon", 26, "At the cursor, insert a '{' and '};' separated by a blank line.", 63, "w:\\4ed\\code\\4coder_combined_write_commands.cpp", 46, 63 }, { PROC_LINKS(open_matching_file_cpp, 0), "open_matching_file_cpp", 22, "If the current file is a *.cpp or *.h, attempts to open the corresponding *.h or *.cpp file in the other view.", 110, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1543 }, -{ PROC_LINKS(open_panel_hsplit, 0), "open_panel_hsplit", 17, "Create a new panel by horizontally splitting the active panel.", 62, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 178 }, -{ PROC_LINKS(open_panel_vsplit, 0), "open_panel_vsplit", 17, "Create a new panel by vertically splitting the active panel.", 60, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 169 }, +{ PROC_LINKS(open_panel_hsplit, 0), "open_panel_hsplit", 17, "Create a new panel by horizontally splitting the active panel.", 62, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 263 }, +{ PROC_LINKS(open_panel_vsplit, 0), "open_panel_vsplit", 17, "Create a new panel by vertically splitting the active panel.", 60, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 254 }, { PROC_LINKS(page_down, 0), "page_down", 9, "Scrolls the view down one view height and moves the cursor down one view height.", 80, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 358 }, { PROC_LINKS(page_up, 0), "page_up", 7, "Scrolls the view up one view height and moves the cursor up one view height.", 76, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 349 }, { PROC_LINKS(paste, 0), "paste", 5, "At the cursor, insert the text at the top of the clipboard.", 59, "w:\\4ed\\code\\4coder_clipboard.cpp", 32, 46 }, @@ -405,9 +405,9 @@ static Command_Metadata fcoder_metacmd_table[234] = { { PROC_LINKS(query_replace, 0), "query_replace", 13, "Queries the user for two strings, and incrementally replaces every occurence of the first string with the second string.", 120, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1062 }, { PROC_LINKS(query_replace_identifier, 0), "query_replace_identifier", 24, "Queries the user for a string, and incrementally replace every occurence of the word or token found at the cursor with the specified string.", 140, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1086 }, { PROC_LINKS(query_replace_selection, 0), "query_replace_selection", 23, "Queries the user for a string, and incrementally replace every occurence of the string found in the selected range with the specified string.", 141, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1104 }, -{ PROC_LINKS(redo, 0), "redo", 4, "Advances forward through the undo history in the buffer containing the most recent regular edit.", 96, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1723 }, -{ PROC_LINKS(redo_this_buffer, 0), "redo_this_buffer", 16, "Advances forwards through the undo history of the current buffer.", 65, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1637 }, -{ PROC_LINKS(remap_interactive, 0), "remap_interactive", 17, "Switch to a named key binding map.", 34, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 297 }, +{ PROC_LINKS(redo, 0), "redo", 4, "Advances forward through the undo history in the buffer containing the most recent regular edit.", 96, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1783 }, +{ PROC_LINKS(redo_this_buffer, 0), "redo_this_buffer", 16, "Advances forwards through the undo history of the current buffer.", 65, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1691 }, +{ PROC_LINKS(remap_interactive, 0), "remap_interactive", 17, "Switch to a named key binding map.", 34, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 382 }, { PROC_LINKS(rename_file_query, 0), "rename_file_query", 17, "Queries the user for a new name and renames the file of the current buffer, altering the buffer's name too.", 107, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1244 }, { PROC_LINKS(rename_parameter, 0), "rename_parameter", 16, "If the cursor is found to be on the name of a function parameter in the signature of a function definition, all occurences within the scope of the function will be replaced with a new provided string.", 200, "w:\\4ed\\code\\4coder_experiments.cpp", 34, 383 }, { PROC_LINKS(reopen, 0), "reopen", 6, "Reopen the current buffer from the hard drive.", 46, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1615 }, @@ -447,8 +447,8 @@ static Command_Metadata fcoder_metacmd_table[234] = { { PROC_LINKS(set_bindings_default, 0), "set_bindings_default", 20, "Remap keybindings using the 'default' mapping rule.", 51, "w:\\4ed\\code\\4coder_remapping_commands.cpp", 41, 61 }, { PROC_LINKS(set_bindings_mac_default, 0), "set_bindings_mac_default", 24, "Remap keybindings using the 'mac-default' mapping rule.", 55, "w:\\4ed\\code\\4coder_remapping_commands.cpp", 41, 75 }, { PROC_LINKS(set_mark, 0), "set_mark", 8, "Sets the mark to the current position of the cursor.", 52, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 121 }, -{ PROC_LINKS(set_mode_to_notepad_like, 0), "set_mode_to_notepad_like", 24, "Sets the edit mode to Notepad like.", 35, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 265 }, -{ PROC_LINKS(set_mode_to_original, 0), "set_mode_to_original", 20, "Sets the edit mode to 4coder original.", 38, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 259 }, +{ PROC_LINKS(set_mode_to_notepad_like, 0), "set_mode_to_notepad_like", 24, "Sets the edit mode to Notepad like.", 35, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 350 }, +{ PROC_LINKS(set_mode_to_original, 0), "set_mode_to_original", 20, "Sets the edit mode to 4coder original.", 38, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 344 }, { PROC_LINKS(setup_build_bat, 0), "setup_build_bat", 15, "Queries the user for several configuration options and initializes a new build batch script.", 92, "w:\\4ed\\code\\4coder_project_commands.cpp", 39, 1498 }, { PROC_LINKS(setup_build_bat_and_sh, 0), "setup_build_bat_and_sh", 22, "Queries the user for several configuration options and initializes a new build batch script.", 92, "w:\\4ed\\code\\4coder_project_commands.cpp", 39, 1510 }, { PROC_LINKS(setup_build_sh, 0), "setup_build_sh", 14, "Queries the user for several configuration options and initializes a new build shell script.", 92, "w:\\4ed\\code\\4coder_project_commands.cpp", 39, 1504 }, @@ -458,24 +458,24 @@ static Command_Metadata fcoder_metacmd_table[234] = { { PROC_LINKS(snipe_token_or_word, 0), "snipe_token_or_word", 19, "Delete a single, whole token on or to the left of the cursor and post it to the clipboard.", 90, "w:\\4ed\\code\\4coder_seek.cpp", 27, 1269 }, { PROC_LINKS(snipe_token_or_word_right, 0), "snipe_token_or_word_right", 25, "Delete a single, whole token on or to the right of the cursor and post it to the clipboard.", 91, "w:\\4ed\\code\\4coder_seek.cpp", 27, 1275 }, { PROC_LINKS(snippet_lister, 0), "snippet_lister", 14, "Opens a snippet lister for inserting whole pre-written snippets of text.", 72, "w:\\4ed\\code\\4coder_combined_write_commands.cpp", 46, 248 }, -{ PROC_LINKS(suppress_mouse, 0), "suppress_mouse", 14, "Hides the mouse and causes all mosue input (clicks, position, wheel) to be ignored.", 83, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 241 }, +{ PROC_LINKS(suppress_mouse, 0), "suppress_mouse", 14, "Hides the mouse and causes all mosue input (clicks, position, wheel) to be ignored.", 83, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 326 }, { PROC_LINKS(swap_buffers_between_panels, 0), "swap_buffers_between_panels", 27, "Set the other non-active panel to view the buffer that the active panel views, and switch to that panel.", 104, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1567 }, { PROC_LINKS(to_lowercase, 0), "to_lowercase", 12, "Converts all ascii text in the range between the cursor and the mark to lowercase.", 82, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 421 }, { PROC_LINKS(to_uppercase, 0), "to_uppercase", 12, "Converts all ascii text in the range between the cursor and the mark to uppercase.", 82, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 401 }, { PROC_LINKS(toggle_filebar, 0), "toggle_filebar", 14, "Toggles the visibility status of the current view's filebar.", 60, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 551 }, { PROC_LINKS(toggle_fps_meter, 0), "toggle_fps_meter", 16, "Toggles the visibility of the FPS performance meter", 51, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 569 }, -{ PROC_LINKS(toggle_fullscreen, 0), "toggle_fullscreen", 17, "Toggle fullscreen mode on or off. The change(s) do not take effect until the next frame.", 89, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 289 }, -{ PROC_LINKS(toggle_highlight_enclosing_scopes, 0), "toggle_highlight_enclosing_scopes", 33, "In code files scopes surrounding the cursor are highlighted with distinguishing colors.", 87, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 277 }, -{ PROC_LINKS(toggle_highlight_line_at_cursor, 0), "toggle_highlight_line_at_cursor", 31, "Toggles the line highlight at the cursor.", 41, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 271 }, +{ PROC_LINKS(toggle_fullscreen, 0), "toggle_fullscreen", 17, "Toggle fullscreen mode on or off. The change(s) do not take effect until the next frame.", 89, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 374 }, +{ PROC_LINKS(toggle_highlight_enclosing_scopes, 0), "toggle_highlight_enclosing_scopes", 33, "In code files scopes surrounding the cursor are highlighted with distinguishing colors.", 87, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 362 }, +{ PROC_LINKS(toggle_highlight_line_at_cursor, 0), "toggle_highlight_line_at_cursor", 31, "Toggles the line highlight at the cursor.", 41, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 356 }, { PROC_LINKS(toggle_line_numbers, 0), "toggle_line_numbers", 19, "Toggles the left margin line numbers.", 37, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 656 }, { PROC_LINKS(toggle_line_wrap, 0), "toggle_line_wrap", 16, "Toggles the current buffer's line wrapping status.", 50, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 560 }, -{ PROC_LINKS(toggle_mouse, 0), "toggle_mouse", 12, "Toggles the mouse suppression mode, see suppress_mouse and allow_mouse.", 71, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 253 }, -{ PROC_LINKS(toggle_paren_matching_helper, 0), "toggle_paren_matching_helper", 28, "In code files matching parentheses pairs are colored with distinguishing colors.", 80, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 283 }, +{ PROC_LINKS(toggle_mouse, 0), "toggle_mouse", 12, "Toggles the mouse suppression mode, see suppress_mouse and allow_mouse.", 71, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 338 }, +{ PROC_LINKS(toggle_paren_matching_helper, 0), "toggle_paren_matching_helper", 28, "In code files matching parentheses pairs are colored with distinguishing colors.", 80, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 368 }, { PROC_LINKS(toggle_show_whitespace, 0), "toggle_show_whitespace", 22, "Toggles the current buffer's whitespace visibility status.", 58, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 649 }, { PROC_LINKS(toggle_virtual_whitespace, 0), "toggle_virtual_whitespace", 25, "Toggles the current buffer's virtual whitespace status.", 55, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 638 }, { PROC_LINKS(uncomment_line, 0), "uncomment_line", 14, "If present, delete '//' at the beginning of the line after leading whitespace.", 78, "w:\\4ed\\code\\4coder_combined_write_commands.cpp", 46, 147 }, -{ PROC_LINKS(undo, 0), "undo", 4, "Advances backward through the undo history in the buffer containing the most recent regular edit.", 97, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1651 }, -{ PROC_LINKS(undo_this_buffer, 0), "undo_this_buffer", 16, "Advances backwards through the undo history of the current buffer.", 66, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1625 }, +{ PROC_LINKS(undo, 0), "undo", 4, "Advances backward through the undo history in the buffer containing the most recent regular edit.", 97, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1707 }, +{ PROC_LINKS(undo_this_buffer, 0), "undo_this_buffer", 16, "Advances backwards through the undo history of the current buffer.", 66, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1677 }, { PROC_LINKS(view_buffer_other_panel, 0), "view_buffer_other_panel", 23, "Set the other non-active panel to view the buffer that the active panel views, and switch to that panel.", 104, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1557 }, { PROC_LINKS(view_jump_list_with_lister, 0), "view_jump_list_with_lister", 26, "When executed on a buffer with jumps, creates a persistent lister for all the jumps", 83, "w:\\4ed\\code\\4coder_jump_lister.cpp", 34, 108 }, { PROC_LINKS(word_complete, 0), "word_complete", 13, "Iteratively tries completing the word to the left of the cursor with other words in open buffers that have the same prefix string.", 130, "w:\\4ed\\code\\4coder_search.cpp", 29, 958 }, diff --git a/4coder_helper.cpp b/4coder_helper.cpp index b1ccd23e..469233d3 100644 --- a/4coder_helper.cpp +++ b/4coder_helper.cpp @@ -608,10 +608,8 @@ buffer_identifier_to_buffer_summary(Application_Links *app, Buffer_Identifier id } static b32 -view_open_file(Application_Links *app, View_Summary *view, - char *filename, i32 filename_len, b32 never_new){ +view_open_file(Application_Links *app, View_Summary *view, char *filename, i32 filename_len, b32 never_new){ b32 result = false; - if (view != 0){ Buffer_Summary buffer = {}; if (open_file(app, &buffer, filename, filename_len, false, never_new)){ @@ -619,37 +617,70 @@ view_open_file(Application_Links *app, View_Summary *view, result = true; } } - return(result); } -static void -get_view_prev(Application_Links *app, View_Summary *view, u32 access){ - if (view->exists){ - View_ID original_id = view->view_id; - View_ID check_id = original_id; - - View_Summary new_view = {}; - - for (;;){ - --check_id; - if (check_id <= 0){ - check_id = 16; - } - if (check_id == original_id){ - new_view = *view; - break; - } - new_view = get_view(app, check_id, access); - if (new_view.exists){ - break; - } - } - - *view = new_view; - } +//////////////////////////////// + +// TODO(allen): replace this with get_view_prev(app, 0, access, view_id_out); +static b32 +get_view_last(Application_Links *app, Access_Flag access, View_ID *view_id_out){ + return(get_view_prev(app, 0, access, view_id_out)); } +static View_ID +get_next_view_looped_all_panels(Application_Links *app, View_ID view_id, Access_Flag access){ + if (!get_view_next(app, view_id, access, &view_id)){ + if (!get_view_first(app, access, &view_id)){ + view_id = 0; + } + } + return(view_id); +} + +static View_ID +get_prev_view_looped_all_panels(Application_Links *app, View_ID view_id, Access_Flag access){ + if (!get_view_prev(app, view_id, access, &view_id)){ + if (!get_view_prev(app, 0, access, &view_id)){ + view_id = 0; + } + } + return(view_id); +} + +//// + +static void +get_view_prev(Application_Links *app, View_Summary *view, Access_Flag access){ + View_ID new_id = 0; + get_view_prev(app, view->view_id, access, &new_id); + get_view_summary(app, new_id, access, view); +} + +static View_Summary +get_view_last(Application_Links *app, Access_Flag access){ + View_Summary view = {}; + View_ID new_id = 0; + if (get_view_last(app, access, &new_id)){ + get_view_summary(app, new_id, access, &view); + } + return(view); +} + +static void +get_next_view_looped_all_panels(Application_Links *app, View_Summary *view, Access_Flag access){ + View_ID new_id = get_next_view_looped_all_panels(app, view->view_id, access); + get_view_summary(app, new_id, access, view); +} + +static void +get_prev_view_looped_all_panels(Application_Links *app, View_Summary *view, u32 access){ + View_ID new_id = get_prev_view_looped_all_panels(app, view->view_id, access); + get_view_summary(app, new_id, access, view); +} + +//////////////////////////////// + static Buffer_Kill_Result kill_buffer(Application_Links *app, Buffer_Identifier identifier, View_ID gui_view_id, Buffer_Kill_Flag flags){ Buffer_Kill_Result result = kill_buffer(app, identifier, flags); @@ -661,33 +692,6 @@ kill_buffer(Application_Links *app, Buffer_Identifier identifier, View_ID gui_vi return(result); } -static View_Summary -get_view_last(Application_Links *app, u32 access){ - View_Summary view = {}; - view.exists = true; - get_view_prev(app, &view, access); - if (view.view_id < 1 || view.view_id > 16){ - memset(&view, 0, sizeof(view)); - } - return(view); -} - -static void -get_next_view_looped_all_panels(Application_Links *app, View_Summary *view, u32 access){ - get_view_next(app, view, access); - if (!view->exists){ - *view = get_view_first(app, access); - } -} - -static void -get_prev_view_looped_all_panels(Application_Links *app, View_Summary *view, u32 access){ - get_view_prev(app, view, access); - if (!view->exists){ - *view = get_view_last(app, access); - } -} - static void refresh_buffer(Application_Links *app, Buffer_Summary *buffer){ *buffer = get_buffer(app, buffer->buffer_id, AccessAll); @@ -1659,33 +1663,21 @@ get_single_record(Application_Links *app, Buffer_ID buffer_id, History_Record_In //////////////////////////////// -static void -view_buffer_set(Application_Links *app, Buffer_ID *buffers, i32 count){ - // TODO(allen): do(implement view_buffer_set) -} - -//////////////////////////////// - static void condense_whitespace(String *a) { *a = skip_chop_whitespace(*a); - int size = a->size; a->size = 0; int i = 0; - while(i < size) - { - if(char_is_whitespace(a->str[i])) - { + for (;i < size;){ + if (char_is_whitespace(a->str[i])){ a->str[a->size++] = ' '; - while((i < size) && char_is_whitespace(a->str[i])) - { + for (;(i < size) && char_is_whitespace(a->str[i]);){ ++i; } } - else - { + else{ a->str[a->size++] = a->str[i++]; } } diff --git a/4ed_api_implementation.cpp b/4ed_api_implementation.cpp index c7cc4a36..521071f8 100644 --- a/4ed_api_implementation.cpp +++ b/4ed_api_implementation.cpp @@ -1720,6 +1720,26 @@ get_view_next__inner(Layout *layout, View *view){ return(view); } +internal View* +get_view_prev__inner(Layout *layout, View *view){ + if (view != 0){ + Panel *panel = view->panel; + panel = layout_get_prev_open_panel(layout, panel); + if (panel != 0){ + view = panel->view; + } + else{ + view = 0; + } + } + else{ + Panel *panel = layout_get_first_open_panel(layout); + view = panel->view; + } + return(view); +} + +// TODO(allen): replace this with get_view_next(app, 0, access, view_id_out); // TODO(allen): redocument API_EXPORT b32 Get_View_First(Application_Links *app, Access_Flag access, View_ID *view_id_out) @@ -1780,6 +1800,24 @@ DOC_SEE(get_view_first) return(result); } +API_EXPORT b32 +Get_View_Prev(Application_Links *app, View_ID view_id, Access_Flag access, View_ID *view_id_out) +{ + Models *models = (Models*)app->cmd_context; + Layout *layout = &models->layout; + View *view = imp_get_view(models, view_id); + view = get_view_prev__inner(layout, view); + for (;view != 0 && !access_test(view_get_access_flags(view), access);){ + view = get_view_prev__inner(layout, view); + } + b32 result = false; + if (view != 0){ + *view_id_out = view_get_id(&models->live_set, view); + result = true; + } + return(result); +} + // TODO(allen): redocument API_EXPORT b32 Get_View_Summary(Application_Links *app, View_ID view_id, Access_Flag access, View_Summary *view_summary_out) @@ -3622,11 +3660,6 @@ buffer_history__fill_record_info(Record *record, Record_Info *out){ out->single.string_backward = make_string(record->single.str_backward, record->single.length_backward); out->single.first = record->single.first; }break; - case RecordKind_Batch: - { - out->batch.type = record->batch.type; - out->batch.count = record->batch.count; - }break; case RecordKind_Group: { out->group.count = record->group.count; diff --git a/4ed_edit.cpp b/4ed_edit.cpp index a8dcefd8..8ab90a50 100644 --- a/4ed_edit.cpp +++ b/4ed_edit.cpp @@ -348,34 +348,6 @@ edit__apply_record_forward(System_Functions *system, Models *models, Editing_Fil edit_single(system, models, file, edit, behaviors_prototype); }break; - case RecordKind_Batch: - { - Partition *scratch = &models->mem.part; - Temp_Memory temp = begin_temp_memory(scratch); - - i32 count = record->batch.count; - Edit_Array edits = {}; - edits.vals = push_array(scratch, Edit, count); - edits.count = count; - - Edit *edit = edits.vals; - Record_Batch_Slot *batch_slot = record->batch.batch_records; - char *str_base_forward = record->batch.str_base_forward; - for (i32 i = 0; i < count; i += 1, edit += 1, batch_slot += 1){ - edit->str = str_base_forward; - edit->length = batch_slot->length_forward; - edit->range.first = batch_slot->first; - edit->range.one_past_last = edit->range.first + batch_slot->length_backward; - str_base_forward += batch_slot->length_forward; - } - - Edit_Behaviors behaviors = behaviors_prototype; - behaviors.batch_type = record->batch.type; - edit_batch(system, models, file, edits, behaviors); - - end_temp_memory(temp); - }break; - case RecordKind_Group: { Node *sentinel = &record->group.children; @@ -410,37 +382,6 @@ edit__apply_record_backward(System_Functions *system, Models *models, Editing_Fi edit_single(system, models, file, edit, behaviors_prototype); }break; - case RecordKind_Batch: - { - Partition *scratch = &models->mem.part; - Temp_Memory temp = begin_temp_memory(scratch); - - i32 count = record->batch.count; - Edit_Array edits = {}; - edits.vals = push_array(scratch, Edit, count); - edits.count = count; - - i32 shift_amount = 0; - - Edit *edit = edits.vals; - Record_Batch_Slot *batch_slot = record->batch.batch_records; - char *str_base_backward = record->batch.str_base_backward; - for (i32 i = 0; i < count; i += 1, edit += 1, batch_slot += 1){ - edit->str = str_base_backward; - edit->length = batch_slot->length_backward; - edit->range.first = batch_slot->first + shift_amount; - edit->range.one_past_last = edit->range.first + batch_slot->length_forward; - str_base_backward += batch_slot->length_backward; - shift_amount += batch_slot->length_forward - batch_slot->length_backward; - } - - Edit_Behaviors behaviors = behaviors_prototype; - behaviors.batch_type = record->batch.type; - edit_batch(system, models, file, edits, behaviors); - - end_temp_memory(temp); - }break; - case RecordKind_Group: { Node *sentinel = &record->group.children; diff --git a/4ed_history.cpp b/4ed_history.cpp index 63b41843..1a466c92 100644 --- a/4ed_history.cpp +++ b/4ed_history.cpp @@ -239,115 +239,56 @@ history__free_nodes(History *history, i32 first_index, Node *first_node, Node *l internal void history_record_edit(Heap *heap, Global_History *global_history, History *history, Gap_Buffer *buffer, Edit edit){ - if (!history->activated){ - return; - } - - Assert(history->record_lookup.count == history->record_count); - - Record *new_record = history__allocate_record(heap, history); - history__stash_record(heap, history, new_record); - - new_record->restore_point = temp_memory_light(begin_temp_memory(&history->arena)); - new_record->edit_number = global_history_get_edit_number(global_history); - - new_record->kind = RecordKind_Single; - - i32 length_forward = edit.length; - i32 length_backward = edit.range.one_past_last - edit.range.first; - - new_record->single.str_forward = push_array(&history->arena, char, length_forward); - new_record->single.str_backward = push_array(&history->arena, char, length_backward); - new_record->single.length_forward = length_forward; - new_record->single.length_backward = length_backward; - new_record->single.first = edit.range.first; - - block_copy(new_record->single.str_forward, edit.str, length_forward); - buffer_stringify_range(buffer, edit.range, new_record->single.str_backward); - - Assert(history->record_lookup.count == history->record_count); -} - -internal void -history_record_edit(Heap *heap, Global_History *global_history, History *history, Gap_Buffer *buffer, Edit_Array edits, Buffer_Batch_Edit_Type batch_type){ - if (!history->activated){ - return; - } - Assert(history->record_lookup.count == history->record_count); - - Record *new_record = history__allocate_record(heap, history); - history__stash_record(heap, history, new_record); - - new_record->restore_point = temp_memory_light(begin_temp_memory(&history->arena)); - new_record->edit_number = global_history_get_edit_number(global_history); - - new_record->kind = RecordKind_Batch; - - i32 length_forward = 0; - i32 length_backward = 0; - - for (i32 i = 0; i < edits.count; i += 1){ - length_forward += edits.vals[i].length; - length_backward += edits.vals[i].range.one_past_last - edits.vals[i].range.first; - } - - new_record->batch.type = batch_type; - new_record->batch.count = edits.count; - new_record->batch.str_base_forward = push_array(&history->arena, char, length_forward); - new_record->batch.str_base_backward = push_array(&history->arena, char, length_backward); - new_record->batch.batch_records = push_array(&history->arena, Record_Batch_Slot, edits.count); - - char *str_base_forward = new_record->batch.str_base_forward; - char *cursor_forward = str_base_forward; - char *str_base_backward = new_record->batch.str_base_backward; - char *cursor_backward = str_base_backward; - - Record_Batch_Slot *batch_slot = new_record->batch.batch_records; - Edit *edit = edits.vals; - - for (i32 i = 0; i < edits.count; i += 1, batch_slot += 1, edit += 1){ - i32 edit_first = edit->range.first; - i32 edit_length_forward = edit->length; - i32 edit_length_backward = edit->range.one_past_last - edit_first; + if (history->activated){ + Assert(history->record_lookup.count == history->record_count); - batch_slot->length_forward = edit_length_forward ; - batch_slot->length_backward = edit_length_backward; - batch_slot->first = edit_first; + Record *new_record = history__allocate_record(heap, history); + history__stash_record(heap, history, new_record); - block_copy(cursor_forward , edit->str, edit_length_forward); - buffer_stringify_range(buffer, edit->range, cursor_backward); + new_record->restore_point = temp_memory_light(begin_temp_memory(&history->arena)); + new_record->edit_number = global_history_get_edit_number(global_history); - cursor_forward += edit_length_forward ; - cursor_backward += edit_length_backward; + new_record->kind = RecordKind_Single; + + i32 length_forward = edit.length; + i32 length_backward = edit.range.one_past_last - edit.range.first; + + new_record->single.str_forward = push_array(&history->arena, char, length_forward); + new_record->single.str_backward = push_array(&history->arena, char, length_backward); + new_record->single.length_forward = length_forward; + new_record->single.length_backward = length_backward; + new_record->single.first = edit.range.first; + + block_copy(new_record->single.str_forward, edit.str, length_forward); + buffer_stringify_range(buffer, edit.range, new_record->single.str_backward); + + Assert(history->record_lookup.count == history->record_count); } - - Assert(history->record_lookup.count == history->record_count); } internal void history_dump_records_after_index(History *history, i32 index){ - if (!history->activated){ - return; + if (history->activated){ + Assert(history->record_lookup.count == history->record_count); + + Assert(0 <= index && index <= history->record_count); + if (index < history->record_count){ + Node *node = history__to_node(history, index); + Node *first_node_to_clear = node->next; + + Node *sentinel = &history->records; + Assert(first_node_to_clear != sentinel); + + Record *first_record_to_clear = CastFromMember(Record, node, first_node_to_clear); + end_temp_memory(&history->arena, first_record_to_clear->restore_point); + + Node *last_node_to_clear = sentinel->prev; + + history__free_nodes(history, index + 1, first_node_to_clear, last_node_to_clear); + } + + Assert(history->record_lookup.count == history->record_count); } - Assert(history->record_lookup.count == history->record_count); - - Assert(0 <= index && index <= history->record_count); - if (index < history->record_count){ - Node *node = history__to_node(history, index); - Node *first_node_to_clear = node->next; - - Node *sentinel = &history->records; - Assert(first_node_to_clear != sentinel); - - Record *first_record_to_clear = CastFromMember(Record, node, first_node_to_clear); - end_temp_memory(&history->arena, first_record_to_clear->restore_point); - - Node *last_node_to_clear = sentinel->prev; - - history__free_nodes(history, index + 1, first_node_to_clear, last_node_to_clear); - } - - Assert(history->record_lookup.count == history->record_count); } internal void @@ -429,91 +370,82 @@ history__optimize_group(Partition *scratch, History *history, Record *record){ internal void history_merge_records(Partition *scratch, Heap *heap, History *history, i32 first_index, i32 last_index){ - if (!history->activated){ - return; - } - - Assert(history->record_lookup.count == history->record_count); - - Assert(first_index < last_index); - Node *first_node = history__to_node(history, first_index); - Node *last_node = history__to_node(history, last_index ); - Assert(first_node != &history->records && first_node != 0); - Assert(last_node != &history->records && last_node != 0); - - Record *new_record = history__allocate_record(heap, history); - - Node *left = first_node->prev; - Node *right = last_node->next; - left->next = &new_record->node; - new_record->node.prev = left; - right->prev = &new_record->node; - new_record->node.next = right; - - // NOTE(allen): here we remove (last_index - first_index + 1) nodes, and insert 1 node - // which simplifies to this: - history->record_count -= last_index - first_index; - - Record *first_record = CastFromMember(Record, node, first_node); - Record *last_record = CastFromMember(Record, node, last_node); - - new_record->restore_point = first_record->restore_point; - new_record->edit_number = last_record->edit_number; - new_record->kind = RecordKind_Group; - - Node *new_sentinel = &new_record->group.children; - dll_init_sentinel(new_sentinel); - - Node *one_past_last_node = last_node->next; - i32 count = 0; - for (Node *node = first_node, *next = 0; - node != one_past_last_node; - node = next){ - next = node->next; - Record *record = CastFromMember(Record, node, node); - switch (record->kind){ - case RecordKind_Single: - { - dll_insert_back(new_sentinel, &record->node); - count += 1; - }break; - - case RecordKind_Batch: - { - dll_insert_back(new_sentinel, &record->node); - count += 1; - }break; - - case RecordKind_Group: - { - Node *first = record->group.children.next; - Node *last = record->group.children.prev; - Assert(first != &record->group.children); - Assert(last != &record->group.children); + if (history->activated){ + Assert(history->record_lookup.count == history->record_count); + Assert(first_index < last_index); + Node *first_node = history__to_node(history, first_index); + Node *last_node = history__to_node(history, last_index ); + Assert(first_node != &history->records && first_node != 0); + Assert(last_node != &history->records && last_node != 0); + + Record *new_record = history__allocate_record(heap, history); + + Node *left = first_node->prev; + Node *right = last_node->next; + left->next = &new_record->node; + new_record->node.prev = left; + right->prev = &new_record->node; + new_record->node.next = right; + + // NOTE(allen): here we remove (last_index - first_index + 1) nodes, and insert 1 node + // which simplifies to this: + history->record_count -= last_index - first_index; + + Record *first_record = CastFromMember(Record, node, first_node); + Record *last_record = CastFromMember(Record, node, last_node); + + new_record->restore_point = first_record->restore_point; + new_record->edit_number = last_record->edit_number; + new_record->kind = RecordKind_Group; + + Node *new_sentinel = &new_record->group.children; + dll_init_sentinel(new_sentinel); + + Node *one_past_last_node = last_node->next; + i32 count = 0; + for (Node *node = first_node, *next = 0; + node != one_past_last_node; + node = next){ + next = node->next; + Record *record = CastFromMember(Record, node, node); + switch (record->kind){ + case RecordKind_Single: + { + dll_insert_back(new_sentinel, &record->node); + count += 1; + }break; - Node *sub_right = new_sentinel; - Node *sub_left = new_sentinel->prev; - sub_left->next = first; - first->prev = sub_left; - last->next = sub_right; - sub_right->prev = last; - count += record->group.count; - }break; - - default: - { - InvalidCodePath; - }break; + case RecordKind_Group: + { + Node *first = record->group.children.next; + Node *last = record->group.children.prev; + Assert(first != &record->group.children); + Assert(last != &record->group.children); + + Node *sub_right = new_sentinel; + Node *sub_left = new_sentinel->prev; + sub_left->next = first; + first->prev = sub_left; + last->next = sub_right; + sub_right->prev = last; + count += record->group.count; + }break; + + default: + { + InvalidCodePath; + }break; + } + } + + new_record->group.count = count; + + history__merge_record_ptr_range_to_one_ptr(&history->record_lookup, first_index, last_index, new_record); + Assert(history->record_lookup.count == history->record_count); + + if (first_index == history->record_count){ + history__optimize_group(scratch, history, new_record); } - } - - new_record->group.count = count; - - history__merge_record_ptr_range_to_one_ptr(&history->record_lookup, first_index, last_index, new_record); - Assert(history->record_lookup.count == history->record_count); - - if (first_index == history->record_count){ - history__optimize_group(scratch, history, new_record); } } diff --git a/4ed_layout.cpp b/4ed_layout.cpp index 7f87aa10..8bfe7bdb 100644 --- a/4ed_layout.cpp +++ b/4ed_layout.cpp @@ -133,6 +133,16 @@ layout_get_next_open_panel(Layout *layout, Panel *panel){ return(panel); } +internal Panel* +layout_get_prev_open_panel(Layout *layout, Panel *panel){ + panel = CastFromMember(Panel, node, panel->node.prev); + if (&panel->node == &layout->open_panels){ + panel = 0; + } + AssertImplies(panel != 0, panel->kind == PanelKind_Final); + return(panel); +} + internal Panel* layout_get_active_panel(Layout *layout){ return(layout->active_panel);