Undo/Redo cursor positioning fixed

This commit is contained in:
Allen Webster 2019-03-21 22:06:30 -07:00
parent 3f3a31b114
commit 2c381917fd
12 changed files with 447 additions and 395 deletions

View File

@ -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;

View File

@ -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, &current);
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, &current);
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);
}

View File

@ -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;

View File

@ -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.")
{

View File

@ -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);

View File

@ -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));}

View File

@ -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 },

View File

@ -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++];
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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);